diff --git a/storybook/pages/DAppRequestModalPage.qml b/storybook/pages/DAppRequestModalPage.qml
deleted file mode 100644
index d32bb6259e..0000000000
--- a/storybook/pages/DAppRequestModalPage.qml
+++ /dev/null
@@ -1,196 +0,0 @@
-import QtQuick 2.15
-import QtQuick.Controls 2.15
-import QtQuick.Layouts 1.15
-import QtQml 2.15
-import Qt.labs.settings 1.0
-import QtTest 1.15
-
-import StatusQ.Core 0.1
-import StatusQ.Core.Utils 0.1
-import StatusQ.Controls 0.1
-import StatusQ.Components 0.1
-import StatusQ.Core.Theme 0.1
-import StatusQ.Popups.Dialog 0.1
-
-import Models 1.0
-import Storybook 1.0
-
-import shared.popups.walletconnect 1.0
-
-import SortFilterProxyModel 0.2
-
-import AppLayouts.Wallet.panels 1.0
-import AppLayouts.Wallet.services.dapps.types 1.0
-
-import utils 1.0
-import shared.stores 1.0
-
-Item {
- id: root
-
- function openModal() {
- modal.open()
- }
-
- // qml Splitter
- SplitView {
- anchors.fill: parent
-
- ColumnLayout {
- SplitView.fillWidth: true
-
- Component.onCompleted: root.openModal()
-
- DAppRequestModal {
- id: modal
-
- anchors.centerIn: parent
-
- spacing: 8
-
- dappName: settings.dappName
- dappUrl: settings.dappUrl
- dappIcon: settings.dappIcon
- payloadData: d.currentPayload ? d.currentPayload.payloadData : null
- method: d.currentPayload ? d.currentPayload.method : ""
- maxFeesText: d.currentPayload ? d.currentPayload.maxFeesText : ""
- maxFeesEthText: d.currentPayload ? d.currentPayload.maxFeesEthText : ""
- enoughFunds: settings.enoughFunds
- estimatedTimeText: d.currentPayload ? d.currentPayload.estimatedTimeText : ""
-
- account: d.selectedAccount
- network: d.selectedNetwork
-
- onSign: {
- console.log("Sign button clicked")
- }
- onReject: {
- console.log("Reject button clicked")
- }
- }
-
- StatusButton {
- id: openButton
-
- Layout.alignment: Qt.AlignHCenter
- Layout.margins: 20
-
- text: "Open DAppRequestModal"
-
- onClicked: root.openModal()
- }
-
- ColumnLayout {}
- }
-
- ColumnLayout {
- id: optionsSpace
-
- TextField {
- id: dappNameTextField
-
- text: settings.dappName
- onTextChanged: settings.dappName = text
- }
- TextField {
- id: dappUrlTextField
-
- text: settings.dappUrl
- onTextChanged: settings.dappUrl = text
- }
- TextField {
- id: dappIconTextField
-
- text: settings.dappIcon
- onTextChanged: settings.dappIcon = text
- }
- TextField {
- id: accountDisplayTextField
-
- text: settings.accountDisplay
- onTextChanged: settings.accountDisplay = text
- }
- StatusComboBox {
- id: methodsComboBox
-
- model: d.methodsModel
- control.textRole: "method"
- currentIndex: settings.payloadMethod
- onCurrentIndexChanged: {
- d.currentPayload = null
- settings.payloadMethod = currentIndex
- d.currentPayload = d.payloadOptions[currentIndex]
- }
- }
- StatusCheckBox {
- id: enoughFundsCheckBox
-
- text: "Enough funds"
- checked: settings.enoughFunds
- onCheckedChanged: settings.enoughFunds = checked
- }
-
- Item { Layout.fillHeight: true }
- }
- }
-
- Settings {
- id: settings
-
- property string dappName: "OpenSea"
- property string dappUrl: "opensea.io"
- property string dappIcon: "https://opensea.io/static/images/logos/opensea-logo.svg"
- property string accountDisplay: "helloworld"
- property int payloadMethod: 0
- property bool enoughFunds: true
- }
-
- QtObject {
- id: d
-
- Component.onCompleted: methodsModel.append(payloadOptions)
-
- readonly property var accountsModel: WalletAccountsModel{}
- readonly property var selectedAccount: accountsModel.data[0]
-
- readonly property var selectedNetwork: NetworksModel.flatNetworks.get(0)
-
- readonly property ListModel methodsModel: ListModel {}
- property var currentPayload: payloadOptions[settings.payloadMethod]
- property string maxFeesText: ""
- property string estimatedTimeText: ""
-
- readonly property var payloadOptions: [
- {
- payloadData: {"message":"This is a message to sign.\nSigning this will prove ownership of the account."},
- method: SessionRequest.methods.personalSign.name,
- maxFeesText: "",
- maxFeesEthText: "",
- estimatedTimeText: ""
- },
- {
- payloadData: {"message": "{\"types\":{\"EIP712Domain\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"chainId\",\"type\":\"uint256\"},{\"name\":\"verifyingContract\",\"type\":\"address\"}],\"Person\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"wallet\",\"type\":\"address\"}],\"Mail\":[{\"name\":\"from\",\"type\":\"Person\"},{\"name\":\"to\",\"type\":\"Person\"},{\"name\":\"contents\",\"type\":\"string\"}]},\"primaryType\":\"Mail\",\"domain\":{\"name\":\"Ether Mail\",\"version\":\"1\",\"chainId\":1,\"verifyingContract\":\"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC\"},\"message\":{\"from\":{\"name\":\"Cow\",\"wallet\":\"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826\"},\"to\":{\"name\":\"Bob\",\"wallet\":\"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB\"},\"contents\":\"Hello, Bob!\"}}"},
- method: SessionRequest.methods.signTypedData_v4.name,
- maxFeesText: "",
- maxFeesEthText: "",
- estimatedTimeText: ""
- },
- {
- payloadData: {"tx":{"data":"0x","from":"0xE2d622C817878dA5143bBE06866ca8E35273Ba8a","gasLimit":"0x5208","gasPrice":"0x048ddbc5","nonce":"0x2a","to":"0xE2d622C817878dA5143bBE06866ca8E35273Ba8a","value":"0x00"}},
- method: SessionRequest.methods.signTransaction.name,
- maxFeesText: "1.82 EUR",
- maxFeesEthText: "0.0001 ETH",
- estimatedTimeText: "3-5 mins"
- },
- {
- payloadData: {"tx":{"data":"0x","from":"0xE2d622C817878dA5143bBE06866ca8E35273Ba8a","gasLimit":"0x5208","gasPrice":"0x048ddbc5","nonce":"0x2a","to":"0xE2d622C817878dA5143bBE06866ca8E35273Ba8a","value":"0x00"}},
- method: SessionRequest.methods.sendTransaction.name,
- maxFeesText: "0.92 EUR",
- maxFeesEthText: "0.00005 ETH",
- estimatedTimeText: "1-2 mins"
- }
- ]
- }
-}
-
-// category: Wallet
diff --git a/storybook/pages/DAppSignRequestModalPage.qml b/storybook/pages/DAppSignRequestModalPage.qml
new file mode 100644
index 0000000000..edf7bb3db4
--- /dev/null
+++ b/storybook/pages/DAppSignRequestModalPage.qml
@@ -0,0 +1,137 @@
+// category: Popups
+
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+import shared.popups.walletconnect 1.0
+import utils 1.0
+import Storybook 1.0
+
+SplitView {
+ id: root
+
+ PopupBackground {
+ SplitView.fillWidth: true
+ SplitView.fillHeight: true
+ Button {
+ anchors.centerIn: parent
+ text: "Open"
+ onClicked: dappSignRequestModal.visible = true
+ }
+
+ DAppSignRequestModal {
+ id: dappSignRequestModal
+
+ loginType: loginType.currentValue
+ visible: true
+ modal: false
+ closePolicy: Popup.NoAutoClose
+ dappUrl: "https://example.com"
+ dappIcon: "https://picsum.photos/200/200"
+ dappName: "OpenSea"
+ accountColor: "blue"
+ accountName: "Account Name"
+ accountAddress: "0xE2d622C817878dA5143bBE06866ca8E35273Ba8"
+ networkName: "Ethereum"
+ networkIconPath: "https://picsum.photos/200/200"
+
+ currentCurrency: "EUR"
+ fiatFees: fiatFees.text
+ cryptoFees: "0.001"
+ estimatedTime: "3-5 minutes"
+ feesLoading: feesLoading.checked
+ hasFees: hasFees.checked
+ enoughFundsForTransaction: enoughFeesForTransaction.checked
+ enoughFundsForFees: enoughFeesForGas.checked
+
+ // sun emoji
+ accountEmoji: "\u2600"
+ requestPayload: controls.contentToSign[contentToSignComboBox.currentIndex]
+ signingTransaction: signingTransaction.checked
+
+ onAccepted: print ("Accepted")
+ onRejected: print ("Rejected")
+ }
+ }
+ Pane {
+ id: controls
+ SplitView.preferredWidth: 300
+ SplitView.fillHeight: true
+
+ readonly property var contentToSign: ['{
+ "id": 1714038548266495,
+ "params": {
+ "chainld": "eip155:11155111",
+ "request": {
+ "expiryTimestamp": 1714038848,
+ "method": "eth_signTransaction",
+ "params": [{
+ "data": "0x",
+ "from": "0xE2d622C817878dA5143bBE06866ca8E35273Ba8",
+ "gasLimit": "0x5208",
+ "gasPrice": "0xa677ef31",
+ "nonce": "0x27",
+ "to": "0xE2d622C817878dA5143bBE06866ca8E35273Ba8a",
+ "value": "0x00"
+ }]
+ }
+ },
+ "topic": "a0f85b23a1f3a540d85760a523963165fb92169d57320c",
+ "verifyContext": {
+ "verified": {
+ "isScam": false,
+ "origin": "https://react-app.walletconnect.com/",
+ "validation": "VALID",
+ "verifyUrl": "https://verify.walletconnect.com/"
+ }
+ }
+ }',
+ '"tx":{"data":"0x","from":"0xE2d622C817878dA5143bBE06866ca8E35273Ba8a","gasLimit":"0x5208","gasPrice":"0x048ddbc5","nonce":"0x2a","to":"0xE2d622C817878dA5143bBE06866ca8E35273Ba8a","value":"0x00"}',
+ ""
+ ]
+
+ ColumnLayout {
+ TextField {
+ id: fiatFees
+ text: "1.54"
+ }
+ ComboBox {
+ id: loginType
+ model: [{name: "Password", value: Constants.LoginType.Password}, {name: "Biometrics", value: Constants.LoginType.Biometrics}, {name: "Keycard", value: Constants.LoginType.Keycard}]
+ textRole: "name"
+ valueRole: "value"
+ currentIndex: 0
+ }
+ ComboBox {
+ id: contentToSignComboBox
+ model: ["Long content to sign", "Short content to sign", "Empty content to sign"]
+ currentIndex: 0
+ }
+ CheckBox {
+ id: enoughFeesForTransaction
+ text: "Enough fees for transaction"
+ checked: true
+ }
+ CheckBox {
+ id: enoughFeesForGas
+ text: "Enough fees for gas"
+ checked: true
+ }
+ CheckBox {
+ id: feesLoading
+ text: "Fees loading"
+ checked: false
+ }
+ CheckBox {
+ id: hasFees
+ text: "Has fees"
+ checked: true
+ }
+ CheckBox {
+ id: signingTransaction
+ text: "Signing transaction"
+ checked: false
+ }
+ }
+ }
+}
diff --git a/storybook/pages/DAppsWorkflowPage.qml b/storybook/pages/DAppsWorkflowPage.qml
index f278db1b70..73212670f5 100644
--- a/storybook/pages/DAppsWorkflowPage.qml
+++ b/storybook/pages/DAppsWorkflowPage.qml
@@ -61,6 +61,8 @@ Item {
spacing: 8
wcService: walletConnectService
+ loginType: Constants.LoginType.Biometrics
+ selectedAccountAddress: ""
}
}
ColumnLayout {}
@@ -373,7 +375,6 @@ Item {
}
walletRootStore: QObject {
- property string selectedAddress: ""
property var filteredFlatModel: SortFilterProxyModel {
sourceModel: NetworksModel.flatNetworks
filters: ValueFilter { roleName: "isTest"; value: settings.testNetworks; }
diff --git a/storybook/qmlTests/tests/tst_DAppsWorkflow.qml b/storybook/qmlTests/tests/tst_DAppsWorkflow.qml
index d7daed93fc..7c764613af 100644
--- a/storybook/qmlTests/tests/tst_DAppsWorkflow.qml
+++ b/storybook/qmlTests/tests/tst_DAppsWorkflow.qml
@@ -121,7 +121,6 @@ Item {
id: walletStoreComponent
QtObject {
- property string selectedAddress: ""
readonly property ListModel filteredFlatModel: ListModel {
ListElement { chainId: 1 }
ListElement {
@@ -503,6 +502,7 @@ Item {
Component {
id: componentUnderTest
DAppsWorkflow {
+ loginType: Constants.LoginType.Password
}
}
@@ -605,9 +605,9 @@ Item {
verify(popup.visible)
compare(popup.dappName, td.session.peer.metadata.name)
- compare(popup.account.name, td.account.name)
- compare(popup.account.address, td.account.address)
- compare(popup.network.chainId, td.network.chainId)
+ compare(popup.accountName, td.account.name)
+ compare(popup.accountAddress, td.account.address)
+ compare(popup.networkName, td.network.chainName)
popup.close()
waitForRendering(controlUnderTest)
diff --git a/storybook/qmlTests/tests/tst_SwapApproveCapModal.qml b/storybook/qmlTests/tests/tst_SwapApproveCapModal.qml
index 4b7b308580..cb7b63f39e 100644
--- a/storybook/qmlTests/tests/tst_SwapApproveCapModal.qml
+++ b/storybook/qmlTests/tests/tst_SwapApproveCapModal.qml
@@ -93,16 +93,16 @@ Item {
.arg(controlUnderTest.formatBigNumber(controlUnderTest.fromTokenAmount)).arg(controlUnderTest.fromTokenSymbol)
.arg(controlUnderTest.accountName).arg(controlUnderTest.serviceProviderURL).arg(controlUnderTest.networkName))
- const fromImageHidden = findChild(controlUnderTest.contentItem, "fromImage")
+ const fromImageHidden = findChild(controlUnderTest.contentItem, "fromImageIdenticon")
compare(fromImageHidden.visible, false)
const fromImage = findChild(controlUnderTest.contentItem, "fromImageIdenticon")
verify(!!fromImage)
compare(fromImage.asset.emoji, controlUnderTest.accountEmoji)
compare(fromImage.asset.color, controlUnderTest.accountColor)
- const toImage = findChild(controlUnderTest.contentItem, "toImage")
+ const toImage = findChild(controlUnderTest.contentItem, "toImageIdenticon")
verify(!!toImage)
- compare(toImage.image.source, Constants.tokenIcon(controlUnderTest.fromTokenSymbol))
+ compare(toImage.asset.name, Constants.tokenIcon(controlUnderTest.fromTokenSymbol))
// spending cap box
const spendingCapBox = findChild(controlUnderTest.contentItem, "spendingCapBox")
diff --git a/storybook/qmlTests/tests/tst_SwapSignModal.qml b/storybook/qmlTests/tests/tst_SwapSignModal.qml
index ab37cae83c..beaa50e282 100644
--- a/storybook/qmlTests/tests/tst_SwapSignModal.qml
+++ b/storybook/qmlTests/tests/tst_SwapSignModal.qml
@@ -95,12 +95,12 @@ Item {
const headerText = findChild(controlUnderTest.contentItem, "headerText")
verify(!!headerText)
compare(headerText.text, qsTr("Swap 1000.123456789 SNT to 1.42 ETH in %1 on %2").arg(controlUnderTest.accountName).arg(controlUnderTest.networkName))
- const fromImage = findChild(controlUnderTest.contentItem, "fromImage")
+ const fromImage = findChild(controlUnderTest.contentItem, "fromImageIdenticon")
verify(!!fromImage)
- compare(fromImage.image.source, Constants.tokenIcon(controlUnderTest.fromTokenSymbol))
- const toImage = findChild(controlUnderTest.contentItem, "toImage")
+ compare(fromImage.asset.name, Constants.tokenIcon(controlUnderTest.fromTokenSymbol))
+ const toImage = findChild(controlUnderTest.contentItem, "toImageIdenticon")
verify(!!toImage)
- compare(toImage.image.source, Constants.tokenIcon(controlUnderTest.toTokenSymbol))
+ compare(toImage.asset.name, Constants.tokenIcon(controlUnderTest.toTokenSymbol))
// pay box
const payBox = findChild(controlUnderTest.contentItem, "payBox")
diff --git a/ui/StatusQ/src/assets.qrc b/ui/StatusQ/src/assets.qrc
index af5b276c17..e6c3245fbf 100644
--- a/ui/StatusQ/src/assets.qrc
+++ b/ui/StatusQ/src/assets.qrc
@@ -165,6 +165,7 @@
assets/img/icons/checkmark.svg
assets/img/icons/chevron-down.svg
assets/img/icons/chevron-up.svg
+ assets/img/icons/collapse.svg
assets/img/icons/clear.svg
assets/img/icons/close-circle.svg
assets/img/icons/close.svg
@@ -187,6 +188,7 @@
assets/img/icons/emojis.svg
assets/img/icons/ETH.png
assets/img/icons/exchange.svg
+ assets/img/icons/expand.svg
assets/img/icons/external.svg
assets/img/icons/external-link.svg
assets/img/icons/face-id.svg
diff --git a/ui/StatusQ/src/assets/img/icons/collapse.svg b/ui/StatusQ/src/assets/img/icons/collapse.svg
new file mode 100644
index 0000000000..c764b4aa0e
--- /dev/null
+++ b/ui/StatusQ/src/assets/img/icons/collapse.svg
@@ -0,0 +1,8 @@
+
diff --git a/ui/StatusQ/src/assets/img/icons/expand.svg b/ui/StatusQ/src/assets/img/icons/expand.svg
new file mode 100644
index 0000000000..820a769ffd
--- /dev/null
+++ b/ui/StatusQ/src/assets/img/icons/expand.svg
@@ -0,0 +1,8 @@
+
diff --git a/ui/app/AppLayouts/Wallet/panels/DAppsWorkflow.qml b/ui/app/AppLayouts/Wallet/panels/DAppsWorkflow.qml
index a716fa0b59..dd2c6d1201 100644
--- a/ui/app/AppLayouts/Wallet/panels/DAppsWorkflow.qml
+++ b/ui/app/AppLayouts/Wallet/panels/DAppsWorkflow.qml
@@ -11,13 +11,15 @@ import shared.popups.walletconnect 1.0
import AppLayouts.Wallet.services.dapps 1.0
import AppLayouts.Wallet.services.dapps.types 1.0
-import shared.stores 1.0
import utils 1.0
DappsComboBox {
id: root
required property WalletConnectService wcService
+ // Values mapped to Constants.LoginType
+ required property int loginType
+ property string selectedAccountAddress
signal pairWCReady()
@@ -85,7 +87,7 @@ DappsComboBox {
}
]
}
- selectedAccountAddress: root.wcService.selectedAccountAddress
+ selectedAccountAddress: root.selectedAccountAddress
dAppUrl: proposalMedatada.url
dAppName: proposalMedatada.name
@@ -116,26 +118,62 @@ DappsComboBox {
property SessionRequestResolved request: null
- sourceComponent: DAppRequestModal {
- account: request.account
- network: request.network
-
- dappName: request.dappName
- dappUrl: request.dappUrl
- dappIcon: request.dappIcon
-
- payloadData: request.data
- method: request.method
- maxFeesText: request.maxFeesText
- maxFeesEthText: request.maxFeesEthText
- enoughFunds: request.enoughFunds
- estimatedTimeText: request.estimatedTimeText
-
+ sourceComponent: DAppSignRequestModal {
+ objectName: "dappsRequestModal"
+ loginType: request.account.migragedToKeycard ? Constants.LoginType.Keycard : root.loginType
visible: true
- onClosed: sessionRequestLoader.active = false
+ dappUrl: request.dappUrl
+ dappIcon: request.dappIcon
+ dappName: request.dappName
- onSign: {
+ accountColor: request.account.color
+ accountName: request.account.name
+ accountAddress: request.account.address
+ accountEmoji: request.account.emoji
+
+ networkName: request.network.chainName
+ networkIconPath: Style.svg(request.network.iconUrl)
+
+ currentCurrency: ""
+ fiatFees: request.maxFeesText
+ cryptoFees: request.maxFeesEthText
+ estimatedTime: request.estimatedTimeText
+ feesLoading: !request.maxFeesText || !request.maxFeesEthText
+ hasFees: signingTransaction
+ enoughFundsForTransaction: request.enoughFunds
+ enoughFundsForFees: request.enoughFunds
+
+ signingTransaction: request.method === SessionRequest.methods.signTransaction.name || request.method === SessionRequest.methods.sendTransaction.name
+ requestPayload: {
+ switch(request.method) {
+ case SessionRequest.methods.personalSign.name:
+ return SessionRequest.methods.personalSign.getMessageFromData(request.data)
+ case SessionRequest.methods.sign.name: {
+ return SessionRequest.methods.sign.getMessageFromData(request.data)
+ }
+ case SessionRequest.methods.signTypedData_v4.name: {
+ const stringPayload = SessionRequest.methods.signTypedData_v4.getMessageFromData(request.data)
+ return JSON.stringify(JSON.parse(stringPayload), null, 2)
+ }
+ case SessionRequest.methods.signTypedData.name: {
+ const stringPayload = SessionRequest.methods.signTypedData.getMessageFromData(root.payloadData)
+ return JSON.stringify(JSON.parse(stringPayload), null, 2)
+ }
+ case SessionRequest.methods.signTransaction.name: {
+ const jsonPayload = SessionRequest.methods.signTransaction.getTxObjFromData(request.data)
+ return JSON.stringify(jsonPayload, null, 2)
+ }
+ case SessionRequest.methods.sendTransaction.name: {
+ const jsonPayload = SessionRequest.methods.sendTransaction.getTxObjFromData(request.data)
+ return JSON.stringify(jsonPayload, null, 2)
+ }
+ }
+ }
+
+ onClosed: Qt.callLater( () => sessionRequestLoader.active = false)
+
+ onAccepted: {
if (!request) {
console.error("Error signing: request is null")
return
@@ -143,28 +181,32 @@ DappsComboBox {
root.wcService.requestHandler.authenticate(request)
}
- onReject: {
+ onRejected: {
let userRejected = true
root.wcService.requestHandler.rejectSessionRequest(request, userRejected)
- close()
}
Connections {
target: root.wcService.requestHandler
function onMaxFeesUpdated(maxFees, maxFeesWei, haveEnoughFunds, symbol) {
- maxFeesText = `${maxFees.toFixed(2)} ${symbol}`
+ fiatFees = maxFees
+ currentCurrency = symbol
+
var ethStr = "?"
try {
ethStr = globalUtils.wei2Eth(maxFeesWei, 9)
} catch (e) {
// ignore error in case of tests and storybook where we don't have access to globalUtils
}
- maxFeesEthText = `${ethStr} ETH`
- enoughFunds = haveEnoughFunds
+ cryptoFees = ethStr
+ enoughFundsForTransaction = haveEnoughFunds
+ enoughFundsForFees = haveEnoughFunds
+ feesLoading = false
+ hasFees = !!maxFees
}
function onEstimatedTimeUpdated(minMinutes, maxMinutes) {
- estimatedTimeText = qsTr("%1-%2mins").arg(minMinutes).arg(maxMinutes)
+ estimatedTime = qsTr("%1-%2mins").arg(minMinutes).arg(maxMinutes)
}
}
}
diff --git a/ui/app/AppLayouts/Wallet/panels/WalletHeader.qml b/ui/app/AppLayouts/Wallet/panels/WalletHeader.qml
index a9944edca8..c8c8d9ae3a 100644
--- a/ui/app/AppLayouts/Wallet/panels/WalletHeader.qml
+++ b/ui/app/AppLayouts/Wallet/panels/WalletHeader.qml
@@ -128,6 +128,8 @@ Item {
enabled: !!Global.walletConnectService
wcService: Global.walletConnectService
+ loginType: root.store.loginType
+ selectedAccountAddress: root.walletStore.selectedAddress
}
StatusButton {
diff --git a/ui/app/AppLayouts/Wallet/popups/SignTransactionModalBase.qml b/ui/app/AppLayouts/Wallet/popups/SignTransactionModalBase.qml
index f145bd9fb0..c9b88707f3 100644
--- a/ui/app/AppLayouts/Wallet/popups/SignTransactionModalBase.qml
+++ b/ui/app/AppLayouts/Wallet/popups/SignTransactionModalBase.qml
@@ -2,6 +2,7 @@ import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQml.Models 2.15
+import QtGraphicalEffects 1.15
import StatusQ 0.1
import StatusQ.Core 0.1
@@ -24,6 +25,7 @@ StatusDialog {
property Component headerIconComponent
property bool feesLoading
+ property bool signButtonEnabled: true
property ObjectModel leftFooterContents
property ObjectModel rightFooterContents: ObjectModel {
@@ -39,7 +41,7 @@ StatusDialog {
StatusButton {
objectName: "signButton"
id: signButton
- interactive: !root.feesLoading
+ interactive: !root.feesLoading && root.signButtonEnabled
icon.name: Constants.authenticationIconByType[root.loginType]
text: qsTr("Sign")
onClicked: root.accept() // close and emit accepted() signal
@@ -51,11 +53,14 @@ StatusDialog {
property url fromImageSource
property alias fromImageSmartIdenticon: fromImageSmartIdenticon
property url toImageSource
+ readonly property alias toImageSmartIdenticon: toImageSmartIdenticon
property alias headerMainText: headerMainText.text
- property alias headerSubTextLayout: headerSubTextLayout.children
+ readonly property alias headerSubTextLayout: headerSubTextLayout.children
property string infoTagText
+ readonly property alias infoTag: infoTag
+ property bool showHeaderDivider: true
- default property alias contents: contentsLayout.children
+ default property alias contents: contentsLayout.data
width: 480
padding: 0
@@ -127,26 +132,48 @@ StatusDialog {
id: fromImageSmartIdenticon
width: 40
height: 40
+ asset.name: root.fromImageSource
+ asset.width: 40
+ asset.height: 40
asset.bgWidth: 40
asset.bgHeight: 40
+ asset.color: "transparent"
+ asset.bgColor: "transparent"
visible: !!asset.name
+ layer.enabled: toImageSmartIdenticon.visible
+ layer.effect: OpacityMask {
+ id: mask
+ invert: true
+
+ maskSource: Item {
+ width: mask.width + 4
+ height: mask.height + 4
+
+ Rectangle {
+ anchors.centerIn: parent
+ anchors.horizontalCenterOffset: toImageSmartIdenticon.width - 10
+
+ width: parent.width
+ height: width
+ radius: width / 2
+ }
+ }
+ }
}
- StatusRoundedImage {
- objectName: "fromImage"
- width: 42
- height: 42
- border.width: 2
- border.color: "transparent"
- image.source: root.fromImageSource
- visible: root.fromImageSource.toString() !== ""
- }
- StatusRoundedImage {
- objectName: "toImage"
- width: 42
- height: 42
- border.width: 2
- border.color: Theme.palette.statusBadge.foregroundColor
- image.source: root.toImageSource
+
+ StatusSmartIdenticon {
+ objectName: "toImageIdenticon"
+ id: toImageSmartIdenticon
+ width: 40
+ height: 40
+ asset.bgWidth: 40
+ asset.bgHeight: 40
+ visible: !!asset.name || !!asset.source
+ asset.name: root.toImageSource
+ asset.width: 40
+ asset.height: 40
+ asset.color: "transparent"
+ asset.bgColor: "transparent"
}
}
@@ -182,6 +209,7 @@ StatusDialog {
StatusDialogDivider {
Layout.fillWidth: true
Layout.bottomMargin: Style.current.bigPadding
+ visible: root.showHeaderDivider
}
ColumnLayout {
diff --git a/ui/app/AppLayouts/Wallet/services/dapps/DAppsRequestHandler.qml b/ui/app/AppLayouts/Wallet/services/dapps/DAppsRequestHandler.qml
index 3be258f1e4..f865c38a2c 100644
--- a/ui/app/AppLayouts/Wallet/services/dapps/DAppsRequestHandler.qml
+++ b/ui/app/AppLayouts/Wallet/services/dapps/DAppsRequestHandler.qml
@@ -159,6 +159,13 @@ QObject {
obj.resolveDappInfoFromSession(session)
root.sessionRequest(obj)
// TODO #15192: update maxFees
+ if (!event.params.request.params[0].gasLimit || !event.params.request.params[0].gasPrice) {
+ root.maxFeesUpdated(0, 0, true, "")
+ root.estimatedTimeUpdated(0, 0)
+ return
+ }
+
+
let gasLimit = parseFloat(parseInt(event.params.request.params[0].gasLimit, 16));
let gasPrice = parseFloat(parseInt(event.params.request.params[0].gasPrice, 16));
let maxFees = gasLimit * gasPrice
diff --git a/ui/app/AppLayouts/Wallet/services/dapps/WalletConnectService.qml b/ui/app/AppLayouts/Wallet/services/dapps/WalletConnectService.qml
index 488d1a9f09..b607cce9ab 100644
--- a/ui/app/AppLayouts/Wallet/services/dapps/WalletConnectService.qml
+++ b/ui/app/AppLayouts/Wallet/services/dapps/WalletConnectService.qml
@@ -32,8 +32,6 @@ QObject {
required property DAppsStore store
required property var walletRootStore
- readonly property string selectedAccountAddress: walletRootStore.selectedAddress
-
readonly property alias dappsModel: dappsProvider.dappsModel
readonly property alias requestHandler: requestHandler
diff --git a/ui/imports/shared/popups/walletconnect/DAppRequestModal.qml b/ui/imports/shared/popups/walletconnect/DAppRequestModal.qml
deleted file mode 100644
index fb8b4969bf..0000000000
--- a/ui/imports/shared/popups/walletconnect/DAppRequestModal.qml
+++ /dev/null
@@ -1,362 +0,0 @@
-import QtQuick 2.15
-import QtQuick.Layouts 1.15
-import QtQml.Models 2.15
-
-import StatusQ.Core 0.1
-import StatusQ.Popups.Dialog 0.1
-import StatusQ.Controls 0.1
-import StatusQ.Components 0.1
-import StatusQ.Core.Theme 0.1
-import StatusQ.Core.Utils 0.1 as StatusQ
-
-import shared.popups.walletconnect.panels 1.0
-import utils 1.0
-
-import AppLayouts.Wallet.services.dapps.types 1.0
-
-StatusDialog {
- id: root
-
- objectName: "dappsRequestModal"
-
- implicitWidth: 480
-
- required property string dappName
- required property string dappUrl
- required property url dappIcon
- required property string method
- required property var payloadData
- property string maxFeesText: ""
- property string maxFeesEthText: ""
- property bool enoughFunds: false
- property string estimatedTimeText: ""
-
- required property var account
- property var network: null
-
- signal sign()
- signal reject()
-
- title: qsTr("Sign request")
-
- padding: 20
-
- onPayloadDataChanged: d.updateDisplay()
- onMethodChanged: d.updateDisplay()
- Component.onCompleted: d.updateDisplay()
-
- contentItem: StatusScrollView {
- id: scrollView
- padding: 0
- ColumnLayout {
- spacing: 20
- clip: true
-
- width: scrollView.availableWidth
-
- IntentionPanel {
- Layout.fillWidth: true
-
- dappName: root.dappName
- dappIcon: root.dappIcon
- account: root.account
-
- userDisplayNaming: d.userDisplayNaming
- }
-
- ContentPanel {
- Layout.fillWidth: true
- Layout.maximumHeight: 340
-
- payloadToDisplay: d.payloadToDisplay
- }
-
- // TODO: externalize as a TargetPanel
- ColumnLayout {
- spacing: 8
-
- StatusBaseText {
- text: qsTr("Sign with")
- font.pixelSize: 13
- color: Theme.palette.directColor1
- }
-
- // TODO #14762: implement proper control to display the accounts details
- Rectangle {
- Layout.fillWidth: true
- Layout.preferredHeight: 76
-
- radius: 8
- border.width: 1
- border.color: Theme.palette.baseColor2
- color: "transparent"
-
- RowLayout {
- spacing: 12
- anchors.fill: parent
- anchors.margins: 16
-
- StatusSmartIdenticon {
- width: 40
- height: 40
-
- asset: StatusAssetSettings {
- color: Theme.palette.primaryColor1
- isImage: false
- isLetterIdenticon: true
- useAcronymForLetterIdenticon: false
- emoji: root.account.emoji
- }
- }
-
- ColumnLayout {
- Layout.alignment: Qt.AlignLeft
-
- StatusBaseText {
- text: root.account.name
-
- Layout.alignment: Qt.AlignLeft
-
- font.pixelSize: 13
- }
- StatusBaseText {
- text: StatusQ.Utils.elideAndFormatWalletAddress(root.account.address, 6, 4)
-
- Layout.alignment: Qt.AlignLeft
-
- font.pixelSize: 13
-
- color: Theme.palette.baseColor1
- }
- }
-
- Item {Layout.fillWidth: true }
- }
- }
-
- StatusBaseText {
- text: qsTr("Network")
- font.pixelSize: 13
- color: Theme.palette.directColor1
- }
-
- // TODO #14762: implement proper control to display the chain
- Rectangle {
- Layout.fillWidth: true
- Layout.preferredHeight: 76
-
- visible: root.network !== null
-
- radius: 8
- border.width: 1
- border.color: Theme.palette.baseColor2
- color: "transparent"
-
- RowLayout {
- spacing: 12
- anchors.fill: parent
- anchors.margins: 16
-
- StatusSmartIdenticon {
- width: 40
- height: 40
-
- asset: StatusAssetSettings {
- isImage: true
- name: !!root.network ? Style.svg("tiny/" + root.network.iconUrl) : ""
- }
- }
-
- StatusBaseText {
- text: !!root.network ? root.network.chainName : ""
-
- Layout.alignment: Qt.AlignLeft
-
- font.pixelSize: 13
- }
- Item {Layout.fillWidth: true }
- }
- }
-
- StatusBaseText {
- text: qsTr("Fees")
- font.pixelSize: 13
- color: Theme.palette.directColor1
- visible: d.isTransaction()
- }
-
- Rectangle {
- Layout.fillWidth: true
- Layout.preferredHeight: 76
-
- visible: root.network !== null && d.isTransaction()
-
- radius: 8
- border.width: 1
- border.color: Theme.palette.baseColor2
- color: "transparent"
-
- RowLayout {
- spacing: 12
- anchors.fill: parent
- anchors.margins: 16
-
- StatusBaseText {
- text: qsTr("Max. fees on %1").arg(!!root.network && root.network.chainName)
-
- Layout.alignment: Qt.AlignLeft | Qt.AlignTop
-
- font.pixelSize: 13
- color: Theme.palette.baseColor1
- }
-
- Item {Layout.fillWidth: true }
-
- ColumnLayout {
- StatusBaseText {
- text: root.maxFeesText
-
- Layout.alignment: Qt.AlignRight
-
- font.pixelSize: 13
- color: root.enoughFunds ? Theme.palette.directColor1 : Theme.palette.dangerColor1
- }
-
- StatusBaseText {
- text: root.maxFeesEthText
-
- Layout.alignment: Qt.AlignRight
-
- font.pixelSize: 13
- color: root.enoughFunds ? Theme.palette.baseColor1 : Theme.palette.dangerColor1
- }
- }
- }
- }
- }
- }
- }
-
- header: StatusDialogHeader {
- leftComponent: Item {
- width: 46
- height: 46
-
- StatusSmartIdenticon {
- anchors.fill: parent
- anchors.margins: 3
-
- asset: StatusAssetSettings {
- width: 40
- height: 40
- bgRadius: bgWidth / 2
- imgIsIdenticon: false
- isImage: true
- useAcronymForLetterIdenticon: false
- name: root.dappIcon
- }
- bridgeBadge.visible: true
- bridgeBadge.width: 16
- bridgeBadge.height: 16
- bridgeBadge.image.source: "assets/sign.svg"
- bridgeBadge.border.width: 3
- bridgeBadge.border.color: "transparent"
- bridgeBadge.color: Theme.palette.miscColor1
- }
- }
- headline.title: qsTr("Sign request")
- headline.subtitle: root.dappUrl
- }
-
- footer: StatusDialogFooter {
- id: footer
-
- leftButtons: ObjectModel {
- MaxFeesDisplay {
- maxFeesText: root.maxFeesText
- feesTextColor: root.enoughFunds ? Theme.palette.directColor1 : Theme.palette.dangerColor1
- }
- Item {
- width: 20
- }
- EstimatedTimeDisplay {
- estimatedTimeText: root.estimatedTimeText
- visible: !!root.estimatedTimeText
- }
- }
-
- rightButtons: ObjectModel {
- StatusButton {
- objectName: "rejectButton"
-
- height: 44
- text: qsTr("Reject")
-
- onClicked: {
- root.reject()
- }
- }
- StatusButton {
- height: 44
- text: qsTr("Sign")
-
- onClicked: {
- root.sign()
- }
- }
- }
- }
-
- QtObject {
- id: d
-
- property string payloadToDisplay: ""
- property string userDisplayNaming: ""
-
- function isTransaction() {
- return root.method === SessionRequest.methods.signTransaction.name || root.method === SessionRequest.methods.sendTransaction.name
- }
-
- function updateDisplay() {
- if (!root.payloadData)
- return
-
- switch (root.method) {
- case SessionRequest.methods.personalSign.name: {
- payloadToDisplay = SessionRequest.methods.personalSign.getMessageFromData(root.payloadData)
- userDisplayNaming = SessionRequest.methods.personalSign.requestDisplay
- break
- }
- case SessionRequest.methods.sign.name: {
- payloadToDisplay = SessionRequest.methods.sign.getMessageFromData(root.payloadData)
- userDisplayNaming = SessionRequest.methods.sign.requestDisplay
- break
- }
- case SessionRequest.methods.signTypedData_v4.name: {
- let messageObject = SessionRequest.methods.signTypedData_v4.getMessageFromData(root.payloadData)
- payloadToDisplay = JSON.stringify(JSON.parse(messageObject), null, 2)
- userDisplayNaming = SessionRequest.methods.signTypedData_v4.requestDisplay
- break
- }
- case SessionRequest.methods.signTypedData.name: {
- let messageObject = SessionRequest.methods.signTypedData.getMessageFromData(root.payloadData)
- payloadToDisplay = JSON.stringify(JSON.parse(messageObject), null, 2)
- userDisplayNaming = SessionRequest.methods.signTypedData.requestDisplay
- break
- }
- case SessionRequest.methods.signTransaction.name: {
- let tx = SessionRequest.methods.signTransaction.getTxObjFromData(root.payloadData)
- payloadToDisplay = JSON.stringify(tx, null, 2)
- userDisplayNaming = SessionRequest.methods.signTransaction.requestDisplay
- break
- }
- case SessionRequest.methods.sendTransaction.name: {
- let tx = SessionRequest.methods.sendTransaction.getTxObjFromData(root.payloadData)
- payloadToDisplay = JSON.stringify(tx, null, 2)
- userDisplayNaming = SessionRequest.methods.sendTransaction.requestDisplay
- break
- }
- }
- }
- }
-}
diff --git a/ui/imports/shared/popups/walletconnect/DAppSignRequestModal.qml b/ui/imports/shared/popups/walletconnect/DAppSignRequestModal.qml
new file mode 100644
index 0000000000..613138eba9
--- /dev/null
+++ b/ui/imports/shared/popups/walletconnect/DAppSignRequestModal.qml
@@ -0,0 +1,192 @@
+import QtQuick 2.15
+import QtQuick.Layouts 1.15
+import QtQml.Models 2.15
+
+import StatusQ 0.1
+import StatusQ.Controls 0.1
+import StatusQ.Core 0.1
+import StatusQ.Core.Theme 0.1
+import StatusQ.Core.Utils 0.1 as SQUtils
+import AppLayouts.Wallet.popups 1.0
+import AppLayouts.Wallet.panels 1.0
+
+import shared.popups.walletconnect.panels 1.0
+
+import utils 1.0
+
+SignTransactionModalBase {
+ id: root
+
+ required property bool signingTransaction
+ // DApp info
+ required property url dappUrl
+ required property url dappIcon
+ required property string dappName
+ // Payload to sign
+ required property string requestPayload
+ // Account
+ required property color accountColor
+ required property string accountName
+ required property string accountEmoji
+ required property string accountAddress
+ // Network
+ required property string networkName
+ required property string networkIconPath
+ // Fees
+ required property string currentCurrency
+ required property string fiatFees
+ required property string cryptoFees
+ required property string estimatedTime
+ required property bool hasFees
+
+ property bool enoughFundsForTransaction: true
+ property bool enoughFundsForFees: false
+
+ signButtonEnabled: enoughFundsForTransaction && enoughFundsForFees
+ title: qsTr("Sign Request")
+ subtitle: SQUtils.StringUtils.extractDomainFromLink(root.dappUrl)
+ headerIconComponent: RoundImageWithBadge {
+ imageUrl: root.dappIcon
+ width: 40
+ height: 40
+ }
+
+ gradientColor: Utils.setColorAlpha(root.accountColor, 0.05) // 5% of wallet color
+ headerMainText: root.signingTransaction ? qsTr("%1 wants you to sign this transaction with %2").arg(root.dappName).arg(root.accountName) :
+ qsTr("%1 wants you to sign this message with %2").arg(root.dappName).arg(root.accountName)
+
+ fromImageSmartIdenticon.asset.name: "filled-account"
+ fromImageSmartIdenticon.asset.emoji: root.accountEmoji
+ fromImageSmartIdenticon.asset.color: root.accountColor
+ fromImageSmartIdenticon.asset.isLetterIdenticon: !!root.accountEmoji
+ toImageSmartIdenticon.asset.name: Style.svg("sign")
+ toImageSmartIdenticon.asset.bgColor: Theme.palette.primaryColor3
+ toImageSmartIdenticon.asset.width: 24
+ toImageSmartIdenticon.asset.height: 24
+ toImageSmartIdenticon.asset.color: Theme.palette.primaryColor1
+
+ infoTagText: qsTr("Only sign if you trust the dApp")
+ infoTag.states: [
+ State {
+ name: "insufficientFunds"
+ when: !root.enoughFundsForTransaction
+ PropertyChanges {
+ target: infoTag
+ asset.color: Theme.palette.dangerColor1
+ tagPrimaryLabel.color: Theme.palette.dangerColor1
+ backgroundColor: Theme.palette.dangerColor3
+ bgBorderColor: Theme.palette.dangerColor2
+ tagPrimaryLabel.text: qsTr("Insufficient funds for transaction")
+ }
+ }
+ ]
+ showHeaderDivider: !root.requestPayload
+
+ leftFooterContents: ObjectModel {
+ RowLayout {
+ Layout.leftMargin: 4
+ spacing: Style.current.bigPadding
+ ColumnLayout {
+ spacing: 2
+ StatusBaseText {
+ text: qsTr("Max fees:")
+ color: Theme.palette.baseColor1
+ font.pixelSize: Style.current.additionalTextSize
+ }
+ StatusTextWithLoadingState {
+ Layout.fillWidth: true
+ objectName: "footerFiatFeesText"
+ text: "%1 %2".arg(formatBigNumber(root.fiatFees)).arg(root.currentCurrency)
+ loading: root.feesLoading
+ customColor: root.enoughFundsForFees ? Theme.palette.directColor1 : Theme.palette.dangerColor1
+ elide: Qt.ElideMiddle
+ Binding on text {
+ when: !root.hasFees
+ value: qsTr("No fees")
+ }
+ }
+ }
+ ColumnLayout {
+ spacing: 2
+ visible: root.hasFees
+ StatusBaseText {
+ text: qsTr("Est. time:")
+ color: Theme.palette.baseColor1
+ font.pixelSize: Style.current.additionalTextSize
+ }
+ StatusTextWithLoadingState {
+ objectName: "footerEstimatedTime"
+ text: root.estimatedTime
+ loading: root.feesLoading
+ }
+ }
+ }
+ }
+
+ // Payload
+ ContentPanel {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ payloadToDisplay: root.requestPayload
+ visible: !!root.requestPayload
+ }
+
+ // Account
+ SignInfoBox {
+ Layout.fillWidth: true
+ Layout.bottomMargin: Style.current.bigPadding
+ objectName: "accountBox"
+ caption: qsTr("Sign with")
+ primaryText: root.accountName
+ secondaryText: SQUtils.Utils.elideAndFormatWalletAddress(root.accountAddress)
+ asset.name: "filled-account"
+ asset.emoji: root.accountEmoji
+ asset.color: root.accountColor
+ asset.isLetterIdenticon: !!root.accountEmoji
+ }
+
+ // Network
+ SignInfoBox {
+ Layout.fillWidth: true
+ Layout.bottomMargin: Style.current.bigPadding
+ objectName: "networkBox"
+ caption: qsTr("Network")
+ primaryText: root.networkName
+ icon: root.networkIconPath
+ }
+
+ // Fees
+ SignInfoBox {
+ Layout.fillWidth: true
+ Layout.bottomMargin: Style.current.bigPadding
+ objectName: "feesBox"
+ caption: qsTr("Fees")
+ primaryText: qsTr("Max. fees on %1").arg(root.networkName)
+ secondaryText: " "
+ enabled: false
+ visible: root.hasFees
+ components: [
+ ColumnLayout {
+ spacing: 2
+ StatusTextWithLoadingState {
+ objectName: "fiatFeesText"
+ Layout.alignment: Qt.AlignRight
+ text: "%1 %2".arg(formatBigNumber(root.fiatFees)).arg(root.currentCurrency)
+ horizontalAlignment: Text.AlignRight
+ font.pixelSize: Style.current.additionalTextSize
+ loading: root.feesLoading
+ customColor: root.enoughFundsForFees ? Theme.palette.directColor1 : Theme.palette.dangerColor1
+ }
+ StatusTextWithLoadingState {
+ objectName: "cryptoFeesText"
+ Layout.alignment: Qt.AlignRight
+ text: "%1 ETH".arg(formatBigNumber(root.cryptoFees))
+ horizontalAlignment: Text.AlignRight
+ font.pixelSize: Style.current.additionalTextSize
+ customColor: root.enoughFundsForFees ? Theme.palette.baseColor1 : Theme.palette.dangerColor1
+ loading: root.feesLoading
+ }
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/ui/imports/shared/popups/walletconnect/RoundImageWithBadge.qml b/ui/imports/shared/popups/walletconnect/RoundImageWithBadge.qml
index e476a3de66..d22969b858 100644
--- a/ui/imports/shared/popups/walletconnect/RoundImageWithBadge.qml
+++ b/ui/imports/shared/popups/walletconnect/RoundImageWithBadge.qml
@@ -39,15 +39,15 @@ Item {
anchors.fill: mainImage
active: !mainImage.visible
sourceComponent: StatusRoundedComponent {
+ id: imageWrapper
color: Theme.palette.primaryColor3
StatusIcon {
- anchors.fill: parent
- anchors.margins: Style.current.padding
+ anchors.fill: imageWrapper
+ anchors.margins: imageWrapper.width / 4.5
color: Theme.palette.primaryColor1
icon: "dapp"
}
- }
- }
+ } }
layer.enabled: true
layer.effect: OpacityMask {
@@ -72,7 +72,7 @@ Item {
StatusRoundIcon {
id: badge
- width: (root.width / 2) - Style.current.padding
+ width: root.width / 3.6
height: width
anchors.bottom: parent.bottom
anchors.right: parent.right
diff --git a/ui/imports/shared/popups/walletconnect/panels/ContentPanel.qml b/ui/imports/shared/popups/walletconnect/panels/ContentPanel.qml
index df35e13b89..b2dd16a73b 100644
--- a/ui/imports/shared/popups/walletconnect/panels/ContentPanel.qml
+++ b/ui/imports/shared/popups/walletconnect/panels/ContentPanel.qml
@@ -1,9 +1,13 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
+import QtGraphicalEffects 1.15
+import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
+import utils 1.0
+
Rectangle {
id: root
@@ -14,40 +18,60 @@ Rectangle {
color: "transparent"
radius: 8
- implicitHeight: contentScrollView.implicitHeight + (2 * contentText.anchors.margins)
+ implicitHeight: d.expanded ? contentText.implicitHeight + (2 * contentText.anchors.margins) :
+ Math.min(contentText.implicitHeight + (2 * contentText.anchors.margins), 200)
- MouseArea {
- anchors.fill: parent
- cursorShape: contentScrollView.enabled || !enabled ? undefined : Qt.PointingHandCursor
- enabled: contentScrollView.height < contentScrollView.contentHeight
-
- onClicked: {
- contentScrollView.enabled = !contentScrollView.enabled
- }
- z: contentScrollView.z + 1
+ HoverHandler {
+ id: hoverHandler
+ target: root
}
- StatusScrollView {
- id: contentScrollView
+ StatusBaseText {
+ id: contentText
+ objectName: "textContent"
+
anchors.fill: parent
+ anchors.margins: 20
- contentWidth: availableWidth
- contentHeight: contentText.contentHeight
+ text: root.payloadToDisplay
+ font.pixelSize: Style.current.additionalTextSize
+ lineHeightMode: Text.FixedHeight
+ lineHeight: 18
- padding: 0
+ wrapMode: Text.WrapAnywhere
- enabled: false
-
- StatusBaseText {
- id: contentText
- anchors.fill: parent
- anchors.margins: 20
-
- width: contentScrollView.availableWidth
-
- text: root.payloadToDisplay
-
- wrapMode: Text.WrapAnywhere
+ StatusFlatButton {
+ objectName: "expandButton"
+ anchors.top: parent.top
+ anchors.right: parent.right
+ icon.name: d.expanded ? "collapse" : "expand"
+ icon.color: hovered ? Theme.palette.directColor1 : Theme.palette.baseColor1
+ hoverColor: "transparent"
+ visible: d.canExpand && hoverHandler.hovered
+ onClicked: {
+ d.expanded = !d.expanded
+ }
}
+
+ layer.enabled: !d.expanded && d.canExpand
+ layer.effect: OpacityMask {
+ maskSource: Rectangle {
+ width: root.width
+ height: root.height
+ gradient: Gradient {
+ orientation: Gradient.Vertical
+ GradientStop { position: 0.0 }
+ GradientStop { position: (root.height - 60) / root.height }
+ GradientStop { position: 1; color: "transparent" }
+ }
+ }
+ }
+ }
+
+ QtObject {
+ id: d
+ readonly property int maxContentHeight: 350
+ property bool expanded: false
+ property bool canExpand: contentText.implicitHeight > maxContentHeight
}
}
diff --git a/ui/imports/shared/popups/walletconnect/qmldir b/ui/imports/shared/popups/walletconnect/qmldir
index db9ca02679..8086638a23 100644
--- a/ui/imports/shared/popups/walletconnect/qmldir
+++ b/ui/imports/shared/popups/walletconnect/qmldir
@@ -2,6 +2,6 @@ PairWCModal 1.0 PairWCModal.qml
DAppsListPopup 1.0 DAppsListPopup.qml
ConnectDAppModal 1.0 ConnectDAppModal.qml
ConnectionStatusTag 1.0 ConnectionStatusTag.qml
-DAppRequestModal 1.0 DAppRequestModal.qml
+DAppSignRequestModal 1.0 DAppSignRequestModal.qml
DAppsUriCopyInstructionsPopup 1.0 DAppsUriCopyInstructionsPopup.qml
RoundImageWithBadge 1.0 RoundImageWithBadge.qml
diff --git a/ui/imports/shared/stores/DAppsStore.qml b/ui/imports/shared/stores/DAppsStore.qml
index f2c408a2b8..236b5c8f22 100644
--- a/ui/imports/shared/stores/DAppsStore.qml
+++ b/ui/imports/shared/stores/DAppsStore.qml
@@ -6,7 +6,6 @@ QObject {
id: root
required property var controller
-
/// \c dappsJson serialized from status-go.wallet.GetDapps
signal dappsListReceived(string dappsJson)
signal userAuthenticated(string topic, string id, string password, string pin)