fix(@desktop/activity): Fix filter layout and added recipient search (#11883)

This commit is contained in:
Cuteivist 2023-08-16 16:06:56 +02:00 committed by GitHub
parent dc950d828f
commit beaca31664
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 309 additions and 236 deletions

View File

@ -64,6 +64,11 @@ Item {
This property holds a reference to the TextEdit's placeholderText property.
*/
property alias placeholderText: statusBaseInput.placeholderText
/*!
\qmlproperty alias StatusInput::placeholderFont
This property holds a reference to the TextEdit's placeholder font property.
*/
property alias placeholderFont: statusBaseInput.placeholderFont
/*!
\qmlproperty alias StatusInput::font
This property holds a reference to the TextEdit's font property.

View File

@ -97,12 +97,12 @@ Item {
id: leftTab
anchors.fill: parent
changeSelectedAccount: function(address) {
RootStore.setFilterAddress(address)
root.resetView()
RootStore.setFilterAddress(address)
}
selectAllAccounts: function() {
RootStore.setFillterAllAddresses()
root.resetView()
RootStore.setFillterAllAddresses()
}
onShowSavedAddressesChanged: {
if(showSavedAddresses)

View File

@ -84,7 +84,7 @@ StatusMenu {
}
ActivityTokensFilterSubMenu {
id: tokensMenu
height: Math.min(439, tokensMenu.implicitHeight)
height: 439
onBack: root.open()
tokensList: root.tokensList
tokensFilter: root.tokensFilter
@ -96,7 +96,7 @@ StatusMenu {
}
ActivityCounterpartyFilterSubMenu {
id: counterPartyMenu
height: Math.min(439, counterPartyMenu.implicitHeight)
height: 439
onBack: root.open()
store: root.store
recentsList: root.recentsList

View File

@ -40,124 +40,183 @@ StatusMenu {
Component.onCompleted: root.updateRecipientsModel()
MenuBackButton {
id: backButton
width: parent.width
onClicked: {
close()
back()
}
}
contentItem: ColumnLayout {
spacing: 12
StatusSwitchTabBar {
id: tabBar
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: backButton.bottom
anchors.topMargin: 12
width: parent.width - 16
StatusSwitchTabButton {
text: qsTr("Recent")
}
StatusSwitchTabButton {
text: qsTr("Saved")
}
}
StackLayout {
id: layout
width: parent.width
anchors.top: tabBar.bottom
anchors.topMargin: 12
currentIndex: tabBar.currentIndex
Column {
id: column1
MenuBackButton {
id: backButton
Layout.fillWidth: true
spacing: 0
ButtonGroup {
id: recentsButtonGroup
exclusive: false
onClicked: {
close()
back()
}
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("No Recents")
visible: root.recentsList.count === 0 && !root.loadingRecipients
}
SearchBox {
id: searchBox
property string searchValue: ""
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.leftMargin: 8
Layout.rightMargin: 8
font.pixelSize: 13
placeholderFont.pixelSize: font.pixelSize
input.height: 36
placeholderText: qsTr("Search name, ENS or address")
onTextChanged: searchTimer.restart()
// Used to optimize the search when writing word
Timer {
id: searchTimer
interval: 750
onTriggered: searchBox.searchValue = searchBox.text
}
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Loading Recents")
visible: root.loadingRecipients
}
StatusSwitchTabBar {
id: tabBar
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.leftMargin: 8
Layout.rightMargin: 8
StatusSwitchTabButton {
text: qsTr("Recent")
}
StatusListView {
visible: !root.loadingRecipients
width: parent.width
height: root.height - tabBar.height - 12
model: root.recentsList
reuseItems: true
delegate: ActivityTypeCheckBox {
readonly property string name: store.getNameForAddress(model.address)
width: ListView.view.width
height: 44
title: name || StatusQUtils.Utils.elideText(model.address,6,4)
subTitle: name ? StatusQUtils.Utils.elideText(model.address,6,4): ""
statusListItemSubTitle.elide: Text.ElideMiddle
statusListItemSubTitle.wrapMode: Text.NoWrap
assetSettings.name: name || "address"
assetSettings.isLetterIdenticon: !!name
assetSettings.bgHeight: 32
assetSettings.bgWidth: 32
assetSettings.bgRadius: assetSettings.bgHeight/2
assetSettings.width: 16
assetSettings.height: 16
buttonGroup: recentsButtonGroup
allChecked: root.allRecentsChecked
checked: root.allRecentsChecked ? true : root.recentsFilters.includes(model.address)
onActionTriggered: root.recentsToggled(model.address)
StatusSwitchTabButton {
text: qsTr("Saved")
}
}
StackLayout {
id: layout
Layout.fillWidth: true
Layout.fillHeight: true
currentIndex: tabBar.currentIndex
ColumnLayout {
id: column1
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 0
ButtonGroup {
id: recentsButtonGroup
exclusive: false
}
}
}
Column {
id: column2
Layout.fillWidth: true
spacing: 0
ButtonGroup {
id: savedButtonGroup
exclusive: false
}
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("No Saved Address")
visible: root.savedAddressList.count === 0
}
StatusListView {
width: parent.width
height: root.height - tabBar.height - 12
model: root.savedAddressList
delegate: ActivityTypeCheckBox {
width: ListView.view.width
height: 44
title: model.name ?? ""
subTitle: {
if (model.ens.length > 0) {
return sensor.containsMouse ? Utils.richColorText(model.ens, Theme.palette.directColor1) : model.ens
}
else {
let elidedAddress = StatusQUtils.Utils.elideText(model.address,6,4)
return sensor.containsMouse ? WalletUtils.colorizedChainPrefix(model.chainShortNames) + Utils.richColorText(elidedAddress, Theme.palette.directColor1): model.chainShortNames + elidedAddress
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: qsTr("No Recents")
visible: recipientsListView.count === 0 && !root.loadingRecipients
}
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: qsTr("Loading Recents")
visible: root.loadingRecipients
}
StatusListView {
id: recipientsListView
visible: !root.loadingRecipients
Layout.fillWidth: true
Layout.fillHeight: true
model: SortFilterProxyModel {
sourceModel: root.recentsList
filters: ExpressionFilter {
enabled: root.recentsList.count > 0 && layout.currentIndex === 0
expression: {
const searchValue = searchBox.searchValue
if (!searchValue)
return true
const address = model.address.toLowerCase()
return address.startsWith(searchValue) || store.getNameForAddress(address).toLowerCase().indexOf(searchValue) !== -1
}
}
}
statusListItemSubTitle.elide: Text.ElideMiddle
statusListItemSubTitle.wrapMode: Text.NoWrap
assetSettings.name: model.name
assetSettings.isLetterIdenticon: true
buttonGroup: savedButtonGroup
allChecked: root.allSavedAddressesChecked
checked: root.allSavedAddressesChecked ? true : root.savedAddressFilters.includes(model.address)
onActionTriggered: root.savedAddressToggled(model.address)
reuseItems: true
delegate: ActivityTypeCheckBox {
readonly property string name: store.getNameForAddress(model.address)
width: ListView.view.width
height: 44
title: name || StatusQUtils.Utils.elideText(model.address,6,4)
subTitle: name ? StatusQUtils.Utils.elideText(model.address,6,4): ""
statusListItemSubTitle.elide: Text.ElideMiddle
statusListItemSubTitle.wrapMode: Text.NoWrap
assetSettings.name: name || "address"
assetSettings.isLetterIdenticon: !!name
assetSettings.bgHeight: 32
assetSettings.bgWidth: 32
assetSettings.bgRadius: assetSettings.bgHeight/2
assetSettings.width: !!name ? 32 : 16
assetSettings.height: !!name ? 32 : 16
buttonGroup: recentsButtonGroup
allChecked: root.allRecentsChecked
checked: root.allRecentsChecked ? true : root.recentsFilters.includes(model.address)
onActionTriggered: root.recentsToggled(model.address)
}
}
}
ColumnLayout {
id: column2
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 0
ButtonGroup {
id: savedButtonGroup
exclusive: false
}
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: qsTr("No Saved Address")
visible: savedAddressesListView.count === 0
}
StatusListView {
id: savedAddressesListView
Layout.fillWidth: true
Layout.fillHeight: true
model: SortFilterProxyModel {
sourceModel: root.savedAddressList
filters: ExpressionFilter {
enabled: root.savedAddressList.count > 0 && layout.currentIndex === 1
expression: {
const searchValue = searchBox.searchValue
if (!searchValue)
return true
return model.name.toLowerCase().indexOf(searchValue) !== -1
|| model.address.toLowerCase().startsWith(searchValue)
|| model.ens.toLowerCase().startsWith(searchValue)
}
}
}
delegate: ActivityTypeCheckBox {
width: ListView.view.width
height: 44
title: model.name ?? ""
subTitle: {
if (model.ens.length > 0) {
return sensor.containsMouse ? Utils.richColorText(model.ens, Theme.palette.directColor1) : model.ens
}
else {
let elidedAddress = StatusQUtils.Utils.elideText(model.address,6,4)
return sensor.containsMouse ? WalletUtils.colorizedChainPrefix(model.chainShortNames) + Utils.richColorText(elidedAddress, Theme.palette.directColor1): model.chainShortNames + elidedAddress
}
}
statusListItemSubTitle.elide: Text.ElideMiddle
statusListItemSubTitle.wrapMode: Text.NoWrap
assetSettings.name: model.name
assetSettings.isLetterIdenticon: true
assetSettings.bgHeight: 32
assetSettings.bgWidth: 32
assetSettings.width: 32
assetSettings.height: 32
buttonGroup: savedButtonGroup
allChecked: root.allSavedAddressesChecked
checked: root.allSavedAddressesChecked ? true : root.savedAddressFilters.includes(model.address)
onActionTriggered: root.savedAddressToggled(model.address)
}
}
}
}
}
}

View File

@ -28,7 +28,7 @@ StatusMenu {
signal tokenToggled(string tokenSymbol)
signal collectibleToggled(double id)
property var searchTokenSymbolByAddressFn: function (address) { return "" }
property var searchTokenSymbolByAddressFn: function (address) { return "" } // TODO
implicitWidth: 289
@ -37,140 +37,148 @@ StatusMenu {
property bool isFetching: root.collectiblesList.isFetching
}
MenuBackButton {
id: backButton
width: parent.width
onClicked: {
close()
back()
}
}
StatusSwitchTabBar {
id: tabBar
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: backButton.bottom
anchors.topMargin: 12
width: parent.width - 16
StatusSwitchTabButton {
text: qsTr("Assets")
}
StatusSwitchTabButton {
text: qsTr("Collectibles")
}
}
StackLayout {
id: layout
width: parent.width
anchors.top: tabBar.bottom
anchors.topMargin: 12
currentIndex: tabBar.currentIndex
Column {
contentItem: ColumnLayout {
spacing: 12
MenuBackButton {
id: backButton
Layout.fillWidth: true
spacing: 8
ButtonGroup {
id: tokenButtonGroup
exclusive: false
}
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("No Assets")
visible: root.tokensList.count === 0
}
SearchBox {
id: tokensSearchBox
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width - 16
input.height: 36
placeholderText: qsTr("Search asset name")
}
StatusListView {
width: parent.width
height: root.height - tabBar.height - tokensSearchBox.height - 12
spacing: 0
model: SortFilterProxyModel {
sourceModel: root.tokensList
filters: ExpressionFilter {
enabled: root.tokensList.count > 0
expression: {
var tokenSymbolByAddress = root.searchTokenSymbolByAddressFn(tokensSearchBox.text)
return symbol.startsWith(tokensSearchBox.text.toUpperCase()) || name.toUpperCase().startsWith(tokensSearchBox.text.toUpperCase()) || (tokenSymbolByAddress!=="" && symbol.startsWith(tokenSymbolByAddress))
}
}
}
delegate: ActivityTypeCheckBox {
width: ListView.view.width
height: 44
title: model.name
titleAsideText: model.symbol
assetSettings.name: model.symbol ? Constants.tokenIcon(symbol) : ""
assetSettings.isImage: true
buttonGroup: tokenButtonGroup
allChecked: root.allTokensChecked
checked: root.allTokensChecked || root.tokensFilter.includes(model.symbol)
onActionTriggered: root.tokenToggled(model.symbol)
}
onClicked: {
close()
back()
}
}
Column {
width: parent.width
spacing: 8
ButtonGroup {
id: collectibleButtonGroup
exclusive: false
StatusSwitchTabBar {
id: tabBar
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.leftMargin: 8
Layout.rightMargin: 8
StatusSwitchTabButton {
text: qsTr("Assets")
}
StatusBaseText {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("No Collectibles")
visible: root.collectiblesList.count === 0
StatusSwitchTabButton {
text: qsTr("Collectibles")
}
}
SearchBox {
id: collectiblesSearchBox
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width - 16
input.height: 36
placeholderText: qsTr("Search collectible name")
}
StackLayout {
id: layout
Layout.fillWidth: true
Layout.fillHeight: true
currentIndex: tabBar.currentIndex
StatusListView {
width: parent.width
height: root.height - tabBar.height - tokensSearchBox.height - 12
spacing: 0
reuseItems: true
model: SortFilterProxyModel {
sourceModel: root.collectiblesList
filters: ExpressionFilter {
enabled: root.collectiblesList.count > 0 && !!collectiblesSearchBox.text
expression: {
let searchText = collectiblesSearchBox.text.toUpperCase()
return name.toUpperCase().startsWith(searchText)
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 8
ButtonGroup {
id: tokenButtonGroup
exclusive: false
}
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: qsTr("No Assets")
visible: root.tokensList.count === 0
}
SearchBox {
id: tokensSearchBox
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.leftMargin: 8
Layout.rightMargin: 8
input.height: 36
placeholderText: qsTr("Search asset name")
}
StatusListView {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 0
model: SortFilterProxyModel {
sourceModel: root.tokensList
filters: ExpressionFilter {
enabled: root.tokensList.count > 0
expression: {
const tokenSymbolByAddress = root.searchTokenSymbolByAddressFn(tokensSearchBox.text)
return symbol.startsWith(tokensSearchBox.text.toUpperCase()) || name.toUpperCase().startsWith(tokensSearchBox.text.toUpperCase()) || (tokenSymbolByAddress!=="" && symbol.startsWith(tokenSymbolByAddress))
}
}
}
delegate: ActivityTypeCheckBox {
width: ListView.view.width
height: 44
title: model.name
titleAsideText: model.symbol
assetSettings.name: model.symbol ? Constants.tokenIcon(symbol) : ""
assetSettings.isImage: true
buttonGroup: tokenButtonGroup
allChecked: root.allTokensChecked
checked: root.allTokensChecked || root.tokensFilter.includes(model.symbol)
onActionTriggered: root.tokenToggled(model.symbol)
}
}
delegate: ActivityTypeCheckBox {
width: ListView.view.width
height: 44
title: model.name
assetSettings.name: model.imageUrl
assetSettings.isImage: true
assetSettings.bgWidth: 32
assetSettings.bgHeight: 32
assetSettings.bgRadius: assetSettings.bgHeight/2
buttonGroup: collectibleButtonGroup
allChecked: root.allCollectiblesChecked
checked: root.allCollectiblesChecked || root.collectiblesFilter.includes(model.id)
onActionTriggered: root.collectibleToggled(model.id)
loading: d.isFetching
}
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 8
ButtonGroup {
id: collectibleButtonGroup
exclusive: false
}
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: qsTr("No Collectibles")
visible: root.collectiblesList.count === 0
}
SearchBox {
id: collectiblesSearchBox
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
Layout.leftMargin: 8
Layout.rightMargin: 8
input.height: 36
placeholderText: qsTr("Search collectible name")
}
StatusListView {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 0
reuseItems: true
model: SortFilterProxyModel {
sourceModel: root.collectiblesList
filters: ExpressionFilter {
enabled: root.collectiblesList.count > 0 && !!collectiblesSearchBox.text
expression: {
const searchText = collectiblesSearchBox.text.toUpperCase()
return name.toUpperCase().startsWith(searchText)
}
}
}
delegate: ActivityTypeCheckBox {
width: ListView.view.width
height: 44
title: model.name
assetSettings.name: model.imageUrl
assetSettings.isImage: true
assetSettings.bgWidth: 32
assetSettings.bgHeight: 32
assetSettings.bgRadius: assetSettings.bgHeight/2
buttonGroup: collectibleButtonGroup
allChecked: root.allCollectiblesChecked
checked: root.allCollectiblesChecked || root.collectiblesFilter.includes(model.id)
onActionTriggered: root.collectibleToggled(model.id)
loading: d.isFetching
}
}
}
}

View File

@ -486,6 +486,7 @@ Item {
}
}
tertiaryTitle: !d.loadingInputDate && !d.decodedInputData ? qsTr("Data could not be decoded") : ""
statusListItemTertiaryTitle.anchors.top: undefined
statusListItemTertiaryTitle.anchors.baseline: statusListItemTitle.baseline
statusListItemTertiaryTitle.font: statusListItemTitle.font
onButtonClicked: addressMenu.openInputDataMenu(this, !!d.decodedInputData ? d.decodedInputData : root.transaction.input)