From fffaebfffbad4774c59f4884126211fabfcf5a7e Mon Sep 17 00:00:00 2001 From: Dario Gabriel Lipicar Date: Tue, 11 Feb 2025 10:20:34 -0300 Subject: [PATCH] feat: implement New tag and decorator for NetworkFilter --- .../main/wallet_section/networks/model.nim | 6 ++- .../service/network/network_item.nim | 19 ++++++-- src/app_service/service/network/types.nim | 4 +- storybook/pages/NetworkFilterPage.qml | 14 ++++++ storybook/pages/StatusNewTagPage.qml | 45 ++++++++++++++++++ storybook/src/Models/NetworksModel.qml | 8 ++++ .../StatusQ/Components/StatusNewDecorator.qml | 36 +++++++++++++++ .../src/StatusQ/Components/StatusNewTag.qml | 46 +++++++++++++++++++ .../Components/private/StatusGradient.qml | 13 ++++++ .../src/StatusQ/Components/private/qmldir | 1 + ui/StatusQ/src/StatusQ/Components/qmldir | 2 + ui/StatusQ/src/statusq.qrc | 3 ++ .../Wallet/controls/NetworkFilter.qml | 15 ++++++ .../controls/NetworkSelectItemDelegate.qml | 18 ++++++++ .../AppLayouts/Wallet/panels/WalletHeader.qml | 9 ++++ .../Wallet/popups/NetworkSelectPopup.qml | 2 + .../Wallet/views/NetworkSelectorView.qml | 2 + vendor/status-go | 2 +- 18 files changed, 238 insertions(+), 7 deletions(-) create mode 100644 storybook/pages/StatusNewTagPage.qml create mode 100644 ui/StatusQ/src/StatusQ/Components/StatusNewDecorator.qml create mode 100644 ui/StatusQ/src/StatusQ/Components/StatusNewTag.qml create mode 100644 ui/StatusQ/src/StatusQ/Components/private/StatusGradient.qml diff --git a/src/app/modules/main/wallet_section/networks/model.nim b/src/app/modules/main/wallet_section/networks/model.nim index b4e10390e2..cf29f0b9a6 100644 --- a/src/app/modules/main/wallet_section/networks/model.nim +++ b/src/app/modules/main/wallet_section/networks/model.nim @@ -21,6 +21,7 @@ type ShortName IsActive IsDeactivatable + IsNew QtObject: type @@ -56,7 +57,8 @@ QtObject: ModelRole.ShortName.int: "shortName", ModelRole.ChainColor.int: "chainColor", ModelRole.IsActive.int: "isActive", - ModelRole.IsDeactivatable.int: "isDeactivatable" + ModelRole.IsDeactivatable.int: "isDeactivatable", + ModelRole.IsNew.int: "isNew" }.toTable method data(self: Model, index: QModelIndex, role: int): QVariant = @@ -98,6 +100,8 @@ QtObject: result = newQVariant(item.isActive) of ModelRole.IsDeactivatable: result = newQVariant(item.isDeactivatable) + of ModelRole.IsNew: + result = newQVariant(item.isNew) proc refreshModel*(self: Model) = self.beginResetModel() diff --git a/src/app_service/service/network/network_item.nim b/src/app_service/service/network/network_item.nim index 6f42f16590..cc76eafb4b 100644 --- a/src/app_service/service/network/network_item.nim +++ b/src/app_service/service/network/network_item.nim @@ -2,7 +2,7 @@ import NimQml, stew/shims/strformat import sequtils, sugar import backend/network_types -import ./rpc_provider_item +import ./rpc_provider_item, ./types export rpc_provider_item @@ -24,6 +24,7 @@ QtObject: relatedChainId*: int isActive*: bool isDeactivatable*: bool + isNew*: bool proc setup*(self: NetworkItem, chainId: int, @@ -41,7 +42,8 @@ QtObject: isEnabled: bool, relatedChainId: int, isActive: bool, - isDeactivatable: bool + isDeactivatable: bool, + isNew: bool ) = self.QObject.setup self.chainId = chainId @@ -60,6 +62,7 @@ QtObject: self.relatedChainId = relatedChainId self.isActive = isActive self.isDeactivatable = isDeactivatable + self.isNew = isNew proc delete*(self: NetworkItem) = self.QObject.delete @@ -67,10 +70,12 @@ QtObject: proc networkDtoToItem*(network: NetworkDto): NetworkItem = new(result, delete) let rpcProviders = network.rpcProviders.map(p => rpcProviderDtoToItem(p)) + # We construct the isNew value client-side, at least for now + let isNew = network.chainId == Base or network.chainId == BaseSepolia result.setup(network.chainId, network.layer, network.chainName, network.iconUrl, network.shortName, network.chainColor, rpcProviders, network.blockExplorerURL, network.nativeCurrencyName, network.nativeCurrencySymbol, network.nativeCurrencyDecimals, - network.isTest, network.isEnabled, network.relatedChainId, network.isActive, network.isDeactivatable) + network.isTest, network.isEnabled, network.relatedChainId, network.isActive, network.isDeactivatable, isNew) proc networkItemToDto*(network: NetworkItem): NetworkDto = result = NetworkDto( @@ -109,7 +114,8 @@ QtObject: isEnabled: {self.isEnabled}, relatedChainId: {self.relatedChainId}, isActive: {self.isActive}, - isDeactivatable: {self.isDeactivatable} + isDeactivatable: {self.isDeactivatable}, + isNew: {self.isNew} ]""" proc chainId*(self: NetworkItem): int {.slot.} = @@ -184,3 +190,8 @@ QtObject: return self.isActive QtProperty[bool] isActive: read = isActive + + proc isNew*(self: NetworkItem): bool {.slot.} = + return self.isNew + QtProperty[bool] isNew: + read = isNew diff --git a/src/app_service/service/network/types.nim b/src/app_service/service/network/types.nim index 83758742e0..c17b5306d6 100644 --- a/src/app_service/service/network/types.nim +++ b/src/app_service/service/network/types.nim @@ -1,9 +1,11 @@ const Mainnet = 1 const Sepolia = 11155111 +const Base = 8453 +const BaseSepolia = 84532 const NETWORK_LAYER_1 = 1 const NETWORK_LAYER_2 = 2 -export Mainnet, Sepolia +export Mainnet, Sepolia, Base, BaseSepolia export NETWORK_LAYER_1, NETWORK_LAYER_2 diff --git a/storybook/pages/NetworkFilterPage.qml b/storybook/pages/NetworkFilterPage.qml index 3c8b349e42..4c86422e91 100644 --- a/storybook/pages/NetworkFilterPage.qml +++ b/storybook/pages/NetworkFilterPage.qml @@ -51,6 +51,8 @@ SplitView { multiSelection: multiSelectionCheckBox.checked showTitle: ctrlShowTitle.checked showManageNetworksButton: ctrlShowManageNetworksButton.checked + showNewTag: ctrlShowNewTagButton.checked + showNewDecorator: ctrlShowNewDecoratorButton.checked selectionAllowed: selectionAllowedCheckBox.checked showSelectionIndicator: (ctrlShowCheckBoxes.checked && multiSelection) || (ctrlShowRadioButtons.checked && !multiSelection) } @@ -105,6 +107,18 @@ SplitView { checked: true } + CheckBox { + id: ctrlShowNewTagButton + text: "Show 'NEW' tag" + checked: true + } + + CheckBox { + id: ctrlShowNewDecoratorButton + text: "Show 'New' decorator" + checked: true + } + CheckBox { id: selectionAllowedCheckBox text: "Selection allowed" diff --git a/storybook/pages/StatusNewTagPage.qml b/storybook/pages/StatusNewTagPage.qml new file mode 100644 index 0000000000..b73e246817 --- /dev/null +++ b/storybook/pages/StatusNewTagPage.qml @@ -0,0 +1,45 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import StatusQ.Core 0.1 +import StatusQ.Components 0.1 +import Storybook 1.0 +import utils 1.0 + +SplitView { + id: root + + orientation: Qt.Horizontal + + Item { + SplitView.fillWidth: true + SplitView.fillHeight: true + + StatusNewTag { + anchors.centerIn: parent + tooltipText: ctrlTooltip.text + } + } + + LogsAndControlsPanel { + SplitView.minimumWidth: 300 + SplitView.preferredWidth: 400 + + SplitView.fillHeight: true + + RowLayout { + Label { + text: "Tooltip:" + } + TextField { + id: ctrlTooltip + text: "Hic sunt leones!!!" + } + } + } +} + +// category: Components + +// https://www.figma.com/design/FkFClTCYKf83RJWoifWgoX/Wallet-v2?node-id=28725-330957&m=dev diff --git a/storybook/src/Models/NetworksModel.qml b/storybook/src/Models/NetworksModel.qml index 54b135fb26..77c3d59de6 100644 --- a/storybook/src/Models/NetworksModel.qml +++ b/storybook/src/Models/NetworksModel.qml @@ -420,6 +420,7 @@ QtObject { isEnabled: true, isActive: true, isDeactivatable: false, + isNew: false, }, { chainId: sepMainnetChainId, @@ -438,6 +439,7 @@ QtObject { isEnabled: false, isActive: true, isDeactivatable: false, + isNew: false, }, { chainId: optChainId, @@ -456,6 +458,7 @@ QtObject { isEnabled: true, isActive: false, isDeactivatable: true, + isNew: false, }, { chainId: sepOptChainId, @@ -474,6 +477,7 @@ QtObject { isEnabled: true, isActive: true, isDeactivatable: true, + isNew: false, }, { chainId: arbChainId, @@ -492,6 +496,7 @@ QtObject { isEnabled: false, isActive: true, isDeactivatable: true, + isNew: false, }, { chainId: sepArbChainId, @@ -510,6 +515,7 @@ QtObject { isEnabled: false, isActive: true, isDeactivatable: true, + isNew: false, }, { chainId: baseChainId, @@ -528,6 +534,7 @@ QtObject { isEnabled: false, isActive: false, isDeactivatable: true, + isNew: true, }, { chainId: sepBaseChainId, @@ -546,6 +553,7 @@ QtObject { isEnabled: false, isActive: true, isDeactivatable: true, + isNew: true, }] ) } diff --git a/ui/StatusQ/src/StatusQ/Components/StatusNewDecorator.qml b/ui/StatusQ/src/StatusQ/Components/StatusNewDecorator.qml new file mode 100644 index 0000000000..a42a72be6e --- /dev/null +++ b/ui/StatusQ/src/StatusQ/Components/StatusNewDecorator.qml @@ -0,0 +1,36 @@ +import QtQuick 2.15 +import QtGraphicalEffects 1.15 + +import StatusQ 0.1 +import StatusQ.Components.private 0.1 +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 + +Rectangle { + id: root + + property int borderWidth: 2 + height: innerCircle.height + borderWidth + width: innerCircle.width + borderWidth + + color: Theme.palette.baseColor2 + radius: height/2 + + Rectangle { + id: innerCircle + + anchors.centerIn: parent + height: 10 + width: 10 + + StatusGradient { + id: gradient + + anchors.fill: parent + source: parent + } + + radius: height/2 + } +} + diff --git a/ui/StatusQ/src/StatusQ/Components/StatusNewTag.qml b/ui/StatusQ/src/StatusQ/Components/StatusNewTag.qml new file mode 100644 index 0000000000..c4dcac5fae --- /dev/null +++ b/ui/StatusQ/src/StatusQ/Components/StatusNewTag.qml @@ -0,0 +1,46 @@ +import QtQuick 2.15 +import QtGraphicalEffects 1.15 + +import StatusQ.Components.private 0.1 +import StatusQ.Core 0.1 +import StatusQ.Controls 0.1 +import StatusQ.Core.Theme 0.1 + +Rectangle { + id: root + + property alias tooltipText: tip.text + property alias cursorShape: hoverHandler.cursorShape + + readonly property bool hovered: hoverHandler.hovered + + StatusGradient { + id: gradient + anchors.fill: parent + source: root + } + + implicitHeight: 20 + implicitWidth: 36 + radius: height/2 + border.width: 0 + + StatusBaseText { + font.pixelSize: 10 + font.weight: Font.DemiBold + color: Theme.palette.indirectColor4 + anchors.centerIn: parent + text: qsTr("NEW") + } + + StatusToolTip { + id: tip + visible: hoverHandler.hovered && !!text + maxWidth: 333 + } + + HoverHandler { + id: hoverHandler + enabled: root.visible + } +} diff --git a/ui/StatusQ/src/StatusQ/Components/private/StatusGradient.qml b/ui/StatusQ/src/StatusQ/Components/private/StatusGradient.qml new file mode 100644 index 0000000000..7636d843b3 --- /dev/null +++ b/ui/StatusQ/src/StatusQ/Components/private/StatusGradient.qml @@ -0,0 +1,13 @@ +import QtQuick 2.15 +import QtGraphicalEffects 1.15 + +LinearGradient { + id: root + start: Qt.point(-0.48*width, 0.46*height) + end: Qt.point(1.36*width, 0.42*height) + gradient: Gradient { + GradientStop { position: 0.0; color: "#2A799B" } + GradientStop { position: 0.25; color: "#F6B03C" } + GradientStop { position: 0.84; color: "#FF33A3" } + } +} \ No newline at end of file diff --git a/ui/StatusQ/src/StatusQ/Components/private/qmldir b/ui/StatusQ/src/StatusQ/Components/private/qmldir index 320aa22691..6e964ad0c9 100644 --- a/ui/StatusQ/src/StatusQ/Components/private/qmldir +++ b/ui/StatusQ/src/StatusQ/Components/private/qmldir @@ -4,3 +4,4 @@ StatusImageMessage 0.1 statusMessage/StatusImageMessage.qml StatusMessageImageAlbum 0.1 statusMessage/StatusMessageImageAlbum.qml StatusComboboxBackground 0.1 StatusComboboxBackground.qml StatusComboboxIndicator 0.1 StatusComboboxIndicator.qml +StatusGradient 0.1 StatusGradient.qml diff --git a/ui/StatusQ/src/StatusQ/Components/qmldir b/ui/StatusQ/src/StatusQ/Components/qmldir index 1aac49fb44..f1c8b309cb 100644 --- a/ui/StatusQ/src/StatusQ/Components/qmldir +++ b/ui/StatusQ/src/StatusQ/Components/qmldir @@ -48,6 +48,8 @@ StatusMessageHeader 0.1 StatusMessageHeader.qml StatusMessageSenderDetails 0.1 StatusMessageSenderDetails.qml StatusNavigationListItem 0.1 StatusNavigationListItem.qml StatusNavigationPanelHeadline 0.1 StatusNavigationPanelHeadline.qml +StatusNewDecorator 0.1 StatusNewDecorator.qml +StatusNewTag 0.1 StatusNewTag.qml StatusOnlineBadge 0.1 StatusOnlineBadge.qml StatusPageIndicator 0.1 StatusPageIndicator.qml StatusQrCodeScanner 0.1 StatusQrCodeScanner.qml diff --git a/ui/StatusQ/src/statusq.qrc b/ui/StatusQ/src/statusq.qrc index 56505ef537..98cb2c5444 100644 --- a/ui/StatusQ/src/statusq.qrc +++ b/ui/StatusQ/src/statusq.qrc @@ -48,6 +48,8 @@ StatusQ/Components/StatusMessageSenderDetails.qml StatusQ/Components/StatusNavigationListItem.qml StatusQ/Components/StatusNavigationPanelHeadline.qml + StatusQ/Components/StatusNewDecorator.qml + StatusQ/Components/StatusNewTag.qml StatusQ/Components/StatusOnlineBadge.qml StatusQ/Components/StatusPageIndicator.qml StatusQ/Components/StatusQrCodeScanner.qml @@ -69,6 +71,7 @@ StatusQ/Components/private/LoadingDotItem.qml StatusQ/Components/private/StatusComboboxBackground.qml StatusQ/Components/private/StatusComboboxIndicator.qml + StatusQ/Components/private/StatusGradient.qml StatusQ/Components/private/chart/ChartCanvas.qml StatusQ/Components/private/chart/Library/Animator.qml StatusQ/Components/private/chart/Library/Chart.bundle.js diff --git a/ui/app/AppLayouts/Wallet/controls/NetworkFilter.qml b/ui/app/AppLayouts/Wallet/controls/NetworkFilter.qml index 5e6e3b19d2..ff506f3ba1 100644 --- a/ui/app/AppLayouts/Wallet/controls/NetworkFilter.qml +++ b/ui/app/AppLayouts/Wallet/controls/NetworkFilter.qml @@ -33,10 +33,13 @@ StatusComboBox { property bool showTitle: true property bool selectionAllowed: true property bool showManageNetworksButton: false + property bool showNewTag: false + property bool showNewDecorator: false property var selection: [] signal toggleNetwork(int chainId, int index) signal manageNetworksClicked() + signal popupOpened() onSelectionChanged: { if (root.selection !== networkSelectorView.selection) { @@ -44,6 +47,15 @@ StatusComboBox { } } + StatusNewDecorator { + id: newDecorator + anchors.verticalCenter: parent.top + anchors.verticalCenterOffset: 3 + anchors.horizontalCenter: parent.right + anchors.horizontalCenterOffset: -3 + visible: root.showNewDecorator + } + control.padding: 12 control.spacing: 0 control.rightPadding: 36 @@ -154,6 +166,7 @@ StatusComboBox { multiSelection: root.multiSelection showSelectionIndicator: root.showSelectionIndicator showManageNetworksButton: root.showManageNetworksButton + showNewTag: root.showNewTag selection: root.selection onSelectionChanged: { @@ -168,6 +181,8 @@ StatusComboBox { control.popup.close() root.manageNetworksClicked() } + + onOpened: root.popupOpened() } Connections { diff --git a/ui/app/AppLayouts/Wallet/controls/NetworkSelectItemDelegate.qml b/ui/app/AppLayouts/Wallet/controls/NetworkSelectItemDelegate.qml index 907cc5bf11..7819b28a5a 100644 --- a/ui/app/AppLayouts/Wallet/controls/NetworkSelectItemDelegate.qml +++ b/ui/app/AppLayouts/Wallet/controls/NetworkSelectItemDelegate.qml @@ -1,8 +1,10 @@ import QtQuick 2.15 import QtQml 2.15 import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 import QtGraphicalEffects 1.15 +import StatusQ 0.1 import StatusQ.Components 0.1 import StatusQ.Controls 0.1 import StatusQ.Core.Theme 0.1 @@ -24,6 +26,7 @@ StatusListItem { property bool showIndicator: true property bool multiSelection: false property bool interactive: true + property bool showNewTag: false // output signal // Emitted when the checkbox is clicked @@ -40,6 +43,8 @@ StatusListItem { d.toggled() } + statusListItemTitleIcons.sourceComponent: root.showNewTag ? newTagComponent : undefined + leftPadding: 16 rightPadding: 16 statusListItemTitleArea.anchors.leftMargin: 12 @@ -98,6 +103,19 @@ StatusListItem { } } + Component { + id: newTagComponent + RowLayout { + spacing: 0 + Column { + width: 8 + } + StatusNewTag { + tooltipText: qsTr("%1 chain integrated. You can now view and swap %1 assets, as well as interact with %1 dApps.").arg(root.title) + } + } + } + QtObject { id: d property int checkState: root.checkState diff --git a/ui/app/AppLayouts/Wallet/panels/WalletHeader.qml b/ui/app/AppLayouts/Wallet/panels/WalletHeader.qml index 5610a04330..a2d00ea544 100644 --- a/ui/app/AppLayouts/Wallet/panels/WalletHeader.qml +++ b/ui/app/AppLayouts/Wallet/panels/WalletHeader.qml @@ -2,6 +2,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import QtQml 2.15 +import Qt.labs.settings 1.1 import StatusQ 0.1 import StatusQ.Core 0.1 @@ -45,6 +46,11 @@ Item { implicitHeight: 88 + Settings { + id: walletHeaderLocalSettings + property bool networksFilterOpened: false + } + GridLayout { width: parent.width columns: 2 @@ -180,12 +186,15 @@ Item { id: networkFilter showTitle: false showManageNetworksButton: true + showNewTag: true + showNewDecorator: !walletHeaderLocalSettings.networksFilterOpened Layout.alignment: Qt.AlignTop flatNetworks: root.walletStore.filteredFlatModel onToggleNetwork: root.walletStore.toggleNetwork(chainId) onManageNetworksClicked: root.manageNetworksRequested() + onPopupOpened: walletHeaderLocalSettings.networksFilterOpened = true Binding on selection { value: chainIdsAggregator.value diff --git a/ui/app/AppLayouts/Wallet/popups/NetworkSelectPopup.qml b/ui/app/AppLayouts/Wallet/popups/NetworkSelectPopup.qml index 5426ea69df..622aedc1b8 100644 --- a/ui/app/AppLayouts/Wallet/popups/NetworkSelectPopup.qml +++ b/ui/app/AppLayouts/Wallet/popups/NetworkSelectPopup.qml @@ -24,6 +24,7 @@ Popup { property bool selectionAllowed: true property bool multiSelection: false property bool showManageNetworksButton: false + property bool showNewTag: false property var selection: [] signal toggleNetwork(int chainId, int index) @@ -68,6 +69,7 @@ Popup { interactive: root.selectionAllowed multiSelection: root.multiSelection showIndicator: root.showSelectionIndicator + showNewTag: root.showNewTag selection: root.selection onSelectionChanged: { diff --git a/ui/app/AppLayouts/Wallet/views/NetworkSelectorView.qml b/ui/app/AppLayouts/Wallet/views/NetworkSelectorView.qml index 9bc86a516c..ab9e63c672 100644 --- a/ui/app/AppLayouts/Wallet/views/NetworkSelectorView.qml +++ b/ui/app/AppLayouts/Wallet/views/NetworkSelectorView.qml @@ -26,6 +26,7 @@ StatusListView { property bool showIndicator: true property bool multiSelection: false property bool interactive: true + property bool showNewTag: true /** The list selected of chain ids @@ -62,6 +63,7 @@ StatusListView { showIndicator: root.showIndicator multiSelection: root.multiSelection interactive: root.interactive + showNewTag: root.showNewTag && model.isNew checkState: inSelection ? (d.allSelected && root.interactive ? Qt.PartiallyChecked : Qt.Checked) : Qt.Unchecked nextCheckState: checkState diff --git a/vendor/status-go b/vendor/status-go index d6a67cb182..86fa8950c3 160000 --- a/vendor/status-go +++ b/vendor/status-go @@ -1 +1 @@ -Subproject commit d6a67cb18206e4937c69411c2b4f151b784a04f4 +Subproject commit 86fa8950c3e308e1f026574cfd5bf12458def833