feat(LoginWithKeycardFlow): implement "Unlock with recovery phrase"

- instead of the factory reset when the keycard is locked
This commit is contained in:
Lukáš Tinkl 2025-01-06 18:11:49 +01:00 committed by Lukáš Tinkl
parent 7547442e39
commit 151ffbe503
6 changed files with 73 additions and 7 deletions

View File

@ -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()
}
}
}
}

View File

@ -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

View File

@ -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))()
}
}
},

View File

@ -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))()
}
}
},

View File

@ -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: "<font color='%1'>".arg(Theme.palette.dangerColor1) + qsTr("Keycard locked") + "</font>"
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

View File

@ -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