commit d55d0d61ed1cbeb883772d5e49d6db051ecce5b5
parent cf904805017f7a32b2f508e9ca77a1e5a87befa4
Author: William Casarin <jb55@jb55.com>
Date: Wed, 15 Feb 2023 09:35:47 -0800
perf: debounce incoming dms
This fixes perf issues on startup if you have lots of dms
Changelog-Fixed: Fix lag on startup when you have lots of DMs
Changelog-Fixed: Fix an issues where dm notifications appear without any new events
Diffstat:
2 files changed, 61 insertions(+), 13 deletions(-)
diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj
@@ -42,6 +42,7 @@
4C285C8A2838B985008A31F1 /* ProfilePictureSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C285C892838B985008A31F1 /* ProfilePictureSelector.swift */; };
4C285C8C28398BC7008A31F1 /* Keys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C285C8B28398BC6008A31F1 /* Keys.swift */; };
4C285C8E28399BFE008A31F1 /* SaveKeysView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C285C8D28399BFD008A31F1 /* SaveKeysView.swift */; };
+ 4C2CDDF7299D4A5E00879FD5 /* Debouncer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C2CDDF6299D4A5E00879FD5 /* Debouncer.swift */; };
4C363A8428233689006E126D /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A8328233689006E126D /* Parser.swift */; };
4C363A8828236948006E126D /* BlocksView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A8728236948006E126D /* BlocksView.swift */; };
4C363A8A28236B57006E126D /* MentionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363A8928236B57006E126D /* MentionView.swift */; };
@@ -312,6 +313,7 @@
4C285C892838B985008A31F1 /* ProfilePictureSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfilePictureSelector.swift; sourceTree = "<group>"; };
4C285C8B28398BC6008A31F1 /* Keys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keys.swift; sourceTree = "<group>"; };
4C285C8D28399BFD008A31F1 /* SaveKeysView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveKeysView.swift; sourceTree = "<group>"; };
+ 4C2CDDF6299D4A5E00879FD5 /* Debouncer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Debouncer.swift; sourceTree = "<group>"; };
4C363A8328233689006E126D /* Parser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Parser.swift; sourceTree = "<group>"; };
4C363A8728236948006E126D /* BlocksView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlocksView.swift; sourceTree = "<group>"; };
4C363A8928236B57006E126D /* MentionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentionView.swift; sourceTree = "<group>"; };
@@ -780,6 +782,7 @@
4CB883A72975FC1800DC99E7 /* Zaps.swift */,
4CB883B5297730E400DC99E7 /* LNUrls.swift */,
3AB72AB8298ECF30004BB58C /* Translator.swift */,
+ 4C2CDDF6299D4A5E00879FD5 /* Debouncer.swift */,
);
path = Util;
sourceTree = "<group>";
@@ -1342,6 +1345,7 @@
4CE879552996BAB900F758CC /* RelayPaidDetail.swift in Sources */,
4CF0ABD42980996B00D66079 /* Report.swift in Sources */,
4C06670B28FDE64700038D2A /* damus.c in Sources */,
+ 4C2CDDF7299D4A5E00879FD5 /* Debouncer.swift in Sources */,
3AAA95CC298E07E900F3D526 /* DeepLPlan.swift in Sources */,
4FE60CDD295E1C5E00105A1F /* Wallet.swift in Sources */,
3AA247FF297E3D900090C62D /* RepostsView.swift in Sources */,
diff --git a/damus/Models/HomeModel.swift b/damus/Models/HomeModel.swift
@@ -38,6 +38,9 @@ class HomeModel: ObservableObject {
var channels: [String: NostrEvent] = [:]
var last_event_of_kind: [String: [Int: NostrEvent]] = [:]
var done_init: Bool = false
+ var incoming_dms: [NostrEvent] = []
+ let dm_debouncer = Debouncer(interval: 0.5)
+ var should_debounce_dms = true
let home_subid = UUID().description
let contacts_subid = UUID().description
@@ -56,16 +59,25 @@ class HomeModel: ObservableObject {
init() {
self.damus_state = DamusState.empty
self.dms = DirectMessagesModel(our_pubkey: damus_state.pubkey)
+ self.setup_debouncer()
}
init(damus_state: DamusState) {
self.damus_state = damus_state
self.dms = DirectMessagesModel(our_pubkey: damus_state.pubkey)
+ self.setup_debouncer()
}
var pool: RelayPool {
return damus_state.pool
}
+
+ func setup_debouncer() {
+ // turn off debouncer after initial load
+ DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
+ self.should_debounce_dms = false
+ }
+ }
func has_sub_id_event(sub_id: String, ev_id: String) -> Bool {
if !has_event.keys.contains(sub_id) {
@@ -303,7 +315,8 @@ class HomeModel: ObservableObject {
case .eose(let sub_id):
if sub_id == dms_subid {
- let dms = dms.dms.flatMap { $0.1.events }
+ var dms = dms.dms.flatMap { $0.1.events }
+ dms.append(contentsOf: incoming_dms)
load_profiles(profiles_subid: profiles_subid, relay_id: relay_id, events: dms, damus_state: damus_state)
} else if sub_id == notifications_subid {
load_profiles(profiles_subid: profiles_subid, relay_id: relay_id, events: notifications, damus_state: damus_state)
@@ -477,10 +490,28 @@ class HomeModel: ObservableObject {
handle_notification(ev: ev)
}
}
-
+
func handle_dm(_ ev: NostrEvent) {
- if let notifs = handle_incoming_dm(contacts: damus_state.contacts, prev_events: self.new_events, dms: self.dms, our_pubkey: self.damus_state.pubkey, ev: ev) {
- self.new_events = notifs
+ guard should_show_event(contacts: damus_state.contacts, ev: ev) else {
+ return
+ }
+
+ if !should_debounce_dms {
+ self.incoming_dms.append(ev)
+ if let notifs = handle_incoming_dms(contacts: self.damus_state.contacts, prev_events: self.new_events, dms: self.dms, our_pubkey: self.damus_state.pubkey, evs: self.incoming_dms) {
+ self.new_events = notifs
+ }
+ self.incoming_dms = []
+ return
+ }
+
+ incoming_dms.append(ev)
+
+ dm_debouncer.debounce {
+ if let notifs = handle_incoming_dms(contacts: self.damus_state.contacts, prev_events: self.new_events, dms: self.dms, our_pubkey: self.damus_state.pubkey, evs: self.incoming_dms) {
+ self.new_events = notifs
+ }
+ self.incoming_dms = []
}
}
}
@@ -761,14 +792,10 @@ func fetch_relay_metadata(relay_id: String) async throws -> RelayMetadata? {
func process_relay_metadata() {
}
-func handle_incoming_dm(contacts: Contacts, prev_events: NewEventsBits, dms: DirectMessagesModel, our_pubkey: String, ev: NostrEvent) -> NewEventsBits? {
- // hide blocked users
- guard should_show_event(contacts: contacts, ev: ev) else {
- return prev_events
- }
-
+func handle_incoming_dm(ev: NostrEvent, our_pubkey: String, dms: DirectMessagesModel, prev_events: NewEventsBits) -> (Bool, NewEventsBits?) {
var inserted = false
var found = false
+
let ours = ev.pubkey == our_pubkey
var i = 0
@@ -795,15 +822,32 @@ func handle_incoming_dm(contacts: Contacts, prev_events: NewEventsBits, dms: Dir
}
if !found {
- inserted = true
let model = DirectMessageModel(events: [ev], our_pubkey: our_pubkey)
dms.dms.append((the_pk, model))
}
+
+ var new_bits: NewEventsBits? = nil
+ if inserted {
+ new_bits = handle_last_events(new_events: prev_events, ev: ev, timeline: .dms, shouldNotify: !ours)
+ }
+
+ return (inserted, new_bits)
+}
+
+func handle_incoming_dms(contacts: Contacts, prev_events: NewEventsBits, dms: DirectMessagesModel, our_pubkey: String, evs: [NostrEvent]) -> NewEventsBits? {
+ var inserted = false
var new_events: NewEventsBits? = nil
+
+ for ev in evs {
+ let res = handle_incoming_dm(ev: ev, our_pubkey: our_pubkey, dms: dms, prev_events: prev_events)
+ inserted = res.0 || inserted
+ if let new = res.1 {
+ new_events = new
+ }
+ }
+
if inserted {
- new_events = handle_last_events(new_events: prev_events, ev: ev, timeline: .dms, shouldNotify: !ours)
-
dms.dms = dms.dms.filter({ $0.1.events.count > 0 }).sorted { a, b in
return a.1.events.last!.created_at > b.1.events.last!.created_at
}