From fad608cd342c7ff985bbd26fea41143b2792a814 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 6 Sep 2023 16:10:36 +0300 Subject: [PATCH] Adopt the new room list service syncIndicatorListener --- .../Sources/Application/AppCoordinator.swift | 32 ++++++---------- .../Sources/Services/Client/ClientProxy.swift | 37 +++++++++++++++++-- .../Services/Client/ClientProxyProtocol.swift | 8 +++- .../Services/Client/MockClientProxy.swift | 2 + 4 files changed, 54 insertions(+), 25 deletions(-) diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index bc354544b..9a868dd01 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -598,33 +598,25 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate, ServiceLocator.shared.analytics.signpost.beginFirstSync() userSession.clientProxy.startSync() - let identifier = "StaleDataIndicator" - - func showLoadingIndicator() { - ServiceLocator.shared.userIndicatorController.submitIndicator(.init(id: identifier, type: .toast(progress: .indeterminate), title: L10n.commonSyncing, persistent: true)) - } - guard clientProxyObserver == nil else { return } - // Prevent the syncing indicator from showing over the offline one - if ServiceLocator.shared.networkMonitor.reachabilityPublisher.value == .reachable { - showLoadingIndicator() - } - clientProxyObserver = userSession.clientProxy - .callbacks + .loadingStatePublisher + .removeDuplicates() .receive(on: DispatchQueue.main) - .sink { action in - switch action { - case .startedUpdating: - showLoadingIndicator() - case .receivedSyncUpdate: + .sink { state in + let toastIdentifier = "StaleDataIndicator" + + switch state { + case .loading: + if ServiceLocator.shared.networkMonitor.reachabilityPublisher.value == .reachable { + ServiceLocator.shared.userIndicatorController.submitIndicator(.init(id: toastIdentifier, type: .toast(progress: .indeterminate), title: L10n.commonSyncing, persistent: true)) + } + case .notLoading: ServiceLocator.shared.analytics.signpost.endFirstSync() - ServiceLocator.shared.userIndicatorController.retractIndicatorWithId(identifier) - default: - break + ServiceLocator.shared.userIndicatorController.retractIndicatorWithId(toastIdentifier) } } } diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index fc38b929c..34cc03d2a 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -30,6 +30,7 @@ class ClientProxy: ClientProxyProtocol { private var roomListService: RoomListService? private var roomListStateUpdateTaskHandle: TaskHandle? + private var roomListStateLoadingStateUpdateTaskHandle: TaskHandle? private var syncService: SyncService? private var syncServiceStateUpdateTaskHandle: TaskHandle? @@ -60,6 +61,11 @@ class ClientProxy: ClientProxyProtocol { let callbacks = PassthroughSubject() + private let loadingStateSubject = CurrentValueSubject(.notLoading) + var loadingStatePublisher: CurrentValuePublisher { + loadingStateSubject.asCurrentValuePublisher() + } + init(client: ClientProtocol, backgroundTaskService: BackgroundTaskServiceProtocol, appSettings: AppSettings) async { self.client = client self.backgroundTaskService = backgroundTaskService @@ -419,6 +425,7 @@ class ClientProxy: ClientProxyProtocol { syncServiceStateUpdateTaskHandle = createSyncServiceStateObserver(syncService) roomListStateUpdateTaskHandle = createRoomListServiceObserver(roomListService) + roomListStateLoadingStateUpdateTaskHandle = createRoomListLoadingStateUpdateObserver(roomListService) } catch { MXLog.error("Failed building room list service with error: \(error)") @@ -432,10 +439,7 @@ class ClientProxy: ClientProxyProtocol { MXLog.info("Received sync service update: \(state)") switch state { - case .running: - // Show the loading spinner when the sync service goes into running - callbacks.send(.startedUpdating) - case .terminated, .idle: + case .running, .terminated, .idle: break case .error: restartSync() @@ -458,6 +462,19 @@ class ClientProxy: ClientProxyProtocol { }) } + private func createRoomListLoadingStateUpdateObserver(_ roomListService: RoomListService) -> TaskHandle { + roomListService.syncIndicator(listener: RoomListServiceSyncIndicatorListenerProxy { [weak self] state in + guard let self else { return } + + switch state { + case .show: + loadingStateSubject.send(.loading) + case .hide: + loadingStateSubject.send(.notLoading) + } + }) + } + private func roomTupleForIdentifier(_ identifier: String) -> (RoomListItem?, Room?) { do { let roomListItem = try roomListService?.room(roomId: identifier) @@ -509,6 +526,18 @@ private class RoomListStateListenerProxy: RoomListServiceStateListener { } } +private class RoomListServiceSyncIndicatorListenerProxy: RoomListServiceSyncIndicatorListener { + private let onUpdateClosure: (RoomListServiceSyncIndicator) -> Void + + init(onUpdateClosure: @escaping (RoomListServiceSyncIndicator) -> Void) { + self.onUpdateClosure = onUpdateClosure + } + + func onUpdate(syncIndicator: RoomListServiceSyncIndicator) { + onUpdateClosure(syncIndicator) + } +} + private class ClientDelegateWrapper: ClientDelegate { private let authErrorCallback: (Bool) -> Void private let tokenRefreshCallback: () -> Void diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index c3a9dd167..dca66ccee 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -19,7 +19,6 @@ import Foundation import MatrixRustSDK enum ClientProxyCallback { - case startedUpdating case receivedSyncUpdate case receivedAuthError(isSoftLogout: Bool) case updateRestorationToken @@ -33,6 +32,11 @@ enum ClientProxyCallback { } } +enum ClientProxyLoadingState { + case loading + case notLoading +} + enum ClientProxyError: Error { case failedCreatingRoom case failedRetrievingDirectRoom @@ -67,6 +71,8 @@ struct PusherConfiguration { protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { var callbacks: PassthroughSubject { get } + var loadingStatePublisher: CurrentValuePublisher { get } + var userID: String { get } var deviceID: String? { get } diff --git a/ElementX/Sources/Services/Client/MockClientProxy.swift b/ElementX/Sources/Services/Client/MockClientProxy.swift index b78a0031a..33df497aa 100644 --- a/ElementX/Sources/Services/Client/MockClientProxy.swift +++ b/ElementX/Sources/Services/Client/MockClientProxy.swift @@ -21,6 +21,8 @@ import MatrixRustSDK class MockClientProxy: ClientProxyProtocol { let callbacks = PassthroughSubject() + let loadingStatePublisher = CurrentValuePublisher(.notLoading) + let userID: String let deviceID: String? let homeserver = ""