From 2d5f1a2c1980e87d76d77a9699c7e8b9cc4b6fe6 Mon Sep 17 00:00:00 2001 From: Ethan Pippin Date: Fri, 18 Mar 2022 21:59:25 -0600 Subject: [PATCH] update notifications --- .../MainCoordinator/iOSMainCoordinator.swift | 14 ++-- Shared/Singleton/SessionManager.swift | 8 +- .../SwiftfinNotificationCenter.swift | 75 +++++++++++++++---- Shared/ViewModels/HomeViewModel.swift | 5 +- .../ItemViewModel/ItemViewModel.swift | 9 +-- Shared/ViewModels/ServerDetailViewModel.swift | 3 +- Shared/ViewModels/ServerListViewModel.swift | 3 +- Shared/ViewModels/UserListViewModel.swift | 6 +- .../VideoPlayerViewModel.swift | 3 +- Swiftfin/AppURLHandler/AppURLHandler.swift | 2 +- 10 files changed, 80 insertions(+), 48 deletions(-) diff --git a/Shared/Coordinators/MainCoordinator/iOSMainCoordinator.swift b/Shared/Coordinators/MainCoordinator/iOSMainCoordinator.swift index 7e47fa65..d1690c2f 100644 --- a/Shared/Coordinators/MainCoordinator/iOSMainCoordinator.swift +++ b/Shared/Coordinators/MainCoordinator/iOSMainCoordinator.swift @@ -45,12 +45,10 @@ final class MainCoordinator: NavigationCoordinatable { barAppearance.tintColor = UIColor(Color.jellyfinPurple) // Notification setup for state - let nc = SwiftfinNotificationCenter.main - nc.addObserver(self, selector: #selector(didLogIn), name: SwiftfinNotificationCenter.Keys.didSignIn, object: nil) - nc.addObserver(self, selector: #selector(didLogOut), name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil) - nc.addObserver(self, selector: #selector(processDeepLink), name: SwiftfinNotificationCenter.Keys.processDeepLink, object: nil) - nc.addObserver(self, selector: #selector(didChangeServerCurrentURI), - name: SwiftfinNotificationCenter.Keys.didChangeServerCurrentURI, object: nil) + Notifications[.didSignIn].subscribe(self, selector: #selector(didSignIn)) + Notifications[.didSignOut].subscribe(self, selector: #selector(didSignOut)) + Notifications[.processDeepLink].subscribe(self, selector: #selector(processDeepLink(_:))) + Notifications[.didChangeServerCurrentURI].subscribe(self, selector: #selector(didChangeServerCurrentURI(_:))) Defaults.publisher(.appAppearance) .sink { _ in @@ -60,13 +58,13 @@ final class MainCoordinator: NavigationCoordinatable { } @objc - func didLogIn() { + func didSignIn() { LogManager.shared.log.info("Received `didSignIn` from SwiftfinNotificationCenter.") root(\.mainTab) } @objc - func didLogOut() { + func didSignOut() { LogManager.shared.log.info("Received `didSignOut` from SwiftfinNotificationCenter.") root(\.serverList) } diff --git a/Shared/Singleton/SessionManager.swift b/Shared/Singleton/SessionManager.swift index abba3f1d..a6ddd435 100644 --- a/Shared/Singleton/SessionManager.swift +++ b/Shared/Singleton/SessionManager.swift @@ -240,7 +240,7 @@ final class SessionManager { Defaults[.lastServerUserID] = user.id currentLogin = (server: currentServer.state, user: currentUser.state) - SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSignIn, object: nil) + Notifications[.didSignIn].post() }) .map { _, user, _ in user.state @@ -255,7 +255,7 @@ final class SessionManager { Defaults[.lastServerUserID] = user.id setAuthHeader(with: user.accessToken) currentLogin = (server: server, user: user) - SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSignIn, object: nil) + Notifications[.didSignIn].post() } // MARK: logout @@ -265,7 +265,7 @@ final class SessionManager { JellyfinAPI.basePath = "" setAuthHeader(with: "") Defaults[.lastServerUserID] = nil - SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil) + Notifications[.didSignOut].post() } // MARK: purge @@ -278,7 +278,7 @@ final class SessionManager { delete(server: server) } - SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didPurge, object: nil) + Notifications[.didPurge].post() } // MARK: delete user diff --git a/Shared/Singleton/SwiftfinNotificationCenter.swift b/Shared/Singleton/SwiftfinNotificationCenter.swift index cbf99bcd..61fcfbc9 100644 --- a/Shared/Singleton/SwiftfinNotificationCenter.swift +++ b/Shared/Singleton/SwiftfinNotificationCenter.swift @@ -8,20 +8,63 @@ import Foundation -enum SwiftfinNotificationCenter { - - static let main: NotificationCenter = { - NotificationCenter() - }() - - enum Keys { - static let didSignIn = Notification.Name("didSignIn") - static let didSignOut = Notification.Name("didSignOut") - static let processDeepLink = Notification.Name("processDeepLink") - static let didPurge = Notification.Name("didPurge") - static let didChangeServerCurrentURI = Notification.Name("didChangeCurrentLoginURI") - - // Send with an item id to check if current item for item views - static let didSendStopReport = Notification.Name("didSendStopReport") - } +class SwiftfinNotification { + + private let notificationName: Notification.Name + + fileprivate init(_ notificationName: Notification.Name) { + self.notificationName = notificationName + } + + func post(object: Any? = nil) { + Notifications.main.post(name: notificationName, object: object) + } + + func subscribe(_ observer: Any, selector: Selector) { + Notifications.main.addObserver(observer, selector: selector, name: notificationName, object: nil) + } + + func unsubscribe(_ observer: Any) { + Notifications.main.removeObserver(self, name: notificationName, object: nil) + } +} + +enum Notifications { + + static let main: NotificationCenter = { + NotificationCenter() + }() + + final class Key { + public typealias NotificationKey = Notifications.Key + + public let key: String + public let underlyingNotification: SwiftfinNotification + + public init(_ key: String) { + self.key = key + self.underlyingNotification = SwiftfinNotification(Notification.Name(key)) + } + } + + static subscript(key: Key) -> SwiftfinNotification { + return key.underlyingNotification + } + + static func unsubscribe(_ observer: Any) { + main.removeObserver(observer) + } +} + +extension Notifications.Key { + + static let didSignIn = NotificationKey("didSignIn") + static let didSignOut = NotificationKey("didSignOut") + static let processDeepLink = NotificationKey("processDeepLink") + static let didPurge = NotificationKey("didPurge") + static let didChangeServerCurrentURI = NotificationKey("didChangeCurrentLoginURI") + static let toggleOfflineMode = NotificationKey("toggleOfflineMode") + static let didDeleteOfflineItem = NotificationKey("didDeleteOfflineItem") + static let didAddDownload = NotificationKey("didAddDownload") + static let didSendStopReport = NotificationKey("didSendStopReport") } diff --git a/Shared/ViewModels/HomeViewModel.swift b/Shared/ViewModels/HomeViewModel.swift index 9df68555..7b93a9b0 100644 --- a/Shared/ViewModels/HomeViewModel.swift +++ b/Shared/ViewModels/HomeViewModel.swift @@ -34,9 +34,8 @@ final class HomeViewModel: ViewModel { // Nov. 6, 2021 // This is a workaround since Stinsen doesn't have the ability to rebuild a root at the time of writing. // See ServerDetailViewModel.swift for feature request issue - let nc = SwiftfinNotificationCenter.main - nc.addObserver(self, selector: #selector(didSignIn), name: SwiftfinNotificationCenter.Keys.didSignIn, object: nil) - nc.addObserver(self, selector: #selector(didSignOut), name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil) + Notifications[.didSignIn].subscribe(self, selector: #selector(didSignIn)) + Notifications[.didSignOut].subscribe(self, selector: #selector(didSignOut)) } @objc diff --git a/Shared/ViewModels/ItemViewModel/ItemViewModel.swift b/Shared/ViewModels/ItemViewModel/ItemViewModel.swift index 0b493a24..7d9b8c6c 100644 --- a/Shared/ViewModels/ItemViewModel/ItemViewModel.swift +++ b/Shared/ViewModels/ItemViewModel/ItemViewModel.swift @@ -54,11 +54,8 @@ class ItemViewModel: ViewModel { super.init() getSimilarItems() - - SwiftfinNotificationCenter.main.addObserver(self, - selector: #selector(receivedStopReport(_:)), - name: SwiftfinNotificationCenter.Keys.didSendStopReport, - object: nil) + + Notifications[.didSendStopReport].subscribe(self, selector: #selector(receivedStopReport(_:))) refreshItemVideoPlayerViewModel(for: item) } @@ -72,7 +69,7 @@ class ItemViewModel: ViewModel { } else { // Remove if necessary. Note that this cannot be in deinit as // holding as an observer won't allow the object to be deinit-ed - SwiftfinNotificationCenter.main.removeObserver(self) + Notifications.unsubscribe(self) } } diff --git a/Shared/ViewModels/ServerDetailViewModel.swift b/Shared/ViewModels/ServerDetailViewModel.swift index b821c01f..08030106 100644 --- a/Shared/ViewModels/ServerDetailViewModel.swift +++ b/Shared/ViewModels/ServerDetailViewModel.swift @@ -25,8 +25,7 @@ class ServerDetailViewModel: ViewModel { } receiveValue: { newServerState in self.server = newServerState - let nc = SwiftfinNotificationCenter.main - nc.post(name: SwiftfinNotificationCenter.Keys.didChangeServerCurrentURI, object: newServerState) + Notifications[.didChangeServerCurrentURI].post(object: newServerState) } .store(in: &cancellables) } diff --git a/Shared/ViewModels/ServerListViewModel.swift b/Shared/ViewModels/ServerListViewModel.swift index 721c05dc..7691e100 100644 --- a/Shared/ViewModels/ServerListViewModel.swift +++ b/Shared/ViewModels/ServerListViewModel.swift @@ -20,8 +20,7 @@ class ServerListViewModel: ObservableObject { // This is a workaround since Stinsen doesn't have the ability to rebuild a root at the time of writing. // Feature request issue: https://github.com/rundfunk47/stinsen/issues/33 // Go to each MainCoordinator and implement the rebuild of the root when receiving the notification - let nc = SwiftfinNotificationCenter.main - nc.addObserver(self, selector: #selector(didPurge), name: SwiftfinNotificationCenter.Keys.didPurge, object: nil) + Notifications[.didPurge].subscribe(self, selector: #selector(didPurge)) } func fetchServers() { diff --git a/Shared/ViewModels/UserListViewModel.swift b/Shared/ViewModels/UserListViewModel.swift index c3a11919..258555da 100644 --- a/Shared/ViewModels/UserListViewModel.swift +++ b/Shared/ViewModels/UserListViewModel.swift @@ -20,10 +20,8 @@ class UserListViewModel: ViewModel { self.server = server super.init() - - let nc = SwiftfinNotificationCenter.main - nc.addObserver(self, selector: #selector(didChangeCurrentLoginURI), name: SwiftfinNotificationCenter.Keys.didChangeServerCurrentURI, - object: nil) + + Notifications[.didChangeServerCurrentURI].subscribe(self, selector: #selector(didChangeCurrentLoginURI(_:))) } @objc diff --git a/Shared/ViewModels/VideoPlayerViewModel/VideoPlayerViewModel.swift b/Shared/ViewModels/VideoPlayerViewModel/VideoPlayerViewModel.swift index bcbe6a11..1325c0e6 100644 --- a/Shared/ViewModels/VideoPlayerViewModel/VideoPlayerViewModel.swift +++ b/Shared/ViewModels/VideoPlayerViewModel/VideoPlayerViewModel.swift @@ -585,8 +585,7 @@ extension VideoPlayerViewModel { self.handleAPIRequestError(completion: completion) } receiveValue: { _ in LogManager.shared.log.debug("Stop report sent for item: \(self.item.id ?? "No ID")") - SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSendStopReport, - object: self.item.id) + Notifications[.didSendStopReport].post(object: self.item.id) } .store(in: &cancellables) } diff --git a/Swiftfin/AppURLHandler/AppURLHandler.swift b/Swiftfin/AppURLHandler/AppURLHandler.swift index 412a4c84..6c091372 100644 --- a/Swiftfin/AppURLHandler/AppURLHandler.swift +++ b/Swiftfin/AppURLHandler/AppURLHandler.swift @@ -81,7 +81,7 @@ extension AppURLHandler { // It would be nice if the ItemViewModel could be initialized to id later. getItem(userID: userID, itemID: itemID) { item in guard let item = item else { return } - SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.processDeepLink, object: DeepLink.item(item)) + Notifications[.processDeepLink].post(object: DeepLink.item(item)) } return true