metatext/ViewModels/Sources/ViewModels/RootViewModel.swift

120 lines
4.5 KiB
Swift
Raw Normal View History

2020-08-03 15:20:51 +00:00
// Copyright © 2020 Metabolist. All rights reserved.
import Combine
2020-09-05 02:31:43 +00:00
import Foundation
2020-08-31 18:57:02 +00:00
import ServiceLayer
2020-08-03 15:20:51 +00:00
2020-09-01 07:33:49 +00:00
public final class RootViewModel: ObservableObject {
2020-09-09 23:00:10 +00:00
@Published public private(set) var navigationViewModel: NavigationViewModel?
2020-08-09 05:37:04 +00:00
2020-10-05 22:50:05 +00:00
@Published private var mostRecentlyUsedIdentityId: Identity.Id?
2020-09-09 06:17:35 +00:00
private let environment: AppEnvironment
2020-08-26 21:35:06 +00:00
private let allIdentitiesService: AllIdentitiesService
private let userNotificationService: UserNotificationService
2020-09-06 21:37:54 +00:00
private let registerForRemoteNotifications: () -> AnyPublisher<Data, Error>
2020-08-03 15:20:51 +00:00
private var cancellables = Set<AnyCancellable>()
2020-09-01 07:33:49 +00:00
public init(environment: AppEnvironment,
2020-09-06 21:37:54 +00:00
registerForRemoteNotifications: @escaping () -> AnyPublisher<Data, Error>) throws {
2020-09-09 06:17:35 +00:00
self.environment = environment
2020-09-01 07:33:49 +00:00
allIdentitiesService = try AllIdentitiesService(environment: environment)
userNotificationService = UserNotificationService(environment: environment)
self.registerForRemoteNotifications = registerForRemoteNotifications
2020-08-09 05:37:04 +00:00
2020-10-06 20:44:22 +00:00
allIdentitiesService.immediateMostRecentlyUsedIdentityIdPublisher()
2020-09-09 12:05:43 +00:00
.replaceError(with: nil)
2020-10-05 22:50:05 +00:00
.assign(to: &$mostRecentlyUsedIdentityId)
2020-08-26 08:40:54 +00:00
2020-10-05 22:50:05 +00:00
identitySelected(id: mostRecentlyUsedIdentityId, immediate: true)
2020-08-12 07:24:39 +00:00
2020-09-13 00:50:22 +00:00
allIdentitiesService.identitiesCreated
.sink { [weak self] in self?.identitySelected(id: $0) }
.store(in: &cancellables)
userNotificationService.isAuthorized()
2020-08-12 07:24:39 +00:00
.filter { $0 }
2020-09-01 07:33:49 +00:00
.zip(registerForRemoteNotifications())
2020-08-12 07:24:39 +00:00
.map { $1 }
2020-08-26 21:35:06 +00:00
.flatMap(allIdentitiesService.updatePushSubscriptions(deviceToken:))
2020-08-12 07:24:39 +00:00
.sink { _ in } receiveValue: { _ in }
.store(in: &cancellables)
2020-08-03 15:20:51 +00:00
}
}
2020-09-01 07:33:49 +00:00
public extension RootViewModel {
2020-10-05 22:50:05 +00:00
func identitySelected(id: Identity.Id?) {
2020-09-09 12:05:43 +00:00
identitySelected(id: id, immediate: false)
2020-08-12 07:24:39 +00:00
}
2020-10-05 22:50:05 +00:00
func deleteIdentity(id: Identity.Id) {
2020-09-09 05:40:49 +00:00
allIdentitiesService.deleteIdentity(id: id)
2020-08-14 01:59:17 +00:00
.sink { _ in } receiveValue: { _ in }
2020-08-09 05:37:04 +00:00
.store(in: &cancellables)
}
func addIdentityViewModel() -> AddIdentityViewModel {
2020-09-09 06:17:35 +00:00
AddIdentityViewModel(
allIdentitiesService: allIdentitiesService,
2020-09-10 04:51:31 +00:00
instanceURLService: InstanceURLService(environment: environment))
2020-08-03 15:20:51 +00:00
}
2020-12-10 02:44:06 +00:00
func newStatusViewModel(identification: Identification) -> NewStatusViewModel {
NewStatusViewModel(
allIdentitiesService: allIdentitiesService,
identification: identification,
environment: environment)
}
2020-08-03 15:20:51 +00:00
}
2020-09-09 12:05:43 +00:00
private extension RootViewModel {
2020-10-05 22:50:05 +00:00
func identitySelected(id: Identity.Id?, immediate: Bool) {
2020-09-09 22:48:56 +00:00
navigationViewModel?.presentingSecondaryNavigation = false
2020-09-09 12:05:43 +00:00
guard
let id = id,
let identityService = try? allIdentitiesService.identityService(id: id) else {
2020-09-09 22:48:56 +00:00
navigationViewModel = nil
2020-09-09 12:05:43 +00:00
return
}
2020-10-06 20:44:22 +00:00
let identityPublisher = identityService.identityPublisher(immediate: immediate)
2020-09-09 12:05:43 +00:00
.catch { [weak self] _ -> Empty<Identity, Never> in
DispatchQueue.main.async {
2020-10-05 22:50:05 +00:00
self?.identitySelected(id: self?.mostRecentlyUsedIdentityId, immediate: false)
2020-09-09 12:05:43 +00:00
}
return Empty()
}
.share()
2020-10-06 20:44:22 +00:00
identityPublisher
2020-09-09 22:48:56 +00:00
.filter { [weak self] in $0.id != self?.navigationViewModel?.identification.identity.id }
.map { [weak self] in
2020-10-15 07:44:01 +00:00
guard let self = self else { return nil }
2020-09-09 22:48:56 +00:00
let identification = Identification(
2020-09-09 20:21:04 +00:00
identity: $0,
2020-10-06 20:44:22 +00:00
publisher: identityPublisher.eraseToAnyPublisher(),
2020-10-15 07:44:01 +00:00
service: identityService,
environment: self.environment)
identification.service.updateLastUse()
.sink { _ in } receiveValue: { _ in }
.store(in: &self.cancellables)
self.userNotificationService.isAuthorized()
.filter { $0 }
.zip(self.registerForRemoteNotifications())
.filter { identification.identity.lastRegisteredDeviceToken != $1 }
.map { ($1, identification.identity.pushSubscriptionAlerts) }
.flatMap(identification.service.createPushSubscription(deviceToken:alerts:))
.sink { _ in } receiveValue: { _ in }
.store(in: &self.cancellables)
2020-09-09 22:48:56 +00:00
2020-09-09 23:00:10 +00:00
return NavigationViewModel(identification: identification)
2020-09-09 20:21:04 +00:00
}
2020-09-09 22:48:56 +00:00
.assign(to: &$navigationViewModel)
2020-09-09 12:05:43 +00:00
}
}