From 46d5057f8e0a35af99e0107b61347366b78c371c Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Fri, 12 Apr 2024 11:29:14 +0200 Subject: [PATCH] QR Code, verification code views (#2685) --- .../en.lproj/Localizable.strings | 5 ++ ElementX/Sources/Generated/Strings.swift | 10 +++ .../Mocks/Generated/GeneratedMocks.swift | 25 +++++- .../View/PINTextField.swift | 49 ++++++++--- .../QRCodeLoginScreenModels.swift | 25 ++++++ .../View/QRCodeLoginScreen.swift | 82 ++++++++++++++++++- .../test_pINTextField-iPad-en-GB.1.png | 4 +- .../test_pINTextField-iPad-pseudo.1.png | 4 +- .../test_pINTextField-iPhone-15-en-GB.1.png | 4 +- .../test_pINTextField-iPhone-15-pseudo.1.png | 4 +- ...CodeLoginScreen-iPad-en-GB.Device-code.png | 3 + ...ginScreen-iPad-en-GB.Verification-code.png | 3 + ...odeLoginScreen-iPad-pseudo.Device-code.png | 3 + ...inScreen-iPad-pseudo.Verification-code.png | 3 + ...oginScreen-iPhone-15-en-GB.Device-code.png | 3 + ...reen-iPhone-15-en-GB.Verification-code.png | 3 + ...ginScreen-iPhone-15-pseudo.Device-code.png | 3 + ...een-iPhone-15-pseudo.Verification-code.png | 3 + 18 files changed, 215 insertions(+), 21 deletions(-) create mode 100644 PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-code.png create mode 100644 PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Verification-code.png create mode 100644 PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-code.png create mode 100644 PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Verification-code.png create mode 100644 PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Device-code.png create mode 100644 PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Verification-code.png create mode 100644 PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Device-code.png create mode 100644 PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Verification-code.png diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 432843dff..7aad9d381 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -489,6 +489,8 @@ "screen_qr_code_login_connection_note_secure_state_list_item_2" = "If you encounter the same problem, try a different wifi network or use your mobile data instead of wifi"; "screen_qr_code_login_connection_note_secure_state_list_item_3" = "If that doesn’t work, sign in manually"; "screen_qr_code_login_connection_note_secure_state_title" = "Connection not secure"; +"screen_qr_code_login_device_code_subtitle" = "You’ll be asked to enter the two digits shown below."; +"screen_qr_code_login_device_code_title" = "Enter number on your device"; "screen_qr_code_login_initial_state_item_1" = "Open %1$@ on a desktop device"; "screen_qr_code_login_initial_state_item_2" = "Click on your avatar"; "screen_qr_code_login_initial_state_item_3" = "Select %1$@"; @@ -504,6 +506,9 @@ "screen_qr_code_login_scanning_state_title" = "Scan the QR code"; "screen_qr_code_login_start_over_button" = "Start over"; "screen_qr_code_login_unknown_error_description" = "An unexpected error occurred. Please try again."; +"screen_qr_code_login_verify_code_loading" = "Waiting for your other device"; +"screen_qr_code_login_verify_code_subtitle" = "Your account provider may ask for the following code to verify the sign in."; +"screen_qr_code_login_verify_code_title" = "Your verification code"; "screen_recovery_key_change_description" = "Get a new recovery key if you've lost your existing one. After changing your recovery key, your old one will no longer work."; "screen_recovery_key_change_generate_key" = "Generate a new recovery key"; "screen_recovery_key_change_generate_key_description" = "Make sure you can store your recovery key somewhere safe"; diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index 5c799022b..d9700b88c 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -1197,6 +1197,10 @@ internal enum L10n { internal static var screenQrCodeLoginConnectionNoteSecureStateListItem3: String { return L10n.tr("Localizable", "screen_qr_code_login_connection_note_secure_state_list_item_3") } /// Connection not secure internal static var screenQrCodeLoginConnectionNoteSecureStateTitle: String { return L10n.tr("Localizable", "screen_qr_code_login_connection_note_secure_state_title") } + /// You’ll be asked to enter the two digits shown below. + internal static var screenQrCodeLoginDeviceCodeSubtitle: String { return L10n.tr("Localizable", "screen_qr_code_login_device_code_subtitle") } + /// Enter number on your device + internal static var screenQrCodeLoginDeviceCodeTitle: String { return L10n.tr("Localizable", "screen_qr_code_login_device_code_title") } /// Open %1$@ on a desktop device internal static func screenQrCodeLoginInitialStateItem1(_ p1: Any) -> String { return L10n.tr("Localizable", "screen_qr_code_login_initial_state_item_1", String(describing: p1)) @@ -1237,6 +1241,12 @@ internal enum L10n { internal static var screenQrCodeLoginStartOverButton: String { return L10n.tr("Localizable", "screen_qr_code_login_start_over_button") } /// An unexpected error occurred. Please try again. internal static var screenQrCodeLoginUnknownErrorDescription: String { return L10n.tr("Localizable", "screen_qr_code_login_unknown_error_description") } + /// Waiting for your other device + internal static var screenQrCodeLoginVerifyCodeLoading: String { return L10n.tr("Localizable", "screen_qr_code_login_verify_code_loading") } + /// Your account provider may ask for the following code to verify the sign in. + internal static var screenQrCodeLoginVerifyCodeSubtitle: String { return L10n.tr("Localizable", "screen_qr_code_login_verify_code_subtitle") } + /// Your verification code + internal static var screenQrCodeLoginVerifyCodeTitle: String { return L10n.tr("Localizable", "screen_qr_code_login_verify_code_title") } /// Get a new recovery key if you've lost your existing one. After changing your recovery key, your old one will no longer work. internal static var screenRecoveryKeyChangeDescription: String { return L10n.tr("Localizable", "screen_recovery_key_change_description") } /// Generate a new recovery key diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 2d8608ca8..20dd66cee 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -903,7 +903,30 @@ class ApplicationMock: ApplicationProtocol { } //MARK: - openAppSettings - var openAppSettingsCallsCount = 0 + var openAppSettingsUnderlyingCallsCount = 0 + var openAppSettingsCallsCount: Int { + get { + if Thread.isMainThread { + return openAppSettingsUnderlyingCallsCount + } else { + var returnValue: Int? = nil + DispatchQueue.main.sync { + returnValue = openAppSettingsUnderlyingCallsCount + } + + return returnValue! + } + } + set { + if Thread.isMainThread { + openAppSettingsUnderlyingCallsCount = newValue + } else { + DispatchQueue.main.sync { + openAppSettingsUnderlyingCallsCount = newValue + } + } + } + } var openAppSettingsCalled: Bool { return openAppSettingsCallsCount > 0 } diff --git a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/View/PINTextField.swift b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/View/PINTextField.swift index 6c60f0a3c..aa0b172fe 100644 --- a/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/View/PINTextField.swift +++ b/ElementX/Sources/Screens/AppLock/AppLockSetupPINScreen/View/PINTextField.swift @@ -21,10 +21,12 @@ import SwiftUI struct PINTextField: View { @Binding var pinCode: String var isSecure = false + var maxLength = 4 + var size = PINDigitField.Size.medium var body: some View { textField - .textFieldStyle(PINTextFieldStyle(pinCode: pinCode, isSecure: isSecure)) + .textFieldStyle(PINTextFieldStyle(pinCode: pinCode, isSecure: isSecure, maxLength: maxLength, size: size)) .keyboardType(.numberPad) .accessibilityIdentifier(A11yIdentifiers.appLockSetupPINScreen.textField) .onChange(of: pinCode) { newValue in @@ -47,7 +49,7 @@ struct PINTextField: View { func sanitize(_ pinCode: String) -> String { var sanitized = pinCode - if sanitized.count > 4 { sanitized = String(pinCode.prefix(4)) } + if sanitized.count > maxLength { sanitized = String(pinCode.prefix(maxLength)) } return sanitized.filter(\.isNumber) } } @@ -55,14 +57,15 @@ struct PINTextField: View { /// A text field style for displaying individual digits of a PIN code. private struct PINTextFieldStyle: TextFieldStyle { @FocusState private var isFocussed - let pinCode: String let isSecure: Bool + let maxLength: Int + let size: PINDigitField.Size func _body(configuration: TextField<_Label>) -> some View { HStack(spacing: 8) { - ForEach(0..<4) { index in - PINDigitField(digit: digit(index)) + ForEach(0.. some View { + VStack(spacing: 16) { + switch state { + case .deviceCode: + HeroImage(icon: \.computer, style: .subtle) + + VStack(spacing: 8) { + Text(L10n.screenQrCodeLoginDeviceCodeTitle) + .foregroundColor(.compound.textPrimary) + .font(.compound.headingMDBold) + .multilineTextAlignment(.center) + + Text(L10n.screenQrCodeLoginDeviceCodeSubtitle) + .foregroundColor(.compound.textSecondary) + .font(.compound.bodyMD) + .multilineTextAlignment(.center) + } + case .verificationCode: + HeroImage(icon: \.lock, style: .subtle) + + VStack(spacing: 8) { + Text(L10n.screenQrCodeLoginVerifyCodeTitle) + .foregroundColor(.compound.textPrimary) + .font(.compound.headingMDBold) + .multilineTextAlignment(.center) + + Text(L10n.screenQrCodeLoginVerifyCodeSubtitle) + .foregroundColor(.compound.textSecondary) + .font(.compound.bodyMD) + .multilineTextAlignment(.center) + } + } + } + } + private var qrScanContent: some View { FullscreenDialog { VStack(spacing: 40) { @@ -139,8 +205,10 @@ struct QRCodeLoginScreen: View { @ToolbarContentBuilder private var toolbar: some ToolbarContent { ToolbarItem(placement: .cancellationAction) { - Button(L10n.actionCancel) { - context.send(viewAction: .cancel) + if !context.viewState.state.isDisplayingCode { + Button(L10n.actionCancel) { + context.send(viewAction: .cancel) + } } } } @@ -280,6 +348,10 @@ struct QRCodeLoginScreen_Previews: PreviewProvider, TestablePreview { static let unknownErrorStateViewModel = QRCodeLoginScreenViewModel.mock(state: .error(.unknown)) + static let deviceCodeStateViewModel = QRCodeLoginScreenViewModel.mock(state: .displayCode(.deviceCode("12"))) + + static let verificationCodeStateViewModel = QRCodeLoginScreenViewModel.mock(state: .displayCode(.verificationCode("123456"))) + static var previews: some View { QRCodeLoginScreen(context: initialStateViewModel.context) .previewDisplayName("Initial") @@ -301,5 +373,11 @@ struct QRCodeLoginScreen_Previews: PreviewProvider, TestablePreview { QRCodeLoginScreen(context: unknownErrorStateViewModel.context) .previewDisplayName("Unknown error") + + QRCodeLoginScreen(context: deviceCodeStateViewModel.context) + .previewDisplayName("Device code") + + QRCodeLoginScreen(context: verificationCodeStateViewModel.context) + .previewDisplayName("Verification code") } } diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-en-GB.1.png index abf65af94..f4fb26e04 100644 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-en-GB.1.png +++ b/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ac5e80718c2743b6b8216aaeaa21229fad3df57fa9cd35863ab501b2a4a3cdd0 -size 98975 +oid sha256:e0192824c55a29ba61462860dbffc5bfc68caba0ad0215fae4f9f53d7b6f8ef2 +size 114873 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-pseudo.1.png index abf65af94..f4fb26e04 100644 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-pseudo.1.png +++ b/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ac5e80718c2743b6b8216aaeaa21229fad3df57fa9cd35863ab501b2a4a3cdd0 -size 98975 +oid sha256:e0192824c55a29ba61462860dbffc5bfc68caba0ad0215fae4f9f53d7b6f8ef2 +size 114873 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-en-GB.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-en-GB.1.png index c073e5a89..fdb6d179f 100644 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-en-GB.1.png +++ b/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2f981e016006994602734727f6e9c572ef7ea32074969271859a63912468c89 -size 57355 +oid sha256:5f754c85b955f5a88143ebe6c678e1755b29630a47469a5e0db0b3a001c5732d +size 70008 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-pseudo.1.png b/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-pseudo.1.png index c073e5a89..fdb6d179f 100644 --- a/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-pseudo.1.png +++ b/PreviewTests/__Snapshots__/PreviewTests/test_pINTextField-iPhone-15-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2f981e016006994602734727f6e9c572ef7ea32074969271859a63912468c89 -size 57355 +oid sha256:5f754c85b955f5a88143ebe6c678e1755b29630a47469a5e0db0b3a001c5732d +size 70008 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-code.png new file mode 100644 index 000000000..e9124a65e --- /dev/null +++ b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Device-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:69f20f9ebb23a1fc1bc92bef28b793fed1d8a6069178829b829335bd312cd105 +size 137600 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Verification-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Verification-code.png new file mode 100644 index 000000000..5698bf08f --- /dev/null +++ b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-en-GB.Verification-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b5b822e7a1380acd9e37090351b33b501cdc765eeaaa618b5f496b00b338e1c7 +size 148871 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-code.png new file mode 100644 index 000000000..944ba857f --- /dev/null +++ b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Device-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf8df4df6deb00290f82809251a2444215abd2e55cad38520028268725165fde +size 179746 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Verification-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Verification-code.png new file mode 100644 index 000000000..742e17af1 --- /dev/null +++ b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPad-pseudo.Verification-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ebeab85e81357abf24439be16f41146bf574832fa0dbf8b06c4795643e3371a +size 195293 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Device-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Device-code.png new file mode 100644 index 000000000..b73e8ca7d --- /dev/null +++ b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Device-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6c69ae18ca45caf28053e12f16a3abfeff8a68a402ee25268d7942dd0f74f66 +size 87265 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Verification-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Verification-code.png new file mode 100644 index 000000000..641142126 --- /dev/null +++ b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-en-GB.Verification-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:55ff031e7342b78b4ef14f93448046926ae35392789b0931dd2d45cb2faefdf4 +size 97749 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Device-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Device-code.png new file mode 100644 index 000000000..d27437bdb --- /dev/null +++ b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Device-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57ed01bb0263c7f0663fc5ac5a9800916ca76c04d3aafe86061ca3ddafe93e6e +size 129567 diff --git a/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Verification-code.png b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Verification-code.png new file mode 100644 index 000000000..f8248b21c --- /dev/null +++ b/PreviewTests/__Snapshots__/PreviewTests/test_qRCodeLoginScreen-iPhone-15-pseudo.Verification-code.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8b0fabf3b7ae480bb43460c889038c6d7d4dafd2d6a04c294d028600cbe2133 +size 138029