From 046aa365655ab65e67fbf5beff0d36d713d9df59 Mon Sep 17 00:00:00 2001 From: Alexandra Betouni Date: Thu, 26 May 2022 16:40:41 +0300 Subject: [PATCH] feat(settings): Adding new Backup Seed Phrase section & modal Closes #4918 --- .../AppLayouts/Profile/panels/MenuPanel.qml | 22 +- .../Profile/popups/BackupSeedModal.qml | 364 +++++------------- .../popups/backupseed/Acknowledgements.qml | 106 +++++ .../Profile/popups/backupseed/Backup.qml | 79 ++++ .../popups/backupseed/BackupSeedStepBase.qml | 42 ++ .../backupseed/ConfirmSeedPhrasePanel.qml | 76 ++++ .../ConfirmStoringSeedPhrasePanel.qml | 54 +++ .../popups/backupseed/TabBarButton.qml | 18 + .../Profile/stores/ProfileSectionStore.qml | 9 +- .../AppLayouts/Profile/views/LeftTabView.qml | 11 +- .../AppLayouts/Profile/views/PrivacyView.qml | 22 -- ui/app/mainui/AppMain.qml | 3 +- ui/imports/utils/Constants.qml | 1 + 13 files changed, 498 insertions(+), 309 deletions(-) create mode 100644 ui/app/AppLayouts/Profile/popups/backupseed/Acknowledgements.qml create mode 100644 ui/app/AppLayouts/Profile/popups/backupseed/Backup.qml create mode 100644 ui/app/AppLayouts/Profile/popups/backupseed/BackupSeedStepBase.qml create mode 100644 ui/app/AppLayouts/Profile/popups/backupseed/ConfirmSeedPhrasePanel.qml create mode 100644 ui/app/AppLayouts/Profile/popups/backupseed/ConfirmStoringSeedPhrasePanel.qml create mode 100644 ui/app/AppLayouts/Profile/popups/backupseed/TabBarButton.qml diff --git a/ui/app/AppLayouts/Profile/panels/MenuPanel.qml b/ui/app/AppLayouts/Profile/panels/MenuPanel.qml index b848d27968..2a6b8ff959 100644 --- a/ui/app/AppLayouts/Profile/panels/MenuPanel.qml +++ b/ui/app/AppLayouts/Profile/panels/MenuPanel.qml @@ -30,8 +30,21 @@ Column { icon.name: model.icon selected: Global.settingsSubsection === model.subsection onClicked: root.menuItemClicked(model) + badge.value: { + switch (model.subsection) { + case Constants.settingsSubsection.backUpSeed: + return !root.privacyStore.mnemonicBackedUp + default: return ""; + } + } visible: { - (model.subsection !== Constants.settingsSubsection.ensUsernames || root.walletMenuItemEnabled) + switch (model.subsection) { + case Constants.settingsSubsection.ensUsernames: + return root.walletMenuItemEnabled; + case Constants.settingsSubsection.backUpSeed: + return !root.privacyStore.mnemonicBackedUp; + default: return true; + } } } } @@ -76,13 +89,6 @@ Column { selected: Global.settingsSubsection === model.subsection onClicked: root.menuItemClicked(model) visible: model.subsection !== Constants.settingsSubsection.browserSettings || root.browserMenuItemEnabled - badge.value: { - switch (model.subsection) { - case Constants.settingsSubsection.privacyAndSecurity: - return !root.privacyStore.mnemonicBackedUp - default: return "" - } - } } } diff --git a/ui/app/AppLayouts/Profile/popups/BackupSeedModal.qml b/ui/app/AppLayouts/Profile/popups/BackupSeedModal.qml index 48e51a092a..879e22993e 100644 --- a/ui/app/AppLayouts/Profile/popups/BackupSeedModal.qml +++ b/ui/app/AppLayouts/Profile/popups/BackupSeedModal.qml @@ -1,293 +1,115 @@ import QtQuick 2.12 -import QtQuick.Controls 2.3 -import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.14 import utils 1.0 import shared.panels 1.0 import shared.popups 1.0 import shared.controls 1.0 +import StatusQ.Core 0.1 +import StatusQ.Popups 0.1 import StatusQ.Controls 0.1 +import StatusQ.Core.Theme 0.1 -// TODO: replace with StatusModal -ModalPopup { +import "backupseed" + +StatusModal { id: popup + width: 480 + height: 748 + header.title: qsTr("Back up your seed phrase") property var privacyStore - property bool showWarning: true - property int seedWord1Idx: -1; - property int seedWord2Idx: -1; - property string validationError: "" - - focus: visible - - onOpened: { - seedWord1Idx = -1; - seedWord2Idx = -1; - txtFieldWord.text = ""; - validationError = ""; - } - - header: Item { - height: 50 - StyledText { - id: lblTitle - //% "Back up seed phrase" - text: qsTrId("back-up-seed-phrase") - font.pixelSize: 17 - font.bold: true - anchors.left: parent.left - } - StyledText { - anchors.top: lblTitle.bottom - anchors.topMargin: Style.current.smallPadding - //% "Step %1 of 3" - text: qsTrId("step--1-of-3").arg(seedWord2Idx > -1 ? 3 : (seedWord1Idx > -1 ? 2 : 1)) - font.pixelSize: 14 - anchors.left: parent.left - } - } - - Loader { - active: popup.opened && !showWarning && seedWord1Idx == -1 - width: parent.width - height: item ? item.height : 0 - - sourceComponent: Component { - id: seedComponent - Item { - id: seed - width: parent.width - height: children[0].height - - Rectangle { - id: wrapper - property int len: mnemonicRepeater.count - anchors.top: parent.top - anchors.topMargin: Style.current.padding - height: 40 * (len / 2) - width: 350 - border.width: 1 - color: Style.current.background - border.color: Style.current.border - radius: Style.current.radius - anchors.horizontalCenter: parent.horizontalCenter - - Repeater { - id: mnemonicRepeater - model: popup.privacyStore.getMnemonic().split(" ") - Rectangle { - id: word - height: 40 - width: 175 - color: "transparent" - anchors.top: (index == 0 - || index == (wrapper.len / 2)) ? parent.top : parent.children[index - 1].bottom - anchors.left: (index < (wrapper.len / 2)) ? parent.left : undefined - anchors.right: (index >= wrapper.len / 2) ? parent.right : undefined - - Rectangle { - width: 1 - height: parent.height - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.right: parent.right - anchors.rightMargin: 175 - color: Style.current.inputBackground - visible: index >= wrapper.len / 2 - } - - StyledText { - id: count - text: index + 1 - color: Style.current.secondaryText - anchors.bottom: parent.bottom - anchors.bottomMargin: Style.current.smallPadding - anchors.left: parent.left - anchors.leftMargin: Style.current.bigPadding - font.pixelSize: 15 - } - - StyledTextEdit { - text: modelData - font.pixelSize: 15 - anchors.bottom: parent.bottom - anchors.bottomMargin: Style.current.smallPadding - anchors.left: count.right - anchors.leftMargin: Style.current.padding - selectByMouse: true - readOnly: true - } - } - } - } + rightButtons: [ + StatusFlatButton { + text: "Not Now" + visible: (stack.currentIndex === 0) + border.color: Theme.palette.baseColor2 + onClicked: { + popup.close(); } - } - } - - Item { - visible: showWarning - anchors.left: parent.left - anchors.right: parent.right - StyledText { - id: lblLoseSeed - //% "If you lose your seed phrase you lose your data and funds" - text: qsTrId("your-data-belongs-to-you") - wrapMode: Text.WordWrap - font.pixelSize: 17 - font.bold: true - anchors.left: parent.left - anchors.right: parent.right - } - StyledText { - anchors.top: lblLoseSeed.bottom - anchors.topMargin: Style.current.smallPadding - wrapMode: Text.WordWrap - //% "If you lose access, for example by losing your phone, you can only access your keys with your seed phrase. No one, but you has your seed phrase. Write it down. Keep it safe" - text: qsTrId("your-data-belongs-to-you-description") - anchors.left: parent.left - anchors.right: parent.right - } - } - - Item { - id: textInput - visible: seedWord1Idx > -1 || seedWord2Idx > -1 - anchors.left: parent.left - anchors.right: parent.right - focus: visible - onActiveFocusChanged: { - if (activeFocus) - txtFieldWord.forceActiveFocus(Qt.MouseFocusReason) - } - Keys.onReturnPressed: function(event) { - confirmButton.clicked() - } - - StyledText { - id: txtChk - //% "Check your seed phrase" - text: qsTrId("check-your-recovery-phrase") - } - StyledText { - //% "Word #%1" - text: qsTrId("word---1").arg((seedWord2Idx > -1 ? seedWord2Idx : seedWord1Idx) + 1) - anchors.left: txtChk.right - anchors.leftMargin: 5 - color: Style.current.secondaryText - } - - Input { - id: txtFieldWord - anchors.top: txtChk.bottom - anchors.topMargin: Style.current.padding - anchors.left: txtChk.left - anchors.right: parent.right - //% "Enter word" - placeholderText: qsTrId("enter-word") - text: "" - validationError: popup.validationError - } - - StyledText { - anchors.top: txtFieldWord.bottom - anchors.topMargin: Style.current.padding - wrapMode: Text.WordWrap - anchors.left: parent.left - anchors.right: parent.right - //% "In order to check if you have backed up your seed phrase correctly, enter the word #%1 above" - text: qsTrId("in-order-to-check-if-you-have-backed-up-your-seed-phrase-correctly--enter-the-word---1-above").arg((seedWord2Idx > -1 ? seedWord2Idx : seedWord1Idx) + 1) - color: Style.current.secondaryText - } - - Component { - id: removeSeedPhraseConfirmDialogComponent - ConfirmationDialog { - id: confirmPopup - //% "Are you sure?" - header.title: qsTrId("are-you-sure?") - //% "You will not be able to see the whole seed phrase again" - confirmationText: qsTrId("are-you-sure-description") - onConfirmButtonClicked: { - popup.privacyStore.removeMnemonic() - popup.close(); - confirmPopup.close(); - } - onClosed: { - destroy(); - } - } - } - } - - StyledText { - id: confirmationsInfo - visible: !showWarning && seedWord1Idx == -1 - //% "With this 12 words you can always get your key back. Write it down. Keep it safe, offline, and separate from this device." - text: qsTrId( - "with-this-12-words-you-can-always-get-your-key-back.-write-it-down.-keep-it-safe,-offline,-and-separate-from-this-device.") - font.pixelSize: 14 - font.weight: Font.Medium - color: Style.current.secondaryText - anchors.bottom: parent.bottom - anchors.bottomMargin: Style.current.padding - anchors.left: parent.left - anchors.leftMargin: Style.current.smallPadding - anchors.right: parent.right - anchors.rightMargin: Style.current.smallPadding - wrapMode: Text.WordWrap - } - - - - footer: StatusButton { - id: confirmButton - text: showWarning ? - //% "Okay, continue" - qsTrId("ok-continue") : - //% "Next" - qsTrId("next") - anchors.right: parent.right - anchors.rightMargin: Style.current.smallPadding - anchors.bottom: parent.bottom - focus: !textInput.visible - Keys.onReturnPressed: function(event) { - confirmButton.clicked() - } - onClicked: { - if(showWarning){ - showWarning = false; - } else { - if(seedWord1Idx == -1){ - seedWord1Idx = Math.floor(Math.random() * 12); + }, + StatusButton { + enabled: { + if (stack.currentIndex === 0) { + return acknowledgment.allAccepted; } else { - if(seedWord2Idx == -1){ - if(popup.privacyStore.getMnemonicWordAtIndex(seedWord1Idx) !== txtFieldWord.text){ - //% "Wrong word" - validationError = qsTrId("wrong-word"); - return; - } - - validationError = ""; - txtFieldWord.text = ""; - - do { - seedWord2Idx = Math.floor(Math.random() * 12); - } while(seedWord2Idx == seedWord1Idx); + 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 { - if(popup.privacyStore.getMnemonicWordAtIndex(seedWord2Idx) !== txtFieldWord.text){ - //% "Wrong word" - validationError = qsTrId("wrong-word"); - return; - } - - validationError = ""; - txtFieldWord.text = ""; - Global.openPopup(removeSeedPhraseConfirmDialogComponent); + 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; } } } } + ] + + 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--; + } + } + } + ] + + 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 } } } diff --git a/ui/app/AppLayouts/Profile/popups/backupseed/Acknowledgements.qml b/ui/app/AppLayouts/Profile/popups/backupseed/Acknowledgements.qml new file mode 100644 index 0000000000..019fb23b88 --- /dev/null +++ b/ui/app/AppLayouts/Profile/popups/backupseed/Acknowledgements.qml @@ -0,0 +1,106 @@ +import QtQuick 2.12 +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 + } + + 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 + } + + 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.") + } + + 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 must back it up. The simplest way is to write it down offline and store it somewhere secure.") + } + + ColumnLayout { + anchors.topMargin: 49 + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: secondTxtDesc.bottom + spacing: Style.current.padding + StatusCheckBox { + id: havePen + width: parent.width + text: qsTrId("I have a pen and paper") + } + StatusCheckBox { + id: writeDown + width: parent.width + text: qsTrId("I am ready to write down my seed phrase") + } + StatusCheckBox { + id: storeIt + width: parent.width + text: qsTr("I know where I’ll store it") + } + } + + Item { + width: parent.width + height: 60 + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + StyledText { + anchors.fill: parent + anchors.margins: Style.current.halfPadding + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: Style.current.primaryTextFontSize + wrapMode: Text.WordWrap + 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 + color: Theme.palette.dangerColor1 + opacity: 0.1 + } + } +} diff --git a/ui/app/AppLayouts/Profile/popups/backupseed/Backup.qml b/ui/app/AppLayouts/Profile/popups/backupseed/Backup.qml new file mode 100644 index 0000000000..71f9853582 --- /dev/null +++ b/ui/app/AppLayouts/Profile/popups/backupseed/Backup.qml @@ -0,0 +1,79 @@ +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 } + } +} diff --git a/ui/app/AppLayouts/Profile/popups/backupseed/BackupSeedStepBase.qml b/ui/app/AppLayouts/Profile/popups/backupseed/BackupSeedStepBase.qml new file mode 100644 index 0000000000..c885b749ee --- /dev/null +++ b/ui/app/AppLayouts/Profile/popups/backupseed/BackupSeedStepBase.qml @@ -0,0 +1,42 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import StatusQ.Controls 0.1 +import shared.panels 1.0 +import StatusQ.Controls.Validators 0.1 +import utils 1.0 + +Item { + 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 + } + + 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") : "" + } + ] + } +} diff --git a/ui/app/AppLayouts/Profile/popups/backupseed/ConfirmSeedPhrasePanel.qml b/ui/app/AppLayouts/Profile/popups/backupseed/ConfirmSeedPhrasePanel.qml new file mode 100644 index 0000000000..1a51f807c9 --- /dev/null +++ b/ui/app/AppLayouts/Profile/popups/backupseed/ConfirmSeedPhrasePanel.qml @@ -0,0 +1,76 @@ +import QtQuick 2.12 +import StatusQ.Controls 0.1 +import QtGraphicalEffects 1.13 +import StatusQ.Core.Theme 0.1 + +import shared.panels 1.0 +import utils 1.0 + +BackupSeedStepBase { + id: root + 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] + } + } + + 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; + } + } + + 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 + font.pixelSize: Style.current.primaryTextFontSize + wrapMode: Text.WordWrap + textFormat: Text.RichText + color: Theme.palette.dangerColor1 + text: qsTr("The next screen contains your seed phrase.\nAnyone who sees it can use it to access to your funds.") + } +} diff --git a/ui/app/AppLayouts/Profile/popups/backupseed/ConfirmStoringSeedPhrasePanel.qml b/ui/app/AppLayouts/Profile/popups/backupseed/ConfirmStoringSeedPhrasePanel.qml new file mode 100644 index 0000000000..00d56d5575 --- /dev/null +++ b/ui/app/AppLayouts/Profile/popups/backupseed/ConfirmStoringSeedPhrasePanel.qml @@ -0,0 +1,54 @@ +import QtQuick 2.12 +import utils 1.0 +import shared.panels 1.0 +import StatusQ.Controls 0.1 + +BackupSeedStepBase { + titleText: qsTr("Complete back up") + property bool seedStored: storeCheck.checked + + 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") + } + + 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 application’s storage. This makes your funds more secure.") + } + + 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.") + } + + 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.") + } +} diff --git a/ui/app/AppLayouts/Profile/popups/backupseed/TabBarButton.qml b/ui/app/AppLayouts/Profile/popups/backupseed/TabBarButton.qml new file mode 100644 index 0000000000..9f81e3d09a --- /dev/null +++ b/ui/app/AppLayouts/Profile/popups/backupseed/TabBarButton.qml @@ -0,0 +1,18 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import StatusQ.Core.Theme 0.1 + +TabButton { + id: root + property int index: 0 + property int currentIndex: 0 + implicitWidth: 59 + implicitHeight: 4 + enabled: false + background: Rectangle { + anchors.fill: parent + radius: 4 + color: (root.currentIndex === index) || (root.currentIndex > index) ? + Theme.palette.primaryColor1 : Theme.palette.primaryColor2 + } +} diff --git a/ui/app/AppLayouts/Profile/stores/ProfileSectionStore.qml b/ui/app/AppLayouts/Profile/stores/ProfileSectionStore.qml index dee62a29db..d60b6813ba 100644 --- a/ui/app/AppLayouts/Profile/stores/ProfileSectionStore.qml +++ b/ui/app/AppLayouts/Profile/stores/ProfileSectionStore.qml @@ -65,6 +65,9 @@ QtObject { property ListModel mainMenuItems: ListModel { Component.onCompleted: { + append({subsection: Constants.settingsSubsection.backUpSeed, + text: qsTr("Back up seed phrase"), + icon: "seed-phrase"}) append({subsection: Constants.settingsSubsection.profile, text: qsTr("Profile"), icon: "profile"}) @@ -96,12 +99,12 @@ QtObject { append({subsection: Constants.settingsSubsection.appearance, text: qsTr("Appearance"), icon: "appearance"}) - append({subsection: Constants.settingsSubsection.language, - text: qsTr("Language & Currency"), - icon: "language"}) append({subsection: Constants.settingsSubsection.notifications, text: qsTr("Notifications & Sounds"), icon: "notification"}) + append({subsection: Constants.settingsSubsection.language, + text: qsTr("Language & Currency"), + icon: "language"}) append({subsection: Constants.settingsSubsection.devicesSettings, text: qsTr("Devices settings"), icon: "mobile"}) diff --git a/ui/app/AppLayouts/Profile/views/LeftTabView.qml b/ui/app/AppLayouts/Profile/views/LeftTabView.qml index b0395a1149..79941121c3 100644 --- a/ui/app/AppLayouts/Profile/views/LeftTabView.qml +++ b/ui/app/AppLayouts/Profile/views/LeftTabView.qml @@ -41,12 +41,15 @@ Item { appsMenuItems: store.appsMenuItems browserMenuItemEnabled: store.browserMenuItemEnabled walletMenuItemEnabled: store.walletMenuItemEnabled - onMenuItemClicked: { - if (menu_item.subsection === Constants.settingsSubsection.signout) { - return confirmDialog.open() + if (menu_item.subsection === Constants.settingsSubsection.backUpSeed) { + Global.openBackUpSeedPopup(); + } else { + if (menu_item.subsection === Constants.settingsSubsection.signout) { + return confirmDialog.open(); + } + Global.settingsSubsection = menu_item.subsection; } - Global.settingsSubsection = menu_item.subsection } } } diff --git a/ui/app/AppLayouts/Profile/views/PrivacyView.qml b/ui/app/AppLayouts/Profile/views/PrivacyView.qml index 384826ad4f..b53cba1e55 100644 --- a/ui/app/AppLayouts/Profile/views/PrivacyView.qml +++ b/ui/app/AppLayouts/Profile/views/PrivacyView.qml @@ -24,28 +24,6 @@ SettingsContentBase { spacing: Constants.settingsSection.itemSpacing width: root.contentWidth - StatusListItem { - id: backupSeedPhrase - Layout.fillWidth: true - //% "Backup Seed Phrase" - title: qsTrId("backup-seed-phrase") - enabled: !root.privacyStore.mnemonicBackedUp - implicitHeight: 52 - components: [ - StatusBadge { - value: !root.privacyStore.mnemonicBackedUp - visible: !root.privacyStore.mnemonicBackedUp - anchors.verticalCenter: parent.verticalCenter - }, - StatusIcon { - icon: "chevron-down" - rotation: 270 - color: Theme.palette.baseColor1 - } - ] - sensor.onClicked: Global.openBackUpSeedPopup() - } - StatusListItem { Layout.fillWidth: true title: qsTr("Change password") diff --git a/ui/app/mainui/AppMain.qml b/ui/app/mainui/AppMain.qml index 9118a4462b..22abf819b9 100644 --- a/ui/app/mainui/AppMain.qml +++ b/ui/app/mainui/AppMain.qml @@ -98,7 +98,7 @@ Item { var popup = changeProfilePicComponent.createObject(appMain); popup.open(); } - onOpenBackUpSeedPopup : { + onOpenBackUpSeedPopup: { var popup = backupSeedModalComponent.createObject(appMain) popup.open() } @@ -145,6 +145,7 @@ Item { property Component backupSeedModalComponent: BackupSeedModal { id: backupSeedModal + anchors.centerIn: parent privacyStore: appMain.rootStore.profileSectionStore.privacyStore } diff --git a/ui/imports/utils/Constants.qml b/ui/imports/utils/Constants.qml index 6e7a533aef..42d1ef967e 100644 --- a/ui/imports/utils/Constants.qml +++ b/ui/imports/utils/Constants.qml @@ -44,6 +44,7 @@ QtObject { property int advanced: 11 property int about: 12 property int signout: 13 + property int backUpSeed: 14 } readonly property QtObject userStatus: QtObject{