Allow viewing registered device tokens

This commit is contained in:
Jackson Harper 2022-12-09 18:50:30 +08:00
parent 0ae690f13f
commit 340623a57c
4 changed files with 153 additions and 1 deletions

View file

@ -0,0 +1,82 @@
import Models
import Services
import SwiftUI
import Utils
import Views
@MainActor final class PushNotificationDevicesViewModel: ObservableObject {
@Published var isLoading = false
@Published var devices = [InternalDeviceToken]()
func loadDevices(dataService: DataService) {
isLoading = true
Task {
self.devices = (try? await dataService.devices()) ?? []
isLoading = false
}
}
func removeToken(dataService: DataService, tokenID: String) {
if let idx = devices.firstIndex(where: { $0.id == tokenID }) {
Task {
try await dataService.syncDeviceToken(deviceTokenOperation: .deleteToken(tokenID: tokenID))
devices.remove(at: idx)
}
}
}
}
struct PushNotificationDevicesView: View {
@EnvironmentObject var dataService: DataService
@StateObject var viewModel = PushNotificationDevicesViewModel()
var body: some View {
Group {
#if os(iOS)
Form {
innerBody
}
#elseif os(macOS)
List {
innerBody
}
.listStyle(InsetListStyle())
#endif
}
.task { viewModel.loadDevices(dataService: dataService) }
}
func createdStr(_ device: InternalDeviceToken) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .short
if let createdAt = device.createdAt {
return dateFormatter.string(from: createdAt)
}
return ""
}
private var innerBody: some View {
List {
Section(header: Text("Registered device tokens (swipe to remove)")) {
ForEach(viewModel.devices) { device in
Text("Created: \(createdStr(device))")
.swipeActions(edge: .trailing) {
Button(
role: .destructive,
action: {
viewModel.removeToken(dataService: dataService, tokenID: device.id)
},
label: {
Image(systemName: "trash")
}
)
}
}
}
}
.navigationTitle("Devices")
}
}

View file

@ -28,7 +28,8 @@ import Views
self.desiredNotificationsEnabled = granted
Task {
if let savedToken = UserDefaults.standard.string(forKey: UserDefaultKey.firebasePushToken.rawValue) {
try? await dataService.syncDeviceToken(deviceTokenOperation: DeviceTokenOperation.addToken(token: savedToken))
try? await dataService.syncDeviceToken(
deviceTokenOperation: DeviceTokenOperation.addToken(token: savedToken))
}
NotificationCenter.default.post(name: Notification.Name("ReconfigurePushNotifications"), object: nil)
}
@ -83,6 +84,12 @@ struct PushNotificationSettingsView: View {
""")
.accentColor(.blue)
}
Section {
NavigationLink("Devices") {
PushNotificationDevicesView()
}
}
}
.navigationTitle("Push Notifications")
}

View file

@ -0,0 +1,55 @@
import CoreData
import Foundation
import Models
import SwiftGraphQL
public extension DataService {
func devices() async throws -> [InternalDeviceToken] {
enum QueryResult {
case success(result: [InternalDeviceToken])
case error(error: String)
}
let deviceTokensSelection = Selection.DeviceToken {
InternalDeviceToken(
id: try $0.id(),
createdAt: try $0.createdAt().value
)
}
let selection = Selection<QueryResult, Unions.DeviceTokensResult> {
try $0.on(
deviceTokensError: .init {
QueryResult.error(error: try $0.errorCodes().description)
},
deviceTokensSuccess: .init {
QueryResult.success(result: try $0.deviceTokens(selection: deviceTokensSelection.list))
}
)
}
let query = Selection.Query {
try $0.deviceTokens(selection: selection)
}
let path = appEnvironment.graphqlPath
let headers = networker.defaultHeaders
let context = backgroundContext
return try await withCheckedThrowingContinuation { continuation in
send(query, to: path, headers: headers) { queryResult in
guard let payload = try? queryResult.get() else {
continuation.resume(throwing: BasicError.message(messageText: "network request failed"))
return
}
switch payload.data {
case let .success(result: result):
continuation.resume(returning: result)
case .error:
continuation.resume(throwing: BasicError.message(messageText: "DeviceToken Email fetch error"))
}
}
}
}
}

View file

@ -0,0 +1,8 @@
import CoreData
import Foundation
import Models
public struct InternalDeviceToken: Identifiable {
public let id: String
public let createdAt: Date?
}