From f9bda5ced4469d0376b660da5523e9500a0485a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Tinkl?= Date: Thu, 20 Feb 2025 16:24:58 +0100 Subject: [PATCH] fix(Onboarding): Back button appears on loading screen - don't clear the stack, we might need it to show errors during login (while displaying splash screen) - use the `backAvailableHint` instead on the splash screen itself to hide the back button - when a login error happens, unwind (or recreate) the stack to show the LoginScreen page again, together with the error message - add a simulation of these 2 scenarios to StoryBook, together with showing the splash screen after a login Fixes #17352 --- storybook/pages/OnboardingLayoutPage.qml | 23 +++++++++++++++++-- .../Onboarding2/OnboardingLayout.qml | 14 +++++++++-- ui/main.qml | 6 ++--- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/storybook/pages/OnboardingLayoutPage.qml b/storybook/pages/OnboardingLayoutPage.qml index 2ffbc7e70e..ecff586f81 100644 --- a/storybook/pages/OnboardingLayoutPage.qml +++ b/storybook/pages/OnboardingLayoutPage.qml @@ -166,6 +166,12 @@ SplitView { // password signals signal accountLoginError(string error, bool wrongPassword) + + // (test) error handler + onAccountLoginError: function (error, wrongPassword) { + ctrlLoginResult.result = "" + onboarding.unwindToLoginScreen() + } } biometricsAvailable: ctrlBiometrics.checked @@ -179,7 +185,6 @@ SplitView { logs.logEvent("onFinished", ["flow", "data"], arguments) console.warn("!!! SIMULATION: SHOWING SPLASH") - stack.clear() stack.push(splashScreen, { runningProgressAnimation: true }) } @@ -188,7 +193,7 @@ SplitView { // SIMULATION: emit an error in case of wrong password or PIN if (method === Onboarding.LoginMethod.Password && data.password !== mockDriver.password) { - onboardingStore.accountLoginError("The impossible has happened", Math.random() < 0.5) // randomly fail between a wrong pass and some other error + onboardingStore.accountLoginError("", true) ctrlLoginResult.result = "" } else if (method === Onboarding.LoginMethod.Keycard && data.pin !== mockDriver.pin) { onboardingStore.keycardRemainingPinAttempts-- // SIMULATION: decrease the remaining PIN attempts @@ -200,6 +205,7 @@ SplitView { ctrlLoginResult.result = "" } else { ctrlLoginResult.result = "" + stack.push(splashScreen, { runningProgressAnimation: true }) } } @@ -359,6 +365,7 @@ SplitView { id: splashScreen DidYouKnowSplashScreen { + readonly property bool backAvailableHint: false property bool runningProgressAnimation NumberAnimation on progress { @@ -460,6 +467,18 @@ SplitView { visible: ctrlLoginScreen.checked text: "Login result: %1".arg(result) } + + Button { + text: "Unwind" + visible: ctrlLoginScreen.checked && onboarding.stack.depth > 1 && !(onboarding.currentPage instanceof DidYouKnowSplashScreen) + onClicked: onboarding.unwindToLoginScreen() + } + + Button { + text: "Simulate login error" + visible: ctrlLoginScreen.checked && onboarding.currentPage instanceof DidYouKnowSplashScreen + onClicked: onboarding.onboardingStore.accountLoginError("SIMULATION: Something bad happened", false) + } } RowLayout { diff --git a/ui/app/AppLayouts/Onboarding2/OnboardingLayout.qml b/ui/app/AppLayouts/Onboarding2/OnboardingLayout.qml index bc4d1327e3..c84ef5b8e0 100644 --- a/ui/app/AppLayouts/Onboarding2/OnboardingLayout.qml +++ b/ui/app/AppLayouts/Onboarding2/OnboardingLayout.qml @@ -24,7 +24,7 @@ Page { property bool networkChecksEnabled: true property alias keycardPinInfoPageDelay: onboardingFlow.keycardPinInfoPageDelay - readonly property alias stack: onboardingFlow + readonly property alias stack: onboardingFlow // TODO remove external stack access readonly property string currentPageName: stack.topLevelItem ? Utils.objectTypeName(stack.topLevelItem) : "" signal shareUsageDataRequested(bool enabled) @@ -49,6 +49,16 @@ Page { d.resetState() } + // clear the stack down to the LoginScreen, or recreate it + // the purpose is to return from main/splash screen in case of a late stage error + // and use the below error handler (onAccountLoginError) + function unwindToLoginScreen() { + onboardingFlow.pop(null, StackView.PopTransition) + if (!onboardingFlow.loginScreen) { + restartFlow() + } + } + function setBiometricResponse(secret: string, error = "", detailedError = "", wrongFingerprint = false) { @@ -216,10 +226,10 @@ Page { } } + // error handler for the LoginScreen Connections { target: root.onboardingStore - // (password) login function onAccountLoginError(error: string, wrongPassword: bool) { const loginScreen = onboardingFlow.loginScreen diff --git a/ui/main.qml b/ui/main.qml index 6681002175..f499594256 100644 --- a/ui/main.qml +++ b/ui/main.qml @@ -198,7 +198,7 @@ StatusWindow { Theme.changeTheme(localAppSettings.theme, systemPalette.isCurrentSystemThemeDark()) Theme.changeFontSize(localAccountSensitiveSettings.fontSize) - d.runMockedKeycardControllerWindow() // FIXME this is run twice with onboardingV1 + d.runMockedKeycardControllerWindow() } //TODO remove direct backend access @@ -395,6 +395,7 @@ StatusWindow { Component { id: splashScreenV2 DidYouKnowSplashScreen { + readonly property bool backAvailableHint: false readonly property string pageClassName: "Splash" property bool runningProgressAnimation messagesEnabled: true @@ -475,7 +476,6 @@ StatusWindow { console.error("!!! ONBOARDING FINISHED WITH ERROR:", error) return } - stack.clear() stack.push(splashScreenV2, { runningProgressAnimation: true }) } @@ -500,7 +500,7 @@ StatusWindow { moveToAppMain() } onAccountLoginError: function (error, wrongPassword) { - onboardingLayout.stack.pop() + onboardingLayout.unwindToLoginScreen() // error handled internally } }