2024-04-07 18:04:42 +00:00
|
|
|
//
|
|
|
|
// NotificationsPrefsView.swift
|
|
|
|
// Tusker
|
|
|
|
//
|
|
|
|
// Created by Shadowfacts on 4/6/24.
|
|
|
|
// Copyright © 2024 Shadowfacts. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import SwiftUI
|
|
|
|
import UserNotifications
|
2024-04-07 19:49:12 +00:00
|
|
|
import UserAccounts
|
2024-04-08 13:48:40 +00:00
|
|
|
import PushNotifications
|
2024-04-08 22:45:54 +00:00
|
|
|
import TuskerComponents
|
2024-04-07 18:04:42 +00:00
|
|
|
|
|
|
|
struct NotificationsPrefsView: View {
|
|
|
|
@State private var error: NotificationsSetupError?
|
2024-04-08 22:45:54 +00:00
|
|
|
@State private var isSetup = AsyncToggle.Mode.off
|
2024-04-07 18:04:42 +00:00
|
|
|
@State private var pushProxyRegistration: PushProxyRegistration?
|
2024-04-07 19:49:12 +00:00
|
|
|
@ObservedObject private var userAccounts = UserAccountsManager.shared
|
2024-04-07 18:04:42 +00:00
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
List {
|
|
|
|
enableSection
|
2024-04-08 13:48:40 +00:00
|
|
|
if isSetup == .on,
|
|
|
|
let pushProxyRegistration {
|
|
|
|
accountsSection(pushProxyRegistration: pushProxyRegistration)
|
2024-04-07 19:49:12 +00:00
|
|
|
}
|
2024-04-07 18:04:42 +00:00
|
|
|
}
|
|
|
|
.listStyle(.insetGrouped)
|
|
|
|
.appGroupedListBackground(container: PreferencesNavigationController.self)
|
|
|
|
.navigationTitle("Notifications")
|
|
|
|
}
|
|
|
|
|
|
|
|
private var enableSection: some View {
|
|
|
|
Section {
|
2024-04-08 22:45:54 +00:00
|
|
|
AsyncToggle("Push Notifications", mode: $isSetup, onChange: isSetupChanged(newValue:))
|
2024-04-07 18:04:42 +00:00
|
|
|
}
|
2024-04-07 19:49:12 +00:00
|
|
|
.appGroupedListRowBackground()
|
2024-04-07 18:04:42 +00:00
|
|
|
.alertWithData("An Error Occurred", data: $error) { error in
|
|
|
|
Button("OK") {}
|
|
|
|
} message: { error in
|
|
|
|
Text(error.localizedDescription)
|
|
|
|
}
|
|
|
|
.task { @MainActor in
|
2024-04-09 16:35:51 +00:00
|
|
|
pushProxyRegistration = PushManager.shared.proxyRegistration
|
2024-04-07 19:49:12 +00:00
|
|
|
isSetup = pushProxyRegistration != nil ? .on : .off
|
2024-04-07 18:04:42 +00:00
|
|
|
if !UIApplication.shared.isRegisteredForRemoteNotifications {
|
|
|
|
_ = await registerForRemoteNotifications()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-08 13:48:40 +00:00
|
|
|
private func accountsSection(pushProxyRegistration: PushProxyRegistration) -> some View {
|
2024-04-07 19:49:12 +00:00
|
|
|
Section {
|
|
|
|
ForEach(userAccounts.accounts) { account in
|
2024-04-08 13:48:40 +00:00
|
|
|
PushInstanceSettingsView(account: account, pushProxyRegistration: pushProxyRegistration)
|
2024-04-07 18:04:42 +00:00
|
|
|
}
|
2024-04-07 19:49:12 +00:00
|
|
|
}
|
|
|
|
.appGroupedListRowBackground()
|
|
|
|
}
|
|
|
|
|
2024-04-09 15:49:03 +00:00
|
|
|
private func isSetupChanged(newValue: Bool) async -> Bool {
|
2024-04-07 19:49:12 +00:00
|
|
|
if newValue {
|
2024-04-09 15:49:03 +00:00
|
|
|
return await startRegistration()
|
2024-04-07 19:49:12 +00:00
|
|
|
} else {
|
2024-04-09 15:49:03 +00:00
|
|
|
return await unregister()
|
2024-04-07 18:04:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private func startRegistration() async -> Bool {
|
|
|
|
let authorized: Bool
|
|
|
|
do {
|
2024-04-10 23:13:47 +00:00
|
|
|
// TODO: support .providesAppNotificationSettings
|
2024-04-07 18:04:42 +00:00
|
|
|
authorized = try await UNUserNotificationCenter.current().requestAuthorization(options: [.alert])
|
|
|
|
} catch {
|
|
|
|
self.error = .requestingAuthorization(error)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
guard authorized else {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return await registerForRemoteNotifications()
|
|
|
|
}
|
|
|
|
|
|
|
|
private func registerForRemoteNotifications() async -> Bool {
|
|
|
|
do {
|
|
|
|
pushProxyRegistration = try await PushManager.shared.register(transactionID: 0)
|
|
|
|
return true
|
|
|
|
} catch {
|
|
|
|
self.error = .registering(error)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private func unregister() async -> Bool {
|
|
|
|
do {
|
|
|
|
try await PushManager.shared.unregister()
|
|
|
|
pushProxyRegistration = nil
|
|
|
|
return true
|
|
|
|
} catch {
|
|
|
|
self.error = .unregistering(error)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private enum NotificationsSetupError: LocalizedError {
|
|
|
|
case requestingAuthorization(any Error)
|
|
|
|
case registering(any Error)
|
|
|
|
case unregistering(any Error)
|
|
|
|
|
|
|
|
var errorDescription: String? {
|
|
|
|
switch self {
|
|
|
|
case .requestingAuthorization(let error):
|
|
|
|
"Notifications authorization request failed: \(error.localizedDescription)"
|
|
|
|
case .registering(let error):
|
|
|
|
"Registration failed: \(error.localizedDescription)"
|
|
|
|
case .unregistering(let error):
|
|
|
|
"Deactivation failed: \(error.localizedDescription)"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|