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
This commit is contained in:
@@ -616,7 +616,8 @@ struct ContentView: View {
|
|||||||
relay_filters: relay_filters,
|
relay_filters: relay_filters,
|
||||||
relay_metadata: metadatas,
|
relay_metadata: metadatas,
|
||||||
drafts: Drafts(),
|
drafts: Drafts(),
|
||||||
events: EventCache()
|
events: EventCache(),
|
||||||
|
bookmarks: BookmarksManager(pubkey: pubkey)
|
||||||
)
|
)
|
||||||
home.damus_state = self.damus_state!
|
home.damus_state = self.damus_state!
|
||||||
|
|
||||||
|
|||||||
@@ -7,44 +7,65 @@
|
|||||||
|
|
||||||
import Foundation
|
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 userDefaults = UserDefaults.standard
|
||||||
private let pubkey: String
|
private let pubkey: String
|
||||||
|
|
||||||
init(pubkey: String) {
|
private var _bookmarks: [NostrEvent]
|
||||||
self.pubkey = pubkey
|
var bookmarks: [NostrEvent] {
|
||||||
}
|
|
||||||
|
|
||||||
var bookmarks: [String] {
|
|
||||||
get {
|
get {
|
||||||
return userDefaults.stringArray(forKey: storageKey()) ?? []
|
return _bookmarks
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
let uniqueBookmarks = Array(Set(newValue))
|
if save_bookmarks(pubkey: pubkey, current_value: _bookmarks, value: newValue) {
|
||||||
if uniqueBookmarks != bookmarks {
|
self._bookmarks = newValue
|
||||||
userDefaults.set(uniqueBookmarks, forKey: storageKey())
|
self.objectWillChange.send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isBookmarked(_ string: String) -> Bool {
|
init(pubkey: String) {
|
||||||
return bookmarks.contains(string)
|
self._bookmarks = load_bookmarks(pubkey: pubkey)
|
||||||
|
self.pubkey = pubkey
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateBookmark(_ string: String) {
|
func isBookmarked(_ ev: NostrEvent) -> Bool {
|
||||||
if isBookmarked(string) {
|
return bookmarks.contains(ev)
|
||||||
bookmarks = bookmarks.filter { $0 != string }
|
}
|
||||||
|
|
||||||
|
func updateBookmark(_ ev: NostrEvent) {
|
||||||
|
if isBookmarked(ev) {
|
||||||
|
bookmarks = bookmarks.filter { $0 != ev }
|
||||||
} else {
|
} else {
|
||||||
bookmarks.append(string)
|
bookmarks.append(ev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearAll() {
|
func clearAll() {
|
||||||
bookmarks = []
|
bookmarks = []
|
||||||
}
|
}
|
||||||
|
|
||||||
private func storageKey() -> String {
|
|
||||||
pk_setting_key(pubkey, key: "bookmarks")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ struct DamusState {
|
|||||||
let relay_metadata: RelayMetadatas
|
let relay_metadata: RelayMetadatas
|
||||||
let drafts: Drafts
|
let drafts: Drafts
|
||||||
let events: EventCache
|
let events: EventCache
|
||||||
|
let bookmarks: BookmarksManager
|
||||||
|
|
||||||
var pubkey: String {
|
var pubkey: String {
|
||||||
return keypair.pubkey
|
return keypair.pubkey
|
||||||
@@ -35,6 +36,6 @@ struct DamusState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static var empty: 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: ""))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,9 +101,6 @@ extension Notification.Name {
|
|||||||
static var update_stats: Notification.Name {
|
static var update_stats: Notification.Name {
|
||||||
return Notification.Name("update_stats")
|
return Notification.Name("update_stats")
|
||||||
}
|
}
|
||||||
static var update_bookmarks: Notification.Name {
|
|
||||||
return Notification.Name("update_bookmarks")
|
|
||||||
}
|
|
||||||
static var zapping: Notification.Name {
|
static var zapping: Notification.Name {
|
||||||
return Notification.Name("zapping")
|
return Notification.Name("zapping")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,15 +12,20 @@ struct BookmarksView: View {
|
|||||||
private let noneFilter: (NostrEvent) -> Bool = { _ in true }
|
private let noneFilter: (NostrEvent) -> Bool = { _ in true }
|
||||||
private let bookmarksTitle = NSLocalizedString("Bookmarks", comment: "Title of bookmarks view")
|
private let bookmarksTitle = NSLocalizedString("Bookmarks", comment: "Title of bookmarks view")
|
||||||
|
|
||||||
@State private var bookmarkEvents: [NostrEvent] = []
|
@ObservedObject var manager: BookmarksManager
|
||||||
|
|
||||||
init(state: DamusState) {
|
init(state: DamusState) {
|
||||||
self.state = state
|
self.state = state
|
||||||
|
self._manager = ObservedObject(initialValue: state.bookmarks)
|
||||||
|
}
|
||||||
|
|
||||||
|
var bookmarks: [NostrEvent] {
|
||||||
|
manager.bookmarks
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
if bookmarkEvents.isEmpty {
|
if bookmarks.isEmpty {
|
||||||
VStack {
|
VStack {
|
||||||
Image(systemName: "bookmark")
|
Image(systemName: "bookmark")
|
||||||
.resizable()
|
.resizable()
|
||||||
@@ -28,12 +33,9 @@ struct BookmarksView: View {
|
|||||||
.frame(width: 32.0, height: 32.0)
|
.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"))
|
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 {
|
} else {
|
||||||
ScrollView {
|
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)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
.navigationTitle(bookmarksTitle)
|
.navigationTitle(bookmarksTitle)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
if !bookmarkEvents.isEmpty {
|
if !bookmarks.isEmpty {
|
||||||
Button(NSLocalizedString("Clear All", comment: "Button for clearing bookmarks data.")) {
|
Button(NSLocalizedString("Clear All", comment: "Button for clearing bookmarks data.")) {
|
||||||
BookmarksManager(pubkey: state.pubkey).clearAll()
|
manager.clearAll()
|
||||||
bookmarkEvents = []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ struct ChatroomView: View {
|
|||||||
next_ev: ind == count-1 ? nil : thread.events[ind+1],
|
next_ev: ind == count-1 ? nil : thread.events[ind+1],
|
||||||
damus_state: damus
|
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 {
|
.onTapGesture {
|
||||||
if thread.initial_event.id == ev.id {
|
if thread.initial_event.id == ev.id {
|
||||||
//dismiss()
|
//dismiss()
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ struct DMChatView: View {
|
|||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
ForEach(Array(zip(dms.events, dms.events.indices)), id: \.0.id) { (ev, ind) in
|
ForEach(Array(zip(dms.events, dms.events.indices)), id: \.0.id) { (ev, ind) in
|
||||||
DMView(event: dms.events[ind], damus_state: damus_state)
|
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)
|
EndBlock(height: 80)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
return self.contextMenu {
|
||||||
EventMenuContext(event: event, keypair: keypair, target_pubkey: target_pubkey)
|
EventMenuContext(event: event, keypair: keypair, target_pubkey: target_pubkey, bookmarks: bookmarks)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ struct EmbeddedEventView: View {
|
|||||||
|
|
||||||
EventBody(damus_state: damus_state, event: event, size: .small)
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,20 @@ struct EventMenuContext: View {
|
|||||||
let event: NostrEvent
|
let event: NostrEvent
|
||||||
let keypair: Keypair
|
let keypair: Keypair
|
||||||
let target_pubkey: String
|
let target_pubkey: String
|
||||||
|
let bookmarks: BookmarksManager
|
||||||
|
|
||||||
@State private var isBookmarked: Bool = false
|
@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 {
|
var body: some View {
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
@@ -41,21 +52,14 @@ struct EventMenuContext: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
let event_json = event_to_json(ev: event)
|
self.bookmarks.updateBookmark(event)
|
||||||
BookmarksManager(pubkey: keypair.pubkey).updateBookmark(event_json)
|
isBookmarked = self.bookmarks.isBookmarked(event)
|
||||||
isBookmarked = BookmarksManager(pubkey: keypair.pubkey).isBookmarked(event_json)
|
|
||||||
notify(.update_bookmarks, event)
|
|
||||||
} label: {
|
} label: {
|
||||||
let imageName = isBookmarked ? "bookmark.fill" : "bookmark"
|
let imageName = isBookmarked ? "bookmark.fill" : "bookmark"
|
||||||
let removeBookmarkString = NSLocalizedString("Remove Bookmark", comment: "Context menu option for removing a note 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.")
|
let addBookmarkString = NSLocalizedString("Add Bookmark", comment: "Context menu option for adding a note bookmark.")
|
||||||
Label(isBookmarked ? removeBookmarkString : addBookmarkString, systemImage: imageName)
|
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 {
|
Button {
|
||||||
NotificationCenter.default.post(name: .broadcast_event, object: event)
|
NotificationCenter.default.post(name: .broadcast_event, object: event)
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ struct SelectedEventView: View {
|
|||||||
self.bar.update(damus: self.damus, evid: target)
|
self.bar.update(damus: self.damus, evid: target)
|
||||||
}
|
}
|
||||||
.padding([.leading], 2)
|
.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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ struct TextEvent: View {
|
|||||||
.id(event.id)
|
.id(event.id)
|
||||||
.frame(maxWidth: .infinity, minHeight: PFP_SIZE)
|
.frame(maxWidth: .infinity, minHeight: PFP_SIZE)
|
||||||
.padding([.bottom], 2)
|
.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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user