Compare commits
1 Commits
remove-mys
...
profile_co
| Author | SHA1 | Date | |
|---|---|---|---|
|
caa4bfe864
|
@@ -10,8 +10,9 @@ import Foundation
|
|||||||
|
|
||||||
/// Simple filter to determine whether to show posts or all posts and replies.
|
/// Simple filter to determine whether to show posts or all posts and replies.
|
||||||
enum FilterState : Int {
|
enum FilterState : Int {
|
||||||
case posts_and_replies = 1
|
|
||||||
case posts = 0
|
case posts = 0
|
||||||
|
case posts_and_replies = 1
|
||||||
|
case conversations = 2
|
||||||
|
|
||||||
func filter(ev: NostrEvent) -> Bool {
|
func filter(ev: NostrEvent) -> Bool {
|
||||||
switch self {
|
switch self {
|
||||||
@@ -19,6 +20,8 @@ enum FilterState : Int {
|
|||||||
return ev.known_kind == .boost || ev.known_kind == .highlight || !ev.is_reply()
|
return ev.known_kind == .boost || ev.known_kind == .highlight || !ev.is_reply()
|
||||||
case .posts_and_replies:
|
case .posts_and_replies:
|
||||||
return true
|
return true
|
||||||
|
case .conversations:
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,10 @@ class ProfileModel: ObservableObject, Equatable {
|
|||||||
var seen_event: Set<NoteId> = Set()
|
var seen_event: Set<NoteId> = Set()
|
||||||
var sub_id = UUID().description
|
var sub_id = UUID().description
|
||||||
var prof_subid = UUID().description
|
var prof_subid = UUID().description
|
||||||
|
var conversations_subid = UUID().description
|
||||||
var findRelay_subid = UUID().description
|
var findRelay_subid = UUID().description
|
||||||
|
var conversation_events: Set<NoteId> = Set()
|
||||||
|
|
||||||
init(pubkey: Pubkey, damus: DamusState) {
|
init(pubkey: Pubkey, damus: DamusState) {
|
||||||
self.pubkey = pubkey
|
self.pubkey = pubkey
|
||||||
self.damus = damus
|
self.damus = damus
|
||||||
@@ -59,6 +61,9 @@ class ProfileModel: ObservableObject, Equatable {
|
|||||||
print("unsubscribing from profile \(pubkey) with sub_id \(sub_id)")
|
print("unsubscribing from profile \(pubkey) with sub_id \(sub_id)")
|
||||||
damus.pool.unsubscribe(sub_id: sub_id)
|
damus.pool.unsubscribe(sub_id: sub_id)
|
||||||
damus.pool.unsubscribe(sub_id: prof_subid)
|
damus.pool.unsubscribe(sub_id: prof_subid)
|
||||||
|
if pubkey != damus.pubkey {
|
||||||
|
damus.pool.unsubscribe(sub_id: conversations_subid)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func subscribe() {
|
func subscribe() {
|
||||||
@@ -69,13 +74,29 @@ class ProfileModel: ObservableObject, Equatable {
|
|||||||
|
|
||||||
text_filter.authors = [pubkey]
|
text_filter.authors = [pubkey]
|
||||||
text_filter.limit = 500
|
text_filter.limit = 500
|
||||||
|
|
||||||
print("subscribing to profile \(pubkey) with sub_id \(sub_id)")
|
print("subscribing to textlike events from profile \(pubkey) with sub_id \(sub_id)")
|
||||||
//print_filters(relay_id: "profile", filters: [[text_filter], [profile_filter]])
|
//print_filters(relay_id: "profile", filters: [[text_filter], [profile_filter]])
|
||||||
damus.pool.subscribe(sub_id: sub_id, filters: [text_filter], handler: handle_event)
|
damus.pool.subscribe(sub_id: sub_id, filters: [text_filter], handler: handle_event)
|
||||||
damus.pool.subscribe(sub_id: prof_subid, filters: [profile_filter], handler: handle_event)
|
damus.pool.subscribe(sub_id: prof_subid, filters: [profile_filter], handler: handle_event)
|
||||||
|
|
||||||
|
subscribe_to_conversations()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func subscribe_to_conversations() {
|
||||||
|
// Only subscribe to conversation events if the profile is not us.
|
||||||
|
guard pubkey != damus.pubkey else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let conversation_kinds: [NostrKind] = [.text, .longform, .highlight]
|
||||||
|
let limit: UInt32 = 500
|
||||||
|
let conversations_filter_them = NostrFilter(kinds: conversation_kinds, pubkeys: [damus.pubkey], limit: limit, authors: [pubkey])
|
||||||
|
let conversations_filter_us = NostrFilter(kinds: conversation_kinds, pubkeys: [pubkey], limit: limit, authors: [damus.pubkey])
|
||||||
|
print("subscribing to conversation events from and to profile \(pubkey) with sub_id \(conversations_subid)")
|
||||||
|
damus.pool.subscribe(sub_id: conversations_subid, filters: [conversations_filter_them, conversations_filter_us], handler: handle_event)
|
||||||
|
}
|
||||||
|
|
||||||
func handle_profile_contact_event(_ ev: NostrEvent) {
|
func handle_profile_contact_event(_ ev: NostrEvent) {
|
||||||
process_contact_event(state: damus, ev: ev)
|
process_contact_event(state: damus, ev: ev)
|
||||||
|
|
||||||
@@ -90,15 +111,8 @@ class ProfileModel: ObservableObject, Equatable {
|
|||||||
self.following = count_pubkeys(ev.tags)
|
self.following = count_pubkeys(ev.tags)
|
||||||
self.relays = decode_json_relays(ev.content)
|
self.relays = decode_json_relays(ev.content)
|
||||||
}
|
}
|
||||||
|
|
||||||
func add_event(_ ev: NostrEvent) {
|
|
||||||
guard ev.should_show_event else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if seen_event.contains(ev.id) {
|
private func add_event(_ ev: NostrEvent) {
|
||||||
return
|
|
||||||
}
|
|
||||||
if ev.is_textlike || ev.known_kind == .boost {
|
if ev.is_textlike || ev.known_kind == .boost {
|
||||||
if self.events.insert(ev) {
|
if self.events.insert(ev) {
|
||||||
self.objectWillChange.send()
|
self.objectWillChange.send()
|
||||||
@@ -109,24 +123,57 @@ class ProfileModel: ObservableObject, Equatable {
|
|||||||
seen_event.insert(ev.id)
|
seen_event.insert(ev.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure the event public key matches the public key(s) we are querying.
|
||||||
|
// This is done to protect against a relay not properly filtering events by the pubkey
|
||||||
|
// See https://github.com/damus-io/damus/issues/1846 for more information
|
||||||
|
private func relay_filtered_correctly(_ ev: NostrEvent, subid: String?) -> Bool {
|
||||||
|
if subid == self.conversations_subid {
|
||||||
|
switch ev.pubkey {
|
||||||
|
case self.pubkey:
|
||||||
|
return ev.referenced_pubkeys.contains(damus.pubkey)
|
||||||
|
case damus.pubkey:
|
||||||
|
return ev.referenced_pubkeys.contains(self.pubkey)
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.pubkey == ev.pubkey
|
||||||
|
}
|
||||||
|
|
||||||
private func handle_event(relay_id: RelayURL, ev: NostrConnectionEvent) {
|
private func handle_event(relay_id: RelayURL, ev: NostrConnectionEvent) {
|
||||||
switch ev {
|
switch ev {
|
||||||
case .ws_event:
|
case .ws_event:
|
||||||
return
|
return
|
||||||
case .nostr_event(let resp):
|
case .nostr_event(let resp):
|
||||||
guard resp.subid == self.sub_id || resp.subid == self.prof_subid else {
|
guard resp.subid == self.sub_id || resp.subid == self.prof_subid || resp.subid == self.conversations_subid else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch resp {
|
switch resp {
|
||||||
case .ok:
|
case .ok:
|
||||||
break
|
break
|
||||||
case .event(_, let ev):
|
case .event(_, let ev):
|
||||||
// Ensure the event public key matches this profiles public key
|
guard ev.should_show_event else {
|
||||||
// This is done to protect against a relay not properly filtering events by the pubkey
|
break
|
||||||
// See https://github.com/damus-io/damus/issues/1846 for more information
|
}
|
||||||
guard self.pubkey == ev.pubkey else { break }
|
|
||||||
|
|
||||||
add_event(ev)
|
if !seen_event.contains(ev.id) {
|
||||||
|
guard relay_filtered_correctly(ev, subid: resp.subid) else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
add_event(ev)
|
||||||
|
|
||||||
|
if resp.subid == self.conversations_subid {
|
||||||
|
conversation_events.insert(ev.id)
|
||||||
|
}
|
||||||
|
} else if resp.subid == self.conversations_subid && !conversation_events.contains(ev.id) {
|
||||||
|
guard relay_filtered_correctly(ev, subid: resp.subid) else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
conversation_events.insert(ev.id)
|
||||||
|
}
|
||||||
case .notice:
|
case .notice:
|
||||||
break
|
break
|
||||||
//notify(.notice, notice)
|
//notify(.notice, notice)
|
||||||
|
|||||||
@@ -122,6 +122,9 @@ struct ProfileView: View {
|
|||||||
func content_filter(_ fstate: FilterState) -> ((NostrEvent) -> Bool) {
|
func content_filter(_ fstate: FilterState) -> ((NostrEvent) -> Bool) {
|
||||||
var filters = ContentFilters.defaults(damus_state: damus_state)
|
var filters = ContentFilters.defaults(damus_state: damus_state)
|
||||||
filters.append(fstate.filter)
|
filters.append(fstate.filter)
|
||||||
|
if fstate == .conversations {
|
||||||
|
filters.append({ profile.conversation_events.contains($0.id) } )
|
||||||
|
}
|
||||||
return ContentFilters(filters: filters).filter
|
return ContentFilters(filters: filters).filter
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,6 +432,17 @@ struct ProfileView: View {
|
|||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tabs: [(String, FilterState)] {
|
||||||
|
var tabs = [
|
||||||
|
(NSLocalizedString("Notes", comment: "Label for filter for seeing only notes (instead of notes and replies)."), FilterState.posts),
|
||||||
|
(NSLocalizedString("Notes & Replies", comment: "Label for filter for seeing notes and replies (instead of only notes)."), FilterState.posts_and_replies)
|
||||||
|
]
|
||||||
|
if profile.pubkey != damus_state.pubkey && !profile.conversation_events.isEmpty {
|
||||||
|
tabs.append((NSLocalizedString("Conversations", comment: "Label for filter for seeing notes and replies that involve conversations between the signed in user and the current profile."), FilterState.conversations))
|
||||||
|
}
|
||||||
|
return tabs
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
ScrollView(.vertical) {
|
ScrollView(.vertical) {
|
||||||
@@ -440,10 +454,7 @@ struct ProfileView: View {
|
|||||||
aboutSection
|
aboutSection
|
||||||
|
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
CustomPicker(tabs: [
|
CustomPicker(tabs: tabs, selection: $filter_state)
|
||||||
(NSLocalizedString("Notes", comment: "Label for filter for seeing only notes (instead of notes and replies)."), FilterState.posts),
|
|
||||||
(NSLocalizedString("Notes & Replies", comment: "Label for filter for seeing notes and replies (instead of only notes)."), FilterState.posts_and_replies)
|
|
||||||
], selection: $filter_state)
|
|
||||||
Divider()
|
Divider()
|
||||||
.frame(height: 1)
|
.frame(height: 1)
|
||||||
}
|
}
|
||||||
@@ -455,6 +466,9 @@ struct ProfileView: View {
|
|||||||
if filter_state == FilterState.posts_and_replies {
|
if filter_state == FilterState.posts_and_replies {
|
||||||
InnerTimelineView(events: profile.events, damus: damus_state, filter: content_filter(FilterState.posts_and_replies))
|
InnerTimelineView(events: profile.events, damus: damus_state, filter: content_filter(FilterState.posts_and_replies))
|
||||||
}
|
}
|
||||||
|
if filter_state == FilterState.conversations && !profile.conversation_events.isEmpty {
|
||||||
|
InnerTimelineView(events: profile.events, damus: damus_state, filter: content_filter(FilterState.conversations))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal, Theme.safeAreaInsets?.left)
|
.padding(.horizontal, Theme.safeAreaInsets?.left)
|
||||||
.zIndex(-yOffset > navbarHeight ? 0 : 1)
|
.zIndex(-yOffset > navbarHeight ? 0 : 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user