damus

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

commit b58baca227596f72a734fdce1346350e5dffea76
parent 54237049801097ab47c155337b27ed98bf2d35db
Author: William Casarin <jb55@jb55.com>
Date:   Fri,  3 Mar 2023 11:57:18 -0500

Bookmarks Refactor

- Don't do async loading stuff
- Move bookmarkmanager to damus state
- Remove bookmarks update notififcation and switch to observed object
- Switch api to use events explicitly instead of strings

Diffstat:
Mdamus/ContentView.swift | 3++-
Mdamus/Models/BookmarksManager.swift | 61+++++++++++++++++++++++++++++++++++++++++--------------------
Mdamus/Models/DamusState.swift | 3++-
Mdamus/Util/Notifications.swift | 3---
Mdamus/Views/BookmarksView.swift | 30+++++++++++-------------------
Mdamus/Views/ChatroomView.swift | 2+-
Mdamus/Views/DMChatView.swift | 2+-
Mdamus/Views/EventView.swift | 4++--
Mdamus/Views/Events/EmbeddedEventView.swift | 2+-
Mdamus/Views/Events/EventMenu.swift | 22+++++++++++++---------
Mdamus/Views/Events/SelectedEventView.swift | 2+-
Mdamus/Views/Events/TextEvent.swift | 2+-
12 files changed, 76 insertions(+), 60 deletions(-)

diff --git a/damus/ContentView.swift b/damus/ContentView.swift @@ -616,7 +616,8 @@ struct ContentView: View { relay_filters: relay_filters, relay_metadata: metadatas, drafts: Drafts(), - events: EventCache() + events: EventCache(), + bookmarks: BookmarksManager(pubkey: pubkey) ) home.damus_state = self.damus_state! diff --git a/damus/Models/BookmarksManager.swift b/damus/Models/BookmarksManager.swift @@ -7,44 +7,65 @@ import Foundation -class BookmarksManager { +fileprivate func get_bookmarks_key(pubkey: String) -> String { + pk_setting_key(pubkey, key: "bookmarks") +} + +func load_bookmarks(pubkey: String) -> [NostrEvent] { + let key = get_bookmarks_key(pubkey: pubkey) + return (UserDefaults.standard.stringArray(forKey: key) ?? []).compactMap { + event_from_json(dat: $0) + } +} + +func save_bookmarks(pubkey: String, current_value: [NostrEvent], value: [NostrEvent]) -> Bool { + let uniq_bookmarks = Array(Set(value)) + + if uniq_bookmarks != current_value { + let encoded = uniq_bookmarks.map(event_to_json) + UserDefaults.standard.set(encoded, forKey: get_bookmarks_key(pubkey: pubkey)) + return true + } + + return false +} + +class BookmarksManager: ObservableObject { private let userDefaults = UserDefaults.standard private let pubkey: String - init(pubkey: String) { - self.pubkey = pubkey - } - - var bookmarks: [String] { + private var _bookmarks: [NostrEvent] + var bookmarks: [NostrEvent] { get { - return userDefaults.stringArray(forKey: storageKey()) ?? [] + return _bookmarks } set { - let uniqueBookmarks = Array(Set(newValue)) - if uniqueBookmarks != bookmarks { - userDefaults.set(uniqueBookmarks, forKey: storageKey()) + if save_bookmarks(pubkey: pubkey, current_value: _bookmarks, value: newValue) { + self._bookmarks = newValue + self.objectWillChange.send() } } } - func isBookmarked(_ string: String) -> Bool { - return bookmarks.contains(string) + init(pubkey: String) { + self._bookmarks = load_bookmarks(pubkey: pubkey) + self.pubkey = pubkey + } + + func isBookmarked(_ ev: NostrEvent) -> Bool { + return bookmarks.contains(ev) } - func updateBookmark(_ string: String) { - if isBookmarked(string) { - bookmarks = bookmarks.filter { $0 != string } + func updateBookmark(_ ev: NostrEvent) { + if isBookmarked(ev) { + bookmarks = bookmarks.filter { $0 != ev } } else { - bookmarks.append(string) + bookmarks.append(ev) } } func clearAll() { bookmarks = [] } - - private func storageKey() -> String { - pk_setting_key(pubkey, key: "bookmarks") - } } diff --git a/damus/Models/DamusState.swift b/damus/Models/DamusState.swift @@ -25,6 +25,7 @@ struct DamusState { let relay_metadata: RelayMetadatas let drafts: Drafts let events: EventCache + let bookmarks: BookmarksManager var pubkey: String { return keypair.pubkey @@ -35,6 +36,6 @@ struct DamusState { } static var empty: DamusState { - return DamusState.init(pool: RelayPool(), keypair: Keypair(pubkey: "", privkey: ""), likes: EventCounter(our_pubkey: ""), boosts: EventCounter(our_pubkey: ""), contacts: Contacts(our_pubkey: ""), tips: TipCounter(our_pubkey: ""), profiles: Profiles(), dms: DirectMessagesModel(our_pubkey: ""), previews: PreviewCache(), zaps: Zaps(our_pubkey: ""), lnurls: LNUrls(), settings: UserSettingsStore(), relay_filters: RelayFilters(our_pubkey: ""), relay_metadata: RelayMetadatas(), drafts: Drafts(), events: EventCache()) + return DamusState.init(pool: RelayPool(), keypair: Keypair(pubkey: "", privkey: ""), likes: EventCounter(our_pubkey: ""), boosts: EventCounter(our_pubkey: ""), contacts: Contacts(our_pubkey: ""), tips: TipCounter(our_pubkey: ""), profiles: Profiles(), dms: DirectMessagesModel(our_pubkey: ""), previews: PreviewCache(), zaps: Zaps(our_pubkey: ""), lnurls: LNUrls(), settings: UserSettingsStore(), relay_filters: RelayFilters(our_pubkey: ""), relay_metadata: RelayMetadatas(), drafts: Drafts(), events: EventCache(), bookmarks: BookmarksManager(pubkey: "")) } } diff --git a/damus/Util/Notifications.swift b/damus/Util/Notifications.swift @@ -101,9 +101,6 @@ extension Notification.Name { static var update_stats: Notification.Name { return Notification.Name("update_stats") } - static var update_bookmarks: Notification.Name { - return Notification.Name("update_bookmarks") - } static var zapping: Notification.Name { return Notification.Name("zapping") } diff --git a/damus/Views/BookmarksView.swift b/damus/Views/BookmarksView.swift @@ -12,15 +12,20 @@ struct BookmarksView: View { private let noneFilter: (NostrEvent) -> Bool = { _ in true } private let bookmarksTitle = NSLocalizedString("Bookmarks", comment: "Title of bookmarks view") - @State private var bookmarkEvents: [NostrEvent] = [] + @ObservedObject var manager: BookmarksManager init(state: DamusState) { self.state = state + self._manager = ObservedObject(initialValue: state.bookmarks) + } + + var bookmarks: [NostrEvent] { + manager.bookmarks } var body: some View { Group { - if bookmarkEvents.isEmpty { + if bookmarks.isEmpty { VStack { Image(systemName: "bookmark") .resizable() @@ -28,12 +33,9 @@ struct BookmarksView: View { .frame(width: 32.0, height: 32.0) Text(NSLocalizedString("You have no bookmarks yet, add them in the context menu", comment: "Text indicating that there are no bookmarks to be viewed")) } - .task { - updateBookmarks() - } } else { ScrollView { - InnerTimelineView(events: EventHolder(events: bookmarkEvents, incoming: []), damus: state, show_friend_icon: true, filter: noneFilter) + InnerTimelineView(events: EventHolder(events: bookmarks, incoming: []), damus: state, show_friend_icon: true, filter: noneFilter) } } @@ -41,22 +43,12 @@ struct BookmarksView: View { .navigationBarTitleDisplayMode(.inline) .navigationTitle(bookmarksTitle) .toolbar { - if !bookmarkEvents.isEmpty { + if !bookmarks.isEmpty { Button(NSLocalizedString("Clear All", comment: "Button for clearing bookmarks data.")) { - BookmarksManager(pubkey: state.pubkey).clearAll() - bookmarkEvents = [] - } + manager.clearAll() + } } } - .onReceive(handle_notify(.update_bookmarks)) { _ in - updateBookmarks() - } - } - - private func updateBookmarks() { - bookmarkEvents = BookmarksManager(pubkey: state.pubkey).bookmarks.compactMap { bookmark_json in - event_from_json(dat: bookmark_json) - } } } diff --git a/damus/Views/ChatroomView.swift b/damus/Views/ChatroomView.swift @@ -24,7 +24,7 @@ struct ChatroomView: View { next_ev: ind == count-1 ? nil : thread.events[ind+1], damus_state: damus ) - .event_context_menu(ev, keypair: damus.keypair, target_pubkey: ev.pubkey) + .event_context_menu(ev, keypair: damus.keypair, target_pubkey: ev.pubkey, bookmarks: damus.bookmarks) .onTapGesture { if thread.initial_event.id == ev.id { //dismiss() diff --git a/damus/Views/DMChatView.swift b/damus/Views/DMChatView.swift @@ -19,7 +19,7 @@ struct DMChatView: View { VStack(alignment: .leading) { ForEach(Array(zip(dms.events, dms.events.indices)), id: \.0.id) { (ev, ind) in DMView(event: dms.events[ind], damus_state: damus_state) - .event_context_menu(ev, keypair: damus_state.keypair, target_pubkey: ev.pubkey) + .event_context_menu(ev, keypair: damus_state.keypair, target_pubkey: ev.pubkey, bookmarks: damus_state.bookmarks) } EndBlock(height: 80) } diff --git a/damus/Views/EventView.swift b/damus/Views/EventView.swift @@ -126,9 +126,9 @@ extension View { } } - func event_context_menu(_ event: NostrEvent, keypair: Keypair, target_pubkey: String) -> some View { + func event_context_menu(_ event: NostrEvent, keypair: Keypair, target_pubkey: String, bookmarks: BookmarksManager) -> some View { return self.contextMenu { - EventMenuContext(event: event, keypair: keypair, target_pubkey: target_pubkey) + EventMenuContext(event: event, keypair: keypair, target_pubkey: target_pubkey, bookmarks: bookmarks) } } diff --git a/damus/Views/Events/EmbeddedEventView.swift b/damus/Views/Events/EmbeddedEventView.swift @@ -23,7 +23,7 @@ struct EmbeddedEventView: View { EventBody(damus_state: damus_state, event: event, size: .small) } - .event_context_menu(event, keypair: damus_state.keypair, target_pubkey: pubkey) + .event_context_menu(event, keypair: damus_state.keypair, target_pubkey: pubkey, bookmarks: damus_state.bookmarks) } } diff --git a/damus/Views/Events/EventMenu.swift b/damus/Views/Events/EventMenu.swift @@ -11,9 +11,20 @@ struct EventMenuContext: View { let event: NostrEvent let keypair: Keypair let target_pubkey: String + let bookmarks: BookmarksManager @State private var isBookmarked: Bool = false + init(event: NostrEvent, keypair: Keypair, target_pubkey: String, bookmarks: BookmarksManager) { + let bookmarked = bookmarks.isBookmarked(event) + self._isBookmarked = State(initialValue: bookmarked) + + self.bookmarks = bookmarks + self.event = event + self.keypair = keypair + self.target_pubkey = target_pubkey + } + var body: some View { Button { @@ -41,21 +52,14 @@ struct EventMenuContext: View { } Button { - let event_json = event_to_json(ev: event) - BookmarksManager(pubkey: keypair.pubkey).updateBookmark(event_json) - isBookmarked = BookmarksManager(pubkey: keypair.pubkey).isBookmarked(event_json) - notify(.update_bookmarks, event) + self.bookmarks.updateBookmark(event) + isBookmarked = self.bookmarks.isBookmarked(event) } label: { let imageName = isBookmarked ? "bookmark.fill" : "bookmark" let removeBookmarkString = NSLocalizedString("Remove Bookmark", comment: "Context menu option for removing a note bookmark.") let addBookmarkString = NSLocalizedString("Add Bookmark", comment: "Context menu option for adding a note bookmark.") Label(isBookmarked ? removeBookmarkString : addBookmarkString, systemImage: imageName) } - .onAppear { - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - isBookmarked = BookmarksManager(pubkey: keypair.pubkey).isBookmarked(event_to_json(ev: event)) - } - } Button { NotificationCenter.default.post(name: .broadcast_event, object: event) diff --git a/damus/Views/Events/SelectedEventView.swift b/damus/Views/Events/SelectedEventView.swift @@ -60,7 +60,7 @@ struct SelectedEventView: View { self.bar.update(damus: self.damus, evid: target) } .padding([.leading], 2) - .event_context_menu(event, keypair: damus.keypair, target_pubkey: event.pubkey) + .event_context_menu(event, keypair: damus.keypair, target_pubkey: event.pubkey, bookmarks: damus.bookmarks) } } } diff --git a/damus/Views/Events/TextEvent.swift b/damus/Views/Events/TextEvent.swift @@ -66,7 +66,7 @@ struct TextEvent: View { .id(event.id) .frame(maxWidth: .infinity, minHeight: PFP_SIZE) .padding([.bottom], 2) - .event_context_menu(event, keypair: damus.keypair, target_pubkey: pubkey) + .event_context_menu(event, keypair: damus.keypair, target_pubkey: pubkey, bookmarks: damus.bookmarks) } }