commit aa559b2916e01c7721fce4ced2f4b6f41e3df3ba
parent 9bf8349db60a9f247aa02e29a1205c8bb7ec9716
Author: William Casarin <jb55@jb55.com>
Date: Fri, 21 Apr 2023 16:21:01 -0700
Refactor and Scope user settings to pubkey
Diffstat:
10 files changed, 269 insertions(+), 286 deletions(-)
diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj
@@ -155,6 +155,7 @@
4C9F18E229AA9B6C008C55EC /* CustomizeZapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C9F18E129AA9B6C008C55EC /* CustomizeZapView.swift */; };
4C9F18E429ABDE6D008C55EC /* MaybeAnonPfpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C9F18E329ABDE6D008C55EC /* MaybeAnonPfpView.swift */; };
4CA2EFA0280E37AC0044ACD8 /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA2EF9F280E37AC0044ACD8 /* TimelineView.swift */; };
+ 4CA5588329F33F5B00DC6A45 /* StringCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA5588229F33F5B00DC6A45 /* StringCodable.swift */; };
4CAAD8AD298851D000060CEA /* AccountDeletion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CAAD8AC298851D000060CEA /* AccountDeletion.swift */; };
4CAAD8B029888AD200060CEA /* RelayConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CAAD8AF29888AD200060CEA /* RelayConfigView.swift */; };
4CACA9D5280C31E100D9BBE8 /* ReplyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CACA9D4280C31E100D9BBE8 /* ReplyView.swift */; };
@@ -563,6 +564,7 @@
4C9F18E129AA9B6C008C55EC /* CustomizeZapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomizeZapView.swift; sourceTree = "<group>"; };
4C9F18E329ABDE6D008C55EC /* MaybeAnonPfpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MaybeAnonPfpView.swift; sourceTree = "<group>"; };
4CA2EF9F280E37AC0044ACD8 /* TimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineView.swift; sourceTree = "<group>"; };
+ 4CA5588229F33F5B00DC6A45 /* StringCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringCodable.swift; sourceTree = "<group>"; };
4CAAD8AC298851D000060CEA /* AccountDeletion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDeletion.swift; sourceTree = "<group>"; };
4CAAD8AF29888AD200060CEA /* RelayConfigView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayConfigView.swift; sourceTree = "<group>"; };
4CACA9D4280C31E100D9BBE8 /* ReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyView.swift; sourceTree = "<group>"; };
@@ -1008,6 +1010,7 @@
4C8D00C729DF791C0036AF10 /* CompatibleAttribute.swift */,
4C8D00CB29DF92DF0036AF10 /* Hashtags.swift */,
4CDA128B29EB19C40006FA5A /* LocalNotification.swift */,
+ 4CA5588229F33F5B00DC6A45 /* StringCodable.swift */,
);
path = Util;
sourceTree = "<group>";
@@ -1524,6 +1527,7 @@
4CC6193A29DC777C006A86D1 /* RelayBootstrap.swift in Sources */,
4C285C8A2838B985008A31F1 /* ProfilePictureSelector.swift in Sources */,
4C9F18E429ABDE6D008C55EC /* MaybeAnonPfpView.swift in Sources */,
+ 4CA5588329F33F5B00DC6A45 /* StringCodable.swift in Sources */,
4C75EFB92804A2740006080F /* EventView.swift in Sources */,
4C8D00C829DF791C0036AF10 /* CompatibleAttribute.swift in Sources */,
3AA247FD297E3CFF0090C62D /* RepostsModel.swift in Sources */,
diff --git a/damus/ContentView.swift b/damus/ContentView.swift
@@ -678,7 +678,12 @@ struct ContentView: View {
}
pool.register_handler(sub_id: sub_id, handler: home.handle_event)
-
+
+ // dumb stuff needed for property wrappers
+ UserSettingsStore.pubkey = pubkey
+ let settings = UserSettingsStore()
+ UserSettingsStore.shared = settings
+
self.damus_state = DamusState(pool: pool,
keypair: keypair,
likes: EventCounter(our_pubkey: pubkey),
@@ -690,7 +695,7 @@ struct ContentView: View {
previews: PreviewCache(),
zaps: Zaps(our_pubkey: pubkey),
lnurls: LNUrls(),
- settings: UserSettingsStore(),
+ settings: settings,
relay_filters: relay_filters,
relay_metadata: metadatas,
drafts: Drafts(),
diff --git a/damus/Models/DamusState.swift b/damus/Models/DamusState.swift
@@ -39,6 +39,8 @@ struct DamusState {
keypair.privkey != nil
}
+ static var settings_pubkey: String? = nil
+
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(), bookmarks: BookmarksManager(pubkey: ""), postbox: PostBox(pool: RelayPool()), bootstrap_relays: [], replies: ReplyCounter(our_pubkey: ""), muted_threads: MutedThreadsManager(keypair: Keypair(pubkey: "", privkey: nil))) }
}
diff --git a/damus/Models/DeepLPlan.swift b/damus/Models/DeepLPlan.swift
@@ -7,7 +7,19 @@
import Foundation
-enum DeepLPlan: String, CaseIterable, Identifiable {
+enum DeepLPlan: String, CaseIterable, Identifiable, StringCodable {
+ init?(from string: String) {
+ guard let dl = DeepLPlan(rawValue: string) else {
+ return nil
+ }
+
+ self = dl
+ }
+
+ func to_string() -> String {
+ return self.rawValue
+ }
+
var id: String { self.rawValue }
struct Model: Identifiable, Hashable {
diff --git a/damus/Models/TranslationService.swift b/damus/Models/TranslationService.swift
@@ -7,7 +7,19 @@
import Foundation
-enum TranslationService: String, CaseIterable, Identifiable {
+enum TranslationService: String, CaseIterable, Identifiable, StringCodable {
+ init?(from string: String) {
+ guard let ts = TranslationService(rawValue: string) else {
+ return nil
+ }
+
+ self = ts
+ }
+
+ func to_string() -> String {
+ return self.rawValue
+ }
+
var id: String { self.rawValue }
struct Model: Identifiable, Hashable {
diff --git a/damus/Models/UserSettingsStore.swift b/damus/Models/UserSettingsStore.swift
@@ -9,218 +9,135 @@ import Foundation
import Vault
import UIKit
-func should_show_wallet_selector(_ pubkey: String) -> Bool {
- return UserDefaults.standard.object(forKey: "show_wallet_selector") as? Bool ?? true
-}
-
-func pk_setting_key(_ pubkey: String, key: String) -> String {
- return "\(pubkey)_\(key)"
-}
-
-func default_zap_setting_key(pubkey: String) -> String {
- return pk_setting_key(pubkey, key: "default_zap_amount")
-}
-
-func set_default_zap_amount(pubkey: String, amount: Int) {
- let key = default_zap_setting_key(pubkey: pubkey)
- UserDefaults.standard.setValue(amount, forKey: key)
-}
-
-let fallback_zap_amount = 1000
-
-func get_default_zap_amount(pubkey: String) -> Int {
- let key = default_zap_setting_key(pubkey: pubkey)
- let amt = UserDefaults.standard.integer(forKey: key)
- if amt == 0 {
- return fallback_zap_amount
- }
- return amt
-}
-
-func should_disable_image_animation() -> Bool {
- return (UserDefaults.standard.object(forKey: "disable_animation") as? Bool)
- ?? UIAccessibility.isReduceMotionEnabled
- }
-
-func get_default_wallet(_ pubkey: String) -> Wallet {
- if let defaultWalletName = UserDefaults.standard.string(forKey: "default_wallet"),
- let default_wallet = Wallet(rawValue: defaultWalletName)
- {
- return default_wallet
- } else {
- return .system_default_wallet
- }
-}
-
-func get_media_uploader(_ pubkey: String) -> MediaUploader {
- if let defaultMediaUploader = UserDefaults.standard.string(forKey: "default_media_uploader"),
- let defaultMediaUploader = MediaUploader(rawValue: defaultMediaUploader) {
- return defaultMediaUploader
- } else {
- return .nostrBuild
- }
-}
-
-private func get_translation_service(_ pubkey: String) -> TranslationService? {
- guard let translation_service = UserDefaults.standard.string(forKey: "translation_service") else {
- return nil
- }
-
- return TranslationService(rawValue: translation_service)
-}
-
-private func get_deepl_plan(_ pubkey: String) -> DeepLPlan? {
- guard let server_name = UserDefaults.standard.string(forKey: "deepl_plan") else {
- return nil
- }
-
- return DeepLPlan(rawValue: server_name)
-}
-
-private func get_libretranslate_server(_ pubkey: String) -> LibreTranslateServer? {
- guard let server_name = UserDefaults.standard.string(forKey: "libretranslate_server") else {
- return nil
- }
+@propertyWrapper struct Setting<T: Equatable> {
+ private let key: String
+ private var value: T
- return LibreTranslateServer(rawValue: server_name)
-}
-
-private func get_libretranslate_url(_ pubkey: String, server: LibreTranslateServer) -> String? {
- if let url = server.model.url {
- return url
- }
-
- return UserDefaults.standard.object(forKey: "libretranslate_url") as? String
-}
-
-class UserSettingsStore: ObservableObject {
- @Published var default_wallet: Wallet {
- didSet {
- UserDefaults.standard.set(default_wallet.rawValue, forKey: "default_wallet")
- }
- }
-
- @Published var default_media_uploader: MediaUploader {
- didSet {
- UserDefaults.standard.set(default_media_uploader.rawValue, forKey: "default_media_uploader")
+ init(key: String, default_value: T) {
+ self.key = pk_setting_key(UserSettingsStore.pubkey ?? "", key: key)
+ if let loaded = UserDefaults.standard.object(forKey: self.key) as? T {
+ self.value = loaded
+ } else if let loaded = UserDefaults.standard.object(forKey: key) as? T {
+ // try to load from deprecated non-pubkey-keyed setting
+ self.value = loaded
+ } else {
+ self.value = default_value
}
}
- @Published var show_wallet_selector: Bool {
- didSet {
- UserDefaults.standard.set(show_wallet_selector, forKey: "show_wallet_selector")
+ var wrappedValue: T {
+ get { return value }
+ set {
+ guard self.value != newValue else {
+ return
+ }
+ self.value = newValue
+ UserDefaults.standard.set(newValue, forKey: key)
+ UserSettingsStore.shared!.objectWillChange.send()
}
}
+}
- @Published var left_handed: Bool {
- didSet {
- UserDefaults.standard.set(left_handed, forKey: "left_handed")
- }
- }
+@propertyWrapper class StringSetting<T: StringCodable & Equatable> {
+ private let key: String
+ private var value: T
- @Published var always_show_images: Bool {
- didSet {
- UserDefaults.standard.set(always_show_images, forKey: "always_show_images")
- }
- }
-
- @Published var zap_vibration: Bool {
- didSet {
- UserDefaults.standard.set(zap_vibration, forKey: "zap_vibration")
- }
- }
-
- @Published var zap_notification: Bool {
- didSet {
- UserDefaults.standard.set(zap_notification, forKey: "zap_notification")
- }
- }
-
- @Published var mention_notification: Bool {
- didSet {
- UserDefaults.standard.set(mention_notification, forKey: "mention_notification")
- }
- }
-
- @Published var repost_notification: Bool {
- didSet {
- UserDefaults.standard.set(repost_notification, forKey: "repost_notification")
- }
- }
-
- @Published var dm_notification: Bool {
- didSet {
- UserDefaults.standard.set(dm_notification, forKey: "dm_notification")
- }
- }
-
- @Published var like_notification: Bool {
- didSet {
- UserDefaults.standard.set(like_notification, forKey: "like_notification")
- }
- }
-
- @Published var notification_only_from_following: Bool {
- didSet {
- UserDefaults.standard.set(notification_only_from_following, forKey: "notification_only_from_following")
+ init(key: String, default_value: T) {
+ self.key = pk_setting_key(UserSettingsStore.pubkey ?? "", key: key)
+ if let loaded = UserDefaults.standard.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) {
+ // try to load from deprecated non-pubkey-keyed setting
+ self.value = val
+ } else {
+ self.value = default_value
}
}
- @Published var translate_dms: Bool {
- didSet {
- UserDefaults.standard.set(translate_dms, forKey: "translate_dms")
+ var wrappedValue: T {
+ get { return value }
+ set {
+ guard self.value != newValue else {
+ return
+ }
+ self.value = newValue
+ UserDefaults.standard.set(newValue.to_string(), forKey: key)
+ UserSettingsStore.shared!.objectWillChange.send()
}
}
+}
- @Published var truncate_timeline_text: Bool {
- didSet {
- UserDefaults.standard.set(truncate_timeline_text, forKey: "truncate_timeline_text")
- }
- }
+class UserSettingsStore: ObservableObject {
+ static var pubkey: String? = nil
+ static var shared: UserSettingsStore? = nil
- @Published var notification_indicators: Int {
- didSet {
- UserDefaults.standard.set(notification_indicators, forKey: "notification_indicators")
- }
- }
+ @StringSetting(key: "default_wallet", default_value: .system_default_wallet)
+ var default_wallet: Wallet
- @Published var truncate_mention_text: Bool {
- didSet {
- UserDefaults.standard.set(truncate_mention_text, forKey: "truncate_mention_text")
- }
- }
+ @StringSetting(key: "default_media_uploader", default_value: .nostrBuild)
+ var default_media_uploader: MediaUploader
+
+ @Setting(key: "show_wallet_selector", default_value: true)
+ var show_wallet_selector: Bool
+
+ @Setting(key: "left_handed", default_value: false)
+ var left_handed: Bool
+
+ @Setting(key: "always_show_images", default_value: false)
+ var always_show_images: Bool
- @Published var auto_translate: Bool {
- didSet {
- UserDefaults.standard.set(auto_translate, forKey: "auto_translate")
- }
- }
+ @Setting(key: "zap_vibration", default_value: true)
+ var zap_vibration: Bool
+
+ @Setting(key: "zap_notification", default_value: true)
+ var zap_notification: Bool
+
+ @Setting(key: "mention_notification", default_value: true)
+ var mention_notification: Bool
- @Published var show_only_preferred_languages: Bool {
- didSet {
- UserDefaults.standard.set(show_only_preferred_languages, forKey: "show_only_preferred_languages")
- }
- }
+ @Setting(key: "repost_notification", default_value: true)
+ var repost_notification: Bool
+
+ @Setting(key: "dm_notification", default_value: true)
+ var dm_notification: Bool
+
+ @Setting(key: "like_notification", default_value: true)
+ var like_notification: Bool
+
+ @Setting(key: "notification_only_from_following", default_value: false)
+ var notification_only_from_following: Bool
+
+ @Setting(key: "translate_dms", default_value: false)
+ var translate_dms: Bool
+
+ @Setting(key: "truncate_timeline_text", default_value: false)
+ var truncate_timeline_text: Bool
+
+ @Setting(key: "truncate_mention_text", default_value: true)
+ var truncate_mention_text: Bool
+
+ @Setting(key: "notification_indicators", default_value: NewEventsBits.all.rawValue)
+ var notification_indicators: Int
+
+ @Setting(key: "auto_translate", default_value: true)
+ var auto_translate: Bool
- @Published var onlyzaps_mode: Bool {
- didSet {
- UserDefaults.standard.set(onlyzaps_mode, forKey: "onlyzaps_mode")
- }
- }
+ @Setting(key: "show_only_preferred_languages", default_value: false)
+ var show_only_preferred_languages: Bool
- @Published var translation_service: TranslationService {
- didSet {
- UserDefaults.standard.set(translation_service.rawValue, forKey: "translation_service")
- }
- }
+ @Setting(key: "onlyzaps_mode", default_value: false)
+ var onlyzaps_mode: Bool
+
+ @Setting(key: "disable_animation", default_value: UIAccessibility.isReduceMotionEnabled)
+ var disable_animation: Bool
- @Published var deepl_plan: DeepLPlan {
- didSet {
- UserDefaults.standard.set(deepl_plan.rawValue, forKey: "deepl_plan")
- }
- }
+ @StringSetting(key: "translation_service", default_value: .none)
+ var translation_service: TranslationService
- @Published var deepl_api_key: String {
+ @StringSetting(key: "deepl_plan", default_value: .free)
+ var deepl_plan: DeepLPlan
+
+ var deepl_api_key: String {
didSet {
do {
if deepl_api_key == "" {
@@ -234,31 +151,14 @@ class UserSettingsStore: ObservableObject {
}
}
- @Published var libretranslate_server: LibreTranslateServer {
- didSet {
- if oldValue == libretranslate_server {
- return
- }
-
- UserDefaults.standard.set(libretranslate_server.rawValue, forKey: "libretranslate_server")
-
- libretranslate_api_key = ""
-
- if libretranslate_server == .custom {
- libretranslate_url = ""
- } else {
- libretranslate_url = libretranslate_server.model.url!
- }
- }
- }
-
- @Published var libretranslate_url: String {
- didSet {
- UserDefaults.standard.set(libretranslate_url, forKey: "libretranslate_url")
- }
- }
+ @Setting(key: "libretranslate_server", default_value: .vern)
+ var libretranslate_server: LibreTranslateServer
+
+ @Setting(key: "libretranslate_url", default_value: "")
+ var libretranslate_url: String
- @Published var libretranslate_api_key: String {
+ @Setting(key: "libretranslate_api_key", default_value: "")
+ var libretranslate_api_key: String {
didSet {
do {
if libretranslate_api_key == "" {
@@ -271,72 +171,8 @@ class UserSettingsStore: ObservableObject {
}
}
}
-
- @Published var disable_animation: Bool {
- didSet {
- UserDefaults.standard.set(disable_animation, forKey: "disable_animation")
- }
- }
init() {
- // TODO: pubkey-scoped settings
- let pubkey = ""
- self.default_wallet = get_default_wallet(pubkey)
- show_wallet_selector = should_show_wallet_selector(pubkey)
- always_show_images = UserDefaults.standard.object(forKey: "always_show_images") as? Bool ?? false
-
- default_media_uploader = get_media_uploader(pubkey)
-
- left_handed = UserDefaults.standard.object(forKey: "left_handed") as? Bool ?? false
- zap_vibration = UserDefaults.standard.object(forKey: "zap_vibration") as? Bool ?? false
- zap_notification = UserDefaults.standard.object(forKey: "zap_notification") as? Bool ?? true
- mention_notification = UserDefaults.standard.object(forKey: "mention_notification") as? Bool ?? true
- repost_notification = UserDefaults.standard.object(forKey: "repost_notification") as? Bool ?? true
- like_notification = UserDefaults.standard.object(forKey: "like_notification") as? Bool ?? true
- dm_notification = UserDefaults.standard.object(forKey: "dm_notification") as? Bool ?? true
- notification_indicators = UserDefaults.standard.object(forKey: "notification_indicators") as? Int ?? NewEventsBits.all.rawValue
- notification_only_from_following = UserDefaults.standard.object(forKey: "notification_only_from_following") as? Bool ?? false
- translate_dms = UserDefaults.standard.object(forKey: "translate_dms") as? Bool ?? false
- truncate_timeline_text = UserDefaults.standard.object(forKey: "truncate_timeline_text") as? Bool ?? false
- truncate_mention_text = UserDefaults.standard.object(forKey: "truncate_mention_text") as? Bool ?? false
- disable_animation = should_disable_image_animation()
- auto_translate = UserDefaults.standard.object(forKey: "auto_translate") as? Bool ?? true
- show_only_preferred_languages = UserDefaults.standard.object(forKey: "show_only_preferred_languages") as? Bool ?? false
- onlyzaps_mode = UserDefaults.standard.object(forKey: "onlyzaps_mode") as? Bool ?? false
-
- // Note from @tyiu:
- // Default translation service is disabled by default for now until we gain some confidence that it is working well in production.
- // Instead of throwing all Damus users onto feature immediately, allow for discovery of feature organically.
- // Also, we are connecting to servers listed as mirrors on the official LibreTranslate GitHub README that do not require API keys.
- // However, we have not asked them for permission to use, so we're trying to be good neighbors for now.
- // Opportunity: spin up dedicated trusted LibreTranslate server that requires an API key for any access (or higher rate limit access).
- if let translation_service = get_translation_service(pubkey) {
- self.translation_service = translation_service
- } else {
- self.translation_service = .none
- }
-
- if let libretranslate_server = get_libretranslate_server(pubkey) {
- self.libretranslate_server = libretranslate_server
- self.libretranslate_url = get_libretranslate_url(pubkey, server: libretranslate_server) ?? ""
- } else {
- // Choose a random server to distribute load.
- libretranslate_server = .allCases.filter { $0 != .custom }.randomElement()!
- libretranslate_url = ""
- }
-
- do {
- libretranslate_api_key = try Vault.getPrivateKey(keychainConfiguration: DamusLibreTranslateKeychainConfiguration())
- } catch {
- libretranslate_api_key = ""
- }
-
- if let deepl_plan = get_deepl_plan(pubkey) {
- self.deepl_plan = deepl_plan
- } else {
- self.deepl_plan = .free
- }
-
do {
deepl_api_key = try Vault.getPrivateKey(keychainConfiguration: DamusDeepLKeychainConfiguration())
} catch {
@@ -383,3 +219,79 @@ struct DamusDeepLKeychainConfiguration: KeychainConfiguration {
var accessGroup: String? = nil
var accountName = "deepl_apikey"
}
+
+func should_show_wallet_selector(_ pubkey: String) -> Bool {
+ return UserDefaults.standard.object(forKey: "show_wallet_selector") as? Bool ?? true
+}
+
+func pk_setting_key(_ pubkey: String, key: String) -> String {
+ return "\(pubkey)_\(key)"
+}
+
+func default_zap_setting_key(pubkey: String) -> String {
+ return pk_setting_key(pubkey, key: "default_zap_amount")
+}
+
+func set_default_zap_amount(pubkey: String, amount: Int) {
+ let key = default_zap_setting_key(pubkey: pubkey)
+ UserDefaults.standard.setValue(amount, forKey: key)
+}
+
+let fallback_zap_amount = 1000
+
+func get_default_zap_amount(pubkey: String) -> Int {
+ let key = default_zap_setting_key(pubkey: pubkey)
+ let amt = UserDefaults.standard.integer(forKey: key)
+ if amt == 0 {
+ return fallback_zap_amount
+ }
+ return amt
+}
+
+func should_disable_image_animation() -> Bool {
+ return (UserDefaults.standard.object(forKey: "disable_animation") as? Bool)
+ ?? UIAccessibility.isReduceMotionEnabled
+ }
+
+func get_default_wallet(_ pubkey: String) -> Wallet {
+ if let defaultWalletName = UserDefaults.standard.string(forKey: "default_wallet"),
+ let default_wallet = Wallet(rawValue: defaultWalletName)
+ {
+ return default_wallet
+ } else {
+ return .system_default_wallet
+ }
+}
+
+func get_media_uploader(_ pubkey: String) -> MediaUploader {
+ if let defaultMediaUploader = UserDefaults.standard.string(forKey: "default_media_uploader"),
+ let defaultMediaUploader = MediaUploader(rawValue: defaultMediaUploader) {
+ return defaultMediaUploader
+ } else {
+ return .nostrBuild
+ }
+}
+
+private func get_translation_service(_ pubkey: String) -> TranslationService? {
+ guard let translation_service = UserDefaults.standard.string(forKey: "translation_service") else {
+ return nil
+ }
+
+ return TranslationService(rawValue: translation_service)
+}
+
+private func get_libretranslate_url(_ pubkey: String, server: LibreTranslateServer) -> String? {
+ if let url = server.model.url {
+ return url
+ }
+
+ return UserDefaults.standard.object(forKey: "libretranslate_url") as? String
+}
+
+private func get_libretranslate_server(_ pubkey: String) -> LibreTranslateServer? {
+ guard let server_name = UserDefaults.standard.string(forKey: "libretranslate_server") else {
+ return nil
+ }
+
+ return LibreTranslateServer(rawValue: server_name)
+}
diff --git a/damus/Models/Wallet.swift b/damus/Models/Wallet.swift
@@ -7,7 +7,7 @@
import Foundation
-enum Wallet: String, CaseIterable, Identifiable {
+enum Wallet: String, CaseIterable, Identifiable, StringCodable {
var id: String { self.rawValue }
struct Model: Identifiable, Hashable {
@@ -20,6 +20,17 @@ enum Wallet: String, CaseIterable, Identifiable {
var image: String
}
+ func to_string() -> String {
+ return rawValue
+ }
+
+ init?(from string: String) {
+ guard let w = Wallet(rawValue: string) else {
+ return nil
+ }
+ self = w
+ }
+
// New url prefixes needed to be added to LSApplicationQueriesSchemes
case system_default_wallet
case strike
diff --git a/damus/Util/StringCodable.swift b/damus/Util/StringCodable.swift
@@ -0,0 +1,13 @@
+//
+// StringCodable.swift
+// damus
+//
+// Created by William Casarin on 2023-04-21.
+//
+
+import Foundation
+
+protocol StringCodable {
+ init?(from string: String)
+ func to_string() -> String
+}
diff --git a/damus/Views/AttachMediaUtility.swift b/damus/Views/AttachMediaUtility.swift
@@ -89,10 +89,22 @@ extension NSMutableData {
}
}
-enum MediaUploader: String, CaseIterable, Identifiable {
+enum MediaUploader: String, CaseIterable, Identifiable, StringCodable {
var id: String { self.rawValue }
case nostrBuild
case nostrImg
+
+ init?(from string: String) {
+ guard let mu = MediaUploader(rawValue: string) else {
+ return nil
+ }
+
+ self = mu
+ }
+
+ func to_string() -> String {
+ return rawValue
+ }
var nameParam: String {
switch self {
diff --git a/damus/Views/Profile/ProfileView.swift b/damus/Views/Profile/ProfileView.swift
@@ -266,9 +266,9 @@ struct ProfileView: View {
} label: {
Label(addr, systemImage: "doc.on.doc")
}
- } else if let lnurl = profile.lud06 {
+ } else if let lnurl = profile.lnurl {
Button {
- UIPasteboard.general.string = profile.lnurl ?? ""
+ UIPasteboard.general.string = lnurl
} label: {
Label(NSLocalizedString("Copy LNURL", comment: "Context menu option for copying a user's Lightning URL."), systemImage: "doc.on.doc")
}