diff --git a/.gitmodules b/.gitmodules index a832b398fb..6efc0e3d16 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,6 @@ [submodule "ci_tools_atomic_dex/vcpkg-custom-ports"] path = ci_tools_atomic_dex/vcpkg-custom-ports url = https://github.com/KomodoPlatform/vcpkg-custom-ports -[submodule "atomic_defi_design/bignumberjs/bignumber.js"] - path = atomic_defi_design/bignumberjs/bignumber.js +[submodule "atomic_defi_design/imports/bignumberjs/bignumber.js"] + path = atomic_defi_design/imports/bignumberjs/bignumber.js url = https://github.com/KomodoPlatform/bignumber.js.git diff --git a/assets/config/0.5.5-coins.json b/assets/config/0.5.5-coins.json index 0365137ffe..a5519d2a3d 100644 --- a/assets/config/0.5.5-coins.json +++ b/assets/config/0.5.5-coins.json @@ -6729,10 +6729,16 @@ "nomics_id": "SPACE7", "electrum": [ { - "url": "electrum1.spaceworks.co:50001" + "url": "electrum3.cipig.net:10011", + "ws_url": "electrum3.cipig.net:30011" }, { - "url": "electrum2.spaceworks.co:50001" + "url": "electrum2.cipig.net:10011", + "ws_url": "electrum2.cipig.net:30011" + }, + { + "url": "electrum1.cipig.net:10011", + "ws_url": "electrum1.cipig.net:30011" } ], "explorer_url": [ @@ -7403,6 +7409,7 @@ "active": false, "coinpaprika_id": "xrg-ergon", "coingecko_id": "test-coin", + "nomics_id": "XRG", "currently_enabled": false, "electrum": [ { diff --git a/atomic_defi_design/Dex/Components/CannotEnableCoinModal.qml b/atomic_defi_design/Dex/Components/CannotEnableCoinModal.qml index 69c59d8811..19c44755c6 100644 --- a/atomic_defi_design/Dex/Components/CannotEnableCoinModal.qml +++ b/atomic_defi_design/Dex/Components/CannotEnableCoinModal.qml @@ -2,7 +2,7 @@ import QtQuick 2.12 import QtQuick.Layouts 1.15 -BasicModal +MultipageModal { property string coin_to_enable_ticker // The coin you tried to enable. property var settings_modal: setting_modal // A reference to a SettingModal object. Open when "Increase limit in settings" button is clicked. @@ -10,9 +10,9 @@ BasicModal id: root width: 600 - ModalContent + MultipageModalContent { - title: qsTr("Failed to enable %1").arg(coin_to_enable_ticker) + titleText: qsTr("Failed to enable %1").arg(coin_to_enable_ticker) DefaultText { Layout.fillWidth: true diff --git a/atomic_defi_design/Dex/Components/CexInfoModal.qml b/atomic_defi_design/Dex/Components/CexInfoModal.qml index 466f7fcd11..64777e138f 100644 --- a/atomic_defi_design/Dex/Components/CexInfoModal.qml +++ b/atomic_defi_design/Dex/Components/CexInfoModal.qml @@ -6,12 +6,12 @@ import QtQuick.Layouts 1.15 import "../Constants" import App 1.0 -BasicModal { +MultipageModal { id: root // Inside modal - ModalContent { - title: General.cex_icon + " " + qsTr("Market Data") + MultipageModalContent { + titleText: General.cex_icon + " " + qsTr("Market Data") DefaultText { Layout.preferredHeight: 200 diff --git a/atomic_defi_design/Dex/Components/ComponentWithTitle.qml b/atomic_defi_design/Dex/Components/ComponentWithTitle.qml index 1b569e8abf..8465e89673 100644 --- a/atomic_defi_design/Dex/Components/ComponentWithTitle.qml +++ b/atomic_defi_design/Dex/Components/ComponentWithTitle.qml @@ -1,36 +1,47 @@ import QtQuick 2.15 import QtQuick.Layouts 1.15 + import App 1.0 +import "../Constants" +import Dex.Themes 1.0 as Dex -ColumnLayout { - property alias title: title.text - property bool expandable: false - property bool expanded: false - readonly property bool show_content: !expandable || expanded +ColumnLayout +{ + property alias title: title.text + property bool expandable: false + property bool expanded: false + readonly property bool show_content: !expandable || expanded - RowLayout { - id: row_layout + RowLayout + { + id: rowLayout Layout.fillWidth: true - Arrow { - id: arrow_icon + Arrow + { + id: arrowIco + visible: expandable - up: expanded - color: mouse_area.containsMouse ? Style.colorOrange : expanded ? DexTheme.redColor : DexTheme.greenColor + Layout.alignment: Qt.AlignVCenter + + up: expanded + color: mouseArea.containsMouse ? Dex.CurrentTheme.foregroundColor3 : Dex.CurrentTheme.foregroundColor2 } - TitleText { + TitleText + { id: title Layout.fillWidth: true - color: !expandable ? DexTheme.foregroundColorDarkColor4 : DexTheme.foregroundColorLightColor2 - font: DexTypo.body2 - opacity: .6 - DefaultMouseArea { - id: mouse_area + + color: Dex.CurrentTheme.foregroundColor2 + + DefaultMouseArea + { + id: mouseArea enabled: expandable anchors.fill: parent - anchors.leftMargin: -arrow_icon.width - row_layout.spacing + anchors.leftMargin: -arrowIco.width - rowLayout.spacing hoverEnabled: true onClicked: expanded = !expanded } diff --git a/atomic_defi_design/Dex/Components/DefaultListView.qml b/atomic_defi_design/Dex/Components/DefaultListView.qml index 06090585af..d723a2b199 100644 --- a/atomic_defi_design/Dex/Components/DefaultListView.qml +++ b/atomic_defi_design/Dex/Components/DefaultListView.qml @@ -32,4 +32,4 @@ ListView duration: Style.animationDuration * 0.5;velocity: -1 } } -} \ No newline at end of file +} diff --git a/atomic_defi_design/Dex/Components/DefaultModal.qml b/atomic_defi_design/Dex/Components/DefaultModal.qml index 87f52b9cfd..1302c9e155 100644 --- a/atomic_defi_design/Dex/Components/DefaultModal.qml +++ b/atomic_defi_design/Dex/Components/DefaultModal.qml @@ -12,14 +12,17 @@ Popup property int radius: 18 anchors.centerIn: Overlay.overlay + horizontalPadding: 88 + verticalPadding: 52 + modal: true focus: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside - Overlay.modal: Rectangle - { - color: "#AA000000" - } + background: DefaultRectangle { radius: root.radius; color: Dex.CurrentTheme.floatingBackgroundColor } + + Overlay.modal: Rectangle { color: "#AA000000" } // Fade in animation onVisibleChanged: @@ -27,20 +30,16 @@ Popup if (visible) { opacity = 0 - fade_animation.start() + fadeAnimation.start() } } NumberAnimation { - id: fade_animation + id: fadeAnimation target: root property: "opacity" duration: Style.animationDuration to: 1 } - - background: DexRectangle { - radius: 18 - } } diff --git a/atomic_defi_design/Dex/Components/DefaultScrollView.qml b/atomic_defi_design/Dex/Components/DefaultScrollView.qml new file mode 100644 index 0000000000..4eee53c923 --- /dev/null +++ b/atomic_defi_design/Dex/Components/DefaultScrollView.qml @@ -0,0 +1,29 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +import Dex.Themes 1.0 as Dex + +ScrollView +{ + id: control + + clip: true + ScrollBar.vertical.background: Rectangle { color: Dex.CurrentTheme.scrollBarBackgroundColor; radius: 8 } + ScrollBar.vertical.contentItem: Rectangle + { + implicitWidth: 10 + implicitHeight: 20 + color: Dex.CurrentTheme.scrollBarIndicatorColor + radius: 8 + } + ScrollBar.vertical.policy: contentHeight > height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff + ScrollBar.horizontal.background: Rectangle { color: Dex.CurrentTheme.scrollBarBackgroundColor; radius: 8 } + ScrollBar.horizontal.contentItem: Rectangle + { + implicitWidth: 20 + implicitHeight: 10 + color: Dex.CurrentTheme.scrollBarIndicatorColor + radius: 8 + } + ScrollBar.horizontal.policy: contentHeight > height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff +} diff --git a/atomic_defi_design/Dex/Components/DexScrollBar.qml b/atomic_defi_design/Dex/Components/DexScrollBar.qml index 1d1f10d69a..14f5c65766 100644 --- a/atomic_defi_design/Dex/Components/DexScrollBar.qml +++ b/atomic_defi_design/Dex/Components/DexScrollBar.qml @@ -22,7 +22,7 @@ ScrollBar height: parent.height anchors.verticalCenter: parent.verticalCenter - color: Dex.CurrentTheme.scrollBarBackgroundColor + color: Dex.CurrentTheme.scrollBarIndicatorColor } } @@ -36,7 +36,7 @@ ScrollBar width: parent.width height: parent.height anchors.verticalCenter: parent.verticalCenter - color: Dex.CurrentTheme.scrollBarIndicatorColor + color: Dex.CurrentTheme.scrollBarBackgroundColor } } -} \ No newline at end of file +} diff --git a/atomic_defi_design/Dex/Components/EulaModal.qml b/atomic_defi_design/Dex/Components/EulaModal.qml index 6065baad1e..a5b5e5fec0 100644 --- a/atomic_defi_design/Dex/Components/EulaModal.qml +++ b/atomic_defi_design/Dex/Components/EulaModal.qml @@ -6,7 +6,7 @@ import QtQuick.Layouts 1.15 import "../Constants" import App 1.0 //> API.app_name -BasicModal +MultipageModal { id: root @@ -21,9 +21,9 @@ BasicModal {} property bool close_only: false - ModalContent + MultipageModalContent { - title: qsTr("Disclaimer & Terms of Service") + titleText: qsTr("Disclaimer & Terms of Service") InnerBackground { @@ -144,4 +144,4 @@ BasicModal

This document was last updated on January 31st, 2020

" .arg(API.app_name) } -} \ No newline at end of file +} diff --git a/atomic_defi_design/Dex/Components/HelpModal.qml b/atomic_defi_design/Dex/Components/HelpModal.qml index 1a0fad4bda..8648c38733 100644 --- a/atomic_defi_design/Dex/Components/HelpModal.qml +++ b/atomic_defi_design/Dex/Components/HelpModal.qml @@ -1,11 +1,11 @@ import QtQuick 2.12 -BasicModal +MultipageModal { property string helpSentence - property alias title: _content.title + property alias title: _content.titleText width: 500 - ModalContent { id: _content; DexLabel { text: helpSentence } } + MultipageModalContent { id: _content; DexLabel { text: helpSentence } } } diff --git a/atomic_defi_design/Dex/Components/LogModal.qml b/atomic_defi_design/Dex/Components/LogModal.qml index f523ae1cbe..570f96bf63 100644 --- a/atomic_defi_design/Dex/Components/LogModal.qml +++ b/atomic_defi_design/Dex/Components/LogModal.qml @@ -1,13 +1,13 @@ import QtQuick 2.15 import QtQuick.Layouts 1.15 -BasicModal { +MultipageModal { id: root - property alias header: modal_content.title + property alias header: modal_content.titleText property alias field: text_area.field - ModalContent { + MultipageModalContent { id: modal_content TextAreaWithTitle { diff --git a/atomic_defi_design/Dex/Components/MinTradeModal.qml b/atomic_defi_design/Dex/Components/MinTradeModal.qml index 865db370c3..b81d0a56c0 100644 --- a/atomic_defi_design/Dex/Components/MinTradeModal.qml +++ b/atomic_defi_design/Dex/Components/MinTradeModal.qml @@ -6,12 +6,12 @@ import QtQuick.Layouts 1.15 import "../Constants" import App 1.0 -BasicModal { +MultipageModal { id: root // Inside modal - ModalContent { - title: General.cex_icon + " " + qsTr("Minimum Trading Amount") + MultipageModalContent { + titleText: General.cex_icon + " " + qsTr("Minimum Trading Amount") DefaultText { //Layout.preferredHeight: 200 diff --git a/atomic_defi_design/Dex/Components/ModalContent.qml b/atomic_defi_design/Dex/Components/ModalContent.qml deleted file mode 100644 index 959a328126..0000000000 --- a/atomic_defi_design/Dex/Components/ModalContent.qml +++ /dev/null @@ -1,64 +0,0 @@ -//! Qt Imports -import QtQuick 2.15 -import QtQuick.Layouts 1.15 - -//! Project Imports -import "../Constants" -import App 1.0 - -// The content of a modal. Must be a child of a `BasicModal` component. -ColumnLayout -{ - property var titleAlignment: Qt.AlignLeft - property int titleTopMargin: 20 - - property alias title: _title.text - default property alias content: _innerLayout.data - property alias footer: _footer.data - - Layout.fillWidth: true - spacing: 10 - - DefaultText - { - id: _title - Layout.topMargin: parent.titleTopMargin - Layout.alignment: parent.titleAlignment - font: DexTypo.head6 - } - - DexFlickable - { - id: _flickable - - readonly property int padding: 25 - - flickableDirection: Flickable.VerticalFlick - - rightMargin: -1 - - Layout.preferredWidth: contentWidth - Layout.preferredHeight: contentHeight - Layout.maximumHeight: window.height - 200 - - contentWidth: _innerLayout.width + padding // Padding is for preventing shadows effect being cut - contentHeight: _innerLayout.height + padding - - ColumnLayout - { - id: _innerLayout - spacing: Style.rowSpacing - anchors.centerIn: parent - width: _modalWidth - (_modalPadding * 2) - _flickable.padding - } - } - - RowLayout // Footer - { - id: _footer - Layout.topMargin: Style.rowSpacing - Layout.rightMargin: 40 - Layout.leftMargin: 40 - spacing: Style.buttonSpacing - } -} diff --git a/atomic_defi_design/Dex/Components/ModalContent2.qml b/atomic_defi_design/Dex/Components/ModalContent2.qml deleted file mode 100644 index 2035ead2a0..0000000000 --- a/atomic_defi_design/Dex/Components/ModalContent2.qml +++ /dev/null @@ -1,48 +0,0 @@ -//! Qt Imports -import QtQuick 2.15 -import QtQuick.Layouts 1.15 - -//! Project Imports -import "../Constants" -import App 1.0 - -ColumnLayout -{ - id: root - - property alias title: _title - property alias titleText: _title.text - property var titleAlignment: Qt.AlignLeft - property int titleTopMargin: 20 - - default property alias content: _innerLayout.data - - Layout.fillWidth: true - Layout.leftMargin: 88 - Layout.rightMargin: 88 - Layout.topMargin: 52 - Layout.bottomMargin: 52 - - DefaultText - { - id: _title - Layout.topMargin: parent.titleTopMargin - Layout.alignment: parent.titleAlignment - font: DexTypo.head6 - } - - DefaultFlickable - { - flickableDirection: Flickable.VerticalFlick - - Layout.fillWidth: true - Layout.preferredHeight: _innerLayout.height - Layout.maximumHeight: window.height - 200 - - ColumnLayout - { - id: _innerLayout - anchors.centerIn: parent - } - } -} diff --git a/atomic_defi_design/Dex/Components/BasicModal.qml b/atomic_defi_design/Dex/Components/MultipageModal.qml similarity index 87% rename from atomic_defi_design/Dex/Components/BasicModal.qml rename to atomic_defi_design/Dex/Components/MultipageModal.qml index a9e02b2045..8fcfff3e3e 100644 --- a/atomic_defi_design/Dex/Components/BasicModal.qml +++ b/atomic_defi_design/Dex/Components/MultipageModal.qml @@ -23,7 +23,7 @@ DefaultModal else { targetPageIndex = currentIndex + 1 - page_change_animation.start() + changePageAnim.start() } } @@ -34,37 +34,33 @@ DefaultModal else { targetPageIndex = currentIndex - 1 - page_change_animation.start() + changePageAnim.start() } } //! Appearance - padding: 20 - leftPadding: 20 - rightPadding: 20 - bottomPadding: 15 width: 676 - height: column_layout.height + verticalPadding * 2 + height: columnLayout.height + verticalPadding * 2 onOpened: stack_layout.opacity = 1 - SequentialAnimation { - id: page_change_animation - NumberAnimation { id: fade_out; target: root; property: "opacity"; to: 0; duration: Style.animationDuration } + SequentialAnimation + { + id: changePageAnim + NumberAnimation { id: fadeOut; target: root; property: "opacity"; to: 0; duration: Style.animationDuration } PropertyAction { target: root; property: "currentIndex"; value: targetPageIndex } - NumberAnimation { target: root; property: "opacity"; to: 1; duration: fade_out.duration } + NumberAnimation { target: root; property: "opacity"; to: 1; duration: fadeOut.duration } } Column { - id: column_layout + id: columnLayout spacing: Style.rowSpacing width: parent.width anchors.horizontalCenter: parent.horizontalCenter Row { - id: page_indicator visible: root.count > 1 anchors.horizontalCenter: parent.horizontalCenter diff --git a/atomic_defi_design/Dex/Components/MultipageModalContent.qml b/atomic_defi_design/Dex/Components/MultipageModalContent.qml new file mode 100644 index 0000000000..83de4fbc1d --- /dev/null +++ b/atomic_defi_design/Dex/Components/MultipageModalContent.qml @@ -0,0 +1,58 @@ +//! Qt Imports +import QtQuick 2.15 +import QtQuick.Layouts 1.15 + +//! Project Imports +import "../Constants" +import App 1.0 + +ColumnLayout +{ + id: root + + property alias title: _title + property alias titleText: _title.text + property var titleAlignment: Qt.AlignLeft + property int titleTopMargin: 20 + property int topMarginAfterTitle: 30 + + default property alias content: _innerLayout.data + property alias footer: _footer.data + + Layout.fillWidth: true + + DefaultText + { + id: _title + Layout.topMargin: root.titleTopMargin + Layout.alignment: root.titleAlignment + font: DexTypo.head6 + } + + DefaultFlickable + { + flickableDirection: Flickable.VerticalFlick + + Layout.topMargin: root.topMarginAfterTitle + Layout.fillWidth: true + Layout.preferredHeight: contentHeight + Layout.maximumHeight: window.height - 200 + + contentHeight: _innerLayout.height + + ColumnLayout + { + id: _innerLayout + anchors.centerIn: parent + width: parent.width + } + } + + // Footer + RowLayout + { + id: _footer + Layout.topMargin: Style.rowSpacing + spacing: Style.buttonSpacing + } +} diff --git a/atomic_defi_design/Dex/Components/RestartModal.qml b/atomic_defi_design/Dex/Components/RestartModal.qml index 94512f2b6f..c2cef491be 100644 --- a/atomic_defi_design/Dex/Components/RestartModal.qml +++ b/atomic_defi_design/Dex/Components/RestartModal.qml @@ -7,7 +7,7 @@ import QtQuick.Controls 2.15 import "../Constants" import App 1.0 -BasicModal +MultipageModal { id: root @@ -33,10 +33,10 @@ BasicModal } } - ModalContent + MultipageModalContent { Layout.fillWidth: true - title: qsTr("Applying the changes...") + titleText: qsTr("Applying the changes...") Timer { diff --git a/atomic_defi_design/Dex/Components/TextAreaWithTitle.qml b/atomic_defi_design/Dex/Components/TextAreaWithTitle.qml index 19497779bd..9757c9ce6f 100644 --- a/atomic_defi_design/Dex/Components/TextAreaWithTitle.qml +++ b/atomic_defi_design/Dex/Components/TextAreaWithTitle.qml @@ -1,53 +1,63 @@ import QtQuick 2.15 import QtQuick.Layouts 1.15 + import Qaterial 1.0 as Qaterial + import "../Constants" import App 1.0 import Dex.Themes 1.0 as Dex -ColumnLayout { +ColumnLayout +{ id: control property alias title: title_text.text + property color titleColor: Dex.CurrentTheme.foregroundColor property alias field: input_field property alias save_button: save_button property alias hide_button: hide_button property alias hide_button_area: hide_button.mouse_area - property bool copyable: false - property bool hidable: false - property var onReturn // function + property bool copyable: false + property bool hidable: false + property var onReturn // function property alias remove_newline: input_field.remove_newline - property bool hiding: true + property bool hiding: true - property bool saveable: false + property bool saveable: false signal saved() signal copied() - // Local - function reset() { - input_field.text = '' - } + function reset() { input_field.text = '' } + + TitleText + { + id: title_text + + Layout.alignment: Qt.AlignVCenter + + color: titleColor + + Qaterial.Icon + { + visible: control.copyable - RowLayout { - TitleText { - id: title_text Layout.alignment: Qt.AlignVCenter - Qaterial.Icon { - visible: control.copyable - Layout.alignment: Qt.AlignVCenter - x: title_text.implicitWidth + 10 - size: 16 - icon: Qaterial.Icons.contentCopy - color: copyArea.containsMouse ? Dex.CurrentTheme.accentColor : Dex.CurrentTheme.foregroundColor - DexMouseArea { - id: copyArea - anchors.fill: parent - hoverEnabled: true - onClicked: { - Qaterial.Clipboard.text = input_field.text - control.copied() - } + + x: title_text.implicitWidth + 10 + size: 16 + icon: Qaterial.Icons.contentCopy + color: copyArea.containsMouse ? Dex.CurrentTheme.accentColor : Dex.CurrentTheme.foregroundColor + + DefaultMouseArea + { + id: copyArea + anchors.fill: parent + hoverEnabled: true + onClicked: + { + Qaterial.Clipboard.text = input_field.text + control.copied() } } } @@ -87,9 +97,5 @@ ColumnLayout { font.pixelSize: Style.textSizeSmall height: 20 } - } - - + } } - - diff --git a/atomic_defi_design/Dex/Components/TextEditWithTitle.qml b/atomic_defi_design/Dex/Components/TextEditWithTitle.qml index 6e6c454e57..521bba7526 100644 --- a/atomic_defi_design/Dex/Components/TextEditWithTitle.qml +++ b/atomic_defi_design/Dex/Components/TextEditWithTitle.qml @@ -1,60 +1,63 @@ import QtQuick 2.15 import QtQuick.Layouts 1.15 + import Qaterial 1.0 as Qaterial + import "../Constants" as Constants import App 1.0 +import Dex.Themes 1.0 as Dex -ComponentWithTitle { +ComponentWithTitle +{ id: control - property alias text: text.text_value - property alias value_color: text.color - property alias privacy: text.privacy - + property alias label: text + property alias text: text.text_value + property alias value_color: text.color + property alias privacy: text.privacy property bool copy: false property string onCopyNotificationTitle: qsTr("Swap ID") property string onCopyNotificationMsg: qsTr("copied to clipboard") - RowLayout { + Row + { Layout.fillWidth: true - DexLabel { + DefaultText + { id: text + width: implicitWidth > parent.width * 0.9 ? parent.width * 0.9 : implicitWidth + clip: true textFormat: TextEdit.AutoText - Layout.alignment: Qt.AlignVCenter - Layout.preferredHeight: show_content ? contentHeight : 0 - Behavior on Layout.preferredHeight { SmoothedAnimation { id: expand_animation; duration: Constants.Style.animationDuration * 2; velocity: -1 } } - color: DexTheme.foregroundColor - - - opacity: show_content ? 1 : 0 - Behavior on opacity { SmoothedAnimation { duration: expand_animation.duration; velocity: -1 } } + wrapMode: Text.WrapAnywhere + Behavior on opacity { SmoothedAnimation { duration: expand_animation.duration; velocity: -1 } } + Behavior on Layout.preferredHeight { SmoothedAnimation { id: expand_animation; duration: Constants.Style.animationDuration * 2; velocity: -1 } } } - Qaterial.Icon { + Qaterial.Icon + { visible: control.copy - Layout.alignment: Qt.AlignVCenter - x: text.implicitWidth + 10 + + width: parent.width * 0.1 size: 16 icon: Qaterial.Icons.contentCopy - color: copyArea.containsMouse ? DexTheme.accentColor : DexTheme.foregroundColor - DexMouseArea { + color: copyArea.containsMouse ? Dex.CurrentTheme.foregroundColor2 : Dex.CurrentTheme.foregroundColor + + DefaultMouseArea + { id: copyArea anchors.fill: parent hoverEnabled: true - onClicked: { + onClicked: + { Qaterial.Clipboard.text = control.text app.notifyCopy(onCopyNotificationTitle, onCopyNotificationMsg) } } } - - Item { - Layout.fillWidth: true - } } } diff --git a/atomic_defi_design/Dex/Dashboard/FatalErrorModal.qml b/atomic_defi_design/Dex/Dashboard/FatalErrorModal.qml index 6ed4cb0b52..e4bc2646d4 100644 --- a/atomic_defi_design/Dex/Dashboard/FatalErrorModal.qml +++ b/atomic_defi_design/Dex/Dashboard/FatalErrorModal.qml @@ -6,7 +6,7 @@ import "../Constants" import App 1.0 import "../Components" -BasicModal { +MultipageModal { id: root property string message @@ -23,8 +23,8 @@ BasicModal { width: 900 - ModalContent { - title: qsTr("Fatal Error") + MultipageModalContent { + titleText: qsTr("Fatal Error") DefaultText { text: message === "connection dropped" ? qsTr("Connection has been lost. You have been disconnected.") : diff --git a/atomic_defi_design/Dex/Dashboard/NewUpdateModal.qml b/atomic_defi_design/Dex/Dashboard/NewUpdateModal.qml index 0e7fe689f6..a79589df4d 100644 --- a/atomic_defi_design/Dex/Dashboard/NewUpdateModal.qml +++ b/atomic_defi_design/Dex/Dashboard/NewUpdateModal.qml @@ -4,11 +4,11 @@ import QtQuick.Layouts 1.15 //> Layout.fillWidth import QtQuick.Controls 2.15 //> ProgressBar // Project imports -import "../Components" //> BasicModal +import "../Components" //> MultipageModal import "../Constants" import App 1.0 //> API.app.self_update_service -BasicModal +MultipageModal { id: root @@ -67,9 +67,9 @@ BasicModal onInvalid_update_filesChanged: select_index() // Section when fetching update - ModalContent + MultipageModalContent { - title: qsTr("Searching new updates...") + titleText: qsTr("Searching new updates...") titleAlignment: Label.AlignHCenter DefaultText @@ -80,9 +80,9 @@ BasicModal } // Section when no new update is found. - ModalContent + MultipageModalContent { - title: qsTr("Already updated") + titleText: qsTr("Already updated") titleAlignment: Label.AlignHCenter @@ -104,9 +104,9 @@ BasicModal } // Second section. Asks user to update its client. - ModalContent + MultipageModalContent { - title: qsTr("New update detected !") + titleText: qsTr("New update detected !") DefaultText { @@ -134,9 +134,9 @@ BasicModal } // Download progress bar - ModalContent + MultipageModalContent { - title: qsTr("Download in progress...") + titleText: qsTr("Download in progress...") RowLayout { @@ -157,9 +157,9 @@ BasicModal } // Update download finished... Asks for restart - ModalContent + MultipageModalContent { - title: qsTr("Update downloaded") + titleText: qsTr("Update downloaded") DefaultText { diff --git a/atomic_defi_design/Dex/Exchange/Trade/ConfirmMultiOrderTradeModal.qml b/atomic_defi_design/Dex/Exchange/Trade/ConfirmMultiOrderTradeModal.qml index 7959856df1..be005b5314 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/ConfirmMultiOrderTradeModal.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/ConfirmMultiOrderTradeModal.qml @@ -9,7 +9,7 @@ import ".." import "Orders/" -BasicModal { +MultipageModal { id: root width: 1100 @@ -20,8 +20,8 @@ BasicModal { } - ModalContent { - title: qsTr("Confirm Multi Order Details") + MultipageModalContent { + titleText: qsTr("Confirm Multi Order Details") DefaultListView { id: list diff --git a/atomic_defi_design/Dex/Exchange/Trade/ConfirmTradeModal.qml b/atomic_defi_design/Dex/Exchange/Trade/ConfirmTradeModal.qml index cb967dde1f..f315edd17f 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/ConfirmTradeModal.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/ConfirmTradeModal.qml @@ -1,93 +1,69 @@ import QtQuick 2.15 import QtQuick.Layouts 1.15 import QtQuick.Controls 2.15 -import AtomicDEX.TradingError 1.0 +import AtomicDEX.TradingError 1.0 import "../../Components" import "../../Constants" import ".." - import "Orders/" - import App 1.0 +import Dex.Themes 1.0 as Dex -BasicModal +MultipageModal { id: root width: 650 + readonly property var fees: API.app.trading_pg.fees - ModalContent + MultipageModalContent { - title: qsTr("Confirm Exchange Details") + titleText: qsTr("Confirm Exchange Details") OrderContent { - Layout.topMargin: 10 Layout.fillWidth: true - Layout.leftMargin: 20 - Layout.rightMargin: Layout.leftMargin - height: 50 - Layout.alignment: Qt.AlignHCenter - - details: ({ - base_coin: base_ticker, - rel_coin: rel_ticker, - base_amount: base_amount, - rel_amount: rel_amount, - - order_id: '', - date: '', - }) - in_modal: true + details: + ({ + base_coin: base_ticker, + rel_coin: rel_ticker, + base_amount: base_amount, + rel_amount: rel_amount, + order_id: '', + date: '', + }) } - Column - { - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: 500 - PriceLineSimplified { - width: 500 - } - } + PriceLineSimplified { Layout.fillWidth: true } HorizontalLine { - Layout.topMargin: 5 - Layout.bottomMargin: 5 Layout.fillWidth: true } - Column + ColumnLayout { - Layout.preferredWidth: 500 - Layout.alignment: Qt.AlignHCenter - Layout.bottomMargin: 5 + Layout.fillWidth: true - ColumnLayout + DefaultText { - id: warning_texts - width: 500 - - DexLabel - { - Layout.alignment: Qt.AlignLeft - text_value: qsTr("This swap request can not be undone and is a final event!") - } + Layout.alignment: Qt.AlignLeft + text_value: qsTr("This swap request can not be undone and is a final event!") + } - DexLabel - { - Layout.alignment: Qt.AlignLeft - text_value: qsTr("This transaction can take up to 60 mins - DO NOT close this application!") - font.pixelSize: Style.textSizeSmall4 - } + DefaultText + { + Layout.alignment: Qt.AlignLeft + text_value: qsTr("This transaction can take up to 60 mins - DO NOT close this application!") + font.pixelSize: Style.textSizeSmall4 } } Item { - Layout.preferredWidth: 500 + Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter Layout.preferredHeight: fees_detail.height + 10 opacity: .7 @@ -100,31 +76,27 @@ BasicModal Repeater { model: fees.base_transaction_fees_ticker && !API.app.trading_pg.preimage_rpc_busy ? General.getFeesDetail(fees) : [] - delegate: DefaultText { - visible: true + delegate: DefaultText + { font.pixelSize: Style.textSizeSmall1 text: General.getFeesDetailText(modelData.label, modelData.fee, modelData.ticker) } anchors.horizontalCenter: parent.horizontalCenter } - Item {width: 1; height: 10} Repeater { model: fees.base_transaction_fees_ticker ? fees.total_fees : [] - delegate: DefaultText { - visible: true + delegate: DefaultText + { text: General.getFeesDetailText( - qsTr("Total %1 fees:").arg(modelData.coin), - modelData.required_balance, - modelData.coin - ) + qsTr("Total %1 fees:").arg(modelData.coin), + modelData.required_balance, + modelData.coin) } - anchors.horizontalCenter: parent.horizontalCenter + anchors.horizontalCenter: parent.horizontalCenter } - Item {width: 1; height: 10} - } DefaultText { @@ -133,7 +105,7 @@ BasicModal width: parent.width horizontalAlignment: DefaultText.AlignHCenter font: DexTypo.caption - color: DexTheme.redColor + color: Dex.CurrentTheme.noColor text_value: General.getTradingError( last_trading_error, curr_fee_info, @@ -142,32 +114,38 @@ BasicModal } } - ColumnLayout { + ColumnLayout + { id: config_section readonly property var default_config: API.app.trading_pg.get_raw_mm2_coin_cfg(rel_ticker) readonly property bool is_dpow_configurable: config_section.default_config.requires_notarization || false + Layout.bottomMargin: 10 Layout.alignment: Qt.AlignHCenter - ColumnLayout { + ColumnLayout + { Layout.alignment: Qt.AlignHCenter visible: !enable_custom_config.checked - DefaultText { + DefaultText + { Layout.alignment: Qt.AlignHCenter text_value: qsTr("Security configuration") font.weight: Font.Medium } - DefaultText { + DefaultText + { Layout.alignment: Qt.AlignHCenter text_value: "✅ " + (config_section.is_dpow_configurable ? qsTr("dPoW protected") : qsTr("%1 confirmations for incoming %2 transactions").arg(config_section.default_config.required_confirmations || 1).arg(rel_ticker)) } - DefaultText { + DefaultText + { visible: config_section.is_dpow_configurable Layout.alignment: Qt.AlignHCenter text_value: General.cex_icon + ' ' + qsTr('Read more about dPoW') + '' @@ -176,22 +154,32 @@ BasicModal } // Enable custom config - DexCheckBox { + DexCheckBox + { Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + Layout.maximumWidth: config_section.width + id: enable_custom_config + spacing: 2 text: qsTr("Use custom protection settings for incoming %1 transactions", "TICKER").arg(rel_ticker) + boxWidth: 24 + boxHeight: 24 + label.horizontalAlignment: Text.AlignHCenter } // Configuration settings - ColumnLayout { + ColumnLayout + { id: custom_config visible: enable_custom_config.checked Layout.alignment: Qt.AlignHCenter // dPoW configuration switch - DefaultSwitch { + DefaultSwitch + { id: enable_dpow_confs Layout.alignment: Qt.AlignHCenter @@ -200,7 +188,8 @@ BasicModal text: qsTr("Enable Komodo dPoW security") } - DefaultText { + DefaultText + { visible: enable_dpow_confs.visible && enable_dpow_confs.enabled Layout.alignment: Qt.AlignHCenter text_value: General.cex_icon + ' ' + qsTr('Read more about dPoW') + '' @@ -208,18 +197,21 @@ BasicModal } // Normal configuration settings - ColumnLayout { + ColumnLayout + { Layout.alignment: Qt.AlignHCenter visible: !config_section.is_dpow_configurable || !enable_dpow_confs.checked enabled: !config_section.is_dpow_configurable || !enable_dpow_confs.checked - HorizontalLine { + HorizontalLine + { Layout.topMargin: 10 Layout.bottomMargin: 10 Layout.fillWidth: true } - DefaultText { + DefaultText + { Layout.preferredHeight: 10 Layout.alignment: Qt.AlignHCenter text_value: qsTr("Required Confirmations") + ": " + required_confirmation_count.value @@ -227,7 +219,8 @@ BasicModal opacity: parent.enabled ? 1 : .6 } - DexSlider { + DexSlider + { id: required_confirmation_count readonly property int default_confirmation_count: 3 Layout.alignment: Qt.AlignHCenter @@ -241,7 +234,8 @@ BasicModal } } - FloatingBackground { + FloatingBackground + { visible: enable_custom_config.visible && enable_custom_config.enabled && enable_custom_config.checked && (config_section.is_dpow_configurable && !enable_dpow_confs.checked) Layout.alignment: Qt.AlignHCenter @@ -252,64 +246,58 @@ BasicModal width: dpow_off_warning.width + 20 height: dpow_off_warning.height + 20 - ColumnLayout { + ColumnLayout + { id: dpow_off_warning anchors.centerIn: parent - DefaultText { + DefaultText + { Layout.alignment: Qt.AlignHCenter - color: Style.colorWhite0 text_value: Style.warningCharacter + " " + qsTr("Warning, this atomic swap is not dPoW protected!") } } } - DefaultBusyIndicator { + DefaultBusyIndicator + { visible: buy_sell_rpc_busy Layout.alignment: Qt.AlignCenter } } - HorizontalLine { - Layout.fillWidth: true - } - // Buttons - footer: [ - Item { - Layout.fillWidth: true - }, - DexAppButton { + + HorizontalLine { Layout.fillWidth: true } + + footer: + [ + Item { Layout.fillWidth: true }, + DexAppButton + { text: qsTr("Cancel") padding: 10 leftPadding: 45 rightPadding: 45 radius: 10 - onClicked: { - //fees = [] - root.close() - } + onClicked: root.close() }, - Item { - Layout.fillWidth: true - }, - DexGradientAppButton { + Item { Layout.fillWidth: true }, + DexGradientAppButton + { text: qsTr("Confirm") padding: 10 leftPadding: 45 rightPadding: 45 - radius: 10 enabled: !buy_sell_rpc_busy && last_trading_error === TradingError.None - onClicked: { - trade({ - enable_custom_config: enable_custom_config.checked, + onClicked: + { + trade({ enable_custom_config: enable_custom_config.checked, is_dpow_configurable: config_section.is_dpow_configurable, enable_dpow_confs: enable_dpow_confs.checked, - required_confirmation_count: required_confirmation_count.value, - }, config_section.default_config) + required_confirmation_count: required_confirmation_count.value, }, + config_section.default_config) } }, - Item { - Layout.fillWidth: true - } + Item { Layout.fillWidth: true } ] } } diff --git a/atomic_defi_design/Dex/Exchange/Trade/Orders/OrderContent.qml b/atomic_defi_design/Dex/Exchange/Trade/Orders/OrderContent.qml index 9cf267171b..839700621b 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/Orders/OrderContent.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/Orders/OrderContent.qml @@ -4,95 +4,133 @@ import QtQuick.Controls 2.15 import QtGraphicalEffects 1.0 -import App 1.0 - import Qaterial 1.0 as Qaterial +import App 1.0 import "../../../Components" +import "../../../Constants" +import Dex.Themes 1.0 as Dex + +RowLayout +{ + property var details + + DefaultRectangle + { + Layout.preferredWidth: 226 + Layout.preferredHeight: 66 + radius: 10 + + RowLayout + { + anchors.fill: parent + anchors.margins: 14 + spacing: 23 + + DefaultImage + { + Layout.preferredWidth: 35 + Layout.preferredHeight: 35 + Layout.alignment: Qt.AlignVCenter + + source: General.coinIcon(!details ? atomic_app_primary_coin : details.base_coin) + } + + ColumnLayout + { + Layout.fillWidth: true + RowLayout + { + Layout.fillWidth: true + spacing: 5 + DefaultText + { + Layout.fillWidth: true + text: details ? details.base_coin : "" + } -// Content -Item { - property - var details - property bool in_modal: false - - readonly property bool is_placed_order: !details ? false : - details.order_id !== '' - - RowLayout { - width: 500 - height: 60 - anchors.centerIn: parent - spacing: 23 - DexRectangle { - Layout.fillWidth: true - Layout.fillHeight: true - color: DexTheme.contentColorTop - RowLayout { - width: parent.width - 40 - height: 60 - anchors.centerIn: parent - spacing: 23 - DefaultImage { - id: base_icon - source: General.coinIcon(!details ? atomic_app_primary_coin : - details.base_coin) - Layout.preferredWidth: 40 - Layout.preferredHeight: 40 - Layout.alignment: Qt.AlignVCenter + DefaultText + { + Layout.fillWidth: true + text: details ? General.coinName(details.base_coin) : "" + wrapMode: Text.NoWrap + elide: Text.ElideRight + font.pixelSize: 11 + } } - DexLabel { - id: base_amount - text_value: !details ? "" : - "" + details.base_coin + "" - + " %1".arg(General.coinName(details.base_coin))+ "
" - + General.formatCrypto("", details.base_amount, details.base_coin).split(" ")[1] + "
" - + General.getFiatText(details.base_amount, details.base_coin, false) - font: DexTypo.body2 + DefaultText + { Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter - privacy: is_placed_order - opacity: .9 + text: details ? details.base_amount : "" + font.pixelSize: 11 + wrapMode: Text.NoWrap + elide: Text.ElideRight } } } + } - Qaterial.Icon { - color: DexTheme.foregroundColor - icon: Qaterial.Icons.swapHorizontal - Layout.alignment: Qt.AlignVCenter - } + Qaterial.Icon + { + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + + color: Dex.CurrentTheme.foregroundColor + icon: Qaterial.Icons.swapHorizontal + } + + DefaultRectangle + { + Layout.preferredWidth: 226 + Layout.preferredHeight: 66 + radius: 10 + + RowLayout + { + anchors.fill: parent + anchors.margins: 14 + spacing: 23 + + DefaultImage + { + Layout.preferredWidth: 35 + Layout.preferredHeight: 35 + Layout.alignment: Qt.AlignVCenter + + source: General.coinIcon(!details ? atomic_app_primary_coin : details.rel_coin) + } + + ColumnLayout + { + Layout.fillWidth: true + RowLayout + { + Layout.fillWidth: true + spacing: 5 + DefaultText + { + Layout.fillWidth: true + text: details ? details.rel_coin : "" + } - DexRectangle { - Layout.fillWidth: true - Layout.fillHeight: true - color: DexTheme.contentColorTop - RowLayout { - width: parent.width - 40 - height: 60 - anchors.centerIn: parent - spacing: 23 - DefaultImage { - id: rel_icon - source: General.coinIcon(!details ? atomic_app_primary_coin : - details.rel_coin) - Layout.preferredWidth: 40 - Layout.preferredHeight: 40 - Layout.alignment: Qt.AlignVCenter + DefaultText + { + Layout.fillWidth: true + text: details ? General.coinName(details.rel_coin) : "" + wrapMode: Text.NoWrap + elide: Text.ElideRight + font.pixelSize: 11 + } } - DexLabel { - id: rel_amount - text_value: !details ? "" : "" + details.rel_coin - + " %1
".arg(General.coinName(details.rel_coin)) - + General.formatCrypto("", details.rel_amount, details.rel_coin).split(" ")[1] + "
" - + General.getFiatText(details.rel_amount, details.rel_coin, false) - font: DexTypo.body2 + DefaultText + { Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter - privacy: is_placed_order - opacity: .9 + text: details ? details.rel_amount : "" + font.pixelSize: 11 + wrapMode: Text.NoWrap + elide: Text.ElideRight } } } diff --git a/atomic_defi_design/Dex/Exchange/Trade/Orders/OrderModal.qml b/atomic_defi_design/Dex/Exchange/Trade/Orders/OrderModal.qml index f230dc57ff..256d6f89fb 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/Orders/OrderModal.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/Orders/OrderModal.qml @@ -2,38 +2,39 @@ import QtQuick 2.15 import QtQuick.Layouts 1.15 import QtQuick.Controls 2.15 -import App 1.0 - import Qaterial 1.0 as Qaterial import "../../../Components" +import "../../../Constants" +import Dex.Themes 1.0 as Dex +import App 1.0 -BasicModal { +MultipageModal +{ id: root property var details - onDetailsChanged: { - if (!details) root.close() - } - + onDetailsChanged: { if (!details) root.close() } onOpened: swap_progress.updateSimulatedTime() - onClosed: details = undefined - ModalContent { - title: !details ? "" : details.is_swap ? qsTr("Swap Details") : qsTr("Order Details") + MultipageModalContent + { + titleText: !details ? "" : details.is_swap ? qsTr("Swap Details") : qsTr("Order Details") titleAlignment: Qt.AlignHCenter // Complete image - DefaultImage { + DefaultImage + { visible: !details ? false : details.is_swap && details.order_status === "successful" Layout.alignment: Qt.AlignHCenter source: General.image_path + "exchange-trade-complete.png" } // Loading symbol - DefaultBusyIndicator { + DefaultBusyIndicator + { visible: !details ? false : details.is_swap && details.order_status !== "successful" running: (!details ? false : details.is_swap && @@ -43,120 +44,264 @@ BasicModal { } // Status Text - DefaultText { + DefaultText + { Layout.alignment: Qt.AlignHCenter Layout.topMargin: 5 font.pixelSize: Style.textSize1 font.bold: true - visible: !details ? false : - details.is_swap || !details.is_maker - color: !details ? "white" : - visible ? getStatusColor(details.order_status) : '' - text_value: !details ? "" : - visible ? getStatusText(details.order_status) : '' + visible: !details ? false : details.is_swap || !details.is_maker + text_value: !details ? "" : visible ? getStatusText(details.order_status) : '' } - OrderContent { - Layout.topMargin: 25 - Layout.preferredWidth: 500 - Layout.alignment: Qt.AlignHCenter - Layout.preferredHeight: 66 - details: root.details - in_modal: true - } - - HorizontalLine { - Layout.fillWidth: true - Layout.bottomMargin: 20 - color: Style.colorWhite8 - } - - // Maker/Taker - DefaultText { - text_value: !details ? "" : details.is_maker ? qsTr("Maker Order") : qsTr("Taker Order") - color: Style.colorThemeDarkLight - Layout.alignment: Qt.AlignRight - } + RowLayout + { + Layout.topMargin: 22 + + DefaultRectangle + { + Layout.preferredWidth: 226 + Layout.preferredHeight: 66 + radius: 10 + + RowLayout + { + anchors.fill: parent + anchors.margins: 14 + spacing: 23 + + DefaultImage + { + Layout.preferredWidth: 35 + Layout.preferredHeight: 35 + Layout.alignment: Qt.AlignVCenter + + source: General.coinIcon(!details ? atomic_app_primary_coin : details.base_coin) + } + + ColumnLayout + { + Layout.fillWidth: true + RowLayout + { + Layout.fillWidth: true + spacing: 5 + DefaultText + { + Layout.fillWidth: true + text: details ? details.base_coin : "" + } + + DefaultText + { + Layout.fillWidth: true + text: details ? General.coinName(details.base_coin) : "" + wrapMode: Text.NoWrap + elide: Text.ElideRight + font.pixelSize: 11 + } + } + + DefaultText + { + Layout.fillWidth: true + text: details ? details.base_amount : "" + font.pixelSize: 11 + wrapMode: Text.NoWrap + elide: Text.ElideRight + } + } + } + } - // Refund state - TextFieldWithTitle { - Layout.topMargin: -20 + Qaterial.Icon + { + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter - title: qsTr("Refund State") - field.text: !details ? "" : - details.order_status === "refunding" ? qsTr("Your swap failed but the auto-refund process for your payment started already. Please wait and keep application opened until you receive your payment back") : "" - field.readOnly: true + color: Dex.CurrentTheme.foregroundColor + icon: Qaterial.Icons.swapHorizontal + } - visible: field.text !== '' + DefaultRectangle + { + Layout.preferredWidth: 226 + Layout.preferredHeight: 66 + radius: 10 + + RowLayout + { + anchors.fill: parent + anchors.margins: 14 + spacing: 23 + + DefaultImage + { + Layout.preferredWidth: 35 + Layout.preferredHeight: 35 + Layout.alignment: Qt.AlignVCenter + + source: General.coinIcon(!details ? atomic_app_primary_coin : details.rel_coin) + } + + ColumnLayout + { + Layout.fillWidth: true + RowLayout + { + Layout.fillWidth: true + spacing: 5 + DefaultText + { + Layout.fillWidth: true + text: details ? details.rel_coin : "" + } + + DefaultText + { + Layout.fillWidth: true + text: details ? General.coinName(details.rel_coin) : "" + wrapMode: Text.NoWrap + elide: Text.ElideRight + font.pixelSize: 11 + } + } + + DefaultText + { + Layout.fillWidth: true + text: details ? details.rel_amount : "" + font.pixelSize: 11 + wrapMode: Text.NoWrap + elide: Text.ElideRight + } + } + } + } } - // Date - TextEditWithTitle { - title: qsTr("Date") - text: !details ? "" : details.date - visible: text !== '' - } + DefaultScrollView + { + Layout.topMargin: 20 + Layout.fillWidth: true + Layout.preferredHeight: 300 + + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + + ColumnLayout + { + width: 400 + height: parent.height - 30 + spacing: 12 + + // Maker/Taker + TextEditWithTitle + { + Layout.fillWidth: true + title: qsTr("Order Type") + text: !details ? "" : details.is_maker ? qsTr("Maker Order") : qsTr("Taker Order") + label.font.pixelSize: 13 + } - // ID - TextEditWithTitle { - title: qsTr("ID") - text: !details ? "" : details.order_id - visible: text !== '' - copy: true - privacy: true - } + // Refund state + TextFieldWithTitle + { + Layout.fillWidth: true + title: qsTr("Refund State") + field.text: !details ? "" : details.order_status === "refunding" ? qsTr("Your swap failed but the auto-refund process for your payment started already. Please wait and keep application opened until you receive your payment back") : "" + field.readOnly: true + field.font.pixelSize: 13 + visible: field.text !== '' + } - // Payment ID - TextEditWithTitle { - title: !details ? "" : details.is_maker ? qsTr("Maker Payment Sent ID") : qsTr("Maker Payment Spent ID") - text: !details ? "" : details.maker_payment_id - visible: text !== '' - privacy: true - } + // Date + TextEditWithTitle + { + Layout.fillWidth: true + title: qsTr("Date") + text: !details ? "" : details.date + label.font.pixelSize: 13 + visible: text !== '' + } - // Payment ID - TextEditWithTitle { - title: !details ? "" : details.is_maker ? qsTr("Taker Payment Spent ID") : qsTr("Taker Payment Sent ID") - text: !details ? "" : details.taker_payment_id - visible: text !== '' - privacy: true - } + // ID + TextEditWithTitle + { + Layout.fillWidth: true + title: qsTr("ID") + text: !details ? "" : details.order_id + label.font.pixelSize: 13 + visible: text !== '' + copy: true + privacy: true + } - // Error ID - TextEditWithTitle { - title: qsTr("Error ID") - text: !details ? "" : details.order_error_state - visible: text !== '' - } + // Payment ID + TextEditWithTitle + { + Layout.fillWidth: true + title: !details ? "" : details.is_maker ? qsTr("Maker Payment Sent ID") : qsTr("Maker Payment Spent ID") + text: !details ? "" : details.maker_payment_id + label.font.pixelSize: 13 + visible: text !== '' + privacy: true + } - // Error Details - TextFieldWithTitle { - title: qsTr("Error Log") - field.text: !details ? "" : details.order_error_message - field.readOnly: true - copyable: true + // Payment ID + TextEditWithTitle + { + Layout.fillWidth: true + title: !details ? "" : details.is_maker ? qsTr("Taker Payment Spent ID") : qsTr("Taker Payment Sent ID") + text: !details ? "" : details.taker_payment_id + label.font.pixelSize: 13 + visible: text !== '' + privacy: true + } - visible: field.text !== '' - } + // Error ID + TextEditWithTitle + { + Layout.fillWidth: true + title: qsTr("Error ID") + text: !details ? "" : details.order_error_state + label.font.pixelSize: 13 + visible: text !== '' + } - HorizontalLine { - visible: swap_progress.visible - Layout.fillWidth: true - Layout.topMargin: 10 - Layout.bottomMargin: Layout.topMargin - color: Style.colorWhite8 - } + // Error Details + TextEditWithTitle + { + Layout.fillWidth: true + title: qsTr("Error Log") + text: !details ? "" : details.order_error_message + label.font.pixelSize: 13 + visible: text !== '' + copy: true + onCopyNotificationTitle: qsTr("Error Log") + } - SwapProgress { - id: swap_progress - visible: General.exists(details) && details.order_status !== "matching" - Layout.fillWidth: true - details: root.details + HorizontalLine + { + visible: swap_progress.visible + Layout.fillWidth: true + Layout.topMargin: 10 + } + + SwapProgress + { + id: swap_progress + visible: General.exists(details) && details.order_status !== "matching" + Layout.fillWidth: true + details: root.details + } + } } // Buttons - footer: [ - DexAppButton { + footer: + [ + DexAppButton + { text: qsTr("Close") leftPadding: 20 rightPadding: 20 @@ -165,7 +310,8 @@ BasicModal { }, // Cancel button - DexAppOutlineButton { + DexAppOutlineButton + { id: cancelOrderButton visible: !details ? false : details.cancellable leftPadding: 20 @@ -175,13 +321,15 @@ BasicModal { onClicked: cancelOrder(details.order_id) }, - Item { + Item + { visible: !cancelOrderButton.visible Layout.fillWidth: true }, // Recover Funds button - DexAppButton { + DexAppButton + { id: refundButton leftPadding: 20 rightPadding: 20 @@ -193,19 +341,21 @@ BasicModal { onClicked: API.app.orders_mdl.recover_fund(details.order_id) }, - Item { + Item + { visible: !refundButton.visible & !cancelOrderButton.visible Layout.fillWidth: true }, - - DexAppOutlineButton { + DexAppOutlineButton + { text: qsTr("View on Explorer") leftPadding: 20 rightPadding: 20 radius: 18 visible: !details ? false : details.maker_payment_id !== '' || details.taker_payment_id !== '' - onClicked: { + onClicked: + { if (!details) return const maker_id = details.maker_payment_id diff --git a/atomic_defi_design/Dex/Exchange/Trade/PriceLineSimplified.qml b/atomic_defi_design/Dex/Exchange/Trade/PriceLineSimplified.qml index 79d17208d3..3dbe24e2d0 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/PriceLineSimplified.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/PriceLineSimplified.qml @@ -4,12 +4,11 @@ import QtQuick.Controls 2.15 import "../../Components" import "../../Constants" - import App 1.0 +import Dex.Themes 1.0 as Dex -// Price -ColumnLayout { - +ColumnLayout +{ readonly property string price: non_null_price readonly property string price_reversed: API.app.trading_pg.price_reversed readonly property string cex_price: API.app.trading_pg.cex_price @@ -22,58 +21,63 @@ ColumnLayout { readonly property int fontSizeBigger: Style.textSizeSmall2 readonly property int line_scale: getComparisonScale(cex_price_diff) - function getComparisonScale(value) { + function getComparisonScale(value) + { return Math.min(Math.pow(10, General.getDigitCount(parseFloat(value))), 1000000000) } - function limitDigits(value) { + function limitDigits(value) + { return parseFloat(General.formatDouble(value, 2)) } + spacing: 35 - - DexLabel { + DefaultText + { visible: !price_entered && invalid_cex_price Layout.alignment: Qt.AlignHCenter text_value: qsTr("Set swap price for evaluation") font.pixelSize: fontSizeBigger } - spacing: 35 - RowLayout { - Layout.preferredWidth: 500 + + RowLayout + { + Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter - ColumnLayout { + ColumnLayout + { visible: price_entered - DexLabel { - Layout.alignment: Qt.AlignLeft + DefaultText + { text_value: qsTr("Exchange rate") + (preffered_order.price !== undefined ? (" (" + qsTr("Selected") + ")") : "") font.pixelSize: fontSize } // Price reversed - DexLabel { - Layout.alignment: Qt.AlignLeft + DefaultText + { text_value: General.formatCrypto("", "1", right_ticker) + " = " + General.formatCrypto("", price_reversed, left_ticker) font.pixelSize: fontSizeBigger font.weight: Font.Medium } // Price - DexLabel { - Layout.alignment: Qt.AlignLeft + DefaultText + { text_value: General.formatCrypto("", price, right_ticker) + " = " + General.formatCrypto("", "1", left_ticker) font.pixelSize: fontSize } } - Item { - Layout.fillWidth: true - } + Item { Layout.fillWidth: true } - ColumnLayout { + ColumnLayout + { visible: !invalid_cex_price - DexLabel { + DefaultText + { Layout.alignment: Qt.AlignRight text_value: General.cex_icon + " " + qsTr("CEXchange rate") font.pixelSize: fontSize @@ -82,7 +86,8 @@ ColumnLayout { } // Price reversed - DexLabel { + DefaultText + { Layout.alignment: Qt.AlignRight text_value: General.formatCrypto("", "1", right_ticker) + " = " + General.formatCrypto("", cex_price_reversed, left_ticker) font.pixelSize: fontSizeBigger @@ -90,7 +95,8 @@ ColumnLayout { } // Price - DexLabel { + DefaultText + { Layout.alignment: Qt.AlignRight text_value: General.formatCrypto("", cex_price, right_ticker) + " = " + General.formatCrypto("", "1", left_ticker) font.pixelSize: fontSize @@ -100,21 +106,25 @@ ColumnLayout { // Price Comparison - ColumnLayout { + ColumnLayout + { visible: price_entered && !invalid_cex_price Layout.alignment: Qt.AlignHCenter - RowLayout { + RowLayout + { Layout.fillWidth: true - GradientRectangle { - width: 500 - height: 6 + GradientRectangle + { + Layout.fillWidth: true + Layout.preferredHeight: 6 - start_color: DexTheme.greenColor - end_color: DexTheme.redColor + start_color: Dex.CurrentTheme.okColor + end_color: Dex.CurrentTheme.noColor - AnimatedRectangle { + AnimatedRectangle + { width: 4 height: parent.height * 2 anchors.verticalCenter: parent.verticalCenter @@ -122,14 +132,16 @@ ColumnLayout { anchors.horizontalCenterOffset: 0.5 * parent.width * Math.min(Math.max(parseFloat(cex_price_diff) / line_scale, -1), 1) } - DexLabel { + DefaultText + { text_value: General.formatPercent(line_scale) font.pixelSize: fontSize anchors.top: parent.top anchors.topMargin: -15 } - DexLabel { + DefaultText + { text_value: General.formatPercent(-line_scale) font.pixelSize: fontSize anchors.top: parent.top @@ -139,19 +151,14 @@ ColumnLayout { } } - DexLabel { + DefaultText + { id: price_diff_text Layout.topMargin: 10 - Layout.bottomMargin: Layout.topMargin Layout.alignment: Qt.AlignHCenter - color: parseFloat(cex_price_diff) <= 0 ? DexTheme.greenColor : DexTheme.redColor + color: parseFloat(cex_price_diff) <= 0 ? Dex.CurrentTheme.okColor : Dex.CurrentTheme.noColor text_value: (parseFloat(cex_price_diff) > 0 ? qsTr("Expensive") : qsTr("Expedient")) + ":    " + qsTr("%1 compared to CEX", "PRICE_DIFF%").arg("" + General.formatPercent(limitDigits(cex_price_diff)) + "") font.pixelSize: fontSize } - - } - - // CEXchange - } diff --git a/atomic_defi_design/Dex/Exchange/Trade/ProView.qml b/atomic_defi_design/Dex/Exchange/Trade/ProView.qml index 01205741b8..f5a9b3f377 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/ProView.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/ProView.qml @@ -34,10 +34,16 @@ import Dex.Themes 1.0 as Dex import "../ProView" -ColumnLayout { +ColumnLayout +{ id: form property alias dexConfig: dex_config_popup - function selectOrder(is_asks, coin, price, quantity, price_denom, price_numer, quantity_denom, quantity_numer, min_volume, base_min_volume, base_max_volume, rel_min_volume, rel_max_volume, base_max_volume_denom, base_max_volume_numer, uuid) { + function selectOrder(is_asks, coin, price, quantity, price_denom, + price_numer, quantity_denom, quantity_numer, + min_volume, base_min_volume, base_max_volume, + rel_min_volume, rel_max_volume, base_max_volume_denom, + base_max_volume_numer, uuid) + { setMarketMode(!is_asks ? MarketMode.Sell : MarketMode.Buy) API.app.trading_pg.preffered_order = { @@ -60,15 +66,19 @@ ColumnLayout { form_base.focusVolumeField() } - Connections { + + Connections + { target: exchange_trade - function onBuy_sell_rpc_busyChanged() { + function onBuy_sell_rpc_busyChanged() + { if (buy_sell_rpc_busy) return const response = General.clone(buy_sell_last_rpc_data) - if (response.error_code) { + if (response.error_code) + { confirm_trade_modal.close() toast.show(qsTr("Failed to place the order"), @@ -76,7 +86,9 @@ ColumnLayout { response.error_message) return - } else if (response.result && response.result.uuid) { + } + else if (response.result && response.result.uuid) + { // Make sure there is information confirm_trade_modal.close() @@ -88,27 +100,35 @@ ColumnLayout { } } } - spacing: 10 - anchors.topMargin: 20 - anchors.leftMargin: 10 - anchors.fill: parent - Connections { + + Connections + { target: app - function onPairChanged(base, rel) { + function onPairChanged(base, rel) + { dex_chart.visible = true } } - DexBoxManager { + spacing: 10 + anchors.topMargin: 20 + anchors.leftMargin: 10 + anchors.fill: parent + + DexBoxManager + { id: splitView Layout.fillWidth: true Layout.fillHeight: true itemLists: [left_section, order_form] spacing: 15 + handle: Item { implicitWidth: 2 implicitHeight: 4 - Rectangle { + + Rectangle + { implicitWidth: 2 implicitHeight: 4 anchors.centerIn: parent @@ -117,7 +137,8 @@ ColumnLayout { } } - DexTradeBox { + DexTradeBox + { id: left_section minimumWidth: 500 defaultWidth: 520 @@ -125,7 +146,9 @@ ColumnLayout { hideHeader: true SplitView.fillHeight: true color: 'transparent' - DexBoxManager { + + DexBoxManager + { anchors.fill: parent anchors.margins: 0 anchors.rightMargin: 0 @@ -140,35 +163,48 @@ ColumnLayout { opacity: 0.4 } } + itemLists: [dex_chart, optionBox] - DexTradeBox { + + DexTradeBox + { id: dex_chart title: qsTr("Chart") expandedVert: dex_chart.visible? true : false - onVisibleChanged: { - if(visible) { + onVisibleChanged: + { + if(visible) + { expandedVert = true } } canBeFull: true - onFullScreenChanged: { - if(fullScreen){ + onFullScreenChanged: + { + if(fullScreen) + { _best_order_box.visible = false _orderbook_box.visible = false optionBox.visible = false order_form.visible = false - } else { + } + else + { _best_order_box.visible = true _orderbook_box.visible = true optionBox.visible = true order_form.visible = true } } - Item { + + Item + { id: chart_view anchors.fill: parent anchors.topMargin: 40 - CandleStickChart { + + CandleStickChart + { id: candleChart color: 'transparent' anchors.fill: parent @@ -179,6 +215,7 @@ ColumnLayout { dashboard.webEngineView.parent = chart_view; dashboard.webEngineView.anchors.fill = chart_view; } + Component.onDestruction: { dashboard.webEngineView.visible = false; @@ -186,6 +223,7 @@ ColumnLayout { } } } + DexTradeBox { canBeFull: true @@ -193,6 +231,7 @@ ColumnLayout { maximumHeight: 80 minimumHeight: 75 color: 'transparent' + RowLayout { id: selectors @@ -200,6 +239,7 @@ ColumnLayout { anchors.fill: parent anchors.rightMargin: 10 anchors.leftMargin: 10 + TickerSelector { id: selector_left @@ -274,6 +314,7 @@ ColumnLayout { height: parent.height clip: !parent.contentVisible anchors.horizontalCenter: parent.horizontalCenter + Qaterial.LatoTabBar { property int taux_exchange: 0 @@ -300,6 +341,7 @@ ColumnLayout { indicatorColor: Dex.CurrentTheme.tabSelectedColor opacity: checked ? 1 : .6 } + Qaterial.LatoTabButton { width: 120 @@ -310,6 +352,7 @@ ColumnLayout { indicatorColor: Dex.CurrentTheme.tabSelectedColor opacity: checked ? 1 : .6 } + Qaterial.LatoTabButton { width: 120 @@ -321,12 +364,14 @@ ColumnLayout { opacity: checked ? 1 : .6 } } + Item { id: swipeContainer anchors.horizontalCenter: parent.horizontalCenter width: parent.width height: optionBox.height - (tabView.height + 40) + SwipeView { id: swipeView @@ -334,6 +379,7 @@ ColumnLayout { interactive: false currentIndex: tabView.currentIndex anchors.fill: parent + onCurrentIndexChanged: { swipeView.currentItem.update(); @@ -349,6 +395,7 @@ ColumnLayout { } OrdersView.OrdersPage { id: order_component; clip: true } + OrdersView.OrdersPage { id: history_component @@ -362,17 +409,21 @@ ColumnLayout { Item { SplitView.maximumHeight: 1 } } } - Item { + + Item + { id: _book_and_best property bool showing: (_best_order_box.visible || _orderbook_box.visible) SplitView.minimumWidth: showing ? 390 : 0 SplitView.maximumWidth: showing ? 430 : 0 SplitView.preferredWidth: showing ? 390 : 0 clip: true - DexBoxManager { + DexBoxManager + { anchors.fill: parent orientation: Qt.Vertical - handle: Item { + handle: Item + { implicitWidth: 40 implicitHeight: 6 InnerBackground { @@ -382,7 +433,9 @@ ColumnLayout { opacity: 0.4 } } + itemLists: [_orderbook_box, _best_order_box] + DexTradeBox { id: _orderbook_box @@ -390,6 +443,7 @@ ColumnLayout { closable: true title: qsTr("Order Book") expandedVert: true + Behavior on SplitView.preferredWidth { NumberAnimation @@ -397,6 +451,7 @@ ColumnLayout { duration: 100 } } + OrderBook.Vertical { clip: !parent.contentVisible @@ -405,7 +460,9 @@ ColumnLayout { anchors.fill: parent } } - DexTradeBox { + + DexTradeBox + { id: _best_order_box defaultHeight: 250 @@ -446,41 +503,49 @@ ColumnLayout { minimumWidth: isBigScreen ? 290 : 280 expandable: false SplitView.fillHeight: true + ColumnLayout { visible: parent.contentVisible anchors.topMargin: 60 anchors.fill: parent + Row { width: parent.width spacing: 10 Layout.alignment: Qt.AlignHCenter + MarketModeSelector { marketMode: MarketMode.Buy ticker: atomic_qt_utilities.retrieve_main_ticker(left_ticker) } + MarketModeSelector { ticker: atomic_qt_utilities.retrieve_main_ticker(left_ticker) } } + Item { Layout.fillWidth: true Layout.fillHeight: true + ColumnLayout { property int space: 10 anchors.fill: parent anchors.topMargin: 5 spacing: 10 + Item { Layout.fillWidth: true Layout.preferredHeight: 40 visible: API.app.trading_pg.preffered_order.price !== undefined + Rectangle { width: parent.width - 20 @@ -600,10 +665,12 @@ ColumnLayout { } } - ModalLoader { + ModalLoader + { id: confirm_trade_modal sourceComponent: ConfirmTradeModal {} } + DexPopup { id: dex_config_popup @@ -626,6 +693,7 @@ ColumnLayout { { implicitWidth: 320 implicitHeight: 190 + Column { anchors.fill: parent @@ -637,42 +705,56 @@ ColumnLayout { text: "Display Settings" font: DexTypo.body2 } + HorizontalLine { width: parent.width-20;anchors.horizontalCenter: parent.horizontalCenter;opacity: .4 } + DexCheckEye { text: "Trading Information" targetProperty: "visible" target: optionBox } + HorizontalLine { width: parent.width-20;anchors.horizontalCenter: parent.horizontalCenter;opacity: .4 } + DexCheckEye { text: "Order Book" targetProperty: "visible" target: _orderbook_box } + HorizontalLine { width: parent.width-20;anchors.horizontalCenter: parent.horizontalCenter;opacity: .4 } - DexCheckEye { + + DexCheckEye + { text: "Best Order" targetProperty: "visible" target: _best_order_box } + HorizontalLine { width: parent.width-20;anchors.horizontalCenter: parent.horizontalCenter;opacity: .4 } - DexCheckEye { + + DexCheckEye + { id: place_visibility text: "Place Order" targetProperty: "visible" target: order_form } } - Component.onCompleted: { + + Component.onCompleted: + { dex_chart.visible = proview_settings.chart_visibility optionBox.visible = proview_settings.option_visibility _orderbook_box.visible = proview_settings.orderbook_visibility _best_order_box.visible = proview_settings.best_order_visibility order_form.visible = proview_settings.form_visibility } - Component.onDestruction: { + + Component.onDestruction: + { proview_settings.form_visibility = order_form.visible proview_settings.chart_visibility = dex_chart.visible proview_settings.option_visibility = optionBox.visible @@ -681,6 +763,4 @@ ColumnLayout { } } } - - } diff --git a/atomic_defi_design/Dex/Exchange/Trade/SimpleView/Main.qml b/atomic_defi_design/Dex/Exchange/Trade/SimpleView/Main.qml index 0a8222963e..4880ce3c64 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/SimpleView/Main.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/SimpleView/Main.qml @@ -17,7 +17,6 @@ import Dex.Themes 1.0 as Dex Item { id: root - readonly property var subPages: Main.getSubPages() // Variable which holds the current sub-page of the SimpleView. @@ -77,6 +76,7 @@ Item Behavior on x { NumberAnimation { duration: 150 } } } + RowLayout { anchors.fill: parent @@ -144,6 +144,7 @@ Item } } } + Item { FloatingBackground @@ -159,6 +160,7 @@ Item SubOrders { id: orders_view } } } + Item { FloatingBackground diff --git a/atomic_defi_design/Dex/Exchange/Trade/SimpleView/OrderRemovedModal.qml b/atomic_defi_design/Dex/Exchange/Trade/SimpleView/OrderRemovedModal.qml index 1f6c076f14..dc49f96c39 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/SimpleView/OrderRemovedModal.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/SimpleView/OrderRemovedModal.qml @@ -1,16 +1,22 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 + import "../../../Components" import "../../../Constants" -BasicModal +MultipageModal { id: root width: 1000 - ModalContent + MultipageModalContent { - title: qsTr("Selected Order Removed") + titleText: qsTr("Selected Order Removed") DefaultText { + Layout.fillWidth: true + + wrapMode: Text.WordWrap text: qsTr("The selected order does not exist anymore, it might have been matched or canceled, and no order with a better price is available.\nPlease select a new order.") } diff --git a/atomic_defi_design/Dex/Exchange/Trade/SimpleView/SubBestOrder.qml b/atomic_defi_design/Dex/Exchange/Trade/SimpleView/SubBestOrder.qml index 6059a279c8..d785923592 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/SimpleView/SubBestOrder.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/SimpleView/SubBestOrder.qml @@ -6,7 +6,7 @@ import QtQuick.Controls 2.15 //> ItemDelegate import App 1.0 //! Project Imports -import "../../../Components" //> BasicModal +import "../../../Components" //> MultipageModal import "../../../Constants" as Constants //> API import Dex.Themes 1.0 as Dex diff --git a/atomic_defi_design/Dex/Exchange/Trade/SimpleView/SubCoinSelector.qml b/atomic_defi_design/Dex/Exchange/Trade/SimpleView/SubCoinSelector.qml index aa4c69019d..da89721846 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/SimpleView/SubCoinSelector.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/SimpleView/SubCoinSelector.qml @@ -9,7 +9,7 @@ import Qaterial 1.0 as Qaterial import App 1.0 //! Project Imports -import "../../../Components" //> BasicModal +import "../../../Components" //> MultipageModal import "../../../Constants" as Constants //> API import Dex.Themes 1.0 as Dex diff --git a/atomic_defi_design/Dex/Exchange/Trade/SimpleView/Trade.qml b/atomic_defi_design/Dex/Exchange/Trade/SimpleView/Trade.qml index 632a710cd3..a4a8d89cec 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/SimpleView/Trade.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/SimpleView/Trade.qml @@ -19,14 +19,14 @@ ClipRRect // Trade Card { id: _tradeCard - property string selectedTicker: !Constants.API.app.portfolio_pg.global_cfg_mdl.get_coin_info(left_ticker).is_testnet && - left_ticker !== "RICK" && left_ticker !== "MORTY" ? - left_ticker : "" + property string selectedTicker: API.app.get_balance(left_ticker) > 0 ? left_ticker : "" property var selectedOrder: undefined property bool best: false property bool coinSelection: false + property bool has_coins_with_balance: API.app.has_coins_with_balance() onSelectedTickerChanged: { selectedOrder = undefined; setPair(true, selectedTicker); _fromValue.text = "" } + onSelectedOrderChanged: { if (typeof selectedOrder !== 'undefined' && selectedOrder.from_best_order) Constants.API.app.trading_pg.orderbook.select_best_order(selectedOrder.uuid) @@ -35,6 +35,7 @@ ClipRRect // Trade Card Constants.API.app.trading_pg.determine_fees() } + onEnabledChanged: selectedOrder = undefined Component.onDestruction: selectedOrder = undefined Component.onCompleted: _fromValue.forceActiveFocus() @@ -142,6 +143,7 @@ ClipRRect // Trade Card leftPadding: 20 topPadding: 20 spacing: 15 + DexLabel // Title { text: qsTr("Swap") @@ -189,12 +191,13 @@ ClipRRect // Trade Card } } } + DexLabel // Title { text: qsTr("You have no tradable assets.") font: DexTypo.head6 opacity: .85 - visible: parseFloat(API.app.portfolio_pg.balance_fiat_all) == 0 + visible: !has_coins_with_balance } } @@ -217,7 +220,7 @@ ClipRRect // Trade Card Layout.preferredHeight: 90 Layout.alignment: Qt.AlignHCenter radius: 20 - visible: !coinSelectorSimplified.visible && parseFloat(API.app.portfolio_pg.balance_fiat_all) > 0 + visible: !coinSelectorSimplified.visible && has_coins_with_balance DefaultText // From Text { @@ -230,7 +233,6 @@ ClipRRect // Trade Card font.pixelSize: Constants.Style.textSizeSmall4 } - Text // Tradable Balance { readonly property int _maxWidth: 140 @@ -285,6 +287,7 @@ ClipRRect // Trade Card { id: _fromValue enabled: selectedTicker !== "" + visible: enabled anchors.bottom: parent.bottom anchors.bottomMargin: 19 anchors.left: parent.left @@ -304,6 +307,7 @@ ClipRRect // Trade Card } else Constants.API.app.trading_pg.volume = text } + onFocusChanged: { if (!focus && parseFloat(text) < parseFloat(Constants.API.app.trading_pg.min_trade_vol)) @@ -317,6 +321,7 @@ ClipRRect // Trade Card Text // Amount In Fiat { enabled: _fromValue.text + visible: enabled anchors.top: _fromValue.bottom anchors.topMargin: -3 anchors.left: _fromValue.left @@ -433,7 +438,7 @@ ClipRRect // Trade Card DefaultBusyIndicator { anchors.centerIn: parent - visible: Constants.API.app.trading_pg.max_volume == 0 + visible: selectedTicker !== "" && Constants.API.app.trading_pg.max_volume == 0 } } @@ -447,7 +452,7 @@ ClipRRect // Trade Card color: DexTheme.tradeFieldBoxBackgroundColor visible: !bestOrderSimplified.visible && !coinSelectorSimplified.visible - && parseFloat(API.app.portfolio_pg.balance_fiat_all) > 0 + && has_coins_with_balance DefaultText { @@ -563,15 +568,12 @@ ClipRRect // Trade Card anchors.verticalCenterOffset: -5 anchors.left: _bestOrderIcon.right anchors.leftMargin: 10 - width: 60 text: enabled ? atomic_qt_utilities.retrieve_main_ticker(selectedOrder.coin) : "" font.pixelSize: Constants.Style.textSizeSmall2 - wrapMode: Text.NoWrap - DefaultText { id: _bestOrderTickerTypeText @@ -611,7 +613,7 @@ ClipRRect // Trade Card visible: enabled && !bestOrderSimplified.visible && !coinSelectorSimplified.visible - && parseFloat(API.app.portfolio_pg.balance_fiat_all) > 0 + && has_coins_with_balance DefaultText { @@ -619,6 +621,7 @@ ClipRRect // Trade Card font.pixelSize: Constants.Style.textSizeSmall3 text: qsTr("Price") } + DefaultText { Layout.alignment: Qt.AlignRight @@ -639,7 +642,7 @@ ClipRRect // Trade Card Layout.preferredHeight: 50 visible: !bestOrderSimplified.visible && !coinSelectorSimplified.visible - && parseFloat(API.app.portfolio_pg.balance_fiat_all) > 0 + && has_coins_with_balance DexGradientAppButton { @@ -694,7 +697,6 @@ ClipRRect // Trade Card } } - // Send button error icon DefaultAlertIcon { @@ -738,16 +740,19 @@ ClipRRect // Trade Card } } } + Item { id: coinSelectorSimplified width: parent.width height: 300 - visible: _tradeCard.coinSelection && parseFloat(API.app.portfolio_pg.balance_fiat_all) > 0 + visible: _tradeCard.coinSelection && has_coins_with_balance + Item { width: parent.width height: 50 + Qaterial.ColorIcon { anchors.verticalCenter: parent.verticalCenter @@ -756,6 +761,7 @@ ClipRRect // Trade Card x: 25 opacity: .7 } + DexTextField { id: _coinSearchField @@ -764,17 +770,20 @@ ClipRRect // Trade Card font.pixelSize: 16 x: 45 placeholderText: qsTr("Search") + background: DexRectangle { border.width: 0 color: 'transparent' } + onTextChanged: { _coinList.model.setFilterFixedString(text) } } } + Connections { target: _tradeCard function onCoinSelectionChanged() { @@ -799,18 +808,20 @@ ClipRRect // Trade Card anchors.bottomMargin: 10 anchors.topMargin: 50 } - } + Item { id: bestOrderSimplified width: parent.width height: 300 - visible: _tradeCard.best && parseFloat(API.app.portfolio_pg.balance_fiat_all) > 0 + visible: _tradeCard.best && has_coins_with_balance + Item { width: parent.width height: 50 + Qaterial.ColorIcon { anchors.verticalCenter: parent.verticalCenter @@ -819,6 +830,7 @@ ClipRRect // Trade Card opacity: .7 color: Dex.CurrentTheme.textPlaceholderColor } + DexTextField { id: _bestOrderSearchField @@ -827,33 +839,39 @@ ClipRRect // Trade Card font.pixelSize: 16 x: 45 placeholderText: qsTr("Search") + background: DexRectangle { border.width: 0 color: 'transparent' } + onTextChanged: { Constants.API.app.trading_pg.orderbook.best_orders.proxy_mdl.setFilterFixedString(text) } } } + Connections { target: _tradeCard function onBestChanged() { _bestOrderSearchField.text = "" } } + SubBestOrder { id: _bestOrderList tradeCard: _tradeCard + onSelectedOrderChanged: { _tradeCard.selectedOrder = selectedOrder _bestOrderSearchField.text = "" _fromValue.forceActiveFocus() } + onBestChanged: { if(!best) @@ -861,6 +879,7 @@ ClipRRect // Trade Card _tradeCard.best = false } } + anchors.fill: parent anchors.rightMargin: 10 anchors.leftMargin: 20 @@ -868,6 +887,7 @@ ClipRRect // Trade Card anchors.topMargin: 50 visible: _tradeCard.width == 600 } + DefaultBusyIndicator { id: bestOrdersLoading @@ -907,7 +927,7 @@ ClipRRect // Trade Card && parseFloat(_fromValue.text) > 0 && !bestOrderSimplified.visible && !coinSelectorSimplified.visible - && parseFloat(API.app.portfolio_pg.balance_fiat_all) > 0 + && has_coins_with_balance && !_swapAlert.visible DexRectangle { @@ -932,8 +952,10 @@ ClipRRect // Trade Card visible: { return !Constants.API.app.trading_pg.preimage_rpc_busy } + enabled: parent.enabled model: Constants.API.app.trading_pg.fees.total_fees + delegate: RowLayout { width: _feesCard.width @@ -947,6 +969,7 @@ ClipRRect // Trade Card text: qsTr("Total %1 fees: ").arg(modelData.coin) font.pixelSize: Constants.Style.textSizeSmall3 } + DefaultText { Layout.alignment: Qt.AlignRight @@ -970,6 +993,7 @@ ClipRRect // Trade Card } } } + Row { anchors.rightMargin: 15 @@ -977,7 +1001,8 @@ ClipRRect // Trade Card height: 50 spacing: 5 y: 12 - visible: parseFloat(API.app.portfolio_pg.balance_fiat_all) > 0 + visible: has_coins_with_balance + DexAppButton { visible: _tradeCard.best @@ -993,6 +1018,7 @@ ClipRRect // Trade Card Constants.API.app.trading_pg.orderbook.refresh_best_orders() } } + DexAppButton { visible: _tradeCard.best || _tradeCard.coinSelection @@ -1002,6 +1028,7 @@ ClipRRect // Trade Card anchors.verticalCenter: parent.verticalCenter width: 35 height: 25 + onClicked: { _tradeCard.best = false diff --git a/atomic_defi_design/Dex/Exchange/Trade/Trading/TradeViewHeader.qml b/atomic_defi_design/Dex/Exchange/Trade/Trading/TradeViewHeader.qml index a8806ae50b..80ebe2e2c9 100644 --- a/atomic_defi_design/Dex/Exchange/Trade/Trading/TradeViewHeader.qml +++ b/atomic_defi_design/Dex/Exchange/Trade/Trading/TradeViewHeader.qml @@ -72,6 +72,7 @@ Item } } } + Item { Layout.fillHeight: true @@ -86,9 +87,10 @@ Item y: -10 width: 40 height: 25 - visible: API.app.trading_pg.current_trading_mode == TradingMode.Pro + enabled: API.app.trading_pg.current_trading_mode == TradingMode.Pro + visible: enabled radius: height / 2 - color: cog_area.containsMouse || _viewLoader.item.dexConfig.visible ? + color: !enabled ? 'transparent' : cog_area.containsMouse || _viewLoader.item.dexConfig.visible ? Dex.CurrentTheme.floatingBackgroundColor : Dex.CurrentTheme.accentColor Behavior on color { ColorAnimation { duration: 150 } } @@ -99,7 +101,7 @@ Item anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter iconSize: 15 - color: cog_area.containsMouse || _viewLoader.item.dexConfig.visible ? + color: !parent.enabled ? 'transparent' : cog_area.containsMouse || _viewLoader.item.dexConfig.visible ? Dex.CurrentTheme.foregroundColor2 : Dex.CurrentTheme.foregroundColor } diff --git a/atomic_defi_design/Dex/Settings/AddCustomCoinModal.qml b/atomic_defi_design/Dex/Settings/AddCustomCoinModal.qml index 9ae0d79247..53016cd6d3 100644 --- a/atomic_defi_design/Dex/Settings/AddCustomCoinModal.qml +++ b/atomic_defi_design/Dex/Settings/AddCustomCoinModal.qml @@ -9,7 +9,7 @@ import "../Components" import "../Constants" import App 1.0 -BasicModal { +MultipageModal { id: root width: 700 @@ -114,8 +114,8 @@ BasicModal { property var currentType: type_model.get(input_type.currentIndex) // Type page - ModalContent { - title: qsTr("Choose the asset type") + MultipageModalContent { + titleText: qsTr("Choose the asset type") ComboBoxWithTitle { id: input_type @@ -146,8 +146,8 @@ BasicModal { } // Ticker page - ModalContent { - title: has_contract_address ? qsTr("Enter the contract address") : qsTr("Choose the asset ticker") + MultipageModalContent { + titleText: has_contract_address ? qsTr("Enter the contract address") : qsTr("Choose the asset ticker") TextFieldWithTitle { id: input_ticker @@ -203,8 +203,8 @@ BasicModal { } // Logo page - ModalContent { - title: qsTr("Choose the asset logo") + MultipageModalContent { + titleText: qsTr("Choose the asset logo") DefaultButton { Layout.fillWidth: true @@ -261,8 +261,8 @@ BasicModal { } // Configuration - ModalContent { - title: qsTr("Configuration") + MultipageModalContent { + titleText: qsTr("Configuration") DefaultText { visible: has_contract_address @@ -338,8 +338,8 @@ BasicModal { } // Preview - ModalContent { - title: qsTr("Preview") + MultipageModalContent { + titleText: qsTr("Preview") DefaultText { id: warning_message diff --git a/atomic_defi_design/Dex/Settings/CamouflagePasswordModal.qml b/atomic_defi_design/Dex/Settings/CamouflagePasswordModal.qml index 8abadc62a5..52900bb6fe 100644 --- a/atomic_defi_design/Dex/Settings/CamouflagePasswordModal.qml +++ b/atomic_defi_design/Dex/Settings/CamouflagePasswordModal.qml @@ -6,7 +6,7 @@ import "../Components" import "../Constants" import App 1.0 -BasicModal { +MultipageModal { id: root width: 800 @@ -15,8 +15,8 @@ BasicModal { input_password_suffix.reset() } - ModalContent { - title: qsTr("Setup Camouflage Password") + MultipageModalContent { + titleText: qsTr("Setup Camouflage Password") FloatingBackground { id: warning_bg diff --git a/atomic_defi_design/Dex/Settings/DeleteWalletModal.qml b/atomic_defi_design/Dex/Settings/DeleteWalletModal.qml index 8de6a1281f..b126dab5e5 100644 --- a/atomic_defi_design/Dex/Settings/DeleteWalletModal.qml +++ b/atomic_defi_design/Dex/Settings/DeleteWalletModal.qml @@ -6,7 +6,7 @@ import "../Components" import "../Constants" import App 1.0 -BasicModal { +MultipageModal { id: root property bool wrong_password: false @@ -18,8 +18,8 @@ BasicModal { input_password.reset() } - ModalContent { - title: qsTr("Delete Wallet") + MultipageModalContent { + titleText: qsTr("Delete Wallet") FloatingBackground { Layout.alignment: Qt.AlignHCenter diff --git a/atomic_defi_design/Dex/Settings/RecoverSeedModal.qml b/atomic_defi_design/Dex/Settings/RecoverSeedModal.qml index 41c1ed558b..288de4af12 100644 --- a/atomic_defi_design/Dex/Settings/RecoverSeedModal.qml +++ b/atomic_defi_design/Dex/Settings/RecoverSeedModal.qml @@ -9,111 +9,97 @@ import "../Constants" import App 1.0 import Dex.Themes 1.0 as Dex -BasicModal +MultipageModal { id: root property var portfolio_model: API.app.portfolio_pg.portfolio_mdl property var settings_page: API.app.settings_pg - property bool wrong_password: false + property bool wrongPassword: false - function tryViewSeed() + function tryViewKeysAndSeed() { - if(!submit_button.enabled) return + if (!submitButton.enabled) return - const result = API.app.settings_pg.retrieve_seed(API.app.wallet_mgr.wallet_default_name, input_password.field.text) + const result = API.app.settings_pg.retrieve_seed(API.app.wallet_mgr.wallet_default_name, inputPassword.field.text) - if(result.length === 2) + if (result.length === 2) { - seed_text.text = result[0] - rpc_pw.text = result[1] - wrong_password = false + seedLabel.text = result[0] + rpcPwLabel.text = result[1] + wrongPassword = false root.nextPage() loading.running = true } else { - wrong_password = true + wrongPassword = true } } - width: 800 + width: 820 onClosed: { - wrong_password = false - input_password.reset() - seed_text.text = "" + wrongPassword = false + inputPassword.reset() + seedLabel.text = "" + rpcPwLabel.text = "" portfolio_model.clean_priv_keys() currentIndex = 0 } - ModalContent + MultipageModalContent { - title: qsTr("View seed and private keys") + titleText: qsTr("View seed and private keys") - ColumnLayout + DefaultText { - DefaultText - { - Layout.topMargin: 10 - Layout.bottomMargin: 10 - Layout.alignment: Qt.AlignHCenter - - text_value: qsTr("Please enter your password to view the seed.") - } - - DexAppPasswordField - { - id: input_password - Layout.fillWidth: true - field.onAccepted: tryViewSeed() - background.color: Dex.CurrentTheme.floatingBackgroundColor - forceFocus: true - - leftIconColor: Dex.CurrentTheme.foregroundColor - hideFieldButton.icon.color: Dex.CurrentTheme.foregroundColor - } + text_value: qsTr("Please enter your password to view the seed.") + } - DefaultText - { - text_value: qsTr("Wrong Password") - color: Style.colorRed - visible: wrong_password - } + DexAppPasswordField + { + id: inputPassword + Layout.fillWidth: true + forceFocus: true + field.onAccepted: tryViewKeysAndSeed() + background.color: Dex.CurrentTheme.floatingBackgroundColor + leftIconColor: Dex.CurrentTheme.foregroundColor + hideFieldButton.icon.color: Dex.CurrentTheme.foregroundColor } - // Buttons - footer: - [ + // Footer + RowLayout + { + Layout.preferredWidth: parent.width + Layout.topMargin: 30 DefaultButton { text: qsTr("Cancel") - Layout.fillWidth: true + Layout.preferredWidth: parent.width / 100 * 48 onClicked: root.close() - }, + } PrimaryButton { - id: submit_button + id: submitButton + Layout.preferredWidth: parent.width / 100 * 48 + enabled: inputPassword.field.length > 0 text: qsTr("View") - Layout.fillWidth: true - enabled: input_password.isValid() - onClicked: tryViewSeed() + onClicked: tryViewKeysAndSeed() } - ] + } } - ModalContent + MultipageModalContent { - title: qsTr("View seed and private keys") - Layout.fillWidth: true + titleText: qsTr("View seed and private keys") Timer { id: loading - repeat: true running: false onTriggered: @@ -121,361 +107,299 @@ BasicModal if (!settings_page.fetching_priv_keys_busy) { repeat = false - busy_view.visible = false - busy_view.enabled = false - seed_container.visible = true - seed_container.enabled = true - coins_list.visible = true - coins_list.enabled = true + busyView.visible = false + busyView.enabled = false + seedContainer.visible = true + seedContainer.enabled = true + coinsList.visible = true + coinsList.enabled = true } } } - DefaultBusyIndicator - { - id: busy_view - Layout.alignment: Qt.AlignHCenter - } + DefaultBusyIndicator { id: busyView; Layout.alignment: Qt.AlignHCenter } - DefaultRectangle + RowLayout { - id: seed_container + id: seedContainer visible: false enabled: false - height: 120 - width: parent.width + spacing: 10 - RowLayout + // Logo + ColumnLayout { - Layout.fillWidth: true - anchors.verticalCenter: parent.verticalCenter - DefaultImage { - Layout.leftMargin: 10 source: Dex.CurrentTheme.bigLogoPath - Layout.preferredWidth: 32 - Layout.preferredHeight: 32 + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: 144 + Layout.preferredHeight: 144 } + } - DefaultText - { - Layout.leftMargin: 5 - Layout.preferredWidth: 100 - text: API.app_name - font.pixelSize: Style.textSizeSmall5 - } + ColumnLayout + { + spacing: 10 - ColumnLayout + // Seed + RowLayout { - RowLayout - { - Qaterial.RawMaterialButton - { - implicitWidth: 45 - backgroundColor: "transparent" - icon.source: Qaterial.Icons.qrcodeScan - icon.color: Dex.CurrentTheme.foregroundColor - - DefaultMouseArea - { - anchors.fill: parent - hoverEnabled: true + spacing: 5 - onClicked: - { - qrcode_modal.qrcode_svg = API.qt_utilities.get_qrcode_svg_from_string(seed_text.text) - qrcode_modal.open() - } - } - } - - Qaterial.RawMaterialButton + Qaterial.RawMaterialButton + { + backgroundImplicitWidth: 40 + backgroundImplicitHeight: 30 + backgroundColor: "transparent" + icon.source: Qaterial.Icons.qrcodeScan + icon.color: Dex.CurrentTheme.foregroundColor + onClicked: { - implicitWidth: 45 - backgroundColor: "transparent" - icon.source: Qaterial.Icons.contentCopy - icon.color: Dex.CurrentTheme.foregroundColor - - DefaultMouseArea - { - anchors.fill: parent - hoverEnabled: true - onClicked: - { - API.qt_utilities.copy_text_to_clipboard(seed_text.text) - app.notifyCopy(qsTr("Seed phrase"), qsTr("copied to clipboard")) - } - } + qrcodeModal.qrcodeSvg = API.qt_utilities.get_qrcode_svg_from_string(seedLabel.text) + qrcodeModal.open() } } - RowLayout + + Qaterial.RawMaterialButton { - Qaterial.RawMaterialButton + backgroundImplicitWidth: 40 + backgroundImplicitHeight: 30 + backgroundColor: "transparent" + icon.source: Qaterial.Icons.contentCopy + icon.color: Dex.CurrentTheme.foregroundColor + onClicked: { - implicitWidth: 45 - backgroundColor: "transparent" - icon.source: Qaterial.Icons.qrcodeScan - icon.color: Dex.CurrentTheme.foregroundColor - - DefaultMouseArea - { - anchors.fill: parent - hoverEnabled: true - - onClicked: - { - qrcode_modal.qrcode_svg = API.qt_utilities.get_qrcode_svg_from_string(rpc_pw.text) - qrcode_modal.open() - } - } + API.qt_utilities.copy_text_to_clipboard(seedLabel.text) + app.notifyCopy(qsTr("Seed"), qsTr("copied to clipboard")) } + } - Qaterial.RawMaterialButton - { - implicitWidth: 45 - backgroundColor: "transparent" - icon.source: Qaterial.Icons.contentCopy - icon.color: Dex.CurrentTheme.foregroundColor - - DefaultMouseArea - { - anchors.fill: parent - hoverEnabled: true - onClicked: - { - API.qt_utilities.copy_text_to_clipboard(rpc_pw.text) - app.notifyCopy(qsTr("RPC password"), qsTr("phrase key copied to clipboard")) - } - } - } + ColumnLayout + { + DefaultText { text: qsTr("Backup Seed"); font.pixelSize: Style.textSizeSmall2 } + DefaultText { id: seedLabel; Layout.fillWidth: true; font.pixelSize: Style.textSizeSmall1; maximumLineCount: 4; wrapMode: Text.Wrap } } } - ColumnLayout + // RPC Password + RowLayout { - // Seed - DefaultText - { - text: qsTr("Backup seed") - color: Style.modalValueColor - font.pixelSize: Style.textSizeSmall2 - } - DefaultText + spacing: 5 + + Qaterial.RawMaterialButton { - Layout.preferredWidth: 400 - id: seed_text - font.pixelSize: Style.textSizeSmall1 + backgroundImplicitWidth: 40 + backgroundImplicitHeight: 30 + backgroundColor: "transparent" + icon.source: Qaterial.Icons.qrcodeScan + icon.color: Dex.CurrentTheme.foregroundColor + onClicked: + { + qrcodeModal.qrcodeSvg = API.qt_utilities.get_qrcode_svg_from_string(rpcPwLabel.text) + qrcodeModal.open() + } } - // RPC Password - DefaultText + Qaterial.RawMaterialButton { - Layout.topMargin: 10 - text: qsTr("RPC Password") - color: Style.modalValueColor - font.pixelSize: Style.textSizeSmall2 + backgroundImplicitWidth: 40 + backgroundImplicitHeight: 30 + backgroundColor: "transparent" + icon.source: Qaterial.Icons.contentCopy + icon.color: Dex.CurrentTheme.foregroundColor + onClicked: + { + API.qt_utilities.copy_text_to_clipboard(rpcPwLabel.text) + app.notifyCopy(qsTr("RPC Password"), qsTr("copied to clipboard")) + } } - DefaultText + ColumnLayout { - id: rpc_pw - font.pixelSize: Style.textSizeSmall3 + DefaultText { text: qsTr("RPC Password"); font.pixelSize: Style.textSizeSmall2 } + DefaultText { id: rpcPwLabel; Layout.fillWidth: true; font.pixelSize: Style.textSizeSmall1; maximumLineCount: 4; wrapMode: Text.WrapAnywhere } } } } } - // Search input + HorizontalLine { Layout.topMargin: 10; Layout.fillWidth: true } + DefaultTextField { - Layout.fillWidth: true + visible: coinsList.visible + enabled: coinsList.enabled + Layout.topMargin: 10 + Layout.preferredWidth: parent.width / 3 placeholderText: qsTr("Search a coin.") onTextChanged: portfolio_model.portfolio_proxy_mdl.setFilterFixedString(text) - Component.onDestruction: portfolio_model.portfolio_proxy_mdl.setFilterFixedString("") } - DexListView + DefaultRectangle { - id: coins_list - + id: coinsList visible: false enabled: false + Layout.topMargin: 10 + Layout.preferredWidth: parent.width + Layout.preferredHeight: 300 + Layout.alignment: Qt.AlignHCenter + radius: 10 + border.color: Dex.CurrentTheme.lineSeparatorColor + border.width: 2 - Layout.fillWidth: true - Layout.fillHeight: true - model: portfolio_mdl.portfolio_proxy_mdl - - delegate: DefaultRectangle + DefaultListView { - height: seed_container.height - width: seed_container.width + anchors.fill: parent + model: portfolio_mdl.portfolio_proxy_mdl - RowLayout + delegate: ColumnLayout { - Layout.fillWidth: true - anchors.verticalCenter: parent.verticalCenter + width: coinsList.width - DefaultImage - { - Layout.leftMargin: 10 - source: General.coinIcon(model.ticker) - Layout.preferredWidth: 32 - Layout.preferredHeight: 32 - } - - DefaultText + RowLayout { - Layout.preferredWidth: 100 + Layout.fillWidth: true Layout.leftMargin: 5 - text: model.name - font.pixelSize: Style.textSizeSmall5 - } - // QR/Copy buttons - ColumnLayout - { - spacing: 3 - - RowLayout + ColumnLayout { - Qaterial.RawMaterialButton + Layout.fillWidth: true + + DefaultImage { - Layout.topMargin: 2 - implicitWidth: 45 - backgroundColor: "transparent" - icon.source: Qaterial.Icons.qrcodeScan - icon.color: Dex.CurrentTheme.foregroundColor + source: General.coinIcon(model.ticker) + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignCenter + } - DefaultMouseArea - { - anchors.fill: parent - hoverEnabled: true + DefaultText + { + text: model.name + font.pixelSize: Style.textSizeSmall5 + horizontalAlignment: Text.AlignHCenter + Layout.preferredWidth: 100 + } + } + ColumnLayout + { + // Public Address + RowLayout + { + Qaterial.RawMaterialButton + { + backgroundImplicitWidth: 40 + backgroundImplicitHeight: 30 + backgroundColor: "transparent" + icon.source: Qaterial.Icons.qrcodeScan + icon.color: Dex.CurrentTheme.foregroundColor onClicked: { - qrcode_modal.qrcode_svg = API.qt_utilities.get_qrcode_svg_from_string(model.public_address) - qrcode_modal.open() + qrcodeModal.qrcodeSvg = API.qt_utilities.get_qrcode_svg_from_string(publicAddress.text) + qrcodeModal.open() } } - } - // Copy clipboard button - Qaterial.RawMaterialButton - { - implicitWidth: 45 - backgroundColor: "transparent" - icon.source: Qaterial.Icons.contentCopy - icon.color: Dex.CurrentTheme.foregroundColor - - DefaultMouseArea + Qaterial.RawMaterialButton { - anchors.fill: parent - hoverEnabled: true + backgroundImplicitWidth: 40 + backgroundImplicitHeight: 30 + backgroundColor: "transparent" + icon.source: Qaterial.Icons.contentCopy + icon.color: Dex.CurrentTheme.foregroundColor onClicked: { - API.qt_utilities.copy_text_to_clipboard(model.public_address) - app.notifyCopy(qsTr("%1 address").arg(model.ticker), qsTr("copied to clipboard")) + API.qt_utilities.copy_text_to_clipboard(publicAddress.text) + app.notifyCopy(model.name, qsTr("Public Address copied to clipboard")) } } - } - } - - RowLayout - { - Qaterial.RawMaterialButton - { - implicitWidth: 45 - backgroundColor: "transparent" - icon.source: Qaterial.Icons.qrcodeScan - icon.color: Dex.CurrentTheme.foregroundColor - DefaultMouseArea + ColumnLayout { - anchors.fill: parent - hoverEnabled: true + Layout.fillWidth: true - onClicked: + DefaultText + { + text: qsTr("Public Address") + font.pixelSize: Style.textSizeSmall2 + } + + DefaultText { - qrcode_modal.qrcode_svg = API.qt_utilities.get_qrcode_svg_from_string(model.priv_key) - qrcode_modal.open() + id: publicAddress + text: model.public_address + font.pixelSize: Style.textSizeSmall1 + maximumLineCount: 4; wrapMode: Text.WrapAnywhere } } } - // Copy clipboard button - Qaterial.RawMaterialButton + // Private Key + RowLayout { - implicitWidth: 45 - backgroundColor: "transparent" - icon.source: Qaterial.Icons.contentCopy - icon.color: Dex.CurrentTheme.foregroundColor - - DefaultMouseArea + Qaterial.RawMaterialButton { - anchors.fill: parent - hoverEnabled: true + backgroundImplicitWidth: 40 + backgroundImplicitHeight: 30 + backgroundColor: "transparent" + icon.source: Qaterial.Icons.qrcodeScan + icon.color: Dex.CurrentTheme.foregroundColor onClicked: { - API.qt_utilities.copy_text_to_clipboard(model.priv_key) - app.notifyCopy(qsTr("%1 private key").arg(model.ticker), qsTr("copied to clipboard")) + qrcodeModal.qrcodeSvg = API.qt_utilities.get_qrcode_svg_from_string(privateKey.text) + qrcodeModal.open() } - } - } - } - } + } - // Addresses - ColumnLayout - { - DefaultText - { - text: qsTr("Public Address") - color: Style.modalValueColor - font.pixelSize: Style.textSizeSmall2 - } + Qaterial.RawMaterialButton + { + backgroundImplicitWidth: 40 + backgroundImplicitHeight: 30 + backgroundColor: "transparent" + icon.source: Qaterial.Icons.contentCopy + icon.color: Dex.CurrentTheme.foregroundColor + onClicked: + { + API.qt_utilities.copy_text_to_clipboard(privateKey.text) + app.notifyCopy(model.name, qsTr("Private Key copied to clipboard")) + } + } - DefaultText - { - text: model.public_address - font.pixelSize: Style.textSizeSmall3 - } + ColumnLayout + { + Layout.fillWidth: true - DefaultText - { - Layout.topMargin: 10 - text: qsTr("Private Key") - color: Style.modalValueColor - font.pixelSize: Style.textSizeSmall2 - } + DefaultText + { + text: qsTr("Private Key") + font.pixelSize: Style.textSizeSmall2 + } - DefaultText - { - text: model.priv_key - font.pixelSize: Style.textSizeSmall3 + DefaultText + { + id: privateKey + text: model.priv_key + font.pixelSize: Style.textSizeSmall1 + maximumLineCount: 4; wrapMode: Text.WrapAnywhere + } + } + } } } + HorizontalLine { Layout.fillWidth: true } } } } - // Buttons - footer: - [ - DefaultButton - { - text: qsTr("Close") - Layout.fillWidth: true - onClicked: root.close() - } - ] - ModalLoader { - id: qrcode_modal + id: qrcodeModal - property string qrcode_svg + property string qrcodeSvg sourceComponent: Popup { @@ -484,12 +408,11 @@ BasicModal x: (root.width - width) / 2 y: ((root.height - height) / 2) - 250 - onClosed: qrcode_svg = "" + onClosed: qrcodeSvg = "" background: Image { - source: qrcode_svg - + source: qrcodeSvg sourceSize.width: 200 sourceSize.height: 200 } diff --git a/atomic_defi_design/Dex/Wallet/AddressBook.qml b/atomic_defi_design/Dex/Wallet/AddressBook.qml index f14fb5096d..a901b762b8 100644 --- a/atomic_defi_design/Dex/Wallet/AddressBook.qml +++ b/atomic_defi_design/Dex/Wallet/AddressBook.qml @@ -262,12 +262,12 @@ ColumnLayout { id: remove_contact_modal - sourceComponent: BasicModal { + sourceComponent: MultipageModal { width: 500 - ModalContent { + MultipageModalContent { Layout.fillWidth: true - title: qsTr("Do you want to remove this contact ?") + titleText: qsTr("Do you want to remove this contact ?") RowLayout { DangerButton { diff --git a/atomic_defi_design/Dex/Wallet/AddressBookAddContactAddressModal.qml b/atomic_defi_design/Dex/Wallet/AddressBookAddContactAddressModal.qml index 26f0e45df8..adb9f3629f 100644 --- a/atomic_defi_design/Dex/Wallet/AddressBookAddContactAddressModal.qml +++ b/atomic_defi_design/Dex/Wallet/AddressBookAddContactAddressModal.qml @@ -7,9 +7,10 @@ import QtQuick.Controls 2.15 //> ToolTip import "../Constants" import App 1.0 import "../Components" +import Dex.Themes 1.0 as Dex // Contact address entry creation/edition modal -BasicModal +MultipageModal { id: root @@ -49,21 +50,18 @@ BasicModal Component.onCompleted: API.app.wallet_pg.validate_address_data = {} Component.onDestruction: API.app.wallet_pg.validate_address_data = {} - ModalContent + MultipageModalContent { Layout.topMargin: 5 Layout.fillWidth: true - title: isEdition ? qsTr("Edit address entry") : qsTr("Create a new address") + titleText: isEdition ? qsTr("Edit address entry") : qsTr("Create a new address") // Wallet Type Selector - DexButton + DefaultButton { - Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true - text: qsTr("Selected wallet: %1").arg(walletType !== "" ? walletType : qsTr("NONE")) - onClicked: wallet_type_list_modal.open() } @@ -73,7 +71,7 @@ BasicModal id: contact_new_address_key Layout.topMargin: 5 - implicitWidth: parent.width + Layout.fillWidth: true placeholderText: qsTr("Enter a name") @@ -109,51 +107,42 @@ BasicModal if (text.length > max_length) text = text.substring(0, max_length) } + } - DexLabel - { - id: invalidAddressMsgLabel - anchors.top: parent.bottom - anchors.topMargin: 3 - anchors.horizontalCenter: parent.horizontalCenter - color: DexTheme.redColor - wrapMode: DexLabel.Wrap - width: 550 - } + DefaultText + { + id: invalidAddressMsgLabel + Layout.fillWidth: true + color: Dex.CurrentTheme.noColor + wrapMode: DexLabel.Wrap } HorizontalLine { Layout.fillWidth: true; Layout.topMargin: 32 } - Item - { - width: root.width - 50 - height: 40 + footer: + [ + DefaultButton + { + Layout.preferredWidth: 120 + visible: !API.app.wallet_pg.convert_address_busy && API.app.wallet_pg.validate_address_data.convertible ? API.app.wallet_pg.validate_address_data.convertible : false + text: qsTr("Convert") + onClicked: API.app.wallet_pg.convert_address(contact_new_address_value.text, retrieveWalletTypeTicker(), API.app.wallet_pg.validate_address_data.to_address_format); + }, - DexButton + DefaultButton { id: validateButton - anchors.left: parent.left enabled: key.length > 0 && value.length > 0 && walletType !== "" && !API.app.wallet_pg.validate_address_busy text: qsTr("Validate") onClicked: API.app.wallet_pg.validate_address(contact_new_address_value.text, retrieveWalletTypeTicker()) - } + }, - DexButton + DefaultButton { - anchors.right: parent.right text: qsTr("Cancel") onClicked: root.close() } - - DexButton - { - anchors.left: validateButton.right - anchors.leftMargin: 10 - visible: !API.app.wallet_pg.convert_address_busy && API.app.wallet_pg.validate_address_data.convertible ? API.app.wallet_pg.validate_address_data.convertible : false - text: qsTr("Convert") - onClicked: API.app.wallet_pg.convert_address(contact_new_address_value.text, retrieveWalletTypeTicker(), API.app.wallet_pg.validate_address_data.to_address_format); - } - } + ] Connections { diff --git a/atomic_defi_design/Dex/Wallet/AddressBookEditContactModal.qml b/atomic_defi_design/Dex/Wallet/AddressBookEditContactModal.qml index 0c0a2d0888..20c6cbb610 100644 --- a/atomic_defi_design/Dex/Wallet/AddressBookEditContactModal.qml +++ b/atomic_defi_design/Dex/Wallet/AddressBookEditContactModal.qml @@ -13,76 +13,80 @@ import Qaterial 1.0 as Qaterial import "../Components" import "../Constants" import App 1.0 +import Dex.Themes 1.0 as Dex -BasicModal { +MultipageModal +{ id: root property var contactModel - function trySend(wallet_type, address) { + function trySend(wallet_type, address) + { // Checks if the selected wallet type is a coin type instead of a coin. - if (API.app.portfolio_pg.global_cfg_mdl.is_coin_type(wallet_type)) { + if (API.app.portfolio_pg.global_cfg_mdl.is_coin_type(wallet_type)) + { send_selector.coin_type = wallet_type send_selector.address = address send_selector.open() } // Checks if the coin is currently enabled. - else if (!API.app.portfolio_pg.is_coin_enabled(wallet_type)) { + else if (!API.app.portfolio_pg.is_coin_enabled(wallet_type)) + { enable_coin_modal.coin_name = wallet_type enable_coin_modal.open() } // Checks if the coin has balance. - else if (parseFloat(API.app.get_balance(wallet_type)) === 0) { - cannot_send_modal.open() - } + else if (parseFloat(API.app.get_balance(wallet_type)) === 0) cannot_send_modal.open() // If the coin has balance and is enabled, opens the send modal. - else { + else + { API.app.wallet_pg.ticker = wallet_type send_modal.address = address send_modal.open() } } - width: 700 + width: 760 onClosed: contactModel.reload() - ModalContent { - Layout.topMargin: 5 - Layout.fillWidth: true - - title: qsTr("Edit contact") + MultipageModalContent + { + titleText: qsTr("Edit contact") // Contact name section - TextFieldWithTitle { + TextFieldWithTitle + { id: name_input - width: 30 + Layout.fillWidth: true title: qsTr("Contact Name") field.placeholderText: qsTr("Enter a contact name") field.text: contactModel.name - field.onTextChanged: { + field.onTextChanged: + { const max_length = 50 if (field.text.length > max_length) field.text = field.text.substring(0, max_length) } } - HorizontalLine { - Layout.fillWidth: true - color: Style.colorWhite8 - } + HorizontalLine { Layout.fillWidth: true } // Wallets Information - ColumnLayout { + ColumnLayout + { + Layout.topMargin: 10 Layout.fillWidth: true // Title TitleText { text: qsTr("Address List") } - DefaultTextField { + DefaultTextField + { Layout.topMargin: 10 Layout.fillWidth: true @@ -98,9 +102,9 @@ BasicModal { id: walletInfoTable property int _typeColWidth: 90 - property int _keyColWidth: 100 + property int _keyColWidth: 70 property int _addressColWidth: 320 - property int _actionsColWidth: 60 + property int _actionsColWidth: 100 model: contactModel.proxy_filter @@ -122,8 +126,6 @@ BasicModal { Layout.fillWidth: true height: 20 - - DefaultText { anchors.verticalCenter: parent.verticalCenter @@ -142,7 +144,7 @@ BasicModal { rowDelegate: DefaultRectangle { height: 37; radius: 0 - color: styleData.selected ? DexTheme.accentLightColor4: styleData.alternate ? DexTheme.accentDarkColor4 : 'transparent' + color: styleData.selected ? Dex.CurrentTheme.accentColor: styleData.alternate ? Dex.CurrentTheme.backgroundColor : Dex.CurrentTheme.backgroundColorDeep } TableViewColumn // Type Column @@ -157,6 +159,7 @@ BasicModal { delegate: RowLayout { + width: walletInfoTable._typeColWidth DexLabel { Layout.preferredWidth: parent.width - 10 @@ -186,6 +189,7 @@ BasicModal { delegate: RowLayout { + width: walletInfoTable._keyColWidth DefaultText { Layout.preferredWidth: parent.width - 10 @@ -215,6 +219,7 @@ BasicModal { delegate: RowLayout { + width: walletInfoTable._addressColWidth DexLabel { Layout.preferredWidth: parent.width - 10 @@ -240,23 +245,24 @@ BasicModal { resizable: false movable: false - delegate: Row + delegate: RowLayout { - spacing: 0 + spacing: 4 + width: walletInfoTable._actionsColWidth Qaterial.OutlineButton // Edit Address Button { - implicitHeight: 35 - implicitWidth: 35 - + Layout.leftMargin: 2 + implicitHeight: 20 + implicitWidth: 20 outlined: false Qaterial.ColorIcon { anchors.centerIn: parent + iconSize: 20 source: Qaterial.Icons.leadPencil - color: DexTheme.foregroundColor - opacity: .8 + color: Dex.CurrentTheme.foregroundColor } onClicked: @@ -270,17 +276,10 @@ BasicModal { Qaterial.OutlineButton // Delete Button { - implicitHeight: 35 - implicitWidth: 35 + implicitHeight: 20 + implicitWidth: 20 outlined: false - Qaterial.ColorIcon - { - anchors.centerIn: parent - source: Qaterial.Icons.trashCan - color: DexTheme.redColor - opacity: .8 - } onClicked: { removeAddressEntryModal.addressKey = model.address_key; @@ -288,51 +287,59 @@ BasicModal { removeAddressEntryModal.contactModel = contactModel; removeAddressEntryModal.open(); } + + Qaterial.ColorIcon + { + anchors.centerIn: parent + iconSize: 20 + source: Qaterial.Icons.trashCan + color: Dex.CurrentTheme.noColor + } } Qaterial.OutlineButton // Copy Clipboard Button { - implicitHeight: 35 - implicitWidth: 35 - + implicitHeight: 20 + implicitWidth: 20 outlined: false + + onClicked: API.qt_utilities.copy_text_to_clipboard(model.address_value) + Qaterial.ColorIcon { anchors.centerIn: parent + iconSize: 20 source: Qaterial.Icons.contentCopy - color: DexTheme.foregroundColor - opacity: .8 + color: Dex.CurrentTheme.foregroundColor } - - onClicked: API.qt_utilities.copy_text_to_clipboard(model.address_value) } Qaterial.OutlineButton // Send Button { - implicitHeight: 35 - implicitWidth: 35 - + implicitHeight: 20 + implicitWidth: 20 outlined: false + + onClicked: trySend(model.address_type, model.address_value) + Qaterial.ColorIcon { anchors.centerIn: parent + iconSize: 20 source: Qaterial.Icons.send - color: DexTheme.foregroundColor - opacity: .8 + color: Dex.CurrentTheme.foregroundColor } - - onClicked: trySend(model.address_type, model.address_value) } } } } - RowLayout { - PrimaryButton { // New Address Button - text: qsTr("New Address") - - onClicked: address_creation_modal.open(); - } + // New Address Button + DefaultButton + { + Layout.preferredWidth: 140 + text: qsTr("Add Address") + onClicked: address_creation_modal.open(); } ModalLoader { @@ -367,28 +374,33 @@ BasicModal { } } - HorizontalLine { + HorizontalLine + { Layout.fillWidth: true - color: Style.colorWhite8 } // Categories Section Title - TitleText { + TitleText + { + Layout.topMargin: 10 text: qsTr("Tags") } // Categories (Tags) List - Flow { + Flow + { Layout.fillWidth: true spacing: 10 - Repeater { + Repeater + { id: category_repeater model: contactModel.categories - DexAppButton { + DexAppButton + { Layout.alignment: Qt.AlignLeft Layout.leftMargin: 4 - border.color: backgroundColor + border.width: 0 iconSource: Qaterial.Icons.closeOctagon text: modelData onClicked: contactModel.remove_category(modelData); @@ -396,7 +408,8 @@ BasicModal { } // Category adding form opening button - DexAppButton { + DexAppButton + { Layout.leftMargin: 10 width: height text: qsTr("+") @@ -405,70 +418,83 @@ BasicModal { } } - HorizontalLine { - Layout.fillWidth: true - color: Style.colorWhite8 - } + HorizontalLine { Layout.fillWidth: true } // Actions on current contact - RowLayout { + RowLayout + { Layout.alignment: Qt.AlignBottom | Qt.AlignRight Layout.rightMargin: 15 - PrimaryButton { // Validate (Save) Changes + // Validate (Save) Changes + DefaultButton + { text: qsTr("Confirm") - onClicked: { + onClicked: + { contactModel.name = name_input.field.text contactModel.save() root.close(); } } - DefaultButton { // Cancel Changes + // Cancel Changes + DefaultButton + { text: qsTr("Cancel") onClicked: root.close() } } // Wallet Type List Modal - ModalLoader { + ModalLoader + { id: wallet_type_list_modal property string selected_wallet_type: "" - sourceComponent: AddressBookWalletTypeListModal { + sourceComponent: AddressBookWalletTypeListModal + { onSelected_wallet_typeChanged: wallet_type_list_modal.selected_wallet_type = selected_wallet_type } } // Enable Coin Modal - ModalLoader { + ModalLoader + { property string coin_name id: enable_coin_modal - sourceComponent: BasicModal { - ModalContent { + sourceComponent: MultipageModal + { + MultipageModalContent + { Layout.fillWidth: true - title: qsTr("Enable " + coin_name) + titleText: qsTr("Enable " + coin_name) - DefaultText { + DefaultText + { text: qsTr("The selected address belongs to a disabled coin, you need to enabled it before sending.") } - Row { + Row + { // Enable button - PrimaryButton { + PrimaryButton + { text: qsTr("Enable") - onClicked: { + onClicked: + { API.app.enable_coin(coin_name) enable_coin_modal.close() } } // Cancel button - DefaultButton { + DefaultButton + { Layout.rightMargin: 5 text: qsTr("Cancel") @@ -480,13 +506,15 @@ BasicModal { } // Send Selector modal - ModalLoader { + ModalLoader + { id: send_selector property string coin_type property string address - onLoaded: { + onLoaded: + { item.coin_type = coin_type item.address = address } @@ -495,31 +523,38 @@ BasicModal { } // Send Modal - ModalLoader { + ModalLoader + { property string address id: send_modal onLoaded: item.address_field.text = address - sourceComponent: SendModal { + sourceComponent: SendModal + { address_field.enabled: false } } // Cannot Send Modal - ModalLoader { + ModalLoader + { id: cannot_send_modal - sourceComponent: BasicModal { - ModalContent { - title: qsTr("Cannot send to this address") + sourceComponent: MultipageModal + { + MultipageModalContent + { + titleText: qsTr("Cannot send to this address") - DefaultText { + DefaultText + { text: qsTr("Your balance is empty") } - DefaultButton { + DefaultButton + { text: qsTr("Ok") onClicked: cannot_send_modal.close() @@ -537,12 +572,12 @@ BasicModal { property string addressKey property string addressType - sourceComponent: BasicModal + sourceComponent: MultipageModal { width: 250 - ModalContent + MultipageModalContent { - title: qsTr("Remove address ?") + titleText: qsTr("Remove address ?") RowLayout { @@ -554,7 +589,8 @@ BasicModal { } // Category (Tag) Adding Modal - ModalLoader { + ModalLoader + { id: add_category_modal onLoaded: item.contactModel = root.contactModel diff --git a/atomic_defi_design/Dex/Wallet/AddressBookNewContactCategoryModal.qml b/atomic_defi_design/Dex/Wallet/AddressBookNewContactCategoryModal.qml index 5b11b85e5b..ba09b631db 100644 --- a/atomic_defi_design/Dex/Wallet/AddressBookNewContactCategoryModal.qml +++ b/atomic_defi_design/Dex/Wallet/AddressBookNewContactCategoryModal.qml @@ -7,62 +7,71 @@ import "../Constants" import App 1.0 //! New category form -BasicModal { +MultipageModal +{ id: root width: 500 property var contactModel - ModalContent { - Layout.fillWidth: true - title: qsTr("Add a new tag") + MultipageModalContent + { + titleText: qsTr("Add a new tag") - RowLayout { - //! Category name input. - DefaultTextField { - id: name_input - placeholderText: qsTr("Enter the tag name") - onTextChanged: { - const max_length = 14 - if(text.length > max_length) - text = text.substring(0, max_length) - } + DefaultTextField + { + id: name_input - //! Error tooltip when category name already exists. - DefaultTooltip { - id: alrady_exists_tooltip - visible: false - contentItem: DefaultText { - text_value: qsTr("This contact already has this tag") - } + Layout.fillWidth: true + + placeholderText: qsTr("Enter the tag name") + onTextChanged: + { + const max_length = 14 + if(text.length > max_length) + text = text.substring(0, max_length) + } + + // Error tooltip when category name already exists. + DefaultTooltip + { + id: alrady_exists_tooltip + visible: false + contentItem: DefaultText + { + text_value: qsTr("This contact already has this tag") } } + } - //! Add - PrimaryButton { - Layout.leftMargin: 90 + footer: + [ + DefaultButton + { + Layout.preferredWidth: 90 + Layout.preferredHeight: 40 text: qsTr("Add") - onClicked: { - if (!contactModel.add_category(name_input.text)) - { - alrady_exists_tooltip.visible = true - } + onClicked: + { + if (!contactModel.add_category(name_input.text)) alrady_exists_tooltip.visible = true else { name_input.text = "" add_category_modal.close() } } - } + }, - //! Cancel - DefaultButton { + DefaultButton + { + Layout.preferredWidth: 90 + Layout.preferredHeight: 40 text: qsTr("Cancel") onClicked: { name_input.text = "" add_category_modal.close() } } - } + ] } } diff --git a/atomic_defi_design/Dex/Wallet/AddressBookNewContactModal.qml b/atomic_defi_design/Dex/Wallet/AddressBookNewContactModal.qml index 8454d472c2..4ecd0096c6 100644 --- a/atomic_defi_design/Dex/Wallet/AddressBookNewContactModal.qml +++ b/atomic_defi_design/Dex/Wallet/AddressBookNewContactModal.qml @@ -6,15 +6,14 @@ import "../Components" import "../Constants" import App 1.0 -BasicModal { +MultipageModal { id: root width: 500 - ModalContent { + MultipageModalContent { Layout.topMargin: 5 - Layout.fillWidth: true - title: qsTr("Create a new contact") + titleText: qsTr("Create a new contact") // Contact name input. DefaultTextField { diff --git a/atomic_defi_design/Dex/Wallet/AddressBookSendWalletSelector.qml b/atomic_defi_design/Dex/Wallet/AddressBookSendWalletSelector.qml index 55ecd7fc25..b6135e2894 100644 --- a/atomic_defi_design/Dex/Wallet/AddressBookSendWalletSelector.qml +++ b/atomic_defi_design/Dex/Wallet/AddressBookSendWalletSelector.qml @@ -6,7 +6,7 @@ import "../Components" import "../Constants" import App 1.0 -BasicModal { +MultipageModal { id: root property string coin_type @@ -14,9 +14,9 @@ BasicModal { width: 400 - ModalContent { + MultipageModalContent { Layout.fillWidth: true - title: qsTr("Choose a valid ") + coin_type + qsTr(" coin") + titleText: qsTr("Choose a valid ") + coin_type + qsTr(" coin") Repeater { model: coin_type == "QRC-20" ? API.app.portfolio_pg.global_cfg_mdl.all_qrc20_proxy : diff --git a/atomic_defi_design/Dex/Wallet/AddressBookWalletTypeList.qml b/atomic_defi_design/Dex/Wallet/AddressBookWalletTypeList.qml index bd58d2ec3d..8f6b749f1b 100644 --- a/atomic_defi_design/Dex/Wallet/AddressBookWalletTypeList.qml +++ b/atomic_defi_design/Dex/Wallet/AddressBookWalletTypeList.qml @@ -28,14 +28,16 @@ Qaterial.Expandable id: _header icon.source: General.image_path + "arrow_down.svg" - DexLabel { + + onClicked: () => _root.expanded = !_root.expanded + + TitleText + { anchors.verticalCenter: parent.verticalCenter + leftPadding: 75 text: title - leftPadding: 60 font.bold: true } - - onClicked: () => _root.expanded = !_root.expanded } delegate: Column diff --git a/atomic_defi_design/Dex/Wallet/AddressBookWalletTypeListModal.qml b/atomic_defi_design/Dex/Wallet/AddressBookWalletTypeListModal.qml index 212373309b..5590cd3689 100644 --- a/atomic_defi_design/Dex/Wallet/AddressBookWalletTypeListModal.qml +++ b/atomic_defi_design/Dex/Wallet/AddressBookWalletTypeListModal.qml @@ -7,7 +7,8 @@ import "../Components" import "../Constants" import App 1.0 -BasicModal { +MultipageModal +{ readonly property var glbCoinsCfgModel: API.app.portfolio_pg.global_cfg_mdl property alias selected_wallet_type: wallet_list.selected_wallet_type @@ -39,18 +40,18 @@ BasicModal { close() } - width: 400 + width: 600 onOpened: _searchbar.forceActiveFocus() onClosed: resetModal() - ModalContent + MultipageModalContent { id: wallet_list property string selected_wallet_type: "" - title: qsTr("Select wallet type") + titleText: qsTr("Select wallet type") // Search input DefaultTextField @@ -68,8 +69,10 @@ BasicModal { { id: _qrc20Expandable + Layout.topMargin: 20 Layout.rightMargin: 10 Layout.fillWidth: true + Layout.fillHeight: true title: "QRC-20 coins" type_title: "QRC-20" diff --git a/atomic_defi_design/Dex/Wallet/AddressList.qml b/atomic_defi_design/Dex/Wallet/AddressList.qml index e97e4c3271..dd0067b367 100644 --- a/atomic_defi_design/Dex/Wallet/AddressList.qml +++ b/atomic_defi_design/Dex/Wallet/AddressList.qml @@ -5,19 +5,23 @@ import QtQuick.Controls 2.15 import "../Components" import "../Constants" import App 1.0 +import Dex.Themes 1.0 as Dex -ColumnLayout { +ColumnLayout +{ + id: root property alias title: title.text property alias model: list.model + property real addressFontSize: DefaultText.font.pixelSize - Layout.fillWidth: true - - TitleText { + TitleText + { id: title - opacity: .6 + color: Dex.CurrentTheme.foregroundColor2 } - ListView { + ListView + { id: list Layout.fillWidth: true Layout.fillHeight: true @@ -25,11 +29,11 @@ ColumnLayout { clip: true - // Row - delegate: DefaultTextEdit { + delegate: DefaultText + { text_value: model.modelData - color: DexTheme.foregroundColor privacy: true + font.pixelSize: root.addressFontSize } } } diff --git a/atomic_defi_design/Dex/Wallet/ClaimFaucetResultModal.qml b/atomic_defi_design/Dex/Wallet/ClaimFaucetResultModal.qml index f97d72388a..fd01e04aaf 100644 --- a/atomic_defi_design/Dex/Wallet/ClaimFaucetResultModal.qml +++ b/atomic_defi_design/Dex/Wallet/ClaimFaucetResultModal.qml @@ -6,16 +6,16 @@ import "../Components" import "../Constants" import App 1.0 -BasicModal { +MultipageModal { readonly property var claiming_faucet_rpc_result: api_wallet_page.claiming_faucet_rpc_data id: root width: 1200 - ModalContent { + MultipageModalContent { id: status - title: claiming_faucet_rpc_result && claiming_faucet_rpc_result.status ? + titleText: claiming_faucet_rpc_result && claiming_faucet_rpc_result.status ? claiming_faucet_rpc_result.status : "" DefaultText { diff --git a/atomic_defi_design/Dex/Wallet/ClaimRewardsModal.qml b/atomic_defi_design/Dex/Wallet/ClaimRewardsModal.qml index 499af89909..9647f72f7b 100644 --- a/atomic_defi_design/Dex/Wallet/ClaimRewardsModal.qml +++ b/atomic_defi_design/Dex/Wallet/ClaimRewardsModal.qml @@ -6,7 +6,8 @@ import "../Components" import "../Constants" import App 1.0 -BasicModal { +MultipageModal +{ id: root readonly property bool empty_data: !prepare_claim_rewards_result || !prepare_claim_rewards_result.withdraw_answer @@ -106,8 +107,8 @@ BasicModal { // Inside modal width: 1200 - ModalContent { - title: qsTr("Claim your %1 reward?", "TICKER").arg(api_wallet_page.ticker) + MultipageModalContent { + titleText: qsTr("Claim your %1 reward?", "TICKER").arg(api_wallet_page.ticker) DefaultBusyIndicator { visible: !can_claim || is_broadcast_busy @@ -428,8 +429,10 @@ BasicModal { } // Buttons - footer: [ - DexAppButton { + footer: + [ + DexAppButton + { text: qsTr("Cancel") leftPadding: 40 rightPadding: 40 @@ -437,11 +440,13 @@ BasicModal { onClicked: root.close() }, - Item { + Item + { Layout.fillWidth: true }, - DexAppOutlineButton { + DexAppOutlineButton + { text: qsTr("Confirm") leftPadding: 40 rightPadding: 40 @@ -454,12 +459,9 @@ BasicModal { } // Result Page - SendResult { - result: ({ - balance_change: empty_data ? "" : prepare_claim_rewards_result.withdraw_answer.my_balance_change, - fees: empty_data ? "" : prepare_claim_rewards_result.withdraw_answer.fee_details.amount, - date: empty_data ? "" : prepare_claim_rewards_result.withdraw_answer.date - }) + SendResult + { + result: prepare_claim_rewards_result tx_hash: broadcast_result function onClose() { root.close() } diff --git a/atomic_defi_design/Dex/Wallet/EnableCoinModal.qml b/atomic_defi_design/Dex/Wallet/EnableCoinModal.qml index bc52cd9d97..7f4abe2327 100644 --- a/atomic_defi_design/Dex/Wallet/EnableCoinModal.qml +++ b/atomic_defi_design/Dex/Wallet/EnableCoinModal.qml @@ -12,7 +12,7 @@ import "../Constants" import App 1.0 import Dex.Themes 1.0 as Dex -BasicModal +MultipageModal { id: root @@ -46,9 +46,9 @@ BasicModal coin_cfg_model.checked_nb = 0; } - ModalContent + MultipageModalContent { - title: qsTr("Enable assets") + titleText: qsTr("Enable assets") titleAlignment: Qt.AlignHCenter // Search input @@ -59,7 +59,7 @@ BasicModal searchIconLeftMargin: 20 Layout.alignment: Qt.AlignHCenter Layout.topMargin: 10 - Layout.preferredWidth: 500 + Layout.fillWidth: true Layout.preferredHeight: 44 textField.placeholderText: qsTr("Search asset") @@ -70,7 +70,7 @@ BasicModal { Layout.alignment: Qt.AlignHCenter Layout.topMargin: 5 - Layout.preferredWidth: 500 + Layout.fillWidth: true Layout.preferredHeight: 25 DexCheckBox @@ -100,7 +100,7 @@ BasicModal } } - HorizontalLine { Layout.topMargin: 5; Layout.alignment: Qt.AlignHCenter; Layout.preferredWidth: 500 } + HorizontalLine { Layout.topMargin: 5; Layout.alignment: Qt.AlignHCenter; Layout.fillWidth: true } DefaultListView { @@ -111,7 +111,7 @@ BasicModal Layout.topMargin: -5 Layout.alignment: Qt.AlignHCenter Layout.preferredHeight: 300 - Layout.preferredWidth: 515 + Layout.fillWidth: true delegate: DexCheckBox { @@ -188,7 +188,7 @@ BasicModal Item { Layout.topMargin: 6 - Layout.preferredWidth: 500 + Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter DexLabel @@ -210,7 +210,7 @@ BasicModal Item { Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: 500 + Layout.fillWidth: true Layout.preferredHeight: 40 DexTransparentButton @@ -241,25 +241,20 @@ BasicModal } } - Item + RowLayout { - Layout.preferredWidth: 500 - Layout.preferredHeight: 40 - Layout.alignment: Qt.AlignHCenter - + Layout.fillWidth: true DefaultButton { - anchors.left: parent.left - width: 199 + Layout.preferredWidth: 199 text: qsTr("Close") radius: 20 onClicked: root.close() } - + Item { Layout.fillWidth: true } DexGradientAppButton { - anchors.right: parent.right - width: 199 + Layout.preferredWidth: 199 visible: coin_cfg_model.length > 0 enabled: coin_cfg_model.checked_nb > 0 text: qsTr("Enable") diff --git a/atomic_defi_design/Dex/Wallet/Main.qml b/atomic_defi_design/Dex/Wallet/Main.qml index 5187d9166c..2609058a28 100644 --- a/atomic_defi_design/Dex/Wallet/Main.qml +++ b/atomic_defi_design/Dex/Wallet/Main.qml @@ -433,13 +433,13 @@ Item Component { id: enable_fees_coin_comp - BasicModal + MultipageModal { id: root width: 300 - ModalContent + MultipageModalContent { - title: qsTr("Enable %1 ?").arg(coin_to_enable_ticker) + titleText: qsTr("Enable %1 ?").arg(coin_to_enable_ticker) RowLayout { Layout.fillWidth: true @@ -617,6 +617,89 @@ Item id: claimFaucetResultModal sourceComponent: ClaimFaucetResultModal {} } + + // Public Key button + Item + { + Layout.minimumWidth: 160 + Layout.maximumWidth: 180 + Layout.fillWidth: true + Layout.preferredHeight: 48 + + visible: current_ticker_infos.name === "Tokel" + + DexAppButton + { + text: qsTr("Public Key") + radius: 18 + font.pixelSize: 16 + anchors.fill: parent + onClicked: + { + API.app.settings_pg.fetchPublicKey() + publicKeyModal.open() + } + } + + ModalLoader + { + id: publicKeyModal + sourceComponent: MultipageModal + { + MultipageModalContent + { + titleText: qsTr("Public Key") + + DefaultBusyIndicator + { + Layout.alignment: Qt.AlignCenter + + visible: API.app.settings_pg.fetchingPublicKey + enabled: visible + } + + RowLayout + { + Layout.fillWidth: true + + DefaultText + { + Layout.fillWidth: true + visible: !API.app.settings_pg.fetchingPublicKey + text: API.app.settings_pg.publicKey + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + } + + Qaterial.RawMaterialButton + { + backgroundImplicitWidth: 40 + backgroundImplicitHeight: 30 + backgroundColor: "transparent" + icon.source: Qaterial.Icons.contentCopy + icon.color: Dex.CurrentTheme.foregroundColor + onClicked: + { + API.qt_utilities.copy_text_to_clipboard(API.app.settings_pg.publicKey) + app.notifyCopy(qsTr("Public Key"), qsTr("Copied to Clipboard")) + } + } + } + + Image + { + visible: !API.app.settings_pg.fetchingPublicKey + + Layout.topMargin: 20 + Layout.alignment: Qt.AlignHCenter + + sourceSize.width: 300 + sourceSize.height: 300 + source: API.qt_utilities.get_qrcode_svg_from_string(API.app.settings_pg.publicKey) + } + } + } + } + } } // Price Graph @@ -835,4 +918,4 @@ Item implicitHeight: Math.min(contentItem.childrenRect.height, wallet.height*0.5) } -} \ No newline at end of file +} diff --git a/atomic_defi_design/Dex/Wallet/ReceiveModal.qml b/atomic_defi_design/Dex/Wallet/ReceiveModal.qml index 5b9ca5fb1f..71a1fb38a0 100644 --- a/atomic_defi_design/Dex/Wallet/ReceiveModal.qml +++ b/atomic_defi_design/Dex/Wallet/ReceiveModal.qml @@ -6,51 +6,51 @@ import "../Components" import "../Constants" import App 1.0 -BasicModal { +MultipageModal +{ id: root - function reset() { + function reset() { } - } + width: 600 + + MultipageModalContent + { + titleText: qsTr("Receive") - width: 500 - - ModalContent { - title: qsTr("Receive") - - // Receive address - TextAreaWithTitle { - title: qsTr("Only send %1 to this address", "TICKER").arg(api_wallet_page.ticker) - field.text: current_ticker_infos.address - field.readOnly: true - field.wrapMode: TextEdit.NoWrap - copyable: true - onCopied: { - app.notifyCopy(qsTr("%1 address").arg(api_wallet_page.ticker), qsTr("copied to clipboard")) - } + TextEditWithTitle + { + title: qsTr("Only send %1 to this address:", "TICKER").arg(api_wallet_page.ticker) + text: current_ticker_infos.address + label.font.pixelSize: 13 + copy: true + privacy: true + onCopyNotificationTitle: qsTr("%1 address".arg(api_wallet_page.ticker)) + onCopyNotificationMsg: qsTr("copied to clipboard.") } - DefaultImage { + DefaultImage + { + Layout.topMargin: 20 Layout.alignment: Qt.AlignHCenter source: current_ticker_infos.qrcode_address - sourceSize.width: 200 - sourceSize.height: 200 + sourceSize.width: 300 + sourceSize.height: 300 } // Buttons - footer: [ - Item { - Layout.fillWidth: true - }, - DexAppButton { + footer: + [ + Item { Layout.fillWidth: true }, + DefaultButton + { text: qsTr("Close") - leftPadding: 40 - rightPadding: 40 - radius: 18 + Layout.fillWidth: true onClicked: root.close() - } + }, + Item { Layout.fillWidth: true } ] } } diff --git a/atomic_defi_design/Dex/Wallet/SendModal.qml b/atomic_defi_design/Dex/Wallet/SendModal.qml index 9a8bc7bcc1..225b2f5af4 100644 --- a/atomic_defi_design/Dex/Wallet/SendModal.qml +++ b/atomic_defi_design/Dex/Wallet/SendModal.qml @@ -10,7 +10,7 @@ import "../Constants" import App 1.0 import Dex.Themes 1.0 as Dex -BasicModal +MultipageModal { id: root @@ -263,7 +263,7 @@ BasicModal } // Prepare Page - ModalContent2 + MultipageModalContent { id: _preparePage @@ -280,7 +280,6 @@ BasicModal Layout.preferredWidth: 420 Layout.preferredHeight: 44 Layout.alignment: Qt.AlignHCenter - Layout.topMargin: 18 color: input_address.background.color radius: input_address.background.radius @@ -341,14 +340,16 @@ BasicModal { visible: errorView && input_address.text !== "" Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true DefaultText { id: reason Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true - wrapMode: Label.Wrap + wrapMode: Text.WrapAtWordBoundaryOrAnywhere color: Dex.CurrentTheme.noColor text_value: qsTr("The address has to be mixed case.") } @@ -454,6 +455,8 @@ BasicModal property string value: "0" enabled: !(new BigNumber(current_ticker_infos.current_currency_ticker_price).isLessThanOrEqualTo(0)) + visible: enabled + text: { if (!enabled) @@ -497,6 +500,8 @@ BasicModal Rectangle { enabled: equivalentAmount.enabled + visible: equivalentAmount.visible + Layout.alignment: Qt.AlignRight Layout.preferredWidth: cryptoFiatSwitchText.width + cryptoFiatSwitchIcon.width + 20 Layout.preferredHeight: 32 @@ -568,13 +573,9 @@ BasicModal DexSwitch { id: custom_fees_switch - enabled: !root.is_send_busy - Layout.topMargin: 32 - text: qsTr("Enable Custom Fees") - onCheckedChanged: input_custom_fees.text = "" } @@ -582,7 +583,6 @@ BasicModal DefaultText { visible: custom_fees_switch.checked - font.pixelSize: 14 color: Dex.CurrentTheme.noColor text_value: qsTr("Only use custom fees if you know what you are doing!") @@ -684,7 +684,7 @@ BasicModal text: qsTr("Close") Layout.alignment: Qt.AlignLeft - Layout.preferredWidth: 199 + Layout.preferredWidth: parent.width / 100 * 48 Layout.preferredHeight: 48 label.font.pixelSize: 16 @@ -693,11 +693,14 @@ BasicModal onClicked: root.close() } + Item { Layout.fillWidth: true } + OutlineButton { enabled: fieldAreFilled() && hasFunds() && !errorView && !root.is_send_busy Layout.alignment: Qt.AlignRight + Layout.preferredWidth: parent.width / 100 * 48 text: qsTr("Prepare") @@ -725,9 +728,9 @@ BasicModal } // Send Page - ModalContent + MultipageModalContent { - title: qsTr("Send") + titleText: qsTr("Send") // Address TextEditWithTitle @@ -785,11 +788,14 @@ BasicModal } // Buttons - footer: [ - Item { + footer: + [ + Item + { Layout.fillWidth: true }, - DexAppButton { + DexAppButton + { text: qsTr("Back") leftPadding: 40 rightPadding: 40 @@ -797,10 +803,12 @@ BasicModal onClicked: root.currentIndex = 0 enabled: !root.is_broadcast_busy }, - Item { + Item + { Layout.fillWidth: true }, - DexAppOutlineButton { + DexAppOutlineButton + { text: qsTr("Send") onClicked: sendCoin() leftPadding: 40 @@ -808,27 +816,24 @@ BasicModal radius: 18 enabled: !root.is_broadcast_busy }, - Item { + Item + { Layout.fillWidth: true } ] } // Result Page - SendResult { - result: ({ - balance_change: empty_data ? "" : send_result.withdraw_answer.my_balance_change, - fees: empty_data ? "" : send_result.withdraw_answer.fee_details.amount, - date: empty_data ? "" : send_result.withdraw_answer.date - }) + SendResult + { + result: send_result address: input_address.text tx_hash: broadcast_result custom_amount: getCryptoAmount() - function onClose() { - if(root.segwit) { - root.segwit_success = true - } + function onClose() + { + if (root.segwit) root.segwit_success = true root.close() } } diff --git a/atomic_defi_design/Dex/Wallet/SendModalContactList.qml b/atomic_defi_design/Dex/Wallet/SendModalContactList.qml index 7c2dd78b8b..20984b8dd2 100644 --- a/atomic_defi_design/Dex/Wallet/SendModalContactList.qml +++ b/atomic_defi_design/Dex/Wallet/SendModalContactList.qml @@ -7,19 +7,20 @@ import QtQuick.Controls 2.15 import "../Components" import "../Constants" import App 1.0 +import Dex.Themes 1.0 as Dex -BasicModal { +MultipageModal +{ id: root - width: 500 - height: 400 + width: 600 property string ticker: api_wallet_page.ticker property var selected_address: "" - ModalContent + MultipageModalContent { - title: qsTr("Select a contact with an %1 address").arg(ticker) + titleText: qsTr("Select a contact with an %1 address").arg(ticker) // Searchbar DefaultTextField @@ -32,109 +33,90 @@ BasicModal { } // Contact List - ColumnLayout + DefaultListView { - Layout.alignment: Qt.AlignHCenter + id: contactListView + Layout.fillWidth: true - DefaultListView + model: API.app.addressbook_pg.model.proxy + delegate: DefaultRectangle { - readonly property int rowHeight: 30 // Visual height of a row. + property int addressesCount + property var contactModel: modelData + + width: contactListView.width + height: 30 + color: mouse_area.containsMouse ? Dex.CurrentTheme.accentColor : index % 2 === 0 ? Dex.CurrentTheme.backgroundColor : Dex.CurrentTheme.backgroundColorDeep Component.onCompleted: { - API.app.addressbook_pg.model.proxy.type_filter = ticker - console.debug("SendModal: Show contact list of given ticker %1 and of size %2" - .arg(API.app.addressbook_pg.model.proxy.type_filter) - .arg(count)) + modelData.proxy_filter.filter_type = ticker + addressesCount = modelData.proxy_filter.rowCount() } - Component.onDestruction: - { - API.app.addressbook_pg.model.proxy.type_filter = "" - console.debug("SendModal: Destroying contact list") - } - model: API.app.addressbook_pg.model.proxy - delegate: AnimatedRectangle - { - property int addressesCount - property var contactModel: modelData - - - width: 450 - height: 30 - color: mouse_area.containsMouse ? DexTheme.buttonColorHovered : index % 2 === 0 ? DexTheme.contentColorTopBold : "transparent" - - Component.onCompleted: - { - modelData.proxy_filter.filter_type = ticker - addressesCount = modelData.proxy_filter.rowCount() - console.debug("SendModal: Apply %1 filter to contact %2. It has %3 %4 addresses" - .arg(ticker) - .arg(modelData.name) - .arg(addressesCount) - .arg(modelData.proxy_filter.filter_type)) - } - - Component.onDestruction: - { - contactModel.proxy_filter.filter_type = "" - console.debug("SendModal: Remove %1 filter to contact %2" - .arg(ticker) - .arg(contactModel.name)) - } + Component.onDestruction: contactModel.proxy_filter.filter_type = "" - DexMouseArea + DefaultMouseArea + { + id: mouse_area + anchors.fill: parent + hoverEnabled: true + onClicked: { - id: mouse_area - anchors.fill: parent - hoverEnabled: true - onClicked: - { - addresses_view.contactModel = modelData - root.currentIndex = 1 - } + addressesView.contactModel = modelData + root.currentIndex = 1 } + } - DefaultText // Contact Name - { - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.leftMargin: 10 - text: modelData.name - elide: Qt.ElideRight - } + DefaultText // Contact Name + { + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 10 + width: parent * 0.4 + text: modelData.name + elide: Qt.ElideRight + } - DefaultText // Contact Addresses Count - { - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: 18 - text: addressesCount > 1 ? qsTr("%1 addresses").arg(addressesCount) : - qsTr("1 address") - } + DefaultText // Contact Addresses Count + { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 10 + width: parent * 0.4 + text: addressesCount > 1 ? qsTr("%1 addresses").arg(addressesCount) : qsTr("1 address") + elide: Qt.ElideRight + } - HorizontalLine - { - width: parent.width - height: 2 - anchors.bottom: parent.bottom - } + HorizontalLine + { + width: parent.width + height: 2 + anchors.bottom: parent.bottom } } - } - DefaultButton // Back to Send Modal Button - { - Layout.alignment: Qt.AlignHCenter - Layout.fillWidth: true - text: qsTr("Back") - onClicked: close() + Component.onCompleted: API.app.addressbook_pg.model.proxy.type_filter = ticker + Component.onDestruction: API.app.addressbook_pg.model.proxy.type_filter = "" } + + footer: + [ + Item { Layout.fillWidth: true }, + DefaultButton // Back to Send Modal Button + { + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: 280 + text: qsTr("Back") + onClicked: close() + }, + Item { Layout.fillWidth: true } + ] } - ModalContent + MultipageModalContent { - id: addresses_view + id: addressesView readonly property var defaultContactModel: { @@ -146,85 +128,91 @@ BasicModal { } property var contactModel: defaultContactModel - title: qsTr("Choose an %1 address of %2") - .arg(contactModel.proxy_filter.filter_type) - .arg(contactModel.name) + property int columnsMargin: 10 + property int nameColumnWidth: width * 0.3 + + titleText: qsTr("Choose an %1 address of %2").arg(contactModel.proxy_filter.filter_type).arg(contactModel.name) RowLayout { Layout.fillWidth: true + spacing: 0 DefaultText { - Layout.leftMargin: 5 - Layout.preferredWidth: 210 + Layout.leftMargin: addressesView.columnsMargin + Layout.preferredWidth: addressesView.nameColumnWidth text: qsTr("Name") - color: DexTheme.foregroundColor - opacity: .7 + color: Dex.CurrentTheme.foregroundColor2 } DefaultText { + Layout.leftMargin: addressesView.columnsMargin text: qsTr("Address") - color: DexTheme.foregroundColor - opacity: .7 + color: Dex.CurrentTheme.foregroundColor2 } } - // Address List - ColumnLayout + DefaultListView { - id: address_list_bg + id: addressListView Layout.fillWidth: true - DefaultListView + model: addressesView.contactModel.proxy_filter + delegate: DefaultRectangle { - readonly property int rowHeight: 30 // Visual height of a row. - - model: addresses_view.contactModel.proxy_filter - delegate: AnimatedRectangle { // Address Row - implicitWidth: 450 - height: 30 - color: address_mouse_area.containsMouse ? DexTheme.buttonColorHovered : index % 2 === 0 ? DexTheme.contentColorTopBold : "transparent" - - DexMouseArea { - id: address_mouse_area - anchors.fill: parent - hoverEnabled: true - onClicked: { - selected_address = model.address_value - close() - } - } + width: addressListView.width + height: 30 + color: address_mouse_area.containsMouse ? Dex.CurrentTheme.accentColor : index % 2 === 0 ? Dex.CurrentTheme.backgroundColor : Dex.CurrentTheme.backgroundColorDeep - DefaultText { // Address Key - width: 150 - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.leftMargin: 10 - text: model.address_key - elide: Qt.ElideRight + DefaultMouseArea + { + id: address_mouse_area + anchors.fill: parent + hoverEnabled: true + onClicked: + { + selected_address = model.address_value + close() } + } - DefaultText { // Address Value - width: 220 - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: 10 - text: model.address_value - elide: Qt.ElideRight - } + DefaultText + { + id: addressKeyLabel + width: addressesView.nameColumnWidth + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: addressesView.columnsMargin + text: model.address_key + elide: Qt.ElideRight + } + + DefaultText + { + anchors.verticalCenter: parent.verticalCenter + anchors.left: addressKeyLabel.right + anchors.leftMargin: addressesView.columnsMargin + anchors.right: parent.right + anchors.rightMargin: addressesView.columnsMargin + text: model.address_value + elide: Qt.ElideRight } } } - DexAppButton - { - radius: 16 - Layout.alignment: Qt.AlignBottom - text: qsTr("Back") - onClicked: currentIndex = 0 - } + footer: + [ + Item { Layout.fillWidth: true }, + DefaultButton + { + Layout.preferredWidth: 280 + text: qsTr("Back") + onClicked: currentIndex = 0 + }, + Item { Layout.fillWidth: true } + ] } } diff --git a/atomic_defi_design/Dex/Wallet/SendResult.qml b/atomic_defi_design/Dex/Wallet/SendResult.qml index 3ada4f1821..0c7e070d10 100644 --- a/atomic_defi_design/Dex/Wallet/SendResult.qml +++ b/atomic_defi_design/Dex/Wallet/SendResult.qml @@ -6,16 +6,16 @@ import "../Components" import "../Constants" import App 1.0 -ModalContent +MultipageModalContent { - property var result: ({ balance_change:"", fees: "", date: "", explorer_url: "" }) - property alias address: address.text - property string custom_amount - property alias tx_hash: tx_hash.text + id: root - function onClose() {} + property var result + property alias address: address.text + property string custom_amount + property alias tx_hash: tx_hash.text - title: qsTr("Transaction Complete!") + titleText: qsTr("Transaction Complete!") // Address TextEditWithTitle @@ -29,9 +29,10 @@ ModalContent TextEditWithTitle { title: qsTr("Amount") + text: { - let amount = custom_amount !== "" ? custom_amount : result.balance_change + let amount = custom_amount !== "" ? custom_amount : result.withdraw_answer.my_balance_change !amount ? "" : General.formatCrypto( '', amount, @@ -46,9 +47,10 @@ ModalContent TextEditWithTitle { title: qsTr("Fees") + text: { - let amount = result.fees + let amount = result.withdraw_answer.fee_details.amount !amount ? "" : General.formatCrypto( '', amount, @@ -60,42 +62,36 @@ ModalContent } // Date - TextEditWithTitle { + TextEditWithTitle + { title: qsTr("Date") - text: result.date + text: result.withdraw_answer.date } // Transaction Hash - TextEditWithTitle { + TextEditWithTitle + { id: tx_hash + Layout.fillWidth: true title: qsTr("Transaction Hash") } // Buttons - footer: [ - Item { + footer: + [ + DexButton + { Layout.fillWidth: true - }, - DexButton { text: qsTr("Close") - leftPadding: 40 - rightPadding: 40 radius: 18 - onClicked: onClose() + onClicked: close() }, - Item { + DexAppOutlineButton + { Layout.fillWidth: true - }, - DexAppOutlineButton { text: qsTr("View on Explorer") - leftPadding: 40 - rightPadding: 40 radius: 18 onClicked: General.viewTxAtExplorer(api_wallet_page.ticker, tx_hash.text) - }, - Item { - Layout.fillWidth: true } - ] } diff --git a/atomic_defi_design/Dex/Wallet/TransactionDetailsModal.qml b/atomic_defi_design/Dex/Wallet/TransactionDetailsModal.qml index 6c3ff61a70..f6e8e37855 100644 --- a/atomic_defi_design/Dex/Wallet/TransactionDetailsModal.qml +++ b/atomic_defi_design/Dex/Wallet/TransactionDetailsModal.qml @@ -10,48 +10,50 @@ import App 1.0 import Dex.Themes 1.0 as Dex // Open Transaction Details Modal -BasicModal { +MultipageModal +{ id: root - function reset() { - - } + function reset() { } property var details - onClosed: { - if(notes.field.enabled) notes.save_button.clicked() + onClosed: + { + if (notes.field.enabled) notes.save_button.clicked() details = undefined } - ModalContent { - title: qsTr("Transaction Details") + MultipageModalContent + { + titleText: qsTr("Transaction Details") // Amount - TextEditWithTitle { + TextEditWithTitle + { title: qsTr("Amount") - text: !details ? "" : - General.formatCrypto(!details.am_i_sender, details.amount, api_wallet_page.ticker, details.amount_fiat, API.app.settings_pg.current_currency) - value_color: !details ? "white" : - details.am_i_sender ? DexTheme.redColor : DexTheme.greenColor + text: !details ? "" : General.formatCrypto(!details.am_i_sender, details.amount, api_wallet_page.ticker, details.amount_fiat, API.app.settings_pg.current_currency) + value_color: !details ? "white" : details.am_i_sender ? DexTheme.redColor : DexTheme.greenColor privacy: true + label.font.pixelSize: 13 } // Fees - TextEditWithTitle { + TextEditWithTitle + { title: qsTr("Fees") - text: !details ? "" : - General.formatCrypto(parseFloat(details.fees) < 0, Math.abs(parseFloat(details.fees)), current_ticker_infos.fee_ticker, details.fees_amount_fiat, API.app.settings_pg.current_currency) - value_color: !details ? "white" : - parseFloat(details.fees) > 0 ? DexTheme.redColor : DexTheme.greenColor + text: !details ? "" : General.formatCrypto(parseFloat(details.fees) < 0, Math.abs(parseFloat(details.fees)), current_ticker_infos.fee_ticker, details.fees_amount_fiat, API.app.settings_pg.current_currency) + value_color: !details ? "white" : parseFloat(details.fees) > 0 ? DexTheme.redColor : DexTheme.greenColor privacy: true + label.font.pixelSize: 13 } // Date - TextEditWithTitle { + TextEditWithTitle + { title: qsTr("Date") - text: !details ? "" : - details.timestamp === 0 ? qsTr("Unconfirmed"): details.date + text: !details ? "" : details.timestamp === 0 ? qsTr("Unconfirmed"): details.date + label.font.pixelSize: 13 } // Transaction Hash @@ -59,8 +61,8 @@ BasicModal { { id: txHash title: qsTr("Transaction Hash") - text: !details ? "" : - details.tx_hash + text: !details ? "" : details.tx_hash + label.font.pixelSize: 13 privacy: true copy: true @@ -69,17 +71,19 @@ BasicModal { } // Confirmations - TextEditWithTitle { + TextEditWithTitle + { title: qsTr("Confirmations") - text: !details ? "" : - details.confirmations + text: !details ? "" : details.confirmations + label.font.pixelSize: 13 } // Block Height - TextEditWithTitle { + TextEditWithTitle + { title: qsTr("Block Height") - text: !details ? "" : - details.blockheight + text: !details ? "" : details.blockheight + label.font.pixelSize: 13 } DexRectangle { @@ -110,51 +114,48 @@ BasicModal { } // Notes - TextAreaWithTitle { + TextAreaWithTitle + { id: notes + + property string prev_text: "" + title: qsTr("Notes") + titleColor: Dex.CurrentTheme.foregroundColor2 remove_newline: false - field.text: !details ? "" : - details.transaction_note - + field.text: !details ? "" : details.transaction_note + saveable: true - property string prev_text: "" - field.onTextChanged: { - if(field.text.length > 500) - field.text = prev_text + field.onTextChanged: + { + if (field.text.length > 500) field.text = prev_text else prev_text = field.text } onSaved: details.transaction_note = field.text - saveable: true } // Buttons - footer: [ - Item { + footer: + [ + DexButton + { Layout.fillWidth: true - }, - DexButton { text: qsTr("Close") leftPadding: 40 rightPadding: 40 radius: 18 onClicked: root.close() }, - Item { + DexAppOutlineButton + { Layout.fillWidth: true - }, - DexAppOutlineButton { text: qsTr("View on Explorer") leftPadding: 40 rightPadding: 40 radius: 18 onClicked: General.viewTxAtExplorer(api_wallet_page.ticker, details.tx_hash, false) - }, - Item { - Layout.fillWidth: true } - ] } } diff --git a/atomic_defi_design/bignumberjs/bignumber.js b/atomic_defi_design/imports/bignumberjs/bignumber.js similarity index 100% rename from atomic_defi_design/bignumberjs/bignumber.js rename to atomic_defi_design/imports/bignumberjs/bignumber.js diff --git a/atomic_defi_design/bignumberjs/qmldir b/atomic_defi_design/imports/bignumberjs/qmldir similarity index 100% rename from atomic_defi_design/bignumberjs/qmldir rename to atomic_defi_design/imports/bignumberjs/qmldir diff --git a/atomic_defi_design/imports/qml.qrc b/atomic_defi_design/imports/qml.qrc new file mode 100644 index 0000000000..04741ccec9 --- /dev/null +++ b/atomic_defi_design/imports/qml.qrc @@ -0,0 +1,6 @@ + + + bignumberjs/qmldir + bignumberjs/bignumber.js/bignumber.js + + \ No newline at end of file diff --git a/atomic_defi_design/qml.qrc b/atomic_defi_design/qml.qrc index adca6c874a..fea5c25f36 100644 --- a/atomic_defi_design/qml.qrc +++ b/atomic_defi_design/qml.qrc @@ -366,7 +366,6 @@ Dex/Components/AmountIntField.qml Dex/Components/AnimatedRectangle.qml Dex/Components/Arrow.qml - Dex/Components/BasicModal.qml Dex/Components/Blank.qml Dex/Components/CannotEnableCoinModal.qml Dex/Components/CexInfoModal.qml @@ -398,6 +397,7 @@ Dex/Components/DefaultRangeSlider.qml Dex/Components/DefaultRectangle.qml Dex/Components/DefaultScrollBar.qml + Dex/Components/DefaultScrollView.qml Dex/Components/DefaultSlider.qml Dex/Components/DefaultSplitView.qml Dex/Components/DefaultSubstractRectangle.qml @@ -480,10 +480,10 @@ Dex/Components/LoaderBusyIndicator.qml Dex/Components/LogModal.qml Dex/Components/MinTradeModal.qml - Dex/Components/ModalContent.qml - Dex/Components/ModalContent2.qml Dex/Components/ModalHeader.qml Dex/Components/ModalLoader.qml + Dex/Components/MultipageModal.qml + Dex/Components/MultipageModalContent.qml Dex/Components/OutlineButton.qml Dex/Components/Pagination.qml Dex/Components/PaginationButton.qml @@ -632,7 +632,5 @@ Dex/main.qml qtquickcontrols2.conf Dex/Components/PopupManager.qml - bignumberjs/qmldir - bignumberjs/bignumber.js/bignumber.js diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8ed57fc35d..25ab4e6aa4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -74,6 +74,7 @@ add_executable(${PROJECT_NAME} ##! QRC ${CMAKE_SOURCE_DIR}/atomic_defi_design/qml.qrc + ${CMAKE_SOURCE_DIR}/atomic_defi_design/imports/qml.qrc ##! Linguistic ${QM_FILES} diff --git a/src/app/app.cpp b/src/app/app.cpp index 3c4482fc47..f47a8e2e0b 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -17,6 +17,7 @@ //! Deps #include #include +#include //! QT #include @@ -151,7 +152,7 @@ namespace atomic_dex return true; } - bool + bool application::disable_no_balance_coins() { auto* portfolio_page = get_portfolio_page(); @@ -169,6 +170,17 @@ namespace atomic_dex return disable_coins(coins_to_disable); } + bool + application::has_coins_with_balance() + { + auto* portfolio_page = get_portfolio_page(); + auto* portfolio_mdl = portfolio_page->get_portfolio(); + auto portfolio_data = portfolio_mdl->get_underlying_data(); + + auto functor = [](const auto& coin) { return coin.balance.toFloat() > 0; }; + return ranges::any_of(portfolio_data, functor); + } + bool atomic_dex::application::first_run() { diff --git a/src/app/app.hpp b/src/app/app.hpp index a205c5c895..82c1b11af0 100644 --- a/src/app/app.hpp +++ b/src/app/app.hpp @@ -171,6 +171,7 @@ namespace atomic_dex Q_INVOKABLE [[nodiscard]] bool do_i_have_enough_funds(const QString& ticker, const QString& amount) const; Q_INVOKABLE bool disable_coins(const QStringList& coins); Q_INVOKABLE bool disable_no_balance_coins(); + Q_INVOKABLE bool has_coins_with_balance(); Q_INVOKABLE QString get_fiat_from_amount(const QString& ticker, const QString& amount); signals: diff --git a/src/core/atomicdex/api/api.call.hpp b/src/core/atomicdex/api/api.call.hpp new file mode 100644 index 0000000000..9f824ed8cc --- /dev/null +++ b/src/core/atomicdex/api/api.call.hpp @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright © 2013-2022 The Komodo Platform Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * Komodo Platform software, including this file may be copied, modified, * + * propagated or distributed except according to the terms contained in the * + * LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#pragma once + +namespace atomic_dex +{ + template + concept api_call = requires(T t) + { + T::endpoint || t.endpoint; + typename T::expected_request_type; t.request; + typename T::expected_answer_type; t.answer; + }; +} \ No newline at end of file diff --git a/src/core/atomicdex/api/mm2/mm2.client.cpp b/src/core/atomicdex/api/mm2/mm2.client.cpp index 8eab3ff8a5..0b51757b58 100644 --- a/src/core/atomicdex/api/mm2/mm2.client.cpp +++ b/src/core/atomicdex/api/mm2/mm2.client.cpp @@ -1,28 +1,72 @@ -// -// Created by Sztergbaum Roman on 27/03/2021. -// - -//! Deps +/****************************************************************************** + * Copyright © 2013-2022 The Komodo Platform Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * Komodo Platform software, including this file may be copied, modified, * + * propagated or distributed except according to the terms contained in the * + * LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +// Deps Headers #include -//! Project Headers +// Project Headers #include "atomicdex/api/mm2/mm2.client.hpp" #include "atomicdex/api/mm2/mm2.hpp" #include "atomicdex/api/mm2/rpc.tx.history.hpp" +#include "rpc.get.public.key.hpp" +#include "rpc.hpp" namespace { template using have_error_field = decltype(std::declval().error.has_value()); - t_http_client - generate_client() + t_http_client generate_client() { web::http::client::http_client_config cfg; using namespace std::chrono_literals; cfg.set_timeout(30s); return web::http::client::http_client(FROM_STD_STR(::mm2::api::g_endpoint), cfg); } + + template + web::http::http_request make_request(typename Rpc::expected_request_type data_req = {}) + { + web::http::http_request request; + nlohmann::json json_req = {{"method", Rpc::endpoint}, {"userpass", mm2::api::get_rpc_password()}}; + + request.set_method(web::http::methods::POST); + if (Rpc::is_v2) + { + json_req["mmrpc"] = "2.0"; + json_req.push_back({"params", data_req}); + } + else + { + json_req.insert(json_req.end(), nlohmann::json(data_req)); + } + request.set_body(json_req.dump()); + return request; + } + + template + typename Rpc::expected_answer_type make_answer(const web::http::http_response& answer) + { + auto json_answer = nlohmann::json::parse(TO_STD_STR(answer.extract_string(true).get())); + if (Rpc::is_v2) + { + return json_answer.at("result").get(); + } + return json_answer.get(); + } } // namespace namespace atomic_dex @@ -91,6 +135,28 @@ namespace atomic_dex return resp; } + template <::mm2::api::rpc ApiCallType> + void mm2_client::process_rpc_async(const std::function& on_rpc_processed) + { + auto request = make_request(); + generate_client() + .request(request, m_token_source.get_token()) + .template then([on_rpc_processed](const web::http::http_response& resp) + { + try + { + auto answer = make_answer(resp); + on_rpc_processed(answer); + } + catch (const std::exception& ex) + { + SPDLOG_ERROR(ex.what()); + } + }); + } + + template void mm2_client::process_rpc_async(const std::function&); + void mm2_client::stop() { diff --git a/src/core/atomicdex/api/mm2/mm2.client.hpp b/src/core/atomicdex/api/mm2/mm2.client.hpp index b483ca0989..fb86964b2f 100644 --- a/src/core/atomicdex/api/mm2/mm2.client.hpp +++ b/src/core/atomicdex/api/mm2/mm2.client.hpp @@ -1,12 +1,16 @@ #pragma once -//! Deps +// Std Headers +#include + +// Deps Headers #include -//! Project Headers +// Project Headers #include "atomicdex/utilities/cpprestsdk.utilities.hpp" -#include "atomicdex/api/mm2/rpc.disable.hpp" -#include "atomicdex/api/mm2/rpc.recover.funds.hpp" +#include "rpc.disable.hpp" +#include "rpc.recover.funds.hpp" +#include "rpc.hpp" namespace atomic_dex { @@ -24,6 +28,9 @@ namespace atomic_dex //! API pplx::task async_rpc_batch_standalone(nlohmann::json batch_array); + template + void process_rpc_async(const std::function& on_rpc_processed); + //! Synced template TAnswer process_rpc(TRequest&& request, std::string rpc_command); diff --git a/src/core/atomicdex/api/mm2/rpc.get.public.key.cpp b/src/core/atomicdex/api/mm2/rpc.get.public.key.cpp new file mode 100644 index 0000000000..966f4d911a --- /dev/null +++ b/src/core/atomicdex/api/mm2/rpc.get.public.key.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** + * Copyright © 2013-2022 The Komodo Platform Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * Komodo Platform software, including this file may be copied, modified, * + * propagated or distributed except according to the terms contained in the * + * LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +// Deps Headers +#include + +// Project Headers +#include "rpc.get.public.key.hpp" + +namespace atomic_dex::mm2 +{ + void from_json(const nlohmann::json& json, get_public_key_answer& in) + { + json.at("public_key").get_to(in.public_key); + } +} \ No newline at end of file diff --git a/src/core/atomicdex/api/mm2/rpc.get.public.key.hpp b/src/core/atomicdex/api/mm2/rpc.get.public.key.hpp new file mode 100644 index 0000000000..e7afee1abf --- /dev/null +++ b/src/core/atomicdex/api/mm2/rpc.get.public.key.hpp @@ -0,0 +1,45 @@ +/****************************************************************************** + * Copyright © 2013-2022 The Komodo Platform Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * Komodo Platform software, including this file may be copied, modified, * + * propagated or distributed except according to the terms contained in the * + * LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#pragma once + +// Std Headers +#include + +// Deps Headers +#include + +namespace atomic_dex::mm2 +{ + struct get_public_key + { + static constexpr auto endpoint = "get_public_key"; + static constexpr bool is_v2 = true; + struct expected_request_type + { + + } request; + struct expected_answer_type + { + std::string public_key; + } answer; + }; + using get_public_key_request = get_public_key::expected_request_type; + using get_public_key_answer = get_public_key::expected_answer_type; + + inline void to_json([[maybe_unused]] nlohmann::json& j, const get_public_key_request&) { } + void from_json(const nlohmann::json& json, get_public_key_answer& in); +} \ No newline at end of file diff --git a/src/core/atomicdex/api/mm2/rpc.hpp b/src/core/atomicdex/api/mm2/rpc.hpp new file mode 100644 index 0000000000..517420762b --- /dev/null +++ b/src/core/atomicdex/api/mm2/rpc.hpp @@ -0,0 +1,32 @@ +/****************************************************************************** +* Copyright © 2013-2022 The Komodo Platform Developers. * +* * +* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * +* the top-level directory of this distribution for the individual copyright * +* holder information and the developer policies on copyright and licensing. * +* * +* Unless otherwise agreed in a custom licensing agreement, no part of the * +* Komodo Platform software, including this file may be copied, modified, * +* propagated or distributed except according to the terms contained in the * +* LICENSE file * +* * +* Removal or modification of this copyright notice is prohibited. * +* * +******************************************************************************/ + +#pragma once + +// Std Headers +#include + +// Project Headers +#include "../api.call.hpp" + +namespace mm2::api +{ + template + concept rpc = requires(Rpc rpc) + { + atomic_dex::api_call && Rpc::is_v2 && std::is_same_v; + }; +} diff --git a/src/core/atomicdex/pages/qt.settings.page.cpp b/src/core/atomicdex/pages/qt.settings.page.cpp index a8fa01df32..bcbb52a64f 100644 --- a/src/core/atomicdex/pages/qt.settings.page.cpp +++ b/src/core/atomicdex/pages/qt.settings.page.cpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2013-2021 The Komodo Platform Developers. * + * Copyright © 2013-2022 The Komodo Platform Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -14,17 +14,17 @@ * * ******************************************************************************/ -//! QT +// Qt Headers #include #include #include #include #include -//! Deps +// Deps Headers #include -//! Project Headers +// Project Headers #include "atomicdex/events/events.hpp" #include "atomicdex/managers/qt.wallet.manager.hpp" #include "atomicdex/models/qt.global.coins.cfg.model.hpp" @@ -35,13 +35,12 @@ #include "atomicdex/services/price/global.provider.hpp" #include "atomicdex/utilities/global.utilities.hpp" #include "atomicdex/utilities/qt.utilities.hpp" +#include "atomicdex/api/mm2/rpc.get.public.key.hpp" namespace { - void - copy_icon(const QString icon_filepath, const QString icons_path_directory, const std::string& ticker) + void copy_icon(const QString icon_filepath, const QString icons_path_directory, const std::string& ticker) { - SPDLOG_INFO("copying icon"); if (not icon_filepath.isEmpty()) { const fs::path& suffix = fs::path(icon_filepath.toStdString()).extension(); @@ -49,41 +48,42 @@ namespace icon_filepath.toStdString(), fs::path(icons_path_directory.toStdString()) / (boost::algorithm::to_lower_copy(ticker) + suffix.string()), get_override_options()); } - SPDLOG_INFO("copying icon finished"); } -} // namespace +} // anonymous namespace -//! Constructo destructor namespace atomic_dex { settings_page::settings_page(entt::registry& registry, ag::ecs::system_manager& system_manager, std::shared_ptr app, QObject* parent) : QObject(parent), system(registry), m_system_manager(system_manager), m_app(app) + {} + + void settings_page::init_lang() { - SPDLOG_INFO("settings_page created"); + set_current_lang(get_current_lang()); } -} // namespace atomic_dex -//! Override -namespace atomic_dex -{ - void - settings_page::update() + void settings_page::garbage_collect_qml() { + SPDLOG_INFO("Garbage collecting QML Engine"); + m_qml_engine->collectGarbage(); + m_qml_engine->trimComponentCache(); + m_qml_engine->clearComponentCache(); } } // namespace atomic_dex -//! Properties +// Base Class ag::ecs::pre_update_system +namespace atomic_dex { void settings_page::update() {} } + +// Getters|Setters namespace atomic_dex { - QString - settings_page::get_current_lang() const + QString settings_page::get_current_lang() const { QSettings& settings = entity_registry_.ctx(); return settings.value("CurrentLang").toString(); } - void - atomic_dex::settings_page::set_current_lang(QString new_lang) + void atomic_dex::settings_page::set_current_lang(QString new_lang) { const std::string new_lang_std = new_lang.toStdString(); QSettings& settings = entity_registry_.ctx(); @@ -122,14 +122,12 @@ namespace atomic_dex SPDLOG_INFO("Post lang changed"); } - bool - atomic_dex::settings_page::is_notification_enabled() const + bool atomic_dex::settings_page::is_notification_enabled() const { return m_config.notification_enabled; } - void - settings_page::set_notification_enabled(bool is_enabled) + void settings_page::set_notification_enabled(bool is_enabled) { if (m_config.notification_enabled != is_enabled) { @@ -138,26 +136,22 @@ namespace atomic_dex } } - QString - settings_page::get_current_currency_sign() const + QString settings_page::get_current_currency_sign() const { return QString::fromStdString(this->m_config.current_currency_sign); } - QString - settings_page::get_current_fiat_sign() const + QString settings_page::get_current_fiat_sign() const { return QString::fromStdString(this->m_config.current_fiat_sign); } - QString - settings_page::get_current_currency() const + QString settings_page::get_current_currency() const { return QString::fromStdString(this->m_config.current_currency); } - void - settings_page::set_current_currency(const QString& current_currency) + void settings_page::set_current_currency(const QString& current_currency) { bool can_proceed = true; std::string reason = ""; @@ -200,14 +194,12 @@ namespace atomic_dex } } - QString - settings_page::get_current_fiat() const + QString settings_page::get_current_fiat() const { return QString::fromStdString(this->m_config.current_fiat); } - void - settings_page::set_current_fiat(const QString& current_fiat) + void settings_page::set_current_fiat(const QString& current_fiat) { if (m_system_manager.get_system().is_fiat_available(current_fiat.toStdString())) { @@ -224,42 +216,78 @@ namespace atomic_dex SPDLOG_ERROR("Cannot change fiat, because other rates are not available"); } } -} // namespace atomic_dex -//! Public API -namespace atomic_dex -{ - atomic_dex::cfg& - settings_page::get_cfg() + bool settings_page::is_fetching_custom_token_data_busy() const { - return m_config; + return m_fetching_erc_data_busy.load(); + } + + void settings_page::set_fetching_custom_token_data_busy(bool status) + { + if (m_fetching_erc_data_busy != status) + { + m_fetching_erc_data_busy = status; + emit customTokenDataStatusChanged(); + } + } + + QVariant settings_page::get_custom_token_data() const + { + return nlohmann_json_object_to_qt_json_object(m_custom_token_data.get()); + } + + void settings_page::set_custom_token_data(QVariant rpc_data) + { + nlohmann::json out = nlohmann::json::parse(QString(QJsonDocument(rpc_data.toJsonObject()).toJson()).toStdString()); + m_custom_token_data = out; + emit customTokenDataChanged(); + } + + bool settings_page::is_fetching_priv_key_busy() const + { + return m_fetching_priv_keys_busy.load(); + } + + void settings_page::set_fetching_priv_key_busy(bool status) + { + if (m_fetching_priv_keys_busy != status) + { + m_fetching_priv_keys_busy = status; + emit privKeyStatusChanged(); + } } - const atomic_dex::cfg& - settings_page::get_cfg() const + bool settings_page::is_fetching_public_key() const + { + return fetching_public_key; + } + + const QString& settings_page::get_public_key() const + { + return public_key; + } + + atomic_dex::cfg& settings_page::get_cfg() { return m_config; } - void - settings_page::init_lang() + const atomic_dex::cfg& settings_page::get_cfg() const { - set_current_lang(get_current_lang()); + return m_config; } } // namespace atomic_dex -//! QML API +// QML API namespace atomic_dex { - QStringList - settings_page::get_available_langs() const + QStringList settings_page::get_available_langs() const { QSettings& settings = entity_registry_.ctx(); return settings.value("AvailableLang").toStringList(); } - QStringList - settings_page::get_available_fiats() const + QStringList settings_page::get_available_fiats() const { QStringList out; out.reserve(m_config.available_fiat.size()); @@ -268,8 +296,7 @@ namespace atomic_dex return out; } - QStringList - settings_page::get_recommended_fiats() const + QStringList settings_page::get_recommended_fiats() const { static const auto nb_recommended = 6; QStringList out; @@ -281,8 +308,7 @@ namespace atomic_dex return out; } - QStringList - settings_page::get_available_currencies() const + QStringList settings_page::get_available_currencies() const { QStringList out; out.reserve(m_config.possible_currencies.size()); @@ -290,26 +316,22 @@ namespace atomic_dex return out; } - bool - settings_page::is_this_ticker_present_in_raw_cfg(const QString& ticker) const + bool settings_page::is_this_ticker_present_in_raw_cfg(const QString& ticker) const { return m_system_manager.get_system().is_this_ticker_present_in_raw_cfg(ticker.toStdString()); } - bool - settings_page::is_this_ticker_present_in_normal_cfg(const QString& ticker) const + bool settings_page::is_this_ticker_present_in_normal_cfg(const QString& ticker) const { return m_system_manager.get_system().is_this_ticker_present_in_normal_cfg(ticker.toStdString()); } - QString - settings_page::get_custom_coins_icons_path() const + QString settings_page::get_custom_coins_icons_path() const { return std_path_to_qstring(utils::get_runtime_coins_path()); } - void - settings_page::process_qrc_20_token_add(const QString& contract_address, const QString& coingecko_id, const QString& icon_filepath) + void settings_page::process_qrc_20_token_add(const QString& contract_address, const QString& coingecko_id, const QString& icon_filepath) { this->set_fetching_custom_token_data_busy(true); using namespace std::string_literals; @@ -395,8 +417,7 @@ namespace atomic_dex ::mm2::api::async_process_rpc_get(::mm2::api::g_qtum_proxy_http_client, "qrc_infos", url).then(answer_functor).then(&handle_exception_pplx_task); } - void - settings_page::process_token_add(const QString& contract_address, const QString& coingecko_id, const QString& icon_filepath, CoinType coin_type) + void settings_page::process_token_add(const QString& contract_address, const QString& coingecko_id, const QString& icon_filepath, CoinType coin_type) { this->set_fetching_custom_token_data_busy(true); using namespace std::string_literals; @@ -493,38 +514,7 @@ namespace atomic_dex ::mm2::api::async_process_rpc_get(*endpoint, "token_infos", url).then(answer_functor).then(&handle_exception_pplx_task); } - bool - settings_page::is_fetching_custom_token_data_busy() const - { - return m_fetching_erc_data_busy.load(); - } - - void - settings_page::set_fetching_custom_token_data_busy(bool status) - { - if (m_fetching_erc_data_busy != status) - { - m_fetching_erc_data_busy = status; - emit customTokenDataStatusChanged(); - } - } - - QVariant - settings_page::get_custom_token_data() const - { - return nlohmann_json_object_to_qt_json_object(m_custom_token_data.get()); - } - - void - settings_page::set_custom_token_data(QVariant rpc_data) - { - nlohmann::json out = nlohmann::json::parse(QString(QJsonDocument(rpc_data.toJsonObject()).toJson()).toStdString()); - m_custom_token_data = out; - emit customTokenDataChanged(); - } - - void - settings_page::submit() + void settings_page::submit() { SPDLOG_DEBUG("submit whole cfg"); nlohmann::json out = m_custom_token_data.get(); @@ -532,21 +522,18 @@ namespace atomic_dex this->set_custom_token_data(QJsonObject{{}}); } - void - settings_page::remove_custom_coin(const QString& ticker) + void settings_page::remove_custom_coin(const QString& ticker) { SPDLOG_DEBUG("remove ticker: {}", ticker.toStdString()); this->m_system_manager.get_system().remove_custom_coin(ticker.toStdString()); } - void - settings_page::set_qml_engine(QQmlApplicationEngine* engine) + void settings_page::set_qml_engine(QQmlApplicationEngine* engine) { m_qml_engine = engine; } - void - settings_page::reset_coin_cfg() + void settings_page::reset_coin_cfg() { using namespace std::string_literals; const std::string wallet_name = qt_wallet_manager::get_default_wallet_name().toStdString(); @@ -614,8 +601,7 @@ namespace atomic_dex functor_remove(std::move(theme_path)); } - QStringList - settings_page::retrieve_seed(const QString& wallet_name, const QString& password) + QStringList settings_page::retrieve_seed(const QString& wallet_name, const QString& password) { QStringList out; std::error_code ec; @@ -680,52 +666,40 @@ namespace atomic_dex return {QString::fromStdString(seed), QString::fromStdString(::mm2::api::get_rpc_password())}; } - QString - settings_page::get_version() + QString settings_page::get_version() { return QString::fromStdString(atomic_dex::get_version()); } - QString - settings_page::get_log_folder() + QString settings_page::get_log_folder() { return QString::fromStdString(utils::get_atomic_dex_logs_folder().string()); } - QString - settings_page::get_mm2_version() + QString settings_page::get_mm2_version() { return QString::fromStdString(::mm2::api::rpc_version()); } - QString - settings_page::get_export_folder() + QString settings_page::get_export_folder() { return QString::fromStdString(utils::get_atomic_dex_export_folder().string()); } - bool - settings_page::is_fetching_priv_key_busy() const - { - return m_fetching_priv_keys_busy.load(); - } - void - settings_page::set_fetching_priv_key_busy(bool status) + void settings_page::fetchPublicKey() { - if (m_fetching_priv_keys_busy != status) + auto& mm2_system = m_system_manager.get_system(); + auto get_pub_key_rpc_callback = [this](auto pub_key_answ) { - m_fetching_priv_keys_busy = status; - emit privKeyStatusChanged(); - } - } + public_key = QString::fromStdString(pub_key_answ.public_key); + fetching_public_key = false; + emit publicKeyChanged(); + emit fetchingPublicKeyChanged(); + }; - void - settings_page::garbage_collect_qml() - { - SPDLOG_INFO("garbage_collect_qml"); - m_qml_engine->collectGarbage(); - // m_qml_engine-> - m_qml_engine->trimComponentCache(); - m_qml_engine->clearComponentCache(); + fetching_public_key = true; + emit fetchingPublicKeyChanged(); + + mm2_system.get_mm2_client().process_rpc_async(get_pub_key_rpc_callback); } } // namespace atomic_dex diff --git a/src/core/atomicdex/pages/qt.settings.page.hpp b/src/core/atomicdex/pages/qt.settings.page.hpp index ab9d27717a..444d5e9247 100644 --- a/src/core/atomicdex/pages/qt.settings.page.hpp +++ b/src/core/atomicdex/pages/qt.settings.page.hpp @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright © 2013-2021 The Komodo Platform Developers. * + * Copyright © 2013-2022 The Komodo Platform Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -16,19 +16,19 @@ #pragma once -//! QT +// QT Headers #include #include #include #include #include -//! Deps +// Deps Headers #include #include #include -//! Project headers +// Project Headers #include "atomicdex/config/app.cfg.hpp" #include "atomicdex/constants/qt.coins.enums.hpp" @@ -36,83 +36,85 @@ namespace atomic_dex { class settings_page final : public QObject, public ag::ecs::pre_update_system { - //! Q_Object definition Q_OBJECT - //! Properties - Q_PROPERTY(QString lang READ get_current_lang WRITE set_current_lang NOTIFY onLangChanged) - Q_PROPERTY(QString current_currency READ get_current_currency WRITE set_current_currency NOTIFY onCurrencyChanged) - Q_PROPERTY(QString current_currency_sign READ get_current_currency_sign NOTIFY onCurrencySignChanged) - Q_PROPERTY(QString current_fiat_sign READ get_current_fiat_sign NOTIFY onFiatSignChanged) - Q_PROPERTY(QString current_fiat READ get_current_fiat WRITE set_current_fiat NOTIFY onFiatChanged) - Q_PROPERTY(bool notification_enabled READ is_notification_enabled WRITE set_notification_enabled NOTIFY onNotificationEnabledChanged) - Q_PROPERTY(QVariant custom_token_data READ get_custom_token_data WRITE set_custom_token_data NOTIFY customTokenDataChanged) - Q_PROPERTY(bool fetching_custom_token_data_busy READ is_fetching_custom_token_data_busy WRITE set_fetching_custom_token_data_busy NOTIFY - customTokenDataStatusChanged) - Q_PROPERTY(bool fetching_priv_keys_busy READ is_fetching_priv_key_busy WRITE set_fetching_priv_key_busy NOTIFY privKeyStatusChanged) + // QML Properties + Q_PROPERTY(QString lang READ get_current_lang WRITE set_current_lang NOTIFY onLangChanged) + Q_PROPERTY(QString current_currency READ get_current_currency WRITE set_current_currency NOTIFY onCurrencyChanged) + Q_PROPERTY(QString current_currency_sign READ get_current_currency_sign NOTIFY onCurrencySignChanged) + Q_PROPERTY(QString current_fiat_sign READ get_current_fiat_sign NOTIFY onFiatSignChanged) + Q_PROPERTY(QString current_fiat READ get_current_fiat WRITE set_current_fiat NOTIFY onFiatChanged) + Q_PROPERTY(bool notification_enabled READ is_notification_enabled WRITE set_notification_enabled NOTIFY onNotificationEnabledChanged) + Q_PROPERTY(QVariant custom_token_data READ get_custom_token_data WRITE set_custom_token_data NOTIFY customTokenDataChanged) + Q_PROPERTY(bool fetching_custom_token_data_busy READ is_fetching_custom_token_data_busy WRITE set_fetching_custom_token_data_busy NOTIFY customTokenDataStatusChanged) + Q_PROPERTY(bool fetching_priv_keys_busy READ is_fetching_priv_key_busy WRITE set_fetching_priv_key_busy NOTIFY privKeyStatusChanged) + Q_PROPERTY(bool fetchingPublicKey READ is_fetching_public_key NOTIFY fetchingPublicKeyChanged) + Q_PROPERTY(QString publicKey READ get_public_key NOTIFY publicKeyChanged) - using t_synchronized_json = boost::synchronized_value; - //! Private member fields Fields - ag::ecs::system_manager& m_system_manager; - std::shared_ptr m_app; - QQmlApplicationEngine* m_qml_engine{nullptr}; - atomic_dex::cfg m_config{load_cfg()}; - QTranslator m_translator; - std::atomic_bool m_fetching_erc_data_busy{false}; - std::atomic_bool m_fetching_priv_keys_busy{false}; - t_synchronized_json m_custom_token_data; + ag::ecs::system_manager& m_system_manager; + std::shared_ptr m_app; + QQmlApplicationEngine* m_qml_engine{nullptr}; + atomic_dex::cfg m_config{load_cfg()}; + QTranslator m_translator; + std::atomic_bool m_fetching_erc_data_busy{false}; + std::atomic_bool m_fetching_priv_keys_busy{false}; + std::atomic_bool fetching_public_key{false}; + QString public_key; + boost::synchronized_value m_custom_token_data; public: explicit settings_page(entt::registry& registry, ag::ecs::system_manager& system_manager, std::shared_ptr app, QObject* parent = nullptr); ~settings_page() final = default; - //! Public override - void update() final; + void init_lang(); + void garbage_collect_qml(); - //! Properties - [[nodiscard]] QString get_current_lang() const; - void set_current_lang(QString new_lang); - [[nodiscard]] QString get_current_currency() const; - [[nodiscard]] QString get_current_currency_sign() const; - [[nodiscard]] QString get_current_fiat_sign() const; - [[nodiscard]] QString get_current_fiat() const; - [[nodiscard]] bool is_notification_enabled() const; - void set_notification_enabled(bool is_enabled); - void set_current_currency(const QString& current_currency); - void set_current_fiat(const QString& current_fiat); - [[nodiscard]] bool is_fetching_custom_token_data_busy() const; - void set_fetching_custom_token_data_busy(bool status); - [[nodiscard]] QVariant get_custom_token_data() const; - void set_custom_token_data(QVariant rpc_data); - [[nodiscard]] bool is_fetching_priv_key_busy() const; - void set_fetching_priv_key_busy(bool status); + // Base Class ag::ecs::pre_update_system + void update() final; - //! Public API - [[nodiscard]] atomic_dex::cfg& get_cfg(); - [[nodiscard]] const atomic_dex::cfg& get_cfg() const; - void init_lang(); - void set_qml_engine(QQmlApplicationEngine* engine); - void garbage_collect_qml(); + // Getters|Setters + [[nodiscard]] QString get_current_lang() const; + void set_current_lang(QString new_lang); + [[nodiscard]] QString get_current_currency() const; + [[nodiscard]] QString get_current_currency_sign() const; + [[nodiscard]] QString get_current_fiat_sign() const; + [[nodiscard]] QString get_current_fiat() const; + [[nodiscard]] bool is_notification_enabled() const; + void set_notification_enabled(bool is_enabled); + void set_current_currency(const QString& current_currency); + void set_current_fiat(const QString& current_fiat); + [[nodiscard]] bool is_fetching_custom_token_data_busy() const; + void set_fetching_custom_token_data_busy(bool status); + [[nodiscard]] QVariant get_custom_token_data() const; + void set_custom_token_data(QVariant rpc_data); + [[nodiscard]] bool is_fetching_priv_key_busy() const; + void set_fetching_priv_key_busy(bool status); + [[nodiscard]] bool is_fetching_public_key() const; + [[nodiscard]] const QString& get_public_key() const; + [[nodiscard]] atomic_dex::cfg& get_cfg(); + [[nodiscard]] const atomic_dex::cfg& get_cfg() const; + void set_qml_engine(QQmlApplicationEngine* engine); // QML API - Q_INVOKABLE void remove_custom_coin(const QString& ticker); - Q_INVOKABLE [[nodiscard]] QStringList get_available_langs() const; - Q_INVOKABLE [[nodiscard]] QStringList get_available_fiats() const; - Q_INVOKABLE [[nodiscard]] QStringList get_recommended_fiats() const; // Returns 6 recommended fiats. Basically, the first 6 values in cfg.json. - Q_INVOKABLE [[nodiscard]] QStringList get_available_currencies() const; - Q_INVOKABLE [[nodiscard]] bool is_this_ticker_present_in_raw_cfg(const QString& ticker) const; - Q_INVOKABLE [[nodiscard]] bool is_this_ticker_present_in_normal_cfg(const QString& ticker) const; - Q_INVOKABLE [[nodiscard]] QString get_custom_coins_icons_path() const; - Q_INVOKABLE void process_token_add(const QString& contract_address, const QString& coingecko_id, const QString& icon_filepath, CoinType coin_type); - Q_INVOKABLE void process_qrc_20_token_add(const QString& contract_address, const QString& coingecko_id, const QString& icon_filepath); - Q_INVOKABLE void submit(); - Q_INVOKABLE void reset_coin_cfg(); - Q_INVOKABLE QStringList retrieve_seed(const QString& wallet_name, const QString& password); - Q_INVOKABLE static QString get_mm2_version(); - Q_INVOKABLE static QString get_log_folder(); - Q_INVOKABLE static QString get_export_folder(); - Q_INVOKABLE static QString get_version(); + Q_INVOKABLE void remove_custom_coin(const QString& ticker); + Q_INVOKABLE [[nodiscard]] QStringList get_available_langs() const; + Q_INVOKABLE [[nodiscard]] QStringList get_available_fiats() const; + Q_INVOKABLE [[nodiscard]] QStringList get_recommended_fiats() const; // Returns 6 recommended fiats. Basically, the first 6 values in cfg.json. + Q_INVOKABLE [[nodiscard]] QStringList get_available_currencies() const; + Q_INVOKABLE [[nodiscard]] bool is_this_ticker_present_in_raw_cfg(const QString& ticker) const; + Q_INVOKABLE [[nodiscard]] bool is_this_ticker_present_in_normal_cfg(const QString& ticker) const; + Q_INVOKABLE [[nodiscard]] QString get_custom_coins_icons_path() const; + Q_INVOKABLE void process_token_add(const QString& contract_address, const QString& coingecko_id, const QString& icon_filepath, CoinType coin_type); + Q_INVOKABLE void process_qrc_20_token_add(const QString& contract_address, const QString& coingecko_id, const QString& icon_filepath); + Q_INVOKABLE void submit(); + Q_INVOKABLE void reset_coin_cfg(); + Q_INVOKABLE QStringList retrieve_seed(const QString& wallet_name, const QString& password); + Q_INVOKABLE static QString get_mm2_version(); + Q_INVOKABLE static QString get_log_folder(); + Q_INVOKABLE static QString get_export_folder(); + Q_INVOKABLE static QString get_version(); + Q_INVOKABLE void fetchPublicKey(); // QML API Properties Signals signals: @@ -126,6 +128,8 @@ namespace atomic_dex void customTokenDataChanged(); void customTokenDataStatusChanged(); void privKeyStatusChanged(); + void fetchingPublicKeyChanged(); + void publicKeyChanged(); }; } // namespace atomic_dex