Use the SDK's offline detection everywhere (except for restarting the sync loop). (#4472)

* Use the SDK's offline state to drive the offline indicator.

* Only use network reachability for restarting the sync loop, use the homeserver reachability for requests.

* Add a separate indicator to distinguish when the server is unreachable but the device is online.
This commit is contained in:
Doug
2025-09-08 13:18:02 +01:00
committed by GitHub
parent 20b57d0ad7
commit 90504d89c8
26 changed files with 152 additions and 127 deletions
@@ -15,7 +15,6 @@ struct RoomDetailsScreenCoordinatorParameters {
let userIndicatorController: UserIndicatorControllerProtocol
let notificationSettings: NotificationSettingsProxyProtocol
let attributedStringBuilder: AttributedStringBuilderProtocol
let appMediator: AppMediatorProtocol
let appSettings: AppSettings
}
@@ -54,7 +53,6 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
userIndicatorController: parameters.userIndicatorController,
notificationSettingsProxy: parameters.notificationSettings,
attributedStringBuilder: parameters.attributedStringBuilder,
appMediator: parameters.appMediator,
appSettings: parameters.appSettings)
}
@@ -49,7 +49,6 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
userIndicatorController: UserIndicatorControllerProtocol,
notificationSettingsProxy: NotificationSettingsProxyProtocol,
attributedStringBuilder: AttributedStringBuilderProtocol,
appMediator: AppMediatorProtocol,
appSettings: AppSettings) {
self.roomProxy = roomProxy
self.userSession = userSession
@@ -79,7 +78,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
state.reportRoomEnabled = await userSession.clientProxy.isReportRoomSupported
}
appMediator.networkMonitor.reachabilityPublisher
userSession.clientProxy.homeserverReachabilityPublisher
.filter { $0 == .reachable }
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
@@ -397,7 +397,6 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
userIndicatorController: ServiceLocator.shared.userIndicatorController,
notificationSettingsProxy: notificationSettingsProxy,
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings)
}
@@ -427,7 +426,6 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
userIndicatorController: ServiceLocator.shared.userIndicatorController,
notificationSettingsProxy: notificationSettingsProxy,
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings)
}
@@ -466,7 +464,6 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
userIndicatorController: ServiceLocator.shared.userIndicatorController,
notificationSettingsProxy: notificationSettingsProxy,
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings)
}
}
@@ -71,7 +71,6 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
roomProxy: parameters.roomProxy,
initialSelectedPinnedEventID: selectedPinnedEventID,
ongoingCallRoomIDPublisher: parameters.ongoingCallRoomIDPublisher,
appMediator: parameters.appMediator,
appSettings: parameters.appSettings,
appHooks: parameters.appHooks,
analyticsService: parameters.analytics,
@@ -16,7 +16,6 @@ typealias RoomScreenViewModelType = StateStoreViewModel<RoomScreenViewState, Roo
class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol {
private let clientProxy: ClientProxyProtocol
private let roomProxy: JoinedRoomProxyProtocol
private let appMediator: AppMediatorProtocol
private let appSettings: AppSettings
private let analyticsService: AnalyticsService
private let userIndicatorController: UserIndicatorControllerProtocol
@@ -54,14 +53,12 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
roomProxy: JoinedRoomProxyProtocol,
initialSelectedPinnedEventID: String?,
ongoingCallRoomIDPublisher: CurrentValuePublisher<String?, Never>,
appMediator: AppMediatorProtocol,
appSettings: AppSettings,
appHooks: AppHooks,
analyticsService: AnalyticsService,
userIndicatorController: UserIndicatorControllerProtocol) {
clientProxy = userSession.clientProxy
self.roomProxy = roomProxy
self.appMediator = appMediator
self.appSettings = appSettings
self.analyticsService = analyticsService
self.userIndicatorController = userIndicatorController
@@ -179,7 +176,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
}
.store(in: &cancellables)
appMediator.networkMonitor.reachabilityPublisher
clientProxy.homeserverReachabilityPublisher
.filter { $0 == .reachable }
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
@@ -413,13 +410,12 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
extension RoomScreenViewModel {
static func mock(roomProxyMock: JoinedRoomProxyMock,
clientProxyMock: ClientProxyMock = ClientProxyMock(),
clientProxyMock: ClientProxyMock = ClientProxyMock(.init()),
appHooks: AppHooks = AppHooks()) -> RoomScreenViewModel {
RoomScreenViewModel(userSession: UserSessionMock(.init(clientProxy: clientProxyMock)),
roomProxy: roomProxyMock,
initialSelectedPinnedEventID: nil,
ongoingCallRoomIDPublisher: .init(.init(nil)),
appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings,
appHooks: appHooks,
analyticsService: ServiceLocator.shared.analytics,
@@ -10,7 +10,7 @@ import SwiftUI
struct SecureBackupLogoutConfirmationScreenCoordinatorParameters {
let secureBackupController: SecureBackupControllerProtocol
let appMediator: AppMediatorProtocol
let homeserverReachabilityPublisher: CurrentValuePublisher<NetworkMonitorReachability, Never>
}
enum SecureBackupLogoutConfirmationScreenCoordinatorAction {
@@ -30,7 +30,7 @@ final class SecureBackupLogoutConfirmationScreenCoordinator: CoordinatorProtocol
init(parameters: SecureBackupLogoutConfirmationScreenCoordinatorParameters) {
viewModel = SecureBackupLogoutConfirmationScreenViewModel(secureBackupController: parameters.secureBackupController,
appMediator: parameters.appMediator)
homeserverReachabilityPublisher: parameters.homeserverReachabilityPublisher)
}
func start() {
@@ -12,7 +12,7 @@ typealias SecureBackupLogoutConfirmationScreenViewModelType = StateStoreViewMode
class SecureBackupLogoutConfirmationScreenViewModel: SecureBackupLogoutConfirmationScreenViewModelType, SecureBackupLogoutConfirmationScreenViewModelProtocol {
private let secureBackupController: SecureBackupControllerProtocol
private let appMediator: AppMediatorProtocol
private let homeserverReachabilityPublisher: CurrentValuePublisher<NetworkMonitorReachability, Never>
private let backupUploadStateSubject: CurrentValueSubject<SecureBackupSteadyState, Never> = .init(.waiting)
@@ -27,13 +27,13 @@ class SecureBackupLogoutConfirmationScreenViewModel: SecureBackupLogoutConfirmat
actionsSubject.eraseToAnyPublisher()
}
init(secureBackupController: SecureBackupControllerProtocol, appMediator: AppMediatorProtocol) {
init(secureBackupController: SecureBackupControllerProtocol, homeserverReachabilityPublisher: CurrentValuePublisher<NetworkMonitorReachability, Never>) {
self.secureBackupController = secureBackupController
self.appMediator = appMediator
self.homeserverReachabilityPublisher = homeserverReachabilityPublisher
super.init(initialViewState: .init(mode: .saveRecoveryKey))
backupUploadStateSubject.combineLatest(appMediator.networkMonitor.reachabilityPublisher)
backupUploadStateSubject.combineLatest(homeserverReachabilityPublisher)
.receive(on: DispatchQueue.main)
.sink { [weak self] backupState, reachability in
guard let self, state.mode != .saveRecoveryKey else { return }
@@ -62,7 +62,7 @@ class SecureBackupLogoutConfirmationScreenViewModel: SecureBackupLogoutConfirmat
private func attemptLogout() {
if case .saveRecoveryKey = state.mode {
updateMode(backupState: backupUploadStateSubject.value, reachability: appMediator.networkMonitor.reachabilityPublisher.value)
updateMode(backupState: backupUploadStateSubject.value, reachability: homeserverReachabilityPublisher.value)
keyUploadWaitingTask = Task {
var result = await secureBackupController.waitForKeyBackupUpload(uploadStateSubject: backupUploadStateSubject)
@@ -161,14 +161,9 @@ struct SecureBackupLogoutConfirmationScreen_Previews: PreviewProvider, TestableP
}
let reachability: NetworkMonitorReachability = mode == .offline ? .unreachable : .reachable
let networkMonitor = NetworkMonitorMock()
networkMonitor.underlyingReachabilityPublisher = CurrentValueSubject<NetworkMonitorReachability, Never>(reachability).asCurrentValuePublisher()
let appMediator = AppMediatorMock()
appMediator.underlyingNetworkMonitor = networkMonitor
let viewModel = SecureBackupLogoutConfirmationScreenViewModel(secureBackupController: secureBackupController,
appMediator: appMediator)
homeserverReachabilityPublisher: .init(reachability))
if mode != .saveRecoveryKey {
viewModel.context.send(viewAction: .logout)