diff --git a/storybook/PagesModel.qml b/storybook/PagesModel.qml index 69b55c0b5e..4a4b491e5e 100644 --- a/storybook/PagesModel.qml +++ b/storybook/PagesModel.qml @@ -185,6 +185,14 @@ ListModel { title: "FeesPanel" section: "Panels" } + ListElement { + title: "FeeRow" + section: "Panels" + } + ListElement { + title: "FeesBox" + section: "Panels" + } ListElement { title: "ChatPermissionQualificationPanel" section: "Panels" diff --git a/storybook/pages/FeeRowPage.qml b/storybook/pages/FeeRowPage.qml new file mode 100644 index 0000000000..9788d5fdc4 --- /dev/null +++ b/storybook/pages/FeeRowPage.qml @@ -0,0 +1,138 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import Storybook 1.0 +import Models 1.0 + +import AppLayouts.Communities.controls 1.0 + +SplitView { + Pane { + SplitView.fillWidth: true + SplitView.fillHeight: true + + Rectangle { + anchors.fill: feesPanel + anchors.margins: -15 + border.color: "lightgray" + color: "transparent" + } + + FeeRow { + id: feesPanel + + anchors.centerIn: parent + + width: 500 + + title: titleButtonsGroup.checkedButton.title + feeText: feeButtonsGroup.checkedButton.fee + + highlightFee: highlightFeeSwitch.checked + errorFee: errorFeeSwitch.checked + } + } + + Pane { + SplitView.minimumWidth: 300 + SplitView.preferredWidth: 300 + + ColumnLayout { + anchors.fill: parent + + Label { + Layout.fillWidth: true + + text: "Title" + } + + ButtonGroup { + id: titleButtonsGroup + + buttons: titleButtonsRow.children + } + + RowLayout { + id: titleButtonsRow + + RadioButton { + readonly property string title: "Airdrop MCT on Status" + + text: "Short" + checked: true + } + + RadioButton { + readonly property string title: + "Mint Doodles Owner and TokenMaster tokens on Optimism" + + text: "Long" + } + + RadioButton { + readonly property string title: ModelsData.descriptions.medium + + text: "Very Long" + } + } + + Label { + Layout.fillWidth: true + + text: "Fee" + } + + ButtonGroup { + id: feeButtonsGroup + + buttons: feeButtonsRow.children + } + + RowLayout { + id: feeButtonsRow + + RadioButton { + readonly property string fee: "" + + text: "Empty" + checked: true + } + + RadioButton { + readonly property string fee: "13.34 USD (0.0072 ETH)" + + text: "Short" + checked: true + } + + RadioButton { + readonly property string fee: "112 323.34 USD (2223.000272 ETH)" + + text: "Long" + } + } + + MenuSeparator { + Layout.fillWidth: true + } + + Switch { + id: highlightFeeSwitch + + text: "Highlight fee" + enabled: true + } + + Switch { + id: errorFeeSwitch + + text: "Fee error" + } + + Item { + Layout.fillHeight: true + } + } + } +} diff --git a/storybook/pages/FeesBoxPage.qml b/storybook/pages/FeesBoxPage.qml new file mode 100644 index 0000000000..f34fb30750 --- /dev/null +++ b/storybook/pages/FeesBoxPage.qml @@ -0,0 +1,224 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import Qt.labs.settings 1.0 + +import Storybook 1.0 +import Models 1.0 + +import AppLayouts.Communities.panels 1.0 +import utils 1.0 + + +SplitView { + FeesModel { + id: feesModel + } + + ListModel { + id: accountsModel + + ListElement { + name: "Test account" + emoji: "😋" + address: "0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7240" + color: "red" + } + + ListElement { + name: "Another account - generated" + emoji: "🚗" + address: "0x7F47C2e98a4BBf5487E6fb082eC2D9Ab0E6d8888" + color: "blue" + } + } + + LimitProxyModel { + id: filteredModel + + sourceModel: feesModel + limit: countSlider.value + } + + Pane { + SplitView.fillWidth: true + SplitView.fillHeight: true + + FeesBox { + id: feesPanel + + anchors.centerIn: parent + + width: 600 + + model: filteredModel + accountsModel: accountsSwitch.checked ? accountsModel : null + placeholderText: placeholderTextField.text + + totalFeeText: totalCheckBox.checked ? + totalFeeTextField.text : "" + generalErrorText: generalErrorCheckBox.checked ? + generalErrorTextField.text : "" + accountErrorText: accountErrorCheckBox.checked ? + accountErrorTextField.text : "" + } + } + + Pane { + SplitView.minimumWidth: 300 + SplitView.preferredWidth: 300 + + Settings { + property alias countSliderValue: countSlider.value + property alias generalErrorCheckBoxChecked: generalErrorCheckBox.checked + property alias accountErrorCheckBoxChecked: accountErrorCheckBox.checked + property alias totalCheckBoxChecked: totalCheckBox.checked + } + + ColumnLayout { + anchors.fill: parent + + Label { + Layout.fillWidth: true + + wrapMode: Text.Wrap + text: "Placeholder text (visible when model count is 0)" + } + + TextField { + id: placeholderTextField + + Layout.fillWidth: true + + text: "Add valid “What” and “To” values to see fees" + } + + MenuSeparator { + Layout.fillWidth: true + } + + GroupBox { + Layout.fillWidth: true + + ColumnLayout { + anchors.fill: parent + + Label { + Layout.fillWidth: true + + text: "Number of items in the model" + } + + RowLayout { + Slider { + id: countSlider + + from: 0 + to: feesModel.count + value: to + stepSize: 1 + snapMode: Slider.SnapAlways + } + + Label { + text: countSlider.value + } + } + } + } + + + GroupBox { + Layout.fillWidth: true + + ColumnLayout { + anchors.fill: parent + + CheckBox { + id: generalErrorCheckBox + + text: "General error" + } + + Label { + Layout.fillWidth: true + + text: "Error text" + } + TextField { + id: generalErrorTextField + + Layout.fillWidth: true + + text: "Transaction fees exceed block gas limit.\n" + + "Try splitting the recipients into two separate airdrops instead." + } + } + } + + Switch { + id: accountsSwitch + + text: "Accounts selector" + checked: true + } + + GroupBox { + Layout.fillWidth: true + + ColumnLayout { + anchors.fill: parent + + CheckBox { + id: accountErrorCheckBox + + text: "Account error" + } + + Label { + Layout.fillWidth: true + + text: "Error text" + } + + TextField { + id: accountErrorTextField + + Layout.fillWidth: true + + text: "Insufficient funds on Optimism or Status to pay gas fees." + } + } + } + + GroupBox { + Layout.fillWidth: true + + ColumnLayout { + anchors.fill: parent + + CheckBox { + id: totalCheckBox + + checked: true + text: "Total fee" + } + + + TextField { + id: totalFeeTextField + + Layout.fillWidth: true + + text: "0.01 ETH ($265.43)" + } + } + } + + Item { + Layout.fillHeight: true + } + } + } +} diff --git a/storybook/pages/FeesPanelPage.qml b/storybook/pages/FeesPanelPage.qml index 081e119612..6130b3ff99 100644 --- a/storybook/pages/FeesPanelPage.qml +++ b/storybook/pages/FeesPanelPage.qml @@ -2,67 +2,57 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import Storybook 1.0 - import AppLayouts.Communities.panels 1.0 +import Storybook 1.0 +import Models 1.0 + + SplitView { - Logs { id: logs } + FeesModel { + id: feesModel + } - SplitView { - orientation: Qt.Vertical + Pane { SplitView.fillWidth: true + SplitView.fillHeight: true - Pane { - SplitView.fillWidth: true - SplitView.fillHeight: true - - Rectangle { - anchors.fill: feesPanel - anchors.margins: -15 - border.color: "lightgray" - } - - FeesPanel { - id: feesPanel - - anchors.centerIn: parent - - width: 500 - - model: ListModel { - ListElement { - account: "My Account 1" - network: "Optimism" - symbol: "TAT" - amount: 2 - feeText: "0.0015 ($75.43)" - } - ListElement { - account: "My Account 2" - network: "Arbitrum" - symbol: "SNT" - amount: 34 - feeText: "0.0085 ETH ($175.43)" - } - } - - errorText: errorTextField.text - isFeeLoading: loadingSwitch.checked - showSummary: showSummarySwitch.checked - showAccounts: showAccountsSwitch.checked - - totalFeeText: "0.01 ETH ($265.43)" - } + Rectangle { + anchors.fill: feesPanel + anchors.margins: -15 + border.color: "lightgray" + color: "transparent" } - LogsAndControlsPanel { - id: logsAndControlsPanel + FeesPanel { + id: feesPanel - SplitView.minimumHeight: 100 - SplitView.preferredHeight: 150 + anchors.centerIn: parent - logsView.logText: logs.logText + width: 500 + + model: LimitProxyModel { + sourceModel: feesModel + limit: countSlider.value + } + + placeholderText: placeholderTextField.text + + footer: Rectangle { + id: footer + + visible: showFooterSwitch.checked + + height: 100 + + border.color: "lightgray" + color: "transparent" + + Label { + anchors.centerIn: parent + text: "footer" + } + } } } @@ -76,36 +66,44 @@ SplitView { Label { Layout.fillWidth: true - text: "Error text" + text: "Placeholder text" } TextField { - id: errorTextField + id: placeholderTextField Layout.fillWidth: true - - text: "" + text: "Add valid “What” and “To” values to see fees" } Switch { - id: loadingSwitch + id: showFooterSwitch - text: "Is fee loading" - checked: false - } - - Switch { - id: showSummarySwitch - - text: "Show summary" + text: "Show footer" checked: true } - Switch { - id: showAccountsSwitch + Label { + Layout.fillWidth: true - text: "Show account names" - checked: true + text: "Number of items in the model" + } + + RowLayout { + Slider { + id: countSlider + + from: 0 + to: feesModel.count + value: to + + stepSize: 1 + snapMode: Slider.SnapAlways + } + + Label { + text: countSlider.value + } } Item { diff --git a/storybook/pages/SignMultiTokenTransactionsPopupPage.qml b/storybook/pages/SignMultiTokenTransactionsPopupPage.qml index 1f91e48817..fa9e755abd 100644 --- a/storybook/pages/SignMultiTokenTransactionsPopupPage.qml +++ b/storybook/pages/SignMultiTokenTransactionsPopupPage.qml @@ -3,12 +3,17 @@ import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import Storybook 1.0 +import Models 1.0 import AppLayouts.Communities.popups 1.0 SplitView { Logs { id: logs } + FeesModel { + id: feesModel + } + SplitView { orientation: Qt.Vertical SplitView.fillWidth: true @@ -18,6 +23,7 @@ SplitView { SplitView.fillWidth: true SplitView.fillHeight: true + padding: 0 PopupBackground { anchors.fill: parent @@ -33,37 +39,25 @@ SplitView { SignMultiTokenTransactionsPopup { id: dialog - model: ListModel { - id: feesModel + model: LimitProxyModel { + id: filteredModel - ListElement { - account: "My Account 1" - network: "Optimism" - symbol: "TAT" - amount: 2 - feeText: "0.0015 ($75.43)" - } - ListElement { - account: "My Account 2" - network: "Arbitrum" - symbol: "SNT" - amount: 34 - feeText: "0.0085 ETH ($175.43)" - } + sourceModel: feesModel + limit: countSlider.value } closePolicy: Popup.NoAutoClose visible: true modal: false destroyOnClose: false + parent: pane + anchors.centerIn: parent - title: `Sign transaction - Airdrop ${model.count} token(s) to 32 recipients` - - isFeeLoading: loadingSwitch.checked - showSummary: showSummarySwitch.checked + title: `Sign transaction` + accountName: accountTextField.text errorText: errorTextField.text - totalFeeText: "0.01 ETH ($265.43)" + totalFeeText: totalCheckBox.checked ? totalFeeTextField.text : "" onSignTransactionClicked: logs.logEvent("SignMultiTokenTransactionsPopup::onSignTransactionClicked") onCancelClicked: logs.logEvent("SignMultiTokenTransactionsPopup::onCancelClicked") @@ -101,25 +95,72 @@ SplitView { text: "" } - SpinBox { - id: recipientsCountSpinBox + Label { + Layout.fillWidth: true - from: 1 - to: 1000 + wrapMode: Text.Wrap + text: "Account" } - Switch { - id: loadingSwitch + TextField { + id: accountTextField - text: "Is fee loading" - checked: false + Layout.fillWidth: true + + text: "My Account" } - Switch { - id: showSummarySwitch + GroupBox { + Layout.fillWidth: true - text: "Is summary visible" - checked: true + ColumnLayout { + anchors.fill: parent + + Label { + Layout.fillWidth: true + + text: "Number of items in the model" + } + + RowLayout { + Slider { + id: countSlider + + from: 1 + to: feesModel.count + value: to + stepSize: 1 + snapMode: Slider.SnapAlways + } + + Label { + text: countSlider.value + } + } + } + } + + GroupBox { + Layout.fillWidth: true + + ColumnLayout { + anchors.fill: parent + + CheckBox { + id: totalCheckBox + + checked: true + text: "Total fee" + } + + TextField { + id: totalFeeTextField + + Layout.fillWidth: true + + text: "0.01 ETH ($265.43)" + } + } } Item { diff --git a/storybook/src/Models/FeesModel.qml b/storybook/src/Models/FeesModel.qml new file mode 100644 index 0000000000..274d8a0b06 --- /dev/null +++ b/storybook/src/Models/FeesModel.qml @@ -0,0 +1,24 @@ +import QtQuick 2.15 + +ListModel { + ListElement { + title: "Airdropping 2 TAT on Optimism" + feeText: "0.0015 ETH ($75.43)" + error: false + } + ListElement { + title: "Airdropping 43 SNT on Arbitrum" + feeText: "0.0085 ETH ($175.43)" + error: true + } + ListElement { + title: "Airdropping 23.123 LLL on Mainnet" + feeText: "0.0000285 ETH ($3722323235.43)" + error: false + } + ListElement { + title: "Airdropping 3323.2323 DDL on Mainnet" + feeText: "0.0285 ETH ($375.43)" + error: false + } +} diff --git a/storybook/src/Models/qmldir b/storybook/src/Models/qmldir index a69f195045..f6df37989d 100644 --- a/storybook/src/Models/qmldir +++ b/storybook/src/Models/qmldir @@ -4,6 +4,7 @@ AssetsModel 1.0 AssetsModel.qml BannerModel 1.0 BannerModel.qml ChannelsModel 1.0 ChannelsModel.qml CollectiblesModel 1.0 CollectiblesModel.qml +FeesModel 1.0 FeesModel.qml IconModel 1.0 IconModel.qml MintedTokensModel 1.0 MintedTokensModel.qml RecipientModel 1.0 RecipientModel.qml diff --git a/ui/StatusQ/src/StatusQ/Components/StatusEmojiAndColorComboBox.qml b/ui/StatusQ/src/StatusQ/Components/StatusEmojiAndColorComboBox.qml index 89baf97091..daf9bd2859 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusEmojiAndColorComboBox.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusEmojiAndColorComboBox.qml @@ -52,8 +52,8 @@ StatusComboBox { QtObject { id: d - readonly property string emoji: ModelUtils.get(root.model, currentIndex, "emoji") - readonly property string color: ModelUtils.get(root.model, currentIndex, "color") + readonly property string emoji: ModelUtils.get(root.model, currentIndex, "emoji") ?? "" + readonly property string color: ModelUtils.get(root.model, currentIndex, "color") ?? "" } control.textRole: "name" diff --git a/ui/app/AppLayouts/Communities/controls/AccountSelector.qml b/ui/app/AppLayouts/Communities/controls/AccountSelector.qml new file mode 100644 index 0000000000..ceaae377be --- /dev/null +++ b/ui/app/AppLayouts/Communities/controls/AccountSelector.qml @@ -0,0 +1,9 @@ +import StatusQ.Components 0.1 +import StatusQ.Controls 0.1 + +StatusEmojiAndColorComboBox { + type: StatusComboBox.Type.Secondary + size: StatusComboBox.Size.Small + implicitHeight: 44 + defaultAssetName: "filled-account" +} diff --git a/ui/app/AppLayouts/Communities/controls/FeeRow.qml b/ui/app/AppLayouts/Communities/controls/FeeRow.qml new file mode 100644 index 0000000000..4c2768d996 --- /dev/null +++ b/ui/app/AppLayouts/Communities/controls/FeeRow.qml @@ -0,0 +1,85 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +import StatusQ.Core 0.1 +import StatusQ.Components 0.1 +import StatusQ.Core.Theme 0.1 + +import utils 1.0 + +Control { + id: root + + property string title + property string feeText + + property bool highlightFee: false + property bool errorFee: false + + background: null + + contentItem: Item { + implicitHeight: Math.max(titleText.implicitHeight, + feeText.implicitHeight) + + readonly property int halfWidth: (width - Style.current.padding) / 2 + + StatusBaseText { + id: titleText + + width: parent.halfWidth + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: parent.bottom + + + text: root.title + wrapMode: Text.Wrap + maximumLineCount: 2 + lineHeight: 22 + lineHeightMode: Text.FixedHeight + font.pixelSize: Style.current.primaryTextFontSize + elide: Text.ElideRight + } + + StatusBaseText { + id: feeText + + readonly property color baseColor: root.highlightFee + ? Theme.palette.directColor1 + : Theme.palette.baseColor1 + + width: parent.halfWidth + anchors.right: parent.right + anchors.top: parent.top + + textFormat: Text.RichText + text: `` + + `${qsTr("Max.")} ${root.feeText}` + + visible: root.feeText !== "" + horizontalAlignment: Text.AlignRight + color: root.errorFee ? Theme.palette.dangerColor1 : baseColor + + font.pixelSize: Style.current.primaryTextFontSize + wrapMode: Text.Wrap + maximumLineCount: 2 + + // Setting text format to Text.RichText behaves similarly as + // as adding vapid onLineLaidOut handler described in + // https://bugreports.qt.io/browse/QTBUG-62057 + // lineHeight: 22 + // lineHeightMode: Text.FixedHeight + } + + LoadingComponent { + visible: root.feeText === "" + + anchors.right: parent.right + anchors.verticalCenter: feeText.verticalCenter + width: 160 + height: 11 + } + } +} diff --git a/ui/app/AppLayouts/Communities/controls/FeesBoxFooter.qml b/ui/app/AppLayouts/Communities/controls/FeesBoxFooter.qml new file mode 100644 index 0000000000..349531c2c0 --- /dev/null +++ b/ui/app/AppLayouts/Communities/controls/FeesBoxFooter.qml @@ -0,0 +1,97 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 + +import utils 1.0 + + +Control { + id: root + + property alias generalErrorText: generalErrorText.text + + property bool showTotal: true + property alias totalFeeText: feeTotalRow.feeText + + property alias accountsModel: accountSelector.model + property alias accountErrorText: accountErrorText.text + + component Separator: Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + Layout.topMargin: Style.current.padding + + color: Theme.palette.baseColor2 + } + + component ErrorText: StatusBaseText { + + Layout.fillWidth: true + Layout.topMargin: Style.current.halfPadding + horizontalAlignment: Text.AlignRight + + font.pixelSize: Theme.tertiaryTextFontSize + color: Theme.palette.dangerColor1 + + wrapMode: Text.Wrap + } + + contentItem: ColumnLayout { + spacing: 0 + + ErrorText { + id: generalErrorText + + visible: text !== "" + } + + Separator { + visible: root.showTotal + } + + FeeRow { + id: feeTotalRow + + Layout.fillWidth: true + Layout.topMargin: Style.current.padding + + title: qsTr("Total") + highlightFee: true + visible: root.showTotal + } + + Separator { + visible: accountSelector.visible + } + + StatusBaseText { + Layout.topMargin: Style.current.padding + Layout.fillWidth: true + + visible: accountSelector.visible + text: qsTr("Select account to pay gas fees from") + color: Theme.palette.baseColor1 + font.pixelSize: Theme.primaryTextFontSize + lineHeight: 1.2 + wrapMode: Text.WordWrap + } + + AccountSelector { + id: accountSelector + + Layout.fillWidth: true + Layout.topMargin: Style.current.halfPadding + + visible: !!model + } + + ErrorText { + id: accountErrorText + + visible: accountSelector.visible && text !== "" + } + } +} diff --git a/ui/app/AppLayouts/Communities/controls/FeesSummaryFooter.qml b/ui/app/AppLayouts/Communities/controls/FeesSummaryFooter.qml new file mode 100644 index 0000000000..bd48085bfe --- /dev/null +++ b/ui/app/AppLayouts/Communities/controls/FeesSummaryFooter.qml @@ -0,0 +1,64 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 + +import utils 1.0 + +Control { + id: root + + property string accountName + property alias totalFeeText: feeTotalRow.feeText + property alias errorText: errorText.text + + contentItem: ColumnLayout { + spacing: 0 + + StatusBaseText { + Layout.topMargin: Style.current.padding + Layout.fillWidth: true + + visible: root.accountName !== "" + color: Theme.palette.baseColor1 + elide: Text.ElideRight + font.pixelSize: Style.current.primaryTextFontSize + maximumLineCount: 2 + text: qsTr("via %1").arg(root.accountName) + wrapMode: Text.Wrap + } + + Rectangle { + Layout.topMargin: Style.current.padding + Layout.fillWidth: true + Layout.preferredHeight: 1 + + color: Theme.palette.baseColor2 + } + + FeeRow { + id: feeTotalRow + + Layout.topMargin: Style.current.padding + Layout.fillWidth: true + + title: qsTr("Total") + highlightFee: true + } + + StatusBaseText { + id: errorText + + Layout.fillWidth: true + Layout.topMargin: Style.current.halfPadding + + color: Theme.palette.dangerColor1 + font.pixelSize: Theme.tertiaryTextFontSize + 1 + horizontalAlignment: Text.AlignRight + visible: text !== "" + wrapMode: Text.Wrap + } + } +} diff --git a/ui/app/AppLayouts/Communities/controls/qmldir b/ui/app/AppLayouts/Communities/controls/qmldir index 10099e243a..083b08eb2b 100644 --- a/ui/app/AppLayouts/Communities/controls/qmldir +++ b/ui/app/AppLayouts/Communities/controls/qmldir @@ -1,3 +1,4 @@ +AccountSelector 1.0 AccountSelector.qml AddressesInputList 1.0 AddressesInputList.qml AddressesSelectorPanel 1.0 AddressesSelectorPanel.qml AirdropRecipientsSelector 1.0 AirdropRecipientsSelector.qml @@ -7,9 +8,12 @@ CategoryListItem 1.0 CategoryListItem.qml ColorPicker 1.0 ColorPicker.qml CommunityListItem 1.0 CommunityListItem.qml DescriptionInput 1.0 DescriptionInput.qml -EnsPanel 1.0 EnsPanel.qml EditCommunitySettingsForm 1.0 EditCommunitySettingsForm.qml +EnsPanel 1.0 EnsPanel.qml ExtendedDropdownContent 1.0 ExtendedDropdownContent.qml +FeeRow 1.0 FeeRow.qml +FeesBoxFooter 1.0 FeesBoxFooter.qml +FeesSummaryFooter 1.0 FeesSummaryFooter.qml HoldingTypes 1.0 HoldingTypes.qml InlineNetworksComboBox 1.0 InlineNetworksComboBox.qml IntroMessageInput 1.0 IntroMessageInput.qml diff --git a/ui/app/AppLayouts/Communities/panels/FeesBox.qml b/ui/app/AppLayouts/Communities/panels/FeesBox.qml new file mode 100644 index 0000000000..e62bbdc850 --- /dev/null +++ b/ui/app/AppLayouts/Communities/panels/FeesBox.qml @@ -0,0 +1,51 @@ +import QtQuick 2.15 + +import StatusQ.Components 0.1 +import StatusQ.Core.Theme 0.1 + +import AppLayouts.Communities.controls 1.0 +import utils 1.0 + +StatusGroupBox { + id: root + + title: qsTr("Fees") + icon: Style.svg("gas") + + // expected roles: + // + // title (string) + // feeText (string) + // error (bool), optional + property alias model: feesBox.model + + property alias accountsModel: footer.accountsModel + property alias placeholderText: feesBox.placeholderText + + property alias totalFeeText: footer.totalFeeText + + property alias generalErrorText: footer.generalErrorText + property alias accountErrorText: footer.accountErrorText + + FeesPanel { + id: feesBox + + width: root.availableWidth + padding: Style.current.padding + verticalPadding: 18 + + background: Rectangle { + radius: Style.current.radius + color: Theme.palette.statusListItem.backgroundColor + } + + footer: FeesBoxFooter { + id: footer + + visible: !!accountsModel || showTotal + || root.generalErrorText || root.accountErrorText + + showTotal: feesBox.count > 1 + } + } +} diff --git a/ui/app/AppLayouts/Communities/panels/FeesPanel.qml b/ui/app/AppLayouts/Communities/panels/FeesPanel.qml index ee0c4ae47a..19647e00ed 100644 --- a/ui/app/AppLayouts/Communities/panels/FeesPanel.qml +++ b/ui/app/AppLayouts/Communities/panels/FeesPanel.qml @@ -1,149 +1,80 @@ import QtQuick 2.15 -import QtQuick.Layouts 1.15 import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 -import StatusQ.Components 0.1 +import AppLayouts.Communities.controls 1.0 import utils 1.0 + Control { id: root - // account, amount, symbol, network, feeText + // expected roles: + // + // title (string) - e.g. ""Airdropping 2 on Optimism" + // feeText (string) - e.g. "0.0015 ($75.54) + // error (bool), optional property alias model: repeater.model readonly property alias count: repeater.count - property alias showSummary: summaryRow.visible - property alias errorText: errorTxt.text - property alias totalFeeText: totalFeeText.text + property alias placeholderText: placeholderText.text - property bool isFeeLoading: false - property bool showAccounts: true + property Item footer + + states: State { + when: root.footer + + ParentChange { + target: root.footer + parent: contentItem + } + + PropertyChanges { + target: root.footer + Layout.fillWidth: true + Layout.topMargin: -Style.current.padding + } + } QtObject { id: d - readonly property int delegateHeightWhenAccountsHidden: 28 + readonly property int delegateHeight: 28 } contentItem: ColumnLayout { spacing: Style.current.padding + StatusBaseText { + id: placeholderText + + Layout.fillWidth: true + Layout.preferredHeight: Math.max(implicitHeight, d.delegateHeight) + + visible: repeater.count === 0 + + font.pixelSize: Style.current.primaryTextFontSize + wrapMode: Text.Wrap + color: Theme.palette.baseColor1 + verticalAlignment: Text.AlignVCenter + } + Repeater { id: repeater - Item { + FeeRow { Layout.fillWidth: true - Layout.preferredHeight: root.showAccounts - ? delegateColumn.implicitHeight - : Math.max(delegateColumn.implicitHeight, - d.delegateHeightWhenAccountsHidden) + Layout.preferredHeight: Math.max(implicitHeight, + d.delegateHeight) - ColumnLayout { - id: delegateColumn - - width: parent.width - anchors.verticalCenter: parent.verticalCenter - - RowLayout { - Layout.fillWidth: true - - StatusBaseText { - Layout.fillWidth: true - - text: qsTr("Airdropping %1 %2 on %3") - .arg(model.amount).arg(model.symbol) - .arg(model.network) - - font.pixelSize: Style.current.primaryTextFontSize - elide: Text.ElideRight - } - - StatusDotsLoadingIndicator { - Layout.rightMargin: Style.current.padding - - visible: root.isFeeLoading - } - - StatusBaseText { - text: model.feeText - - visible: !root.isFeeLoading - font.pixelSize: Style.current.primaryTextFontSize - elide: Text.ElideMiddle - color: repeater.count === 1 ? Theme.palette.directColor1 - : Theme.palette.baseColor1 - } - } - - StatusBaseText { - Layout.fillWidth: true - - visible: root.showAccounts - - text: qsTr("via %1").arg(model.account) - horizontalAlignment: Text.AlignLeft - font.pixelSize: Style.current.primaryTextFontSize - elide: Text.ElideMiddle - color: Theme.palette.baseColor1 - } - } + title: model.title + feeText: model.feeText + errorFee: !!model.error + highlightFee: repeater.count === 1 } } - - Rectangle { - Layout.fillWidth: true - Layout.preferredHeight: 1 - - visible: summaryRow.visible - - color: Theme.palette.baseColor2 - } - - RowLayout { - id: summaryRow - - Layout.fillWidth: true - Layout.topMargin: Style.current.halfPadding - - StatusBaseText { - Layout.fillWidth: true - - text: qsTr("Total") - - font.pixelSize: Style.current.primaryTextFontSize - elide: Text.ElideMiddle - } - - StatusDotsLoadingIndicator { - visible: root.isFeeLoading - - Layout.rightMargin: Style.current.padding - } - - StatusBaseText { - id: totalFeeText - - font.pixelSize: Style.current.primaryTextFontSize - visible: !root.isFeeLoading - } - } - - StatusBaseText { - id: errorTxt - - Layout.topMargin: Style.current.halfPadding - Layout.fillWidth: true - - wrapMode: Text.Wrap - horizontalAlignment: Text.AlignRight - font.pixelSize: Style.current.primaryTextFontSize - color: Theme.palette.dangerColor1 - - text: root.errorText - visible: root.errorText !== "" - } } } diff --git a/ui/app/AppLayouts/Communities/panels/qmldir b/ui/app/AppLayouts/Communities/panels/qmldir index 7801971678..cd706cbaf2 100644 --- a/ui/app/AppLayouts/Communities/panels/qmldir +++ b/ui/app/AppLayouts/Communities/panels/qmldir @@ -5,6 +5,8 @@ ChannelsAndCategoriesBannerPanel 1.0 ChannelsAndCategoriesBannerPanel.qml ChatPermissionQualificationPanel 1.0 ChatPermissionQualificationPanel.qml ColorPanel 1.0 ColorPanel.qml ColumnHeaderPanel 1.0 ColumnHeaderPanel.qml +EditSettingsPanel 1.0 EditSettingsPanel.qml +FeesBox 1.0 FeesBox.qml FeesPanel 1.0 FeesPanel.qml HidePermissionPanel 1.0 HidePermissionPanel.qml IntroPanel 1.0 IntroPanel.qml @@ -14,6 +16,7 @@ JoinPermissionsOverlayPanel 1.0 JoinPermissionsOverlayPanel.qml MembersSettingsPanel 1.0 MembersSettingsPanel.qml MintTokensFooterPanel 1.0 MintTokensFooterPanel.qml MintTokensSettingsPanel 1.0 MintTokensSettingsPanel.qml +OverviewSettingsChart 1.0 OverviewSettingsChart.qml OverviewSettingsFooter 1.0 OverviewSettingsFooter.qml OverviewSettingsPanel 1.0 OverviewSettingsPanel.qml PermissionConflictWarningPanel 1.0 PermissionConflictWarningPanel.qml @@ -32,5 +35,3 @@ TokenHoldersProxyModel 1.0 TokenHoldersProxyModel.qml TokenInfoPanel 1.0 TokenInfoPanel.qml WarningPanel 1.0 WarningPanel.qml WelcomeBannerPanel 1.0 WelcomeBannerPanel.qml -EditSettingsPanel 1.0 EditSettingsPanel.qml -OverviewSettingsChart 1.0 OverviewSettingsChart.qml \ No newline at end of file diff --git a/ui/app/AppLayouts/Communities/popups/SignMultiTokenTransactionsPopup.qml b/ui/app/AppLayouts/Communities/popups/SignMultiTokenTransactionsPopup.qml index 1a09c347f4..aa5daaf4f7 100644 --- a/ui/app/AppLayouts/Communities/popups/SignMultiTokenTransactionsPopup.qml +++ b/ui/app/AppLayouts/Communities/popups/SignMultiTokenTransactionsPopup.qml @@ -6,18 +6,22 @@ import StatusQ.Popups.Dialog 0.1 import utils 1.0 +import AppLayouts.Communities.controls 1.0 import AppLayouts.Communities.panels 1.0 StatusDialog { id: root - // account, amount, symbol, network, feeText + // expected roles: + // + // title (string) + // feeText (string) + // error (bool), optional property alias model: feesPanel.model - property alias showSummary: feesPanel.showSummary - property alias errorText: feesPanel.errorText - property alias totalFeeText: feesPanel.totalFeeText - property alias isFeeLoading: feesPanel.isFeeLoading + property alias errorText: footer.errorText + property alias totalFeeText: footer.totalFeeText + property alias accountName: footer.accountName signal signTransactionClicked() signal cancelClicked() @@ -29,11 +33,13 @@ StatusDialog { } implicitWidth: 600 // by design - topPadding: 2 * Style.current.padding // by design - bottomPadding: Style.current.bigPadding contentItem: FeesPanel { id: feesPanel + + footer: FeesSummaryFooter { + id: footer + } } footer: StatusDialogFooter { diff --git a/ui/app/AppLayouts/Communities/views/EditAirdropView.qml b/ui/app/AppLayouts/Communities/views/EditAirdropView.qml index d2fd296361..b417907593 100644 --- a/ui/app/AppLayouts/Communities/views/EditAirdropView.qml +++ b/ui/app/AppLayouts/Communities/views/EditAirdropView.qml @@ -171,14 +171,7 @@ StatusScrollView { + membersModelTracker.revision + (d.showFees ? 1 : 0) - onTotalRevisionChanged: { - Qt.callLater(() => { - if (!d.showFees) - return - - d.resetFees() - }) - } + onTotalRevisionChanged: Qt.callLater(() => d.resetFees()) function prepareEntry(key, amount, type) { let tokenModel = null @@ -216,10 +209,10 @@ StatusScrollView { airdropTokens.forEach(entry => { feesModel.append({ contractUniqueKey: entry.contractUniqueKey, - amount: entry.amount * addresses.count, - account: entry.accountName, - symbol: entry.symbol, - network: entry.networkText, + title: qsTr("Airdropping %1 %2 on %3") + .arg(entry.amount * addresses.count) + .arg(entry.symbol) + .arg(entry.networkText), feeText: "" }) }) @@ -245,6 +238,11 @@ StatusScrollView { d.feesError = "" d.totalFee = "" + if (!d.showFees) { + feesModel.clear() + return + } + d.rebuildFeesModel() d.requestFees() } @@ -584,61 +582,12 @@ StatusScrollView { SequenceColumnLayout.Separator {} - StatusGroupBox { - id: feesBox - + FeesBox { Layout.fillWidth: true - implicitWidth: 0 - title: qsTr("Fees") - icon: Style.svg("gas") - - Control { - id: feesControl - - width: feesBox.availableWidth - - padding: Style.current.padding - verticalPadding: 18 - - background: Rectangle { - radius: Style.current.radius - color: Theme.palette.statusListItem.backgroundColor - } - - contentItem: Loader { - Component { - id: feesPanelComponent - - FeesPanel { - width: feesControl.availableWidth - - showAccounts: false - totalFeeText: d.totalFee - showSummary: count > 1 - isFeeLoading: d.isFeeLoading - - model: feesModel - } - } - - Component { - id: placeholderComponent - - StatusBaseText { - width: feesControl.availableWidth - - text: qsTr("Add valid “What” and “To” values to see fees") - font.pixelSize: Style.current.primaryTextFontSize - elide: Text.ElideRight - color: Theme.palette.baseColor1 - } - } - - sourceComponent: d.showFees ? feesPanelComponent - : placeholderComponent - } - } + model: feesModel + totalFeeText: d.totalFee + placeholderText: qsTr("Add valid “What” and “To” values to see fees") } WarningPanel { @@ -682,8 +631,6 @@ StatusScrollView { model: feesModel - isFeeLoading: d.isFeeLoading - totalFeeText: d.totalFee errorText: d.feesError