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

85 lines
3.1 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 -> Bool
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 -> Bool
@State private var isLoading: [PushSubscription.Alerts: Bool] = [:]
init(account: UserAccountInfo, subscription: PushSubscription, updateSubscription: @escaping (PushSubscription.Alerts, PushSubscription.Policy) async -> Bool) {
self.account = account
self.subscription = subscription
self.updateSubscription = updateSubscription
}
var body: some View {
VStack(alignment: .prefsAvatar) {
toggle("All", alert: [.mention, .favorite, .reblog, .follow, .followRequest, .poll, .update])
toggle("Mentions", alert: .mention)
toggle("Favorites", alert: .favorite)
toggle("Reblogs", alert: .reblog)
toggle("Follows", alert: [.follow, .followRequest])
toggle("Polls", alert: .poll)
toggle("Edits", alert: .update)
// status notifications not supported until we can enable/disable them in the app
}
// 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 toggle(_ titleKey: LocalizedStringKey, alert: PushSubscription.Alerts) -> some View {
let binding: Binding<AsyncToggle.Mode> = Binding {
isLoading[alert] == true ? .loading : subscription.alerts.contains(alert) ? .on : .off
} set: { newValue in
isLoading[alert] = newValue == .loading
}
return AsyncToggle(titleKey, mode: binding) {
return await updateSubscription(alert: alert, isOn: $0)
}
}
private func updateSubscription(alert: PushSubscription.Alerts, isOn: Bool) async -> Bool {
var newAlerts = subscription.alerts
if isOn {
newAlerts.insert(alert)
} else {
newAlerts.remove(alert)
}
return await updateSubscription(newAlerts, subscription.policy)
}
}
//#Preview {
// PushSubscriptionView()
//}