blocks: pass keypair instead of privkey to avoid pubkey gen

Generating a pubkey is quite slow, so pass a keypair instead of privkey
This commit is contained in:
William Casarin
2023-08-28 11:46:03 -07:00
parent 8e92e28faf
commit c71b0ee916
24 changed files with 108 additions and 107 deletions

View File

@@ -64,7 +64,7 @@ struct TranslateView: View {
guard let note_language = translations_model.note_language else { guard let note_language = translations_model.note_language else {
return 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 { DispatchQueue.main.async {
self.translations_model.state = res 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. // If the note language is different from our preferred languages, send a translation request.
let translator = Translator(settings) 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()) let translated_note = try? await translator.translate(originalContent, from: note_lang, to: current_language())
guard let translated_note else { guard let translated_note else {

View File

@@ -11,9 +11,9 @@ enum NoteContent {
case note(NostrEvent) case note(NostrEvent)
case content(String, TagsSequence?) case content(String, TagsSequence?)
init(note: NostrEvent, privkey: Privkey?) { init(note: NostrEvent, keypair: Keypair) {
if note.known_kind == .dm { if note.known_kind == .dm {
self = .content(note.get_content(privkey), note.tags) self = .content(note.get_content(keypair), note.tags)
} else { } else {
self = .note(note) self = .note(note)
} }

View File

@@ -59,11 +59,11 @@ enum Sheets: Identifiable {
enum FilterState : Int { enum FilterState : Int {
case posts_and_replies = 1 case posts_and_replies = 1
case posts = 0 case posts = 0
func filter(ev: NostrEvent) -> Bool { func filter(ev: NostrEvent) -> Bool {
switch self { switch self {
case .posts: case .posts:
return ev.known_kind == .boost || !ev.is_reply(nil) return ev.known_kind == .boost || !ev.is_reply(.empty)
case .posts_and_replies: case .posts_and_replies:
return true return true
} }

View File

@@ -43,8 +43,8 @@ struct DamusState {
// thread zaps // thread zaps
if let ev = zap.event, !settings.nozaps, zap.is_in_thread { if let ev = zap.event, !settings.nozaps, zap.is_in_thread {
// [nozaps]: thread zaps are only available outside of the app store // [nozaps]: thread zaps are only available outside of the app store
replies.count_replies(ev, privkey: self.keypair.privkey) replies.count_replies(ev, keypair: self.keypair)
events.add_replies(ev: ev, privkey: self.keypair.privkey) events.add_replies(ev: ev, keypair: self.keypair)
} }
// associate with events as well // associate with events as well

View File

@@ -253,7 +253,7 @@ class HomeModel {
process_zap_event(damus_state: damus_state, ev: ev) { zapres in process_zap_event(damus_state: damus_state, ev: ev) { zapres in
guard case .done(let zap) = zapres, guard case .done(let zap) = zapres,
zap.target.pubkey == self.damus_state.keypair.pubkey, 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 return
} }
@@ -299,7 +299,7 @@ class HomeModel {
return false 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 // don't show notifications from ourselves
guard ev.pubkey != damus_state.pubkey, guard ev.pubkey != damus_state.pubkey,
event_has_our_pubkey(ev, our_pubkey: self.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 return
} }
@@ -637,13 +637,13 @@ class HomeModel {
func handle_text_event(sub_id: String, _ ev: NostrEvent) { 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 return
} }
// TODO: will we need to process this in other places like zap request contents, etc? // TODO: will we need to process this in other places like zap request contents, etc?
process_image_metadatas(cache: damus_state.events, ev: ev) 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) damus_state.events.insert(ev)
if sub_id == home_subid { if sub_id == home_subid {
@@ -657,14 +657,14 @@ class HomeModel {
notification_status.new_events = notifs notification_status.new_events = notifs
if damus_state.settings.dm_notification && ev.age < HomeModel.event_max_age_for_notification { 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) let notify = LocalNotification(type: .dm, event: ev, target: ev, content: convo)
create_local_notification(profiles: damus_state.profiles, notify: notify) create_local_notification(profiles: damus_state.profiles, notify: notify)
} }
} }
func handle_dm(_ ev: NostrEvent) { 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 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) { if contacts.is_muted(ev.pubkey) {
return false return false
} }
if hellthreads.isMutedThread(ev, privkey: privkey) { if hellthreads.isMutedThread(ev, keypair: keypair) {
return false 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 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 // special case for longform events
if ev.known_kind == .longform { if ev.known_kind == .longform {
let longform = LongformEvent(event: ev) 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. // 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 return
} }
@@ -1265,12 +1265,12 @@ func process_local_notification(damus_state: DamusState, event ev: NostrEvent) {
} }
if type == .text, damus_state.settings.mention_notification { 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 { for case .mention(let mention) in blocks {
guard case .pubkey(let pk) = mention.ref, pk == damus_state.keypair.pubkey else { guard case .pubkey(let pk) = mention.ref, pk == damus_state.keypair.pubkey else {
continue 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) let notify = LocalNotification(type: .mention, event: ev, target: ev, content: content_preview)
create_local_notification(profiles: damus_state.profiles, notify: notify ) 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, damus_state.settings.repost_notification,
let inner_ev = ev.get_inner_event(cache: damus_state.events) 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) let notify = LocalNotification(type: .repost, event: ev, target: inner_ev, content: content_preview)
create_local_notification(profiles: damus_state.profiles, notify: notify) create_local_notification(profiles: damus_state.profiles, notify: notify)
} else if type == .like, } 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 evid = ev.referenced_ids.last,
let liked_event = damus_state.events.lookup(evid) 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) let notify = LocalNotification(type: .like, event: ev, target: liked_event, content: content_preview)
create_local_notification(profiles: damus_state.profiles, notify: notify) create_local_notification(profiles: damus_state.profiles, notify: notify)
} }

View File

@@ -56,13 +56,13 @@ class MutedThreadsManager: ObservableObject {
self.keypair = keypair self.keypair = keypair
} }
func isMutedThread(_ ev: NostrEvent, privkey: Privkey?) -> Bool { func isMutedThread(_ ev: NostrEvent, keypair: Keypair) -> Bool {
return _mutedThreadsSet.contains(ev.thread_id(privkey: privkey)) return _mutedThreadsSet.contains(ev.thread_id(keypair: keypair))
} }
func updateMutedThread(_ ev: NostrEvent) { func updateMutedThread(_ ev: NostrEvent) {
let threadId = ev.thread_id(privkey: nil) let threadId = ev.thread_id(keypair: keypair)
if isMutedThread(ev, privkey: keypair.privkey) { if isMutedThread(ev, keypair: keypair) {
mutedThreads = mutedThreads.filter { $0 != threadId } mutedThreads = mutedThreads.filter { $0 != threadId }
_mutedThreadsSet.remove(threadId) _mutedThreadsSet.remove(threadId)
notify(.unmute_thread(ev)) notify(.unmute_thread(ev))

View File

@@ -35,7 +35,7 @@ class SearchHomeModel: ObservableObject {
} }
func filter_muted() { 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() self.objectWillChange.send()
} }
@@ -60,7 +60,7 @@ class SearchHomeModel: ObservableObject {
guard sub_id == self.base_subid || sub_id == self.profiles_subid else { guard sub_id == self.base_subid || sub_id == self.profiles_subid else {
return 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) { if !damus_state.settings.multiple_events_per_pubkey && seen_pubkey.contains(ev.pubkey) {
return return

View File

@@ -28,7 +28,7 @@ class SearchModel: ObservableObject {
func filter_muted() { func filter_muted() {
self.events.filter { 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() self.objectWillChange.send()
} }
@@ -57,7 +57,7 @@ class SearchModel: ObservableObject {
return 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 return
} }

View File

@@ -18,7 +18,7 @@ class ThreadModel: ObservableObject {
self.event_map = Set() self.event_map = Set()
self.event = event self.event = event
self.original_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 { var is_original: Bool {
@@ -46,9 +46,9 @@ class ThreadModel: ObservableObject {
} }
@discardableResult @discardableResult
func set_active_event(_ ev: NostrEvent, privkey: Privkey?) -> Bool { func set_active_event(_ ev: NostrEvent, keypair: Keypair) -> Bool {
self.event = ev self.event = ev
add_event(ev, privkey: privkey) add_event(ev, keypair: keypair)
//self.objectWillChange.send() //self.objectWillChange.send()
return false return false
@@ -59,8 +59,8 @@ class ThreadModel: ObservableObject {
var event_filter = NostrFilter() var event_filter = NostrFilter()
var ref_events = 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.referenced_ids = [thread_id, event.id]
ref_events.kinds = [.text] ref_events.kinds = [.text]
ref_events.limit = 1000 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) 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) { if event_map.contains(ev) {
return return
} }
let the_ev = damus_state.events.upsert(ev) let the_ev = damus_state.events.upsert(ev)
damus_state.replies.count_replies(the_ev, privkey: privkey) damus_state.replies.count_replies(ev, keypair: keypair)
damus_state.events.add_replies(ev: the_ev, privkey: privkey) damus_state.events.add_replies(ev: ev, keypair: keypair)
event_map.insert(ev) event_map.insert(ev)
objectWillChange.send() objectWillChange.send()
@@ -112,7 +112,7 @@ class ThreadModel: ObservableObject {
} }
} else if ev.is_textlike { } else if ev.is_textlike {
self.add_event(ev, privkey: damus_state.keypair.privkey) self.add_event(ev, keypair: damus_state.keypair)
} }
} }

View File

@@ -928,8 +928,8 @@ func validate_event(ev: NostrEvent) -> ValidationResult {
return ok ? .ok : .bad_sig return ok ? .ok : .bad_sig
} }
func first_eref_mention(ev: NostrEvent, privkey: Privkey?) -> Mention<NoteId>? { func first_eref_mention(ev: NostrEvent, keypair: Keypair) -> Mention<NoteId>? {
let blocks = ev.blocks(privkey).blocks.filter { block in let blocks = ev.blocks(keypair).blocks.filter { block in
guard case .mention(let mention) = block, guard case .mention(let mention) = block,
case .note = mention.ref else { case .note = mention.ref else {
return false return false

View File

@@ -228,13 +228,13 @@ class EventCache {
return model return model
} }
func parent_events(event: NostrEvent, privkey: Privkey?) -> [NostrEvent] { func parent_events(event: NostrEvent, keypair: Keypair) -> [NostrEvent] {
var parents: [NostrEvent] = [] var parents: [NostrEvent] = []
var ev = event var ev = event
while true { 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 let next_ev = lookup(direct_reply), next_ev != ev
else { else {
break break
@@ -247,8 +247,8 @@ class EventCache {
return parents.reversed() return parents.reversed()
} }
func add_replies(ev: NostrEvent, privkey: Privkey?) { func add_replies(ev: NostrEvent, keypair: Keypair) {
for reply in ev.direct_replies(privkey) { for reply in ev.direct_replies(keypair) {
replies.add(id: reply, reply_id: ev.id) 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)") print("Preloading event \(plan.event.content)")
if artifacts == nil && plan.load_artifacts { 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 artifacts = arts
// we need these asap // 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) { 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 // only separated artifacts have previews
if case .separated(let sep) = arts { if case .separated(let sep) = arts {
let preview = await load_preview(artifacts: sep) 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 var translations: TranslateStatus? = nil
// We have to recheck should_translate here now that we have note_language // 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 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 let ts = translations

View File

@@ -33,6 +33,10 @@ struct Keypair {
let pubkey_bech32: String let pubkey_bech32: String
let privkey_bech32: String? let privkey_bech32: String?
static var empty: Keypair {
Keypair(pubkey: .empty, privkey: nil)
}
func to_full() -> FullKeypair? { func to_full() -> FullKeypair? {
guard let privkey = self.privkey else { guard let privkey = self.privkey else {
return nil return nil

View File

@@ -28,7 +28,7 @@ class ReplyCounter {
return replies[evid] ?? 0 return replies[evid] ?? 0
} }
func count_replies(_ event: NostrEvent, privkey: Privkey?) { func count_replies(_ event: NostrEvent, keypair: Keypair) {
guard event.is_textlike else { guard event.is_textlike else {
return return
} }
@@ -39,7 +39,7 @@ class ReplyCounter {
counted.insert(event.id) counted.insert(event.id)
for reply in event.direct_replies(privkey) { for reply in event.direct_replies(keypair) {
if event.pubkey == our_pubkey { if event.pubkey == our_pubkey {
self.our_replies[reply] = event self.our_replies[reply] = event
} }

View File

@@ -17,7 +17,7 @@ struct DMView: View {
var Mention: some View { var Mention: some View {
Group { 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) BuilderEventView(damus: damus_state, event_id: mention.ref)
} else { } else {
EmptyView() EmptyView()

View File

@@ -10,11 +10,11 @@ import SwiftUI
struct ReplyPart: View { struct ReplyPart: View {
let events: EventCache let events: EventCache
let event: NostrEvent let event: NostrEvent
let privkey: Privkey? let keypair: Keypair
let profiles: Profiles let profiles: Profiles
var replying_to: NostrEvent? { 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 return nil
} }
@@ -23,7 +23,7 @@ struct ReplyPart: View {
var body: some View { var body: some View {
Group { 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) ReplyDescription(event: event, replying_to: replying_to, profiles: profiles)
} else { } else {
EmptyView() EmptyView()
@@ -34,6 +34,6 @@ struct ReplyPart: View {
struct ReplyPart_Previews: PreviewProvider { struct ReplyPart_Previews: PreviewProvider {
static var previews: some View { 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)
} }
} }

View File

@@ -54,7 +54,7 @@ struct MenuItems: View {
let bookmarked = bookmarks.isBookmarked(event) let bookmarked = bookmarks.isBookmarked(event)
self._isBookmarked = State(initialValue: bookmarked) 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._isMutedThread = State(initialValue: muted_thread)
self.bookmarks = bookmarks self.bookmarks = bookmarks
@@ -68,7 +68,7 @@ struct MenuItems: View {
var body: some View { var body: some View {
Group { Group {
Button { Button {
UIPasteboard.general.string = event.get_content(keypair.privkey) UIPasteboard.general.string = event.get_content(keypair)
} label: { } label: {
Label(NSLocalizedString("Copy text", comment: "Context menu option for copying the text from an note."), image: "copy2") 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 { if event.known_kind != .dm {
Button { Button {
self.muted_threads.updateMutedThread(event) 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 isMutedThread = muted
} label: { } label: {
let imageName = isMutedThread ? "mute" : "mute" let imageName = isMutedThread ? "mute" : "mute"

View File

@@ -39,7 +39,7 @@ struct EventShell<Content: View>: View {
return nil 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 { 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) 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) { 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 content
@@ -98,7 +98,7 @@ struct EventShell<Content: View>: View {
VStack(alignment: .leading, spacing: 2) { VStack(alignment: .leading, spacing: 2) {
EventTop(state: state, event: event, pubkey: pubkey, is_anon: is_anon) 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) 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) .padding(.horizontal)

View File

@@ -76,8 +76,8 @@ let test_longform_event = LongformEvent.parse(from: NostrEvent(
struct LongformView_Previews: PreviewProvider { struct LongformView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
let st = test_damus_state() 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)) let model = NoteArtifactsModel(state: .loaded(artifacts))
ScrollView { ScrollView {
LongformView(state: st, event: test_longform_event, artifacts: model) LongformView(state: st, event: test_longform_event, artifacts: model)

View File

@@ -18,11 +18,11 @@ struct MutedEventView: View {
self.damus_state = damus_state self.damus_state = damus_state
self.event = event self.event = event
self.selected = selected 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 { 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 { var MutedBox: some View {

View File

@@ -19,7 +19,7 @@ struct SelectedEventView: View {
@StateObject var bar: ActionBarModel @StateObject var bar: ActionBarModel
var replying_to: NostrEvent? { 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 return nil
} }
@@ -50,14 +50,14 @@ struct SelectedEventView: View {
.minimumScaleFactor(0.75) .minimumScaleFactor(0.75)
.lineLimit(1) .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) ReplyDescription(event: event, replying_to: replying_to, profiles: damus.profiles)
.padding(.horizontal) .padding(.horizontal)
} }
EventBody(damus_state: damus, event: event, size: size, options: [.wide]) 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) BuilderEventView(damus: damus, event_id: mention.ref)
.padding(.horizontal) .padding(.horizontal)
} }

View File

@@ -36,7 +36,7 @@ struct NoteContentView: View {
@ObservedObject var settings: UserSettingsStore @ObservedObject var settings: UserSettingsStore
var note_artifacts: NoteArtifacts { 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) { 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) await preload_event(plan: plan, state: damus_state)
} else if force_artifacts { } 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) self.artifacts_model.state = .loaded(arts)
} }
} }
@@ -228,7 +228,7 @@ struct NoteContentView: View {
var body: some View { var body: some View {
ArtifactContent ArtifactContent
.onReceive(handle_notify(.profile_updated)) { profile in .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 { for block in blocks.blocks {
switch block { switch block {
case .mention(let m): case .mention(let m):
@@ -394,8 +394,8 @@ func note_artifact_is_separated(kind: NostrKind?) -> Bool {
return kind != .longform return kind != .longform
} }
func render_note_content(ev: NostrEvent, profiles: Profiles, privkey: Privkey?) -> NoteArtifacts { func render_note_content(ev: NostrEvent, profiles: Profiles, keypair: Keypair) -> NoteArtifacts {
let blocks = ev.blocks(privkey) let blocks = ev.blocks(keypair)
if ev.known_kind == .longform { if ev.known_kind == .longform {
return .longform(LongformContent(ev.content)) return .longform(LongformContent(ev.content))

View File

@@ -50,7 +50,7 @@ struct SearchHomeView: View {
damus: damus_state, damus: damus_state,
show_friend_icon: true, show_friend_icon: true,
filter: { ev in 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 return false
} }

View File

@@ -14,7 +14,7 @@ struct ThreadView: View {
@Environment(\.dismiss) var dismiss @Environment(\.dismiss) var dismiss
var parent_events: [NostrEvent] { 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] { var child_events: [NostrEvent] {
@@ -34,7 +34,7 @@ struct ThreadView: View {
selected: false) selected: false)
.padding(.horizontal) .padding(.horizontal)
.onTapGesture { .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) scroll_to_event(scroller: reader, id: parent_event.id, delay: 0.1, animate: false)
} }
@@ -77,7 +77,7 @@ struct ThreadView: View {
) )
.padding(.horizontal) .padding(.horizontal)
.onTapGesture { .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) scroll_to_event(scroller: reader, id: child_event.id, delay: 0.1, animate: false)
} }

View File

@@ -268,8 +268,8 @@ extension NdbNote {
return !too_big return !too_big
} }
func get_blocks(privkey: Privkey?) -> Blocks { func get_blocks(keypair: Keypair) -> Blocks {
return parse_note_content(content: .init(note: self, privkey: privkey)) return parse_note_content(content: .init(note: self, keypair: keypair))
} }
func get_inner_event(cache: EventCache) -> NostrEvent? { func get_inner_event(cache: EventCache) -> NostrEvent? {
@@ -314,41 +314,38 @@ extension NdbNote {
References<RefId>(tags: self.tags) References<RefId>(tags: self.tags)
} }
func event_refs(_ privkey: Privkey?) -> [EventRef] { func event_refs(_ keypair: Keypair) -> [EventRef] {
if let rs = _event_refs { if let rs = _event_refs {
return rs 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 self._event_refs = refs
return refs return refs
} }
func get_content(_ privkey: Privkey?) -> String { func get_content(_ keypair: Keypair) -> String {
if known_kind == .dm { if known_kind == .dm {
return decrypted(privkey: privkey) ?? "*failed to decrypt content*" return decrypted(keypair: keypair) ?? "*failed to decrypt content*"
} }
return content return content
} }
func blocks(_ privkey: Privkey?) -> Blocks { func blocks(_ keypair: Keypair) -> Blocks {
if let bs = _blocks { return bs } if let bs = _blocks { return bs }
let blocks = get_blocks(privkey: privkey) let blocks = get_blocks(keypair: keypair)
self._blocks = blocks self._blocks = blocks
return blocks return blocks
} }
// NDBTODO: switch this to operating on bytes not strings // NDBTODO: switch this to operating on bytes not strings
func decrypted(privkey: Privkey?) -> String? { func decrypted(keypair: Keypair) -> String? {
if let decrypted_content { if let decrypted_content {
return decrypted_content return decrypted_content
} }
guard let privkey, let our_pubkey = keypair.pubkey
let our_pubkey = privkey_to_pubkey(privkey: privkey) else {
return nil
}
// NDBTODO: don't hex encode // NDBTODO: don't hex encode
var pubkey = self.pubkey var pubkey = self.pubkey
@@ -359,14 +356,14 @@ extension NdbNote {
} }
// NDBTODO: pass data to pubkey // 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 self.decrypted_content = dec
return dec return dec
} }
public func direct_replies(_ privkey: Privkey?) -> [NoteId] { public func direct_replies(_ keypair: Keypair) -> [NoteId] {
return event_refs(privkey).reduce(into: []) { acc, evref in return event_refs(keypair).reduce(into: []) { acc, evref in
if let direct_reply = evref.is_direct_reply { if let direct_reply = evref.is_direct_reply {
acc.append(direct_reply.note_id) acc.append(direct_reply.note_id)
} }
@@ -374,8 +371,8 @@ extension NdbNote {
} }
// NDBTODO: just use Id // NDBTODO: just use Id
public func thread_id(privkey: Privkey?) -> NoteId { public func thread_id(keypair: Keypair) -> NoteId {
for ref in event_refs(privkey) { for ref in event_refs(keypair) {
if let thread_id = ref.is_thread_id { if let thread_id = ref.is_thread_id {
return thread_id.note_id return thread_id.note_id
} }
@@ -405,16 +402,16 @@ extension NdbNote {
} }
*/ */
func is_reply(_ privkey: Privkey?) -> Bool { func is_reply(_ keypair: Keypair) -> Bool {
return event_is_reply(self.event_refs(privkey)) 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.") 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 // 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. // 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: " ") 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. // Only accept language recognition hypothesis if there's at least a 50% probability that it's accurate.