Load zaps instantly on events

Refactor our event cache a bit and add zap caching

Changelog-Changed: Load zaps instantly on events
This commit is contained in:
William Casarin
2023-04-28 17:22:53 -07:00
parent c2325a5e39
commit be08083b88
6 changed files with 67 additions and 29 deletions

View File

@@ -31,6 +31,14 @@ struct DamusState {
let replies: ReplyCounter let replies: ReplyCounter
let muted_threads: MutedThreadsManager 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 { var pubkey: String {
return keypair.pubkey return keypair.pubkey
} }

View File

@@ -128,7 +128,7 @@ class HomeModel: ObservableObject {
return return
} }
damus_state.zaps.add_zap(zap: zap) damus_state.add_zap(zap: zap)
guard zap.target.pubkey == our_keypair.pubkey else { guard zap.target.pubkey == our_keypair.pubkey else {
return return
@@ -726,7 +726,7 @@ func guard_valid_event(events: EventCache, ev: NostrEvent, callback: @escaping (
let result = validate_event(ev: ev) let result = validate_event(ev: ev)
DispatchQueue.main.async { DispatchQueue.main.async {
events.validation[ev.id] = result events.store_event_validation(evid: ev.id, validated: result)
guard result == .ok else { guard result == .ok else {
return return
} }

View File

@@ -10,7 +10,6 @@ import Foundation
class ZapsModel: ObservableObject { class ZapsModel: ObservableObject {
let state: DamusState let state: DamusState
let target: ZapTarget let target: ZapTarget
var zaps: [Zap]
let zaps_subid = UUID().description let zaps_subid = UUID().description
let profiles_subid = UUID().description let profiles_subid = UUID().description
@@ -18,7 +17,10 @@ class ZapsModel: ObservableObject {
init(state: DamusState, target: ZapTarget) { init(state: DamusState, target: ZapTarget) {
self.state = state self.state = state
self.target = target self.target = target
self.zaps = [] }
var zaps: [Zap] {
return state.events.lookup_zaps(target: target)
} }
func subscribe() { func subscribe() {
@@ -51,7 +53,7 @@ class ZapsModel: ObservableObject {
case .notice: case .notice:
break break
case .eose: 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) load_profiles(profiles_subid: profiles_subid, relay_id: relay_id, load: .from_events(events), damus_state: state)
case .event(_, let ev): case .event(_, let ev):
guard ev.kind == 9735 else { guard ev.kind == 9735 else {
@@ -59,7 +61,7 @@ class ZapsModel: ObservableObject {
} }
if let zap = state.zaps.zaps[ev.id] { 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() objectWillChange.send()
} }
} else { } else {
@@ -71,9 +73,7 @@ class ZapsModel: ObservableObject {
return return
} }
state.zaps.add_zap(zap: zap) if self.state.add_zap(zap: zap) {
if insert_uniq_sorted_zap_by_amount(zaps: &zaps, new_zap: zap) {
objectWillChange.send() objectWillChange.send()
} }
} }

View File

@@ -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 { class EventCache {
private var events: [String: NostrEvent] = [:] private var events: [String: NostrEvent] = [:]
private var replies = ReplyMap() private var replies = ReplyMap()
private var cancellable: AnyCancellable? private var cancellable: AnyCancellable?
private var translations: [String: TranslateStatus] = [:]
private var artifacts: [String: NoteArtifacts] = [:]
// url to meta
private var image_metadata: [String: ImageMetadataState] = [:] private var image_metadata: [String: ImageMetadataState] = [:]
var validation: [String: ValidationResult] = [:] private var event_data: [String: EventData] = [:]
//private var thread_latest: [String: Int64] //private var thread_latest: [String: Int64]
@@ -54,20 +65,40 @@ class EventCache {
} }
} }
func is_event_valid(_ evid: String) -> ValidationResult { private func get_cache_data(_ evid: String) -> EventData {
guard let result = validation[evid] else { guard let data = event_data[evid] else {
return .unknown 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) { 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) { 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) { func store_img_metadata(url: URL, meta: ImageMetadataState) {
@@ -75,7 +106,7 @@ class EventCache {
} }
func lookup_artifacts(evid: String) -> NoteArtifacts? { func lookup_artifacts(evid: String) -> NoteArtifacts? {
return self.artifacts[evid] return get_cache_data(evid).artifacts
} }
func lookup_img_metadata(url: URL) -> ImageMetadataState? { func lookup_img_metadata(url: URL) -> ImageMetadataState? {
@@ -83,7 +114,7 @@ class EventCache {
} }
func lookup_translated_artifacts(evid: String) -> TranslateStatus? { func lookup_translated_artifacts(evid: String) -> TranslateStatus? {
return self.translations[evid] return get_cache_data(evid).translations
} }
func parent_events(event: NostrEvent) -> [NostrEvent] { func parent_events(event: NostrEvent) -> [NostrEvent] {
@@ -149,8 +180,7 @@ class EventCache {
private func prune() { private func prune() {
events = [:] events = [:]
translations = [:] event_data = [:]
artifacts = [:]
replies.replies = [:] replies.replies = [:]
} }
} }

View File

@@ -204,7 +204,7 @@ struct EventGroupView: View {
.frame(width: PFP_SIZE + 10) .frame(width: PFP_SIZE + 10)
VStack(alignment: .leading) { VStack(alignment: .leading) {
ProfilePicturesView(state: state, events: group.events) ProfilePicturesView(state: state, pubkeys: group.events.map { $0.pubkey })
if let event { if let event {
let thread = ThreadModel(event: event, damus_state: state) let thread = ThreadModel(event: event, damus_state: state)

View File

@@ -9,7 +9,7 @@ import SwiftUI
struct ProfilePicturesView: View { struct ProfilePicturesView: View {
let state: DamusState let state: DamusState
let events: [NostrEvent] let pubkeys: [String]
@State var nav_target: String? = nil @State var nav_target: String? = nil
@State var navigating: Bool = false @State var navigating: Bool = false
@@ -19,10 +19,10 @@ struct ProfilePicturesView: View {
EmptyView() EmptyView()
} }
HStack { HStack {
ForEach(events.prefix(8)) { ev in ForEach(pubkeys.prefix(8), id: \.self) { pubkey in
ProfilePicView(pubkey: ev.pubkey, size: 32.0, highlight: .none, profiles: state.profiles, disable_animation: state.settings.disable_animation) ProfilePicView(pubkey: pubkey, size: 32.0, highlight: .none, profiles: state.profiles, disable_animation: state.settings.disable_animation)
.onTapGesture { .onTapGesture {
nav_target = ev.pubkey nav_target = pubkey
navigating = true navigating = true
} }
} }
@@ -32,6 +32,6 @@ struct ProfilePicturesView: View {
struct ProfilePicturesView_Previews: PreviewProvider { struct ProfilePicturesView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
ProfilePicturesView(state: test_damus_state(), events: [test_event, test_event]) ProfilePicturesView(state: test_damus_state(), pubkeys: ["a", "b"])
} }
} }