field_ios

In-the-field app for Radroots on iOS
git clone https://radroots.dev/git/field_ios.git
Log | Files | Refs | LICENSE

commit f476611d115f0c9030a8c45ca9da0a15efb6da0f
parent 7104657813fd3f783ecf9a23f164ec40519ddc01
Author: triesap <triesap@radroots.dev>
Date:   Thu, 25 Dec 2025 01:53:26 +0000

kit: add Swift nostr posting and stream helpers

- Bump RadrootsCore submodule to latest runtime APIs
- Add NostrEventId wrapper for typed event identifiers
- Expose profile/text/reply posting helpers on Radroots
- Add start/next/stop post stream helpers with runtime guard

Diffstat:
ARadrootsKit/Sources/RadrootsKit/Nostr.swift | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+), 0 deletions(-)

diff --git a/RadrootsKit/Sources/RadrootsKit/Nostr.swift b/RadrootsKit/Sources/RadrootsKit/Nostr.swift @@ -0,0 +1,93 @@ +import Foundation + +public struct NostrEventId: Hashable, Sendable { + public let rawValue: String + + public init(_ rawValue: String) { + self.rawValue = rawValue + } +} + +public extension NostrPostEventMetadata { + var eventId: NostrEventId { + NostrEventId(id) + } +} + +public extension NostrProfileEventMetadata { + var eventId: NostrEventId { + NostrEventId(id) + } +} + +public enum RadrootsRuntimeError: LocalizedError { + case runtimeNotStarted + + public var errorDescription: String? { + "Radroots runtime not started." + } +} + +@MainActor +public extension Radroots { + func nostrPostProfile( + name: String? = nil, + displayName: String? = nil, + nip05: String? = nil, + about: String? = nil + ) throws -> NostrEventId { + let rt = try requireRuntime() + let id = try rt.nostrPostProfile( + name: name, + displayName: displayName, + nip05: nip05, + about: about + ) + return NostrEventId(id) + } + + func nostrPostTextNote(content: String) throws -> NostrEventId { + let rt = try requireRuntime() + let id = try rt.nostrPostTextNote(content: content) + return NostrEventId(id) + } + + func nostrPostReply( + parentEventIdHex: String, + parentAuthorHex: String, + content: String, + rootEventIdHex: String? = nil + ) throws -> NostrEventId { + let rt = try requireRuntime() + let id = try rt.nostrPostReply( + parentEventIdHex: parentEventIdHex, + parentAuthorHex: parentAuthorHex, + content: content, + rootEventIdHex: rootEventIdHex + ) + return NostrEventId(id) + } + + func nostrStartPostStream(sinceUnix: UInt64? = nil) throws { + let rt = try requireRuntime() + try rt.nostrStartPostEventStream(sinceUnix: sinceUnix) + } + + func nostrNextPostStreamEvent() -> NostrPostEventMetadata? { + guard let rt = runtime else { return nil } + return rt.nostrNextPostEvent() + } + + func nostrStopPostStream() throws { + let rt = try requireRuntime() + try rt.nostrStopPostEventStream() + } +} + +@MainActor +private extension Radroots { + func requireRuntime() throws -> RadrootsRuntime { + guard let rt = runtime else { throw RadrootsRuntimeError.runtimeNotStarted } + return rt + } +}