[UI - Swap] Update / improve NetworkFilter component to cover swap design specs

- add new `showRadioButtons` and `showTitle` UI customization points
- adjust SB and expose all the existing modes, fix it to make it work
with multi selection
- integrate these new modes into SwapModal to align it with the Figma
design

Fixes #14780
This commit is contained in:
Lukáš Tinkl 2024-06-06 11:49:13 +02:00 committed by Lukáš Tinkl
parent dbbe88bc83
commit 70d2a1dd75
7 changed files with 163 additions and 39 deletions

View File

@ -1,6 +1,6 @@
import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import AppLayouts.Communities.views 1.0
import AppLayouts.Communities.controls 1.0

View File

@ -7,6 +7,7 @@ import Models 1.0
import SortFilterProxyModel 0.2
import AppLayouts.stores 1.0
import AppLayouts.Wallet.controls 1.0
SplitView {
@ -17,8 +18,80 @@ SplitView {
readonly property string optimismName : "Optimism"
readonly property string arbitrumName : "Arbitrum"
SplitView {
// Keep a clone so that the UX can be modified without affecting the original model
CloneModel {
id: simulatedNimModel
sourceModel: SortFilterProxyModel {
sourceModel: NetworksModel.flatNetworks
filters: ValueFilter { roleName: "isTest"; value: false }
}
roles: ["chainId", "layer", "chainName", "isTest", "isEnabled", "iconUrl", "shortName", "chainColor"]
rolesOverride: [{ role: "enabledState", transform: (mD) => {
return simulatedNimModel.areAllEnabled(sourceModel)
? NetworkSelectItemDelegate.UxEnabledState.AllEnabled
: mD.isEnabled
? NetworkSelectItemDelegate.UxEnabledState.Enabled
: NetworkSelectItemDelegate.UxEnabledState.Disabled
}
}]
/// Simulate the Nim model
function toggleNetwork(network) {
const chainId = network.chainId
let chainIdOnlyEnabled = true
let chainIdOnlyDisabled = true
let allEnabled = true
for (let i = 0; i < simulatedNimModel.count; i++) {
const item = simulatedNimModel.get(i)
if(item.enabledState === NetworkSelectItemDelegate.UxEnabledState.Enabled) {
if(item.chainId !== chainId) {
chainIdOnlyEnabled = false
}
} else if(item.enabledState === NetworkSelectItemDelegate.UxEnabledState.Disabled) {
if(item.chainId !== chainId) {
chainIdOnlyDisabled = false
}
allEnabled = false
} else {
if(item.chainId === chainId) {
chainIdOnlyDisabled = false
chainIdOnlyEnabled = false
}
}
}
for (let i = 0; i < simulatedNimModel.count; i++) {
const item = simulatedNimModel.get(i)
if(allEnabled) {
simulatedNimModel.setProperty(i, "enabledState", item.chainId === chainId ? NetworkSelectItemDelegate.UxEnabledState.Enabled : NetworkSelectItemDelegate.UxEnabledState.Disabled)
} else if(chainIdOnlyEnabled || chainIdOnlyDisabled) {
simulatedNimModel.setProperty(i, "enabledState", NetworkSelectItemDelegate.UxEnabledState.AllEnabled)
} else if(item.chainId === chainId) {
simulatedNimModel.setProperty(i, "enabledState", item.enabledState === NetworkSelectItemDelegate.UxEnabledState.Enabled
? NetworkSelectItemDelegate.UxEnabledState.Disabled
: NetworkSelectItemDelegate.UxEnabledState.Enabled)
}
const haveEnabled = item.enabledState !== NetworkSelectItemDelegate.UxEnabledState.Disabled
if(item.isEnabled !== haveEnabled) {
simulatedNimModel.setProperty(i, "isEnabled", haveEnabled)
}
}
}
function areAllEnabled(modelToCheck) {
for (let i = 0; i < modelToCheck.count; i++) {
if(!(modelToCheck.get(i).isEnabled)) {
return false
}
}
return true
}
}
SplitView {
orientation: Qt.Vertical
SplitView.fillWidth: true
@ -28,35 +101,33 @@ SplitView {
SplitView.fillWidth: true
SplitView.fillHeight: true
Rectangle {
width: 800
height: 200
border.width: 1
NetworkFilter {
id: networkFilter
anchors.centerIn: parent
NetworkFilter {
id: networkFilter
flatNetworks: simulatedNimModel
anchors.centerIn: parent
multiSelection: multiSelectionCheckBox.checked
showAllSelectedText: ctrlShowAllSelectedText.checked
showTitle: ctrlShowTitle.checked
showCheckboxes: ctrlShowCheckBoxes.checked
showRadioButtons: ctrlShowRadioButtons.checked
flatNetworks: SortFilterProxyModel {
sourceModel: NetworksModel.flatNetworks
filters: ValueFilter { roleName: "isTest"; value: false; }
}
onToggleNetwork: (network) => {
logs.logEvent("onToggleNetwork: " + network.chainName)
multiSelection: multiSelectionCheckBox.checked
if(multiSelection) {
simulatedNimModel.toggleNetwork(network)
} else {
if(network.chainName === root.ethereumName)
ethRadioBtn.checked = true
onToggleNetwork: {
else if(network.chainName === root.optimismName)
optRadioBtn.checked = true
logs.logEvent("onToggleNetwork: " + network.chainName)
if(network.chainName === root.ethereumName)
ethRadioBtn.checked = true
else if(network.chainName === root.optimismName)
optRadioBtn.checked = true
else if(network.chainName === root.arbitrumName)
arbRadioBtn.checked = true
else if(network.chainName === root.arbitrumName)
arbRadioBtn.checked = true
}
}
}
@ -86,6 +157,34 @@ SplitView {
onCheckedChanged: if(!checked) ethRadioBtn.checked = true
}
CheckBox {
id: ctrlShowTitle
visible: !multiSelectionCheckBox.checked
text: "Show title text"
checked: true
}
CheckBox {
id: ctrlShowCheckBoxes
visible: multiSelectionCheckBox.checked
text: "Show checkboxes"
checked: true
}
CheckBox {
id: ctrlShowRadioButtons
visible: !multiSelectionCheckBox.checked
text: "Show radio buttons"
checked: true
}
CheckBox {
id: ctrlShowAllSelectedText
text: "Show 'All networks' text"
visible: multiSelectionCheckBox.checked
checked: true
}
ColumnLayout {
visible: !multiSelectionCheckBox.checked
Label {

View File

@ -289,9 +289,7 @@ Item {
// check default value of network comboBox, should be mainnet
compare(root.swapFormData.selectedNetworkChainId, -1)
const networkComboBoxText = findChild(networkComboBox.control.contentItem, "contentItemText")
verify(!!networkComboBoxText)
compare(networkComboBoxText.text, root.swapAdaptor.filteredFlatNetworksModel.get(0).chainName)
compare(root.swapAdaptor.filteredFlatNetworksModel.get(0).chainId, 11155111 /*Sepolia Mainnet*/)
// lets ensure that the selected one is correctly set
for (let i=0; i<networkComboBox.control.popup.contentItem.count; i++) {
@ -313,7 +311,10 @@ Item {
// verify values set
verify(!networkComboBox.control.popup.opened)
compare(root.swapFormData.selectedNetworkChainId, networkComboBox.control.popup.contentItem.model.get(i).chainId)
compare(networkComboBoxText.text, root.swapAdaptor.filteredFlatNetworksModel.get(i).chainName)
const networkComboIcon = findChild(networkComboBox.control.contentItem, "contentItemIcon")
verify(!!networkComboIcon)
verify(networkComboIcon.asset.name.includes(root.swapAdaptor.filteredFlatNetworksModel.get(i).iconUrl))
}
}
networkComboBox.control.popup.close()

View File

@ -27,6 +27,8 @@ StatusComboBox {
property var preferredSharingNetworks: []
property bool showAllSelectedText: true
property bool showCheckboxes: true
property bool showRadioButtons: true
property bool showTitle: true
/// \c network is a network.model.nim entry
/// It is called for every toggled network if \c multiSelection is \c true
@ -47,8 +49,14 @@ StatusComboBox {
QtObject {
id: d
readonly property string selectedChainName: NetworkModelHelpers.getChainName(root.flatNetworks, d.currentIndex)
readonly property string selectedIconUrl: NetworkModelHelpers.getChainIconUrl(root.flatNetworks, d.currentIndex)
readonly property string selectedChainName: {
root.multiSelection
NetworkModelHelpers.getChainName(root.flatNetworks, d.currentIndex)
}
readonly property string selectedIconUrl: {
root.multiSelection
NetworkModelHelpers.getChainIconUrl(root.flatNetworks, d.currentIndex)
}
readonly property bool allSelected: enabledFlatNetworks.count === root.flatNetworks.count
readonly property bool noneSelected: enabledFlatNetworks.count === 0
@ -69,7 +77,9 @@ StatusComboBox {
control.topPadding: 7
control.popup.x: root.width - control.popup.width
control.popup.width: 430
control.popup.width: 300
control.popup.horizontalPadding: 4
control.popup.verticalPadding: 4
size: StatusComboBox.Size.Small
@ -86,6 +96,7 @@ StatusComboBox {
control.contentItem: RowLayout {
spacing: Style.current.padding
StatusSmartIdenticon {
objectName: "contentItemIcon"
Layout.alignment: Qt.AlignVCenter
asset.height: 24
asset.width: 24
@ -104,7 +115,8 @@ StatusComboBox {
lineHeight: 24
lineHeightMode: Text.FixedHeight
verticalAlignment: Text.AlignVCenter
text: root.multiSelection ? (d.noneSelected ? qsTr("Select networks"): d.allSelected && root.showAllSelectedText ? qsTr("All networks") : "") : d.selectedChainName
text: root.multiSelection ? (d.noneSelected ? qsTr("Select networks"): d.allSelected && root.showAllSelectedText ? qsTr("All networks") : "")
: (root.showTitle ? d.selectedChainName : "")
color: Theme.palette.baseColor1
visible: !!text
}
@ -130,6 +142,7 @@ StatusComboBox {
preferredSharingNetworks: root.preferredSharingNetworks
preferredNetworksMode: root.preferredNetworksMode
showCheckboxes: root.showCheckboxes
showRadioButtons: root.showRadioButtons
implicitWidth: contentWidth
implicitHeight: contentHeight

View File

@ -16,6 +16,7 @@ StatusListItem {
property var radioButtonGroup
property bool useEnabledRole: true
property bool showCheckboxes: true
property bool showRadioButtons: true
// Needed for preferred sharing networks
property bool preferredNetworksMode: false
@ -45,6 +46,10 @@ StatusListItem {
}
}
leftPadding: 12
rightPadding: 0
statusListItemTitleArea.anchors.leftMargin: 12
components: [
StatusCheckBox {
id: checkBox
@ -58,10 +63,10 @@ StatusListItem {
}
else if(root.useEnabledRole) {
return model.isEnabled ? Qt.Checked : Qt.Unchecked
} else if(model.enabledState === NetworkSelectItemDelegate.Enabled) {
} else if (model.enabledState === NetworkSelectItemDelegate.UxEnabledState.Enabled) {
return Qt.Checked
} else {
if( model.enabledState === NetworkSelectItemDelegate.AllEnabled) {
if( model.enabledState === NetworkSelectItemDelegate.UxEnabledState.AllEnabled) {
return Qt.PartiallyChecked
} else {
return Qt.Unchecked
@ -76,7 +81,7 @@ StatusListItem {
},
StatusRadioButton {
id: radioButton
visible: root.singleSelection.enabled
visible: root.singleSelection.enabled && root.showRadioButtons
size: StatusRadioButton.Size.Large
ButtonGroup.group: root.radioButtonGroup
checked: root.singleSelection.currentModel === root.networkModel && root.singleSelection.currentIndex === model.index

View File

@ -71,6 +71,8 @@ StatusDialog {
objectName: "networkFilter"
Layout.alignment: Qt.AlignVCenter
multiSelection: false
showRadioButtons: false
showTitle: false
flatNetworks: root.swapAdaptor.filteredFlatNetworksModel
onToggleNetwork: (network) => {
root.swapInputParamsForm.selectedNetworkChainId = network.chainId
@ -97,6 +99,9 @@ StatusDialog {
StatusBaseText {
text: qsTr("Selected to token: %1").arg(swapInputParamsForm.toTokenKey)
}
StatusBaseText {
text: qsTr("Selected network chainId: %1").arg(swapInputParamsForm.selectedNetworkChainId)
}
}
}

View File

@ -20,6 +20,7 @@ StatusListView {
property var preferredSharingNetworks: []
property bool preferredNetworksMode: false
property bool showCheckboxes: true
property bool showRadioButtons: true
signal toggleNetwork(var network, int index)
@ -32,11 +33,12 @@ StatusListView {
networkModel: root.model
useEnabledRole: root.useEnabledRole
singleSelection: root.singleSelection
onToggleNetwork: root.toggleNetwork(network, index)
onToggleNetwork: (network, model, index) => root.toggleNetwork(network, index)
preferredNetworksMode: root.preferredNetworksMode
preferredSharingNetworks: root.preferredSharingNetworks
allChecked: root.preferredSharingNetworks.length === root.count
showCheckboxes: root.showCheckboxes
showRadioButtons: root.showRadioButtons
}
section {
@ -50,7 +52,6 @@ StatusListView {
id: layer2text
StatusBaseText {
width: parent.width
font.pixelSize: Style.current.primaryTextFontSize
color: Theme.palette.baseColor1
text: qsTr("Layer 2")
height: 40