mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Secure backup tweaks (#2122)
* Show the recovery section if key backup is anything **but** disabled * Don't show an action on secure backup if its current state is unknown * Do not show a badge on the home screen avatar while the recovery state is unknown * Do not assume key backup is disabled when its state is unknown. If the state is unknown, check if a backup exists remotely. * Dedupe remote backup state requests and handle task cancellations
This commit is contained in:
@@ -85,7 +85,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
.sink { [weak self] recoveryKeyState in
|
||||
guard let self, appSettings.chatBackupEnabled else { return }
|
||||
|
||||
let requiresSecureBackupSetup = recoveryKeyState == .unknown || recoveryKeyState == .disabled || recoveryKeyState == .incomplete
|
||||
let requiresSecureBackupSetup = recoveryKeyState == .disabled || recoveryKeyState == .incomplete
|
||||
|
||||
state.showUserMenuBadge = requiresSecureBackupSetup
|
||||
state.showSettingsMenuOptionBadge = requiresSecureBackupSetup
|
||||
|
||||
+4
-2
@@ -23,7 +23,7 @@ struct SecureBackupScreen: View {
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
if context.viewState.keyBackupState != .enabled {
|
||||
if context.viewState.keyBackupState == .disabled {
|
||||
keyBackupSection
|
||||
} else {
|
||||
keyBackupSection
|
||||
@@ -77,10 +77,12 @@ struct SecureBackupScreen: View {
|
||||
ListRow(label: .plain(title: L10n.screenChatBackupKeyBackupActionDisable, role: .destructive), kind: .navigationLink {
|
||||
context.send(viewAction: .keyBackup)
|
||||
})
|
||||
case .disabled, .enabling, .unknown:
|
||||
case .disabled, .enabling:
|
||||
ListRow(label: .plain(title: L10n.screenChatBackupKeyBackupActionEnable), kind: .navigationLink {
|
||||
context.send(viewAction: .keyBackup)
|
||||
})
|
||||
case .unknown:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@ class SecureBackupController: SecureBackupControllerProtocol {
|
||||
private var backupStateListenerTaskHandle: TaskHandle?
|
||||
private var recoveryStateListenerTaskHandle: TaskHandle?
|
||||
|
||||
/// Used to dedupe remote backup state requests
|
||||
@CancellableTask private var remoteBackupStateTask: Task<Void, Error>?
|
||||
|
||||
var recoveryKeyState: CurrentValuePublisher<SecureBackupRecoveryKeyState, Never> {
|
||||
recoveryKeyStateSubject.asCurrentValuePublisher()
|
||||
}
|
||||
@@ -39,11 +42,18 @@ class SecureBackupController: SecureBackupControllerProtocol {
|
||||
self.encryption = encryption
|
||||
|
||||
backupStateListenerTaskHandle = encryption.backupStateListener(listener: SecureBackupControllerBackupStateListener { [weak self] state in
|
||||
self?.keyBackupStateSubject.send(state.keyBackupState)
|
||||
guard let self else { return }
|
||||
|
||||
keyBackupStateSubject.send(state.keyBackupState)
|
||||
|
||||
if case .unknown = state {
|
||||
updateBackupStateFromRemote()
|
||||
}
|
||||
})
|
||||
|
||||
recoveryStateListenerTaskHandle = encryption.recoveryStateListener(listener: SecureBackupRecoveryStateListener { [weak self] state in
|
||||
guard let self else { return }
|
||||
|
||||
switch state {
|
||||
case .unknown:
|
||||
recoveryKeyStateSubject.send(.unknown)
|
||||
@@ -55,6 +65,8 @@ class SecureBackupController: SecureBackupControllerProtocol {
|
||||
recoveryKeyStateSubject.send(.incomplete)
|
||||
}
|
||||
})
|
||||
|
||||
updateBackupStateFromRemote()
|
||||
}
|
||||
|
||||
func enable() async -> Result<Void, SecureBackupControllerError> {
|
||||
@@ -140,6 +152,30 @@ class SecureBackupController: SecureBackupControllerProtocol {
|
||||
return .failure(.failedUploadingForBackup)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func updateBackupStateFromRemote(retry: Bool = true) {
|
||||
remoteBackupStateTask = Task {
|
||||
do {
|
||||
let backupExists = try await self.encryption.backupExistsOnServer()
|
||||
|
||||
if Task.isCancelled {
|
||||
return
|
||||
}
|
||||
|
||||
if !backupExists {
|
||||
keyBackupStateSubject.send(.disabled)
|
||||
}
|
||||
} catch {
|
||||
MXLog.error("Failed retrieving remote backup state with error: \(error)")
|
||||
|
||||
if retry {
|
||||
updateBackupStateFromRemote(retry: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class SecureBackupControllerBackupStateListener: BackupStateListener {
|
||||
@@ -182,7 +218,7 @@ extension BackupState {
|
||||
var keyBackupState: SecureBackupKeyBackupState {
|
||||
switch self {
|
||||
case .unknown:
|
||||
return .disabled
|
||||
return .unknown
|
||||
case .creating:
|
||||
return .enabling
|
||||
case .enabling:
|
||||
|
||||
Reference in New Issue
Block a user