fix(@desktop): Refactor Backupseed modal

Close #6144
This commit is contained in:
MishkaRogachev 2022-06-28 13:55:33 +03:00 committed by Mikhail Rogachev
parent 97a553ff8c
commit 6d72e19568
11 changed files with 341 additions and 340 deletions

View File

@ -91,6 +91,7 @@ Flickable {
StatusStackModal {
anchors.centerIn: parent
width: 640
replaceItem: CommunityColorPanel {
Component.onCompleted: color = colorPicker.color
onAccepted: {
@ -113,6 +114,7 @@ Flickable {
StatusStackModal {
anchors.centerIn: parent
width: 640
replaceItem: CommunityTagsPanel {
Component.onCompleted: {
tags = tagsPicker.tags;

View File

@ -26,6 +26,13 @@ StatusStackModal {
property var store
stackTitle: qsTr("Create New Community")
width: 640
nextButton: StatusButton {
text: qsTr("Next")
enabled: nameInput.valid && descriptionTextInput.valid
onClicked: currentIndex++
}
finishButton: StatusButton {
text: qsTr("Create Community")
@ -36,9 +43,6 @@ StatusStackModal {
stackItems: [
Flickable {
id: generalView
readonly property bool canGoNext: nameInput.valid && descriptionTextInput.valid
clip: true
contentHeight: generalViewLayout.height
implicitHeight: generalViewLayout.implicitHeight
@ -125,7 +129,6 @@ StatusStackModal {
},
ColumnLayout {
id: introOutroMessageView
spacing: 12
CommunityIntroMessageInput {

View File

@ -14,102 +14,113 @@ import StatusQ.Core.Theme 0.1
import "backupseed"
StatusModal {
id: popup
width: 480
height: 748
header.title: qsTr("Back up your seed phrase")
StatusStackModal {
id: root
property var privacyStore
rightButtons: [
StatusFlatButton {
text: "Not Now"
visible: (stack.currentIndex === 0)
QtObject {
id: d
readonly property int firstRandomNo: getRandomWordNumber()
readonly property int secondRandomNo: {
var num = firstRandomNo;
while (num === firstRandomNo) {
num = getRandomWordNumber();
}
return num;
}
property alias seedHidden: confirmSeedPhrase.hideSeed
property alias seedStored: confirmStoringSeedPhrase.seedStored
property alias validFirstSeedWord: confirmFirstWord.inputValid
property alias validSecondSeedWord: confirmSecondWord.inputValid
property Item skipButton: StatusButton {
visible: currentIndex === 0
border.color: Theme.palette.baseColor2
onClicked: {
popup.close();
}
},
StatusButton {
enabled: {
if (stack.currentIndex === 0) {
return acknowledgment.allAccepted;
} else {
switch (backUp.bar.currentIndex) {
case 0:
return !backUp.seedHidden;
case 1:
return backUp.validFirstSeedWord;
case 2:
return backUp.validSecondSeedWord;
case 3:
return backUp.seedStored;
default:
return true;
}
}
}
text: {
if (stack.currentIndex === 1) {
if (backUp.bar.currentIndex === 0) {
return qsTr("Confirm Seed Phrase");
} else if (backUp.bar.currentIndex === 1 ||
backUp.bar.currentIndex === 2) {
return qsTr("Continue");
} else {
return qsTr("Complete & Delete My Seed Phrase");
}
} else {
return qsTr("Confirm Seed Phrase");
}
}
onClicked: {
if (stack.currentIndex === 0) {
stack.currentIndex = 1;
} else {
switch (backUp.bar.currentIndex) {
case 0:
case 1:
case 2:
backUp.bar.currentIndex++;
break;
case 3:
popup.privacyStore.removeMnemonic();
popup.close();
break;
}
}
}
text: qsTr("Not Now")
onClicked: root.close()
}
]
leftButtons: [
StatusRoundButton {
visible: (stack.currentIndex === 1)
icon.name: "arrow-right"
rotation: 180
onClicked: {
if (backUp.bar.currentIndex === 0) {
stack.currentIndex = 0;
} else {
backUp.bar.currentIndex--;
}
}
function getRandomWordNumber() {
return Math.floor(Math.random() * 12);
}
]
contentItem: StackLayout {
id: stack
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
anchors.top: parent.top
anchors.topMargin: 80
anchors.bottom: parent.bottom
anchors.bottomMargin: 88
Acknowledgements { id: acknowledgment }
Backup { id: backUp; privacyStore: popup.privacyStore }
}
width: 480
header.title: qsTr("Back up your seed phrase")
rightButtons: [ nextButton, finishButton, d.skipButton ]
nextButton: StatusButton {
enabled: {
switch (root.currentIndex) {
case 0:
return acknowledgment.allAccepted;
case 1:
return !d.seedHidden;
case 2:
return d.validFirstSeedWord;
case 3:
return d.validSecondSeedWord;
default:
return true;
}
}
text: {
switch (root.currentIndex) {
case 0:
case 1:
return qsTr("Confirm Seed Phrase");
case 2:
case 3:
return qsTr("Continue");;
default:
return "";
}
}
onClicked: root.currentIndex++
}
finishButton: StatusButton {
text: qsTr("Complete & Delete My Seed Phrase")
enabled: d.seedStored
onClicked: {
root.privacyStore.removeMnemonic();
root.close();
}
}
subHeaderItem: SubheaderTabBar {
// Count without Acknowledgements
steps: root.itemsCount - 1
currentIndex: root.currentIndex - 1
visible: root.currentIndex > 0
}
stackItems: [
Acknowledgements {
id: acknowledgment
},
ConfirmSeedPhrasePanel {
id: confirmSeedPhrase
seedPhrase: root.privacyStore.getMnemonic().split(" ")
},
BackupSeedStepBase {
id: confirmFirstWord
titleText: qsTr("Confirm word #%1 of your seed phrase").arg(d.firstRandomNo + 1)
wordRandomNumber: d.firstRandomNo
wordAtRandomNumber: root.privacyStore.getMnemonicWordAtIndex(d.firstRandomNo)
},
BackupSeedStepBase {
id: confirmSecondWord
titleText: qsTr("Confirm word #%1 of your seed phrase").arg(d.secondRandomNo + 1)
wordRandomNumber: d.secondRandomNo
wordAtRandomNumber: root.privacyStore.getMnemonicWordAtIndex(d.secondRandomNo)
},
ConfirmStoringSeedPhrasePanel {
id: confirmStoringSeedPhrase
}
]
}

View File

@ -3,89 +3,96 @@ import QtQuick.Layouts 1.12
import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
import shared.panels 1.0
import utils 1.0
Item {
anchors.fill: parent
objectName: "acknowledgment"
property bool allAccepted: (havePen.checked && writeDown.checked && storeIt.checked)
Image {
id: keysImg
width: 120
height: 120
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
fillMode: Image.PreserveAspectFit
source: Style.png("onboarding/keys")
mipmap: true
}
ColumnLayout {
id: root
StyledText {
id: txtTitle
text: qsTr("Secure Your Assets and Funds")
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
anchors.right: parent.right
anchors.left: parent.left
font.bold: true
anchors.top: keysImg.bottom
anchors.topMargin: Style.current.padding
font.pixelSize: 22
}
readonly property bool allAccepted: havePen.checked && writeDown.checked && storeIt.checked
StyledText {
id: txtDesc
anchors.top: txtTitle.bottom
anchors.topMargin: Style.current.padding
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: Style.current.primaryTextFontSize
font.letterSpacing: -0.2
text: qsTr("Your seed phrase is a 12-word passcode to your funds.")
}
spacing: Style.current.padding
implicitHeight: 520
StyledText {
id: secondTxtDesc
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
anchors.leftMargin: Style.current.padding
anchors.left: parent.left
anchors.top: txtDesc.bottom
anchors.topMargin: Style.current.bigPadding
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
textFormat: Text.RichText
font.pixelSize: Style.current.primaryTextFontSize
text: qsTr("Your seed phrase cannot be recovered if lost. Therefore, you <b>must</b> back it up. The simplest way is to <b>write it down offline and store it somewhere secure.</b>")
}
Flickable {
id: flick
clip: true
contentHeight: flickLayout.height
implicitHeight: flickLayout.implicitHeight
interactive: contentHeight > height
flickableDirection: Flickable.VerticalFlick
Layout.fillWidth: true
Layout.fillHeight: true
ColumnLayout {
anchors.topMargin: 49
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: secondTxtDesc.bottom
spacing: Style.current.padding
StatusCheckBox {
id: havePen
ColumnLayout {
id: flickLayout
width: parent.width
text: qsTr("I have a pen and paper")
}
StatusCheckBox {
id: writeDown
width: parent.width
text: qsTr("I am ready to write down my seed phrase")
}
StatusCheckBox {
id: storeIt
width: parent.width
text: qsTr("I know where Ill store it")
spacing: Style.current.padding
Image {
id: keysImg
fillMode: Image.PreserveAspectFit
source: Style.png("onboarding/keys")
mipmap: true
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 120
Layout.preferredHeight: width
}
StyledText {
id: txtTitle
text: qsTr("Secure Your Assets and Funds")
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
font.bold: true
font.pixelSize: 22
Layout.fillWidth: true
}
StyledText {
id: txtDesc
font.pixelSize: Style.current.primaryTextFontSize
font.letterSpacing: -0.2
text: qsTr("Your seed phrase is a 12-word passcode to your funds.")
Layout.fillWidth: true
}
StyledText {
id: secondTxtDesc
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
textFormat: Text.RichText
font.pixelSize: Style.current.primaryTextFontSize
text: qsTr("Your seed phrase cannot be recovered if lost. Therefore, you <b>must</b> back it up. The simplest way is to <b>write it down offline and store it somewhere secure.</b>")
Layout.fillWidth: true
}
StatusCheckBox {
id: havePen
text: qsTr("I have a pen and paper")
Layout.fillWidth: true
}
StatusCheckBox {
id: writeDown
text: qsTr("I am ready to write down my seed phrase")
Layout.fillWidth: true
}
StatusCheckBox {
id: storeIt
text: qsTr("I know where Ill store it")
Layout.fillWidth: true
}
}
}
Item {
width: parent.width
height: 60
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
color: Theme.palette.statusModal.backgroundColor
Layout.fillWidth: true
Layout.preferredHeight: 60
StyledText {
anchors.fill: parent
anchors.margins: Style.current.halfPadding
@ -96,6 +103,7 @@ Item {
color: Theme.palette.dangerColor1
text: qsTr("You can only complete this process once. Status will not store your seed phrase and can never help you recover it.")
}
Rectangle {
anchors.fill: parent
radius: 8

View File

@ -1,79 +0,0 @@
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
import StatusQ.Core.Theme 0.1
import shared.panels 1.0
import utils 1.0
Item {
id: root
property var privacyStore
property alias bar: bar
property alias seedHidden: confirmSeedPhrase.hideSeed
property alias seedStored: confirmStoringSeedPhrase.seedStored
property int firstRandomNo: Math.floor(Math.random() * 12)
property alias validFirstSeedWord: confirmFirstWord.inputValid
property alias validSecondSeedWord: confirmSecondWord.inputValid
property int secondRandomNo: {
var num = Math.floor(Math.random() * 12);
return (num === firstRandomNo) ? Math.floor(Math.random() * 12) : num;
}
anchors.fill: parent
StyledText {
id: txtDesc
anchors.right: parent.right
anchors.left: parent.left
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
font.pixelSize: Style.current.additionalTextSize
color: Style.current.secondaryText
text: qsTr("Step " + (bar.currentIndex+1) + " of " + bar.count)
}
TabBar {
id: bar
width: (59 * count)
height: 4
anchors.top: txtDesc.bottom
anchors.topMargin: Style.current.halfPadding
anchors.horizontalCenter: parent.horizontalCenter
spacing: 2
background: null
TabBarButton { index: 0; currentIndex: bar.currentIndex }
TabBarButton { index: 1; currentIndex: bar.currentIndex }
TabBarButton { index: 2; currentIndex: bar.currentIndex }
TabBarButton { index: 3; currentIndex: bar.currentIndex }
}
StackLayout {
id: stack
anchors.top: bar.bottom
anchors.topMargin: Style.current.halfPadding
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
currentIndex: bar.currentIndex
ConfirmSeedPhrasePanel {
id: confirmSeedPhrase
seedPhrase: root.privacyStore.getMnemonic().split(" ")
}
BackupSeedStepBase {
id: confirmFirstWord
titleText: qsTr("Confirm word #" + (root.firstRandomNo+1) + " of your seed phrase")
wordRandomNumber: root.firstRandomNo
wordAtRandomNumber: root.privacyStore.getMnemonicWordAtIndex(root.firstRandomNo)
}
BackupSeedStepBase {
id: confirmSecondWord
titleText: qsTr("Confirm word #" + (root.secondRandomNo+1) + " of your seed phrase")
wordRandomNumber: root.secondRandomNo
wordAtRandomNumber: root.privacyStore.getMnemonicWordAtIndex(root.secondRandomNo)
}
ConfirmStoringSeedPhrasePanel { id: confirmStoringSeedPhrase }
}
}

View File

@ -1,42 +1,58 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import StatusQ.Controls 0.1
import shared.panels 1.0
import StatusQ.Controls.Validators 0.1
import shared.panels 1.0
import utils 1.0
Item {
Flickable {
id: root
property int wordRandomNumber: -1
property string wordAtRandomNumber
property bool secondWordValid: true
property alias titleText: txtTitle.text
property alias inputValid: inputText.valid
StyledText {
id: txtTitle
anchors.right: parent.right
anchors.left: parent.left
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
font.pixelSize: Style.current.primaryTextFontSize
}
default property alias content: column.children
StatusInput {
id: inputText
visible: (wordRandomNumber > -1)
implicitWidth: 448
input.implicitHeight: 44
anchors.top: parent.top
anchors.topMargin: 40
anchors.horizontalCenter: parent.horizontalCenter
validationMode: StatusInput.ValidationMode.Always
label: qsTr("Word #" + (wordRandomNumber+1))
input.placeholderText: qsTr("Enter word")
validators: [
StatusValidator {
validate: function (t) { return (wordAtRandomNumber === inputText.text); }
errorMessage: (inputText.text.length) > 0 ? qsTr("Wrong word") : ""
}
]
clip: true
contentHeight: column.height
implicitHeight: 520
interactive: contentHeight > height
flickableDirection: Flickable.VerticalFlick
ColumnLayout {
id: column
width: parent.width
spacing: Style.current.padding
StyledText {
id: txtTitle
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
font.pixelSize: Style.current.primaryTextFontSize
Layout.fillWidth: true
}
StatusInput {
id: inputText
visible: (wordRandomNumber > -1)
implicitWidth: 448
input.implicitHeight: 44
validationMode: StatusInput.ValidationMode.Always
label: qsTr("Word #%1").arg(wordRandomNumber + 1)
input.placeholderText: qsTr("Enter word")
validators: [
StatusValidator {
validate: function (t) { return (root.wordAtRandomNumber === inputText.text); }
errorMessage: (inputText.text.length) > 0 ? qsTr("Wrong word") : ""
}
]
Layout.fillWidth: true
}
}
}

View File

@ -1,69 +1,72 @@
import QtQuick 2.12
import StatusQ.Controls 0.1
import QtQuick.Layouts 1.12
import QtGraphicalEffects 1.13
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import shared.panels 1.0
import utils 1.0
BackupSeedStepBase {
id: root
property var seedPhrase
property var seedPhrase: []
property bool hideSeed: true
titleText: qsTr("Write down your 12-word seed phrase to keep offline")
GridView {
id: grid
width: parent.width
height: 304
anchors.left: parent.left
anchors.leftMargin: 2
anchors.top: parent.top
anchors.topMargin: 88
flow: GridView.FlowTopToBottom
cellWidth: 208
cellHeight: 48
interactive: false
model: 12
property var wordIndex: ["1", "3", "5", "7", "9", "11", "2", "4", "6", "8", "10", "12"]
delegate: StatusSeedPhraseInput {
id: seedWordInput
width: (grid.cellWidth - 4)
height: (grid.cellHeight - 4)
textEdit.input.edit.enabled: false
text: root.seedPhrase[parseInt(leftComponentText)-1]
leftComponentText: grid.wordIndex[index]
Item {
implicitHeight: 304
Layout.fillWidth: true
GridView {
id: grid
anchors.fill: parent
visible: !hideSeed
flow: GridView.FlowTopToBottom
cellWidth: 208
cellHeight: 48
interactive: false
model: 12
property var wordIndex: ["1", "3", "5", "7", "9", "11", "2", "4", "6", "8", "10", "12"]
delegate: StatusSeedPhraseInput {
id: seedWordInput
width: (grid.cellWidth - 4)
height: (grid.cellHeight - 4)
textEdit.input.edit.enabled: false
text: {
var index = parseInt(leftComponentText) - 1;
if (!root.seedPhrase || index < 0 || index > root.seedPhrase.length - 1)
return "";
return root.seedPhrase[index];
}
leftComponentText: grid.wordIndex[index]
}
}
}
GaussianBlur {
id: blur
anchors.fill: grid
visible: hideSeed
source: grid
radius: 16
samples: 16
}
GaussianBlur {
id: blur
anchors.fill: grid
visible: hideSeed
source: grid
radius: 16
samples: 16
}
StatusButton {
anchors.centerIn: grid
visible: hideSeed
icon.name: "view"
text: qsTr("Reveal seed phrase")
onClicked: {
hideSeed = false;
StatusButton {
anchors.centerIn: parent
visible: hideSeed
icon.name: "view"
text: qsTr("Reveal seed phrase")
onClicked: {
hideSeed = false;
}
}
}
StyledText {
id: text
anchors.left: parent.left
//anchors.leftMargin: Style.current.bigPadding
anchors.right: parent.right
//anchors.rightMargin: Style.current.bigPadding
anchors.top: grid.bottom
anchors.topMargin: 36
visible: hideSeed
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
@ -72,5 +75,6 @@ BackupSeedStepBase {
textFormat: Text.RichText
color: Theme.palette.dangerColor1
text: qsTr("The next screen contains your seed phrase.\n<b>Anyone</b> who sees it can use it to access to your funds.")
Layout.fillWidth: true
}
}

View File

@ -1,54 +1,49 @@
import QtQuick 2.12
import utils 1.0
import shared.panels 1.0
import QtQuick.Layouts 1.12
import StatusQ.Controls 0.1
import utils 1.0
import shared.panels 1.0
BackupSeedStepBase {
titleText: qsTr("Complete back up")
id: root
property bool seedStored: storeCheck.checked
titleText: qsTr("Complete back up")
StyledText {
id: txtTitle
anchors.top: parent.top
anchors.topMargin: 40
anchors.right: parent.right
anchors.left: parent.left
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
font.bold: true
font.pixelSize: 17
text: qsTr("Store Your Phrase Offline and Complete Your Back Up")
Layout.fillWidth: true
}
StyledText {
id: txtDesc
anchors.top: txtTitle.bottom
anchors.topMargin: Style.current.padding
anchors.right: parent.right
anchors.left: parent.left
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
font.pixelSize: Style.current.primaryTextFontSize
text: qsTr("By completing this process, you will remove your seed phrase from this applications storage. This makes your funds more secure.")
Layout.fillWidth: true
}
StyledText {
id: secondTxtDesc
anchors.right: parent.right
anchors.left: parent.left
anchors.top: txtDesc.bottom
anchors.topMargin: Style.current.bigPadding
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
font.pixelSize: Style.current.primaryTextFontSize
text: qsTr("You will remain logged in, and your seed phrase will be entirely in your hands.")
Layout.fillWidth: true
}
StatusCheckBox {
id: storeCheck
width: parent.width
anchors.top: secondTxtDesc.bottom
anchors.topMargin: 48
text: qsTr("I aknowledge that Status will not be able to show me my seed phrase again.")
Layout.fillWidth: true
}
}

View File

@ -0,0 +1,43 @@
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
import StatusQ.Core.Theme 0.1
import StatusQ.Core 0.1
import shared.panels 1.0
import utils 1.0
ColumnLayout {
id: root
property int steps: 4
property int currentIndex: 0
spacing: Style.current.halfPadding
StyledText {
id: txtDesc
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
font.pixelSize: Style.current.additionalTextSize
color: Style.current.secondaryText
text: qsTr("Step %1 of %2").arg(root.currentIndex + 1).arg(steps)
Layout.fillWidth: true
}
TabBar {
id: bar
height: 4
spacing: 2
background: null
Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: 59 * steps
Repeater {
model: steps
SubheaderTabButton { index: modelData; currentIndex: root.currentIndex}
}
}
}

View File

@ -100,10 +100,7 @@ Item {
var popup = changeProfilePicComponent.createObject(appMain);
popup.chooseImageToCrop();
}
onOpenBackUpSeedPopup: {
var popup = backupSeedModalComponent.createObject(appMain)
popup.open()
}
onOpenBackUpSeedPopup: Global.openPopup(backupSeedModalComponent)
onDisplayToastMessage: {
appMain.rootStore.mainModuleInst.displayEphemeralNotification(title, subTitle, icon, loading, ephNotifType, url);
}
@ -153,6 +150,7 @@ Item {
id: backupSeedModal
anchors.centerIn: parent
privacyStore: appMain.rootStore.profileSectionStore.privacyStore
onClosed: destroy()
}
property Component displayNamePopupComponent: DisplayNamePopup {