diff --git a/DamusNotificationService/NotificationExtensionState.swift b/DamusNotificationService/NotificationExtensionState.swift index d6db01b4..69acc020 100644 --- a/DamusNotificationService/NotificationExtensionState.swift +++ b/DamusNotificationService/NotificationExtensionState.swift @@ -11,7 +11,6 @@ struct NotificationExtensionState: HeadlessDamusState { let ndb: Ndb let settings: UserSettingsStore let contacts: Contacts - let muted_threads: MutedThreadsManager let keypair: Keypair let profiles: Profiles let zaps: Zaps @@ -28,7 +27,6 @@ struct NotificationExtensionState: HeadlessDamusState { self.settings = UserSettingsStore() self.contacts = Contacts(our_pubkey: keypair.pubkey) - self.muted_threads = MutedThreadsManager(keypair: keypair) self.keypair = keypair self.profiles = Profiles(ndb: ndb) self.zaps = Zaps(our_pubkey: keypair.pubkey) diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj index 4ff64b37..1539e9af 100644 --- a/damus.xcodeproj/project.pbxproj +++ b/damus.xcodeproj/project.pbxproj @@ -508,7 +508,6 @@ D7CB5D402B116E8A00AD4105 /* UserSettingsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA693073295D649800ADDB87 /* UserSettingsStore.swift */; }; D7CB5D412B116F0900AD4105 /* StringCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA5588229F33F5B00DC6A45 /* StringCodable.swift */; }; D7CB5D422B116F8900AD4105 /* Contacts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3AC79A28306D7B00E1F516 /* Contacts.swift */; }; - D7CB5D432B116F9B00AD4105 /* MutedThreadsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A48E7AF29DFBE9D006E787E /* MutedThreadsManager.swift */; }; D7CB5D452B116FE800AD4105 /* Contacts+.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7CB5D442B116FE800AD4105 /* Contacts+.swift */; }; D7CB5D462B11703D00AD4105 /* Notify.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA3529F2A76AE80003BB08B /* Notify.swift */; }; D7CB5D472B11718700AD4105 /* Wallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE60CDC295E1C5E00105A1F /* Wallet.swift */; }; @@ -3522,7 +3521,6 @@ D7CCFC0F2B0587F600323D86 /* Keys.swift in Sources */, D7CB5D542B1174F700AD4105 /* NIP05.swift in Sources */, D798D2232B0859B700234419 /* KeychainStorage.swift in Sources */, - D7CB5D432B116F9B00AD4105 /* MutedThreadsManager.swift in Sources */, D74AAFC32B153395006CF0F4 /* HeadlessDamusState.swift in Sources */, D7CE1B272B0BE224002EDAD4 /* bech32_util.c in Sources */, D7CCFC102B05880F00323D86 /* Id.swift in Sources */, diff --git a/damus/ContentView.swift b/damus/ContentView.swift index 92e08482..b7625afa 100644 --- a/damus/ContentView.swift +++ b/damus/ContentView.swift @@ -674,7 +674,6 @@ struct ContentView: View { postbox: PostBox(pool: pool), bootstrap_relays: bootstrap_relays, replies: ReplyCounter(our_pubkey: pubkey), - muted_threads: MutedThreadsManager(keypair: keypair), wallet: WalletModel(settings: settings), nav: self.navigationCoordinator, music: MusicController(onChange: music_changed), diff --git a/damus/Models/ContentFilters.swift b/damus/Models/ContentFilters.swift index da3c6ba5..c876f3b6 100644 --- a/damus/Models/ContentFilters.swift +++ b/damus/Models/ContentFilters.swift @@ -33,7 +33,7 @@ func get_repost_of_muted_user_filter(damus_state: DamusState) -> ((_ ev: NostrEv guard ev.known_kind == .boost else { return true } // This needs to use cached because it can be way too slow otherwise guard let inner_ev = ev.get_cached_inner_event(cache: damus_state.events) else { return true } - return should_show_event(keypair: damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: inner_ev) + return should_show_event(contacts: damus_state.contacts, ev: inner_ev) } } diff --git a/damus/Models/DamusState.swift b/damus/Models/DamusState.swift index 3e5b4120..0b35abbf 100644 --- a/damus/Models/DamusState.swift +++ b/damus/Models/DamusState.swift @@ -28,7 +28,6 @@ struct DamusState: HeadlessDamusState { let postbox: PostBox let bootstrap_relays: [String] let replies: ReplyCounter - let muted_threads: MutedThreadsManager let wallet: WalletModel let nav: NavigationCoordinator let music: MusicController? @@ -36,7 +35,7 @@ struct DamusState: HeadlessDamusState { let ndb: Ndb var purple: DamusPurple - init(pool: RelayPool, keypair: Keypair, likes: EventCounter, boosts: EventCounter, contacts: Contacts, profiles: Profiles, dms: DirectMessagesModel, previews: PreviewCache, zaps: Zaps, lnurls: LNUrls, settings: UserSettingsStore, relay_filters: RelayFilters, relay_model_cache: RelayModelCache, drafts: Drafts, events: EventCache, bookmarks: BookmarksManager, postbox: PostBox, bootstrap_relays: [String], replies: ReplyCounter, muted_threads: MutedThreadsManager, wallet: WalletModel, nav: NavigationCoordinator, music: MusicController?, video: VideoController, ndb: Ndb, purple: DamusPurple? = nil) { + init(pool: RelayPool, keypair: Keypair, likes: EventCounter, boosts: EventCounter, contacts: Contacts, profiles: Profiles, dms: DirectMessagesModel, previews: PreviewCache, zaps: Zaps, lnurls: LNUrls, settings: UserSettingsStore, relay_filters: RelayFilters, relay_model_cache: RelayModelCache, drafts: Drafts, events: EventCache, bookmarks: BookmarksManager, postbox: PostBox, bootstrap_relays: [String], replies: ReplyCounter, wallet: WalletModel, nav: NavigationCoordinator, music: MusicController?, video: VideoController, ndb: Ndb, purple: DamusPurple? = nil) { self.pool = pool self.keypair = keypair self.likes = likes @@ -56,7 +55,6 @@ struct DamusState: HeadlessDamusState { self.postbox = postbox self.bootstrap_relays = bootstrap_relays self.replies = replies - self.muted_threads = muted_threads self.wallet = wallet self.nav = nav self.music = music @@ -123,7 +121,6 @@ struct DamusState: HeadlessDamusState { postbox: PostBox(pool: RelayPool(ndb: .empty)), bootstrap_relays: [], replies: ReplyCounter(our_pubkey: empty_pub), - muted_threads: MutedThreadsManager(keypair: kp), wallet: WalletModel(settings: UserSettingsStore()), nav: NavigationCoordinator(), music: nil, diff --git a/damus/Models/HeadlessDamusState.swift b/damus/Models/HeadlessDamusState.swift index 15f785f0..dcb9d032 100644 --- a/damus/Models/HeadlessDamusState.swift +++ b/damus/Models/HeadlessDamusState.swift @@ -15,7 +15,6 @@ protocol HeadlessDamusState { var ndb: Ndb { get } var settings: UserSettingsStore { get } var contacts: Contacts { get } - var muted_threads: MutedThreadsManager { get } var keypair: Keypair { get } var profiles: Profiles { get } var zaps: Zaps { get } diff --git a/damus/Models/HomeModel.swift b/damus/Models/HomeModel.swift index e44fb66c..9ea9833d 100644 --- a/damus/Models/HomeModel.swift +++ b/damus/Models/HomeModel.swift @@ -244,7 +244,7 @@ class HomeModel { process_zap_event(state: damus_state, ev: ev) { zapres in guard case .done(let zap) = zapres, zap.target.pubkey == self.damus_state.keypair.pubkey, - should_show_event(keypair: self.damus_state.keypair, hellthreads: self.damus_state.muted_threads, contacts: self.damus_state.contacts, ev: zap.request.ev) else { + should_show_event(contacts: self.damus_state.contacts, ev: zap.request.ev) else { return } @@ -577,6 +577,8 @@ class HomeModel { } damus_state.contacts.set_mutelist(ev) + + migrate_old_muted_threads_to_new_mutelist(keypair: damus_state.keypair, damus_state: damus_state) } func handle_old_list_event(_ ev: NostrEvent) { @@ -597,6 +599,8 @@ class HomeModel { } damus_state.contacts.set_mutelist(ev) + + migrate_old_muted_threads_to_new_mutelist(keypair: damus_state.keypair, damus_state: damus_state) } func get_last_event_of_kind(relay_id: String, kind: UInt32) -> NostrEvent? { @@ -612,7 +616,7 @@ class HomeModel { // don't show notifications from ourselves guard ev.pubkey != damus_state.pubkey, event_has_our_pubkey(ev, our_pubkey: self.damus_state.pubkey), - should_show_event(keypair: self.damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: ev) else { + should_show_event(contacts: damus_state.contacts, ev: ev) else { return } @@ -650,7 +654,7 @@ class HomeModel { func handle_text_event(sub_id: String, _ ev: NostrEvent) { - guard should_show_event(keypair: damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: ev) else { + guard should_show_event(contacts: damus_state.contacts, ev: ev) else { return } @@ -679,7 +683,7 @@ class HomeModel { } func handle_dm(_ ev: NostrEvent) { - guard should_show_event(keypair: damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: ev) else { + guard should_show_event(contacts: damus_state.contacts, ev: ev) else { return } @@ -1086,14 +1090,12 @@ func event_has_our_pubkey(_ ev: NostrEvent, our_pubkey: Pubkey) -> Bool { func should_show_event(event: NostrEvent, damus_state: DamusState) -> Bool { return should_show_event( - keypair: damus_state.keypair, - hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: event ) } -func should_show_event(keypair: Keypair, hellthreads: MutedThreadsManager, contacts: Contacts, ev: NostrEvent) -> Bool { +func should_show_event(contacts: Contacts, ev: NostrEvent) -> Bool { let event_muted = contacts.mutelist?.mute_list?.event_muted_reason(ev) != nil if event_muted { return false diff --git a/damus/Models/MutedThreadsManager.swift b/damus/Models/MutedThreadsManager.swift index 80903e4a..20c1903f 100644 --- a/damus/Models/MutedThreadsManager.swift +++ b/damus/Models/MutedThreadsManager.swift @@ -11,7 +11,7 @@ fileprivate func getMutedThreadsKey(pubkey: Pubkey) -> String { pk_setting_key(pubkey, key: "muted_threads") } -func loadMutedThreads(pubkey: Pubkey) -> [NoteId] { +func loadOldMutedThreads(pubkey: Pubkey) -> [NoteId] { let key = getMutedThreadsKey(pubkey: pubkey) let xs = UserDefaults.standard.stringArray(forKey: key) ?? [] return xs.reduce(into: [NoteId]()) { ids, k in @@ -20,56 +20,20 @@ func loadMutedThreads(pubkey: Pubkey) -> [NoteId] { } } -func saveMutedThreads(pubkey: Pubkey, currentValue: [NoteId], value: [NoteId]) -> Bool { - let uniqueMutedThreads = Array(Set(value)) - - if uniqueMutedThreads != currentValue { - let ids = uniqueMutedThreads.map { note_id in return note_id.hex() } - UserDefaults.standard.set(ids, forKey: getMutedThreadsKey(pubkey: pubkey)) - return true - } - - return false -} - -class MutedThreadsManager: ObservableObject { - - private let keypair: Keypair - - private var _mutedThreadsSet: Set - private var _mutedThreads: [NoteId] - var mutedThreads: [NoteId] { - get { - return _mutedThreads - } - set { - if saveMutedThreads(pubkey: keypair.pubkey, currentValue: _mutedThreads, value: newValue) { - self._mutedThreads = newValue - self.objectWillChange.send() - } - } - } - - init(keypair: Keypair) { - self._mutedThreads = loadMutedThreads(pubkey: keypair.pubkey) - self._mutedThreadsSet = Set(_mutedThreads) - self.keypair = keypair - } - - func isMutedThread(_ ev: NostrEvent, keypair: Keypair) -> Bool { - return _mutedThreadsSet.contains(ev.thread_id(keypair: keypair)) - } - - func updateMutedThread(_ ev: NostrEvent) { - let threadId = ev.thread_id(keypair: keypair) - if isMutedThread(ev, keypair: keypair) { - mutedThreads = mutedThreads.filter { $0 != threadId } - _mutedThreadsSet.remove(threadId) - notify(.unmute_thread(ev)) - } else { - mutedThreads.append(threadId) - _mutedThreadsSet.insert(threadId) - notify(.mute_thread(ev)) - } - } +// We need to still use it since existing users might have their muted threads stored in UserDefaults +// So now all it's doing is moving a users muted threads to the new kind:10000 system +// It should not be used for any purpose beyond that +func migrate_old_muted_threads_to_new_mutelist(keypair: Keypair, damus_state: DamusState) { + // Ensure that keypair is fullkeypair + guard let fullKeypair = keypair.to_full() else { return } + // Load existing muted threads + let mutedThreads = loadOldMutedThreads(pubkey: fullKeypair.pubkey) + guard !mutedThreads.isEmpty else { return } + // Set new muted system for those existing threads + let previous_mute_list_event = damus_state.contacts.mutelist + guard let new_mutelist_event = create_or_update_mutelist(keypair: fullKeypair, mprev: previous_mute_list_event, to_add: Set(mutedThreads.map { MuteItem.thread($0, nil) })) else { return } + damus_state.contacts.set_mutelist(new_mutelist_event) + damus_state.postbox.send(new_mutelist_event) + // Set existing muted threads to an empty array + UserDefaults.standard.set([], forKey: getMutedThreadsKey(pubkey: keypair.pubkey)) } diff --git a/damus/Models/SearchHomeModel.swift b/damus/Models/SearchHomeModel.swift index 84ae5911..63bcc810 100644 --- a/damus/Models/SearchHomeModel.swift +++ b/damus/Models/SearchHomeModel.swift @@ -35,7 +35,7 @@ class SearchHomeModel: ObservableObject { } func filter_muted() { - events.filter { should_show_event(keypair: damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: $0) } + events.filter { should_show_event(contacts: damus_state.contacts, ev: $0) } self.objectWillChange.send() } @@ -60,7 +60,7 @@ class SearchHomeModel: ObservableObject { guard sub_id == self.base_subid || sub_id == self.profiles_subid else { return } - 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 ev.is_textlike && should_show_event(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) { return diff --git a/damus/Models/SearchModel.swift b/damus/Models/SearchModel.swift index b61231af..1d107fc3 100644 --- a/damus/Models/SearchModel.swift +++ b/damus/Models/SearchModel.swift @@ -28,7 +28,7 @@ class SearchModel: ObservableObject { func filter_muted() { self.events.filter { - should_show_event(keypair: state.keypair, hellthreads: state.muted_threads, contacts: state.contacts, ev: $0) + should_show_event(contacts: state.contacts, ev: $0) } self.objectWillChange.send() } @@ -57,7 +57,7 @@ class SearchModel: ObservableObject { return } - guard should_show_event(keypair: state.keypair, hellthreads: state.muted_threads, contacts: state.contacts, ev: ev) else { + guard should_show_event(contacts: state.contacts, ev: ev) else { return } diff --git a/damus/TestData.swift b/damus/TestData.swift index 5b0a3b48..f9515bb5 100644 --- a/damus/TestData.swift +++ b/damus/TestData.swift @@ -87,7 +87,6 @@ var test_damus_state: DamusState = ({ postbox: .init(pool: pool), bootstrap_relays: .init(), replies: .init(our_pubkey: our_pubkey), - muted_threads: .init(keypair: test_keypair), wallet: .init(settings: settings), nav: .init(), music: .init(onChange: {_ in }), diff --git a/damus/Views/Events/EventMutingContainerView.swift b/damus/Views/Events/EventMutingContainerView.swift index 83b7f6b0..c030be24 100644 --- a/damus/Views/Events/EventMutingContainerView.swift +++ b/damus/Views/Events/EventMutingContainerView.swift @@ -27,7 +27,7 @@ struct EventMutingContainerView: View { self.damus_state = damus_state self.event = event self.content = content() - self._shown = State(initialValue: should_show_event(keypair: damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: event)) + self._shown = State(initialValue: should_show_event(contacts: damus_state.contacts, ev: event)) } init(damus_state: DamusState, event: NostrEvent, muteBox: @escaping MuteBoxViewClosure, @ViewBuilder content: () -> Content) { @@ -36,7 +36,7 @@ struct EventMutingContainerView: View { } var should_mute: Bool { - return !should_show_event(keypair: damus_state.keypair, hellthreads: damus_state.muted_threads, contacts: damus_state.contacts, ev: event) + return !should_show_event(contacts: damus_state.contacts, ev: event) } var body: some View { diff --git a/damus/Views/SearchHomeView.swift b/damus/Views/SearchHomeView.swift index 00ae46ea..91a15e2d 100644 --- a/damus/Views/SearchHomeView.swift +++ b/damus/Views/SearchHomeView.swift @@ -59,7 +59,8 @@ struct SearchHomeView: View { return false } - if damus_state.muted_threads.isMutedThread(ev, keypair: self.damus_state.keypair) { + let event_muted = damus_state.contacts.mutelist?.mute_list?.event_muted_reason(ev) != nil + if event_muted { return false } diff --git a/damusTests/LongPostTests.swift b/damusTests/LongPostTests.swift index f4888c9f..70637607 100644 --- a/damusTests/LongPostTests.swift +++ b/damusTests/LongPostTests.swift @@ -34,7 +34,7 @@ final class LongPostTests: XCTestCase { XCTAssertEqual(subid, "subid") XCTAssertTrue(ev.should_show_event) XCTAssertTrue(!ev.too_big) - XCTAssertTrue(should_show_event(keypair: test_keypair, hellthreads: test_damus_state.muted_threads, contacts: contacts, ev: ev)) + XCTAssertTrue(should_show_event(contacts: contacts, ev: ev)) XCTAssertTrue(validate_event(ev: ev) == .ok ) } diff --git a/damusTests/Mocking/MockDamusState.swift b/damusTests/Mocking/MockDamusState.swift index ebdd587e..037c68db 100644 --- a/damusTests/Mocking/MockDamusState.swift +++ b/damusTests/Mocking/MockDamusState.swift @@ -44,7 +44,6 @@ func generate_test_damus_state( postbox: .init(pool: pool), bootstrap_relays: .init(), replies: .init(our_pubkey: our_pubkey), - muted_threads: .init(keypair: test_keypair), wallet: .init(settings: settings), nav: .init(), music: .init(onChange: {_ in }),