From 5840b852138282f0857f75816f8c354947275b95 Mon Sep 17 00:00:00 2001 From: kernelkind Date: Thu, 18 Jan 2024 14:59:31 -0500 Subject: [PATCH] nip19: generate nip19 data in ellipsis & share menus In the ellipsis menu, when the user selects the 'Copy user public key', an nprofile Bech32 entity will be generated which will include TLV data with the user's public key and entire relay list, if available. The nprofile will be added to the user's copy clipboard. When the user presses the share menu on an event and clicks the 'copy link' button, a damus link with the nevent for the note will be generated and copied to the user's clipboard. Closes: https://github.com/damus-io/damus/issues/1844 Changelog-Changed: Generate nprofile/nevent links in share menus Lightning-url: LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G Signed-off-by: kernelkind Reviewed-by: William Casarin Signed-off-by: William Casarin --- damus/Models/ProfileModel.swift | 22 ++++++++++++++++++++++ damus/Views/ActionBar/EventActionBar.swift | 6 ++++-- damus/Views/ActionBar/ShareAction.swift | 12 ++++++++++-- damus/Views/DMChatView.swift | 2 +- damus/Views/Events/EventMenu.swift | 16 +++++++++++++--- 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/damus/Models/ProfileModel.swift b/damus/Models/ProfileModel.swift index d0392659..8b932884 100644 --- a/damus/Models/ProfileModel.swift +++ b/damus/Models/ProfileModel.swift @@ -20,6 +20,7 @@ class ProfileModel: ObservableObject, Equatable { var seen_event: Set = Set() var sub_id = UUID().description var prof_subid = UUID().description + var findRelay_subid = UUID().description init(pubkey: Pubkey, damus: DamusState) { self.pubkey = pubkey @@ -139,6 +140,27 @@ class ProfileModel: ObservableObject, Equatable { } } } + + private func findRelaysHandler(relay_id: String, ev: NostrConnectionEvent) { + if case .nostr_event(let resp) = ev, case .event(_, let event) = resp, case .contacts = event.known_kind { + self.relays = decode_json_relays(event.content) + } + } + + func subscribeToFindRelays() { + var profile_filter = NostrFilter(kinds: [.contacts]) + profile_filter.authors = [pubkey] + + damus.pool.subscribe(sub_id: findRelay_subid, filters: [profile_filter], handler: findRelaysHandler) + } + + func unsubscribeFindRelays() { + damus.pool.unsubscribe(sub_id: findRelay_subid) + } + + func getRelayStrings() -> [String] { + return relays?.keys.map {$0} ?? [] + } } diff --git a/damus/Views/ActionBar/EventActionBar.swift b/damus/Views/ActionBar/EventActionBar.swift index 3775f99d..f7815fe3 100644 --- a/damus/Views/ActionBar/EventActionBar.swift +++ b/damus/Views/ActionBar/EventActionBar.swift @@ -13,6 +13,7 @@ struct EventActionBar: View { let damus_state: DamusState let event: NostrEvent let generator = UIImpactFeedbackGenerator(style: .medium) + let userProfile : ProfileModel // just used for previews @State var show_share_sheet: Bool = false @@ -25,6 +26,7 @@ struct EventActionBar: View { self.damus_state = damus_state self.event = event _bar = ObservedObject(wrappedValue: bar ?? make_actionbar_model(ev: event.id, damus: damus_state)) + self.userProfile = ProfileModel(pubkey: event.pubkey, damus: damus_state) } var lnurl: String? { @@ -100,11 +102,11 @@ struct EventActionBar: View { } .sheet(isPresented: $show_share_action, onDismiss: { self.show_share_action = false }) { if #available(iOS 16.0, *) { - ShareAction(event: event, bookmarks: damus_state.bookmarks, show_share: $show_share_sheet) + ShareAction(event: event, bookmarks: damus_state.bookmarks, show_share: $show_share_sheet, userProfile: userProfile) .presentationDetents([.height(300)]) .presentationDragIndicator(.visible) } else { - ShareAction(event: event, bookmarks: damus_state.bookmarks, show_share: $show_share_sheet) + ShareAction(event: event, bookmarks: damus_state.bookmarks, show_share: $show_share_sheet, userProfile: userProfile) } } .sheet(isPresented: $show_share_sheet, onDismiss: { self.show_share_sheet = false }) { diff --git a/damus/Views/ActionBar/ShareAction.swift b/damus/Views/ActionBar/ShareAction.swift index bb6fd651..64fe1c26 100644 --- a/damus/Views/ActionBar/ShareAction.swift +++ b/damus/Views/ActionBar/ShareAction.swift @@ -10,18 +10,20 @@ import SwiftUI struct ShareAction: View { let event: NostrEvent let bookmarks: BookmarksManager + let userProfile: ProfileModel @State private var isBookmarked: Bool = false @Binding var show_share: Bool @Environment(\.dismiss) var dismiss - init(event: NostrEvent, bookmarks: BookmarksManager, show_share: Binding) { + init(event: NostrEvent, bookmarks: BookmarksManager, show_share: Binding, userProfile: ProfileModel) { let bookmarked = bookmarks.isBookmarked(event) self._isBookmarked = State(initialValue: bookmarked) self.bookmarks = bookmarks self.event = event + self.userProfile = userProfile self._show_share = show_share } @@ -38,7 +40,7 @@ struct ShareAction: View { ShareActionButton(img: "link", text: NSLocalizedString("Copy Link", comment: "Button to copy link to note")) { dismiss() - UIPasteboard.general.string = "https://damus.io/" + event.id.bech32 + UIPasteboard.general.string = "https://damus.io/" + Bech32Object.encode(.nevent(NEvent(noteid: event.id, relays: userProfile.getRelayStrings()))) } let bookmarkImg = isBookmarked ? "bookmark.fill" : "bookmark" @@ -69,6 +71,12 @@ struct ShareAction: View { } } } + .onAppear() { + userProfile.subscribeToFindRelays() + } + .onDisappear() { + userProfile.unsubscribeFindRelays() + } } } diff --git a/damus/Views/DMChatView.swift b/damus/Views/DMChatView.swift index 217f022e..9666ffd9 100644 --- a/damus/Views/DMChatView.swift +++ b/damus/Views/DMChatView.swift @@ -22,7 +22,7 @@ struct DMChatView: View, KeyboardReadable { LazyVStack(alignment: .leading) { ForEach(Array(zip(dms.events, dms.events.indices)), id: \.0.id) { (ev, ind) in DMView(event: dms.events[ind], damus_state: damus_state) - .contextMenu{MenuItems(event: ev, keypair: damus_state.keypair, target_pubkey: ev.pubkey, bookmarks: damus_state.bookmarks, muted_threads: damus_state.muted_threads, settings: damus_state.settings)} + .contextMenu{MenuItems(event: ev, keypair: damus_state.keypair, target_pubkey: ev.pubkey, bookmarks: damus_state.bookmarks, muted_threads: damus_state.muted_threads, settings: damus_state.settings, profileModel: ProfileModel(pubkey: ev.pubkey, damus: damus_state))} } EndBlock(height: 1) } diff --git a/damus/Views/Events/EventMenu.swift b/damus/Views/Events/EventMenu.swift index e7c8a085..8728c9a6 100644 --- a/damus/Views/Events/EventMenu.swift +++ b/damus/Views/Events/EventMenu.swift @@ -13,6 +13,7 @@ struct EventMenuContext: View { let target_pubkey: Pubkey let bookmarks: BookmarksManager let muted_threads: MutedThreadsManager + let profileModel : ProfileModel @ObservedObject var settings: UserSettingsStore init(damus: DamusState, event: NostrEvent) { @@ -22,6 +23,7 @@ struct EventMenuContext: View { self.bookmarks = damus.bookmarks self.muted_threads = damus.muted_threads self._settings = ObservedObject(wrappedValue: damus.settings) + self.profileModel = ProfileModel(pubkey: target_pubkey, damus: damus) } var body: some View { @@ -32,7 +34,7 @@ struct EventMenuContext: View { // Add our Menu button inside an overlay modifier to avoid affecting the rest of the layout around us. .overlay( Menu { - MenuItems(event: event, keypair: keypair, target_pubkey: target_pubkey, bookmarks: bookmarks, muted_threads: muted_threads, settings: settings) + MenuItems(event: event, keypair: keypair, target_pubkey: target_pubkey, bookmarks: bookmarks, muted_threads: muted_threads, settings: settings, profileModel: profileModel) } label: { Color.clear } @@ -52,13 +54,14 @@ struct MenuItems: View { let target_pubkey: Pubkey let bookmarks: BookmarksManager let muted_threads: MutedThreadsManager + let profileModel: ProfileModel @ObservedObject var settings: UserSettingsStore @State private var isBookmarked: Bool = false @State private var isMutedThread: Bool = false - init(event: NostrEvent, keypair: Keypair, target_pubkey: Pubkey, bookmarks: BookmarksManager, muted_threads: MutedThreadsManager, settings: UserSettingsStore) { + init(event: NostrEvent, keypair: Keypair, target_pubkey: Pubkey, bookmarks: BookmarksManager, muted_threads: MutedThreadsManager, settings: UserSettingsStore, profileModel: ProfileModel) { let bookmarked = bookmarks.isBookmarked(event) self._isBookmarked = State(initialValue: bookmarked) @@ -71,6 +74,7 @@ struct MenuItems: View { self.keypair = keypair self.target_pubkey = target_pubkey self.settings = settings + self.profileModel = profileModel } var body: some View { @@ -82,7 +86,7 @@ struct MenuItems: View { } Button { - UIPasteboard.general.string = target_pubkey.npub + UIPasteboard.general.string = Bech32Object.encode(.nprofile(NProfile(author: target_pubkey, relays: profileModel.getRelayStrings()))) } label: { Label(NSLocalizedString("Copy user public key", comment: "Context menu option for copying the ID of the user who created the note."), image: "user") } @@ -144,6 +148,12 @@ struct MenuItems: View { } } } + .onAppear() { + profileModel.subscribeToFindRelays() + } + .onDisappear() { + profileModel.unsubscribeFindRelays() + } } }