diff --git a/src/app/modules/main/wallet_section/add_account/io_interface.nim b/src/app/modules/main/wallet_section/add_account/io_interface.nim index 56a5d7798c..bf7b2d52b2 100644 --- a/src/app/modules/main/wallet_section/add_account/io_interface.nim +++ b/src/app/modules/main/wallet_section/add_account/io_interface.nim @@ -10,7 +10,7 @@ type method delete*(self: AccessInterface) {.base.} = raise newException(ValueError, "No implementation available") -method load*(self: AccessInterface) {.base.} = +method load*(self: AccessInterface, addingWatchOnlyAccount: bool) {.base.} = raise newException(ValueError, "No implementation available") method closeAddAccountPopup*(self: AccessInterface, switchToAccWithAddress: string = "") {.base.} = diff --git a/src/app/modules/main/wallet_section/add_account/module.nim b/src/app/modules/main/wallet_section/add_account/module.nim index 57d4ec95cb..62572c9738 100644 --- a/src/app/modules/main/wallet_section/add_account/module.nim +++ b/src/app/modules/main/wallet_section/add_account/module.nim @@ -72,7 +72,7 @@ method delete*[T](self: Module[T]) = self.viewVariant.delete self.controller.delete -method load*[T](self: Module[T]) = +method load*[T](self: Module[T], addingWatchOnlyAccount: bool) = self.controller.init() self.view.setCurrentState(newMainState(nil)) @@ -91,12 +91,15 @@ method load*[T](self: Module[T]) = items.add(item) item = newKeyPairItem(keyUid = Label_OptionAddWatchOnlyAcc) item.setName(Label_NewWatchOnlyAccount) - item.setIcon("objects") + item.setIcon("show") items.add(item) self.view.setDisablePopup(false) self.view.setOriginModelItems(items) - self.changeSelectedOrigin(items[0].getKeyUid()) + if addingWatchOnlyAccount: + self.changeSelectedOrigin(Label_OptionAddWatchOnlyAcc) + else: + self.changeSelectedOrigin(items[0].getKeyUid()) self.delegate.onAddAccountModuleLoaded() proc tryKeycardSync[T](self: Module[T]) = diff --git a/src/app/modules/main/wallet_section/io_interface.nim b/src/app/modules/main/wallet_section/io_interface.nim index 7b71ee7845..f31ef8faf0 100644 --- a/src/app/modules/main/wallet_section/io_interface.nim +++ b/src/app/modules/main/wallet_section/io_interface.nim @@ -58,7 +58,7 @@ method savedAddressesModuleDidLoad*(self: AccessInterface) {.base.} = method buySellCryptoModuleDidLoad*(self: AccessInterface) {.base.} = raise newException(ValueError, "No implementation available") -method runAddAccountPopup*(self: AccessInterface) {.base.} = +method runAddAccountPopup*(self: AccessInterface, addingWatchOnlyAccount: bool) {.base.} = raise newException(ValueError, "No implementation available") method getAddAccountModule*(self: AccessInterface): QVariant {.base.} = diff --git a/src/app/modules/main/wallet_section/module.nim b/src/app/modules/main/wallet_section/module.nim index 68fea79ecf..f358594a2d 100644 --- a/src/app/modules/main/wallet_section/module.nim +++ b/src/app/modules/main/wallet_section/module.nim @@ -214,11 +214,11 @@ method destroyAddAccountPopup*(self: Module, switchToAccWithAddress: string = "" self.addAccountModule.delete self.addAccountModule = nil -method runAddAccountPopup*(self: Module) = +method runAddAccountPopup*(self: Module, addingWatchOnlyAccount: bool) = self.destroyAddAccountPopup() self.addAccountModule = add_account_module.newModule(self, self.events, self.keycardService, self.accountsService, self.walletAccountService) - self.addAccountModule.load() + self.addAccountModule.load(addingWatchOnlyAccount) method getAddAccountModule*(self: Module): QVariant = if self.addAccountModule.isNil: diff --git a/src/app/modules/main/wallet_section/view.nim b/src/app/modules/main/wallet_section/view.nim index cb3ed139a2..531aa56c45 100644 --- a/src/app/modules/main/wallet_section/view.nim +++ b/src/app/modules/main/wallet_section/view.nim @@ -98,8 +98,8 @@ QtObject: self.isMnemonicBackedUp = mnemonicBackedUp self.currentCurrencyChanged() - proc runAddAccountPopup*(self: View) {.slot.} = - self.delegate.runAddAccountPopup() + proc runAddAccountPopup*(self: View, addingWatchOnlyAccount: bool) {.slot.} = + self.delegate.runAddAccountPopup(addingWatchOnlyAccount) proc getAddAccountModule(self: View): QVariant {.slot.} = return self.delegate.getAddAccountModule() diff --git a/ui/StatusQ/src/StatusQ/Popups/StatusAction.qml b/ui/StatusQ/src/StatusQ/Popups/StatusAction.qml index f0336b94fa..b1c099fd0d 100644 --- a/ui/StatusQ/src/StatusQ/Popups/StatusAction.qml +++ b/ui/StatusQ/src/StatusQ/Popups/StatusAction.qml @@ -9,7 +9,8 @@ Action { enum Type { Normal, - Danger + Danger, + Success } property int type: StatusAction.Type.Normal @@ -37,6 +38,8 @@ Action { return Theme.palette.baseColor1 if (type === StatusAction.Type.Danger) return Theme.palette.dangerColor1 + if (type === StatusAction.Type.Success) + return Theme.palette.successColor1 return Theme.palette.primaryColor1 } } diff --git a/ui/StatusQ/src/StatusQ/Popups/StatusMenuItem.qml b/ui/StatusQ/src/StatusQ/Popups/StatusMenuItem.qml index 85de9a3c51..94bc6f7626 100644 --- a/ui/StatusQ/src/StatusQ/Popups/StatusMenuItem.qml +++ b/ui/StatusQ/src/StatusQ/Popups/StatusMenuItem.qml @@ -25,6 +25,7 @@ MenuItem { readonly property bool hasAction: !!root.action readonly property bool isStatusAction: d.hasAction && (root.action instanceof StatusAction) readonly property bool isStatusDangerAction: d.isStatusAction && root.action.type === StatusAction.Type.Danger + readonly property bool isStatusSuccessAction: d.isStatusAction && root.action.type === StatusAction.Type.Success readonly property StatusAssetSettings originalAssetSettings: d.isStatusSubMenu && root.subMenu.assetSettings ? root.subMenu.assetSettings @@ -130,7 +131,9 @@ MenuItem { text: root.text color: !root.enabled ? Theme.palette.baseColor1 - : d.isStatusDangerAction ? Theme.palette.dangerColor1 : Theme.palette.directColor1 + : d.isStatusDangerAction ? Theme.palette.dangerColor1 + : d.isStatusSuccessAction? + Theme.palette.successColor1 : Theme.palette.directColor1 font.pixelSize: d.fontSettings ? d.fontSettings.pixelSize : d.defaultFontSettings.pixelSize font.bold: d.fontSettings ? d.fontSettings.bold : d.defaultFontSettings.bold @@ -155,6 +158,8 @@ MenuItem { return "transparent" if (d.isStatusDangerAction) return Theme.palette.dangerColor3; + if (d.isStatusSuccessAction) + return Theme.palette.successColor3; return Theme.palette.statusMenu.hoverBackgroundColor; } } diff --git a/ui/app/AppLayouts/Wallet/stores/RootStore.qml b/ui/app/AppLayouts/Wallet/stores/RootStore.qml index 6cefda7d43..78f8bc037d 100644 --- a/ui/app/AppLayouts/Wallet/stores/RootStore.qml +++ b/ui/app/AppLayouts/Wallet/stores/RootStore.qml @@ -190,6 +190,10 @@ QtObject { } function runAddAccountPopup() { - walletSection.runAddAccountPopup() + walletSection.runAddAccountPopup(false) + } + + function runAddWatchOnlyAccountPopup() { + walletSection.runAddAccountPopup(true) } } diff --git a/ui/app/AppLayouts/Wallet/views/AccountContextMenu.qml b/ui/app/AppLayouts/Wallet/views/AccountContextMenu.qml new file mode 100644 index 0000000000..1e89972b56 --- /dev/null +++ b/ui/app/AppLayouts/Wallet/views/AccountContextMenu.qml @@ -0,0 +1,104 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +import StatusQ.Popups 0.1 +import StatusQ.Core.Theme 0.1 + +import utils 1.0 + +import "../stores" + +StatusMenu { + id: root + + property var account + + signal editAccountClicked() + signal deleteAccountClicked() + signal addNewAccountClicked() + signal addWatchOnlyAccountClicked() + + width: 204 + + onAboutToShow: { + d.resetCopyAddressAction() + } + + QtObject { + id: d + + function resetCopyAddressAction() { + copyAddressAction.action.text = qsTr("Copy address") + copyAddressAction.action.type = StatusAction.Type.Normal + copyAddressAction.action.icon.name = "copy" + copyAddressAction.action.icon.color = Theme.palette.primaryColor1 + } + } + + StatusMenuItem { + id: copyAddressAction + enabled: !!root.account + text: qsTr("Copy address") + action: StatusAction {} + MouseArea { + anchors.fill: parent + hoverEnabled: true + cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor + onClicked: { + RootStore.copyToClipboard(root.account.address?? "") + copyAddressAction.action.text = qsTr("Address copied") + copyAddressAction.action.type = StatusAction.Type.Success + copyAddressAction.action.icon.name = "tiny/checkmark" + copyAddressAction.action.icon.color = Theme.palette.successColor1 + + Backpressure.debounce(root, 1500, function () { + d.resetCopyAddressAction() + root.dismiss() + })() + } + } + } + + StatusMenuSeparator { + visible: !!root.account + } + + StatusAction { + enabled: !!root.account + text: qsTr("Edit") + icon.name: "pencil-outline" + onTriggered: { + root.editAccountClicked() + } + } + + StatusAction { + enabled: !!root.account && root.account.walletType !== "" + text: qsTr("Delete") + icon.name: "info" + type: StatusAction.Type.Danger + onTriggered: { + root.deleteAccountClicked() + } + } + + StatusMenuSeparator { + visible: !!root.account + } + + StatusAction { + text: qsTr("Add new account") + icon.name: "add" + onTriggered: { + root.addNewAccountClicked() + } + } + + StatusAction { + text: qsTr("Add watch-only account") + icon.name: "show" + onTriggered: { + root.addWatchOnlyAccountClicked() + } + } +} diff --git a/ui/app/AppLayouts/Wallet/views/LeftTabView.qml b/ui/app/AppLayouts/Wallet/views/LeftTabView.qml index b952b6ccc4..3336065bc2 100644 --- a/ui/app/AppLayouts/Wallet/views/LeftTabView.qml +++ b/ui/app/AppLayouts/Wallet/views/LeftTabView.qml @@ -51,6 +51,19 @@ Rectangle { } } + Loader { + id: walletBckgAccountContextMenu + sourceComponent: AccountContextMenu { + onAddNewAccountClicked: { + RootStore.runAddAccountPopup() + } + + onAddWatchOnlyAccountClicked: { + RootStore.runAddWatchOnlyAccountPopup() + } + } + } + Connections { target: walletSection @@ -62,6 +75,18 @@ Rectangle { } } + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.RightButton + + onClicked: { + if (mouse.button === Qt.RightButton) { + walletBckgAccountContextMenu.active = true + walletBckgAccountContextMenu.item.popup(mouse.x, mouse.y) + } + } + } + ColumnLayout { anchors.fill: parent spacing: Style.current.padding @@ -73,6 +98,14 @@ Rectangle { Layout.rightMargin: Style.current.padding Layout.topMargin: Style.current.padding + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.RightButton + onClicked: { + mouse.accepted = true + } + } + StatusBaseText { id: walletTitleText text: qsTr("Wallet") @@ -100,6 +133,14 @@ Rectangle { Layout.fillWidth: true Layout.leftMargin: Style.current.padding + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.RightButton + onClicked: { + mouse.accepted = true + } + } + StyledTextEditWithLoadingState { id: walletAmountValue objectName: "walletLeftListAmountValue" @@ -177,6 +218,11 @@ Rectangle { errorIcon.tooltip.maxWidth: 300 errorIcon.tooltip.text: networkConnectionStore.accountBalanceNotAvailableText onClicked: { + if (mouse.button === Qt.RightButton) { + accountContextMenu.active = true + accountContextMenu.item.popup(mouse.x, mouse.y) + return + } changeSelectedAccount(index) showSavedAddresses = false } @@ -195,6 +241,27 @@ Rectangle { height: 15 } ] + + Loader { + id: accountContextMenu + sourceComponent: AccountContextMenu { + account: model + + onEditAccountClicked: { + } + + onDeleteAccountClicked: { + } + + onAddNewAccountClicked: { + RootStore.runAddAccountPopup() + } + + onAddWatchOnlyAccountClicked: { + RootStore.runAddWatchOnlyAccountPopup() + } + } + } } readonly property bool footerOverlayed: contentHeight > availableHeight @@ -254,6 +321,15 @@ Rectangle { onClicked: { showSavedAddresses = true } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.RightButton + propagateComposedEvents: true + onClicked: { + mouse.accepted = true + } + } } }