diff --git a/libs/Onboarding/qml/Status/Onboarding/TempTextInput.qml b/libs/Onboarding/qml/Status/Onboarding/TempTextInput.qml index bb69b1601c..fc5f4a15e0 100644 --- a/libs/Onboarding/qml/Status/Onboarding/TempTextInput.qml +++ b/libs/Onboarding/qml/Status/Onboarding/TempTextInput.qml @@ -7,11 +7,10 @@ TextInput { font.pointSize: 23 verticalAlignment: TextInput.AlignVCenter + clip: true + Rectangle { - anchors { - fill: parent - margins: -1 - } + anchors.fill: parent border.width: 1 z: parent.z - 1 } diff --git a/libs/Wallet/CMakeLists.txt b/libs/Wallet/CMakeLists.txt index a7cc8c9349..484a3f8042 100644 --- a/libs/Wallet/CMakeLists.txt +++ b/libs/Wallet/CMakeLists.txt @@ -16,7 +16,9 @@ qt6_add_qml_module(Wallet VERSION 1.0 QML_FILES + qml/Status/Wallet/NewAccount/AddWatchOnlyAccountView.qml qml/Status/Wallet/NewAccount/NewWalletAccountView.qml + qml/Status/Wallet/NewAccount/TmpColorComboBox.qml qml/Status/Wallet/AssetsPanel.qml qml/Status/Wallet/AssetView.qml qml/Status/Wallet/WalletContentView.qml diff --git a/libs/Wallet/include/Status/Wallet/NewWalletAccountController.h b/libs/Wallet/include/Status/Wallet/NewWalletAccountController.h index ddd76411fd..1d13a41c5a 100644 --- a/libs/Wallet/include/Status/Wallet/NewWalletAccountController.h +++ b/libs/Wallet/include/Status/Wallet/NewWalletAccountController.h @@ -50,6 +50,10 @@ public: const QColor &color, const QString &path, const Status::Wallet::WalletAccount *derivedFrom); + /// \see \c accountCreatedStatus for async result + Q_INVOKABLE void addWatchOnlyAccountAsync(const QString &address, const QString &name, + const QColor &color); + /// \returns \c false if fails (due to incomplete user input) Q_INVOKABLE bool retrieveAndUpdateDerivedAddresses(const QString &password, @@ -76,6 +80,8 @@ private: WalletAccountPtr findMissingAccount(); AccountsModel::ObjectContainer filterMainAccounts(const AccountsModel &accounts); + /// Logs a debug message if it fails + void addNewlyCreatedAccount(WalletAccountPtr newAccount); std::shared_ptr m_accounts; /// \todo make it a proxy filter on top of \c m_accounts diff --git a/libs/Wallet/qml/Status/Wallet/AssetsPanel.qml b/libs/Wallet/qml/Status/Wallet/AssetsPanel.qml index 6bfb083507..815b7d687a 100644 --- a/libs/Wallet/qml/Status/Wallet/AssetsPanel.qml +++ b/libs/Wallet/qml/Status/Wallet/AssetsPanel.qml @@ -109,32 +109,72 @@ Item { onClicked: newAccountLoader.active = true } - Loader { - id: newAccountLoader + ColumnLayout { + visible: !errorLayout.visible && newAccountLoader.active - Layout.fillWidth: true + Rectangle { + color: "blue" - visible: !errorLayout.visible && active - active: false + Layout.fillWidth: true + Layout.preferredHeight: 2 + Layout.margins: 5 + } - sourceComponent: Component { - NewWalletAccountView { - controller: root.controller.createNewWalletAccountController() + ComboBox { + id: accountTypeComboBox - onCancel: newAccountLoader.active = false - onAccountCreated: newAccountLoader.active = false + textRole: "title" + valueRole: "sourceComponent" - Connections { - target: controller - function onAccountCreatedStatus(createdSuccessfully) { - if(createdSuccessfully) - newAccountLoader.active = false - else - errorLayout.visible = true + Layout.fillWidth: true + + component NewAccountEntry: ItemDelegate { + required property string title + required property Component sourceComponent + + text: title + width: accountTypeComboBox.width + } + model: ObjectModel { + NewAccountEntry { + title: "New Account" + sourceComponent: NewWalletAccountView { + controller: root.controller.createNewWalletAccountController() + } + } + NewAccountEntry { + title: "Watch Only Account" + sourceComponent: AddWatchOnlyAccountView { + controller: root.controller.createNewWalletAccountController() } } } } + + Loader { + id: newAccountLoader + + Layout.fillWidth: true + + active: false + + sourceComponent: accountTypeComboBox.currentValue + } + + Connections { + target: newAccountLoader.item ? newAccountLoader.item.controller : null + function onAccountCreatedStatus(createdSuccessfully) { + if(createdSuccessfully) + newAccountLoader.active = false + else + errorLayout.visible = true + } + } + Connections { + target: newAccountLoader.item + function onCancel() { newAccountLoader.active = false } + function onAccountCreated() { newAccountLoader.active = false } + } } ColumnLayout { diff --git a/libs/Wallet/qml/Status/Wallet/NewAccount/AddWatchOnlyAccountView.qml b/libs/Wallet/qml/Status/Wallet/NewAccount/AddWatchOnlyAccountView.qml new file mode 100644 index 0000000000..c7e89938d0 --- /dev/null +++ b/libs/Wallet/qml/Status/Wallet/NewAccount/AddWatchOnlyAccountView.qml @@ -0,0 +1,82 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls + +import Status.Wallet + +import Status.Onboarding + +import Status.Containers + +Item { + id: root + + /// NewWalletAccountController + required property var controller + + signal accountCreated() + signal cancel() + + implicitWidth: mainLayout.implicitWidth + implicitHeight: mainLayout.implicitHeight + + ColumnLayout { + id: mainLayout + + anchors.fill: parent + + Label { + text: "Name" + Layout.margins: 5 + } + TempTextInput { + id: nameInput + + text: "Test Watch Account" + + Layout.fillWidth: true + Layout.margins: 5 + } + Label { + text: "Address" + Layout.margins: 5 + } + TempTextInput { + id: addressInput + + text: "0xdb5ac1a559b02e12f29fc0ec0e37be8e046def49" + + Layout.fillWidth: true + Layout.margins: 5 + } + + Label { + text: "Color" + Layout.margins: 5 + } + + TmpColorComboBox { + id: colorCombo + + Layout.fillWidth: true + Layout.margins: 5 + } + + RowLayout { + Button { + text: qsTr("Add Watch Only Account") + + enabled: nameInput.text.length > 5 && addressInput.text.length > 22 && addressInput.text.startsWith("0x") + + onClicked: controller.addWatchOnlyAccountAsync(addressInput.text, nameInput.text, + colorCombo.currentValue); + Layout.margins: 5 + } + Button { + text: qsTr("V") + onClicked: root.cancel() + Layout.margins: 5 + } + } + } +} diff --git a/libs/Wallet/qml/Status/Wallet/NewAccount/NewWalletAccountView.qml b/libs/Wallet/qml/Status/Wallet/NewAccount/NewWalletAccountView.qml index 3a1d0ae778..7cb6abbf0b 100644 --- a/libs/Wallet/qml/Status/Wallet/NewAccount/NewWalletAccountView.qml +++ b/libs/Wallet/qml/Status/Wallet/NewAccount/NewWalletAccountView.qml @@ -35,14 +35,6 @@ Item { anchors.fill: parent - Rectangle { - color: "blue" - - Layout.fillWidth: true - Layout.preferredHeight: 2 - Layout.margins: 5 - } - Label { text: "Name" @@ -77,40 +69,11 @@ Item { Layout.margins: 5 } - ComboBox { + TmpColorComboBox { id: colorCombo - model: ListModel { - ListElement { colorText: "Red"; colorValue: "red" } - ListElement { colorText: "Green"; colorValue: "green" } - ListElement { colorText: "Blue"; colorValue: "blue" } - ListElement { colorText: "Orange"; colorValue: "orange" } - ListElement { colorText: "Pink"; colorValue: "pink" } - ListElement { colorText: "Fuchsia"; colorValue: "fuchsia" } - } - textRole: "colorText" - valueRole: "colorValue" - - currentIndex: 0 - Layout.fillWidth: true Layout.margins: 5 - - delegate: ItemDelegate { - required property string colorText - required property color colorValue - required property int index - - width: colorCombo.width - contentItem: Text { - text: colorText - color: colorValue - font: colorCombo.font - elide: Text.ElideRight - verticalAlignment: Text.AlignVCenter - } - highlighted: colorCombo.highlightedIndex === index - } } Label { @@ -220,8 +183,8 @@ Item { Button { text: qsTr("Create") - enabled: nameInput.text.length > 5 && passwordInput.length > 5 - && pathInput.length > 0 + enabled: nameInput.text.length > 5 && passwordInput.text.length > 5 + && pathInput.text.length > 0 onClicked: root.controller.createAccountAsync(passwordInput.text, nameInput.text, colorCombo.currentValue, pathInput.text, diff --git a/libs/Wallet/qml/Status/Wallet/NewAccount/TmpColorComboBox.qml b/libs/Wallet/qml/Status/Wallet/NewAccount/TmpColorComboBox.qml new file mode 100644 index 0000000000..5ccb371512 --- /dev/null +++ b/libs/Wallet/qml/Status/Wallet/NewAccount/TmpColorComboBox.qml @@ -0,0 +1,36 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls + +ComboBox { + id: colorCombo + + model: ListModel { + ListElement { colorText: "Red"; colorValue: "red" } + ListElement { colorText: "Green"; colorValue: "green" } + ListElement { colorText: "Blue"; colorValue: "blue" } + ListElement { colorText: "Orange"; colorValue: "orange" } + ListElement { colorText: "Pink"; colorValue: "pink" } + ListElement { colorText: "Fuchsia"; colorValue: "fuchsia" } + } + textRole: "colorText" + valueRole: "colorValue" + + currentIndex: 0 + + delegate: ItemDelegate { + required property string colorText + required property color colorValue + required property int index + + width: colorCombo.width + contentItem: Text { + text: colorText + color: colorValue + font: colorCombo.font + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } + highlighted: colorCombo.highlightedIndex === index + } +} diff --git a/libs/Wallet/src/NewWalletAccountController.cpp b/libs/Wallet/src/NewWalletAccountController.cpp index 6467ae49df..638835b5e4 100644 --- a/libs/Wallet/src/NewWalletAccountController.cpp +++ b/libs/Wallet/src/NewWalletAccountController.cpp @@ -72,16 +72,26 @@ void NewWalletAccountController::createAccountAsync(const QString &password, con GoAccounts::generateAccountWithDerivedPath(StatusGo::HashedPassword(UtilsSG::hashPassword(password)), name, color, "", GoAccounts::DerivationPath(path), derivedFrom->data().derivedFrom.value()); - auto found = findMissingAccount(); - if(found) - m_accounts->push_back(found); - else - qWarning() << "Failed to create account. No new account found by this->findMissingAccount"; - emit accountCreatedStatus(found != nullptr); + addNewlyCreatedAccount(findMissingAccount()); } catch(const StatusGo::CallPrivateRpcError& e) { qWarning() << "StatusGoQt.generateAccountWithDerivedPath error: " << e.errorResponse().error.message.c_str(); + + emit accountCreatedStatus(false); + } +} + +void NewWalletAccountController::addWatchOnlyAccountAsync(const QString &address, const QString &name, const QColor &color) +{ + try { + GoAccounts::addAccountWatch(Accounts::EOAddress(address), name, color, u""_qs); + + addNewlyCreatedAccount(findMissingAccount()); + } + catch(const StatusGo::CallPrivateRpcError& e) { + qWarning() << "StatusGoQt.generateAccountWithDerivedPath error: " << e.errorResponse().error.message.c_str(); + emit accountCreatedStatus(false); } } @@ -149,6 +159,16 @@ NewWalletAccountController::filterMainAccounts(const AccountsModel &accounts) return out; } +void NewWalletAccountController::addNewlyCreatedAccount(WalletAccountPtr newAccount) +{ + if(newAccount) + m_accounts->push_back(newAccount); + else + qWarning() << "No new account to add. Creation failed"; + + emit accountCreatedStatus(newAccount != nullptr); +} + DerivedWalletAddress *NewWalletAccountController::selectedDerivedAddress() const { return m_selectedDerivedAddress.get();