feat: add design to enter a seed key

This commit is contained in:
Jonathan Rainville 2020-06-12 16:47:44 -04:00 committed by Iuri Matias
parent 73eb4fe8b1
commit 846dc646e1
11 changed files with 335 additions and 242 deletions

View File

@ -16,6 +16,7 @@ QtObject {
readonly property color darkBlueBtn: "#5a70dd"
readonly property color red: "#FF2D55"
readonly property int xlPadding: 32
readonly property int bigPadding: 24
readonly property int padding: 16
readonly property int smallPadding: 10

View File

@ -57,12 +57,6 @@ ApplicationWindow {
id: keysMainState
onEntered: loader.sourceComponent = keysMain
DSM.SignalTransition {
targetState: existingKeyState
signal: applicationWindow.navigateTo
guard: path === "ExistingKey"
}
DSM.SignalTransition {
targetState: genKeyState
signal: applicationWindow.navigateTo
@ -90,12 +84,6 @@ ApplicationWindow {
signal: onboardingModel.loginResponseChanged
guard: !error
}
DSM.SignalTransition {
targetState: existingKeyState
signal: applicationWindow.navigateTo
guard: path === "ExistingKey"
}
}
DSM.State {
@ -115,6 +103,18 @@ ApplicationWindow {
}
}
DSM.SignalTransition {
targetState: loginModel.rowCount() ? stateLogin : stateIntro
signal: applicationWindow.navigateTo
guard: path === "InitialState"
}
DSM.SignalTransition {
targetState: existingKeyState
signal: applicationWindow.navigateTo
guard: path === "ExistingKey"
}
DSM.FinalState {
id: onboardingDoneState
}
@ -158,7 +158,11 @@ ApplicationWindow {
Component {
id: existingKey
ExistingKey {}
ExistingKey {
onClosed: function () {
applicationWindow.navigateTo("InitialState")
}
}
}
Component {
@ -171,7 +175,12 @@ ApplicationWindow {
Component {
id: login
Login {
btnGenKey.onClicked: applicationWindow.navigateTo("GenKey")
onGenKeyClicked: function () {
applicationWindow.navigateTo("GenKey")
}
onExistingKeyClicked: function () {
applicationWindow.navigateTo("ExistingKey")
}
}
}
}

View File

@ -136,6 +136,8 @@ DISTFILES += \
app/img/walletActive.svg \
app/qmldir \
imports/qmldir \
onboarding/CreatePasswordModal.qml \
onboarding/EnterSeedPhraseModal.qml \
onboarding/ExistingKey.qml \
onboarding/GenKey.qml \
onboarding/Intro.qml \
@ -144,6 +146,7 @@ DISTFILES += \
onboarding/Login/AccountList.qml \
onboarding/Login/AccountSelection.qml \
onboarding/Login/AddressView.qml \
onboarding/Login/ConfirmAddExistingKeyModal.qml \
onboarding/Login/SelectAnotherAccountModal.qml \
onboarding/Login/qmldir \
onboarding/Login/samples/AccountsData.qml \

View File

@ -0,0 +1,136 @@
import QtQuick 2.12
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.3
import "../imports"
import "../shared"
ModalPopup {
property bool loading: false
id: popup
title: qsTr("Create a password")
height: 500
onOpened: {
firstPasswordField.text = "";
firstPasswordField.forceActiveFocus(Qt.MouseFocusReason)
}
Input {
id: firstPasswordField
anchors.rightMargin: 56
anchors.leftMargin: 56
anchors.top: parent.top
anchors.topMargin: 88
placeholderText: qsTr("New password...")
textField.echoMode: TextInput.Password
}
Input {
id: repeatPasswordField
anchors.rightMargin: 0
anchors.leftMargin: 0
anchors.right: firstPasswordField.right
anchors.left: firstPasswordField.left
anchors.top: firstPasswordField.bottom
anchors.topMargin: Theme.xlPadding
placeholderText: qsTr("Confirm password…")
textField.echoMode: TextInput.Password
Keys.onReturnPressed: {
submitBtn.clicked()
}
}
Text {
text: qsTr("At least 6 characters. You will use this password to unlock status on this device & sign transactions.")
wrapMode: Text.WordWrap
anchors.right: parent.right
anchors.rightMargin: Theme.xlPadding
anchors.left: parent.left
anchors.leftMargin: Theme.xlPadding
horizontalAlignment: Text.AlignHCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
color: Theme.darkGrey
font.pixelSize: 12
}
footer: StyledButton {
id: submitBtn
anchors.bottom: parent.bottom
anchors.topMargin: Theme.padding
anchors.right: parent.right
anchors.rightMargin: Theme.padding
label: loading ? qsTr("Logging in...") : qsTr("Create password")
disabled: firstPasswordField.text === "" || repeatPasswordField.text === "" || loading
MessageDialog {
id: importError
title: qsTr("Error importing account")
text: qsTr("An error occurred while importing your account: ")
icon: StandardIcon.Critical
standardButtons: StandardButton.Ok
onVisibilityChanged: {
loading = false
}
}
MessageDialog {
id: importLoginError
title: qsTr("Login failed")
text: qsTr("Login failed. Please re-enter your password and try again.")
icon: StandardIcon.Critical
standardButtons: StandardButton.Ok
onVisibilityChanged: {
loading = false
}
}
MessageDialog {
id: passwordsDontMatchError
title: qsTr("Error")
text: qsTr("Passwords don't match")
icon: StandardIcon.Warning
standardButtons: StandardButton.Ok
onAccepted: {
repeatPasswordField.clear()
repeatPasswordField.forceActiveFocus(Qt.MouseFocusReason)
}
}
Connections {
target: onboardingModel
ignoreUnknownSignals: true
onLoginResponseChanged: {
if (error) {
loading = false
importLoginError.open()
}
}
}
onClicked : {
if (firstPasswordField.text === "" || repeatPasswordField.text === "") {
return
}
if (repeatPasswordField.text !== firstPasswordField.text) {
return passwordsDontMatchError.open()
}
// TODO this doesn't seem to work because the function freezes the view
loading = true
const result = onboardingModel.storeDerivedAndLogin(repeatPasswordField.text);
const error = JSON.parse(result).error
if (error) {
importError.text += error
return importError.open()
}
}
}
}
/*##^##
Designer {
D{i:0;formeditorColor:"#ffffff";height:500;width:400}
}
##^##*/

View File

@ -0,0 +1,83 @@
import QtQuick 2.12
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import "../imports"
import "../shared"
ModalPopup {
property var onConfirmSeedClick: function () {}
id: popup
title: qsTr("Add key")
height: 400
onOpened: {
mnemonicTextField.text = "";
mnemonicTextField.forceActiveFocus(Qt.MouseFocusReason)
}
TextArea {
id: mnemonicTextField
height: 44
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 15
placeholderText: "Enter your seed phrase here..."
anchors.left: parent.left
anchors.leftMargin: 76
anchors.right: parent.right
anchors.rightMargin: 76
anchors.verticalCenter: parent.verticalCenter
Keys.onReturnPressed: {
submitBtn.clicked()
}
}
Text {
text: qsTr("Enter 12, 15, 18, 21 or 24 words.\nSeperate words by a single space.")
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
color: Theme.darkGrey
font.pixelSize: 12
}
footer: Button {
id: submitBtn
anchors.bottom: parent.bottom
anchors.topMargin: Theme.padding
anchors.right: parent.right
anchors.rightMargin: Theme.padding
width: 44
height: 44
background: Rectangle {
radius: 50
color: Theme.lightBlue
}
Image {
sourceSize.height: 15
sourceSize.width: 20
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
source: "../app/img/leave_chat.svg"
rotation: 180
fillMode: Image.PreserveAspectFit
}
onClicked : {
if (mnemonicTextField.text === "") {
return
}
onConfirmSeedClick(mnemonicTextField.text)
popup.close()
}
}
}
/*##^##
Designer {
D{i:0;formeditorColor:"#ffffff";height:500;width:400}
}
##^##*/

View File

@ -5,233 +5,36 @@ import QtQuick.Window 2.11
import QtQuick.Dialogs 1.3
import "../shared"
import "../imports"
import "."
SwipeView {
id: swipeView
Item {
property var onClosed: function () {}
id: existingKeyView
anchors.fill: parent
currentIndex: 0
onCurrentItemChanged: {
currentItem.txtPassword.textField.focus = true;
Component.onCompleted: {
enterSeedPhraseModal.open()
}
Item {
id: wizardStep1
property Item txtPassword: txtMnemonic
width: 620
height: 427
Text {
id: title
text: "Enter mnemonic"
font.pointSize: 36
anchors.top: parent.top
anchors.topMargin: 20
anchors.horizontalCenter: parent.horizontalCenter
EnterSeedPhraseModal {
property bool wentNext: false
id: enterSeedPhraseModal
onConfirmSeedClick: function (mnemonic) {
wentNext = true
onboardingModel.importMnemonic(mnemonic)
createPasswordModal.open()
}
Input {
id: txtMnemonic
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: Theme.padding
anchors.leftMargin: Theme.padding
anchors.left: parent.left
anchors.right: parent.right
placeholderText: "Enter 12, 15, 21 or 24 words. Separate words by a single space."
Keys.onReturnPressed: {
btnImport.clicked()
}
}
StyledButton {
id: btnImport
label: "Next"
anchors.bottom: parent.bottom
anchors.bottomMargin: Theme.padding
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
onboardingModel.importMnemonic(txtMnemonic.textField.text);
swipeView.incrementCurrentIndex();
onClosed: function () {
if (!wentNext) {
existingKeyView.onClosed()
}
}
}
Item {
id: wizardStep2
property Item txtPassword: txtPassword
Text {
id: step2Title
text: "Enter password"
font.pointSize: 36
anchors.top: parent.top
anchors.topMargin: 20
anchors.horizontalCenter: parent.horizontalCenter
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: step2Title.bottom
anchors.topMargin: 30
Column {
Image {
source: onboardingModel.currentAccount.identicon
}
}
Column {
Text {
text: onboardingModel.currentAccount.username
}
Text {
text: onboardingModel.currentAccount.address
width: 160
elide: Text.ElideMiddle
}
}
}
Input {
id: txtPassword
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: Theme.padding
anchors.leftMargin: Theme.padding
anchors.left: parent.left
anchors.right: parent.right
placeholderText: "Enter password"
Component.onCompleted: {
this.textField.echoMode = TextInput.Password
}
Keys.onReturnPressed: {
btnNext.clicked()
}
}
StyledButton {
id: btnNext
label: "Next"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
onClicked: {
swipeView.incrementCurrentIndex();
}
}
}
Item {
id: wizardStep3
property Item txtPassword: txtConfirmPassword
Text {
id: step3Title
text: "Confirm password"
font.pointSize: 36
anchors.top: parent.top
anchors.topMargin: 20
anchors.horizontalCenter: parent.horizontalCenter
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: step3Title.bottom
anchors.topMargin: 30
Column {
Image {
source: onboardingModel.currentAccount.identicon
}
}
Column {
Text {
text: onboardingModel.currentAccount.username
}
Text {
text: onboardingModel.currentAccount.address
width: 160
elide: Text.ElideMiddle
}
}
}
Input {
id: txtConfirmPassword
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: Theme.padding
anchors.leftMargin: Theme.padding
anchors.left: parent.left
anchors.right: parent.right
placeholderText: "Confirm entered password"
Component.onCompleted: {
this.textField.echoMode = TextInput.Password
}
Keys.onReturnPressed: {
btnFinish.clicked()
}
}
MessageDialog {
id: importError
title: "Error importing account"
text: "An error occurred while importing your account: "
icon: StandardIcon.Critical
standardButtons: StandardButton.Ok
onAccepted: {
swipeView.currentIndex = 0
}
}
MessageDialog {
id: importLoginError
title: "Login failed"
text: "Login failed. Please re-enter your password and try again."
icon: StandardIcon.Critical
standardButtons: StandardButton.Ok
}
MessageDialog {
id: passwordsDontMatchError
title: "Error"
text: "Passwords don't match"
icon: StandardIcon.Warning
standardButtons: StandardButton.Ok
onAccepted: {
txtConfirmPassword.clear();
swipeView.currentIndex = 1;
txtPassword.focus = true;
}
}
Connections {
target: onboardingModel
ignoreUnknownSignals: true
onLoginResponseChanged: {
if(error){
importLoginError.open()
}
}
}
StyledButton {
id: btnFinish
label: "Finish"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
onClicked: {
if (txtConfirmPassword.textField.text != txtPassword.textField.text) {
return passwordsDontMatchError.open();
}
const result = onboardingModel.storeDerivedAndLogin(txtConfirmPassword.textField.text);
const error = JSON.parse(result).error;
if (error) {
importError.text += error;
importError.open();
}
}
CreatePasswordModal {
id: createPasswordModal
onClosed: function () {
existingKeyView.onClosed()
}
}
}

View File

@ -9,7 +9,8 @@ import "../imports"
import "./Login"
Item {
property alias btnGenKey: genrateKeysLink
property var onGenKeyClicked: function () {}
property var onExistingKeyClicked: function () {}
property bool loading: false
id: loginView
@ -43,11 +44,21 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
}
ConfirmAddExistingKeyModal {
id: confirmAddExstingKeyModal
onOpenModalClick: function () {
onExistingKeyClicked()
}
}
SelectAnotherAccountModal {
id: selectAnotherAccountModal
onAccountSelect: function (index) {
loginModel.setCurrentAccount(index)
}
onOpenModalClick: function () {
confirmAddExstingKeyModal.open()
}
}
Rectangle {
@ -88,9 +99,11 @@ Item {
changeAccountBtn.isHovered = false
}
onClicked: {
selectAnotherAccountModal.open()
// TODO add popup for when there are no other accounts
if (loginModel.rowCount() > 1) {
selectAnotherAccountModal.open()
} else {
onExistingKeyClicked()
}
}
}
}
@ -182,16 +195,19 @@ Item {
}
MouseArea {
id: genrateKeysLink
width: genrateKeysLinkText.width
height: genrateKeysLinkText.height
id: generateKeysLink
width: generateKeysLinkText.width
height: generateKeysLinkText.height
cursorShape: Qt.PointingHandCursor
anchors.top: txtPassword.bottom
anchors.topMargin: 26
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
onGenKeyClicked()
}
Text {
id: genrateKeysLinkText
id: generateKeysLinkText
color: Theme.blue
text: qsTr("Generate new keys")
font.pixelSize: 13

View File

@ -0,0 +1,37 @@
import QtQuick 2.12
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import "../../imports"
import "../../shared"
ModalPopup {
property var onOpenModalClick: function () {}
id: popup
title: qsTr("Enter seed phrase")
height: 200
Text {
text: "Do you want to add another existing key?"
anchors.left: parent.left
anchors.top: parent.top
}
footer: StyledButton {
anchors.bottom: parent.bottom
anchors.topMargin: Theme.padding
anchors.right: parent.right
anchors.rightMargin: Theme.padding
label: "Add another existing key"
onClicked : {
onOpenModalClick()
popup.close()
}
}
}
/*##^##
Designer {
D{i:0;formeditorColor:"#ffffff";height:500;width:400}
}
##^##*/

View File

@ -6,6 +6,7 @@ import "../../shared"
ModalPopup {
property var onAccountSelect: function () {}
property var onOpenModalClick: function () {}
id: popup
title: qsTr("Your accounts")
@ -20,16 +21,16 @@ ModalPopup {
}
}
footer: StyledButton {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.topMargin: Theme.padding
anchors.right: parent.right
anchors.rightMargin: Theme.padding
label: "Add another existing key"
onClicked : {
console.log('Open other popup for seed')
onOpenModalClick()
popup.close()
}
}
}

View File

@ -2,3 +2,4 @@ AccountSelection 1.0 AccountSelection.qml
AccountList 1.0 AccountList.qml
AddressView 1.0 AddressView.qml
SelectAnotherAccountModal 1.0 SelectAnotherAccountModal.qml
ConfirmAddExistingKeyModal 1.0 ConfirmAddExistingKeyModal.qml

View File

@ -5,3 +5,6 @@ KeysMain 1.0 KeysMain.qml
Login 1.0 Login.qml
OnboardingMain 1.0 OnboardingMain.qml
Slide 1.0 Slide.qml
EnterSeedPhraseModal 1.0 EnterSeedPhraseModal.qml
CreatePasswordModal 1.0 CreatePasswordModal.qml