Improve AsyncToggle behavior on failure

This commit is contained in:
Shadowfacts 2024-04-09 11:49:03 -04:00
parent 42a3f6c880
commit e150856e91
4 changed files with 25 additions and 22 deletions

View File

@ -13,9 +13,9 @@ public struct AsyncToggle: View {
@available(iOS, obsoleted: 16.0, message: "Switch to LabeledContent") @available(iOS, obsoleted: 16.0, message: "Switch to LabeledContent")
let labelHidden: Bool let labelHidden: Bool
@Binding var mode: Mode @Binding var mode: Mode
let onChange: (Bool) async -> Void let onChange: (Bool) async -> Bool
public init(_ titleKey: LocalizedStringKey, labelHidden: Bool = false, mode: Binding<Mode>, onChange: @escaping (Bool) async -> Void) { public init(_ titleKey: LocalizedStringKey, labelHidden: Bool = false, mode: Binding<Mode>, onChange: @escaping (Bool) async -> Bool) {
self.titleKey = titleKey self.titleKey = titleKey
self.labelHidden = labelHidden self.labelHidden = labelHidden
self._mode = mode self._mode = mode
@ -46,8 +46,12 @@ public struct AsyncToggle: View {
} set: { newValue in } set: { newValue in
mode = .loading mode = .loading
Task { Task {
await onChange(newValue) let operationCompleted = await onChange(newValue)
if operationCompleted {
mode = newValue ? .on : .off mode = newValue ? .on : .off
} else {
mode = newValue ? .off : .on
}
} }
}) })
.labelsHidden() .labelsHidden()
@ -70,5 +74,6 @@ public struct AsyncToggle: View {
@State var mode = AsyncToggle.Mode.on @State var mode = AsyncToggle.Mode.on
return AsyncToggle("", mode: $mode) { _ in return AsyncToggle("", mode: $mode) { _ in
try! await Task.sleep(nanoseconds: NSEC_PER_SEC) try! await Task.sleep(nanoseconds: NSEC_PER_SEC)
return true
} }
} }

View File

@ -59,17 +59,11 @@ struct NotificationsPrefsView: View {
.appGroupedListRowBackground() .appGroupedListRowBackground()
} }
private func isSetupChanged(newValue: Bool) async { private func isSetupChanged(newValue: Bool) async -> Bool {
if newValue { if newValue {
let success = await startRegistration() return await startRegistration()
if !success {
isSetup = .off
}
} else { } else {
let success = await unregister() return await unregister()
if !success {
isSetup = .on
}
} }
} }

View File

@ -45,13 +45,14 @@ struct PushInstanceSettingsView: View {
} }
} }
private func updateNotificationsEnabled(enabled: Bool) async { private func updateNotificationsEnabled(enabled: Bool) async -> Bool {
if enabled { if enabled {
do { do {
try await enableNotifications() try await enableNotifications()
} catch { } catch {
PushManager.logger.error("Error creating instance subscription: \(String(describing: error))") PushManager.logger.error("Error creating instance subscription: \(String(describing: error))")
self.error = .enabling(error) self.error = .enabling(error)
return false
} }
} else { } else {
do { do {
@ -59,8 +60,10 @@ struct PushInstanceSettingsView: View {
} catch { } catch {
PushManager.logger.error("Error removing instance subscription: \(String(describing: error))") PushManager.logger.error("Error removing instance subscription: \(String(describing: error))")
self.error = .disabling(error) self.error = .disabling(error)
return false
} }
} }
return true
} }
private func enableNotifications() async throws { private func enableNotifications() async throws {
@ -96,8 +99,7 @@ struct PushInstanceSettingsView: View {
PushManager.logger.debug("Push subscription removed on \(account.instanceURL)") PushManager.logger.debug("Push subscription removed on \(account.instanceURL)")
} }
private func updateSubscription(alerts: PushNotifications.PushSubscription.Alerts, policy: PushNotifications.PushSubscription.Policy) async { private func updateSubscription(alerts: PushNotifications.PushSubscription.Alerts, policy: PushNotifications.PushSubscription.Policy) async -> Bool {
try! await Task.sleep(nanoseconds: NSEC_PER_SEC)
let req = Pachyderm.PushSubscription.update(alerts: .init(alerts), policy: .init(policy)) let req = Pachyderm.PushSubscription.update(alerts: .init(alerts), policy: .init(policy))
let mastodonController = await MastodonController.getForAccount(account) let mastodonController = await MastodonController.getForAccount(account)
do { do {
@ -105,9 +107,11 @@ struct PushInstanceSettingsView: View {
PushManager.logger.debug("Push subscription \(result.id) updated on \(account.instanceURL)") PushManager.logger.debug("Push subscription \(result.id) updated on \(account.instanceURL)")
subscription?.alerts = alerts subscription?.alerts = alerts
subscription?.policy = policy subscription?.policy = policy
return true
} catch { } catch {
PushManager.logger.error("Error updating subscription: \(String(describing: error))") PushManager.logger.error("Error updating subscription: \(String(describing: error))")
self.error = .updating(error) self.error = .updating(error)
return false
} }
} }
} }

View File

@ -14,7 +14,7 @@ import TuskerComponents
struct PushSubscriptionView: View { struct PushSubscriptionView: View {
let account: UserAccountInfo let account: UserAccountInfo
let subscription: PushSubscription? let subscription: PushSubscription?
let updateSubscription: (PushSubscription.Alerts, PushSubscription.Policy) async -> Void let updateSubscription: (PushSubscription.Alerts, PushSubscription.Policy) async -> Bool
var body: some View { var body: some View {
if let subscription { if let subscription {
@ -29,10 +29,10 @@ struct PushSubscriptionView: View {
private struct PushSubscriptionSettingsView: View { private struct PushSubscriptionSettingsView: View {
let account: UserAccountInfo let account: UserAccountInfo
let subscription: PushSubscription let subscription: PushSubscription
let updateSubscription: (PushSubscription.Alerts, PushSubscription.Policy) async -> Void let updateSubscription: (PushSubscription.Alerts, PushSubscription.Policy) async -> Bool
@State private var isLoading: [PushSubscription.Alerts: Bool] = [:] @State private var isLoading: [PushSubscription.Alerts: Bool] = [:]
init(account: UserAccountInfo, subscription: PushSubscription, updateSubscription: @escaping (PushSubscription.Alerts, PushSubscription.Policy) async -> Void) { init(account: UserAccountInfo, subscription: PushSubscription, updateSubscription: @escaping (PushSubscription.Alerts, PushSubscription.Policy) async -> Bool) {
self.account = account self.account = account
self.subscription = subscription self.subscription = subscription
self.updateSubscription = updateSubscription self.updateSubscription = updateSubscription
@ -64,18 +64,18 @@ private struct PushSubscriptionSettingsView: View {
isLoading[alert] = newValue == .loading isLoading[alert] = newValue == .loading
} }
return AsyncToggle(titleKey, mode: binding) { return AsyncToggle(titleKey, mode: binding) {
await updateSubscription(alert: alert, isOn: $0) return await updateSubscription(alert: alert, isOn: $0)
} }
} }
private func updateSubscription(alert: PushSubscription.Alerts, isOn: Bool) async { private func updateSubscription(alert: PushSubscription.Alerts, isOn: Bool) async -> Bool {
var newAlerts = subscription.alerts var newAlerts = subscription.alerts
if isOn { if isOn {
newAlerts.insert(alert) newAlerts.insert(alert)
} else { } else {
newAlerts.remove(alert) newAlerts.remove(alert)
} }
await updateSubscription(newAlerts, subscription.policy) return await updateSubscription(newAlerts, subscription.policy)
} }
} }