damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

commit c71b0ee91688f4a975000e33b5dc37a0f0e74c6d
parent 8e92e28fafb06cfff32988d4ba4ce1f601e920b4
Author: William Casarin <jb55@jb55.com>
Date:   Mon, 28 Aug 2023 11:46:03 -0700

blocks: pass keypair instead of privkey to avoid pubkey gen

Generating a pubkey is quite slow, so pass a keypair instead of privkey

Diffstat:
Mdamus/Components/TranslateView.swift | 8++++----
Mdamus/ContentParsing.swift | 4++--
Mdamus/ContentView.swift | 4++--
Mdamus/Models/DamusState.swift | 4++--
Mdamus/Models/HomeModel.swift | 36++++++++++++++++++------------------
Mdamus/Models/MutedThreadsManager.swift | 8++++----
Mdamus/Models/SearchHomeModel.swift | 4++--
Mdamus/Models/SearchModel.swift | 4++--
Mdamus/Models/ThreadModel.swift | 18+++++++++---------
Mdamus/Nostr/NostrEvent.swift | 4++--
Mdamus/Util/EventCache.swift | 18+++++++++---------
Mdamus/Util/Keys.swift | 4++++
Mdamus/Util/ReplyCounter.swift | 4++--
Mdamus/Views/DMView.swift | 2+-
Mdamus/Views/Events/Components/ReplyPart.swift | 8++++----
Mdamus/Views/Events/EventMenu.swift | 6+++---
Mdamus/Views/Events/EventShell.swift | 6+++---
Mdamus/Views/Events/Longform/LongformView.swift | 4++--
Mdamus/Views/Events/MutedEventView.swift | 4++--
Mdamus/Views/Events/SelectedEventView.swift | 6+++---
Mdamus/Views/NoteContentView.swift | 10+++++-----
Mdamus/Views/SearchHomeView.swift | 2+-
Mdamus/Views/ThreadView.swift | 6+++---
Mnostrdb/NdbNote.swift | 41+++++++++++++++++++----------------------
24 files changed, 108 insertions(+), 107 deletions(-)

diff --git a/damus/Components/TranslateView.swift b/damus/Components/TranslateView.swift @@ -64,7 +64,7 @@ struct TranslateView: View { guard let note_language = translations_model.note_language else { return } - let res = await translate_note(profiles: damus_state.profiles, privkey: damus_state.keypair.privkey, event: event, settings: damus_state.settings, note_lang: note_language) + let res = await translate_note(profiles: damus_state.profiles, keypair: damus_state.keypair, event: event, settings: damus_state.settings, note_lang: note_language) DispatchQueue.main.async { self.translations_model.state = res } @@ -125,11 +125,11 @@ struct TranslateView_Previews: PreviewProvider { } } -func translate_note(profiles: Profiles, privkey: Privkey?, event: NostrEvent, settings: UserSettingsStore, note_lang: String) async -> TranslateStatus { - +func translate_note(profiles: Profiles, keypair: Keypair, event: NostrEvent, settings: UserSettingsStore, note_lang: String) async -> TranslateStatus { + // If the note language is different from our preferred languages, send a translation request. let translator = Translator(settings) - let originalContent = event.get_content(privkey) + let originalContent = event.get_content(keypair) let translated_note = try? await translator.translate(originalContent, from: note_lang, to: current_language()) guard let translated_note else { diff --git a/damus/ContentParsing.swift b/damus/ContentParsing.swift @@ -11,9 +11,9 @@ enum NoteContent { case note(NostrEvent) case content(String, TagsSequence?) - init(note: NostrEvent, privkey: Privkey?) { + init(note: NostrEvent, keypair: Keypair) { if note.known_kind == .dm { - self = .content(note.get_content(privkey), note.tags) + self = .content(note.get_content(keypair), note.tags) } else { self = .note(note) } diff --git a/damus/ContentView.swift b/damus/ContentView.swift @@ -59,11 +59,11 @@ enum Sheets: Identifiable { enum FilterState : Int { case posts_and_replies = 1 case posts = 0 - + func filter(ev: NostrEvent) -> Bool { switch self { case .posts: - return ev.known_kind == .boost || !ev.is_reply(nil) + return ev.known_kind == .boost || !ev.is_reply(.empty) case .posts_and_replies: return true } diff --git a/damus/Models/DamusState.swift b/damus/Models/DamusState.swift @@ -43,8 +43,8 @@ struct DamusState { // thread zaps if let ev = zap.event, !settings.nozaps, zap.is_in_thread { // [nozaps]: thread zaps are only available outside of the app store - replies.count_replies(ev, privkey: self.keypair.privkey) - events.add_replies(ev: ev, privkey: self.keypair.privkey) + replies.count_replies(ev, keypair: self.keypair) + events.add_replies(ev: ev, keypair: self.keypair) } // associate with events as well diff --git a/damus/Models/HomeModel.swift b/damus/Models/HomeModel.swift @@ -253,7 +253,7 @@ class HomeModel { process_zap_event(damus_state: damus_state, ev: ev) { zapres in guard case .done(let zap) = zapres, zap.target.pubkey == self.damus_state.keypair.pubkey, - should_show_event(privkey: self.damus_state.keypair.privkey, hellthreads: self.damus_state.muted_threads, contacts: self.damus_state.contacts, ev: zap.request.ev) else { + should_show_event(keypair: self.damus_state.keypair, hellthreads: self.damus_state.muted_threads, contacts: self.damus_state.contacts, ev: zap.request.ev) else { return } @@ -299,7 +299,7 @@ class HomeModel { return false } - return !damus_state.contacts.is_muted(ev.pubkey) && !damus_state.muted_threads.isMutedThread(ev, privkey: damus_state.keypair.privkey) + return !damus_state.contacts.is_muted(ev.pubkey) && !damus_state.muted_threads.isMutedThread(ev, keypair: damus_state.keypair) } } @@ -599,7 +599,7 @@ class HomeModel { // don't show notifications from ourselves guard ev.pubkey != damus_state.pubkey, event_has_our_pubkey(ev, our_pubkey: self.damus_state.pubkey), - should_show_event(privkey: self.damus_state.keypair.privkey, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: ev) else { + should_show_event(keypair: self.damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: ev) else { return } @@ -637,13 +637,13 @@ class HomeModel { func handle_text_event(sub_id: String, _ ev: NostrEvent) { - guard should_show_event(privkey: damus_state.keypair.privkey, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: ev) else { + guard should_show_event(keypair: damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: ev) else { return } // TODO: will we need to process this in other places like zap request contents, etc? process_image_metadatas(cache: damus_state.events, ev: ev) - damus_state.replies.count_replies(ev, privkey: self.damus_state.keypair.privkey) + damus_state.replies.count_replies(ev, keypair: self.damus_state.keypair) damus_state.events.insert(ev) if sub_id == home_subid { @@ -657,14 +657,14 @@ class HomeModel { notification_status.new_events = notifs if damus_state.settings.dm_notification && ev.age < HomeModel.event_max_age_for_notification { - let convo = ev.decrypted(privkey: self.damus_state.keypair.privkey) ?? NSLocalizedString("New encrypted direct message", comment: "Notification that the user has received a new direct message") + let convo = ev.decrypted(keypair: self.damus_state.keypair) ?? NSLocalizedString("New encrypted direct message", comment: "Notification that the user has received a new direct message") let notify = LocalNotification(type: .dm, event: ev, target: ev, content: convo) create_local_notification(profiles: damus_state.profiles, notify: notify) } } func handle_dm(_ ev: NostrEvent) { - guard should_show_event(privkey: damus_state.keypair.privkey, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: ev) else { + guard should_show_event(keypair: damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: ev) else { return } @@ -1129,12 +1129,12 @@ func event_has_our_pubkey(_ ev: NostrEvent, our_pubkey: Pubkey) -> Bool { } -func should_show_event(privkey: Privkey?, hellthreads: MutedThreadsManager, contacts: Contacts, ev: NostrEvent) -> Bool { +func should_show_event(keypair: Keypair, hellthreads: MutedThreadsManager, contacts: Contacts, ev: NostrEvent) -> Bool { if contacts.is_muted(ev.pubkey) { return false } - if hellthreads.isMutedThread(ev, privkey: privkey) { + if hellthreads.isMutedThread(ev, keypair: keypair) { return false } @@ -1221,11 +1221,11 @@ func create_in_app_event_zap_notification(profiles: Profiles, zap: Zap, locale: } } -func render_notification_content_preview(cache: EventCache, ev: NostrEvent, profiles: Profiles, privkey: Privkey?) -> String { - +func render_notification_content_preview(cache: EventCache, ev: NostrEvent, profiles: Profiles, keypair: Keypair) -> String { + let prefix_len = 300 - let artifacts = cache.get_cache_data(ev.id).artifacts.artifacts ?? render_note_content(ev: ev, profiles: profiles, privkey: privkey) - + let artifacts = cache.get_cache_data(ev.id).artifacts.artifacts ?? render_note_content(ev: ev, profiles: profiles, keypair: keypair) + // special case for longform events if ev.known_kind == .longform { let longform = LongformEvent(event: ev) @@ -1255,7 +1255,7 @@ func process_local_notification(damus_state: DamusState, event ev: NostrEvent) { } // Don't show notifications from muted threads. - if damus_state.muted_threads.isMutedThread(ev, privkey: damus_state.keypair.privkey) { + if damus_state.muted_threads.isMutedThread(ev, keypair: damus_state.keypair) { return } @@ -1265,12 +1265,12 @@ func process_local_notification(damus_state: DamusState, event ev: NostrEvent) { } if type == .text, damus_state.settings.mention_notification { - let blocks = ev.blocks(damus_state.keypair.privkey).blocks + let blocks = ev.blocks(damus_state.keypair).blocks for case .mention(let mention) in blocks { guard case .pubkey(let pk) = mention.ref, pk == damus_state.keypair.pubkey else { continue } - let content_preview = render_notification_content_preview(cache: damus_state.events, ev: ev, profiles: damus_state.profiles, privkey: damus_state.keypair.privkey) + let content_preview = render_notification_content_preview(cache: damus_state.events, ev: ev, profiles: damus_state.profiles, keypair: damus_state.keypair) let notify = LocalNotification(type: .mention, event: ev, target: ev, content: content_preview) create_local_notification(profiles: damus_state.profiles, notify: notify ) } @@ -1278,7 +1278,7 @@ func process_local_notification(damus_state: DamusState, event ev: NostrEvent) { damus_state.settings.repost_notification, let inner_ev = ev.get_inner_event(cache: damus_state.events) { - let content_preview = render_notification_content_preview(cache: damus_state.events, ev: inner_ev, profiles: damus_state.profiles, privkey: damus_state.keypair.privkey) + let content_preview = render_notification_content_preview(cache: damus_state.events, ev: inner_ev, profiles: damus_state.profiles, keypair: damus_state.keypair) let notify = LocalNotification(type: .repost, event: ev, target: inner_ev, content: content_preview) create_local_notification(profiles: damus_state.profiles, notify: notify) } else if type == .like, @@ -1286,7 +1286,7 @@ func process_local_notification(damus_state: DamusState, event ev: NostrEvent) { let evid = ev.referenced_ids.last, let liked_event = damus_state.events.lookup(evid) { - let content_preview = render_notification_content_preview(cache: damus_state.events, ev: liked_event, profiles: damus_state.profiles, privkey: damus_state.keypair.privkey) + let content_preview = render_notification_content_preview(cache: damus_state.events, ev: liked_event, profiles: damus_state.profiles, keypair: damus_state.keypair) let notify = LocalNotification(type: .like, event: ev, target: liked_event, content: content_preview) create_local_notification(profiles: damus_state.profiles, notify: notify) } diff --git a/damus/Models/MutedThreadsManager.swift b/damus/Models/MutedThreadsManager.swift @@ -56,13 +56,13 @@ class MutedThreadsManager: ObservableObject { self.keypair = keypair } - func isMutedThread(_ ev: NostrEvent, privkey: Privkey?) -> Bool { - return _mutedThreadsSet.contains(ev.thread_id(privkey: privkey)) + func isMutedThread(_ ev: NostrEvent, keypair: Keypair) -> Bool { + return _mutedThreadsSet.contains(ev.thread_id(keypair: keypair)) } func updateMutedThread(_ ev: NostrEvent) { - let threadId = ev.thread_id(privkey: nil) - if isMutedThread(ev, privkey: keypair.privkey) { + let threadId = ev.thread_id(keypair: keypair) + if isMutedThread(ev, keypair: keypair) { mutedThreads = mutedThreads.filter { $0 != threadId } _mutedThreadsSet.remove(threadId) notify(.unmute_thread(ev)) diff --git a/damus/Models/SearchHomeModel.swift b/damus/Models/SearchHomeModel.swift @@ -35,7 +35,7 @@ class SearchHomeModel: ObservableObject { } func filter_muted() { - events.filter { should_show_event(privkey: damus_state.keypair.privkey, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: $0) } + events.filter { should_show_event(keypair: damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: $0) } self.objectWillChange.send() } @@ -60,7 +60,7 @@ class SearchHomeModel: ObservableObject { guard sub_id == self.base_subid || sub_id == self.profiles_subid else { return } - if ev.is_textlike && should_show_event(privkey: damus_state.keypair.privkey, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: ev) && !ev.is_reply(nil) + if ev.is_textlike && should_show_event(keypair: damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: ev) && !ev.is_reply(damus_state.keypair) { if !damus_state.settings.multiple_events_per_pubkey && seen_pubkey.contains(ev.pubkey) { return diff --git a/damus/Models/SearchModel.swift b/damus/Models/SearchModel.swift @@ -28,7 +28,7 @@ class SearchModel: ObservableObject { func filter_muted() { self.events.filter { - should_show_event(privkey: state.keypair.privkey, hellthreads: state.muted_threads, contacts: state.contacts, ev: $0) + should_show_event(keypair: state.keypair, hellthreads: state.muted_threads, contacts: state.contacts, ev: $0) } self.objectWillChange.send() } @@ -57,7 +57,7 @@ class SearchModel: ObservableObject { return } - guard should_show_event(privkey: state.keypair.privkey, hellthreads: state.muted_threads, contacts: state.contacts, ev: ev) else { + guard should_show_event(keypair: state.keypair, hellthreads: state.muted_threads, contacts: state.contacts, ev: ev) else { return } diff --git a/damus/Models/ThreadModel.swift b/damus/Models/ThreadModel.swift @@ -18,7 +18,7 @@ class ThreadModel: ObservableObject { self.event_map = Set() self.event = event self.original_event = event - add_event(event, privkey: damus_state.keypair.privkey) + add_event(event, keypair: damus_state.keypair) } var is_original: Bool { @@ -46,9 +46,9 @@ class ThreadModel: ObservableObject { } @discardableResult - func set_active_event(_ ev: NostrEvent, privkey: Privkey?) -> Bool { + func set_active_event(_ ev: NostrEvent, keypair: Keypair) -> Bool { self.event = ev - add_event(ev, privkey: privkey) + add_event(ev, keypair: keypair) //self.objectWillChange.send() return false @@ -59,8 +59,8 @@ class ThreadModel: ObservableObject { var event_filter = NostrFilter() var ref_events = NostrFilter() - let thread_id = event.thread_id(privkey: nil) - + let thread_id = event.thread_id(keypair: .empty) + ref_events.referenced_ids = [thread_id, event.id] ref_events.kinds = [.text] ref_events.limit = 1000 @@ -85,14 +85,14 @@ class ThreadModel: ObservableObject { damus_state.pool.subscribe(sub_id: meta_subid, filters: meta_filters, handler: handle_event) } - func add_event(_ ev: NostrEvent, privkey: Privkey?) { + func add_event(_ ev: NostrEvent, keypair: Keypair) { if event_map.contains(ev) { return } let the_ev = damus_state.events.upsert(ev) - damus_state.replies.count_replies(the_ev, privkey: privkey) - damus_state.events.add_replies(ev: the_ev, privkey: privkey) + damus_state.replies.count_replies(ev, keypair: keypair) + damus_state.events.add_replies(ev: ev, keypair: keypair) event_map.insert(ev) objectWillChange.send() @@ -112,7 +112,7 @@ class ThreadModel: ObservableObject { } } else if ev.is_textlike { - self.add_event(ev, privkey: damus_state.keypair.privkey) + self.add_event(ev, keypair: damus_state.keypair) } } diff --git a/damus/Nostr/NostrEvent.swift b/damus/Nostr/NostrEvent.swift @@ -928,8 +928,8 @@ func validate_event(ev: NostrEvent) -> ValidationResult { return ok ? .ok : .bad_sig } -func first_eref_mention(ev: NostrEvent, privkey: Privkey?) -> Mention<NoteId>? { - let blocks = ev.blocks(privkey).blocks.filter { block in +func first_eref_mention(ev: NostrEvent, keypair: Keypair) -> Mention<NoteId>? { + let blocks = ev.blocks(keypair).blocks.filter { block in guard case .mention(let mention) = block, case .note = mention.ref else { return false diff --git a/damus/Util/EventCache.swift b/damus/Util/EventCache.swift @@ -228,13 +228,13 @@ class EventCache { return model } - func parent_events(event: NostrEvent, privkey: Privkey?) -> [NostrEvent] { + func parent_events(event: NostrEvent, keypair: Keypair) -> [NostrEvent] { var parents: [NostrEvent] = [] var ev = event while true { - guard let direct_reply = ev.direct_replies(privkey).last, + guard let direct_reply = ev.direct_replies(keypair).last, let next_ev = lookup(direct_reply), next_ev != ev else { break @@ -247,8 +247,8 @@ class EventCache { return parents.reversed() } - func add_replies(ev: NostrEvent, privkey: Privkey?) { - for reply in ev.direct_replies(privkey) { + func add_replies(ev: NostrEvent, keypair: Keypair) { + for reply in ev.direct_replies(keypair) { replies.add(id: reply, reply_id: ev.id) } } @@ -420,7 +420,7 @@ func preload_event(plan: PreloadPlan, state: DamusState) async { print("Preloading event \(plan.event.content)") if artifacts == nil && plan.load_artifacts { - let arts = render_note_content(ev: plan.event, profiles: profiles, privkey: our_keypair.privkey) + let arts = render_note_content(ev: plan.event, profiles: profiles, keypair: our_keypair) artifacts = arts // we need these asap @@ -441,8 +441,8 @@ func preload_event(plan: PreloadPlan, state: DamusState) async { } if plan.load_preview, note_artifact_is_separated(kind: plan.event.known_kind) { - let arts = artifacts ?? render_note_content(ev: plan.event, profiles: profiles, privkey: our_keypair.privkey) - + let arts = artifacts ?? render_note_content(ev: plan.event, profiles: profiles, keypair: our_keypair) + // only separated artifacts have previews if case .separated(let sep) = arts { let preview = await load_preview(artifacts: sep) @@ -456,13 +456,13 @@ func preload_event(plan: PreloadPlan, state: DamusState) async { } } - let note_language = plan.data.translations_model.note_language ?? plan.event.note_language(our_keypair.privkey) ?? current_language() + let note_language = plan.data.translations_model.note_language ?? plan.event.note_language(our_keypair) ?? current_language() var translations: TranslateStatus? = nil // We have to recheck should_translate here now that we have note_language if plan.load_translations && should_translate(event: plan.event, our_keypair: our_keypair, settings: settings, note_lang: note_language) && settings.auto_translate { - translations = await translate_note(profiles: profiles, privkey: our_keypair.privkey, event: plan.event, settings: settings, note_lang: note_language) + translations = await translate_note(profiles: profiles, keypair: our_keypair, event: plan.event, settings: settings, note_lang: note_language) } let ts = translations diff --git a/damus/Util/Keys.swift b/damus/Util/Keys.swift @@ -33,6 +33,10 @@ struct Keypair { let pubkey_bech32: String let privkey_bech32: String? + static var empty: Keypair { + Keypair(pubkey: .empty, privkey: nil) + } + func to_full() -> FullKeypair? { guard let privkey = self.privkey else { return nil diff --git a/damus/Util/ReplyCounter.swift b/damus/Util/ReplyCounter.swift @@ -28,7 +28,7 @@ class ReplyCounter { return replies[evid] ?? 0 } - func count_replies(_ event: NostrEvent, privkey: Privkey?) { + func count_replies(_ event: NostrEvent, keypair: Keypair) { guard event.is_textlike else { return } @@ -39,7 +39,7 @@ class ReplyCounter { counted.insert(event.id) - for reply in event.direct_replies(privkey) { + for reply in event.direct_replies(keypair) { if event.pubkey == our_pubkey { self.our_replies[reply] = event } diff --git a/damus/Views/DMView.swift b/damus/Views/DMView.swift @@ -17,7 +17,7 @@ struct DMView: View { var Mention: some View { Group { - if let mention = first_eref_mention(ev: event, privkey: damus_state.keypair.privkey) { + if let mention = first_eref_mention(ev: event, keypair: damus_state.keypair) { BuilderEventView(damus: damus_state, event_id: mention.ref) } else { EmptyView() diff --git a/damus/Views/Events/Components/ReplyPart.swift b/damus/Views/Events/Components/ReplyPart.swift @@ -10,11 +10,11 @@ import SwiftUI struct ReplyPart: View { let events: EventCache let event: NostrEvent - let privkey: Privkey? + let keypair: Keypair let profiles: Profiles var replying_to: NostrEvent? { - guard let note_ref = event.event_refs(privkey).first(where: { evref in evref.is_direct_reply != nil })?.is_direct_reply else { + guard let note_ref = event.event_refs(keypair).first(where: { evref in evref.is_direct_reply != nil })?.is_direct_reply else { return nil } @@ -23,7 +23,7 @@ struct ReplyPart: View { var body: some View { Group { - if event_is_reply(event.event_refs(privkey)) { + if event_is_reply(event.event_refs(keypair)) { ReplyDescription(event: event, replying_to: replying_to, profiles: profiles) } else { EmptyView() @@ -34,6 +34,6 @@ struct ReplyPart: View { struct ReplyPart_Previews: PreviewProvider { static var previews: some View { - ReplyPart(events: test_damus_state().events, event: test_note, privkey: nil, profiles: test_damus_state().profiles) + ReplyPart(events: test_damus_state().events, event: test_note, keypair: Keypair(pubkey: .empty, privkey: nil), profiles: test_damus_state().profiles) } } diff --git a/damus/Views/Events/EventMenu.swift b/damus/Views/Events/EventMenu.swift @@ -54,7 +54,7 @@ struct MenuItems: View { let bookmarked = bookmarks.isBookmarked(event) self._isBookmarked = State(initialValue: bookmarked) - let muted_thread = muted_threads.isMutedThread(event, privkey: keypair.privkey) + let muted_thread = muted_threads.isMutedThread(event, keypair: keypair) self._isMutedThread = State(initialValue: muted_thread) self.bookmarks = bookmarks @@ -68,7 +68,7 @@ struct MenuItems: View { var body: some View { Group { Button { - UIPasteboard.general.string = event.get_content(keypair.privkey) + UIPasteboard.general.string = event.get_content(keypair) } label: { Label(NSLocalizedString("Copy text", comment: "Context menu option for copying the text from an note."), image: "copy2") } @@ -106,7 +106,7 @@ struct MenuItems: View { if event.known_kind != .dm { Button { self.muted_threads.updateMutedThread(event) - let muted = self.muted_threads.isMutedThread(event, privkey: self.keypair.privkey) + let muted = self.muted_threads.isMutedThread(event, keypair: self.keypair) isMutedThread = muted } label: { let imageName = isMutedThread ? "mute" : "mute" diff --git a/damus/Views/Events/EventShell.swift b/damus/Views/Events/EventShell.swift @@ -39,7 +39,7 @@ struct EventShell<Content: View>: View { return nil } - return first_eref_mention(ev: event, privkey: state.keypair.privkey) + return first_eref_mention(ev: event, keypair: state.keypair) } func Mention(_ mention: Mention<NoteId>) -> some View { @@ -71,7 +71,7 @@ struct EventShell<Content: View>: View { UserStatusView(status: state.profiles.profile_data(pubkey).status, show_general: state.settings.show_general_statuses, show_music: state.settings.show_music_statuses) if !options.contains(.no_replying_to) { - ReplyPart(events: state.events, event: event, privkey: state.keypair.privkey, profiles: state.profiles) + ReplyPart(events: state.events, event: event, keypair: state.keypair, profiles: state.profiles) } content @@ -98,7 +98,7 @@ struct EventShell<Content: View>: View { VStack(alignment: .leading, spacing: 2) { EventTop(state: state, event: event, pubkey: pubkey, is_anon: is_anon) UserStatusView(status: state.profiles.profile_data(pubkey).status, show_general: state.settings.show_general_statuses, show_music: state.settings.show_music_statuses) - ReplyPart(events: state.events, event: event, privkey: state.keypair.privkey, profiles: state.profiles) + ReplyPart(events: state.events, event: event, keypair: state.keypair, profiles: state.profiles) } } .padding(.horizontal) diff --git a/damus/Views/Events/Longform/LongformView.swift b/damus/Views/Events/Longform/LongformView.swift @@ -76,8 +76,8 @@ let test_longform_event = LongformEvent.parse(from: NostrEvent( struct LongformView_Previews: PreviewProvider { static var previews: some View { let st = test_damus_state() - let artifacts = render_note_content(ev: test_longform_event.event, profiles: st.profiles, privkey: nil) - + let artifacts = render_note_content(ev: test_longform_event.event, profiles: st.profiles, keypair: Keypair(pubkey: .empty, privkey: nil)) + let model = NoteArtifactsModel(state: .loaded(artifacts)) ScrollView { LongformView(state: st, event: test_longform_event, artifacts: model) diff --git a/damus/Views/Events/MutedEventView.swift b/damus/Views/Events/MutedEventView.swift @@ -18,11 +18,11 @@ struct MutedEventView: View { self.damus_state = damus_state self.event = event self.selected = selected - self._shown = State(initialValue: should_show_event(privkey: damus_state.keypair.privkey, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: event)) + self._shown = State(initialValue: should_show_event(keypair: damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: event)) } var should_mute: Bool { - return !should_show_event(privkey: damus_state.keypair.privkey, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: event) + return !should_show_event(keypair: damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: event) } var MutedBox: some View { diff --git a/damus/Views/Events/SelectedEventView.swift b/damus/Views/Events/SelectedEventView.swift @@ -19,7 +19,7 @@ struct SelectedEventView: View { @StateObject var bar: ActionBarModel var replying_to: NostrEvent? { - guard let note_ref = event.event_refs(damus.keypair.privkey).first(where: { evref in evref.is_direct_reply != nil })?.is_direct_reply else { + guard let note_ref = event.event_refs(damus.keypair).first(where: { evref in evref.is_direct_reply != nil })?.is_direct_reply else { return nil } @@ -50,14 +50,14 @@ struct SelectedEventView: View { .minimumScaleFactor(0.75) .lineLimit(1) - if event_is_reply(event.event_refs(damus.keypair.privkey)) { + if event_is_reply(event.event_refs(damus.keypair)) { ReplyDescription(event: event, replying_to: replying_to, profiles: damus.profiles) .padding(.horizontal) } EventBody(damus_state: damus, event: event, size: size, options: [.wide]) - if let mention = first_eref_mention(ev: event, privkey: damus.keypair.privkey) { + if let mention = first_eref_mention(ev: event, keypair: damus.keypair) { BuilderEventView(damus: damus, event_id: mention.ref) .padding(.horizontal) } diff --git a/damus/Views/NoteContentView.swift b/damus/Views/NoteContentView.swift @@ -36,7 +36,7 @@ struct NoteContentView: View { @ObservedObject var settings: UserSettingsStore var note_artifacts: NoteArtifacts { - return self.artifacts_model.state.artifacts ?? .separated(.just_content(event.get_content(damus_state.keypair.privkey))) + return self.artifacts_model.state.artifacts ?? .separated(.just_content(event.get_content(damus_state.keypair))) } init(damus_state: DamusState, event: NostrEvent, show_images: Bool, size: EventViewKind, options: EventViewOptions) { @@ -180,7 +180,7 @@ struct NoteContentView: View { } await preload_event(plan: plan, state: damus_state) } else if force_artifacts { - let arts = render_note_content(ev: event, profiles: damus_state.profiles, privkey: damus_state.keypair.privkey) + let arts = render_note_content(ev: event, profiles: damus_state.profiles, keypair: damus_state.keypair) self.artifacts_model.state = .loaded(arts) } } @@ -228,7 +228,7 @@ struct NoteContentView: View { var body: some View { ArtifactContent .onReceive(handle_notify(.profile_updated)) { profile in - let blocks = event.blocks(damus_state.keypair.privkey) + let blocks = event.blocks(damus_state.keypair) for block in blocks.blocks { switch block { case .mention(let m): @@ -394,8 +394,8 @@ func note_artifact_is_separated(kind: NostrKind?) -> Bool { return kind != .longform } -func render_note_content(ev: NostrEvent, profiles: Profiles, privkey: Privkey?) -> NoteArtifacts { - let blocks = ev.blocks(privkey) +func render_note_content(ev: NostrEvent, profiles: Profiles, keypair: Keypair) -> NoteArtifacts { + let blocks = ev.blocks(keypair) if ev.known_kind == .longform { return .longform(LongformContent(ev.content)) diff --git a/damus/Views/SearchHomeView.swift b/damus/Views/SearchHomeView.swift @@ -50,7 +50,7 @@ struct SearchHomeView: View { damus: damus_state, show_friend_icon: true, filter: { ev in - if damus_state.muted_threads.isMutedThread(ev, privkey: self.damus_state.keypair.privkey) { + if damus_state.muted_threads.isMutedThread(ev, keypair: self.damus_state.keypair) { return false } diff --git a/damus/Views/ThreadView.swift b/damus/Views/ThreadView.swift @@ -14,7 +14,7 @@ struct ThreadView: View { @Environment(\.dismiss) var dismiss var parent_events: [NostrEvent] { - state.events.parent_events(event: thread.event, privkey: state.keypair.privkey) + state.events.parent_events(event: thread.event, keypair: state.keypair) } var child_events: [NostrEvent] { @@ -34,7 +34,7 @@ struct ThreadView: View { selected: false) .padding(.horizontal) .onTapGesture { - thread.set_active_event(parent_event, privkey: self.state.keypair.privkey) + thread.set_active_event(parent_event, keypair: self.state.keypair) scroll_to_event(scroller: reader, id: parent_event.id, delay: 0.1, animate: false) } @@ -77,7 +77,7 @@ struct ThreadView: View { ) .padding(.horizontal) .onTapGesture { - thread.set_active_event(child_event, privkey: state.keypair.privkey) + thread.set_active_event(child_event, keypair: state.keypair) scroll_to_event(scroller: reader, id: child_event.id, delay: 0.1, animate: false) } diff --git a/nostrdb/NdbNote.swift b/nostrdb/NdbNote.swift @@ -268,8 +268,8 @@ extension NdbNote { return !too_big } - func get_blocks(privkey: Privkey?) -> Blocks { - return parse_note_content(content: .init(note: self, privkey: privkey)) + func get_blocks(keypair: Keypair) -> Blocks { + return parse_note_content(content: .init(note: self, keypair: keypair)) } func get_inner_event(cache: EventCache) -> NostrEvent? { @@ -314,41 +314,38 @@ extension NdbNote { References<RefId>(tags: self.tags) } - func event_refs(_ privkey: Privkey?) -> [EventRef] { + func event_refs(_ keypair: Keypair) -> [EventRef] { if let rs = _event_refs { return rs } - let refs = interpret_event_refs_ndb(blocks: self.blocks(privkey).blocks, tags: self.tags) + let refs = interpret_event_refs_ndb(blocks: self.blocks(keypair).blocks, tags: self.tags) self._event_refs = refs return refs } - func get_content(_ privkey: Privkey?) -> String { + func get_content(_ keypair: Keypair) -> String { if known_kind == .dm { - return decrypted(privkey: privkey) ?? "*failed to decrypt content*" + return decrypted(keypair: keypair) ?? "*failed to decrypt content*" } return content } - func blocks(_ privkey: Privkey?) -> Blocks { + func blocks(_ keypair: Keypair) -> Blocks { if let bs = _blocks { return bs } - let blocks = get_blocks(privkey: privkey) + let blocks = get_blocks(keypair: keypair) self._blocks = blocks return blocks } // NDBTODO: switch this to operating on bytes not strings - func decrypted(privkey: Privkey?) -> String? { + func decrypted(keypair: Keypair) -> String? { if let decrypted_content { return decrypted_content } - guard let privkey, - let our_pubkey = privkey_to_pubkey(privkey: privkey) else { - return nil - } + let our_pubkey = keypair.pubkey // NDBTODO: don't hex encode var pubkey = self.pubkey @@ -359,14 +356,14 @@ extension NdbNote { } // NDBTODO: pass data to pubkey - let dec = decrypt_dm(privkey, pubkey: pubkey, content: self.content, encoding: .base64) + let dec = decrypt_dm(keypair.privkey, pubkey: pubkey, content: self.content, encoding: .base64) self.decrypted_content = dec return dec } - public func direct_replies(_ privkey: Privkey?) -> [NoteId] { - return event_refs(privkey).reduce(into: []) { acc, evref in + public func direct_replies(_ keypair: Keypair) -> [NoteId] { + return event_refs(keypair).reduce(into: []) { acc, evref in if let direct_reply = evref.is_direct_reply { acc.append(direct_reply.note_id) } @@ -374,8 +371,8 @@ extension NdbNote { } // NDBTODO: just use Id - public func thread_id(privkey: Privkey?) -> NoteId { - for ref in event_refs(privkey) { + public func thread_id(keypair: Keypair) -> NoteId { + for ref in event_refs(keypair) { if let thread_id = ref.is_thread_id { return thread_id.note_id } @@ -405,16 +402,16 @@ extension NdbNote { } */ - func is_reply(_ privkey: Privkey?) -> Bool { - return event_is_reply(self.event_refs(privkey)) + func is_reply(_ keypair: Keypair) -> Bool { + return event_is_reply(self.event_refs(keypair)) } - func note_language(_ privkey: Privkey?) -> String? { + func note_language(_ keypair: Keypair) -> String? { assert(!Thread.isMainThread, "This function must not be run on the main thread.") // Rely on Apple's NLLanguageRecognizer to tell us which language it thinks the note is in // and filter on only the text portions of the content as URLs and hashtags confuse the language recognizer. - let originalBlocks = self.blocks(privkey).blocks + let originalBlocks = self.blocks(keypair).blocks let originalOnlyText = originalBlocks.compactMap { $0.is_text }.joined(separator: " ") // Only accept language recognition hypothesis if there's at least a 50% probability that it's accurate.