Route to push notifications on selection

This commit is contained in:
Thomas Ricouard 2023-02-13 21:50:44 +01:00
parent 6fbe56ce15
commit 90199fc88b
3 changed files with 56 additions and 3 deletions

View File

@ -19,6 +19,7 @@ struct IceCubesApp: App {
@StateObject private var currentInstance = CurrentInstance.shared
@StateObject private var currentAccount = CurrentAccount.shared
@StateObject private var userPreferences = UserPreferences.shared
@StateObject private var pushNotificationsService = PushNotificationsService.shared
@StateObject private var watcher = StreamWatcher()
@StateObject private var quickLook = QuickLook()
@StateObject private var theme = Theme.shared
@ -50,12 +51,18 @@ struct IceCubesApp: App {
.environmentObject(userPreferences)
.environmentObject(theme)
.environmentObject(watcher)
.environmentObject(PushNotificationsService.shared)
.environmentObject(pushNotificationsService)
.fullScreenCover(item: $quickLook.url, content: { url in
QuickLookPreview(selectedURL: url, urls: quickLook.urls)
.edgesIgnoringSafeArea(.bottom)
.background(TransparentBackground())
})
.onChange(of: pushNotificationsService.routedNotification) { notification in
if notification != nil {
pushNotificationsService.routedNotification = nil
selectedTab = .notifications
}
}
}
.commands {
appMenu

View File

@ -17,6 +17,7 @@ struct NotificationsTab: View {
@EnvironmentObject private var appAccount: AppAccountsManager
@EnvironmentObject private var currentAccount: CurrentAccount
@EnvironmentObject private var userPreferences: UserPreferences
@EnvironmentObject private var pushNotificationsService: PushNotificationsService
@StateObject private var routerPath = RouterPath()
@Binding var popToRootTab: Tab
@ -53,6 +54,17 @@ struct NotificationsTab: View {
routerPath.path = []
}
}
.onChange(of: pushNotificationsService.routedNotification) { notification in
if let notification {
DispatchQueue.main.async {
if let account = notification.accountId {
routerPath.navigate(to: .accountDetail(id: account))
} else if let status = notification.statusId {
routerPath.navigate(to: .statusDetail(id: status))
}
}
}
}
.onChange(of: scenePhase, perform: { scenePhase in
switch scenePhase {
case .active:

View File

@ -19,19 +19,32 @@ public struct PushAccount {
}
@MainActor
public class PushNotificationsService: ObservableObject {
public class PushNotificationsService: NSObject, ObservableObject {
enum Constants {
static let endpoint = "https://icecubesrelay.fly.dev"
static let keychainAuthKey = "notifications_auth_key"
static let keychainPrivateKey = "notifications_private_key"
}
public struct RoutedNotification: Equatable {
public let accessToken: String
public let statusId: String?
public let accountId: String?
}
public static let shared = PushNotificationsService()
public private(set) var subscriptions: [PushNotificationSubscriptionSettings] = []
@Published public var pushToken: Data?
@Published public var routedNotification: RoutedNotification?
override init() {
super.init()
UNUserNotificationCenter.current().delegate = self
}
private var keychain: KeychainSwift {
let keychain = KeychainSwift()
#if !DEBUG && !targetEnvironment(simulator)
@ -121,6 +134,27 @@ public class PushNotificationsService: ObservableObject {
}
}
extension PushNotificationsService: UNUserNotificationCenterDelegate {
public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async {
guard let plaintext = response.notification.request.content.userInfo["plaintext"] as? Data,
let mastodonPushNotification = try? JSONDecoder().decode(MastodonPushNotification.self, from: plaintext) else {
return
}
if let type = Models.Notification.NotificationType(rawValue: mastodonPushNotification.notificationType) {
switch type {
case .follow, .follow_request:
self.routedNotification = .init(accessToken: mastodonPushNotification.accessToken,
statusId: nil,
accountId: String(mastodonPushNotification.notificationID))
default:
self.routedNotification = .init(accessToken: mastodonPushNotification.accessToken,
statusId: String(mastodonPushNotification.notificationID),
accountId: nil)
}
}
}
}
extension Data {
var hexString: String {
return map { String(format: "%02.2hhx", arguments: [$0]) }.joined()