damus

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

commit b5a3697d78df9fdf9116f6dc22582ab725aeb8ea
parent 247270f3d3efdd3eb4f17da56dcfae60d9b68a93
Author: William Casarin <jb55@jb55.com>
Date:   Sat, 15 Apr 2023 12:41:00 -0700

Refactor direct messages model

We can track the pubkey in the DirectMessageModel instead of having a
janky tuple.

Diffstat:
Mdamus/ContentView.swift | 2+-
Mdamus/Models/DirectMessageModel.swift | 8++++++--
Mdamus/Models/DirectMessagesModel.swift | 41++++++++++++++++++++++++++++++++---------
Mdamus/Models/HomeModel.swift | 18+++++++++---------
Mdamus/Views/DMChatView.swift | 14++++++++------
Mdamus/Views/DirectMessagesView.swift | 28++++++++--------------------
Mdamus/Views/Profile/ProfileView.swift | 3+--
MdamusTests/DMTests.swift | 18+++++++++---------
8 files changed, 74 insertions(+), 58 deletions(-)

diff --git a/damus/ContentView.swift b/damus/ContentView.swift @@ -183,7 +183,7 @@ struct ContentView: View { NotificationsView(state: damus, notifications: home.notifications) case .dms: - DirectMessagesView(damus_state: damus_state!) + DirectMessagesView(damus_state: damus_state!, model: damus_state!.dms) case .none: EmptyView() diff --git a/damus/Models/DirectMessageModel.swift b/damus/Models/DirectMessageModel.swift @@ -16,6 +16,8 @@ class DirectMessageModel: ObservableObject { @Published var draft: String + let pubkey: String + var is_request: Bool var our_pubkey: String @@ -29,17 +31,19 @@ class DirectMessageModel: ObservableObject { return true } - init(events: [NostrEvent], our_pubkey: String) { + init(events: [NostrEvent], our_pubkey: String, pubkey: String) { self.events = events self.is_request = false self.our_pubkey = our_pubkey self.draft = "" + self.pubkey = pubkey } - init(our_pubkey: String) { + init(our_pubkey: String, pubkey: String) { self.events = [] self.is_request = false self.our_pubkey = our_pubkey self.draft = "" + self.pubkey = pubkey } } diff --git a/damus/Models/DirectMessagesModel.swift b/damus/Models/DirectMessagesModel.swift @@ -8,20 +8,43 @@ import Foundation class DirectMessagesModel: ObservableObject { - @Published var dms: [(String, DirectMessageModel)] = [] + @Published var dms: [DirectMessageModel] = [] @Published var loading: Bool = false + @Published var open_dm: Bool = false + @Published private(set) var active_model: DirectMessageModel = DirectMessageModel(our_pubkey: "", pubkey: "") let our_pubkey: String init(our_pubkey: String) { self.our_pubkey = our_pubkey } - var message_requests: [(String, DirectMessageModel)] { - return dms.filter { dm in dm.1.is_request } + var message_requests: [DirectMessageModel] { + return dms.filter { dm in dm.is_request } } - var friend_dms: [(String, DirectMessageModel)] { - return dms.filter { dm in !dm.1.is_request } + var friend_dms: [DirectMessageModel] { + return dms.filter { dm in !dm.is_request } + } + + func set_active_dm_model(_ model: DirectMessageModel) { + self.active_model = model + } + + func open_dm_by_pk(_ pubkey: String) { + self.set_active_dm(pubkey) + self.open_dm = true + } + + func open_dm_by_model(_ model: DirectMessageModel) { + self.set_active_dm_model(model) + self.open_dm = true + } + + func set_active_dm(_ pubkey: String) { + for model in self.dms where model.pubkey == pubkey { + self.set_active_dm_model(model) + break + } } func lookup_or_create(_ pubkey: String) -> DirectMessageModel { @@ -29,15 +52,15 @@ class DirectMessagesModel: ObservableObject { return dm } - let new = DirectMessageModel(our_pubkey: our_pubkey) - dms.append((pubkey, new)) + let new = DirectMessageModel(our_pubkey: our_pubkey, pubkey: pubkey) + dms.append(new) return new } func lookup(_ pubkey: String) -> DirectMessageModel? { for dm in dms { - if pubkey == dm.0 { - return dm.1 + if pubkey == dm.pubkey { + return dm } } diff --git a/damus/Models/HomeModel.swift b/damus/Models/HomeModel.swift @@ -198,7 +198,7 @@ class HomeModel: ObservableObject { func filter_muted() { events.filter { !damus_state.contacts.is_muted($0.pubkey) && !damus_state.muted_threads.isMutedThread($0, privkey: self.damus_state.keypair.privkey) } - self.dms.dms = dms.dms.filter { !damus_state.contacts.is_muted($0.0) } + self.dms.dms = dms.dms.filter { !damus_state.contacts.is_muted($0.pubkey) } notifications.filter_and_build_notifications(damus_state) } @@ -316,7 +316,7 @@ class HomeModel: ObservableObject { case .eose(let sub_id): if sub_id == dms_subid { - var dms = dms.dms.flatMap { $0.1.events } + var dms = dms.dms.flatMap { $0.events } dms.append(contentsOf: incoming_dms) load_profiles(profiles_subid: profiles_subid, relay_id: relay_id, load: .from_events(dms), damus_state: damus_state) } else if sub_id == notifications_subid { @@ -851,10 +851,10 @@ func handle_incoming_dm(ev: NostrEvent, our_pubkey: String, dms: DirectMessagesM } } - for (pk, _) in dms.dms { - if pk == the_pk { + for model in dms.dms { + if model.pubkey == the_pk { found = true - inserted = insert_uniq_sorted_event(events: &(dms.dms[i].1.events), new_ev: ev) { + inserted = insert_uniq_sorted_event(events: &(dms.dms[i].events), new_ev: ev) { $0.created_at < $1.created_at } @@ -864,8 +864,8 @@ func handle_incoming_dm(ev: NostrEvent, our_pubkey: String, dms: DirectMessagesM } if !found { - let model = DirectMessageModel(events: [ev], our_pubkey: our_pubkey) - dms.dms.append((the_pk, model)) + let model = DirectMessageModel(events: [ev], our_pubkey: our_pubkey, pubkey: the_pk) + dms.dms.append(model) inserted = true } @@ -892,8 +892,8 @@ func handle_incoming_dms(prev_events: NewEventsBits, dms: DirectMessagesModel, o } if inserted { - 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 + dms.dms = dms.dms.filter({ $0.events.count > 0 }).sorted { a, b in + return a.events.last!.created_at > b.events.last!.created_at } } diff --git a/damus/Views/DMChatView.swift b/damus/Views/DMChatView.swift @@ -9,10 +9,13 @@ import SwiftUI struct DMChatView: View { let damus_state: DamusState - let pubkey: String - @EnvironmentObject var dms: DirectMessageModel + @ObservedObject var dms: DirectMessageModel @State var showPrivateKeyWarning: Bool = false - + + var pubkey: String { + dms.pubkey + } + var Messages: some View { ScrollViewReader { scroller in ScrollView { @@ -177,10 +180,9 @@ struct DMChatView_Previews: PreviewProvider { static var previews: some View { let ev = NostrEvent(content: "hi", pubkey: "pubkey", kind: 1, tags: []) - let model = DirectMessageModel(events: [ev], our_pubkey: "pubkey") + let model = DirectMessageModel(events: [ev], our_pubkey: "pubkey", pubkey: "the_pk") - DMChatView(damus_state: test_damus_state(), pubkey: "pubkey") - .environmentObject(model) + DMChatView(damus_state: test_damus_state(), dms: model) } } diff --git a/damus/Views/DirectMessagesView.swift b/damus/Views/DirectMessagesView.swift @@ -16,22 +16,12 @@ struct DirectMessagesView: View { let damus_state: DamusState @State var dm_type: DMType = .friend - @State var open_dm: Bool = false - @State var pubkey: String @ObservedObject var model: DirectMessagesModel - @State var active_model: DirectMessageModel = DirectMessageModel(our_pubkey: "") - - init(damus_state: DamusState) { - self.damus_state = damus_state - self._model = ObservedObject(initialValue: damus_state.dms) - self.pubkey = damus_state.pubkey - } func MainContent(requests: Bool) -> some View { ScrollView { - let chat = DMChatView(damus_state: damus_state, pubkey: pubkey) - .environmentObject(active_model) - NavigationLink(destination: chat, isActive: $open_dm) { + let chat = DMChatView(damus_state: damus_state, dms: model.active_model) + NavigationLink(destination: chat, isActive: $model.open_dm) { EmptyView() } LazyVStack(spacing: 0) { @@ -39,7 +29,7 @@ struct DirectMessagesView: View { EmptyTimelineView() } else { let dms = requests ? model.message_requests : model.friend_dms - ForEach(dms, id: \.0) { tup in + ForEach(dms, id: \.pubkey) { tup in MaybeEvent(tup) .padding(.top, 10) @@ -60,14 +50,12 @@ struct DirectMessagesView: View { return [.truncate_content, .no_action_bar, .no_translate] } - func MaybeEvent(_ tup: (String, DirectMessageModel)) -> some View { + func MaybeEvent(_ model: DirectMessageModel) -> some View { Group { - if let ev = tup.1.events.last { - EventView(damus: damus_state, event: ev, pubkey: tup.0, options: options) + if let ev = model.events.last { + EventView(damus: damus_state, event: ev, pubkey: model.pubkey, options: options) .onTapGesture { - pubkey = tup.0 - active_model = tup.1 - open_dm = true + self.model.open_dm_by_model(model) } } else { EmptyView() @@ -107,6 +95,6 @@ struct DirectMessagesView_Previews: PreviewProvider { kind: 4, tags: []) let ds = test_damus_state() - DirectMessagesView(damus_state: ds) + DirectMessagesView(damus_state: ds, model: ds.dms) } } diff --git a/damus/Views/Profile/ProfileView.swift b/damus/Views/Profile/ProfileView.swift @@ -271,8 +271,7 @@ struct ProfileView: View { var dmButton: some View { let dm_model = damus_state.dms.lookup_or_create(profile.pubkey) - let dmview = DMChatView(damus_state: damus_state, pubkey: profile.pubkey) - .environmentObject(dm_model) + let dmview = DMChatView(damus_state: damus_state, dms: dm_model) return NavigationLink(destination: dmview) { Image(systemName: "bubble.left.circle") .profile_button_style(scheme: colorScheme) diff --git a/damusTests/DMTests.swift b/damusTests/DMTests.swift @@ -51,55 +51,55 @@ final class DMTests: XCTestCase { handle_incoming_dms(prev_events: notif, dms: model, our_pubkey: alice.pubkey, evs: [alice_to_bob]) XCTAssertEqual(model.dms.count, 1) - XCTAssertEqual(model.dms[0].0, bob.pubkey) + XCTAssertEqual(model.dms[0].pubkey, bob.pubkey) let bob_to_alice = create_dm("hi alice", to_pk: alice.pubkey, tags: [["p", alice.pubkey]], keypair: bob, created_at: now + 1)! handle_incoming_dms(prev_events: notif, dms: model, our_pubkey: alice.pubkey, evs: [bob_to_alice]) XCTAssertEqual(model.dms.count, 1) - XCTAssertEqual(model.dms[0].0, bob.pubkey) + XCTAssertEqual(model.dms[0].pubkey, bob.pubkey) let alice_to_bob_2 = create_dm("hi bob", to_pk: bob.pubkey, tags: [["p", bob.pubkey]], keypair: alice, created_at: now + 2)! handle_incoming_dms(prev_events: notif, dms: model, our_pubkey: alice.pubkey, evs: [alice_to_bob_2]) XCTAssertEqual(model.dms.count, 1) - XCTAssertEqual(model.dms[0].0, bob.pubkey) + XCTAssertEqual(model.dms[0].pubkey, bob.pubkey) let fiatjaf_to_alice = create_dm("hi alice", to_pk: alice.pubkey, tags: [["p", alice.pubkey]], keypair: fiatjaf, created_at: now+5)! handle_incoming_dms(prev_events: notif, dms: model, our_pubkey: alice.pubkey, evs: [fiatjaf_to_alice]) XCTAssertEqual(model.dms.count, 2) - XCTAssertEqual(model.dms[0].0, fiatjaf.pubkey) + XCTAssertEqual(model.dms[0].pubkey, fiatjaf.pubkey) let dave_to_alice = create_dm("hi alice", to_pk: alice.pubkey, tags: [["p", alice.pubkey]], keypair: dave, created_at: now + 10)! handle_incoming_dms(prev_events: notif, dms: model, our_pubkey: alice.pubkey, evs: [dave_to_alice]) XCTAssertEqual(model.dms.count, 3) - XCTAssertEqual(model.dms[0].0, dave.pubkey) + XCTAssertEqual(model.dms[0].pubkey, dave.pubkey) let bob_to_alice_2 = create_dm("hi alice 2", to_pk: alice.pubkey, tags: [["p", alice.pubkey]], keypair: bob, created_at: now + 15)! handle_incoming_dms(prev_events: notif, dms: model, our_pubkey: alice.pubkey, evs: [bob_to_alice_2]) XCTAssertEqual(model.dms.count, 3) - XCTAssertEqual(model.dms[0].0, bob.pubkey) + XCTAssertEqual(model.dms[0].pubkey, bob.pubkey) let charlie_to_alice = create_dm("hi alice", to_pk: alice.pubkey, tags: [["p", alice.pubkey]], keypair: charlie, created_at: now + 20)! handle_incoming_dms(prev_events: notif, dms: model, our_pubkey: alice.pubkey, evs: [charlie_to_alice]) XCTAssertEqual(model.dms.count, 4) - XCTAssertEqual(model.dms[0].0, charlie.pubkey) + XCTAssertEqual(model.dms[0].pubkey, charlie.pubkey) let bob_to_alice_3 = create_dm("hi alice 3", to_pk: alice.pubkey, tags: [["p", alice.pubkey]], keypair: bob, created_at: now + 25)! handle_incoming_dms(prev_events: notif, dms: model, our_pubkey: alice.pubkey, evs: [bob_to_alice_3]) XCTAssertEqual(model.dms.count, 4) - XCTAssertEqual(model.dms[0].0, bob.pubkey) + XCTAssertEqual(model.dms[0].pubkey, bob.pubkey) let charlie_to_alice_2 = create_dm("hi alice 2", to_pk: alice.pubkey, tags: [["p", alice.pubkey]], keypair: charlie, created_at: now + 30)! handle_incoming_dms(prev_events: notif, dms: model, our_pubkey: alice.pubkey, evs: [charlie_to_alice_2]) XCTAssertEqual(model.dms.count, 4) - XCTAssertEqual(model.dms[0].0, charlie.pubkey) + XCTAssertEqual(model.dms[0].pubkey, charlie.pubkey) } }