From 1d687821d18bb3f00e3cdc419ca595815dd2d873 Mon Sep 17 00:00:00 2001 From: Sudhanshu Vohra Date: Thu, 21 May 2026 18:55:45 +0530 Subject: [PATCH 1/2] Added copy code functionality for Guardian app authenticator --- .../Presentation/TOTPPushQRCodeView.swift | 18 ++++++++++-------- .../Presentation/TOTPPushQRCodeViewModel.swift | 7 +++++-- .../TOTPPushQRViewModelTests.swift | 6 +++++- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/Auth0UniversalComponents/TOTPPushEnrollment/Presentation/TOTPPushQRCodeView.swift b/Auth0UniversalComponents/TOTPPushEnrollment/Presentation/TOTPPushQRCodeView.swift index 06583f5..05e17dd 100644 --- a/Auth0UniversalComponents/TOTPPushEnrollment/Presentation/TOTPPushQRCodeView.swift +++ b/Auth0UniversalComponents/TOTPPushEnrollment/Presentation/TOTPPushQRCodeView.swift @@ -88,14 +88,16 @@ struct TOTPPushQRCodeView: View { } if let manualInputCode = viewModel.manualInputCode { - Text(manualInputCode) - .auth0TextStyle(theme.typography.helper) - .foregroundStyle(theme.colors.text.bold) - .padding(EdgeInsets(top: 10, leading: theme.spacing.sm, bottom: 10, trailing: theme.spacing.sm)) - .overlay { - RoundedRectangle(cornerRadius: theme.radius.inputField) - .stroke(theme.colors.background.primary, lineWidth: 1) - }.padding(.bottom, theme.spacing.md) + if viewModel.showManualCodeText { + Text(manualInputCode) + .auth0TextStyle(theme.typography.helper) + .foregroundStyle(theme.colors.text.bold) + .padding(EdgeInsets(top: 10, leading: theme.spacing.sm, bottom: 10, trailing: theme.spacing.sm)) + .overlay { + RoundedRectangle(cornerRadius: theme.radius.inputField) + .stroke(theme.colors.background.primary, lineWidth: 1) + }.padding(.bottom, theme.spacing.md) + } Button { #if os(macOS) diff --git a/Auth0UniversalComponents/TOTPPushEnrollment/Presentation/TOTPPushQRCodeViewModel.swift b/Auth0UniversalComponents/TOTPPushEnrollment/Presentation/TOTPPushQRCodeViewModel.swift index 806cf74..46e43dc 100644 --- a/Auth0UniversalComponents/TOTPPushEnrollment/Presentation/TOTPPushQRCodeViewModel.swift +++ b/Auth0UniversalComponents/TOTPPushEnrollment/Presentation/TOTPPushQRCodeViewModel.swift @@ -29,6 +29,7 @@ final class TOTPPushQRCodeViewModel: ObservableObject, ErrorViewModelHandler { @Published var qrCodeURI: String? @Published var showLoader: Bool = true @Published var manualInputCode: String? + @Published var showManualCodeText: Bool = false @Published var errorViewModel: ErrorScreenViewModel? @Published var apiCallInProgress: Bool = false @Published var toast: Toast? @@ -129,8 +130,10 @@ final class TOTPPushQRCodeViewModel: ObservableObject, ErrorViewModelHandler { } private func setAuthManualSetupCode() { - if let totpEnrollmentChallenge { - manualInputCode = totpEnrollmentChallenge.authenticatorManualInputCode + if totpEnrollmentChallenge.isNotNil || pushEnrollmentChallenge.isNotNil { + let manualCode: String? = totpEnrollmentChallenge?.authenticatorManualInputCode ?? pushEnrollmentChallenge!.authenticatorQRCodeURI + manualInputCode = manualCode + showManualCodeText = totpEnrollmentChallenge.isNotNil } } diff --git a/Auth0UniversalComponentsTests/TOTPPushEnrollment/TOTPPushQRViewModelTests.swift b/Auth0UniversalComponentsTests/TOTPPushEnrollment/TOTPPushQRViewModelTests.swift index 56714d7..0487946 100644 --- a/Auth0UniversalComponentsTests/TOTPPushEnrollment/TOTPPushQRViewModelTests.swift +++ b/Auth0UniversalComponentsTests/TOTPPushEnrollment/TOTPPushQRViewModelTests.swift @@ -83,6 +83,7 @@ struct TOTPPushQRCodeViewModelTests { #expect(viewModel.showLoader == true) #expect(viewModel.qrCodeURI == nil) #expect(viewModel.manualInputCode == nil) + #expect(viewModel.showManualCodeText == false) #expect(viewModel.errorViewModel == nil) #expect(viewModel.apiCallInProgress == false) @@ -114,6 +115,7 @@ struct TOTPPushQRCodeViewModelTests { } await viewModel.fetchEnrollmentChallenge() #expect(viewModel.manualInputCode == "N47HCYSDHRKWWSLJONYEQ7LXLV5XEMC5") + #expect(viewModel.showManualCodeText == true) } } @@ -126,7 +128,7 @@ struct TOTPPushQRCodeViewModelTests { let viewModel = await TOTPPushQRCodeViewModel( startTOTPEnrollmentUseCase: StartTOTPEnrollmentUseCase(session: makeMockSession()), startPushEnrollmentUseCase: StartPushEnrollmentUseCase(session: makeMockSession()), - type: .totp, + type: .pushNotification, dependencies: Auth0UniversalComponentsSDKInitializer.shared ) await confirmation(expectedCount: 1) { @MainActor confirmation in @@ -142,6 +144,7 @@ struct TOTPPushQRCodeViewModelTests { } await viewModel.fetchEnrollmentChallenge() #expect(viewModel.qrCodeURI != nil) + #expect(viewModel.showManualCodeText == false) } } @@ -215,6 +218,7 @@ struct TOTPPushQRCodeViewModelTests { return (response, pushEnrollmentChallengeData) } await viewModel.fetchEnrollmentChallenge() + #expect(viewModel.showManualCodeText == false) MockURLProtocol.requestHandler = { request in let response = HTTPURLResponse( url: request.url!, From 7a661bd5a160d18aa82549dbf98d083d218b0f15 Mon Sep 17 00:00:00 2001 From: Sudhanshu Vohra Date: Mon, 25 May 2026 15:15:12 +0530 Subject: [PATCH 2/2] Code refactor --- .../Presentation/TOTPPushQRCodeViewModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Auth0UniversalComponents/TOTPPushEnrollment/Presentation/TOTPPushQRCodeViewModel.swift b/Auth0UniversalComponents/TOTPPushEnrollment/Presentation/TOTPPushQRCodeViewModel.swift index c5185cc..549ae4b 100644 --- a/Auth0UniversalComponents/TOTPPushEnrollment/Presentation/TOTPPushQRCodeViewModel.swift +++ b/Auth0UniversalComponents/TOTPPushEnrollment/Presentation/TOTPPushQRCodeViewModel.swift @@ -131,7 +131,7 @@ final class TOTPPushQRCodeViewModel: ObservableObject, ErrorViewModelHandler { private func setAuthManualSetupCode() { if totpEnrollmentChallenge.isNotNil || pushEnrollmentChallenge.isNotNil { - let manualCode: String? = totpEnrollmentChallenge?.authenticatorManualInputCode ?? pushEnrollmentChallenge!.authenticatorQRCodeURI + let manualCode: String? = totpEnrollmentChallenge?.authenticatorManualInputCode ?? pushEnrollmentChallenge?.authenticatorQRCodeURI manualInputCode = manualCode showManualCodeText = totpEnrollmentChallenge.isNotNil }