diff options
| author | dsc <xmrdsc@protonmail.com> | 2019-01-14 01:02:44 +0100 |
|---|---|---|
| committer | dsc <xmrdsc@protonmail.com> | 2019-02-22 03:05:27 +0100 |
| commit | f329a710295deed3c15f2acff9a519c0a70e98e1 (patch) | |
| tree | 95d2b1f6b8c31826a561d74d33368c1e9ef85d42 /wizard/WizardController.qml | |
| parent | 333f4aaf83bd64de02b07a56d86bbf90363e403b (diff) | |
| download | monzero-gui-f329a710295deed3c15f2acff9a519c0a70e98e1.tar.gz monzero-gui-f329a710295deed3c15f2acff9a519c0a70e98e1.tar.xz monzero-gui-f329a710295deed3c15f2acff9a519c0a70e98e1.zip | |
Wizard redesign
Diffstat (limited to 'wizard/WizardController.qml')
| -rw-r--r-- | wizard/WizardController.qml | 484 |
1 files changed, 484 insertions, 0 deletions
diff --git a/wizard/WizardController.qml b/wizard/WizardController.qml new file mode 100644 index 00000000..75e30389 --- /dev/null +++ b/wizard/WizardController.qml @@ -0,0 +1,484 @@ +// Copyright (c) 2014-2019, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.2 +import QtQuick.Dialogs 1.2 + +import moneroComponents.Wallet 1.0 +import "../js/Wizard.js" as Wizard +import "../js/Windows.js" as Windows +import "../js/Utils.js" as Utils +import "../components" as MoneroComponents +import "../pages" + +Rectangle { + id: wizardController + anchors.fill: parent + + signal useMoneroClicked() + + function restart() { + wizardStateView.state = "wizardHome" + wizardController.walletOptionsName = defaultAccountName; + wizardController.walletOptionsLocation = ''; + wizardController.walletOptionsPassword = ''; + wizardController.walletOptionsSeed = ''; + wizardController.walletOptionsBackup = ''; + wizardController.walletRestoreMode = 'seed'; + wizardController.walletOptionsRestoreHeight = 0; + wizardController.walletOptionsIsRecovering = false; + wizardController.walletOptionsIsRecoveringFromDevice = false; + wizardController.walletOptionsDeviceName = ''; + wizardController.tmpWalletFilename = ''; + wizardController.walletRestoreMode = 'seed' + wizardController.walletOptionsSubaddressLookahead = ""; + wizardController.remoteNodes = {}; + wizardController.walletOptionsIsRecoveringFromDevice = false; + } + + property var m_wallet; + property alias wizardState: wizardStateView.state + property alias wizardStatePrevious: wizardStateView.previousView + property int wizardSubViewWidth: 780 * scaleRatio + property int wizardSubViewTopMargin: persistentSettings.customDecorations ? 90 * scaleRatio : 32 * scaleRatio + property bool skipModeSelection: false + + // wallet variables + property string walletOptionsName: '' + property string walletOptionsLocation: '' + property string walletOptionsPassword: '' + property string walletOptionsSeed: '' + property string walletOptionsBackup: '' + property int walletOptionsRestoreHeight: 0 + property string walletOptionsBootstrapAddress: persistentSettings.bootstrapNodeAddress + property bool walletOptionsRestoringFromDevice: false + property bool walletOptionsIsRecovering: false + property bool walletOptionsIsRecoveringFromDevice: false + property string walletOptionsSubaddressLookahead: '' + property string walletOptionsDeviceName: '' + property string tmpWalletFilename: '' + property var remoteNodes: '' + + // language settings, updated via sidebar + property string language_locale: 'en_US' + property string language_wallet: 'English' + property string language_language: 'English (US)' + + // recovery made (restore wallet) + property string walletRestoreMode: 'seed' // seed, keys, qr + + property int layoutScale: { + if(isMobile){ + return 0; + } else if(appWindow.width < 800){ + return 1; + } else { + return 2; + } + } + + Image { + opacity: 1.0 + anchors.fill: parent + source: "../images/middlePanelBg.jpg" + } + + Rectangle { + id: wizardStateView + property Item currentView + property Item previousView + property WizardLanguage wizardLanguageView: WizardLanguage { } + property WizardHome wizardHomeView: WizardHome { } + property WizardCreateWallet1 wizardCreateWallet1View: WizardCreateWallet1 { } + property WizardCreateWallet2 wizardCreateWallet2View: WizardCreateWallet2 { } + property WizardCreateWallet3 wizardCreateWallet3View: WizardCreateWallet3 { } + property WizardCreateWallet4 wizardCreateWallet4View: WizardCreateWallet4 { } + property WizardRestoreWallet1 wizardRestoreWallet1View: WizardRestoreWallet1 { } + property WizardRestoreWallet2 wizardRestoreWallet2View: WizardRestoreWallet2 { } + property WizardRestoreWallet3 wizardRestoreWallet3View: WizardRestoreWallet3 { } + property WizardRestoreWallet4 wizardRestoreWallet4View: WizardRestoreWallet4 { } + property WizardCreateDevice1 wizardCreateDevice1View: WizardCreateDevice1 { } + property WizardOpenWallet1 wizardOpenWallet1View: WizardOpenWallet1 { } + property WizardModeSelection wizardModeSelectionView: WizardModeSelection { } + property WizardModeRemoteNodeWarning wizardModeRemoteNodeWarningView: WizardModeRemoteNodeWarning { } + property WizardModeBootstrap wizardModeBootstrapView: WizardModeBootstrap {} + anchors.fill: parent + + signal previousClicked; + + color: "transparent" + state: '' + + onPreviousClicked: { + if (previousView && previousView.viewName != null){ + state = previousView.viewName; + } else { + state = "wizardHome"; + } + } + + onCurrentViewChanged: { + if (previousView) { + if (typeof previousView.onPageClosed === "function") { + previousView.onPageClosed(); + } + + // Combined with NumberAnimation to fade out views + previousView.opacity = 0; + } + + if (currentView) { + stackView.replace(currentView) + // Calls when view is opened + if (typeof currentView.onPageCompleted === "function") { + currentView.onPageCompleted(previousView); + } + + // Combined with NumberAnimation to fade in views + currentView.opacity = 1; + } + + previousView = currentView; + } + + states: [ + State { + name: "wizardLanguage" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardLanguageView } + }, State { + name: "wizardHome" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardHomeView } + }, State { + name: "wizardCreateWallet1" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardCreateWallet1View } + }, State { + name: "wizardCreateWallet2" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardCreateWallet2View } + }, State { + name: "wizardCreateWallet3" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardCreateWallet3View } + }, State { + name: "wizardCreateWallet4" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardCreateWallet4View } + }, State { + name: "wizardRestoreWallet1" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardRestoreWallet1View } + }, State { + name: "wizardRestoreWallet2" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardRestoreWallet2View } + }, State { + name: "wizardRestoreWallet3" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardRestoreWallet3View } + }, State { + name: "wizardRestoreWallet4" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardRestoreWallet4View } + }, State { + name: "wizardCreateDevice1" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardCreateDevice1View } + }, State { + name: "wizardOpenWallet1" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardOpenWallet1View } + }, State { + name: "wizardModeSelection" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardModeSelectionView } + }, State { + name: "wizardModeRemoteNodeWarning" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardModeRemoteNodeWarningView } + }, State { + name: "wizardModeBootstrap" + PropertyChanges { target: wizardStateView; currentView: wizardStateView.wizardModeBootstrapView } + } + ] + + StackView { + id: stackView + initialItem: wizardStateView.wizardLanguageView + anchors.fill: parent + clip: false + + delegate: StackViewDelegate { + pushTransition: StackViewTransition { + PropertyAnimation { + target: enterItem + property: "x" + from: target.width + to: 0 + duration: 300 + easing.type: Easing.OutCubic + } + PropertyAnimation { + target: exitItem + property: "x" + from: 0 + to: 0 - target.width + duration: 300 + easing.type: Easing.OutCubic + } + } + } + } + } + + //Open Wallet from file + FileDialog { + id: fileDialog + title: qsTr("Please choose a file") + translationManager.emptyString + folder: "file://" + moneroAccountsDir + nameFilters: [ "Wallet files (*.keys)"] + sidebarVisible: false + + onAccepted: { + wizardController.openWalletFile(fileDialog.fileUrl); + } + onRejected: { + console.log("Canceled") + appWindow.viewState = "wizard"; + } + } + + function createWallet() { + // Creates wallet in a temp. location + + // Always delete the wallet object before creating new - we could be stepping back from recovering wallet + if (typeof wizardController.m_wallet !== 'undefined') { + walletManager.closeWallet() + console.log("deleting wallet") + } + + var tmp_wallet_filename = oshelper.temporaryFilename(); + console.log("Creating temporary wallet", tmp_wallet_filename) + var nettype = appWindow.persistentSettings.nettype; + var kdfRounds = appWindow.persistentSettings.kdfRounds; + var wallet = walletManager.createWallet(tmp_wallet_filename, "", wizardController.language_wallet, nettype, kdfRounds) + + wizardController.walletOptionsSeed = wallet.seed + + // saving wallet in "global" object + // @TODO: wallet should have a property pointing to the file where it stored or loaded from + wizardController.m_wallet = wallet; + wizardController.tmpWalletFilename = tmp_wallet_filename + } + + function writeWallet() { + // Save wallet files in user specified location + var new_wallet_filename = Wizard.createWalletPath( + isIOS, + wizardController.walletOptionsLocation, + wizardController.walletOptionsName); + + if(isIOS) { + console.log("saving in ios: " + moneroAccountsDir + new_wallet_filename) + wizardController.m_wallet.store(moneroAccountsDir + new_wallet_filename); + } else { + console.log("saving in wizard: " + new_wallet_filename) + wizardController.m_wallet.store(new_wallet_filename); + } + + // make sure temporary wallet files are deleted + console.log("Removing temporary wallet: " + wizardController.tmpWalletFilename) + oshelper.removeTemporaryWallet(wizardController.tmpWalletFilename) + + // protecting wallet with password + m_wallet.setPassword(walletOptionsPassword); + + // Store password in session to be able to use password protected functions (e.g show seed) + appWindow.walletPassword = walletOptionsPassword + + // save to persistent settings + persistentSettings.language = wizardController.language_language + persistentSettings.locale = wizardController.language_locale + + persistentSettings.account_name = wizardController.walletOptionsName + persistentSettings.wallet_path = new_wallet_filename + persistentSettings.restore_height = (isNaN(walletOptionsRestoreHeight))? 0 : walletOptionsRestoreHeight + + persistentSettings.allow_background_mining = false + persistentSettings.is_recovering = (wizardController.walletOptionsIsRecovering === undefined) ? false : wizardController.walletOptionsIsRecovering + persistentSettings.is_recovering_from_device = (wizardController.walletOptionsIsRecoveringFromDevice === undefined) ? false : wizardController.walletOptionsIsRecoveringFromDevice + } + + function createWalletFromDevice() { + // TODO: create wallet in temporary filename and a) move it to the path specified by user after the final + // page submitted or b) delete it when program closed before reaching final page + + // Always delete the wallet object before creating new - we could be stepping back from recovering wallet + if (typeof wizardController.m_wallet !== 'undefined') { + walletManager.closeWallet() + console.log("deleting wallet") + } + + var tmp_wallet_filename = oshelper.temporaryFilename(); + console.log("Creating temporary wallet", tmp_wallet_filename) + var nettype = persistentSettings.nettype; + var restoreHeight = wizardController.walletOptionsRestoreHeight; + var subaddressLookahead = wizardController.walletOptionsSubaddressLookahead; + var deviceName = wizardController.walletOptionsDeviceName; + + var wallet = walletManager.createWalletFromDevice(tmp_wallet_filename, "", nettype, deviceName, restoreHeight, subaddressLookahead); + + var success = wallet.status === Wallet.Status_Ok; + if (success) { + wizardController.m_wallet = wallet; + wizardController.walletOptionsIsRecoveringFromDevice = true; + wizardController.tmpWalletFilename = tmp_wallet_filename; + wizardController.walletOptionsRestoreHeight = wizardController.m_wallet.walletCreationHeight; + } else { + console.log(wallet.errorString) + appWindow.showStatusMessage(qsTr(wallet.errorString), 5); + walletManager.closeWallet(); + } + return success; + } + + function openWallet(){ + if (typeof wizardController.m_wallet !== 'undefined' && wizardController.m_wallet != null) { + walletManager.closeWallet() + } + + fileDialog.open(); + } + + function openWalletFile(fn) { + persistentSettings.restore_height = 0; + persistentSettings.is_recovering = false; + + appWindow.restoreHeight = 0; + appWindow.walletPassword = ""; + + if(typeof fn == 'object') + persistentSettings.wallet_path = walletManager.urlToLocalPath(fn); + else + persistentSettings.wallet_path = fn; + + if(isIOS) + persistentSettings.wallet_path = persistentSettings.wallet_path.replace(moneroAccountsDir, ""); + + console.log(moneroAccountsDir); + console.log(fn); + console.log(persistentSettings.wallet_path); + + passwordDialog.onAcceptedCallback = function() { + walletPassword = passwordDialog.password; + appWindow.initialize(); + } + passwordDialog.onRejectedCallback = function() { + console.log("Canceled"); + appWindow.viewState = "wizard"; + } + + passwordDialog.open(appWindow.usefulName(appWindow.walletPath())); + } + + function fetchRemoteNodes(cb, cb_err){ + // Fetch remote nodes, parse JSON, store in result `wizardController.remoteNodes`, call setAutNode(), call callback + var url = appWindow.remoteNodeService + 'api/nodes.json'; + console.log("HTTP request: " + url); + + var xhr = new XMLHttpRequest(); + xhr.timeout = 3500; + + // Unfortunately we cannot spoof User-Agent since it is hardcoded in Qt + //xhr.setRequestHeader("User-Agent", "-"); + + xhr.onreadystatechange = function() { + var msg; + if (xhr.readyState != 4) { + return; + } else if(xhr.status != 200){ + msg = "Error fetching remote nodes; status code was not 200"; + console.log(msg); + if(typeof cb_err === 'function') + return cb_err(msg); + } else { + var body = xhr.responseText; + if(typeof body === 'undefined' || body === ''){ + msg = "Error fetching remote nodes; response body was empty"; + console.log(msg); + if(typeof cb_err === 'function') + return cb_err(msg); + } + + var data = JSON.parse(body); + wizardController.remoteNodes = data; + console.log("node list updated"); + setAutoNode(); + return cb(); + } + } + + xhr.open('GET', url, true); + xhr.send(null); + } + + function setAutoNode(){ + var node; + var nodes; + var nodeObject = wizardController.remoteNodes; + var region = persistentSettings.remoteNodeRegion; + + if(typeof region !== 'undefined' && region !== ""){ + if(nodeObject.hasOwnProperty(region) && nodeObject[region].length > 0){ + nodes = nodeObject[region]; + } else { + console.log("No suitable nodes found for region " + region + ". Defaulting to random node."); + } + } + + if(typeof nodes === 'undefined'){ + nodes = []; + Object.keys(nodeObject).forEach(function(obj, i){ + nodes = nodes.concat(nodeObject[obj]); + }); + } + + // 18089 has precedence + var filteredNodes = Utils.filterNodes(nodes, "18089"); + if(filteredNodes.length > 0){ + node = Utils.randomChoice(filteredNodes); + console.log('Choosing remote node \''+ node +'\' from a list of ' + filteredNodes.length); + } else if(nodes.length > 0){ + node = Utils.randomChoice(nodes); + console.log('Choosing remote node \''+ node +'\' from a list of ' + nodes.length); + } else { + console.log("No suitable nodes found.") + return '' + } + + if(appWindow.walletMode === 0) + persistentSettings.remoteNodeAddress = node; + else if(appWindow.walletMode === 1) + persistentSettings.bootstrapNodeAddress = node; + } + + Component.onCompleted: { + // + } +} |
