damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | LICENSE

commit 8da251dc88f9846fbce302672435a1c59dfca593
parent 040ffdf9f597da3a83a91a8411a5bd6f7a0356f6
Author: William Casarin <jb55@jb55.com>
Date:   Sat, 14 May 2022 15:35:34 -0700

send_filters refactor

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Mdamus.xcodeproj/project.pbxproj | 4++++
Mdamus/ContentView.swift | 76++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Mdamus/Models/ActionBarModel.swift | 10+++++++++-
Mdamus/Models/DamusState.swift | 1+
Mdamus/Models/ProfileModel.swift | 1+
Mdamus/Models/SearchModel.swift | 3++-
Mdamus/Nostr/NostrFilter.swift | 2++
Adamus/Util/TipCounter.swift | 25+++++++++++++++++++++++++
Mdamus/Views/ChatView.swift | 2+-
Mdamus/Views/EventActionBar.swift | 19+++++++++++++++++--
Mdamus/Views/EventView.swift | 22+++++++++++++++-------
11 files changed, 129 insertions(+), 36 deletions(-)

diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj @@ -37,6 +37,7 @@ 4C3BEFDA281DCA1400B3DE84 /* LikeCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD9281DCA1400B3DE84 /* LikeCounter.swift */; }; 4C3BEFDC281DCE6100B3DE84 /* Liked.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFDB281DCE6100B3DE84 /* Liked.swift */; }; 4C3BEFE0281DE1ED00B3DE84 /* DamusState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFDF281DE1ED00B3DE84 /* DamusState.swift */; }; + 4C477C9E282C3A4800033AA3 /* TipCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C477C9D282C3A4800033AA3 /* TipCounter.swift */; }; 4C75EFA427FA577B0006080F /* PostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C75EFA327FA577B0006080F /* PostView.swift */; }; 4C75EFA627FF87A20006080F /* Nostr.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C75EFA527FF87A20006080F /* Nostr.swift */; }; 4C75EFAD28049CFB0006080F /* PostButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C75EFAC28049CFB0006080F /* PostButton.swift */; }; @@ -120,6 +121,7 @@ 4C3BEFD9281DCA1400B3DE84 /* LikeCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LikeCounter.swift; sourceTree = "<group>"; }; 4C3BEFDB281DCE6100B3DE84 /* Liked.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Liked.swift; sourceTree = "<group>"; }; 4C3BEFDF281DE1ED00B3DE84 /* DamusState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusState.swift; sourceTree = "<group>"; }; + 4C477C9D282C3A4800033AA3 /* TipCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TipCounter.swift; sourceTree = "<group>"; }; 4C75EFA327FA577B0006080F /* PostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostView.swift; sourceTree = "<group>"; }; 4C75EFA527FF87A20006080F /* Nostr.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Nostr.swift; sourceTree = "<group>"; }; 4C75EFA72804823E0006080F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; @@ -258,6 +260,7 @@ 4C363A8328233689006E126D /* Parser.swift */, 4C363A8528234FDE006E126D /* ImageCache.swift */, 4C363AA728297703006E126D /* InsertSort.swift */, + 4C477C9D282C3A4800033AA3 /* TipCounter.swift */, ); path = Util; sourceTree = "<group>"; @@ -490,6 +493,7 @@ 4C363A9828283441006E126D /* TestingPrivate.swift in Sources */, 4C363A9028247A1D006E126D /* NostrLink.swift in Sources */, 4C0A3F8C280F5FCA000448DE /* ChatroomView.swift in Sources */, + 4C477C9E282C3A4800033AA3 /* TipCounter.swift in Sources */, 4C0A3F91280F6528000448DE /* ChatView.swift in Sources */, 4C75EFA627FF87A20006080F /* Nostr.swift in Sources */, 4C75EFB328049D640006080F /* NostrEvent.swift in Sources */, diff --git a/damus/ContentView.swift b/damus/ContentView.swift @@ -360,6 +360,7 @@ struct ContentView: View { func connect() { let pool = RelayPool() + add_relay(pool, "wss://relay.damus.io") add_relay(pool, "wss://nostr-pub.wellorder.net") add_relay(pool, "wss://nostr.onsats.org") add_relay(pool, "wss://nostr.bitcoiner.social") @@ -372,6 +373,7 @@ struct ContentView: View { self.damus = DamusState(pool: pool, pubkey: pubkey, likes: EventCounter(our_pubkey: pubkey), boosts: EventCounter(our_pubkey: pubkey), + tips: TipCounter(our_pubkey: pubkey), image_cache: ImageCache(), profiles: Profiles() ) @@ -393,7 +395,7 @@ struct ContentView: View { var boost_ev_id = ev.last_refid()?.ref_id // CHECK SIGS ON THESE - if var inner_ev = ev.inner_event { + if let inner_ev = ev.inner_event { boost_ev_id = inner_ev.id if inner_ev.kind == 1 { @@ -461,32 +463,21 @@ struct ContentView: View { func send_filters(relay_id: String) { // TODO: since times should be based on events from a specific relay // perhaps we could mark this in the relay pool somehow - let last_text_event = get_last_event_of_kind(relay_id: relay_id, kind: NostrKind.text.rawValue) - let since = get_since_time(last_event: last_text_event) - var since_filter = NostrFilter.filter_kinds([1,5,6]) - since_filter.since = since - - let last_like_event = get_last_event_of_kind(relay_id: relay_id, kind: 7) - var like_filter = NostrFilter.filter_kinds([7]) - like_filter.since = get_since_time(last_event: last_like_event) - //like_filter.ids = get_like_pow() - - let last_metadata_event = get_last_event_of_kind(relay_id: relay_id, kind: NostrKind.metadata.rawValue) - var profile_filter = NostrFilter.filter_profiles - if let prof_since = get_metadata_since_time(last_metadata_event) { - profile_filter.since = prof_since - } - - /* - var notification_filter = NostrFilter.filter_text - notification_filter.since = since - */ - + let text_filter = NostrFilter.filter_kinds([1,5,6,7]) + let profile_filter = NostrFilter.filter_profiles var contacts_filter = NostrFilter.filter_contacts contacts_filter.authors = [self.pubkey] - let filters = [since_filter, profile_filter, contacts_filter, like_filter] - print("connected to \(relay_id), refreshing from \(since)") + var filters = [text_filter, profile_filter, contacts_filter] + + filters = update_filters_with_since(last_of_kind: last_event_of_kind[relay_id] ?? [:], filters: filters) + + print("connected to \(relay_id) with filters:") + for filter in filters { + print(filter) + } + print("-----") + self.damus?.pool.send(.subscribe(.init(filters: filters, sub_id: sub_id)), to: [relay_id]) //self.pool?.send(.subscribe(.init(filters: [notification_filter], sub_id: "notifications"))) } @@ -734,3 +725,40 @@ func save_last_notified(_ ev: NostrEvent) { func get_like_pow() -> [String] { return ["00000"] // 20 bits } + + +func update_filters_with_since(last_of_kind: [Int: NostrEvent], filters: [NostrFilter]) -> [NostrFilter] { + let now = Int64(Date.now.timeIntervalSince1970) + + return filters.map { filter in + let kinds = filter.kinds ?? [] + let initial: Int64? = nil + let earliest = kinds.reduce(initial) { earliest, kind in + let last = last_of_kind[kind] + var since: Int64? = nil + + if kind == 0 { + since = get_metadata_since_time(last) + } else { + since = get_since_time(last_event: last) + } + + if earliest == nil { + if since == nil { + return nil + } + return since + } + + return since! < earliest! ? since! : earliest! + } + + if let earliest = earliest { + var with_since = NostrFilter.copy(from: filter) + with_since.since = earliest + return with_since + } + + return filter + } +} diff --git a/damus/Models/ActionBarModel.swift b/damus/Models/ActionBarModel.swift @@ -11,14 +11,22 @@ import Foundation class ActionBarModel: ObservableObject { @Published var our_like: NostrEvent? @Published var our_boost: NostrEvent? + @Published var our_tip: NostrEvent? @Published var likes: Int @Published var boosts: Int + @Published var tips: Int64 - init(likes: Int, boosts: Int, our_like: NostrEvent?, our_boost: NostrEvent?) { + init(likes: Int, boosts: Int, tips: Int64, our_like: NostrEvent?, our_boost: NostrEvent?, our_tip: NostrEvent?) { self.likes = likes self.boosts = boosts + self.tips = tips self.our_like = our_like self.our_boost = our_boost + self.our_tip = our_tip + } + + var tipped: Bool { + return our_tip != nil } var liked: Bool { diff --git a/damus/Models/DamusState.swift b/damus/Models/DamusState.swift @@ -12,6 +12,7 @@ struct DamusState { let pubkey: String let likes: EventCounter let boosts: EventCounter + let tips: TipCounter let image_cache: ImageCache let profiles: Profiles } diff --git a/damus/Models/ProfileModel.swift b/damus/Models/ProfileModel.swift @@ -36,6 +36,7 @@ class ProfileModel: ObservableObject { var filter = NostrFilter.filter_authors([pubkey]) filter.kinds = kinds + filter.limit = 500 print("subscribing to profile \(pubkey) with sub_id \(sub_id)") damus.pool.subscribe(sub_id: sub_id, filters: [filter], handler: handle_event) diff --git a/damus/Models/SearchModel.swift b/damus/Models/SearchModel.swift @@ -13,6 +13,7 @@ class SearchModel: ObservableObject { let pool: RelayPool var search: NostrFilter let sub_id = UUID().description + let limit: UInt32 = 500 init(pool: RelayPool, search: NostrFilter) { self.pool = pool @@ -21,7 +22,7 @@ class SearchModel: ObservableObject { func subscribe() { // since 1 month - search.since = Int64(Date.now.timeIntervalSince1970) - 2629800 * 1 + search.limit = self.limit search.kinds = [1,5,7] //likes_filter.ids = ref_events.referenced_ids! diff --git a/damus/Nostr/NostrFilter.swift b/damus/Nostr/NostrFilter.swift @@ -14,6 +14,7 @@ struct NostrFilter: Codable { var pubkeys: [String]? var since: Int64? var until: Int64? + var limit: UInt32? var authors: [String]? var hashtag: [String]? = nil @@ -26,6 +27,7 @@ struct NostrFilter: Codable { case since case until case authors + case limit } public static func copy(from: NostrFilter) -> NostrFilter { diff --git a/damus/Util/TipCounter.swift b/damus/Util/TipCounter.swift @@ -0,0 +1,25 @@ +// +// TipCounter.swift +// damus +// +// Created by William Casarin on 2022-05-11. +// + +import Foundation + +class TipCounter { + var tips: [String: Int64] = [:] + var user_tips: [String: Set<String>] = [:] + var our_tips: [String: NostrEvent] = [:] + var our_pubkey: String + + enum CountResult { + case already_tipped + case success(Int64) + } + + init (our_pubkey: String) { + self.our_pubkey = our_pubkey + } +} + diff --git a/damus/Views/ChatView.swift b/damus/Views/ChatView.swift @@ -113,7 +113,7 @@ struct ChatView: View { NoteContentView(event: event, profiles: damus.profiles, content: event.content) if is_active || next_ev == nil || next_ev!.pubkey != event.pubkey { - let bar = make_actionbar_model(ev: event, like_counter: damus.likes, boost_counter: damus.boosts) + let bar = make_actionbar_model(ev: event, damus: damus) EventActionBar(event: event, our_pubkey: damus.pubkey, profiles: damus.profiles, diff --git a/damus/Views/EventActionBar.swift b/damus/Views/EventActionBar.swift @@ -37,7 +37,7 @@ struct EventActionBar: View { EventActionButton(img: "bubble.left", col: nil) { notify(.reply, event) } - .padding([.trailing], 40) + .padding([.trailing], 20) HStack(alignment: .bottom) { Text("\(bar.likes > 0 ? "\(bar.likes)" : "")") @@ -52,7 +52,7 @@ struct EventActionBar: View { } } } - .padding([.trailing], 40) + .padding([.trailing], 20) HStack(alignment: .bottom) { Text("\(bar.boosts > 0 ? "\(bar.boosts)" : "")") @@ -67,6 +67,21 @@ struct EventActionBar: View { } } } + .padding([.trailing], 20) + + HStack(alignment: .bottom) { + Text("\(bar.tips > 0 ? "\(bar.tips)" : "")") + .font(.footnote) + .foregroundColor(bar.tipped ? Color.orange : Color.gray) + + EventActionButton(img: bar.tipped ? "bitcoinsign.circle.fill" : "bitcoinsign.circle", col: bar.tipped ? Color.orange : nil) { + if bar.tipped { + notify(.delete, bar.our_tip) + } else { + notify(.boost, event) + } + } + } } .onReceive(handle_notify(.liked)) { n in diff --git a/damus/Views/EventView.swift b/damus/Views/EventView.swift @@ -99,7 +99,7 @@ struct EventView: View { Spacer() if has_action_bar { - let bar = make_actionbar_model(ev: event, like_counter: damus.likes, boost_counter: damus.boosts) + let bar = make_actionbar_model(ev: event, damus: damus) EventActionBar(event: event, our_pubkey: damus.pubkey, profiles: damus.profiles, bar: bar) } @@ -180,11 +180,19 @@ func reply_others_desc(n: Int, n_pubkeys: Int) -> String { -func make_actionbar_model(ev: NostrEvent, like_counter: EventCounter, boost_counter: EventCounter) -> ActionBarModel { - let likes = like_counter.counts[ev.id] - let boosts = boost_counter.counts[ev.id] - let our_like = like_counter.our_events[ev.id] - let our_boost = boost_counter.our_events[ev.id] +func make_actionbar_model(ev: NostrEvent, damus: DamusState) -> ActionBarModel { + let likes = damus.likes.counts[ev.id] + let boosts = damus.boosts.counts[ev.id] + let tips = damus.tips.tips[ev.id] + let our_like = damus.likes.our_events[ev.id] + let our_boost = damus.boosts.our_events[ev.id] + let our_tip = damus.tips.our_tips[ev.id] - return ActionBarModel(likes: likes ?? 0, boosts: boosts ?? 0, our_like: our_like, our_boost: our_boost) + return ActionBarModel(likes: likes ?? 0, + boosts: boosts ?? 0, + tips: tips ?? 0, + our_like: our_like, + our_boost: our_boost, + our_tip: our_tip + ) }