Notificatio navigation wip

This commit is contained in:
Justin Mazzocchi 2021-02-04 00:30:37 -08:00
parent aea6030d43
commit 03b17d21ee
No known key found for this signature in database
GPG Key ID: E223E6937AAFB01C
5 changed files with 48 additions and 27 deletions

View File

@ -39,6 +39,7 @@ final class NotificationService: UNNotificationServiceExtension {
return
}
bestAttemptContent.userInfo[PushNotificationParsingService.pushNotificationUserInfoKey] = decryptedJSON
bestAttemptContent.title = pushNotification.title
bestAttemptContent.body = XMLUnescaper(string: pushNotification.body).unescape()

View File

@ -19,6 +19,9 @@ public struct PushNotificationParsingService {
}
public extension PushNotificationParsingService {
static let identityIdUserInfoKey = "i"
static let pushNotificationUserInfoKey = "com.metabolist.metatext.push-notification-user-info-key"
func extractAndDecrypt(userInfo: [AnyHashable: Any]) throws -> (Data, Identity.Id) {
guard let identityIdString = userInfo[Self.identityIdUserInfoKey] as? String,
let identityId = Identity.Id(uuidString: identityIdString),
@ -48,7 +51,6 @@ public extension PushNotificationParsingService {
}
private extension PushNotificationParsingService {
static let identityIdUserInfoKey = "i"
static let encryptedMessageUserInfoKey = "m"
static let saltUserInfoKey = "s"
static let serverPublicKeyUserInfoKey = "k"

View File

@ -9,28 +9,27 @@ import ViewModels
@main
struct MetatextApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
private let environment = AppEnvironment.live(
userNotificationCenter: .current(),
reduceMotion: { UIAccessibility.isReduceMotionEnabled })
// swiftlint:disable:next force_try
private let viewModel = try! RootViewModel(environment: Self.environment)
init() {
try? AVAudioSession.sharedInstance().setCategory(.ambient, mode: .default)
try? ImageCacheConfiguration(environment: environment).configure()
try? ImageCacheConfiguration(environment: Self.environment).configure()
}
var body: some Scene {
WindowGroup {
RootView(
// swiftlint:disable force_try
viewModel: try! RootViewModel(
environment: environment,
registerForRemoteNotifications: appDelegate.registerForRemoteNotifications))
// swiftlint:enable force_try
viewModel.registerForRemoteNotifications = appDelegate.registerForRemoteNotifications
return WindowGroup {
RootView(viewModel: viewModel)
}
}
}
private extension MetatextApp {
static let environment = AppEnvironment.live(
userNotificationCenter: .current(),
reduceMotion: { UIAccessibility.isReduceMotionEnabled })
static let imageCacheName = "Images"
static let imageCacheDirectoryURL = FileManager.default.containerURL(
forSecurityApplicationGroupIdentifier: AppEnvironment.appGroup)?

View File

@ -70,7 +70,7 @@ public extension Instance {
}
public extension RootViewModel {
static let preview = try! RootViewModel(environment: environment) { Empty().eraseToAnyPublisher() }
static let preview = try! RootViewModel(environment: environment)
}
public extension IdentityContext {

View File

@ -7,20 +7,30 @@ import ServiceLayer
public final class RootViewModel: ObservableObject {
@Published public private(set) var navigationViewModel: NavigationViewModel?
public var registerForRemoteNotifications: (() -> AnyPublisher<Data, Error>)? {
didSet {
guard let registerForRemoteNotifications = registerForRemoteNotifications else { return }
userNotificationService.isAuthorized(request: false)
.filter { $0 }
.zip(registerForRemoteNotifications())
.map { $1 }
.flatMap(allIdentitiesService.updatePushSubscriptions(deviceToken:))
.sink { _ in } receiveValue: { _ in }
.store(in: &cancellables)
}
}
@Published private var mostRecentlyUsedIdentityId: Identity.Id?
private let environment: AppEnvironment
private let allIdentitiesService: AllIdentitiesService
private let userNotificationService: UserNotificationService
private let registerForRemoteNotifications: () -> AnyPublisher<Data, Error>
private var cancellables = Set<AnyCancellable>()
public init(environment: AppEnvironment,
registerForRemoteNotifications: @escaping () -> AnyPublisher<Data, Error>) throws {
public init(environment: AppEnvironment) throws {
self.environment = environment
allIdentitiesService = try AllIdentitiesService(environment: environment)
userNotificationService = UserNotificationService(environment: environment)
self.registerForRemoteNotifications = registerForRemoteNotifications
allIdentitiesService.immediateMostRecentlyUsedIdentityIdPublisher()
.replaceError(with: nil)
@ -32,14 +42,6 @@ public final class RootViewModel: ObservableObject {
.sink { [weak self] in self?.identitySelected(id: $0) }
.store(in: &cancellables)
userNotificationService.isAuthorized(request: false)
.filter { $0 }
.zip(registerForRemoteNotifications())
.map { $1 }
.flatMap(allIdentitiesService.updatePushSubscriptions(deviceToken:))
.sink { _ in } receiveValue: { _ in }
.store(in: &cancellables)
userNotificationService.events
.sink { [weak self] in self?.handle(event: $0) }
.store(in: &cancellables)
@ -116,10 +118,12 @@ private extension RootViewModel {
.sink { _ in } receiveValue: { _ in }
.store(in: &self.cancellables)
if identityContext.identity.authenticated && !identityContext.identity.pending {
if identityContext.identity.authenticated,
!identityContext.identity.pending,
let registerForRemoteNotifications = self.registerForRemoteNotifications {
self.userNotificationService.isAuthorized(request: true)
.filter { $0 }
.zip(self.registerForRemoteNotifications())
.zip(registerForRemoteNotifications())
.filter { identityContext.identity.lastRegisteredDeviceToken != $1 }
.map { ($1, identityContext.identity.pushSubscriptionAlerts) }
.flatMap(identityContext.service.createPushSubscription(deviceToken:alerts:))
@ -136,8 +140,23 @@ private extension RootViewModel {
switch event {
case let .willPresentNotification(_, completionHandler):
completionHandler(.banner)
case let .didReceiveResponse(response, completionHandler):
let userInfo = response.notification.request.content.userInfo
if let identityIdString = userInfo[PushNotificationParsingService.identityIdUserInfoKey] as? String,
let identityId = Identity.Id(uuidString: identityIdString),
let pushNotificationJSON = userInfo[PushNotificationParsingService.pushNotificationUserInfoKey] as? Data,
let pushNotification = try? MastodonDecoder().decode(PushNotification.self, from: pushNotificationJSON) {
handle(pushNotification: pushNotification, identityId: identityId)
}
completionHandler()
default:
break
}
}
func handle(pushNotification: PushNotification, identityId: Identity.Id) {
// TODO
}
}