2023-12-26 10:19:41 +00:00
|
|
|
import QtQuick 2.14
|
|
|
|
import QtQuick.Controls 2.14
|
|
|
|
import QtQuick.Layouts 1.14
|
|
|
|
|
|
|
|
import StatusQ.Components 0.1
|
|
|
|
import StatusQ.Core 0.1
|
|
|
|
import StatusQ.Core.Theme 0.1
|
2024-01-23 15:35:53 +00:00
|
|
|
import StatusQ.Controls.Validators 0.1
|
2023-12-26 10:19:41 +00:00
|
|
|
|
|
|
|
import SortFilterProxyModel 0.2
|
|
|
|
|
2024-01-23 15:35:53 +00:00
|
|
|
import utils 1.0
|
2023-12-26 10:19:41 +00:00
|
|
|
import shared.controls 1.0
|
2024-05-22 08:13:39 +00:00
|
|
|
import shared.stores 1.0 as SharedStores
|
|
|
|
import AppLayouts.Profile.stores 1.0 as ProfileStores
|
2023-12-26 10:19:41 +00:00
|
|
|
|
|
|
|
import "../stores"
|
|
|
|
import "../controls"
|
|
|
|
|
|
|
|
ColumnLayout {
|
|
|
|
id: root
|
|
|
|
|
2024-05-22 08:13:39 +00:00
|
|
|
property ProfileStores.ContactsStore contactsStore
|
|
|
|
property SharedStores.NetworkConnectionStore networkConnectionStore
|
2023-12-26 10:19:41 +00:00
|
|
|
|
2024-11-05 18:51:17 +00:00
|
|
|
signal sendToAddressRequested(string address)
|
|
|
|
|
2023-12-26 10:19:41 +00:00
|
|
|
QtObject {
|
|
|
|
id: d
|
|
|
|
|
|
|
|
function reset() {
|
|
|
|
RootStore.lastCreatedSavedAddress = undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-23 15:35:53 +00:00
|
|
|
SearchBox {
|
|
|
|
id: searchBox
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.bottomMargin: 16
|
|
|
|
visible: RootStore.savedAddresses.count > 0
|
|
|
|
placeholderText: qsTr("Search for name, ENS or address")
|
|
|
|
|
|
|
|
validators: [
|
|
|
|
StatusValidator {
|
|
|
|
property bool isEmoji: false
|
|
|
|
|
|
|
|
name: "check-for-no-emojis"
|
|
|
|
validate: (value) => {
|
|
|
|
if (!value) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
isEmoji = Constants.regularExpressions.emoji.test(value)
|
|
|
|
if (isEmoji){
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return Constants.regularExpressions.alphanumericalExpanded1.test(value)
|
|
|
|
}
|
|
|
|
errorMessage: isEmoji?
|
|
|
|
qsTr("Your search is too cool (use A-Z and 0-9, single whitespace, hyphens and underscores only)")
|
|
|
|
: qsTr("Your search contains invalid characters (use A-Z and 0-9, single whitespace, hyphens and underscores only)")
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
2023-12-26 10:19:41 +00:00
|
|
|
ShapeRectangle {
|
|
|
|
id: noSavedAddresses
|
|
|
|
Layout.fillWidth: true
|
2024-01-23 15:35:53 +00:00
|
|
|
visible: RootStore.savedAddresses.count === 0
|
2023-12-26 10:19:41 +00:00
|
|
|
text: qsTr("Your saved addresses will appear here")
|
|
|
|
}
|
|
|
|
|
2024-01-23 15:35:53 +00:00
|
|
|
ShapeRectangle {
|
|
|
|
id: emptySearchResult
|
|
|
|
Layout.fillWidth: true
|
|
|
|
visible: RootStore.savedAddresses.count > 0 && listView.count === 0
|
|
|
|
text: qsTr("No saved addresses found. Check spelling or address is correct.")
|
|
|
|
}
|
|
|
|
|
2023-12-26 10:19:41 +00:00
|
|
|
StatusLoadingIndicator {
|
|
|
|
id: loadingIndicator
|
|
|
|
Layout.alignment: Qt.AlignHCenter
|
|
|
|
visible: RootStore.addingSavedAddress || RootStore.deletingSavedAddress
|
|
|
|
color: Theme.palette.directColor4
|
|
|
|
}
|
|
|
|
|
|
|
|
Item {
|
2024-02-12 16:03:11 +00:00
|
|
|
visible: noSavedAddresses.visible || emptySearchResult.visible
|
2023-12-26 10:19:41 +00:00
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
}
|
|
|
|
|
|
|
|
StatusListView {
|
|
|
|
id: listView
|
|
|
|
objectName: "SavedAddressesView_savedAddresses"
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
2023-12-29 15:40:14 +00:00
|
|
|
spacing: 8
|
2023-12-26 10:19:41 +00:00
|
|
|
visible: count > 0
|
2023-12-29 15:40:14 +00:00
|
|
|
|
2023-12-26 10:19:41 +00:00
|
|
|
model: SortFilterProxyModel {
|
|
|
|
sourceModel: RootStore.savedAddresses
|
2024-01-23 15:35:53 +00:00
|
|
|
delayed: true
|
|
|
|
|
|
|
|
sorters: RoleSorter {
|
|
|
|
roleName: "name"
|
|
|
|
sortOrder: Qt.AscendingOrder
|
|
|
|
}
|
|
|
|
|
|
|
|
filters: ExpressionFilter {
|
|
|
|
|
|
|
|
function spellingTolerantSearch(data, searchKeyword) {
|
|
|
|
const regex = new RegExp(searchKeyword.split('').join('.{0,1}'), 'i')
|
|
|
|
return regex.test(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
enabled: !!searchBox.text && searchBox.valid
|
|
|
|
|
|
|
|
expression: {
|
|
|
|
searchBox.text
|
|
|
|
let keyword = searchBox.text.trim().toUpperCase()
|
|
|
|
return spellingTolerantSearch(model.name, keyword) ||
|
|
|
|
model.address.toUpperCase().includes(keyword) ||
|
2024-10-03 20:13:01 +00:00
|
|
|
model.ens.toUpperCase().includes(keyword)
|
2024-01-23 15:35:53 +00:00
|
|
|
}
|
|
|
|
}
|
2023-12-26 10:19:41 +00:00
|
|
|
}
|
2023-12-29 15:40:14 +00:00
|
|
|
|
|
|
|
section.property: "name"
|
|
|
|
section.criteria: ViewSection.FirstCharacter
|
|
|
|
section.delegate: Item {
|
|
|
|
height: 34
|
|
|
|
width: children.width
|
|
|
|
StatusBaseText {
|
|
|
|
anchors.left: parent.left
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
text: section.toUpperCase()
|
|
|
|
color: Theme.palette.baseColor1
|
|
|
|
font.pixelSize: 15
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-26 10:19:41 +00:00
|
|
|
delegate: SavedAddressesDelegate {
|
|
|
|
id: savedAddressDelegate
|
|
|
|
objectName: "savedAddressView_Delegate_" + name
|
|
|
|
name: model.name
|
2024-02-22 08:33:16 +00:00
|
|
|
address: model.mixedcaseAddress
|
2023-12-26 10:19:41 +00:00
|
|
|
ens: model.ens
|
2023-12-29 13:10:55 +00:00
|
|
|
colorId: model.colorId
|
2024-02-02 09:55:56 +00:00
|
|
|
networkConnectionStore: root.networkConnectionStore
|
2023-12-26 10:19:41 +00:00
|
|
|
areTestNetworksEnabled: RootStore.areTestNetworksEnabled
|
2024-11-05 18:51:17 +00:00
|
|
|
onOpenSendModal: root.sendToAddressRequested(recipient)
|
2023-12-26 10:19:41 +00:00
|
|
|
|
|
|
|
states: [
|
|
|
|
State {
|
|
|
|
name: "highlighted"
|
2023-12-29 13:10:55 +00:00
|
|
|
when: RootStore.lastCreatedSavedAddress ? (!RootStore.lastCreatedSavedAddress.error &&
|
2024-01-09 13:50:01 +00:00
|
|
|
RootStore.lastCreatedSavedAddress.address.toLowerCase() === address.toLowerCase()) : false
|
2023-12-26 10:19:41 +00:00
|
|
|
PropertyChanges { target: savedAddressDelegate; color: Theme.palette.baseColor2 }
|
|
|
|
StateChangeScript {
|
|
|
|
script: Qt.callLater(d.reset)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
transitions: [
|
|
|
|
Transition {
|
|
|
|
from: "highlighted"
|
|
|
|
ColorAnimation {
|
|
|
|
target: savedAddressDelegate
|
|
|
|
duration: 3000
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|