Show recovery instead of verification if this is the last session and recovery is set up

* Show recovery instead of verification if this is the last session and recovery is set up

* Rename `recoveryKeyState` to `recoveryState`

* Remove duplicates on session security state changes.

* Fix missing "Save recovery key" button

* Fix unit tests

* Rename `isLastDevice` to `isOnlyDeviceLeft`

* Address PR comments
This commit is contained in:
Stefan Ceriu
2024-02-16 11:38:49 +02:00
committed by GitHub
parent e0c9f43026
commit db05540cc5
23 changed files with 255 additions and 208 deletions
@@ -34,6 +34,12 @@ enum SettingsScreenViewModelAction {
case logout
}
enum SettingsScreenSecuritySectionMode {
case none
case sessionVerification
case secureBackup
}
struct SettingsScreenViewState: BindableState {
var deviceID: String?
var userID: String
@@ -41,9 +47,10 @@ struct SettingsScreenViewState: BindableState {
var accountSessionsListURL: URL?
var userAvatarURL: URL?
var userDisplayName: String?
var isSessionVerified: Bool?
var showSecureBackupBadge = false
var showDeveloperOptions: Bool
var securitySectionMode = SettingsScreenSecuritySectionMode.none
var showSecuritySectionBadge = false
}
enum SettingsScreenViewAction {
@@ -44,17 +44,31 @@ class SettingsScreenViewModel: SettingsScreenViewModelType, SettingsScreenViewMo
.weakAssign(to: \.state.userDisplayName, on: self)
.store(in: &cancellables)
userSession.sessionVerificationState
userSession.sessionSecurityStatePublisher
.receive(on: DispatchQueue.main)
.weakAssign(to: \.state.isSessionVerified, on: self)
.store(in: &cancellables)
userSession.clientProxy.secureBackupController.recoveryKeyState
.receive(on: DispatchQueue.main)
.sink { [weak self] state in
.sink { [weak self] securityState in
guard let self else { return }
self.state.showSecureBackupBadge = (state == .incomplete || state == .disabled)
switch (securityState.verificationState, securityState.recoveryState) {
case (.unverified, _):
state.showSecuritySectionBadge = true
state.securitySectionMode = .sessionVerification
case (.unverifiedLastSession, .incomplete):
state.showSecuritySectionBadge = true
state.securitySectionMode = .secureBackup
case (.verified, .disabled):
state.showSecuritySectionBadge = true
state.securitySectionMode = .secureBackup
case (.verified, .incomplete):
state.showSecuritySectionBadge = true
state.securitySectionMode = .secureBackup
case (.unknown, _):
state.showSecuritySectionBadge = false
state.securitySectionMode = .none
default:
state.showSecuritySectionBadge = false
state.securitySectionMode = .secureBackup
}
}
.store(in: &cancellables)
@@ -80,18 +80,20 @@ struct SettingsScreen: View {
@ViewBuilder
private var accountSecuritySection: some View {
Section {
if let isSessionVerified = context.viewState.isSessionVerified {
if !isSessionVerified {
ListRow(label: .default(title: L10n.actionCompleteVerification,
icon: \.checkCircle),
kind: .button { context.send(viewAction: .sessionVerification) })
} else {
ListRow(label: .default(title: L10n.commonChatBackup,
icon: \.key),
details: context.viewState.showSecureBackupBadge ? .icon(secureBackupBadge) : nil,
kind: .navigationLink { context.send(viewAction: .secureBackup) })
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.secureBackup)
}
switch context.viewState.securitySectionMode {
case .sessionVerification:
ListRow(label: .default(title: L10n.actionCompleteVerification,
icon: \.checkCircle),
details: context.viewState.showSecuritySectionBadge ? .icon(securitySectionBadge) : nil,
kind: .button { context.send(viewAction: .sessionVerification) })
case .secureBackup:
ListRow(label: .default(title: L10n.commonChatBackup,
icon: \.key),
details: context.viewState.showSecuritySectionBadge ? .icon(securitySectionBadge) : nil,
kind: .navigationLink { context.send(viewAction: .secureBackup) })
.accessibilityIdentifier(A11yIdentifiers.settingsScreen.secureBackup)
default:
EmptyView()
}
}
}
@@ -210,8 +212,8 @@ struct SettingsScreen: View {
}
@ViewBuilder
private var secureBackupBadge: some View {
if context.viewState.showSecureBackupBadge {
private var securitySectionBadge: some View {
if context.viewState.showSecuritySectionBadge {
BadgeView(size: 10)
}
}