status-desktop/ui/app/AppLayouts/Onboarding2/KeycardCreateProfileFlow.qml
Lukáš Tinkl 638676ed0b feat(Onboarding) Implement new Login screen
- implement the new UI and frontend logic of the Login screen
- integrate it (as a separate page) into the OnboardingLayout
- add SB pages
- add an integration QML test
- add some TODOs and FIXMEs for the existing and new external flows,
which will be covered separately in followup PRs

Fixes #17057
2025-01-23 17:41:43 +01:00

213 lines
6.0 KiB
QML

import QtQuick 2.15
import QtQuick.Controls 2.15
import StatusQ.Core.Utils 0.1 as SQUtils
import StatusQ.Core.Backpressure 0.1
import AppLayouts.Onboarding2.pages 1.0
import AppLayouts.Onboarding.enums 1.0
SQUtils.QObject {
id: root
required property StackView stackView
required property int keycardState
required property int addKeyPairState
required property int keycardPinInfoPageDelay
required property var seedWords
required property var isSeedPhraseValid
property bool displayKeycardPromoBanner
signal loginWithKeycardRequested
signal keycardFactoryResetRequested
signal keyPairTransferRequested
signal keycardPinCreated(string pin)
signal seedphraseSubmitted(string seedphrase)
signal keypairAddTryAgainRequested
signal reloadKeycardRequested
signal createProfileWithoutKeycardRequested
signal mnemonicWasShown()
signal mnemonicRemovalRequested()
signal finished(bool fromBackupSeedphrase)
function init() {
root.stackView.push(d.initialComponent())
}
QtObject {
id: d
property bool fromBackupSeedphrase
function initialComponent() {
if (root.keycardState === Onboarding.KeycardState.Empty)
return createKeycardProfilePage
if (root.keycardState === Onboarding.KeycardState.NotEmpty)
return keycardNotEmptyPage
return keycardIntroPage
}
}
Component {
id: keycardIntroPage
KeycardIntroPage {
keycardState: root.keycardState
displayPromoBanner: root.displayKeycardPromoBanner
onReloadKeycardRequested: {
root.reloadKeycardRequested()
root.stackView.replace(d.initialComponent(),
StackView.PopTransition)
}
onKeycardFactoryResetRequested: root.keycardFactoryResetRequested()
onEmptyKeycardDetected: root.stackView.replace(createKeycardProfilePage)
onNotEmptyKeycardDetected: root.stackView.replace(keycardNotEmptyPage)
}
}
Component {
id: createKeycardProfilePage
CreateKeycardProfilePage {
onCreateKeycardProfileWithNewSeedphrase:
root.stackView.push(backupSeedIntroPage)
onCreateKeycardProfileWithExistingSeedphrase:
root.stackView.push(seedphrasePage)
}
}
Component {
id: keycardNotEmptyPage
KeycardNotEmptyPage {
onReloadKeycardRequested: {
root.reloadKeycardRequested()
root.stackView.replace(d.initialComponent(),
StackView.PopTransition)
}
onLoginWithThisKeycardRequested: root.loginWithKeycardRequested()
onKeycardFactoryResetRequested: root.keycardFactoryResetRequested()
}
}
Component {
id: backupSeedIntroPage
BackupSeedphraseIntro {
onBackupSeedphraseRequested: root.stackView.push(backupSeedAcksPage)
}
}
Component {
id: backupSeedAcksPage
BackupSeedphraseAcks {
onBackupSeedphraseContinue: root.stackView.push(backupSeedRevealPage)
}
}
Component {
id: backupSeedRevealPage
BackupSeedphraseReveal {
seedWords: root.seedWords
onMnemonicWasShown: root.mnemonicWasShown()
onBackupSeedphraseConfirmed: root.stackView.push(backupSeedVerifyPage)
}
}
Component {
id: backupSeedVerifyPage
BackupSeedphraseVerify {
seedWordsToVerify: {
const randomIndexes = SQUtils.Utils.nSamples(4, root.seedWords.length)
return randomIndexes.map(i => ({ seedWordNumber: i+1,
seedWord: root.seedWords[i]
}))
}
onBackupSeedphraseVerified: root.stackView.push(backupSeedOutroPage)
}
}
Component {
id: backupSeedOutroPage
BackupSeedphraseOutro {
onBackupSeedphraseRemovalConfirmed: {
root.mnemonicRemovalRequested()
root.stackView.push(keycardCreatePinPage)
}
}
}
Component {
id: seedphrasePage
SeedphrasePage {
title: qsTr("Create profile on empty Keycard using a recovery phrase")
isSeedPhraseValid: root.isSeedPhraseValid
onSeedphraseSubmitted: (seedphrase) => {
root.seedphraseSubmitted(seedphrase)
root.stackView.push(keycardCreatePinPage)
}
StackView.onActivated: d.fromBackupSeedphrase = true
}
}
Component {
id: keycardCreatePinPage
KeycardCreatePinPage {
onKeycardPinCreated: (pin) => {
Backpressure.debounce(root, root.keycardPinInfoPageDelay, () => {
root.keycardPinCreated(pin)
root.keyPairTransferRequested()
root.stackView.push(addKeypairPage)
})()
}
}
}
Component {
id: addKeypairPage
KeycardAddKeyPairPage {
readonly property bool backAvailableHint: false
addKeyPairState: root.addKeyPairState
onKeypairAddContinueRequested: root.finished(d.fromBackupSeedphrase)
onKeypairAddTryAgainRequested: {
root.stackView.replace(addKeypairPage)
root.keypairAddTryAgainRequested()
}
onReloadKeycardRequested: {
root.reloadKeycardRequested()
const page = root.stackView.find(
item => item instanceof CreateKeycardProfilePage)
root.stackView.replace(page, d.initialComponent(),
StackView.PopTransition)
}
onCreateProfilePageRequested: root.createProfileWithoutKeycardRequested()
}
}
}