diff --git a/ui/app/AppLayouts/Onboarding2/LoginWithKeycardFlow.qml b/ui/app/AppLayouts/Onboarding2/LoginWithKeycardFlow.qml index 16dbc82c4d..94c71c3ea9 100644 --- a/ui/app/AppLayouts/Onboarding2/LoginWithKeycardFlow.qml +++ b/ui/app/AppLayouts/Onboarding2/LoginWithKeycardFlow.qml @@ -14,10 +14,13 @@ SQUtils.QObject { required property int keycardState required property var tryToSetPinFunction required property int remainingAttempts + required property var isSeedPhraseValid property bool displayKeycardPromoBanner signal keycardPinEntered(string pin) + signal keycardPinCreated(string pin) + signal seedphraseSubmitted(string seedphrase) signal reloadKeycardRequested signal keycardFactoryResetRequested signal createProfileWithEmptyKeycardRequested @@ -53,9 +56,11 @@ SQUtils.QObject { KeycardIntroPage { keycardState: root.keycardState displayPromoBanner: root.displayKeycardPromoBanner + unlockUsingSeedphrase: true onReloadKeycardRequested: d.reload() onKeycardFactoryResetRequested: root.keycardFactoryResetRequested() + onUnlockWithSeedphraseRequested: root.stackView.push(seedphrasePage) onEmptyKeycardDetected: root.stackView.replace(keycardEmptyPage) onNotEmptyKeycardDetected: root.stackView.replace(keycardEnterPinPage) } @@ -78,6 +83,7 @@ SQUtils.QObject { KeycardEnterPinPage { tryToSetPinFunction: root.tryToSetPinFunction remainingAttempts: root.remainingAttempts + unlockUsingSeedphrase: true onKeycardPinEntered: { root.keycardPinEntered(pin) @@ -86,6 +92,32 @@ SQUtils.QObject { onReloadKeycardRequested: d.reload() onKeycardFactoryResetRequested: root.keycardFactoryResetRequested() + onUnlockWithSeedphraseRequested: root.stackView.push(seedphrasePage) + } + } + + Component { + id: seedphrasePage + + SeedphrasePage { + title: qsTr("Unlock Keycard using the recovery phrase") + btnContinueText: qsTr("Unlock") + isSeedPhraseValid: root.isSeedPhraseValid + onSeedphraseSubmitted: (seedphrase) => { + root.seedphraseSubmitted(seedphrase) + root.stackView.push(keycardCreatePinPage) + } + } + } + + Component { + id: keycardCreatePinPage + + KeycardCreatePinPage { + onKeycardPinCreated: { + root.keycardPinCreated(pin) + root.finished() + } } } } diff --git a/ui/app/AppLayouts/Onboarding2/OnboardingFlow.qml b/ui/app/AppLayouts/Onboarding2/OnboardingFlow.qml index 8115310a79..c850432cac 100644 --- a/ui/app/AppLayouts/Onboarding2/OnboardingFlow.qml +++ b/ui/app/AppLayouts/Onboarding2/OnboardingFlow.qml @@ -37,6 +37,7 @@ SQUtils.QObject { signal seedphraseSubmitted(string seedphrase) signal setPasswordRequested(string password) signal reloadKeycardRequested + signal keycardFactoryResetRequested signal finished(int flow) @@ -162,6 +163,7 @@ SQUtils.QObject { splashScreenDurationMs: root.splashScreenDurationMs onReloadKeycardRequested: root.reloadKeycardRequested() + onKeycardFactoryResetRequested: root.keycardFactoryResetRequested() onKeycardPinCreated: (pin) => root.keycardPinCreated(pin) onLoginWithKeycardRequested: loginWithKeycardFlow.init() @@ -214,10 +216,14 @@ SQUtils.QObject { remainingAttempts: root.remainingAttempts displayKeycardPromoBanner: root.displayKeycardPromoBanner tryToSetPinFunction: root.tryToSetPinFunction + isSeedPhraseValid: root.isSeedPhraseValid onKeycardPinEntered: (pin) => root.keycardPinEntered(pin) + onKeycardPinCreated: (pin) => root.keycardPinCreated(pin) + onSeedphraseSubmitted: (seedphrase) => root.seedphraseSubmitted(seedphrase) onReloadKeycardRequested: root.reloadKeycardRequested() onCreateProfileWithEmptyKeycardRequested: keycardCreateProfileFlow.init() + onKeycardFactoryResetRequested: root.keycardFactoryResetRequested() onFinished: { d.flow = Onboarding.SecondaryFlow.LoginWithKeycard diff --git a/ui/app/AppLayouts/Onboarding2/pages/KeycardCreatePinPage.qml b/ui/app/AppLayouts/Onboarding2/pages/KeycardCreatePinPage.qml index acc9b5f670..d3c96c749d 100644 --- a/ui/app/AppLayouts/Onboarding2/pages/KeycardCreatePinPage.qml +++ b/ui/app/AppLayouts/Onboarding2/pages/KeycardCreatePinPage.qml @@ -7,6 +7,7 @@ import StatusQ.Components 0.1 import StatusQ.Controls 0.1 import StatusQ.Controls.Validators 0.1 import StatusQ.Core.Theme 0.1 +import StatusQ.Core.Backpressure 0.1 import AppLayouts.Onboarding2.controls 1.0 @@ -103,7 +104,7 @@ KeycardBasePage { StateChangeScript { script: { pinInput.setPin(d.pin) - root.keycardPinCreated(d.pin) + Backpressure.debounce(root, 2000, () => root.keycardPinCreated(d.pin))() } } }, diff --git a/ui/app/AppLayouts/Onboarding2/pages/KeycardEnterPinPage.qml b/ui/app/AppLayouts/Onboarding2/pages/KeycardEnterPinPage.qml index 3004a1cdc2..21b02a328d 100644 --- a/ui/app/AppLayouts/Onboarding2/pages/KeycardEnterPinPage.qml +++ b/ui/app/AppLayouts/Onboarding2/pages/KeycardEnterPinPage.qml @@ -17,9 +17,11 @@ KeycardBasePage { property var tryToSetPinFunction: (pin) => { console.error("tryToSetPinFunction: IMPLEMENT ME"); return false } required property int remainingAttempts + property bool unlockUsingSeedphrase signal keycardPinEntered(string pin) signal reloadKeycardRequested() + signal unlockWithSeedphraseRequested() signal keycardFactoryResetRequested() pageClassName: "KeycardEnterPinPage" @@ -63,6 +65,13 @@ KeycardBasePage { text: qsTr("Factory reset Keycard") onClicked: root.keycardFactoryResetRequested() }, + StatusButton { + id: btnUnlockWithSeedphrase + visible: false + text: qsTr("Unlock with recovery phrase") + anchors.horizontalCenter: parent.horizontalCenter + onClicked: root.unlockWithSeedphraseRequested() + }, StatusButton { id: btnReload width: 320 @@ -96,7 +105,11 @@ KeycardBasePage { } PropertyChanges { target: btnFactoryReset - visible: true + visible: !root.unlockUsingSeedphrase + } + PropertyChanges { + target: btnUnlockWithSeedphrase + visible: root.unlockUsingSeedphrase } PropertyChanges { target: btnReload @@ -135,9 +148,7 @@ KeycardBasePage { } StateChangeScript { script: { - Backpressure.debounce(root, 2000, function() { - root.keycardPinEntered(pinInput.pinInput) - })() + Backpressure.debounce(root, 2000, () => root.keycardPinEntered(pinInput.pinInput))() } } }, diff --git a/ui/app/AppLayouts/Onboarding2/pages/KeycardIntroPage.qml b/ui/app/AppLayouts/Onboarding2/pages/KeycardIntroPage.qml index e61866a718..3c88cda384 100644 --- a/ui/app/AppLayouts/Onboarding2/pages/KeycardIntroPage.qml +++ b/ui/app/AppLayouts/Onboarding2/pages/KeycardIntroPage.qml @@ -17,8 +17,10 @@ KeycardBasePage { required property int keycardState // cf Onboarding.KeycardState property bool displayPromoBanner + property bool unlockUsingSeedphrase signal keycardFactoryResetRequested() + signal unlockWithSeedphraseRequested() signal reloadKeycardRequested() signal emptyKeycardDetected() signal notEmptyKeycardDetected() @@ -87,6 +89,13 @@ KeycardBasePage { anchors.horizontalCenter: parent.horizontalCenter onClicked: root.keycardFactoryResetRequested() }, + MaybeOutlineButton { + id: btnUnlockWithSeedphrase + visible: false + text: qsTr("Unlock with recovery phrase") + anchors.horizontalCenter: parent.horizontalCenter + onClicked: root.unlockWithSeedphraseRequested() + }, MaybeOutlineButton { id: btnReload visible: false @@ -190,12 +199,17 @@ KeycardBasePage { PropertyChanges { target: root title: "".arg(Theme.palette.dangerColor1) + qsTr("Keycard locked") + "" - subtitle: qsTr("The Keycard you have inserted is locked, you will need to factory reset it or insert a different one") + subtitle: root.unlockUsingSeedphrase ? qsTr("The Keycard you have inserted is locked, you will need to unlock it using the recovery phrase or insert a different one") + : qsTr("The Keycard you have inserted is locked, you will need to factory reset it or insert a different one") image.source: Theme.png("onboarding/keycard/error") } PropertyChanges { target: btnFactoryReset - visible: true + visible: !root.unlockUsingSeedphrase + } + PropertyChanges { + target: btnUnlockWithSeedphrase + visible: root.unlockUsingSeedphrase } PropertyChanges { target: btnReload diff --git a/ui/app/AppLayouts/Onboarding2/pages/SeedphrasePage.qml b/ui/app/AppLayouts/Onboarding2/pages/SeedphrasePage.qml index b79e842bcf..b410da57e2 100644 --- a/ui/app/AppLayouts/Onboarding2/pages/SeedphrasePage.qml +++ b/ui/app/AppLayouts/Onboarding2/pages/SeedphrasePage.qml @@ -14,6 +14,7 @@ OnboardingPage { title: qsTr("Create profile using a recovery phrase") property string subtitle: qsTr("Enter your 12, 18 or 24 word recovery phrase") + property alias btnContinueText: btnContinue.text property var isSeedPhraseValid: (mnemonic) => { console.error("isSeedPhraseValid IMPLEMENT ME"); return false } @@ -53,6 +54,7 @@ OnboardingPage { } StatusButton { + id: btnContinue objectName: "btnContinue" Layout.alignment: Qt.AlignHCenter Layout.topMargin: -Theme.halfPadding