home: hide users and hashtags from home timeline when you unfollow
Add the ability to resubscribe to home filters so that it will be updated when you follow and unfollow people Changelog-Fixed: Hide users and hashtags from home timeline when you unfollow
This commit is contained in:
@@ -396,11 +396,21 @@ struct ContentView: View {
|
||||
}
|
||||
.onReceive(handle_notify(.unfollow)) { notif in
|
||||
guard let state = self.damus_state else { return }
|
||||
handle_unfollow_notif(state: state, notif: notif)
|
||||
guard let unfollow = handle_unfollow_notif(state: state, notif: notif) else { return }
|
||||
}
|
||||
.onReceive(handle_notify(.unfollowed)) { notif in
|
||||
guard let state = self.damus_state else { return }
|
||||
let unfollow = notif.object as! ReferencedId
|
||||
home.resubscribe(.unfollowing(unfollow))
|
||||
}
|
||||
.onReceive(handle_notify(.follow)) { notif in
|
||||
guard let state = self.damus_state else { return }
|
||||
handle_follow_notif(state: state, notif: notif)
|
||||
guard handle_follow_notif(state: state, notif: notif) else { return }
|
||||
}
|
||||
.onReceive(handle_notify(.followed)) { notif in
|
||||
guard let state = self.damus_state else { return }
|
||||
let follow = notif.object as! ReferencedId
|
||||
home.resubscribe(.following)
|
||||
}
|
||||
.onReceive(handle_notify(.post)) { notif in
|
||||
guard let state = self.damus_state,
|
||||
@@ -875,16 +885,17 @@ func timeline_name(_ timeline: Timeline?) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
func handle_unfollow(state: DamusState, unfollow: ReferencedId) {
|
||||
@discardableResult
|
||||
func handle_unfollow(state: DamusState, unfollow: ReferencedId) -> Bool {
|
||||
guard let keypair = state.keypair.to_full() else {
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
let old_contacts = state.contacts.event
|
||||
|
||||
guard let ev = unfollow_reference(postbox: state.postbox, our_contacts: old_contacts, keypair: keypair, unfollow: unfollow)
|
||||
else {
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
notify(.unfollowed, unfollow)
|
||||
@@ -895,13 +906,20 @@ func handle_unfollow(state: DamusState, unfollow: ReferencedId) {
|
||||
state.contacts.remove_friend(unfollow.ref_id)
|
||||
state.user_search_cache.updateOwnContactsPetnames(id: state.pubkey, oldEvent: old_contacts, newEvent: ev)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func handle_unfollow_notif(state: DamusState, notif: Notification) {
|
||||
func handle_unfollow_notif(state: DamusState, notif: Notification) -> ReferencedId? {
|
||||
let target = notif.object as! FollowTarget
|
||||
let pk = target.pubkey
|
||||
|
||||
handle_unfollow(state: state, unfollow: .p(pk))
|
||||
let ref = ReferencedId.p(pk)
|
||||
if handle_unfollow(state: state, unfollow: ref) {
|
||||
return ref
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
|
||||
@@ -23,6 +23,40 @@ struct NewEventsBits: OptionSet {
|
||||
static let notifications: NewEventsBits = [.zaps, .likes, .reposts, .mentions]
|
||||
}
|
||||
|
||||
enum Resubscribe {
|
||||
case following
|
||||
case unfollowing(ReferencedId)
|
||||
}
|
||||
|
||||
enum HomeResubFilter {
|
||||
case pubkey(String)
|
||||
case hashtag(String)
|
||||
|
||||
init?(from: ReferencedId) {
|
||||
if from.key == "p" {
|
||||
self = .pubkey(from.ref_id)
|
||||
return
|
||||
} else if from.key == "t" {
|
||||
self = .hashtag(from.ref_id)
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func filter(contacts: Contacts, ev: NostrEvent) -> Bool {
|
||||
switch self {
|
||||
case .pubkey(let pk):
|
||||
return ev.pubkey == pk
|
||||
case .hashtag(let ht):
|
||||
if contacts.is_friend(ev.pubkey) {
|
||||
return false
|
||||
}
|
||||
return ev.references(id: ht, key: "t")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class HomeModel {
|
||||
// Don't trigger a user notification for events older than a certain age
|
||||
static let event_max_age_for_notification: TimeInterval = 12 * 60 * 60
|
||||
@@ -36,6 +70,7 @@ class HomeModel {
|
||||
var done_init: Bool = false
|
||||
var incoming_dms: [NostrEvent] = []
|
||||
let dm_debouncer = Debouncer(interval: 0.5)
|
||||
let resub_debouncer = Debouncer(interval: 3.0)
|
||||
var should_debounce_dms = true
|
||||
|
||||
let home_subid = UUID().description
|
||||
@@ -90,6 +125,31 @@ class HomeModel {
|
||||
}
|
||||
}
|
||||
|
||||
func resubscribe(_ resubbing: Resubscribe) {
|
||||
if self.should_debounce_dms {
|
||||
// don't resub on initial load
|
||||
return
|
||||
}
|
||||
|
||||
print("hit resub debouncer")
|
||||
|
||||
resub_debouncer.debounce {
|
||||
print("resub")
|
||||
self.unsubscribe_to_home_filters()
|
||||
|
||||
switch resubbing {
|
||||
case .following:
|
||||
break
|
||||
case .unfollowing(let r):
|
||||
if let filter = HomeResubFilter(from: r) {
|
||||
self.events.filter { ev in !filter.filter(contacts: self.damus_state.contacts, ev: ev) }
|
||||
}
|
||||
}
|
||||
|
||||
self.subscribe_to_home_filters()
|
||||
}
|
||||
}
|
||||
|
||||
func process_event(sub_id: String, relay_id: String, ev: NostrEvent) {
|
||||
if has_sub_id_event(sub_id: sub_id, ev_id: ev.id) {
|
||||
return
|
||||
@@ -639,32 +699,34 @@ func add_contact_if_friend(contacts: Contacts, ev: NostrEvent) {
|
||||
|
||||
func load_our_contacts(state: DamusState, m_old_ev: NostrEvent?, ev: NostrEvent) {
|
||||
let contacts = state.contacts
|
||||
var new_pks = Set<String>()
|
||||
var new_refs = Set<ReferencedId>()
|
||||
// our contacts
|
||||
for tag in ev.tags {
|
||||
if tag.count >= 2 && tag[0] == "p" {
|
||||
new_pks.insert(tag[1])
|
||||
}
|
||||
guard let ref = tag_to_refid(tag) else { continue }
|
||||
new_refs.insert(ref)
|
||||
}
|
||||
|
||||
var old_pks = Set<String>()
|
||||
var old_refs = Set<ReferencedId>()
|
||||
// find removed contacts
|
||||
if let old_ev = m_old_ev {
|
||||
for tag in old_ev.tags {
|
||||
if tag.count >= 2 && tag[0] == "p" {
|
||||
old_pks.insert(tag[1])
|
||||
}
|
||||
guard let ref = tag_to_refid(tag) else { continue }
|
||||
old_refs.insert(ref)
|
||||
}
|
||||
}
|
||||
|
||||
let diff = new_pks.symmetricDifference(old_pks)
|
||||
for pk in diff {
|
||||
if new_pks.contains(pk) {
|
||||
notify(.followed, pk)
|
||||
contacts.add_friend_pubkey(pk)
|
||||
let diff = new_refs.symmetricDifference(old_refs)
|
||||
for ref in diff {
|
||||
if new_refs.contains(ref) {
|
||||
notify(.followed, ref)
|
||||
if ref.key == "p" {
|
||||
contacts.add_friend_pubkey(ref.ref_id)
|
||||
}
|
||||
} else {
|
||||
notify(.unfollowed, pk)
|
||||
contacts.remove_friend(pk)
|
||||
notify(.unfollowed, ref)
|
||||
if ref.key == "p" {
|
||||
contacts.remove_friend(ref.ref_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user