diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index 723efced0..696a20cf0 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -348,7 +348,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate, hideLoadingIndicator() } - userSession.clientProxy.stopSync() + stopSync() userSessionFlowCoordinator?.stop() guard !isSoft else { @@ -462,7 +462,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate, navigationRootCoordinator.setRootCoordinator(SplashScreenCoordinator()) - userSession.clientProxy.stopSync() + stopSync() userSessionFlowCoordinator?.stop() let userID = userSession.userID @@ -536,20 +536,24 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate, @objc private func applicationWillResignActive() { MXLog.info("Application will resign active") - + guard backgroundTask == nil else { return } backgroundTask = backgroundTaskService.startBackgroundTask(withName: "SuspendApp: \(UUID().uuidString)") { [weak self] in - guard let self else { return } - - stopSync() - - backgroundTask = nil - isSuspended = true + guard let self else { + return + } + userSession?.clientProxy.stopSync { + // No need to weakify self, this is a non escaping closure + self.backgroundTask?.stop() + self.backgroundTask = nil + } } - + + isSuspended = true + // This does seem to work if scheduled from the background task above // Schedule it here instead but with an earliest being date of 30 seconds scheduleBackgroundAppRefresh() @@ -562,10 +566,11 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate, backgroundTask?.stop() backgroundTask = nil - if isSuspended { - isSuspended = false + if isSuspended, userSession?.clientProxy.isSyncing == false { startSync() } + + isSuspended = false } // MARK: Background app refresh diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 6baf13417..6a9fde107 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -152,16 +152,30 @@ class ClientProxy: ClientProxyProtocol { return nil } } + + var isSyncing: Bool { + slidingSyncObserverToken != nil + } func startSync() { MXLog.info("Starting sync") - guard slidingSyncObserverToken == nil else { + guard !isSyncing else { return } slidingSyncObserverToken = slidingSync?.sync() } - + + func stopSync(completionHandler: () -> Void) { + guard let slidingSyncObserverToken else { + MXLog.info("No sync is present") + return + } + stopSync() + while !slidingSyncObserverToken.isFinished() { } + completionHandler() + } + func stopSync() { MXLog.info("Stopping sync") slidingSyncObserverToken?.cancel() @@ -178,7 +192,7 @@ class ClientProxy: ClientProxyProtocol { } } } - + func createDirectRoom(with userID: String) async -> Result { await Task.dispatch(on: clientQueue) { do { diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index 6cc2238ee..795f07420 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -81,9 +81,15 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol { var allRoomsSummaryProvider: RoomSummaryProviderProtocol? { get } var invitesSummaryProvider: RoomSummaryProviderProtocol? { get } + + var isSyncing: Bool { get } func startSync() - + + /// Stops the sync usiung non escaping closure. + /// It's supposed to be used for the expiration handlers to guarantee its synchronous execution + func stopSync(completionHandler: () -> Void) + func stopSync() func directRoomForUserID(_ userID: String) async -> Result diff --git a/ElementX/Sources/Services/Client/MockClientProxy.swift b/ElementX/Sources/Services/Client/MockClientProxy.swift index 248d1f795..9a8a5ffd7 100644 --- a/ElementX/Sources/Services/Client/MockClientProxy.swift +++ b/ElementX/Sources/Services/Client/MockClientProxy.swift @@ -33,6 +33,8 @@ class MockClientProxy: ClientProxyProtocol { var invitesSummaryProvider: RoomSummaryProviderProtocol? = MockRoomSummaryProvider() var avatarURLPublisher: AnyPublisher { Empty().eraseToAnyPublisher() } + + var isSyncing: Bool { false } internal init(userID: String, roomSummaryProvider: RoomSummaryProviderProtocol? = MockRoomSummaryProvider()) { self.userID = userID @@ -43,6 +45,8 @@ class MockClientProxy: ClientProxyProtocol { func startSync() { } + func stopSync(completionHandler: () -> Void) { } + func stopSync() { } func directRoomForUserID(_ userID: String) async -> Result { diff --git a/changelog.d/438.bugfix b/changelog.d/438.bugfix new file mode 100644 index 000000000..dfdec8560 --- /dev/null +++ b/changelog.d/438.bugfix @@ -0,0 +1 @@ +Stopping bg task when the app is suspended and the slidingSyncObserver is finished. \ No newline at end of file