Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions damus/Core/Nostr/Id.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,41 @@ struct ReplaceableParam: TagConvertible {
var keychar: AsciiCharacter { "d" }
}

struct AddressPointer: Hashable {
let kind: UInt32
let pubkey: Pubkey
let identifier: String

init(kind: UInt32, pubkey: Pubkey, identifier: String) {
self.kind = kind
self.pubkey = pubkey
self.identifier = identifier
}

init?(rawValue: String) {
let components = rawValue.split(separator: ":", maxSplits: 2, omittingEmptySubsequences: false)
guard components.count == 3,
let kind = UInt32(components[0]),
let pubkey = Pubkey(hex: String(components[1]))
else {
return nil
}

self.init(kind: kind, pubkey: pubkey, identifier: String(components[2]))
}

static func from(tag: TagSequence, allowedKeys: Set<AsciiCharacter>) -> AddressPointer? {
guard tag.count >= 2,
let key = tag[0].single_char,
allowedKeys.contains(key)
else {
return nil
}

return AddressPointer(rawValue: tag[1].string())
}
}

struct Signature: Codable, Hashable, Equatable {
let data: Data

Expand Down
1 change: 1 addition & 0 deletions damus/Core/Nostr/NostrKind.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ enum NostrKind: UInt32, Codable {
case boost = 6
case like = 7
case chat = 42
case comment = 1111
case mute_list = 10000
case relay_list = 10002
case interest_list = 10015
Expand Down
35 changes: 33 additions & 2 deletions damus/Features/Events/Models/LoadableNostrEventView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class LoadableNostrEventViewModel: ObservableObject {
guard let ev = await self.loadEvent(noteId: note_id) else { return .not_found }
guard let known_kind = ev.known_kind else { return .unknown_or_unsupported_kind }
switch known_kind {
case .text, .highlight:
case .text, .highlight, .longform:
return .loaded(route: Route.Thread(thread: ThreadModel(event: ev, damus_state: damus_state)))
case .dm:
let dm_model = damus_state.dms.lookup_or_create(ev.pubkey)
Expand All @@ -74,14 +74,45 @@ class LoadableNostrEventViewModel: ObservableObject {
case .zap, .zap_request:
guard let zap = await get_zap(from: ev, state: damus_state) else { return .not_found }
return .loaded(route: Route.Zaps(target: zap.target))
case .contacts, .metadata, .delete, .boost, .chat, .mute_list, .list_deprecated, .draft, .longform, .nwc_request, .nwc_response, .http_auth, .status, .relay_list, .follow_list, .interest_list, .contact_card:
case .comment:
if let target = commentTarget(ev: ev) {
return await self.executeLoadingLogic(note_reference: target)
}
return .unknown_or_unsupported_kind
case .contacts, .metadata, .delete, .boost, .chat, .mute_list, .list_deprecated, .draft, .nwc_request, .nwc_response, .http_auth, .status, .relay_list, .follow_list, .interest_list, .contact_card:
return .unknown_or_unsupported_kind
}
case .naddr(let naddr):
guard let event = await naddrLookup(damus_state: damus_state, naddr: naddr) else { return .not_found }
return .loaded(route: Route.Thread(thread: ThreadModel(event: event, damus_state: damus_state)))
}
}

private func commentTarget(ev: NostrEvent) -> NoteReference? {
guard ev.known_kind == .comment else {
return nil
}

if let scope = ev.nip22_comment_scope() {
if let parent = scope.parent, let naddr = pointerToNaddr(parent) {
return .naddr(naddr)
}

if let root = scope.root, let naddr = pointerToNaddr(root) {
return .naddr(naddr)
}
}

if let parent = damus_state.events.parent_events(event: ev, keypair: damus_state.keypair).last {
return .note_id(parent.id)
}

return nil
}

private func pointerToNaddr(_ pointer: AddressPointer) -> NAddr? {
NAddr(identifier: pointer.identifier, author: pointer.pubkey, relays: [], kind: pointer.kind)
}

enum ThreadModelLoadingState {
case loading
Expand Down
50 changes: 47 additions & 3 deletions damus/Features/Posting/Views/PostView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,45 @@ func nip10_reply_tags(replying_to: NostrEvent, keypair: Keypair, relayURL: Relay
return tags
}

private func buildTag(_ key: String, _ components: String?...) -> [String] {
var tag = [key]
for component in components {
guard let component, !component.isEmpty else { continue }
tag.append(component)
}
return tag
}

func nip22_comment_tags(replying_to: NostrEvent, state: DamusState) -> [[String]]? {
guard replying_to.known_kind == .longform else {
return nil
}

guard let identifier = replying_to.referenced_params.first?.param.string(), !identifier.isEmpty else {
return nil
}

let address = "\(replying_to.kind):\(replying_to.pubkey.hex()):\(identifier)"
let relay = state.nostrNetwork.relaysForEvent(event: replying_to).first?.absoluteString
let rootKindString = "\(replying_to.kind)"
let rootPubkey = replying_to.pubkey.hex()
let rootId = replying_to.id.hex()

var tags: [[String]] = []

tags.append(buildTag("A", address, relay))
tags.append(["K", rootKindString])
tags.append(buildTag("P", rootPubkey, relay))

// For top-level comments, parent equals root
tags.append(buildTag("a", address, relay))
tags.append(buildTag("e", rootId, relay, rootPubkey))
tags.append(["k", rootKindString])
tags.append(buildTag("p", rootPubkey, relay))

return tags
}

func build_post(state: DamusState, action: PostAction, draft: DraftArtifacts) -> NostrPost {
return build_post(
state: state,
Expand Down Expand Up @@ -912,11 +951,17 @@ func build_post(state: DamusState, post: NSAttributedString, action: PostAction,
}

var tags: [[String]] = []
var postKind: NostrKind = .text

switch action {
case .replying_to(let replying_to):
// start off with the reply tags
tags = nip10_reply_tags(replying_to: replying_to, keypair: state.keypair, relayURL: state.nostrNetwork.relaysForEvent(event: replying_to).first)
if let nip22Tags = nip22_comment_tags(replying_to: replying_to, state: state) {
tags = nip22Tags
postKind = .comment
} else {
tags = nip10_reply_tags(replying_to: replying_to, keypair: state.keypair, relayURL: state.nostrNetwork.relaysForEvent(event: replying_to).first)
}

case .quoting(let ev):
let relay_urls = state.nostrNetwork.relaysForEvent(event: ev)
Expand Down Expand Up @@ -953,7 +998,7 @@ func build_post(state: DamusState, post: NSAttributedString, action: PostAction,
}
}

return NostrPost(content: content.trimmingCharacters(in: .whitespacesAndNewlines), kind: .text, tags: tags)
return NostrPost(content: content.trimmingCharacters(in: .whitespacesAndNewlines), kind: postKind, tags: tags)
}

func isSupportedVideo(url: URL?) -> Bool {
Expand All @@ -974,4 +1019,3 @@ func isSupportedImage(url: URL) -> Bool {
let supportedTypes = ["jpg", "png", "gif"]
return supportedTypes.contains(fileExtension)
}

4 changes: 2 additions & 2 deletions damus/Features/Profile/Models/ProfileModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class ProfileModel: ObservableObject, Equatable {
}

func subscribe() {
var text_filter = NostrFilter(kinds: [.text, .longform, .highlight])
var text_filter = NostrFilter(kinds: [.text, .longform, .highlight, .comment])
var profile_filter = NostrFilter(kinds: [.contacts, .metadata, .boost])
var relay_list_filter = NostrFilter(kinds: [.relay_list], authors: [pubkey])

Expand All @@ -98,7 +98,7 @@ class ProfileModel: ObservableObject, Equatable {
return
}

let conversation_kinds: [NostrKind] = [.text, .longform, .highlight]
let conversation_kinds: [NostrKind] = [.text, .longform, .highlight, .comment]
let limit: UInt32 = 500
let conversations_filter_them = NostrFilter(kinds: conversation_kinds, pubkeys: [damus.pubkey], limit: limit, authors: [pubkey])
let conversations_filter_us = NostrFilter(kinds: conversation_kinds, pubkeys: [pubkey], limit: limit, authors: [damus.pubkey])
Expand Down
5 changes: 2 additions & 3 deletions damus/Features/Timeline/Models/HomeModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ class HomeModel: ContactsDelegate {
}

switch kind {
case .chat, .longform, .text, .highlight:
case .chat, .longform, .text, .highlight, .comment:
handle_text_event(sub_id: sub_id, ev)
case .contacts:
handle_contact_event(sub_id: sub_id, relay_id: relay_id, ev: ev)
Expand Down Expand Up @@ -637,7 +637,7 @@ class HomeModel: ContactsDelegate {
func subscribe_to_home_filters(friends fs: [Pubkey]? = nil, relay_id: RelayURL? = nil) {
// TODO: separate likes?
var home_filter_kinds: [NostrKind] = [
.text, .longform, .boost, .highlight
.text, .longform, .boost, .highlight, .comment
]
if !damus_state.settings.onlyzaps_mode {
home_filter_kinds.append(.like)
Expand Down Expand Up @@ -1214,4 +1214,3 @@ func create_in_app_event_zap_notification(profiles: Profiles, zap: Zap, locale:
}
}
}