130 lines
3.8 KiB
Swift
130 lines
3.8 KiB
Swift
//
|
|
// NotificationsPrefsView.swift
|
|
// Tusker
|
|
//
|
|
// Created by Shadowfacts on 4/6/24.
|
|
// Copyright © 2024 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
import UserNotifications
|
|
|
|
struct NotificationsPrefsView: View {
|
|
@State private var error: NotificationsSetupError?
|
|
@State private var isSetup = false
|
|
@State private var working = false
|
|
@State private var pushProxyRegistration: PushProxyRegistration?
|
|
|
|
var body: some View {
|
|
List {
|
|
enableSection
|
|
}
|
|
.listStyle(.insetGrouped)
|
|
.appGroupedListBackground(container: PreferencesNavigationController.self)
|
|
.navigationTitle("Notifications")
|
|
}
|
|
|
|
private var enableSection: some View {
|
|
Section {
|
|
HStack {
|
|
Text("Push Notifications")
|
|
|
|
Spacer()
|
|
|
|
if working {
|
|
ProgressView()
|
|
} else {
|
|
Toggle("Push Notifications Enabled", isOn: Binding(get: {
|
|
isSetup
|
|
}, set: { newValue in
|
|
isSetup = newValue
|
|
isSetupChanged(newValue: newValue)
|
|
}))
|
|
.labelsHidden()
|
|
}
|
|
}
|
|
}
|
|
.alertWithData("An Error Occurred", data: $error) { error in
|
|
Button("OK") {}
|
|
} message: { error in
|
|
Text(error.localizedDescription)
|
|
}
|
|
.task { @MainActor in
|
|
pushProxyRegistration = PushManager.shared.pushProxyRegistration
|
|
isSetup = pushProxyRegistration != nil
|
|
if !UIApplication.shared.isRegisteredForRemoteNotifications {
|
|
_ = await registerForRemoteNotifications()
|
|
}
|
|
}
|
|
}
|
|
|
|
private func isSetupChanged(newValue: Bool) {
|
|
working = true
|
|
Task {
|
|
defer {
|
|
working = false
|
|
}
|
|
let success = if newValue {
|
|
await startRegistration()
|
|
} else {
|
|
await unregister()
|
|
}
|
|
if !success {
|
|
isSetup = !newValue
|
|
}
|
|
}
|
|
}
|
|
|
|
private func startRegistration() async -> Bool {
|
|
let authorized: Bool
|
|
do {
|
|
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)"
|
|
}
|
|
}
|
|
}
|