From 23f383a7f9accac6bdce1d8cc714000f4db27af9 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 2 Dec 2023 15:33:15 -0500 Subject: [PATCH] Get rid of network request during share extension launch Closes #438 --- .../UserAccounts/UserAccountInfo.swift | 45 ++++++++++++++++--- .../UserAccounts/UserAccountsManager.swift | 25 +++++------ ShareExtension/ShareViewController.swift | 10 ++--- Tusker/API/MastodonController.swift | 3 ++ 4 files changed, 56 insertions(+), 27 deletions(-) diff --git a/Packages/UserAccounts/Sources/UserAccounts/UserAccountInfo.swift b/Packages/UserAccounts/Sources/UserAccounts/UserAccountInfo.swift index 1565dc90..95c0134d 100644 --- a/Packages/UserAccounts/Sources/UserAccounts/UserAccountInfo.swift +++ b/Packages/UserAccounts/Sources/UserAccounts/UserAccountInfo.swift @@ -16,6 +16,11 @@ public struct UserAccountInfo: Equatable, Hashable, Identifiable { public private(set) var username: String! public let accessToken: String + // Sort of hack to be able to access these from the share extension. + public internal(set) var serverDefaultLanguage: String? + public internal(set) var serverDefaultVisibility: String? + public internal(set) var serverDefaultFederation: Bool? + fileprivate static let tempAccountID = "temp" static func id(instanceURL: URL, username: String?) -> String { @@ -47,21 +52,47 @@ public struct UserAccountInfo: Equatable, Hashable, Identifiable { self.accessToken = accessToken } - init?(userDefaultsDict dict: [String: String]) { - guard let id = dict["id"], - let instanceURL = dict["instanceURL"], + init?(userDefaultsDict dict: [String: Any]) { + guard let id = dict["id"] as? String, + let instanceURL = dict["instanceURL"] as? String, let url = URL(string: instanceURL), - let clientID = dict["clientID"], - let secret = dict["clientSecret"], - let accessToken = dict["accessToken"] else { + let clientID = dict["clientID"] as? String, + let secret = dict["clientSecret"] as? String, + let accessToken = dict["accessToken"] as? String else { return nil } self.id = id self.instanceURL = url self.clientID = clientID self.clientSecret = secret - self.username = dict["username"] + self.username = dict["username"] as? String self.accessToken = accessToken + self.serverDefaultLanguage = dict["serverDefaultLanguage"] as? String + self.serverDefaultVisibility = dict["serverDefaultVisibility"] as? String + self.serverDefaultFederation = dict["serverDefaultFederation"] as? Bool + } + + var userDefaultsDict: [String: Any] { + var dict: [String: Any] = [ + "id": id, + "instanceURL": instanceURL.absoluteString, + "clientID": clientID, + "clientSecret": clientSecret, + "accessToken": accessToken, + ] + if let username { + dict["username"] = username + } + if let serverDefaultLanguage { + dict["serverDefaultLanguage"] = serverDefaultLanguage + } + if let serverDefaultVisibility { + dict["serverDefaultVisibility"] = serverDefaultVisibility + } + if let serverDefaultFederation { + dict["serverDefaultFederation"] = serverDefaultFederation + } + return dict } /// A filename-safe string for this account diff --git a/Packages/UserAccounts/Sources/UserAccounts/UserAccountsManager.swift b/Packages/UserAccounts/Sources/UserAccounts/UserAccountsManager.swift index e69973ae..d5752409 100644 --- a/Packages/UserAccounts/Sources/UserAccounts/UserAccountsManager.swift +++ b/Packages/UserAccounts/Sources/UserAccounts/UserAccountsManager.swift @@ -46,19 +46,7 @@ public class UserAccountsManager: ObservableObject { } set { objectWillChange.send() - let array = newValue.map { (info) -> [String: String] in - var res = [ - "id": info.id, - "instanceURL": info.instanceURL.absoluteString, - "clientID": info.clientID, - "clientSecret": info.clientSecret, - "accessToken": info.accessToken - ] - if let username = info.username { - res["username"] = username - } - return res - } + let array = newValue.map(\.userDefaultsDict) defaults.set(array, forKey: accountsKey) } } @@ -146,6 +134,17 @@ public class UserAccountsManager: ObservableObject { public func setMostRecentAccount(_ account: UserAccountInfo?) { mostRecentAccountID = account?.id } + + public func updateServerPreferences(_ account: UserAccountInfo, defaultLanguage: String?, defaultVisibility: String?, defaultFederation: Bool?) { + guard let index = accounts.firstIndex(where: { $0.id == account.id }) else { + return + } + var account = account + account.serverDefaultLanguage = defaultLanguage + account.serverDefaultVisibility = defaultVisibility + account.serverDefaultFederation = defaultFederation + accounts[index] = account + } } diff --git a/ShareExtension/ShareViewController.swift b/ShareExtension/ShareViewController.swift index 8deb9778..1f5bb3ec 100644 --- a/ShareExtension/ShareViewController.swift +++ b/ShareExtension/ShareViewController.swift @@ -53,18 +53,14 @@ class ShareViewController: UIViewController { private func createDraft(account: UserAccountInfo) async -> Draft { async let (text, attachments) = getDraftConfigurationFromExtensionContext() - // TODO: I really don't like that there's a network request in the hot path here, but we don't have easy access to AccountPreferences :/ - let serverPrefs = try? await Client(baseURL: account.instanceURL, accessToken: account.accessToken).run(Client.getPreferences()).0 - let visibility = Preferences.shared.defaultPostVisibility.resolved(withServerDefault: serverPrefs?.postingDefaultVisibility) - let draft = DraftsPersistentContainer.shared.createDraft( accountID: account.id, text: await text, contentWarning: "", inReplyToID: nil, - visibility: visibility, - language: serverPrefs?.postingDefaultLanguage, - localOnly: !(serverPrefs?.postingDefaultFederation ?? true) + visibility: Preferences.shared.defaultPostVisibility.resolved(withServerDefault: account.serverDefaultVisibility.flatMap(Visibility.init(rawValue:))), + language: account.serverDefaultLanguage, + localOnly: !(account.serverDefaultFederation ?? true) ) for attachment in await attachments { diff --git a/Tusker/API/MastodonController.swift b/Tusker/API/MastodonController.swift index 1adf417e..d80bbcfa 100644 --- a/Tusker/API/MastodonController.swift +++ b/Tusker/API/MastodonController.swift @@ -371,6 +371,9 @@ class MastodonController: ObservableObject { accountPreferences!.serverDefaultLanguage = prefs.postingDefaultLanguage accountPreferences!.serverDefaultVisibility = prefs.postingDefaultVisibility accountPreferences!.serverDefaultFederation = prefs.postingDefaultFederation ?? true + if let accountInfo { + UserAccountsManager.shared.updateServerPreferences(accountInfo, defaultLanguage: prefs.postingDefaultLanguage, defaultVisibility: prefs.postingDefaultVisibility.rawValue, defaultFederation: prefs.postingDefaultFederation) + } } private func updateActiveInstance(from instance: Instance) {