Tusker/Tusker/Screens/Preferences/Notifications/PushSubscriptionView.swift

77 lines
2.5 KiB
Swift

//
// PushSubscriptionView.swift
// Tusker
//
// Created by Shadowfacts on 4/7/24.
// Copyright © 2024 Shadowfacts. All rights reserved.
//
import SwiftUI
import UserAccounts
import PushNotifications
import TuskerComponents
struct PushSubscriptionView: View {
let account: UserAccountInfo
let subscription: PushSubscription?
let updateSubscription: (PushSubscription.Alerts, PushSubscription.Policy) async -> Void
var body: some View {
if let subscription {
PushSubscriptionSettingsView(account: account, subscription: subscription, updateSubscription: updateSubscription)
} else {
Text("No notifications")
.foregroundStyle(.secondary)
}
}
}
private struct PushSubscriptionSettingsView: View {
let account: UserAccountInfo
let subscription: PushSubscription
let updateSubscription: (PushSubscription.Alerts, PushSubscription.Policy) async -> Void
@State private var isLoading: [PushSubscription.Alerts: Bool] = [:]
init(account: UserAccountInfo, subscription: PushSubscription, updateSubscription: @escaping (PushSubscription.Alerts, PushSubscription.Policy) async -> Void) {
self.account = account
self.subscription = subscription
self.updateSubscription = updateSubscription
}
var body: some View {
VStack(alignment: .prefsAvatar) {
AsyncToggle("Mentions", mode: alertsBinding(for: .mention)) {
await onChange(alert: .mention, value: $0)
}
}
// this is the default value of the alignment guide, but this modifier is loading bearing
.alignmentGuide(.prefsAvatar, computeValue: { dimension in
dimension[.leading]
})
// otherwise the flexible view makes the containing stack extend under the edge of the list row
.padding(.leading, 38)
}
private func alertsBinding(for alert: PushSubscription.Alerts) -> Binding<AsyncToggle.Mode> {
return Binding {
isLoading[alert] == true ? .loading : subscription.alerts.contains(alert) ? .on : .off
} set: { newValue in
isLoading[alert] = newValue == .loading
}
}
private func onChange(alert: PushSubscription.Alerts, value: Bool) async {
var newAlerts = subscription.alerts
if value {
newAlerts.insert(alert)
} else {
newAlerts.remove(alert)
}
await updateSubscription(newAlerts, subscription.policy)
}
}
//#Preview {
// PushSubscriptionView()
//}