diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index 2d268106b..5e57ad98d 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -370,8 +370,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { guard isLastSession, appSettings.chatBackupEnabled else { ServiceLocator.shared.userIndicatorController.alertInfo = .init(id: .init(), - title: L10n.screenSignoutRecoveryDisabledTitle, - message: L10n.screenSignoutRecoveryDisabledSubtitle, + title: L10n.screenSignoutConfirmationDialogTitle, + message: L10n.screenSignoutConfirmationDialogContent, primaryButton: .init(title: L10n.screenSignoutConfirmationDialogSubmit, role: .destructive) { [weak self] in self?.actionsSubject.send(.logout) }) diff --git a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift index eae072416..6e80bc996 100644 --- a/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift +++ b/ElementX/Sources/Screens/SecureBackup/SecureBackupRecoveryKeyScreen/View/SecureBackupRecoveryKeyScreen.swift @@ -20,15 +20,31 @@ import SwiftUI struct SecureBackupRecoveryKeyScreen: View { @ObservedObject var context: SecureBackupRecoveryKeyScreenViewModel.Context + @FocusState private var focused + private let textFieldIdentifier = "textFieldIdentifier" var body: some View { - mainContent - .padding() - .interactiveDismissDisabled() - .toolbar { toolbar } - .toolbar(.visible, for: .navigationBar) - .background(Color.compound.bgCanvasDefault.ignoresSafeArea()) - .alert(item: $context.alertInfo) + ScrollView { + ScrollViewReader { reader in + mainContent + .padding(16) + .onChange(of: focused) { newValue in + guard newValue == true else { return } + reader.scrollTo(textFieldIdentifier) + } + } + } + .safeAreaInset(edge: .bottom) { + footer + .padding([.horizontal, .bottom], 16) + .padding(.top, 8) + .background(Color.compound.bgCanvasDefault.ignoresSafeArea()) + } + .interactiveDismissDisabled() + .toolbar { toolbar } + .toolbar(.visible, for: .navigationBar) + .background(Color.compound.bgCanvasDefault.ignoresSafeArea()) + .alert(item: $context.alertInfo) } @ViewBuilder @@ -37,7 +53,7 @@ struct SecureBackupRecoveryKeyScreen: View { switch context.viewState.mode { case .setupRecovery, .changeRecovery: header - newRecoveryKeySection + generateRecoveryKeySection case .fixRecovery: header confirmRecoveryKeySection @@ -45,6 +61,38 @@ struct SecureBackupRecoveryKeyScreen: View { } } + @ViewBuilder + private var footer: some View { + switch context.viewState.mode { + case .setupRecovery, .changeRecovery: + if let recoveryKey = context.viewState.recoveryKey { + ShareLink(item: recoveryKey) { + Label(L10n.screenRecoveryKeySaveAction, icon: \.download) + } + .buttonStyle(.compound(.primary)) + .simultaneousGesture(TapGesture().onEnded { _ in + context.send(viewAction: .keySaved) + }) + } + + Button { + context.send(viewAction: .done) + } label: { + Text(L10n.actionDone) + } + .buttonStyle(.compound(.primary)) + .disabled(context.viewState.recoveryKey == nil || context.viewState.doneButtonEnabled == false) + case .fixRecovery: + Button { + context.send(viewAction: .confirmKey) + } label: { + Text(L10n.actionConfirm) + } + .buttonStyle(.compound(.primary)) + .disabled(context.confirmationRecoveryKey.isEmpty) + } + } + @ToolbarContentBuilder private var toolbar: some ToolbarContent { if context.viewState.recoveryKey == nil { @@ -72,31 +120,6 @@ struct SecureBackupRecoveryKeyScreen: View { } } - @ViewBuilder - private var newRecoveryKeySection: some View { - generateRecoveryKeySection - - Spacer() - - if let recoveryKey = context.viewState.recoveryKey { - ShareLink(item: recoveryKey) { - Label(L10n.screenRecoveryKeySaveAction, icon: \.download) - } - .buttonStyle(.compound(.primary)) - .simultaneousGesture(TapGesture().onEnded { _ in - context.send(viewAction: .keySaved) - }) - } - - Button { - context.send(viewAction: .done) - } label: { - Text(L10n.actionDone) - } - .buttonStyle(.compound(.primary)) - .disabled(context.viewState.recoveryKey == nil || context.viewState.doneButtonEnabled == false) - } - private var generateRecoveryKeySection: some View { VStack(alignment: .leading) { Text(L10n.commonRecoveryKey) @@ -155,25 +178,24 @@ struct SecureBackupRecoveryKeyScreen: View { .foregroundColor(.compound.textPrimary) .font(.compound.bodySM) - TextField(L10n.screenRecoveryKeyConfirmKeyPlaceholder, text: $context.confirmationRecoveryKey, axis: .vertical) + TextField(L10n.screenRecoveryKeyConfirmKeyPlaceholder, text: $context.confirmationRecoveryKey) + .textContentType(.password) // Not ideal but stops random suggestions + .autocapitalization(.none) + .disableAutocorrection(true) .frame(maxWidth: .infinity) .padding() .background(Color.compound.bgSubtleSecondaryLevel0) .clipShape(RoundedRectangle(cornerRadius: 8)) + .id(textFieldIdentifier) + .focused($focused) + .submitLabel(.done) + .onSubmit { + context.send(viewAction: .confirmKey) + } Text(context.viewState.recoveryKeySubtitle) .foregroundColor(.compound.textSecondary) .font(.compound.bodySM) - - Spacer() - - Button { - context.send(viewAction: .confirmKey) - } label: { - Text(L10n.actionConfirm) - } - .buttonStyle(.compound(.primary)) - .disabled(context.confirmationRecoveryKey.isEmpty) } } } diff --git a/UnitTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen.Incomplete.png b/UnitTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen.Incomplete.png index 9c5deaf19..146c4d510 100644 --- a/UnitTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen.Incomplete.png +++ b/UnitTests/__Snapshots__/PreviewTests/test_secureBackupRecoveryKeyScreen.Incomplete.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04b0e56fb858bb91536de8a6235b00885e85a717f05ee5c386017a53105f7857 -size 106661 +oid sha256:6e555a2dc897f2b010e6d62f0595d51f892810ea81382d55bc067355d4118ec7 +size 106260