damus

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

commit be08083b88f2ea53a0525808fe7cf0aeba3ff617
parent c2325a5e390a001f4433072070b297531346a6f8
Author: William Casarin <jb55@jb55.com>
Date:   Fri, 28 Apr 2023 17:22:53 -0700

Load zaps instantly on events

Refactor our event cache a bit and add zap caching

Changelog-Changed: Load zaps instantly on events

Diffstat:
Mdamus/Models/DamusState.swift | 8++++++++
Mdamus/Models/HomeModel.swift | 4++--
Mdamus/Models/ZapsModel.swift | 14+++++++-------
Mdamus/Util/EventCache.swift | 58++++++++++++++++++++++++++++++++++++++++++++--------------
Mdamus/Views/Notifications/EventGroupView.swift | 2+-
Mdamus/Views/Notifications/ProfilePicturesView.swift | 10+++++-----
6 files changed, 67 insertions(+), 29 deletions(-)

diff --git a/damus/Models/DamusState.swift b/damus/Models/DamusState.swift @@ -31,6 +31,14 @@ struct DamusState { let replies: ReplyCounter let muted_threads: MutedThreadsManager + @discardableResult + func add_zap(zap: Zap) -> Bool { + // store generic zap mapping + self.zaps.add_zap(zap: zap) + // associate with events as well + return self.events.store_zap(zap: zap) + } + var pubkey: String { return keypair.pubkey } diff --git a/damus/Models/HomeModel.swift b/damus/Models/HomeModel.swift @@ -128,7 +128,7 @@ class HomeModel: ObservableObject { return } - damus_state.zaps.add_zap(zap: zap) + damus_state.add_zap(zap: zap) guard zap.target.pubkey == our_keypair.pubkey else { return @@ -726,7 +726,7 @@ func guard_valid_event(events: EventCache, ev: NostrEvent, callback: @escaping ( let result = validate_event(ev: ev) DispatchQueue.main.async { - events.validation[ev.id] = result + events.store_event_validation(evid: ev.id, validated: result) guard result == .ok else { return } diff --git a/damus/Models/ZapsModel.swift b/damus/Models/ZapsModel.swift @@ -10,7 +10,6 @@ import Foundation class ZapsModel: ObservableObject { let state: DamusState let target: ZapTarget - var zaps: [Zap] let zaps_subid = UUID().description let profiles_subid = UUID().description @@ -18,7 +17,10 @@ class ZapsModel: ObservableObject { init(state: DamusState, target: ZapTarget) { self.state = state self.target = target - self.zaps = [] + } + + var zaps: [Zap] { + return state.events.lookup_zaps(target: target) } func subscribe() { @@ -51,7 +53,7 @@ class ZapsModel: ObservableObject { case .notice: break case .eose: - let events = self.zaps.map { $0.request.ev } + let events = state.events.lookup_zaps(target: target).map { $0.request_ev } load_profiles(profiles_subid: profiles_subid, relay_id: relay_id, load: .from_events(events), damus_state: state) case .event(_, let ev): guard ev.kind == 9735 else { @@ -59,7 +61,7 @@ class ZapsModel: ObservableObject { } if let zap = state.zaps.zaps[ev.id] { - if insert_uniq_sorted_zap_by_amount(zaps: &zaps, new_zap: zap) { + if state.events.store_zap(zap: zap) { objectWillChange.send() } } else { @@ -71,9 +73,7 @@ class ZapsModel: ObservableObject { return } - state.zaps.add_zap(zap: zap) - - if insert_uniq_sorted_zap_by_amount(zaps: &zaps, new_zap: zap) { + if self.state.add_zap(zap: zap) { objectWillChange.send() } } diff --git a/damus/Util/EventCache.swift b/damus/Util/EventCache.swift @@ -34,15 +34,26 @@ enum ImageMetaProcessState { } } +class EventData: ObservableObject { + @Published var translations: TranslateStatus? + @Published var artifacts: NoteArtifacts? + @Published var zaps: [Zap] + var validated: ValidationResult + + init(zaps: [Zap] = []) { + self.translations = nil + self.artifacts = nil + self.zaps = zaps + self.validated = .unknown + } +} + class EventCache { private var events: [String: NostrEvent] = [:] private var replies = ReplyMap() private var cancellable: AnyCancellable? - private var translations: [String: TranslateStatus] = [:] - private var artifacts: [String: NoteArtifacts] = [:] - // url to meta private var image_metadata: [String: ImageMetadataState] = [:] - var validation: [String: ValidationResult] = [:] + private var event_data: [String: EventData] = [:] //private var thread_latest: [String: Int64] @@ -54,20 +65,40 @@ class EventCache { } } - func is_event_valid(_ evid: String) -> ValidationResult { - guard let result = validation[evid] else { - return .unknown + private func get_cache_data(_ evid: String) -> EventData { + guard let data = event_data[evid] else { + let data = EventData() + event_data[evid] = data + return data } - return result + return data + } + + func is_event_valid(_ evid: String) -> ValidationResult { + return get_cache_data(evid).validated + } + + func store_event_validation(evid: String, validated: ValidationResult) { + get_cache_data(evid).validated = validated } func store_translation_artifacts(evid: String, translated: TranslateStatus) { - self.translations[evid] = translated + get_cache_data(evid).translations = translated } func store_artifacts(evid: String, artifacts: NoteArtifacts) { - self.artifacts[evid] = artifacts + get_cache_data(evid).artifacts = artifacts + } + + @discardableResult + func store_zap(zap: Zap) -> Bool { + var data = get_cache_data(zap.target.id) + return insert_uniq_sorted_zap_by_amount(zaps: &data.zaps, new_zap: zap) + } + + func lookup_zaps(target: ZapTarget) -> [Zap] { + return get_cache_data(target.id).zaps } func store_img_metadata(url: URL, meta: ImageMetadataState) { @@ -75,7 +106,7 @@ class EventCache { } func lookup_artifacts(evid: String) -> NoteArtifacts? { - return self.artifacts[evid] + return get_cache_data(evid).artifacts } func lookup_img_metadata(url: URL) -> ImageMetadataState? { @@ -83,7 +114,7 @@ class EventCache { } func lookup_translated_artifacts(evid: String) -> TranslateStatus? { - return self.translations[evid] + return get_cache_data(evid).translations } func parent_events(event: NostrEvent) -> [NostrEvent] { @@ -149,8 +180,7 @@ class EventCache { private func prune() { events = [:] - translations = [:] - artifacts = [:] + event_data = [:] replies.replies = [:] } } diff --git a/damus/Views/Notifications/EventGroupView.swift b/damus/Views/Notifications/EventGroupView.swift @@ -204,7 +204,7 @@ struct EventGroupView: View { .frame(width: PFP_SIZE + 10) VStack(alignment: .leading) { - ProfilePicturesView(state: state, events: group.events) + ProfilePicturesView(state: state, pubkeys: group.events.map { $0.pubkey }) if let event { let thread = ThreadModel(event: event, damus_state: state) diff --git a/damus/Views/Notifications/ProfilePicturesView.swift b/damus/Views/Notifications/ProfilePicturesView.swift @@ -9,7 +9,7 @@ import SwiftUI struct ProfilePicturesView: View { let state: DamusState - let events: [NostrEvent] + let pubkeys: [String] @State var nav_target: String? = nil @State var navigating: Bool = false @@ -19,10 +19,10 @@ struct ProfilePicturesView: View { EmptyView() } HStack { - ForEach(events.prefix(8)) { ev in - ProfilePicView(pubkey: ev.pubkey, size: 32.0, highlight: .none, profiles: state.profiles, disable_animation: state.settings.disable_animation) + ForEach(pubkeys.prefix(8), id: \.self) { pubkey in + ProfilePicView(pubkey: pubkey, size: 32.0, highlight: .none, profiles: state.profiles, disable_animation: state.settings.disable_animation) .onTapGesture { - nav_target = ev.pubkey + nav_target = pubkey navigating = true } } @@ -32,6 +32,6 @@ struct ProfilePicturesView: View { struct ProfilePicturesView_Previews: PreviewProvider { static var previews: some View { - ProfilePicturesView(state: test_damus_state(), events: [test_event, test_event]) + ProfilePicturesView(state: test_damus_state(), pubkeys: ["a", "b"]) } }