diff --git a/src/app/modules/startup/onboarding/item.nim b/src/app/modules/startup/onboarding/item.nim index 7030df840a..a359ffa756 100644 --- a/src/app/modules/startup/onboarding/item.nim +++ b/src/app/modules/startup/onboarding/item.nim @@ -4,13 +4,15 @@ type alias: string identicon: string address: string + pubKey: string keyUid: string -proc initItem*(id, alias, identicon, address, keyUid: string): Item = +proc initItem*(id, alias, identicon, address, pubKey, keyUid: string): Item = result.id = id result.alias = alias result.identicon = identicon result.address = address + result.pubKey = pubKey result.keyUid = keyUid proc getId*(self: Item): string = @@ -25,5 +27,8 @@ proc getIdenticon*(self: Item): string = proc getAddress*(self: Item): string = return self.address +proc getPubKey*(self: Item): string = + return self.pubKey + proc getKeyUid*(self: Item): string = return self.keyUid diff --git a/src/app/modules/startup/onboarding/model.nim b/src/app/modules/startup/onboarding/model.nim index 6c8eb0b272..071486f849 100644 --- a/src/app/modules/startup/onboarding/model.nim +++ b/src/app/modules/startup/onboarding/model.nim @@ -8,6 +8,7 @@ type Alias Identicon Address + PubKey KeyUid QtObject: @@ -35,6 +36,7 @@ QtObject: ModelRole.Alias.int:"username", ModelRole.Identicon.int:"identicon", ModelRole.Address.int:"address", + ModelRole.PubKey.int:"pubKey", ModelRole.KeyUid.int:"keyUid" }.toTable @@ -57,6 +59,8 @@ QtObject: result = newQVariant(item.getIdenticon()) of ModelRole.Address: result = newQVariant(item.getAddress()) + of ModelRole.PubKey: + result = newQVariant(item.getPubKey()) of ModelRole.KeyUid: result = newQVariant(item.getKeyUid()) diff --git a/src/app/modules/startup/onboarding/module.nim b/src/app/modules/startup/onboarding/module.nim index 6727a81d6a..6d2dc86f39 100644 --- a/src/app/modules/startup/onboarding/module.nim +++ b/src/app/modules/startup/onboarding/module.nim @@ -41,7 +41,7 @@ method load*(self: Module) = let generatedAccounts = self.controller.getGeneratedAccounts() var accounts: seq[Item] for acc in generatedAccounts: - accounts.add(initItem(acc.id, acc.alias, acc.identicon, acc.address, acc.keyUid)) + accounts.add(initItem(acc.id, acc.alias, acc.identicon, acc.address, acc.publicKey, acc.keyUid)) self.view.setAccountList(accounts) diff --git a/src/app/modules/startup/onboarding/view.nim b/src/app/modules/startup/onboarding/view.nim index c8c6cffe8d..0e70bfa72c 100644 --- a/src/app/modules/startup/onboarding/view.nim +++ b/src/app/modules/startup/onboarding/view.nim @@ -60,6 +60,13 @@ QtObject: read = getImportedAccountAddress notify = importedAccountChanged + proc getImportedAccountPubKey*(self: View): string {.slot.} = + return self.delegate.getImportedAccount().publicKey + + QtProperty[string] importedAccountPubKey: + read = getImportedAccountPubKey + notify = importedAccountChanged + proc setDisplayName*(self: View, displayName: string) {.slot.} = self.delegate.setDisplayName(displayName) diff --git a/ui/app/AppLayouts/Onboarding/OnboardingLayout.qml b/ui/app/AppLayouts/Onboarding/OnboardingLayout.qml index a62d8e19e4..6e0c6d926b 100644 --- a/ui/app/AppLayouts/Onboarding/OnboardingLayout.qml +++ b/ui/app/AppLayouts/Onboarding/OnboardingLayout.qml @@ -8,6 +8,8 @@ import "stores" QtObject { id: root property bool hasAccounts + property string keysMainSetState: "" + signal loadApp() signal onBoardingStepChanged(var view, string state) @@ -18,38 +20,78 @@ QtObject { DSM.State { id: onboardingState - initialState: root.hasAccounts ? stateLogin : keysMainState + initialState: root.hasAccounts ? stateLogin : welcomeMainState + + DSM.State { + id: welcomeMainState + onEntered: { onBoardingStepChanged(welcomeMain, ""); } + + DSM.SignalTransition { + targetState: keysMainState + signal: Global.applicationWindow.navigateTo + guard: path === "KeyMain" + } + } DSM.State { id: keysMainState - onEntered: { onBoardingStepChanged(welcomeMain, ""); } + onEntered: { onBoardingStepChanged(keysMain, root.keysMainSetState); } DSM.SignalTransition { targetState: genKeyState signal: Global.applicationWindow.navigateTo guard: path === "GenKey" } + + DSM.SignalTransition { + targetState: welcomeMainState + signal: Global.applicationWindow.navigateTo + guard: path === "Welcome" + } } DSM.State { id: existingKeyState onEntered: { onBoardingStepChanged(existingKey, ""); } + DSM.SignalTransition { + targetState: genKeyState + signal: Global.applicationWindow.navigateTo + guard: path === "GenKey" + } + DSM.SignalTransition { targetState: appState signal: startupModule.appStateChanged guard: state === Constants.appState.main } + + DSM.SignalTransition { + targetState: welcomeMainState + signal: Global.applicationWindow.navigateTo + guard: path === "Welcome" + } } DSM.State { id: genKeyState onEntered: { onBoardingStepChanged(genKey, ""); } + DSM.SignalTransition { + targetState: welcomeMainState + signal: Global.applicationWindow.navigateTo + guard: path === "Welcome" + } DSM.SignalTransition { targetState: appState - signal: startupModule.appStateChanged - guard: state === Constants.appState.main + signal: Global.applicationWindow.navigateTo + guard: path === "LoggedIn" + } + + DSM.SignalTransition { + targetState: stateLogin + signal: Global.applicationWindow.navigateTo + guard: path === "LogIn" } } @@ -109,36 +151,24 @@ QtObject { guard: path === "InitialState" } - DSM.SignalTransition { - targetState: existingKeyState - signal: Global.applicationWindow.navigateTo - guard: path === "ExistingKey" - } - DSM.SignalTransition { targetState: keysMainState signal: Global.applicationWindow.navigateTo guard: path === "KeysMain" } + DSM.SignalTransition { + targetState: existingKeyState + signal: Global.applicationWindow.navigateTo + guard: path === "ExistingKey" + } + DSM.SignalTransition { targetState: keycardState signal: Global.applicationWindow.navigateTo guard: path === "KeycardFlowSelection" } - DSM.SignalTransition { - targetState: createPasswordState - signal: applicationWindow.navigateTo - guard: path === "CreatePassword" - } - - DSM.SignalTransition { - targetState: confirmPasswordState - signal: applicationWindow.navigateTo - guard: path === "ConfirmPassword" - } - DSM.FinalState { id: onboardingDoneState } @@ -159,10 +189,12 @@ QtObject { id: welcomeMain WelcomeView { onBtnNewUserClicked: { - onBoardingStepChanged(keysMain, "getkeys"); + root.keysMainSetState = "getkeys"; + Global.applicationWindow.navigateTo("KeyMain"); } onBtnExistingUserClicked: { - onBoardingStepChanged(keysMain, "connectkeys"); + root.keysMainSetState = "connectkeys"; + Global.applicationWindow.navigateTo("KeyMain"); } } } @@ -180,7 +212,7 @@ QtObject { Global.applicationWindow.navigateTo("ExistingKey"); } onBackClicked: { - onBoardingStepChanged(welcomeMain, ""); + Global.applicationWindow.navigateTo("Welcome"); } } } @@ -188,7 +220,9 @@ QtObject { property var existingKeyComponent: Component { id: existingKey ExistingKeyView { - onShowCreatePasswordView: { Global.applicationWindow.navigateTo("CreatePassword") } + onShowCreatePasswordView: { + Global.applicationWindow.navigateTo("GenKey"); + } onClosed: function () { if (root.hasAccounts) { Global.applicationWindow.navigateTo("InitialState") @@ -202,14 +236,16 @@ QtObject { property var genKeyComponent: Component { id: genKey GenKeyView { - onShowCreatePasswordView: { Global.applicationWindow.navigateTo("CreatePassword") } - onClosed: function () { - if (root.hasAccounts) { - Global.applicationWindow.navigateTo("InitialState") + onFinished: { + if (LoginStore.currentAccount.username !== "") { + Global.applicationWindow.navigateTo("LogIn"); } else { - Global.applicationWindow.navigateTo("KeysMain") + Global.applicationWindow.navigateTo("KeysMain"); } } + onKeysGenerated: { + Global.applicationWindow.navigateTo("LoggedIn") + } } } @@ -237,39 +273,4 @@ QtObject { } } } - - property var d: QtObject { - property string newPassword - property string confirmationPassword - } - - property var createPasswordComponent: Component { - id: createPassword - CreatePasswordView { - store: OnboardingStore - newPassword: d.newPassword - confirmationPassword: d.confirmationPassword - - onPasswordCreated: { - d.newPassword = newPassword - d.confirmationPassword = confirmationPassword - applicationWindow.navigateTo("ConfirmPassword") - } - onBackClicked: { - d.newPassword = "" - d.confirmationPassword = "" - applicationWindow.navigateTo("InitialState"); - console.warn("TODO: Integration with onboarding flow!") - } - } - } - - property var confirmPasswordComponent: Component { - id: confirmPassword - ConfirmPasswordView { - password: d.newPassword - - onBackClicked: { applicationWindow.navigateTo("CreatePassword") } - } - } } diff --git a/ui/app/AppLayouts/Onboarding/controls/OnboardingBasePage.qml b/ui/app/AppLayouts/Onboarding/controls/OnboardingBasePage.qml new file mode 100644 index 0000000000..1362123906 --- /dev/null +++ b/ui/app/AppLayouts/Onboarding/controls/OnboardingBasePage.qml @@ -0,0 +1,27 @@ +import QtQuick 2.13 +import QtQuick.Controls 2.13 + +import StatusQ.Controls 0.1 + +import utils 1.0 + +Page { + id: root + signal backClicked() + signal finished() + + background: Rectangle { + color: Style.current.background + } + + StatusRoundButton { + anchors.left: parent.left + anchors.leftMargin: Style.current.padding + anchors.bottom: parent.bottom + anchors.bottomMargin: Style.current.padding + icon.name: "arrow-left" + onClicked: { + root.backClicked(); + } + } +} diff --git a/ui/app/AppLayouts/Onboarding/popups/MnemonicRecoverySuccessModal.qml b/ui/app/AppLayouts/Onboarding/popups/MnemonicRecoverySuccessModal.qml index 474290a4a8..19b7bc55f6 100644 --- a/ui/app/AppLayouts/Onboarding/popups/MnemonicRecoverySuccessModal.qml +++ b/ui/app/AppLayouts/Onboarding/popups/MnemonicRecoverySuccessModal.qml @@ -43,7 +43,7 @@ ModalPopup { anchors.top: info.bottom anchors.topMargin: Style.current.bigPadding anchors.horizontalCenter: parent.horizontalCenter - image.source: OnboardingStore.onBoardingModul.importedAccountIdenticon + image.source: OnboardingStore.onboardingModuleInst.importedAccountIdenticon image.width: 60 image.height: 60 } @@ -53,7 +53,7 @@ ModalPopup { anchors.top: identicon.bottom anchors.topMargin: Style.current.padding anchors.horizontalCenter: identicon.horizontalCenter - text: OnboardingStore.onBoardingModul.importedAccountAlias + text: OnboardingStore.onboardingModuleInst.importedAccountAlias font.weight: Font.Bold font.pixelSize: 15 } @@ -62,7 +62,7 @@ ModalPopup { anchors.top: username.bottom anchors.topMargin: Style.current.halfPadding anchors.horizontalCenter: username.horizontalCenter - text: OnboardingStore.onBoardingModul.importedAccountAddress + text: OnboardingStore.onboardingModuleInst.importedAccountAddress width: 120 } diff --git a/ui/app/AppLayouts/Onboarding/popups/UploadProfilePicModal.qml b/ui/app/AppLayouts/Onboarding/popups/UploadProfilePicModal.qml new file mode 100644 index 0000000000..4cc518560c --- /dev/null +++ b/ui/app/AppLayouts/Onboarding/popups/UploadProfilePicModal.qml @@ -0,0 +1,98 @@ +import QtQuick 2.13 +import QtQuick.Dialogs 1.3 + +import utils 1.0 + +import StatusQ.Controls 0.1 + +import shared 1.0 +import shared.panels 1.0 +import shared.popups 1.0 + +import "../stores" + +// TODO: replace with StatusModal +ModalPopup { + id: popup + title: qsTr("Upload profile picture") + property string selectedImage + property string uploadError + + onSelectedImageChanged: { + if (!selectedImage) { + return; + } + cropImageModal.open(); + } + + Item { + anchors.fill: parent + + RoundedImage { + id: profilePic + source: selectedImage + width: 160 + height: 160 + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + border.width: 1 + border.color: Style.current.border + onClicked: imageDialog.open(); + } + + StyledText { + visible: !!uploadError + text: uploadError + anchors.left: parent.left + anchors.right: parent.right + anchors.top: profilePic.bottom + horizontalAlignment: Text.AlignHCenter + font.pixelSize: 13 + wrapMode: Text.WordWrap + anchors.topMargin: 13 + font.weight: Font.Thin + color: Style.current.danger + } + + ImageCropperModal { + id: cropImageModal + selectedImage: popup.selectedImage + ratio: "1:1" + onCropFinished: { + OnboardingStore.uploadImage(selectedImage, aX, aY, bX, bY); + } + } + } + + footer: Item { + width: parent.width + height: uploadBtn.height + + StatusButton { + id: uploadBtn + text: !!selectedImage ? qsTr("Done") : qsTr("Upload") + anchors.right: parent.right + anchors.bottom: parent.bottom + onClicked: { + if (!!selectedImage) { + close(); + } else { + imageDialog.open(); + } + } + + FileDialog { + id: imageDialog + title: qsTrId("please-choose-an-image") + folder: shortcuts.pictures + nameFilters: [ + qsTrId("image-files----jpg---jpeg---png-") + ] + onAccepted: { + selectedImage = imageDialog.fileUrls[0]; + } + } + } + } +} + diff --git a/ui/app/AppLayouts/Onboarding/shared/CreatePasswordModal.qml b/ui/app/AppLayouts/Onboarding/shared/CreatePasswordModal.qml index 1c9eb34f0e..302e7591bb 100644 --- a/ui/app/AppLayouts/Onboarding/shared/CreatePasswordModal.qml +++ b/ui/app/AppLayouts/Onboarding/shared/CreatePasswordModal.qml @@ -10,6 +10,8 @@ import shared.panels 1.0 import shared.popups 1.0 import shared.controls 1.0 +import "../stores" + // TODO: replace with StatusModal ModalPopup { property var privacyStore @@ -153,7 +155,7 @@ ModalPopup { } Connections { - target: onboardingModule + target: OnboardingStore.onboardingModuleInst onAccountSetupError: { importLoginError.open() } @@ -169,15 +171,15 @@ ModalPopup { passwordValidationError = qsTr("Incorrect password") } else { - Global.applicationWindow.prepareForStoring(repeatPasswordField.text, true) + //Global.applicationWindow.prepareForStoring(repeatPasswordField.text, true) popup.close() } } else { loading = true - onboardingModule.storeSelectedAccountAndLogin(repeatPasswordField.text); - Global.applicationWindow.prepareForStoring(repeatPasswordField.text, false) + OnboardingStore.onboardingModuleInst.storeSelectedAccountAndLogin(repeatPasswordField.text); + //Global.applicationWindow.prepareForStoring(repeatPasswordField.text, false) } } } diff --git a/ui/app/AppLayouts/Onboarding/stores/OnboardingStore.qml b/ui/app/AppLayouts/Onboarding/stores/OnboardingStore.qml index fe966294f6..75eb114d69 100644 --- a/ui/app/AppLayouts/Onboarding/stores/OnboardingStore.qml +++ b/ui/app/AppLayouts/Onboarding/stores/OnboardingStore.qml @@ -1,22 +1,69 @@ pragma Singleton import QtQuick 2.13 +import utils 1.0 QtObject { - property var onBoardingModul: onboardingModule + id: root + property var profileSectionModuleInst: profileSectionModule + property var profileModule: profileSectionModuleInst.profileModule + property var onboardingModuleInst: onboardingModule + property var mainModuleInst: !!mainModule ? mainModule : undefined + property var accountSettings: localAccountSettings + property var privacyModule: profileSectionModuleInst.privacyModule + property string displayName: userProfile !== undefined ? userProfile.displayName : "" + + property url profImgUrl: "" + property real profImgAX: 0.0 + property real profImgAY: 0.0 + property real profImgBX: 0.0 + property real profImgBY: 0.0 + property bool accountCreated: false + + property bool showBeforeGetStartedPopup: true function importMnemonic(mnemonic) { - onBoardingModul.importMnemonic(mnemonic) + onboardingModuleInst.importMnemonic(mnemonic) } function setCurrentAccountAndDisplayName(selectedAccountIdx, displayName) { - onBoardingModul.setDisplayName(displayName) - onBoardingModul.setSelectedAccountByIndex(selectedAccountIdx) + onboardingModuleInst.setDisplayName(displayName) + onboardingModuleInst.setSelectedAccountByIndex(selectedAccountIdx) } - function getPasswordStrengthScore(password) { - let userName = onBoardingModul.importedAccountAlias - return onBoardingModul.getPasswordStrengthScore(password, userName) + function updatedDisplayName(displayName) { + if (displayName !== root.displayName) { + print(displayName, root.displayName) + root.profileModule.setDisplayName(displayName); + } + } + + function saveImage() { + root.profileModule.upload(root.profImgUrl, root.profImgAX, root.profImgAY, root.profImgBX, root.profImgBY); + } + + function uploadImage(source, aX, aY, bX, bY) { + root.profImgUrl = source; + root.profImgAX = aX; + root.profImgAY = aY; + root.profImgBX = bX; + root.profImgBY = bY; + } + + function removeImage() { + return root.profileModule.remove(); + } + + function finishCreatingAccount(pass) { + root.onboardingModuleInst.storeSelectedAccountAndLogin(pass); + } + + function storeToKeyChain(pass) { + mainModule.storePassword(pass); + } + + function changePassword(password, newPassword) { + root.privacyModule.changePassword(password, newPassword) } property ListModel accountsSampleData: ListModel { diff --git a/ui/app/AppLayouts/Onboarding/views/ConfirmPasswordView.qml b/ui/app/AppLayouts/Onboarding/views/ConfirmPasswordView.qml index b1b697e6b2..fa5882155a 100644 --- a/ui/app/AppLayouts/Onboarding/views/ConfirmPasswordView.qml +++ b/ui/app/AppLayouts/Onboarding/views/ConfirmPasswordView.qml @@ -12,18 +12,15 @@ import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 import "../stores" +import "../controls" -Page { +OnboardingBasePage { id: root property string password - - signal backClicked() - - anchors.fill: parent - background: null - - Component.onCompleted: confPswInput.forceActiveFocus(Qt.MouseFocusReason) + property string tmpPass + property string displayName + function forcePswInputFocus() { confPswInput.forceActiveFocus(Qt.MouseFocusReason)} Column { id: view @@ -73,9 +70,7 @@ Page { width: parent.width enabled: !submitBtn.loading - placeholderText: submitBtn.loading ? - qsTr("Connecting...") : - qsTr("Confirm you password (again)") + placeholderText: qsTr("Confirm you password (again)") textField.echoMode: showPassword ? TextInput.Normal : TextInput.Password textField.validator: RegExpValidator { regExp: /^[!-~]{0,64}$/ } // That incudes NOT extended ASCII printable characters less space and a maximum of 64 characters allowed keepHeight: true @@ -106,24 +101,34 @@ Page { id: submitBtn anchors.horizontalCenter: parent.horizontalCenter text: qsTr("Finalize Status Password Creation") - enabled: !submitBtn.loading && confPswInput.text === root.password + enabled:!submitBtn.loading && confPswInput.text === root.password property Timer sim: Timer { id: pause interval: 20 onTriggered: { - // Create new password call action to the backend - OnboardingStore.onBoardingModul.storeSelectedAccountAndLogin(root.password) - Global.applicationWindow.prepareForStoring(root.password, false) + // Create account operation blocks the UI so loading = true; will never have any affect until it is done. + // Getting around it with a small pause (timer) in order to get the desired behavior + OnboardingStore.finishCreatingAccount(root.password) } } onClicked: { - confPswInput.text = "" - submitBtn.loading = true - // Create password operation blocks the UI so loading = true; will never have any affect until changePassword/createPassword is done. - // Getting around it with a small pause (timer) in order to get the desired behavior - pause.start() + //confPswInput.text = "" + if (OnboardingStore.accountCreated) { + if (root.password !== root.tmpPass) { + OnboardingStore.changePassword(root.tmpPass, root.password); + root.tmpPass = root.password; + } else { + submitBtn.loading = false + root.finished(); + } + } else { + root.tmpPass = root.password; + submitBtn.loading = true + OnboardingStore.setCurrentAccountAndDisplayName(0, root.displayName); + pause.start(); + } } } } @@ -138,4 +143,28 @@ Page { icon.name: "arrow-left" onClicked: { root.backClicked() } } + + Connections { + target: startupModule + onAppStateChanged: { + if (state === Constants.appState.main) { + if (!!OnboardingStore.profImgUrl) { + OnboardingStore.saveImage() + OnboardingStore.accountCreated = true; + } + submitBtn.loading = false + root.finished() + } + } + } + + Connections { + target: OnboardingStore.privacyModule + onPasswordChanged: { + if (success) { + submitBtn.loading = false + root.finished(); + } + } + } } diff --git a/ui/app/AppLayouts/Onboarding/views/CreatePasswordView.qml b/ui/app/AppLayouts/Onboarding/views/CreatePasswordView.qml index ed5f6867b5..e664f074a9 100644 --- a/ui/app/AppLayouts/Onboarding/views/CreatePasswordView.qml +++ b/ui/app/AppLayouts/Onboarding/views/CreatePasswordView.qml @@ -1,28 +1,20 @@ import QtQuick 2.0 import QtQuick.Controls 2.13 import QtQuick.Layouts 1.12 - import StatusQ.Controls 0.1 import StatusQ.Core.Theme 0.1 - import utils 1.0 +import shared.views 1.0 import "../../Profile/views" +import "../controls" -Page { +OnboardingBasePage { id: root - property var store property string newPassword property string confirmationPassword - - signal passwordCreated(string newPassword, string confirmationPassword) - signal backClicked() - - anchors.fill: parent - background: null - - Component.onCompleted: { view.forceNewPswInputFocus() } + function forceNewPswInputFocus() { view.forceNewPswInputFocus() } QtObject { id: d @@ -34,21 +26,23 @@ Page { spacing: 4 * Style.current.padding anchors.centerIn: parent z: view.zFront - PasswordView { id: view - store: root.store + onboarding: true newPswText: root.newPassword confirmationPswText: root.confirmationPassword } - StatusButton { id: submitBtn z: d.zFront anchors.horizontalCenter: parent.horizontalCenter text: qsTr("Create password") enabled: view.ready - onClicked: { passwordCreated(view.newPswText, view.confirmationPswText) } + onClicked: { + root.newPassword = view.newPswText + root.confirmationPassword = view.confirmationPswText + root.finished() + } } } @@ -62,7 +56,6 @@ Page { icon.name: "arrow-left" onClicked: { root.backClicked() } } - // By clicking anywhere outside password entries fields or focusable element in the view, it is needed to check if passwords entered matches MouseArea { anchors.fill: parent diff --git a/ui/app/AppLayouts/Onboarding/views/GenKeyView.qml b/ui/app/AppLayouts/Onboarding/views/GenKeyView.qml index d71b749add..17c3c38828 100644 --- a/ui/app/AppLayouts/Onboarding/views/GenKeyView.qml +++ b/ui/app/AppLayouts/Onboarding/views/GenKeyView.qml @@ -1,33 +1,102 @@ import QtQuick 2.13 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 +import StatusQ.Components 0.1 +import StatusQ.Controls 0.1 +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 -import "../popups" +import shared.panels 1.0 + +import utils 1.0 + +import "../controls" +import "../panels" import "../stores" -import "../shared" -Item { - property var onClosed: function () {} - signal showCreatePasswordView() - - id: genKeyView +OnboardingBasePage { + id: root anchors.fill: parent + Behavior on opacity { NumberAnimation { duration: 200 }} + state: "username" - Component.onCompleted: { - genKeyModal.open() + signal keysGenerated() + + function gotoKeysStack(stackIndex) { createKeysStack.currentIndex = stackIndex } + + enum KeysStack { + DETAILS, + CREATE_PWD, + CONFRIM_PWD, + TOUCH_ID } - GenKeyModal { - property bool wentNext: false - id: genKeyModal - onNextClick: function (selectedIndex, displayName) { - wentNext = true - OnboardingStore.setCurrentAccountAndDisplayName(selectedIndex, displayName) - showCreatePasswordView() + QtObject { + id: d + + property string newPassword + property string confirmationPassword + } + + StackLayout { + id: createKeysStack + anchors.fill: parent + currentIndex: GenKeyView.KeysStack.DETAILS + + onCurrentIndexChanged: { + // Set focus: + if(currentIndex === GenKeyView.KeysStack.CREATE_PWD) + createPswView.forceNewPswInputFocus() + else if(currentIndex === GenKeyView.KeysStack.CONFRIM_PWD) + confirmPswView.forcePswInputFocus() } - onClosed: function () { - if (!wentNext) { - genKeyView.onClosed() + + InsertDetailsView { + id: userDetailsPanel + onCreatePassword: { gotoKeysStack(GenKeyView.KeysStack.CREATE_PWD) } + } + CreatePasswordView { + id: createPswView + newPassword: d.newPassword + confirmationPassword: d.confirmationPassword + + onFinished: { + d.newPassword = newPassword + d.confirmationPassword = confirmationPassword + gotoKeysStack(GenKeyView.KeysStack.CONFRIM_PWD) } + onBackClicked: { + d.newPassword = "" + d.confirmationPassword = "" + gotoKeysStack(GenKeyView.KeysStack.DETAILS) + } + } + ConfirmPasswordView { + id: confirmPswView + password: d.newPassword + displayName: userDetailsPanel.displayName + onFinished: { + if (Qt.platform.os == "osx") { + gotoKeysStack(GenKeyView.KeysStack.TOUCH_ID); + } else { + root.keysGenerated(); + } + } + onBackClicked: { gotoKeysStack(GenKeyView.KeysStack.CREATE_PWD) } + } + TouchIDAuthView { + userPass: d.newPassword + onBackClicked: { gotoKeysStack(GenKeyView.KeysStack.CONFRIM_PWD) } + onGenKeysDone: { root.keysGenerated() } + } + } + + onBackClicked: { + if (userDetailsPanel.state === "chatkey") { + userDetailsPanel.state = "username"; + } else { + root.finished(); } } } diff --git a/ui/app/AppLayouts/Onboarding/views/InsertDetailsView.qml b/ui/app/AppLayouts/Onboarding/views/InsertDetailsView.qml new file mode 100644 index 0000000000..501eb188e0 --- /dev/null +++ b/ui/app/AppLayouts/Onboarding/views/InsertDetailsView.qml @@ -0,0 +1,251 @@ +import QtQuick 2.13 +import QtQuick.Layouts 1.12 +import StatusQ.Components 0.1 +import StatusQ.Controls 0.1 +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 + +import shared.panels 1.0 + +import utils 1.0 +import shared.controls 1.0 +import "../popups" +import "../stores" + +Item { + id: root + + property string pubKey + property string address + property string displayName + signal createPassword() + + state: "username" + + ListView { + id: accountsList + model: OnboardingStore.onboardingModuleInst.accountsModel + delegate: Item { + Component.onCompleted: { + root.pubKey = model.pubKey; + root.address = model.address; + } + } + } + + ColumnLayout { + anchors.centerIn: parent + spacing: Style.current.padding + + StyledText { + id: usernameText + text: qsTr("Your profile") + font.weight: Font.Bold + font.pixelSize: 22 + Layout.alignment: Qt.AlignHCenter + } + + StyledText { + id: txtDesc + Layout.preferredWidth: (root.state === "username") ? 338 : 643 + color: Style.current.secondaryText + text: qsTr("Longer and unusual names are better as they are less likely to be used by someone else.") + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + Layout.alignment: Qt.AlignHCenter + font.pixelSize: 15 + } + + Item { + implicitWidth: 100 + implicitHeight: 100 + Layout.alignment: Qt.AlignHCenter + StatusSmartIdenticon { + id: userImage + image.width: 80 + image.height: 80 + icon.width: 80 + icon.height: 80 + icon.letterSize: 32 + icon.color: Theme.palette.miscColor5 + icon.charactersLen: 2 + image.isIdenticon: false + image.source: uploadProfilePicPopup.selectedImage + ringSettings { ringSpecModel: Utils.getColorHashAsJson(root.pubKey) } + } + StatusRoundButton { + id: updatePicButton + width: 40 + height: 40 + anchors.top: parent.top + anchors.right: parent.right + type: StatusFlatRoundButton.Type.Secondary + icon.name: "add" + onClicked: { + uploadProfilePicPopup.open(); + } + } + } + + StatusInput { + id: nameInput + implicitWidth: 328 + Layout.alignment: Qt.AlignHCenter + input.placeholderText: qsTr("Display name") + input.edit.font.capitalization: Font.Capitalize + input.rightComponent: RoundedIcon { + width: 14 + height: 14 + iconWidth: 14 + iconHeight: 14 + color: "transparent" + source: Style.svg("close-filled") + onClicked: { + nameInput.input.edit.clear(); + } + } + onTextChanged: { + userImage.name = text; + } + } + + StyledText { + id: chatKeyTxt + color: Style.current.secondaryText + text: "Chatkey:" + root.address + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + Layout.alignment: Qt.AlignHCenter + font.pixelSize: 15 + } + + Item { + id: chainsChatKeyImg + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: 181 + Layout.preferredHeight: 84 + Image { + anchors.horizontalCenter: parent.horizontalCenter + source: Style.png("onboarding/chains") + } + EmojiHash { + anchors.bottom: parent.bottom + publicKey: root.pubKey + } + StatusSmartIdenticon { + id: userImageCopy + anchors.bottom: parent.bottom + anchors.right: parent.right + icon.width: 44 + icon.height: 44 + icon.color: "transparent" + ringSettings { ringSpecModel: Utils.getColorHashAsJson(root.pubKey) } + } + } + StatusButton { + Layout.alignment: Qt.AlignHCenter | Qt.AlignTop + Layout.topMargin: 125 + enabled: !!nameInput.text + text: qsTr("Next") + onClicked: { + if (root.state === "username") { + if (OnboardingStore.accountCreated) { + OnboardingStore.updatedDisplayName(nameInput.text); + } + root.displayName = nameInput.text; + root.state = "chatkey"; + } else { + createPassword(); + } + } + } + + UploadProfilePicModal { + id: uploadProfilePicPopup + } + } + + states: [ + State { + name: "username" + PropertyChanges { + target: usernameText + text: qsTr("Your profile") + } + PropertyChanges { + target: txtDesc + text: qsTr("Longer and unusual names are better as they are less likely to be used by someone else.") + } + PropertyChanges { + target: chatKeyTxt + visible: false + } + PropertyChanges { + target: chainsChatKeyImg + visible: false + } + PropertyChanges { + target: userImageCopy + visible: false + } + PropertyChanges { + target: updatePicButton + visible: true + } + PropertyChanges { + target: nameInput + visible: true + } + }, + State { + name: "chatkey" + PropertyChanges { + target: usernameText + text: qsTr("Your emojihash and identicon ring") + } + PropertyChanges { + target: txtDesc + text: qsTr("This set of emojis and coloured ring around your avatar are unique and represent your chat key, so your friends can easily distinguish you from potential impersonators.") + } + PropertyChanges { + target: chatKeyTxt + visible: true + } + PropertyChanges { + target: chainsChatKeyImg + visible: true + } + PropertyChanges { + target: userImageCopy + visible: true + } + PropertyChanges { + target: updatePicButton + visible: false + } + PropertyChanges { + target: nameInput + visible: false + } + } + ] + + transitions: [ + Transition { + from: "*" + to: "*" + SequentialAnimation { + PropertyAction { + target: root + property: "opacity" + value: 0.0 + } + PropertyAction { + target: root + property: "opacity" + value: 1.0 + } + } + } + ] +} diff --git a/ui/app/AppLayouts/Onboarding/views/KeysMainView.qml b/ui/app/AppLayouts/Onboarding/views/KeysMainView.qml index 05d48093eb..a540df50d9 100644 --- a/ui/app/AppLayouts/Onboarding/views/KeysMainView.qml +++ b/ui/app/AppLayouts/Onboarding/views/KeysMainView.qml @@ -10,31 +10,16 @@ import StatusQ.Core.Theme 0.1 import shared 1.0 import shared.panels 1.0 import "../popups" +import "../controls" import utils 1.0 -Page { +OnboardingBasePage { id: root signal buttonClicked() signal keycardLinkClicked() signal seedLinkClicked() - signal backClicked() - - background: Rectangle { - color: Style.current.background - } - - Component.onCompleted: { - if(displayBeforeGetStartedModal) { - displayBeforeGetStartedModal = false - beforeGetStartedModal.open() - } - } - - BeforeGetStartedModal { - id: beforeGetStartedModal - } Item { id: container @@ -141,17 +126,6 @@ Page { } } - StatusRoundButton { - anchors.left: parent.left - anchors.leftMargin: Style.current.padding - anchors.bottom: parent.bottom - anchors.bottomMargin: Style.current.padding - icon.name: "arrow-left" - onClicked: { - root.backClicked(); - } - } - states: [ State { name: "connectkeys" @@ -168,6 +142,7 @@ Page { PropertyChanges { target: button text: qsTr("Scan sync code") + enabled: false } PropertyChanges { diff --git a/ui/app/AppLayouts/Onboarding/views/LoginView.qml b/ui/app/AppLayouts/Onboarding/views/LoginView.qml index 1485ca8f1c..6c25a2da84 100644 --- a/ui/app/AppLayouts/Onboarding/views/LoginView.qml +++ b/ui/app/AppLayouts/Onboarding/views/LoginView.qml @@ -31,7 +31,6 @@ Item { loading = true LoginStore.login(password) - Global.applicationWindow.prepareForStoring(password, false) txtPassword.textField.clear() } diff --git a/ui/app/AppLayouts/Onboarding/views/TouchIDAuthView.qml b/ui/app/AppLayouts/Onboarding/views/TouchIDAuthView.qml new file mode 100644 index 0000000000..e875f8833a --- /dev/null +++ b/ui/app/AppLayouts/Onboarding/views/TouchIDAuthView.qml @@ -0,0 +1,129 @@ +import QtQuick 2.13 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 +import StatusQ.Components 0.1 +import StatusQ.Controls 0.1 +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 + +import shared.panels 1.0 + +import utils 1.0 + +import "../controls" +import "../panels" +import "../stores" + +OnboardingBasePage { + id: root + + property string userPass + signal genKeysDone(); + + Item { + id: container + enabled: !dimBackground.active + anchors.centerIn: parent + width: 425 + height: { + let h = 0 + const children = this.children + Object.keys(children).forEach(function (key) { + const child = children[key] + h += child.height + Style.current.padding + }) + return h + } + Image { + id: keysImg + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + fillMode: Image.PreserveAspectFit + source: Style.png("onboarding/fingerprint") + width: 160 + height: 160 + mipmap: true + } + + StyledText { + id: txtTitle + text: qsTr("Biometrics") + anchors.topMargin: Style.current.padding + font.bold: true + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: keysImg.bottom + font.letterSpacing: -0.2 + font.pixelSize: 22 + } + + StyledText { + id: txtDesc + width: 426 + anchors.top: txtTitle.bottom + anchors.topMargin: Style.current.padding + color: Style.current.secondaryText + text: qsTrId("Would you like to use your TouchID to login to Status?") + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + font.pixelSize: 15 + } + ColumnLayout { + anchors.topMargin: 40 + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: txtDesc.bottom + spacing: Style.current.bigPadding + StatusButton { + id: button + Layout.alignment: Qt.AlignHCenter + text: qsTr("Yes, use TouchID ") + onClicked: { + OnboardingStore.accountSettings.storeToKeychainValue = Constants.storeToKeychainValueStore; + dimBackground.active = true; + OnboardingStore.storeToKeyChain(userPass); + } + } + StatusBaseText { + id: keycardLink + Layout.alignment: Qt.AlignHCenter + color: Theme.palette.primaryColor1 + text: qsTr("I prefer to use my PIN") + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + onEntered: { + parent.font.underline = true + } + onExited: { + parent.font.underline = false + } + onClicked: { + OnboardingStore.accountSettings.storeToKeychainValue = Constants.storeToKeychainValueNever; + root.genKeysDone(); + } + } + } + } + } + + Loader { + id: dimBackground + anchors.fill: parent + active: false + sourceComponent: Rectangle { + color: Qt.rgba(0, 0, 0, 0.4) + } + } + + Connections { + enabled: !!OnboardingStore.mainModuleInst + target: OnboardingStore.mainModuleInst + onStoringPasswordSuccess: { + dimBackground.active = false; + root.genKeysDone(); + } + onStoringPasswordError: { + dimBackground.active = false; + } + } +} diff --git a/ui/app/AppLayouts/Onboarding/views/WelcomeView.qml b/ui/app/AppLayouts/Onboarding/views/WelcomeView.qml index 1c72af46ed..f1fb93355b 100644 --- a/ui/app/AppLayouts/Onboarding/views/WelcomeView.qml +++ b/ui/app/AppLayouts/Onboarding/views/WelcomeView.qml @@ -7,6 +7,7 @@ import StatusQ.Controls 0.1 import shared 1.0 import shared.panels 1.0 import "../popups" +import "../stores" import utils 1.0 @@ -21,14 +22,16 @@ Page { } Component.onCompleted: { - if(displayBeforeGetStartedModal) { - displayBeforeGetStartedModal = false - beforeGetStartedModal.open() + if (OnboardingStore.showBeforeGetStartedPopup) { + beforeGetStartedModal.open(); } } BeforeGetStartedModal { id: beforeGetStartedModal + onClosed: { + OnboardingStore.showBeforeGetStartedPopup = false; + } } Item { @@ -52,7 +55,7 @@ Page { anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top fillMode: Image.PreserveAspectFit - source: Style.png("welcome") + source: Style.png("onboarding/welcome") width: 256 height: 256 mipmap: true diff --git a/ui/app/AppLayouts/Profile/popups/ChangePasswordModal.qml b/ui/app/AppLayouts/Profile/popups/ChangePasswordModal.qml index 97bd24150d..2f5866ef27 100644 --- a/ui/app/AppLayouts/Profile/popups/ChangePasswordModal.qml +++ b/ui/app/AppLayouts/Profile/popups/ChangePasswordModal.qml @@ -5,6 +5,7 @@ import QtQuick.Layouts 1.12 import utils 1.0 import shared 1.0 +import shared.views 1.0 import shared.panels 1.0 import shared.controls 1.0 @@ -45,7 +46,6 @@ StatusModal { PasswordView { id: view - store: root.privacyStore anchors.topMargin: Style.current.padding anchors.centerIn: parent titleVisible: false diff --git a/ui/app/AppLayouts/Profile/popups/StoreToKeychainSelectionModal.qml b/ui/app/AppLayouts/Profile/popups/StoreToKeychainSelectionModal.qml index ab255f4942..84ddb7f27e 100644 --- a/ui/app/AppLayouts/Profile/popups/StoreToKeychainSelectionModal.qml +++ b/ui/app/AppLayouts/Profile/popups/StoreToKeychainSelectionModal.qml @@ -58,7 +58,9 @@ ModalPopup { checked: localAccountSettings.storeToKeychainValue === Constants.storeToKeychainValueStore onCheckedChanged: { if (checked && localAccountSettings.storeToKeychainValue !== Constants.storeToKeychainValueStore) { - // TODO: REFACTOR TO NEW PASWORD VIEW + // TODO: REFACTOR TO NEW PASWORD VIEW AND + // DELETE StoreToKeychainSelectionModal.qml + // AND CreatePasswordModal.qml IF NOT NEEDED var storePassPopup = Global.openPopup(storePasswordModal) if(storePassPopup) { diff --git a/ui/app/AppLayouts/Profile/stores/PrivacyStore.qml b/ui/app/AppLayouts/Profile/stores/PrivacyStore.qml index 1c589b2d7c..e3c17320a8 100644 --- a/ui/app/AppLayouts/Profile/stores/PrivacyStore.qml +++ b/ui/app/AppLayouts/Profile/stores/PrivacyStore.qml @@ -28,8 +28,4 @@ QtObject { function validatePassword(password) { return root.privacyModule.validatePassword(password) } - - function getPasswordStrengthScore(password) { - return root.privacyModule.getPasswordStrengthScore(password) - } } diff --git a/ui/imports/assets/images/onboarding/chains.png b/ui/imports/assets/images/onboarding/chains.png new file mode 100644 index 0000000000..0b00308337 Binary files /dev/null and b/ui/imports/assets/images/onboarding/chains.png differ diff --git a/ui/imports/assets/images/onboarding/fingerprint.png b/ui/imports/assets/images/onboarding/fingerprint.png new file mode 100644 index 0000000000..2d55850a76 Binary files /dev/null and b/ui/imports/assets/images/onboarding/fingerprint.png differ diff --git a/ui/imports/assets/images/welcome.png b/ui/imports/assets/images/onboarding/welcome.png similarity index 100% rename from ui/imports/assets/images/welcome.png rename to ui/imports/assets/images/onboarding/welcome.png diff --git a/ui/imports/shared/controls/EmojiHash.qml b/ui/imports/shared/controls/EmojiHash.qml new file mode 100644 index 0000000000..5c39305210 --- /dev/null +++ b/ui/imports/shared/controls/EmojiHash.qml @@ -0,0 +1,24 @@ +import QtQuick 2.13 +import StatusQ.Core.Utils 0.1 as StatusQUtils +import utils 1.0 + +Text { + id: root + property string publicKey + property string size: "14x14" + renderType: Text.NativeRendering + font.pointSize: 1 // make sure there is no padding for emojis due to 'style: "vertical-align: top"' + text: { + const emojiHash = Utils.getEmojiHashAsJson(root.publicKey); + var emojiHashFirstLine = ""; + var emojiHashSecondLine = ""; + for (var i = 0; i < 7; i++) { + emojiHashFirstLine += emojiHash[i]; + } + for (var j = 7; j < emojiHash.length; j++) { + emojiHashSecondLine += emojiHash[j]; + } + return StatusQUtils.Emoji.parse(emojiHashFirstLine, size) + "
" + + StatusQUtils.Emoji.parse(emojiHashSecondLine, size) + } +} diff --git a/ui/imports/shared/controls/chat/ProfileHeader.qml b/ui/imports/shared/controls/chat/ProfileHeader.qml index f22148e9cd..e1551553de 100644 --- a/ui/imports/shared/controls/chat/ProfileHeader.qml +++ b/ui/imports/shared/controls/chat/ProfileHeader.qml @@ -3,6 +3,7 @@ import QtQuick.Layouts 1.14 import utils 1.0 import shared.panels 1.0 +import shared.controls 1.0 import StatusQ.Components 0.1 import StatusQ.Core.Utils 0.1 as StatusQUtils @@ -88,33 +89,14 @@ Item { color: Style.current.secondaryText } - Text { + EmojiHash { id: emojihash - - readonly property size finalSize: supersampling ? Qt.size(emojiSize.width * 2, emojiSize.height * 2) : emojiSize - property string size: `${finalSize.width}x${finalSize.height}` - Layout.fillWidth: true - renderType: Text.NativeRendering - scale: supersampling ? 0.5 : 1 - - text: { - const emojiHash = Utils.getEmojiHashAsJson(root.pubkey) - var emojiHashFirstLine = "" - var emojiHashSecondLine = "" - for (var i = 0; i < 7; i++) { - emojiHashFirstLine += emojiHash[i] - } - for (var i = 7; i < emojiHash.length; i++) { - emojiHashSecondLine += emojiHash[i] - } - - return StatusQUtils.Emoji.parse(emojiHashFirstLine, size) + "
" + - StatusQUtils.Emoji.parse(emojiHashSecondLine, size) - } - horizontalAlignment: Text.AlignHCenter - font.pointSize: 1 // make sure there is no padding for emojis due to 'style: "vertical-align: top"' + publicKey: root.pubkey + readonly property size finalSize: supersampling ? Qt.size(emojiSize.width * 2, emojiSize.height * 2) : emojiSize + size: `${finalSize.width}x${finalSize.height}` + scale: supersampling ? 0.5 : 1 } } } diff --git a/ui/imports/shared/controls/qmldir b/ui/imports/shared/controls/qmldir index f9c647452d..9db2509f68 100644 --- a/ui/imports/shared/controls/qmldir +++ b/ui/imports/shared/controls/qmldir @@ -23,3 +23,4 @@ StyledTextEdit 1.0 StyledTextEdit.qml StyledTextField 1.0 StyledTextField.qml Timer 1.0 Timer.qml TransactionFormGroup 1.0 TransactionFormGroup.qml +EmojiHash 1.0 EmojiHash.qml diff --git a/ui/imports/shared/panels/ImageLoader.qml b/ui/imports/shared/panels/ImageLoader.qml index e7a8f2ab9a..d275503af3 100644 --- a/ui/imports/shared/panels/ImageLoader.qml +++ b/ui/imports/shared/panels/ImageLoader.qml @@ -1,4 +1,4 @@ -import QtQuick 2.3 +import QtQuick 2.13 import QtGraphicalEffects 1.13 import StatusQ.Components 0.1 @@ -53,7 +53,8 @@ Rectangle { ] Connections { - target: mainModule + enabled: !!mainModule + target: enabled ? mainModule : undefined onOnlineStatusChanged: { if (connected && root.state !== "ready" && root.visible && diff --git a/ui/imports/shared/stores/RootStore.qml b/ui/imports/shared/stores/RootStore.qml index 8da246f9a2..617afc1162 100644 --- a/ui/imports/shared/stores/RootStore.qml +++ b/ui/imports/shared/stores/RootStore.qml @@ -10,6 +10,9 @@ QtObject { // property var keycardModelInst: !!keycardModel ? keycardModel : null // property var profileModelInst: !!profileModel ? profileModel : null + property var profileSectionModuleInst: profileSectionModule + property var privacyModule: profileSectionModuleInst.privacyModule + property var onboardingModuleInst: onboardingModule property var userProfileInst: !!userProfile ? userProfile : null property var walletSectionInst: !!walletSection ? walletSection : null property var appSettings: !!localAppSettings ? localAppSettings : null @@ -97,4 +100,13 @@ QtObject { function addToRecentsGif(id) { chatSectionChatContentInputArea.addToRecentsGif(id) } + + function getPasswordStrengthScore(password, onboarding = false) { + if (onboarding) { + let userName = root.onboardingModuleInst.importedAccountAlias; + return root.onboardingModuleInst.getPasswordStrengthScore(password, userName); + } else { + return root.privacyModule.getPasswordStrengthScore(password); + } + } } diff --git a/ui/app/AppLayouts/Profile/views/PasswordView.qml b/ui/imports/shared/views/PasswordView.qml similarity index 98% rename from ui/app/AppLayouts/Profile/views/PasswordView.qml rename to ui/imports/shared/views/PasswordView.qml index 78608fdede..4dd2f29e1c 100644 --- a/ui/app/AppLayouts/Profile/views/PasswordView.qml +++ b/ui/imports/shared/views/PasswordView.qml @@ -4,6 +4,7 @@ import QtQuick.Layouts 1.12 import shared.panels 1.0 import shared.controls 1.0 +import shared.stores 1.0 import utils 1.0 import StatusQ.Controls 0.1 @@ -13,7 +14,6 @@ import StatusQ.Components 0.1 Column { id: root - property var store property bool ready: newPswInput.text.length >= root.minPswLen && newPswInput.text === confirmPswInput.text && errorTxt.text === "" property int minPswLen: 6 property bool createNewPsw: true @@ -22,6 +22,7 @@ Column { property string introText: qsTr("Create a password to unlock Status on this device & sign transactions.") property string recoverText: qsTr("You will not be able to recover this password if it is lost.") property string strengthenText: qsTr("Minimum 6 characers. To strengthen your password consider including:") + property bool onboarding: false readonly property int zBehind: 1 readonly property int zFront: 100 @@ -208,7 +209,7 @@ Column { d.containsSymbols = d.symbolsValidator(text) // Update strength indicator: - strengthInditactor.strength = d.convertStrength(root.store.getPasswordStrengthScore(newPswInput.text)) + strengthInditactor.strength = d.convertStrength(RootStore.getPasswordStrengthScore(newPswInput.text, root.onboarding)) } StatusFlatRoundButton { diff --git a/ui/imports/shared/views/qmldir b/ui/imports/shared/views/qmldir index 00701829ec..99e17b062d 100644 --- a/ui/imports/shared/views/qmldir +++ b/ui/imports/shared/views/qmldir @@ -5,3 +5,4 @@ SearchResults 1.0 SearchResults.qml TransactionPreview 1.0 TransactionPreview.qml TransactionSigner 1.0 TransactionSigner.qml TransactionStackView 1.0 TransactionStackView.qml +PasswordView 1.0 PasswordView.qml diff --git a/ui/main.qml b/ui/main.qml index 8fe2209a14..dae2d3609a 100644 --- a/ui/main.qml +++ b/ui/main.qml @@ -20,7 +20,6 @@ import AppLayouts.Onboarding 1.0 StatusWindow { property bool hasAccounts: startupModule.appState !== Constants.appState.onboarding - property bool displayBeforeGetStartedModal: !hasAccounts property bool appIsReady: false Universal.theme: Universal.System @@ -109,9 +108,6 @@ StatusWindow { // We set main module to the Global singleton once user is logged in and we move to the main app. Global.mainModuleInst = mainModule - mainModule.openStoreToKeychainPopup.connect(function(){ - storeToKeychainConfirmationPopup.open() - }) if(localAccountSensitiveSettings.recentEmojis === "") { localAccountSensitiveSettings.recentEmojis = []; } @@ -253,50 +249,6 @@ StatusWindow { } } - function prepareForStoring(password, runStoreToKeychainPopup) { - if(Qt.platform.os == "osx") - { - storeToKeychainConfirmationPopup.password = password - - if(runStoreToKeychainPopup) - storeToKeychainConfirmationPopup.open() - } - } - - ConfirmationDialog { - id: storeToKeychainConfirmationPopup - property string password: "" - height: 200 - confirmationText: qsTr("Would you like to store password to the Keychain?") - showRejectButton: true - showCancelButton: true - confirmButtonLabel: qsTr("Store") - rejectButtonLabel: qsTr("Not now") - cancelButtonLabel: qsTr("Never") - - function finish() - { - password = "" - storeToKeychainConfirmationPopup.close() - } - - onConfirmButtonClicked: { - localAccountSettings.storeToKeychainValue = Constants.storeToKeychainValueStore - mainModule.storePassword(password) - finish() - } - - onRejectButtonClicked: { - localAccountSettings.storeToKeychainValue = Constants.storeToKeychainValueNotNow - finish() - } - - onCancelButtonClicked: { - localAccountSettings.storeToKeychainValue = Constants.storeToKeychainValueNever - finish() - } - } - Loader { id: loader anchors.fill: parent @@ -321,7 +273,9 @@ StatusWindow { onOnBoardingStepChanged: { loader.sourceComponent = view; - loader.item.state = state; + if (!!state) { + loader.item.state = state; + } } }