damus

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

commit dd7d9a4a66db05fa5529ef83f8712553e3d3178b
parent 6de7d7ae58e1bcb93d62a66e9b9a775a7765346d
Author: William Casarin <jb55@jb55.com>
Date:   Wed, 15 Jun 2022 14:43:22 -0700

eose loading spinners

Changelog-Added: Add [NIP-15](https://github.com/nostr-protocol/nips/blob/master/15.md) loading spinners
Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Mdamus/ContentView.swift | 4++--
Mdamus/Models/HomeModel.swift | 4++++
Mdamus/Models/SearchHomeModel.swift | 5+++++
Mdamus/Models/SearchModel.swift | 48+++++++++++++++++++++++++++++-------------------
Mdamus/Models/ThreadModel.swift | 9++++++++-
Mdamus/Views/SearchHomeView.swift | 2+-
Mdamus/Views/SearchView.swift | 2+-
Mdamus/Views/TimelineView.swift | 5+++++
8 files changed, 55 insertions(+), 24 deletions(-)

diff --git a/damus/ContentView.swift b/damus/ContentView.swift @@ -85,7 +85,7 @@ struct ContentView: View { var PostingTimelineView: some View { ZStack { if let damus = self.damus_state { - TimelineView(events: $home.events, damus: damus) + TimelineView(events: $home.events, loading: $home.loading, damus: damus) } if privkey != nil { PostButtonContainer { @@ -114,7 +114,7 @@ struct ContentView: View { PostingTimelineView case .notifications: - TimelineView(events: $home.notifications, damus: damus) + TimelineView(events: $home.notifications, loading: $home.loading, damus: damus) .navigationTitle("Notifications") case .none: diff --git a/damus/Models/HomeModel.swift b/damus/Models/HomeModel.swift @@ -23,6 +23,7 @@ class HomeModel: ObservableObject { @Published var new_notifications: Bool = false @Published var notifications: [NostrEvent] = [] @Published var events: [NostrEvent] = [] + @Published var loading: Bool = false @Published var signal: SignalModel = SignalModel() init() { @@ -138,8 +139,10 @@ class HomeModel: ObservableObject { switch ev { case .connected: if !done_init { + self.loading = true send_initial_filters(relay_id: relay_id) } else { + self.loading = true send_home_filters(relay_id: relay_id) } case .error(let merr): @@ -178,6 +181,7 @@ class HomeModel: ObservableObject { print(msg) case .eose: + self.loading = false break } } diff --git a/damus/Models/SearchHomeModel.swift b/damus/Models/SearchHomeModel.swift @@ -11,6 +11,8 @@ import Foundation /// The data model for the SearchHome view, typically something global-like class SearchHomeModel: ObservableObject { @Published var events: [NostrEvent] = [] + @Published var loading: Bool = false + let pool: RelayPool let sub_id = UUID().description let limit: UInt32 = 250 @@ -27,10 +29,12 @@ class SearchHomeModel: ObservableObject { } func subscribe() { + loading = true pool.subscribe(sub_id: sub_id, filters: [get_base_filter()], handler: handle_event) } func unsubscribe() { + loading = false pool.unsubscribe(sub_id: sub_id) } @@ -52,6 +56,7 @@ class SearchHomeModel: ObservableObject { case .notice(let msg): print("search home notice: \(msg)") case .eose: + loading = false break } } diff --git a/damus/Models/SearchModel.swift b/damus/Models/SearchModel.swift @@ -10,6 +10,7 @@ import Foundation class SearchModel: ObservableObject { @Published var events: [NostrEvent] = [] + @Published var loading: Bool = false let pool: RelayPool var search: NostrFilter let sub_id = UUID().description @@ -29,11 +30,13 @@ class SearchModel: ObservableObject { print("subscribing to search '\(search)' with sub_id \(sub_id)") pool.register_handler(sub_id: sub_id, handler: handle_event) + loading = true pool.send(.subscribe(.init(filters: [search], sub_id: sub_id))) } func unsubscribe() { self.pool.unsubscribe(sub_id: sub_id) + loading = false print("unsubscribing from search '\(search)' with sub_id \(sub_id)") } @@ -48,11 +51,15 @@ class SearchModel: ObservableObject { } func handle_event(relay_id: String, ev: NostrConnectionEvent) { - handle_subid_event(pool: pool, sub_id: sub_id, relay_id: relay_id, ev: ev) { ev in + let done = handle_subid_event(pool: pool, sub_id: sub_id, relay_id: relay_id, ev: ev) { ev in if ev.known_kind == .text { self.add_event(ev) } } + + if done { + loading = false + } } } @@ -74,26 +81,29 @@ func event_matches_filter(_ ev: NostrEvent, filter: NostrFilter) -> Bool { return true } -func handle_subid_event(pool: RelayPool, sub_id: String, relay_id: String, ev: NostrConnectionEvent, handle: (NostrEvent) -> ()) { - switch ev { - case .ws_event: +func handle_subid_event(pool: RelayPool, sub_id: String, relay_id: String, ev: NostrConnectionEvent, handle: (NostrEvent) -> ()) -> Bool { + switch ev { + case .ws_event: + break + case .nostr_event(let res): + switch res { + case .event(let ev_subid, let ev): + if ev_subid == sub_id { + handle(ev) + } break - case .nostr_event(let res): - switch res { - case .event(let ev_subid, let ev): - if ev_subid == sub_id { - handle(ev) - } - case .notice(let note): - if note.contains("Too many subscription filters") { - // TODO: resend filters? - pool.reconnect(to: [relay_id]) - } - break - - case .eose: - break + case .notice(let note): + if note.contains("Too many subscription filters") { + // TODO: resend filters? + pool.reconnect(to: [relay_id]) } + break + + case .eose: + return true } + } + + return false } diff --git a/damus/Models/ThreadModel.swift b/damus/Models/ThreadModel.swift @@ -33,6 +33,8 @@ class ThreadModel: ObservableObject { @Published var initial_event: InitialEvent @Published var events: [NostrEvent] = [] @Published var event_map: [String: Int] = [:] + @Published var loading: Bool = false + var replies: ReplyMap = ReplyMap() var event: NostrEvent? { @@ -121,6 +123,7 @@ class ThreadModel: ObservableObject { print("subscribing to thread \(initial_event.id) with sub_id \(sub_id)") pool.register_handler(sub_id: sub_id, handler: handle_event) + loading = true pool.send(.subscribe(.init(filters: [ref_events, events_filter], sub_id: sub_id))) } @@ -162,11 +165,15 @@ class ThreadModel: ObservableObject { } func handle_event(relay_id: String, ev: NostrConnectionEvent) { - handle_subid_event(pool: pool, sub_id: sub_id, relay_id: relay_id, ev: ev) { ev in + let done = handle_subid_event(pool: pool, sub_id: sub_id, relay_id: relay_id, ev: ev) { ev in if ev.known_kind == .text { self.add_event(ev) } } + + if done { + loading = false + } } } diff --git a/damus/Views/SearchHomeView.swift b/damus/Views/SearchHomeView.swift @@ -30,7 +30,7 @@ struct SearchHomeView: View { } var GlobalContent: some View { - TimelineView(events: $model.events, damus: damus_state) + TimelineView(events: $model.events, loading: $model.loading, damus: damus_state) } var SearchContent: some View { diff --git a/damus/Views/SearchView.swift b/damus/Views/SearchView.swift @@ -13,7 +13,7 @@ struct SearchView: View { @Environment(\.dismiss) var dismiss var body: some View { - TimelineView(events: $search.events, damus: appstate) + TimelineView(events: $search.events, loading: $search.loading, damus: appstate) .navigationBarTitle(describe_search(search.search)) .padding([.leading, .trailing], 6) .onReceive(handle_notify(.switched_timeline)) { obj in diff --git a/damus/Views/TimelineView.swift b/damus/Views/TimelineView.swift @@ -33,6 +33,7 @@ struct InnerTimelineView: View { struct TimelineView: View { @Binding var events: [NostrEvent] + @Binding var loading: Bool let damus: DamusState @@ -44,6 +45,10 @@ struct TimelineView: View { var MainContent: some View { ScrollViewReader { scroller in ScrollView { + if loading { + ProgressView() + .progressViewStyle(.circular) + } InnerTimelineView(events: $events, damus: damus) } .onReceive(NotificationCenter.default.publisher(for: .scroll_to_top)) { _ in