feat(dapps) implement basic DAppRequestModal
I added it to storybook for testing. There is not integration with with the app yet. Updates: #14762
This commit is contained in:
parent
6973ccef6b
commit
1618e6ce0a
|
@ -72,8 +72,7 @@ Item {
|
|||
|
||||
spacing: 8
|
||||
|
||||
accounts: WalletAccountsModel{
|
||||
}
|
||||
accounts: d.selectedAccount
|
||||
|
||||
flatNetworks: SortFilterProxyModel {
|
||||
sourceModel: NetworksModel.flatNetworks
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
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 utils 1.0
|
||||
import shared.stores 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
function openModal() {
|
||||
modal.openWith()
|
||||
}
|
||||
|
||||
// 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
|
||||
signContent: JSON.stringify(d.signTestContent, null, 2)
|
||||
maxFeesText: "1.82 EUR"
|
||||
estimatedTimeText: "3-5 mins"
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property var accountsModel: WalletAccountsModel{}
|
||||
readonly property var selectedAccount: accountsModel.data[0]
|
||||
|
||||
readonly property var selectedNetwork: NetworksModel.flatNetworks.get(0)
|
||||
|
||||
readonly property var signTestContent: {
|
||||
"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/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// category: Wallet
|
|
@ -83,5 +83,8 @@ QtObject {
|
|||
'mossHovered': '#1E857B',
|
||||
'brownHovered': '#6F2727',
|
||||
'brown2Hovered': '#7C6926',
|
||||
|
||||
'lightDesktopBlue10': '#ECEFFB',
|
||||
'darkDesktopBlue10': '#273251',
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,6 +74,8 @@ ThemePalette {
|
|||
|
||||
messageHighlightColor: getColor('blue4', 0.2)
|
||||
|
||||
desktopBlue10: getColor('darkDesktopBlue10')
|
||||
|
||||
userCustomizationColors: [
|
||||
"#AAC6FF",
|
||||
"#887AF9",
|
||||
|
|
|
@ -72,6 +72,8 @@ ThemePalette {
|
|||
|
||||
messageHighlightColor: getColor('blue', 0.2)
|
||||
|
||||
desktopBlue10: getColor('lightDesktopBlue10')
|
||||
|
||||
userCustomizationColors: [
|
||||
"#2946C4",
|
||||
"#887AF9",
|
||||
|
|
|
@ -183,6 +183,8 @@ QtObject {
|
|||
|
||||
property color messageHighlightColor
|
||||
|
||||
property color desktopBlue10
|
||||
|
||||
property var userCustomizationColors: []
|
||||
|
||||
property var identiconRingColors: []
|
||||
|
|
|
@ -4,3 +4,4 @@ ShowcaseDelegate 1.0 ShowcaseDelegate.qml
|
|||
StaticSocialLinkInput 1.0 StaticSocialLinkInput.qml
|
||||
WalletAccountDelegate 1.0 WalletAccountDelegate.qml
|
||||
WalletKeyPairDelegate 1.0 WalletKeyPairDelegate.qml
|
||||
WalletAccountDetailsKeypairItem 1.0 WalletAccountDetailsKeypairItem.qml
|
|
@ -0,0 +1,376 @@
|
|||
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 utils 1.0
|
||||
|
||||
StatusDialog {
|
||||
id: root
|
||||
|
||||
implicitWidth: 480
|
||||
|
||||
required property string dappName
|
||||
required property string dappUrl
|
||||
required property url dappIcon
|
||||
required property string signContent
|
||||
required property string maxFeesText
|
||||
required property string estimatedTimeText
|
||||
|
||||
required property var account
|
||||
property var network: null
|
||||
|
||||
signal sign()
|
||||
signal reject()
|
||||
|
||||
function openWith() {
|
||||
root.open()
|
||||
}
|
||||
|
||||
title: qsTr("Sign request")
|
||||
|
||||
padding: 20
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 20
|
||||
clip: true
|
||||
|
||||
IntentionPanel {
|
||||
Layout.fillWidth: true
|
||||
|
||||
dappName: root.dappName
|
||||
dappIcon: root.dappIcon
|
||||
account: root.account
|
||||
signContent: root.signContent
|
||||
}
|
||||
|
||||
ContentPanel {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 340
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
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 }
|
||||
}
|
||||
}
|
||||
// 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
|
||||
|
||||
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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {}
|
||||
Item {
|
||||
width: 20
|
||||
}
|
||||
EstimatedTimeDisplay {}
|
||||
}
|
||||
|
||||
rightButtons: ObjectModel {
|
||||
StatusButton {
|
||||
height: 44
|
||||
text: qsTr("Reject")
|
||||
|
||||
onClicked: {
|
||||
root.reject()
|
||||
}
|
||||
}
|
||||
StatusButton {
|
||||
height: 44
|
||||
text: qsTr("Sign")
|
||||
|
||||
onClicked: {
|
||||
root.sign()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component MaxFeesDisplay: ColumnLayout {
|
||||
StatusBaseText {
|
||||
text: qsTr("Max fees:")
|
||||
font.pixelSize: 12
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
StatusBaseText {
|
||||
text: root.maxFeesText
|
||||
font.pixelSize: 16
|
||||
font.weight: Font.DemiBold
|
||||
}
|
||||
}
|
||||
|
||||
component EstimatedTimeDisplay: ColumnLayout {
|
||||
StatusBaseText {
|
||||
text: qsTr("Est. time:")
|
||||
font.pixelSize: 12
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
StatusBaseText {
|
||||
text: root.estimatedTimeText
|
||||
font.pixelSize: 16
|
||||
font.weight: Font.DemiBold
|
||||
}
|
||||
}
|
||||
|
||||
component IntentionPanel: ColumnLayout {
|
||||
spacing: 8
|
||||
|
||||
required property string dappName
|
||||
required property url dappIcon
|
||||
required property var account
|
||||
required property string signContent
|
||||
|
||||
// Icons
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.bottomMargin: 8
|
||||
|
||||
StatusRoundedImage {
|
||||
id: dappIconComponent
|
||||
|
||||
width: height
|
||||
height: parent.height
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.horizontalCenterOffset: -16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
image.source: root.dappIcon
|
||||
}
|
||||
StatusRoundIcon {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.horizontalCenterOffset: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
asset: StatusAssetSettings {
|
||||
width: 24
|
||||
height: 24
|
||||
color: Theme.palette.primaryColor1
|
||||
bgWidth: 40
|
||||
bgHeight: 40
|
||||
bgColor: Theme.palette.desktopBlue10
|
||||
bgRadius: bgWidth / 2
|
||||
bgBorderWidth: 2
|
||||
bgBorderColor: Theme.palette.statusAppLayout.backgroundColor
|
||||
source: "assets/sign.svg"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Names and intentions
|
||||
StatusBaseText {
|
||||
text: qsTr("%1 wants you to sign this transaction with %2").arg(dappName).arg(account.name)
|
||||
|
||||
Layout.preferredWidth: 400
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.DemiBold
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
// TODO #14762: externalize as a InfoPill and merge base implementation with
|
||||
// the existing IssuePill reusable component
|
||||
Rectangle {
|
||||
Layout.preferredWidth: operationStatusLayout.implicitWidth + 24
|
||||
Layout.preferredHeight: operationStatusLayout.implicitHeight + 14
|
||||
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
visible: true
|
||||
|
||||
border.color: Theme.palette.successColor2
|
||||
border.width: 1
|
||||
color: "transparent"
|
||||
radius: height / 2
|
||||
|
||||
RowLayout {
|
||||
id: operationStatusLayout
|
||||
|
||||
spacing: 8
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
StatusIcon {
|
||||
Layout.preferredWidth: 16
|
||||
Layout.preferredHeight: 16
|
||||
|
||||
visible: true
|
||||
|
||||
color: Theme.palette.directColor1
|
||||
icon: "info"
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
text: qsTr("Only sign if you trust the dApp")
|
||||
|
||||
font.pixelSize: 12
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component ContentPanel: Rectangle {
|
||||
id: contentPanelRect
|
||||
border.width: 1
|
||||
border.color: Theme.palette.baseColor2
|
||||
color: "transparent"
|
||||
radius: 8
|
||||
|
||||
StatusScrollView {
|
||||
id: contentScrollView
|
||||
anchors.fill: parent
|
||||
|
||||
contentWidth: availableWidth
|
||||
contentHeight: contentText.implicitHeight
|
||||
|
||||
StatusBaseText {
|
||||
id: contentText
|
||||
anchors.fill: parent
|
||||
anchors.margins: 20
|
||||
|
||||
width: contentScrollView.availableWidth
|
||||
|
||||
text: signContent
|
||||
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Feature / Sign">
|
||||
<path id="Vector 32" d="M3.30026 5.87295C2.67249 5.56241 1.93965 5.00104 1.46227 4.33462C0.711792 3.28696 0.491562 2.00625 1.53098 1.23526C2.3099 0.657513 3.61233 1.37874 4.10757 2.49686C4.7675 3.98668 4.6573 6.28428 3.42906 8.2263C2.8116 9.2026 1.86004 9.10424 1.53098 8.54312C1.07672 7.76851 1.54754 6.07397 3.70877 4.99336C5.59513 4.05019 6.12334 4.52806 6.01429 5.03985C5.9758 5.22047 5.55049 5.95884 6.11735 5.95884C6.60595 5.95884 7.02642 5.354 7.42285 5.03985C7.92791 4.63959 8.4535 4.51593 8.38977 5.26933C8.36595 5.55093 8.48785 6.15638 9.17496 5.81283" stroke="white" stroke-width="0.833333" stroke-linecap="round"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 759 B |
|
@ -1,3 +1,4 @@
|
|||
PairWCModal 1.0 PairWCModal.qml
|
||||
DAppsListPopup 1.0 DAppsListPopup.qml
|
||||
ConnectDAppModal 1.0 ConnectDAppModal.qml
|
||||
ConnectDAppModal 1.0 ConnectDAppModal.qml
|
||||
DAppRequestModal 1.0 DAppRequestModal.qml
|
Loading…
Reference in New Issue