mute: adding filtering support for MuteItem events

This patch depends on: Receiving New Mute List Type

- Changes NewMutesNotify, NewUnmutesNotify & MuteNotify to use MuteItem instead of Pubkey
- Changes is_muted in Contacts.swift to take in a MuteItem instead of a Pubkey
    - A lot of changes here were just modifying callers of that to accept the new parameter type

Related: https://github.com/damus-io/damus/issues/1718
Related: https://github.com/damus-io/damus/issues/856
Lighting Address: fishcharlie@strike.me

Signed-off-by: Charlie Fish <contact@charlie.fish>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
Charlie Fish
2024-01-17 18:17:40 -07:00
committed by William Casarin
parent 07b3146026
commit 7aaea97de0
11 changed files with 43 additions and 49 deletions

View File

@@ -71,7 +71,7 @@ struct ContentView: View {
@State var active_sheet: Sheets? = nil @State var active_sheet: Sheets? = nil
@State var damus_state: DamusState! @State var damus_state: DamusState!
@SceneStorage("ContentView.selected_timeline") var selected_timeline: Timeline = .home @SceneStorage("ContentView.selected_timeline") var selected_timeline: Timeline = .home
@State var muting: Pubkey? = nil @State var muting: MuteItem? = nil
@State var confirm_mute: Bool = false @State var confirm_mute: Bool = false
@State var hide_bar: Bool = false @State var hide_bar: Bool = false
@State var user_muted_confirm: Bool = false @State var user_muted_confirm: Bool = false
@@ -366,8 +366,8 @@ struct ContentView: View {
.onReceive(handle_notify(.report)) { target in .onReceive(handle_notify(.report)) { target in
self.active_sheet = .report(target) self.active_sheet = .report(target)
} }
.onReceive(handle_notify(.mute)) { pubkey in .onReceive(handle_notify(.mute)) { mute_item in
self.muting = pubkey self.muting = mute_item
self.confirm_mute = true self.confirm_mute = true
} }
.onReceive(handle_notify(.attached_wallet)) { nwc in .onReceive(handle_notify(.attached_wallet)) { nwc in
@@ -526,7 +526,7 @@ struct ContentView: View {
user_muted_confirm = false user_muted_confirm = false
} }
}, message: { }, message: {
if let pubkey = self.muting { if case let .user(pubkey, _) = self.muting {
let profile_txn = damus_state!.profiles.lookup(id: pubkey) let profile_txn = damus_state!.profiles.lookup(id: pubkey)
let profile = profile_txn?.unsafeUnownedValue let profile = profile_txn?.unsafeUnownedValue
let name = Profile.displayName(profile: profile, pubkey: pubkey).username.truncate(maxLength: 50) let name = Profile.displayName(profile: profile, pubkey: pubkey).username.truncate(maxLength: 50)
@@ -544,13 +544,13 @@ struct ContentView: View {
Button(NSLocalizedString("Yes, Overwrite", comment: "Text of button that confirms to overwrite the existing mutelist.")) { Button(NSLocalizedString("Yes, Overwrite", comment: "Text of button that confirms to overwrite the existing mutelist.")) {
guard let ds = damus_state, guard let ds = damus_state,
let keypair = ds.keypair.to_full(), let keypair = ds.keypair.to_full(),
let pubkey = muting, let muting,
let mutelist = create_or_update_mutelist(keypair: keypair, mprev: nil, to_add: .user(pubkey, nil)) let mutelist = create_or_update_mutelist(keypair: keypair, mprev: nil, to_add: muting)
else { else {
return return
} }
damus_state?.contacts.set_mutelist(mutelist) ds.contacts.set_mutelist(mutelist)
ds.postbox.send(mutelist) ds.postbox.send(mutelist)
confirm_overwrite_mutelist = false confirm_overwrite_mutelist = false
@@ -573,21 +573,21 @@ struct ContentView: View {
confirm_overwrite_mutelist = true confirm_overwrite_mutelist = true
} else { } else {
guard let keypair = ds.keypair.to_full(), guard let keypair = ds.keypair.to_full(),
let pubkey = muting let muting
else { else {
return return
} }
guard let ev = create_or_update_mutelist(keypair: keypair, mprev: ds.contacts.mutelist, to_add: .user(pubkey, nil)) else { guard let ev = create_or_update_mutelist(keypair: keypair, mprev: ds.contacts.mutelist, to_add: muting) else {
return return
} }
damus_state?.contacts.set_mutelist(ev) ds.contacts.set_mutelist(ev)
ds.postbox.send(ev) ds.postbox.send(ev)
} }
} }
}, message: { }, message: {
if let pubkey = muting { if case let .user(pubkey, _) = muting {
let profile_txn = damus_state?.profiles.lookup(id: pubkey) let profile_txn = damus_state?.profiles.lookup(id: pubkey)
let profile = profile_txn?.unsafeUnownedValue let profile = profile_txn?.unsafeUnownedValue
let name = Profile.displayName(profile: profile, pubkey: pubkey).username.truncate(maxLength: 50) let name = Profile.displayName(profile: profile, pubkey: pubkey).username.truncate(maxLength: 50)

View File

@@ -13,7 +13,7 @@ class Contacts {
private var friend_of_friends: Set<Pubkey> = Set() private var friend_of_friends: Set<Pubkey> = Set()
/// Tracks which friends are friends of a given pubkey. /// Tracks which friends are friends of a given pubkey.
private var pubkey_to_our_friends = [Pubkey : Set<Pubkey>]() private var pubkey_to_our_friends = [Pubkey : Set<Pubkey>]()
private var muted: Set<Pubkey> = Set() private var muted: Set<MuteItem> = Set()
let our_pubkey: Pubkey let our_pubkey: Pubkey
var event: NostrEvent? var event: NostrEvent?
@@ -23,20 +23,20 @@ class Contacts {
self.our_pubkey = our_pubkey self.our_pubkey = our_pubkey
} }
func is_muted(_ pk: Pubkey) -> Bool { func is_muted(_ item: MuteItem) -> Bool {
return muted.contains(pk) return muted.contains(item)
} }
func set_mutelist(_ ev: NostrEvent) { func set_mutelist(_ ev: NostrEvent) {
let oldlist = self.mutelist let oldlist = self.mutelist
self.mutelist = ev self.mutelist = ev
let old = oldlist.map({ ev in Set(ev.referenced_pubkeys) }) ?? Set<Pubkey>() let old: Set<MuteItem> = oldlist?.mute_list ?? Set<MuteItem>()
let new = Set(ev.referenced_pubkeys) let new: Set<MuteItem> = ev.mute_list ?? Set<MuteItem>()
let diff = old.symmetricDifference(new) let diff = old.symmetricDifference(new)
var new_mutes = Set<Pubkey>() var new_mutes = Set<MuteItem>()
var new_unmutes = Set<Pubkey>() var new_unmutes = Set<MuteItem>()
for d in diff { for d in diff {
if new.contains(d) { if new.contains(d) {
@@ -47,7 +47,7 @@ class Contacts {
} }
// TODO: set local mutelist here // TODO: set local mutelist here
self.muted = Set(ev.referenced_pubkeys) self.muted = ev.mute_list ?? Set<MuteItem>()
if new_mutes.count > 0 { if new_mutes.count > 0 {
notify(.new_mutes(new_mutes)) notify(.new_mutes(new_mutes))

View File

@@ -278,11 +278,11 @@ class HomeModel {
func filter_events() { func filter_events() {
events.filter { ev in events.filter { ev in
!damus_state.contacts.is_muted(ev.pubkey) !damus_state.contacts.is_muted(.user(ev.pubkey, nil))
} }
self.dms.dms = dms.dms.filter { ev in self.dms.dms = dms.dms.filter { ev in
!damus_state.contacts.is_muted(ev.pubkey) !damus_state.contacts.is_muted(.user(ev.pubkey, nil))
} }
notifications.filter { ev in notifications.filter { ev in
@@ -290,7 +290,8 @@ class HomeModel {
return false return false
} }
return !damus_state.contacts.is_muted(ev.pubkey) && !damus_state.muted_threads.isMutedThread(ev, keypair: damus_state.keypair) let event_muted = damus_state.contacts.mutelist?.mute_list?.event_muted_reason(ev) != nil
return !event_muted
} }
} }
@@ -1093,11 +1094,8 @@ func should_show_event(event: NostrEvent, damus_state: DamusState) -> Bool {
} }
func should_show_event(keypair: Keypair, hellthreads: MutedThreadsManager, contacts: Contacts, ev: NostrEvent) -> Bool { func should_show_event(keypair: Keypair, hellthreads: MutedThreadsManager, contacts: Contacts, ev: NostrEvent) -> Bool {
if contacts.is_muted(ev.pubkey) { let event_muted = contacts.mutelist?.mute_list?.event_muted_reason(ev) != nil
return false if event_muted {
}
if hellthreads.isMutedThread(ev, keypair: keypair) {
return false return false
} }

View File

@@ -36,16 +36,11 @@ func should_display_notification(state: HeadlessDamusState, event ev: NostrEvent
return false return false
} }
// Don't show notifications from muted threads. // Don't show notifications that match mute list.
if state.muted_threads.isMutedThread(ev, keypair: state.keypair) { if state.contacts.mutelist?.mute_list?.event_muted_reason(ev) != nil {
return false return false
} }
// Don't show notifications from muted users
if state.contacts.is_muted(ev.pubkey) {
return false
}
// Don't show notifications for old events // Don't show notifications for old events
guard ev.age < EVENT_MAX_AGE_FOR_NOTIFICATION else { guard ev.age < EVENT_MAX_AGE_FOR_NOTIFICATION else {
return false return false

View File

@@ -8,8 +8,8 @@
import Foundation import Foundation
struct MuteNotify: Notify { struct MuteNotify: Notify {
typealias Payload = Pubkey typealias Payload = MuteItem
var payload: Payload var payload: MuteItem
} }
extension NotifyHandler { extension NotifyHandler {
@@ -19,7 +19,7 @@ extension NotifyHandler {
} }
extension Notifications { extension Notifications {
static func mute(_ target: Pubkey) -> Notifications<MuteNotify> { static func mute(_ target: MuteItem) -> Notifications<MuteNotify> {
.init(.init(payload: target)) .init(.init(payload: target))
} }
} }

View File

@@ -8,7 +8,7 @@
import Foundation import Foundation
struct NewMutesNotify: Notify { struct NewMutesNotify: Notify {
typealias Payload = Set<Pubkey> typealias Payload = Set<MuteItem>
var payload: Payload var payload: Payload
} }
@@ -19,7 +19,7 @@ extension NotifyHandler {
} }
extension Notifications { extension Notifications {
static func new_mutes(_ pubkeys: Set<Pubkey>) -> Notifications<NewMutesNotify> { static func new_mutes(_ pubkeys: Set<MuteItem>) -> Notifications<NewMutesNotify> {
.init(.init(payload: pubkeys)) .init(.init(payload: pubkeys))
} }
} }

View File

@@ -8,7 +8,7 @@
import Foundation import Foundation
struct NewUnmutesNotify: Notify { struct NewUnmutesNotify: Notify {
typealias Payload = Set<Pubkey> typealias Payload = Set<MuteItem>
var payload: Payload var payload: Payload
} }
@@ -19,7 +19,7 @@ extension NotifyHandler {
} }
extension Notifications { extension Notifications {
static func new_unmutes(_ pubkeys: Set<Pubkey>) -> Notifications<NewUnmutesNotify> { static func new_unmutes(_ pubkeys: Set<MuteItem>) -> Notifications<NewUnmutesNotify> {
.init(.init(payload: pubkeys)) .init(.init(payload: pubkeys))
} }
} }

View File

@@ -39,7 +39,7 @@ struct DirectMessagesView: View {
func filter_dms(dms: [DirectMessageModel]) -> [DirectMessageModel] { func filter_dms(dms: [DirectMessageModel]) -> [DirectMessageModel] {
return dms.filter({ dm in return dms.filter({ dm in
return damus_state.settings.friend_filter.filter(contacts: damus_state.contacts, pubkey: dm.pubkey) && !damus_state.contacts.is_muted(dm.pubkey) return damus_state.settings.friend_filter.filter(contacts: damus_state.contacts, pubkey: dm.pubkey) && !damus_state.contacts.is_muted(.user(dm.pubkey, nil))
}) })
} }

View File

@@ -142,7 +142,7 @@ struct MenuItems: View {
} }
Button(role: .destructive) { Button(role: .destructive) {
notify(.mute(target_pubkey)) notify(.mute(.user(target_pubkey, nil)))
} label: { } label: {
Label(NSLocalizedString("Mute user", comment: "Context menu option for muting users."), image: "mute") Label(NSLocalizedString("Mute user", comment: "Context menu option for muting users."), image: "mute")
} }

View File

@@ -49,12 +49,13 @@ struct EventMutingContainerView<Content: View>: View {
} }
} }
.onReceive(handle_notify(.new_mutes)) { mutes in .onReceive(handle_notify(.new_mutes)) { mutes in
if mutes.contains(event.pubkey) { let new_muted_event_reason = mutes.event_muted_reason(event)
if new_muted_event_reason != nil {
shown = false shown = false
} }
} }
.onReceive(handle_notify(.new_unmutes)) { unmutes in .onReceive(handle_notify(.new_unmutes)) { unmutes in
if unmutes.contains(event.pubkey) { if unmutes.event_muted_reason(event) != nil {
shown = true shown = true
} }
} }

View File

@@ -179,7 +179,7 @@ struct ProfileView: View {
notify(.report(.user(profile.pubkey))) notify(.report(.user(profile.pubkey)))
} }
if damus_state.contacts.is_muted(profile.pubkey) { if damus_state.contacts.is_muted(.user(profile.pubkey, nil)) {
Button(NSLocalizedString("Unmute", comment: "Button to unmute a profile.")) { Button(NSLocalizedString("Unmute", comment: "Button to unmute a profile.")) {
guard guard
let keypair = damus_state.keypair.to_full(), let keypair = damus_state.keypair.to_full(),
@@ -197,7 +197,7 @@ struct ProfileView: View {
} }
} else { } else {
Button(NSLocalizedString("Mute", comment: "Button to mute a profile."), role: .destructive) { Button(NSLocalizedString("Mute", comment: "Button to mute a profile."), role: .destructive) {
notify(.mute(profile.pubkey)) notify(.mute(.user(profile.pubkey, nil)))
} }
} }
} }