mute: integrate new MutelistManager
This patch is slightly large (I think still within the guidelines tho) , but also pretty straightforward. I thought for a while about how I could split this up in a straightforward way, and I couldn’t come up with anything without breaking intermediate builds. - Deleted a lot of old/unnecessary code (ie. the Collection extension for MuteItem, since we’re now using the MutelistManager sets) - Changed damus_state.contacts to damus_state.mutelist_manager for all mute list manager work - Updated MutelistView to take advantage of new code (this is probably the largest change in this patch) Lighting-Address: fishcharlie@strike.me Signed-off-by: Charlie Fish <contact@charlie.fish> Reviewed-by: William Casarin <jb55@jb55.com> Link: 20240210163650.42884-4-contact@charlie.fish Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
committed by
William Casarin
parent
a9baef7a21
commit
1d4d2b0204
@@ -13,51 +13,14 @@ class Contacts {
|
||||
private var friend_of_friends: Set<Pubkey> = Set()
|
||||
/// Tracks which friends are friends of a given pubkey.
|
||||
private var pubkey_to_our_friends = [Pubkey : Set<Pubkey>]()
|
||||
private var muted: Set<MuteItem> = Set()
|
||||
|
||||
let our_pubkey: Pubkey
|
||||
var event: NostrEvent?
|
||||
var mutelist: NostrEvent?
|
||||
|
||||
|
||||
init(our_pubkey: Pubkey) {
|
||||
self.our_pubkey = our_pubkey
|
||||
}
|
||||
|
||||
func is_muted(_ item: MuteItem) -> Bool {
|
||||
return muted.contains(item)
|
||||
}
|
||||
|
||||
func set_mutelist(_ ev: NostrEvent) {
|
||||
let oldlist = self.mutelist
|
||||
self.mutelist = ev
|
||||
|
||||
let old: Set<MuteItem> = oldlist?.mute_list ?? Set<MuteItem>()
|
||||
let new: Set<MuteItem> = ev.mute_list ?? Set<MuteItem>()
|
||||
let diff = old.symmetricDifference(new)
|
||||
|
||||
var new_mutes = Set<MuteItem>()
|
||||
var new_unmutes = Set<MuteItem>()
|
||||
|
||||
for d in diff {
|
||||
if new.contains(d) {
|
||||
new_mutes.insert(d)
|
||||
} else {
|
||||
new_unmutes.insert(d)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: set local mutelist here
|
||||
self.muted = ev.mute_list ?? Set<MuteItem>()
|
||||
|
||||
if new_mutes.count > 0 {
|
||||
notify(.new_mutes(new_mutes))
|
||||
}
|
||||
|
||||
if new_unmutes.count > 0 {
|
||||
notify(.new_unmutes(new_unmutes))
|
||||
}
|
||||
}
|
||||
|
||||
func remove_friend(_ pubkey: Pubkey) {
|
||||
friends.remove(pubkey)
|
||||
|
||||
|
||||
@@ -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(contacts: damus_state.contacts, ev: inner_ev)
|
||||
return should_show_event(state: damus_state, ev: inner_ev)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ struct DamusState: HeadlessDamusState {
|
||||
let likes: EventCounter
|
||||
let boosts: EventCounter
|
||||
let contacts: Contacts
|
||||
let mutelist_manager: MutelistManager
|
||||
let profiles: Profiles
|
||||
let dms: DirectMessagesModel
|
||||
let previews: PreviewCache
|
||||
@@ -34,13 +35,14 @@ struct DamusState: HeadlessDamusState {
|
||||
let video: VideoController
|
||||
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, wallet: WalletModel, nav: NavigationCoordinator, music: MusicController?, video: VideoController, ndb: Ndb, purple: DamusPurple? = nil) {
|
||||
|
||||
init(pool: RelayPool, keypair: Keypair, likes: EventCounter, boosts: EventCounter, contacts: Contacts, mutelist_manager: MutelistManager, 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
|
||||
self.boosts = boosts
|
||||
self.contacts = contacts
|
||||
self.mutelist_manager = mutelist_manager
|
||||
self.profiles = profiles
|
||||
self.dms = dms
|
||||
self.previews = previews
|
||||
@@ -107,6 +109,7 @@ struct DamusState: HeadlessDamusState {
|
||||
likes: EventCounter(our_pubkey: empty_pub),
|
||||
boosts: EventCounter(our_pubkey: empty_pub),
|
||||
contacts: Contacts(our_pubkey: empty_pub),
|
||||
mutelist_manager: MutelistManager(),
|
||||
profiles: Profiles(ndb: .empty),
|
||||
dms: DirectMessagesModel(our_pubkey: empty_pub),
|
||||
previews: PreviewCache(),
|
||||
|
||||
@@ -15,6 +15,7 @@ protocol HeadlessDamusState {
|
||||
var ndb: Ndb { get }
|
||||
var settings: UserSettingsStore { get }
|
||||
var contacts: Contacts { get }
|
||||
var mutelist_manager: MutelistManager { get }
|
||||
var keypair: Keypair { get }
|
||||
var profiles: Profiles { get }
|
||||
var zaps: Zaps { get }
|
||||
|
||||
@@ -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(contacts: self.damus_state.contacts, ev: zap.request.ev) else {
|
||||
should_show_event(state: self.damus_state, ev: zap.request.ev) else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -278,11 +278,11 @@ class HomeModel {
|
||||
|
||||
func filter_events() {
|
||||
events.filter { ev in
|
||||
!damus_state.contacts.is_muted(.user(ev.pubkey, nil))
|
||||
!damus_state.mutelist_manager.is_muted(.user(ev.pubkey, nil))
|
||||
}
|
||||
|
||||
self.dms.dms = dms.dms.filter { ev in
|
||||
!damus_state.contacts.is_muted(.user(ev.pubkey, nil))
|
||||
!damus_state.mutelist_manager.is_muted(.user(ev.pubkey, nil))
|
||||
}
|
||||
|
||||
notifications.filter { ev in
|
||||
@@ -290,7 +290,7 @@ class HomeModel {
|
||||
return false
|
||||
}
|
||||
|
||||
let event_muted = damus_state.contacts.mutelist?.mute_list?.event_muted_reason(ev) != nil
|
||||
let event_muted = damus_state.mutelist_manager.is_event_muted(ev)
|
||||
return !event_muted
|
||||
}
|
||||
}
|
||||
@@ -570,13 +570,13 @@ class HomeModel {
|
||||
}
|
||||
|
||||
// we only care about the most recent mutelist
|
||||
if let mutelist = damus_state.contacts.mutelist {
|
||||
if let mutelist = damus_state.mutelist_manager.event {
|
||||
if ev.created_at <= mutelist.created_at {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
damus_state.contacts.set_mutelist(ev)
|
||||
damus_state.mutelist_manager.set_mutelist(ev)
|
||||
|
||||
migrate_old_muted_threads_to_new_mutelist(keypair: damus_state.keypair, damus_state: damus_state)
|
||||
}
|
||||
@@ -588,7 +588,7 @@ class HomeModel {
|
||||
}
|
||||
|
||||
// we only care about the most recent mutelist
|
||||
if let mutelist = damus_state.contacts.mutelist {
|
||||
if let mutelist = damus_state.mutelist_manager.event {
|
||||
if ev.created_at <= mutelist.created_at {
|
||||
return
|
||||
}
|
||||
@@ -598,7 +598,7 @@ class HomeModel {
|
||||
return
|
||||
}
|
||||
|
||||
damus_state.contacts.set_mutelist(ev)
|
||||
damus_state.mutelist_manager.set_mutelist(ev)
|
||||
|
||||
migrate_old_muted_threads_to_new_mutelist(keypair: damus_state.keypair, damus_state: damus_state)
|
||||
}
|
||||
@@ -616,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(contacts: damus_state.contacts, ev: ev) else {
|
||||
should_show_event(state: damus_state, ev: ev) else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -654,7 +654,7 @@ class HomeModel {
|
||||
|
||||
|
||||
func handle_text_event(sub_id: String, _ ev: NostrEvent) {
|
||||
guard should_show_event(contacts: damus_state.contacts, ev: ev) else {
|
||||
guard should_show_event(state: damus_state, ev: ev) else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -683,7 +683,7 @@ class HomeModel {
|
||||
}
|
||||
|
||||
func handle_dm(_ ev: NostrEvent) {
|
||||
guard should_show_event(contacts: damus_state.contacts, ev: ev) else {
|
||||
guard should_show_event(state: damus_state, ev: ev) else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1090,13 +1090,13 @@ 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(
|
||||
contacts: damus_state.contacts,
|
||||
state: damus_state,
|
||||
ev: event
|
||||
)
|
||||
}
|
||||
|
||||
func should_show_event(contacts: Contacts, ev: NostrEvent) -> Bool {
|
||||
let event_muted = contacts.mutelist?.mute_list?.event_muted_reason(ev) != nil
|
||||
func should_show_event(state: DamusState, ev: NostrEvent, keypair: Keypair? = nil) -> Bool {
|
||||
let event_muted = state.mutelist_manager.is_event_muted(ev, keypair: keypair)
|
||||
if event_muted {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -200,64 +200,3 @@ extension MuteItem: TagConvertible {
|
||||
}
|
||||
}
|
||||
|
||||
extension Collection where Element == MuteItem {
|
||||
/// Check if an event is muted given a collection of ``MutedItem``.
|
||||
///
|
||||
/// - Parameter ev: The ``NostrEvent`` that you want to check the muted reason for.
|
||||
/// - Returns: The ``MuteItem`` that matched the event. Or `nil` if the event is not muted.
|
||||
func event_muted_reason(_ ev: NostrEvent) -> MuteItem? {
|
||||
return self.first { muted_item in
|
||||
switch muted_item {
|
||||
case .user(let pubkey, let expiration_date):
|
||||
return pubkey == ev.pubkey && !muted_item.is_expired()
|
||||
case .hashtag(let hashtag, let expiration_date):
|
||||
return ev.referenced_hashtags.contains(hashtag) && !muted_item.is_expired()
|
||||
case .word(let word, let expiration_date):
|
||||
return ev.content.lowercased().contains(word.lowercased()) && !muted_item.is_expired()
|
||||
case .thread(let note_id, let expiration_date):
|
||||
return ev.referenced_ids.contains(note_id) && !muted_item.is_expired()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var users: [Pubkey] {
|
||||
return self.compactMap { muted_item in
|
||||
if case .user(let pubkey, _) = muted_item,
|
||||
!muted_item.is_expired() {
|
||||
return pubkey
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
var hashtags: [Hashtag] {
|
||||
return self.compactMap { muted_item in
|
||||
if case .hashtag(let hashtag, _) = muted_item,
|
||||
!muted_item.is_expired() {
|
||||
return hashtag
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
var words: [String] {
|
||||
return self.compactMap { muted_item in
|
||||
if case .word(let str, _) = muted_item,
|
||||
!muted_item.is_expired() {
|
||||
return str
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
var threads: [NoteId] {
|
||||
return self.compactMap { muted_item in
|
||||
if case .thread(let note_id, _) = muted_item,
|
||||
!muted_item.is_expired() {
|
||||
return note_id
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,9 @@ func migrate_old_muted_threads_to_new_mutelist(keypair: Keypair, damus_state: Da
|
||||
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
|
||||
let previous_mute_list_event = damus_state.mutelist_manager.event
|
||||
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.mutelist_manager.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))
|
||||
|
||||
@@ -37,7 +37,7 @@ func should_display_notification(state: HeadlessDamusState, event ev: NostrEvent
|
||||
}
|
||||
|
||||
// Don't show notifications that match mute list.
|
||||
if state.contacts.mutelist?.mute_list?.event_muted_reason(ev) != nil {
|
||||
if state.mutelist_manager.is_event_muted(ev, keypair: state.keypair) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class SearchHomeModel: ObservableObject {
|
||||
}
|
||||
|
||||
func filter_muted() {
|
||||
events.filter { should_show_event(contacts: damus_state.contacts, ev: $0) }
|
||||
events.filter { should_show_event(state: damus_state, 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(contacts: damus_state.contacts, ev: ev) && !ev.is_reply(damus_state.keypair)
|
||||
if ev.is_textlike && should_show_event(state: damus_state, ev: ev) && !ev.is_reply(damus_state.keypair)
|
||||
{
|
||||
if !damus_state.settings.multiple_events_per_pubkey && seen_pubkey.contains(ev.pubkey) {
|
||||
return
|
||||
|
||||
@@ -28,7 +28,7 @@ class SearchModel: ObservableObject {
|
||||
|
||||
func filter_muted() {
|
||||
self.events.filter {
|
||||
should_show_event(contacts: state.contacts, ev: $0)
|
||||
should_show_event(state: state, ev: $0)
|
||||
}
|
||||
self.objectWillChange.send()
|
||||
}
|
||||
@@ -57,7 +57,7 @@ class SearchModel: ObservableObject {
|
||||
return
|
||||
}
|
||||
|
||||
guard should_show_event(contacts: state.contacts, ev: ev) else {
|
||||
guard should_show_event(state: state, ev: ev) else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user