From 4d2a845eda99a68e5367cee73c793baf81fe97a1 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Mon, 19 Oct 2020 15:00:43 -0400 Subject: [PATCH] feat: add browser permission modal --- .../Browser/BrowserConnectionModal.qml | 191 ++++++++++++++++++ ui/app/AppLayouts/Browser/BrowserLayout.qml | 101 +-------- .../AppLayouts/Browser/BrowserWalletMenu.qml | 3 + ui/app/AppLayouts/Browser/FaviconImage.qml | 14 ++ ui/nim-status-client.pro | 2 + ui/shared/AccountSelector.qml | 1 + 6 files changed, 217 insertions(+), 95 deletions(-) create mode 100644 ui/app/AppLayouts/Browser/BrowserConnectionModal.qml create mode 100644 ui/app/AppLayouts/Browser/FaviconImage.qml diff --git a/ui/app/AppLayouts/Browser/BrowserConnectionModal.qml b/ui/app/AppLayouts/Browser/BrowserConnectionModal.qml new file mode 100644 index 0000000000..a3a9af87d0 --- /dev/null +++ b/ui/app/AppLayouts/Browser/BrowserConnectionModal.qml @@ -0,0 +1,191 @@ +import QtQuick 2.13 +import QtQuick.Controls 2.13 +import QtQuick.Layouts 1.13 +import "../../../shared" +import "../../../imports" + +Popup { + property var currentTab + property var request: ({"hostname": "", "title": "", "permission": ""}) + property string currentAddress: "" + + id: root + modal: true + Overlay.modal: Rectangle { + color: "#60000000" + } + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + width: 360 + height: 480 + background: Rectangle { + color: Style.current.background + radius: 8 + } + padding: 0 + + function postMessage(isAllowed){ + request.isAllowed = isAllowed; + provider.web3Response(web3Provider.postMessage(JSON.stringify(request))); + } + + onClosed: { + root.destroy(); + } + + // TODO: design required + + ColumnLayout { + anchors.left: parent.left + anchors.leftMargin: Style.current.smallPadding + anchors.right: parent.right + anchors.rightMargin: Style.current.smallPadding + spacing: Style.current.bigPadding + anchors.top: parent.top + anchors.topMargin: 90 + + RowLayout { + property int imgSize: 40 + + id: logoHeader + spacing: Style.current.halfPadding + width: 176 + height: imgSize + Layout.alignment: Qt.AlignHCenter | Qt.AlignTop + + FaviconImage { + id: siteImg + width: logoHeader.imgSize + height: logoHeader.imgSize + } + + SVGImage { + id: dots1 + source: "../../img/dots-icon.svg" + width: 20 + height: 4 + } + + RoundedIcon { + source: "../../img/check.svg" + iconColor: Style.current.primary + color: Style.current.secondaryBackground + width: 24 + height: 24 + } + + SVGImage { + id: dots2 + source: "../../img/dots-icon.svg" + width: 20 + height: 4 + } + + RoundedIcon { + source: "../../img/walletIcon.svg" + iconHeight: 18 + iconWidth: 18 + iconColor: Style.current.primary // TODO use wallet color + color: Style.current.background + width: logoHeader.imgSize + height: logoHeader.imgSize + border.width: 1 + border.color: Style.current.border + } + } + + StyledText { + id: titleText + text: qsTr('"%1" woudl like to connect to').arg(request.title) + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter | Qt.AlignTop + wrapMode: Text.WordWrap + font.weight: Font.Bold + font.pixelSize: 17 + horizontalAlignment: Text.AlignHCenter + } + + AccountSelector { + id: accountSelector + label: "" + width: 190 + Layout.alignment: Qt.AlignHCenter | Qt.AlignTop + showAccountDetails: false + accounts: walletModel.accounts + selectedAccount: walletModel.currentAccount + currency: walletModel.defaultCurrency + reset: function() { + accounts = Qt.binding(function() { return walletModel.accounts }) + selectedAccount = Qt.binding(function() { return walletModel.currentAccount }) + } + onSelectedAccountChanged: { + if (!root.currentAddress) { + // We just set the account for the first time. Nothing to do here + root.currentAddress = selectedAccount.address + return + } + if (root.currentAddress === selectedAccount.address) { + return + } + + root.currentAddress = selectedAccount.address + web3Provider.dappsAddress = selectedAccount.address; + web3Provider.clearPermissions(); + if (selectField.menu.currentIndex !== -1) { + walletModel.setCurrentAccountByIndex(selectField.menu.currentIndex-1) + } + } + } + + + StyledText { + id: infoText + text: { + switch(request.permission){ + case Constants.permission_web3: return qsTr("Allowing authorizes this DApp to retrieve your wallet address and enable Web3"); + case Constants.permission_contactCode: return qsTr("Granting access authorizes this DApp to retrieve your chat key"); + default: return qsTr("Unknown permission: " + request.permission); + } + } + Layout.fillWidth: true + wrapMode: Text.WordWrap + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + font.pixelSize: 15 + horizontalAlignment: Text.AlignHCenter + color: Style.current.secondaryText + } + + Row { + width: childrenRect.width + spacing: Style.current.padding + Layout.alignment: Qt.AlignHCenter | Qt.AlignTop + + StyledButton { + btnColor: Utils.setColorAlpha(Style.current.danger, 0.1) + textColor: Style.current.danger + width: 155 + label: qsTr("Deny") + onClicked: { + postMessage(false); + root.close(); + } + } + + StyledButton { + btnColor: Utils.setColorAlpha(Style.current.success, 0.1) + textColor: Style.current.success + width: 155 + label: qsTr("Allow") + onClicked: { + postMessage(true); + root.close(); + } + } + } + } +} + +/*##^## +Designer { + D{i:0;formeditorColor:"#ffffff"} +} +##^##*/ diff --git a/ui/app/AppLayouts/Browser/BrowserLayout.qml b/ui/app/AppLayouts/Browser/BrowserLayout.qml index 577a2aa053..52084016d5 100644 --- a/ui/app/AppLayouts/Browser/BrowserLayout.qml +++ b/ui/app/AppLayouts/Browser/BrowserLayout.qml @@ -43,92 +43,10 @@ Rectangle { return url; } - property Component accessDialogComponent: ModalPopup { - id: accessDialog - - property var request: ({"hostname": "", "title": "", "permission": ""}) - property bool interactedWith: false - - function postMessage(isAllowed){ - interactedWith = true - request.isAllowed = isAllowed; - provider.web3Response(_web3Provider.postMessage(JSON.stringify(request))); - } - - onClosed: { - if(!interactedWith){ - postMessage(false); - } - accessDialog.destroy(); - } - - // TODO: design required - - StyledText { - id: siteName - text: request.title - anchors.top: parent.top - anchors.topMargin: Style.current.padding - width: parent.width - wrapMode: Text.WordWrap - } - - StyledText { - id: hostName - text: request.hostname - anchors.top: siteName.bottom - anchors.topMargin: Style.current.padding - width: parent.width - wrapMode: Text.WordWrap - } - - StyledText { - id: permission - text: qsTr("Permission requested: %1").arg(request.permission) - anchors.top: hostName.bottom - anchors.topMargin: Style.current.padding - width: parent.width - wrapMode: Text.WordWrap - } - - StyledText { - id: description - anchors.top: permission.bottom - anchors.topMargin: Style.current.padding - width: parent.width - wrapMode: Text.WordWrap - text: { - switch(request.permission){ - case Constants.permission_web3: return qsTr("Allowing authorizes this DApp to retrieve your wallet address and enable Web3"); - case Constants.permission_contactCode: return qsTr("Granting access authorizes this DApp to retrieve your chat key"); - default: return qsTr("Unknown permission: " + request.permission); - } - } - } - - StyledButton { - anchors.bottom: parent.bottom - anchors.bottomMargin: Style.current.padding - anchors.left: parent.left - anchors.leftMargin: Style.current.padding - label: qsTr("Allow") - onClicked: { - postMessage(true); - accessDialog.close(); - } - } - - StyledButton { - anchors.bottom: parent.bottom - anchors.bottomMargin: Style.current.padding - anchors.right: parent.right - anchors.rightMargin: Style.current.padding - label: qsTr("Deny") - onClicked: { - postMessage(false); - accessDialog.close(); - } - } + property Component accessDialogComponent: BrowserConnectionModal { + currentTab: tabs.getTab(tabs.currentIndex) && tabs.getTab(tabs.currentIndex).item + x: browserWindow.width - width - Style.current.halfPadding + y: browserHeader.y + browserHeader.height + Style.current.halfPadding } // TODO we'll need a new dialog at one point because this one is not using the same call, but it's good for now @@ -528,19 +446,12 @@ Rectangle { anchors.bottom: parent.bottom } - Image { + FaviconImage { id: faviconImage + currentTab: tabs.getTab(styleData.index) && tabs.getTab(styleData.index).item anchors.verticalCenter: parent.verticalCenter; anchors.left: parent.left anchors.leftMargin: Style.current.halfPadding - width: 24 - height: 24 - sourceSize: Qt.size(width, height) - // TODO find a better default favicon - source: { - const thisTab = tabs.getTab(styleData.index) && tabs.getTab(styleData.index).item - return thisTab && !!thisTab.icon.toString() ? thisTab.icon : "../../img/globe.svg" - } } StyledText { diff --git a/ui/app/AppLayouts/Browser/BrowserWalletMenu.qml b/ui/app/AppLayouts/Browser/BrowserWalletMenu.qml index e64f3e3910..3e57fcfdc5 100644 --- a/ui/app/AppLayouts/Browser/BrowserWalletMenu.qml +++ b/ui/app/AppLayouts/Browser/BrowserWalletMenu.qml @@ -122,6 +122,9 @@ Popup { accountSelectorRow.currentAddress = selectedAccount.address web3Provider.dappsAddress = selectedAccount.address; web3Provider.clearPermissions(); + if (selectField.menu.currentIndex !== -1) { + walletModel.setCurrentAccountByIndex(selectField.menu.currentIndex-1) + } for (let i = 0; i < tabs.count; ++i){ tabs.getTab(i).item.reload(); } diff --git a/ui/app/AppLayouts/Browser/FaviconImage.qml b/ui/app/AppLayouts/Browser/FaviconImage.qml new file mode 100644 index 0000000000..d1bfa0195c --- /dev/null +++ b/ui/app/AppLayouts/Browser/FaviconImage.qml @@ -0,0 +1,14 @@ +import QtQuick 2.13 +import "../../../shared" +import "../../../imports" + +Image { + property var currentTab + + id: faviconImage + width: 24 + height: 24 + sourceSize: Qt.size(width, height) + // TODO find a better default favicon + source: faviconImage.currentTab && !!faviconImage.currentTab.icon.toString() ? faviconImage.currentTab.icon : "../../img/globe.svg" +} diff --git a/ui/nim-status-client.pro b/ui/nim-status-client.pro index c52123581e..9b41621169 100644 --- a/ui/nim-status-client.pro +++ b/ui/nim-status-client.pro @@ -121,9 +121,11 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target DISTFILES += \ + app/AppLayouts/Browser/BrowserConnectionModal.qml \ app/AppLayouts/Browser/BrowserHeader.qml \ app/AppLayouts/Browser/BrowserTabs.qml \ app/AppLayouts/Browser/BrowserWalletMenu.qml \ + app/AppLayouts/Browser/FaviconImage.qml \ app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandButton.qml \ app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandModal.qml \ app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandsPopup.qml \ diff --git a/ui/shared/AccountSelector.qml b/ui/shared/AccountSelector.qml index 5baa73c1f1..8a929384d6 100644 --- a/ui/shared/AccountSelector.qml +++ b/ui/shared/AccountSelector.qml @@ -12,6 +12,7 @@ Item { property var accounts property var selectedAccount property string currency: "usd" + property alias selectField: select height: select.height + (selectedAccountDetails.visible ? selectedAccountDetails.height : 0) // set to asset symbol to display asset's balance top right