damus

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

commit 5db22ae24417b8e196b0f3fcd9091ec6c07ab791
parent 88f938d11c6141b0cb318c89987c3d64c10e4be6
Author: Daniel D’Aquino <daniel@daquino.me>
Date:   Fri,  1 Dec 2023 21:26:14 +0000

Migrate setting and key stores to shared UserDefaults

This is needed to allow the notification extension to process push notifications, respect user's notification settings, and decrypt DMs on the push notification

Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Mdamus.xcodeproj/project.pbxproj | 6++++++
Adamus/Models/DamusUserDefaults.swift | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdamus/Models/UserSettingsStore.swift | 20++++++++++----------
Mdamus/Util/Keys.swift | 10+++++-----
4 files changed, 88 insertions(+), 15 deletions(-)

diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj @@ -590,6 +590,8 @@ D7EDED2E2B128E8A0018B19C /* CollectionExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EDED2D2B128E8A0018B19C /* CollectionExtension.swift */; }; D7EDED2F2B128E8A0018B19C /* CollectionExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EDED2D2B128E8A0018B19C /* CollectionExtension.swift */; }; D7EDED312B1290B80018B19C /* MarkdownUI in Frameworks */ = {isa = PBXBuildFile; productRef = D7EDED302B1290B80018B19C /* MarkdownUI */; }; + D7EDED332B12ACAE0018B19C /* DamusUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EDED322B12ACAE0018B19C /* DamusUserDefaults.swift */; }; + D7EDED342B12ACAE0018B19C /* DamusUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7EDED322B12ACAE0018B19C /* DamusUserDefaults.swift */; }; D7FB10A72B0C371A00FA8D42 /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C2B10272A7B0F5C008AA43E /* Log.swift */; }; D7FF94002AC7AC5300FD969D /* RelayURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FF93FF2AC7AC5200FD969D /* RelayURL.swift */; }; E4FA1C032A24BB7F00482697 /* SearchSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4FA1C022A24BB7F00482697 /* SearchSettingsView.swift */; }; @@ -1343,6 +1345,7 @@ D7EDED1D2B11797D0018B19C /* LongformEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongformEvent.swift; sourceTree = "<group>"; }; D7EDED202B117DCA0018B19C /* SequenceUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SequenceUtils.swift; sourceTree = "<group>"; }; D7EDED2D2B128E8A0018B19C /* CollectionExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionExtension.swift; sourceTree = "<group>"; }; + D7EDED322B12ACAE0018B19C /* DamusUserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusUserDefaults.swift; sourceTree = "<group>"; }; D7FF93FF2AC7AC5200FD969D /* RelayURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayURL.swift; sourceTree = "<group>"; }; E4FA1C022A24BB7F00482697 /* SearchSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsView.swift; sourceTree = "<group>"; }; E990020E2955F837003BBC5A /* EditMetadataView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditMetadataView.swift; sourceTree = "<group>"; }; @@ -1550,6 +1553,7 @@ D7CB5D5E2B11770C00AD4105 /* FollowState.swift */, D7EDED1B2B1178FE0018B19C /* NoteContent.swift */, D7EDED1D2B11797D0018B19C /* LongformEvent.swift */, + D7EDED322B12ACAE0018B19C /* DamusUserDefaults.swift */, ); path = Models; sourceTree = "<group>"; @@ -3082,6 +3086,7 @@ 4C3AC7A12835A81400E1F516 /* SetupView.swift in Sources */, 4C06670128FC7C5900038D2A /* RelayView.swift in Sources */, 4C285C8C28398BC7008A31F1 /* Keys.swift in Sources */, + D7EDED332B12ACAE0018B19C /* DamusUserDefaults.swift in Sources */, 4CA352AE2A76C1AC003BB08B /* FollowedNotify.swift in Sources */, 4CACA9DC280C38C000D9BBE8 /* Profiles.swift in Sources */, 4CE879582996C45300F758CC /* ZapsView.swift in Sources */, @@ -3373,6 +3378,7 @@ D7CB5D412B116F0900AD4105 /* StringCodable.swift in Sources */, D7CE1B1F2B0BE1B8002EDAD4 /* damus.c in Sources */, D7CE1B1B2B0BE144002EDAD4 /* emitter.c in Sources */, + D7EDED342B12ACAE0018B19C /* DamusUserDefaults.swift in Sources */, D7CB5D562B11759900AD4105 /* MuteThreadNotify.swift in Sources */, D7EDED182B1177A00018B19C /* LNUrlPayRequest.swift in Sources */, D798D21C2B0857E400234419 /* Bech32Object.swift in Sources */, diff --git a/damus/Models/DamusUserDefaults.swift b/damus/Models/DamusUserDefaults.swift @@ -0,0 +1,67 @@ +// +// DamusUserDefaults.swift +// damus +// +// Created by Daniel D’Aquino on 2023-11-25. +// + +import Foundation + +/// DamusUserDefaults +/// This struct acts like a drop-in replacement for `UserDefaults.standard` +/// for cases where we want to store such items in a UserDefaults that is shared among the Damus app group +/// so that they can be accessed from other target (e.g. The notification extension target). +/// +/// This struct handles migration automatically to the new shared UserDefaults +struct DamusUserDefaults { + static let shared: DamusUserDefaults = DamusUserDefaults() + private static let default_suite_name: String = "group.com.damus" // Shared defaults for this app group + + private let suite_name: String + private let defaults: UserDefaults + + // MARK: - Initializers + + init() { + self.init(suite_name: Self.default_suite_name)! // Pretty low risk to force-unwrap given that the default suite name is a constant. + } + + init?(suite_name: String = Self.default_suite_name) { + self.suite_name = suite_name + guard let defaults = UserDefaults(suiteName: suite_name) else { + return nil + } + self.defaults = defaults + } + + // MARK: - Functions for feature parity with UserDefaults.standard + + func string(forKey defaultName: String) -> String? { + if let value = self.defaults.string(forKey: defaultName) { + return value + } + let fallback_value = UserDefaults.standard.string(forKey: defaultName) + self.defaults.set(fallback_value, forKey: defaultName) // Migrate + return fallback_value + } + + func set(_ value: Any?, forKey defaultName: String) { + self.defaults.set(value, forKey: defaultName) + } + + func removeObject(forKey defaultName: String) { + self.defaults.removeObject(forKey: defaultName) + // Remove from standard UserDefaults to avoid it coming back as a fallback_value when we fetch it next time + UserDefaults.standard.removeObject(forKey: defaultName) + } + + func object(forKey defaultName: String) -> Any? { + if let value = self.defaults.object(forKey: defaultName) { + return value + } + let fallback_value = UserDefaults.standard.string(forKey: defaultName) + self.defaults.set(fallback_value, forKey: defaultName) // Migrate + return fallback_value + } + +} diff --git a/damus/Models/UserSettingsStore.swift b/damus/Models/UserSettingsStore.swift @@ -16,13 +16,13 @@ func setting_property_key(key: String) -> String { } func setting_get_property_value<T>(key: String, scoped_key: String, default_value: T) -> T { - if let loaded = UserDefaults.standard.object(forKey: scoped_key) as? T { + if let loaded = DamusUserDefaults.shared.object(forKey: scoped_key) as? T { return loaded - } else if let loaded = UserDefaults.standard.object(forKey: key) as? T { + } else if let loaded = DamusUserDefaults.shared.object(forKey: key) as? T { // If pubkey-scoped setting does not exist but the deprecated non-pubkey-scoped setting does, // migrate the deprecated setting into the pubkey-scoped one and delete the deprecated one. - UserDefaults.standard.set(loaded, forKey: scoped_key) - UserDefaults.standard.removeObject(forKey: key) + DamusUserDefaults.shared.set(loaded, forKey: scoped_key) + DamusUserDefaults.shared.removeObject(forKey: key) return loaded } else { return default_value @@ -31,7 +31,7 @@ func setting_get_property_value<T>(key: String, scoped_key: String, default_valu func setting_set_property_value<T: Equatable>(scoped_key: String, old_value: T, new_value: T) -> T? { guard old_value != new_value else { return nil } - UserDefaults.standard.set(new_value, forKey: scoped_key) + DamusUserDefaults.shared.set(new_value, forKey: scoped_key) UserSettingsStore.shared?.objectWillChange.send() return new_value } @@ -65,14 +65,14 @@ func setting_set_property_value<T: Equatable>(scoped_key: String, old_value: T, init(key: String, default_value: T) { self.key = pk_setting_key(UserSettingsStore.pubkey ?? .empty, key: key) - if let loaded = UserDefaults.standard.string(forKey: self.key), let val = T.init(from: loaded) { + if let loaded = DamusUserDefaults.shared.string(forKey: self.key), let val = T.init(from: loaded) { self.value = val - } else if let loaded = UserDefaults.standard.string(forKey: key), let val = T.init(from: loaded) { + } else if let loaded = DamusUserDefaults.shared.string(forKey: key), let val = T.init(from: loaded) { // If pubkey-scoped setting does not exist but the deprecated non-pubkey-scoped setting does, // migrate the deprecated setting into the pubkey-scoped one and delete the deprecated one. self.value = val - UserDefaults.standard.set(val.to_string(), forKey: self.key) - UserDefaults.standard.removeObject(forKey: key) + DamusUserDefaults.shared.set(val.to_string(), forKey: self.key) + DamusUserDefaults.shared.removeObject(forKey: key) } else { self.value = default_value } @@ -85,7 +85,7 @@ func setting_set_property_value<T: Equatable>(scoped_key: String, old_value: T, return } self.value = newValue - UserDefaults.standard.set(newValue.to_string(), forKey: key) + DamusUserDefaults.shared.set(newValue.to_string(), forKey: key) UserSettingsStore.shared!.objectWillChange.send() } } diff --git a/damus/Util/Keys.swift b/damus/Util/Keys.swift @@ -124,7 +124,7 @@ func privkey_to_pubkey(privkey: Privkey) -> Pubkey? { } func save_pubkey(pubkey: Pubkey) { - UserDefaults.standard.set(pubkey.hex(), forKey: "pubkey") + DamusUserDefaults.shared.set(pubkey.hex(), forKey: "pubkey") } enum Keys { @@ -141,7 +141,7 @@ func clear_saved_privkey() throws { } func clear_saved_pubkey() { - UserDefaults.standard.removeObject(forKey: "pubkey") + DamusUserDefaults.shared.removeObject(forKey: "pubkey") } func save_keypair(pubkey: Pubkey, privkey: Privkey) throws { @@ -175,7 +175,7 @@ func get_saved_keypair() -> Keypair? { } func get_saved_pubkey() -> String? { - return UserDefaults.standard.string(forKey: "pubkey") + return DamusUserDefaults.shared.string(forKey: "pubkey") } func get_saved_privkey() -> String? { @@ -198,10 +198,10 @@ func contentContainsPrivateKey(_ content: String) -> Bool { } fileprivate func removePrivateKeyFromUserDefaults() throws { - guard let privkey_str = UserDefaults.standard.string(forKey: "privkey"), + guard let privkey_str = DamusUserDefaults.shared.string(forKey: "privkey"), let privkey = hex_decode_privkey(privkey_str) else { return } try save_privkey(privkey: privkey) - UserDefaults.standard.removeObject(forKey: "privkey") + DamusUserDefaults.shared.removeObject(forKey: "privkey") }