2024-03-02 10:48:11 +00:00
import QtQuick 2.15
import QtQml 2.15
import QtQuick . Controls 2.15
import QtQml . Models 2.15
import QtQuick . Layouts 1.15
2022-03-01 10:14:13 +00:00
import utils 1.0
import shared . controls 1.0
import shared . panels 1.0
2024-01-26 15:28:49 +00:00
import shared . stores 1.0 as SharedStores
2022-03-01 10:14:13 +00:00
2024-06-15 21:33:12 +00:00
import StatusQ 0.1
2022-03-01 10:14:13 +00:00
import StatusQ . Core 0.1
import StatusQ . Core . Theme 0.1
2024-06-15 21:33:12 +00:00
import StatusQ . Core . Utils 0.1 as StatusQUtils
2022-03-01 10:14:13 +00:00
import StatusQ . Controls 0.1
import StatusQ . Controls . Validators 0.1
2024-01-10 13:31:44 +00:00
import StatusQ . Popups 0.1
2023-02-20 10:57:45 +00:00
import StatusQ . Components 0.1
2022-03-01 10:14:13 +00:00
2023-02-20 10:57:45 +00:00
import SortFilterProxyModel 0.2
2023-04-05 11:10:44 +00:00
import AppLayouts . stores 1.0
2022-03-01 10:14:13 +00:00
import "../stores"
2023-04-05 11:10:44 +00:00
import "../controls"
2023-02-20 10:57:45 +00:00
import ".."
2022-03-01 10:14:13 +00:00
2024-01-10 13:31:44 +00:00
StatusModal {
2022-03-01 10:14:13 +00:00
id: root
2024-03-13 17:38:16 +00:00
property var flatNetworks
2023-03-08 10:57:15 +00:00
2024-01-10 13:31:44 +00:00
closePolicy: Popup . CloseOnEscape | Popup . CloseOnPressOutside
2023-02-20 10:57:45 +00:00
2023-12-29 13:10:55 +00:00
width: 477
2022-03-01 10:14:13 +00:00
2024-01-10 13:31:44 +00:00
headerSettings.title: d . editMode ? qsTr ( "Edit saved address" ) : qsTr ( "Add new saved address" )
headerSettings.subTitle: d . editMode ? d.name : ""
2024-03-02 10:48:11 +00:00
property var store: RootStore
2023-12-29 13:10:55 +00:00
function initWithParams ( params = { } ) {
d . storedName = params . name ? ? ""
d . storedColorId = params . colorId ? ? ""
d . storedChainShortNames = params . chainShortNames ? ? ""
d . editMode = params . edit ? ? false
d . addAddress = params . addAddress ? ? false
d . name = d . storedName
nameInput . input . dirty = false
d . address = params . address ? ? Constants . zeroAddress
d . ens = params . ens ? ? ""
d . colorId = d . storedColorId
d . chainShortNames = d . storedChainShortNames
d . initialized = true
if ( d . colorId === "" ) {
colorSelection . selectedColorIndex = Math . floor ( Math . random ( ) * colorSelection . model . length )
}
else {
let ind = Utils . getColorIndexForId ( d . colorId )
colorSelection . selectedColorIndex = ind
}
2024-01-26 15:28:49 +00:00
if ( d . addressInputIsENS )
2023-12-29 13:10:55 +00:00
addressInput . setPlainText ( d . ens )
else
addressInput . setPlainText ( "%1%2"
. arg ( d . chainShortNames )
. arg ( d . address == Constants . zeroAddress ? "" : d . address ) )
2024-05-27 21:29:31 +00:00
nameInput . input . edit . forceActiveFocus ( )
2023-12-26 10:19:41 +00:00
}
2022-03-01 10:14:13 +00:00
2024-01-26 15:28:49 +00:00
enum CardType {
Contact ,
WalletAccount ,
SavedAddress
}
2022-03-01 10:14:13 +00:00
QtObject {
2022-08-08 18:21:56 +00:00
id: d
2023-12-29 13:10:55 +00:00
2024-01-10 13:31:44 +00:00
readonly property int componentWidth: 445
2023-12-29 13:10:55 +00:00
property bool editMode: false
property bool addAddress: false
property alias name: nameInput . text
property string address: Constants . zeroAddress // Setting as zero address since we don't have the address yet
property string ens: ""
property string colorId: ""
property string chainShortNames: ""
property string storedName: ""
property string storedColorId: ""
property string storedChainShortNames: ""
2023-02-20 10:57:45 +00:00
property bool chainShortNamesDirty: false
2024-06-15 21:33:12 +00:00
property var networkSelection: [ ]
onNetworkSelectionChanged: {
if ( d . networkSelection !== networkSelectPopup . selection ) {
networkSelectPopup . selection = d . networkSelection
}
}
2024-01-26 15:28:49 +00:00
property bool addressInputValid: d . editMode ||
addressInput . input . dirty &&
d . addressInputIsAddress &&
! d . minAddressLengthRequestError &&
! d . addressAlreadyAddedToWalletError &&
! d . addressAlreadyAddedToSavedAddressesError
readonly property bool valid: d . addressInputValid && nameInput . valid
2023-12-29 13:10:55 +00:00
readonly property bool dirty: nameInput . input . dirty && ( ! d . editMode || d . storedName !== d . name )
|| chainShortNamesDirty && ( ! d . editMode || d . storedChainShortNames !== d . chainShortNames )
|| d . colorId . toUpperCase ( ) !== d . storedColorId . toUpperCase ( )
2023-02-20 10:57:45 +00:00
readonly property var chainPrefixRegexPattern: /[^:]+\:?|:/g
2024-01-26 15:28:49 +00:00
readonly property bool addressInputIsENS: ! ! d . ens &&
Utils . isValidEns ( d . ens )
readonly property bool addressInputIsAddress: ! ! d . address &&
d . address != Constants . zeroAddress &&
( Utils . isAddress ( d . address ) || Utils . isValidAddressWithChainPrefix ( d . address ) )
2024-03-02 10:48:11 +00:00
readonly property bool addressInputHasError: ! ! addressInput . errorMessageCmp . text
onAddressInputHasErrorChanged: addressInput . input . valid = ! addressInputHasError // can't use binding because valid is overwritten in StatusInput
readonly property string networksHiddenState: "networksHidden"
2024-01-26 15:28:49 +00:00
property ListModel cardsModel: ListModel { }
// possible errors/warnings
readonly property int minAddressLen: 1
property bool minAddressLengthRequestError: false
property bool addressAlreadyAddedToWalletError: false
property bool addressAlreadyAddedToSavedAddressesError: false
property bool checkingContactsAddressInProgress: false
property int contactsWithSameAddress: 0
2023-02-20 10:57:45 +00:00
2024-05-27 21:29:31 +00:00
function checkIfAddressIsAlreadyAddedToWallet ( address ) {
2024-03-02 10:48:11 +00:00
let account = root . store . getWalletAccount ( address )
2024-01-26 15:28:49 +00:00
d . cardsModel . clear ( )
d . addressAlreadyAddedToWalletError = ! ! account . name
if ( ! d . addressAlreadyAddedToWalletError ) {
return
}
d . cardsModel . append ( {
type: AddEditSavedAddressPopup . CardType . WalletAccount ,
address: account . mixedcaseAddress ,
title: account . name ,
icon: "" ,
emoji: account . emoji ,
color: Utils . getColorForId ( account . colorId ) . toString ( ) . toUpperCase ( )
} )
2024-01-23 08:15:07 +00:00
}
2024-05-27 21:29:31 +00:00
function checkIfAddressIsAlreadyAddedToSavedAddresses ( address ) {
2024-03-02 10:48:11 +00:00
let savedAddress = root . store . getSavedAddress ( address )
2024-01-26 15:28:49 +00:00
d . cardsModel . clear ( )
d . addressAlreadyAddedToSavedAddressesError = ! ! savedAddress . address
if ( ! d . addressAlreadyAddedToSavedAddressesError ) {
return
}
d . cardsModel . append ( {
type: AddEditSavedAddressPopup . CardType . SavedAddress ,
address: savedAddress . ens || savedAddress . address ,
title: savedAddress . name ,
icon: "" ,
emoji: "" ,
color: Utils . getColorForId ( savedAddress . colorId ) . toString ( ) . toUpperCase ( )
} )
2024-01-09 13:50:01 +00:00
}
2024-01-26 15:28:49 +00:00
property bool resolvingEnsNameInProgress: false
readonly property string uuid: Utils . uuid ( )
readonly property var validateEnsAsync: Backpressure . debounce ( root , 500 , function ( value ) {
var name = value . startsWith ( "@" ) ? value . substring ( 1 ) : value
mainModule . resolveENS ( name , d . uuid )
} ) ;
2024-03-29 11:43:49 +00:00
property var contactsModuleInst: SharedStores . RootStore . profileSectionModuleInst . contactsModule
2024-01-26 15:28:49 +00:00
2023-04-05 11:10:44 +00:00
/// Ensures that the \c root.address and \c root.chainShortNames are not reset when the initial text is set
property bool initialized: false
2023-02-20 10:57:45 +00:00
function getPrefixArrayWithColumns ( prefixStr ) {
return prefixStr . match ( d . chainPrefixRegexPattern )
}
2024-01-26 15:28:49 +00:00
function resetAddressValues ( fullReset ) {
if ( fullReset ) {
d . ens = ""
d . address = Constants . zeroAddress
d . chainShortNames = ""
2024-06-15 21:33:12 +00:00
d . networkSelection = [ ]
2024-01-26 15:28:49 +00:00
}
d . cardsModel . clear ( )
d . resolvingEnsNameInProgress = false
d . checkingContactsAddressInProgress = false
}
function checkForAddressInputOwningErrorsWarnings ( ) {
d . addressAlreadyAddedToWalletError = false
d . addressAlreadyAddedToSavedAddressesError = false
if ( d . addressInputIsAddress ) {
2024-05-27 21:29:31 +00:00
d . checkIfAddressIsAlreadyAddedToWallet ( d . address )
2024-01-26 15:28:49 +00:00
if ( d . addressAlreadyAddedToWalletError ) {
addressInput . errorMessageCmp . text = qsTr ( "You cannot add your own account as a saved address" )
addressInput . errorMessageCmp . visible = true
return
}
2024-05-27 21:29:31 +00:00
d . checkIfAddressIsAlreadyAddedToSavedAddresses ( d . address )
2024-01-26 15:28:49 +00:00
if ( d . addressAlreadyAddedToSavedAddressesError ) {
addressInput . errorMessageCmp . text = qsTr ( "This address is already saved" )
addressInput . errorMessageCmp . visible = true
return
}
d . checkingContactsAddressInProgress = true
d . contactsWithSameAddress = 0
2024-03-29 11:43:49 +00:00
d . contactsModuleInst . fetchProfileShowcaseAccountsByAddress ( d . address )
2024-01-26 15:28:49 +00:00
return
}
addressInput . errorMessageCmp . text = qsTr ( "Not registered ens address" )
addressInput . errorMessageCmp . visible = true
}
function checkForAddressInputErrorsWarnings ( ) {
addressInput . errorMessageCmp . visible = false
addressInput . errorMessageCmp . color = Theme . palette . dangerColor1
addressInput . errorMessageCmp . text = ""
d . minAddressLengthRequestError = false
if ( d . editMode || ! addressInput . input . dirty ) {
return
}
if ( d . addressInputIsENS || d . addressInputIsAddress ) {
let value = d . ens || d . address
if ( value . trim ( ) . length < d . minAddressLen ) {
d . minAddressLengthRequestError = true
addressInput . errorMessageCmp . text = qsTr ( "Please enter an ethereum address" )
addressInput . errorMessageCmp . visible = true
return
}
}
if ( d . addressInputIsENS ) {
d . resolvingEnsNameInProgress = true
d . validateEnsAsync ( d . ens )
return
}
2024-03-02 10:48:11 +00:00
networkSelector . state = ""
2024-01-26 15:28:49 +00:00
if ( d . addressInputIsAddress ) {
d . checkForAddressInputOwningErrorsWarnings ( )
return
}
addressInput . errorMessageCmp . text = qsTr ( "Ethereum address invalid" )
addressInput . errorMessageCmp . visible = true
2023-02-20 10:57:45 +00:00
}
2023-12-29 15:40:14 +00:00
function submit ( event ) {
if ( ! d . valid
2024-01-10 13:31:44 +00:00
|| ! d . dirty
|| event !== undefined && event . key !== Qt . Key_Return && event . key !== Qt . Key_Enter )
2023-12-29 15:40:14 +00:00
return
2024-03-02 10:48:11 +00:00
root . store . createOrUpdateSavedAddress ( d . name , d . address , d . ens , d . colorId , d . chainShortNames )
2023-12-29 15:40:14 +00:00
root . close ( )
}
2024-01-26 15:28:49 +00:00
}
2024-01-09 13:50:01 +00:00
2024-01-26 15:28:49 +00:00
Connections {
target: mainModule
function onResolvedENS ( resolvedPubKey: string , resolvedAddress: string , uuid: string ) {
if ( uuid !== d . uuid ) {
return
}
d . resolvingEnsNameInProgress = false
d . address = resolvedAddress
2024-03-02 10:48:11 +00:00
try { // allows to avoid issues in storybook without much refactoring
d . checkForAddressInputOwningErrorsWarnings ( )
}
catch ( e ) {
}
if ( ! d . addressInputHasError )
networkSelector . state = d . networksHiddenState
else
networkSelector . state = ""
2024-01-26 15:28:49 +00:00
}
}
Connections {
2024-03-29 11:43:49 +00:00
target: d . contactsModuleInst
2024-01-26 15:28:49 +00:00
function onProfileShowcaseAccountsByAddressFetched ( accounts: string ) {
d . cardsModel . clear ( )
d . checkingContactsAddressInProgress = false
try {
let accountsJson = JSON . parse ( accounts )
d . contactsWithSameAddress = accountsJson . length
addressInput . errorMessageCmp . visible = d . contactsWithSameAddress > 0
addressInput . errorMessageCmp . color = Theme . palette . warningColor1
addressInput . errorMessageCmp . text = ""
if ( d . contactsWithSameAddress === 1 )
addressInput . errorMessageCmp . text = qsTr ( "This address belongs to a contact" )
if ( d . contactsWithSameAddress > 1 )
addressInput . errorMessageCmp . text = qsTr ( "This address belongs to the following contacts" )
for ( let i = 0 ; i < accountsJson . length ; ++ i ) {
let contact = Utils . getContactDetailsAsJson ( accountsJson [ i ] . contactId , true , true , true )
d . cardsModel . append ( {
type: AddEditSavedAddressPopup . CardType . Contact ,
address: accountsJson [ i ] . address ,
title: ProfileUtils . displayName ( contact . localNickname , contact . name , contact . displayName , contact . alias ) ,
icon: contact . icon ,
emoji: "" ,
color: Utils . colorForColorId ( contact . colorId ) ,
onlineStatus: contact . onlineStatus ,
colorHash: contact . colorHash
} )
}
}
catch ( e ) {
console . warn ( "error parsing fetched accounts for contact: " , e . message )
}
}
2022-03-01 10:14:13 +00:00
}
2024-01-10 13:31:44 +00:00
StatusScrollView {
id: scrollView
anchors.fill: parent
padding: 0
contentWidth: availableWidth
Column {
2024-03-02 10:48:11 +00:00
id: column
2024-01-10 13:31:44 +00:00
width: scrollView . availableWidth
height: childrenRect . height
2024-03-02 10:48:11 +00:00
2024-01-10 13:31:44 +00:00
topPadding: 24 // (16 + 8 for Name, until we add it to the StatusInput component)
bottomPadding: 28
spacing: Style . current . xlPadding
StatusInput {
id: nameInput
implicitWidth: d . componentWidth
anchors.horizontalCenter: parent . horizontalCenter
charLimit: 24
input.edit.objectName: "savedAddressNameInput"
placeholderText: qsTr ( "Address name" )
label: qsTr ( "Name" )
validators: [
StatusMinLengthValidator {
minLength: 1
errorMessage: qsTr ( "Please name your saved address" )
} ,
StatusValidator {
2024-01-23 15:35:53 +00:00
property bool isEmoji: false
2024-01-10 13:31:44 +00:00
name: "check-for-no-emojis"
validate: ( value ) = > {
2024-01-23 15:35:53 +00:00
if ( ! value ) {
return true
}
isEmoji = Constants . regularExpressions . emoji . test ( value )
if ( isEmoji ) {
return false
}
return Constants . regularExpressions . alphanumericalExpanded1 . test ( value )
2024-01-10 13:31:44 +00:00
}
2024-01-23 15:35:53 +00:00
errorMessage: isEmoji ?
Constants . errorMessages . emojRegExp
: Constants . errorMessages . alphanumericalExpanded1RegExp
2024-01-10 13:31:44 +00:00
} ,
StatusValidator {
name: "check-saved-address-existence"
validate: ( value ) = > {
2024-03-02 10:48:11 +00:00
return ! root . store . savedAddressNameExists ( value )
2024-01-10 13:31:44 +00:00
|| d . editMode && d . storedName == value
}
errorMessage: qsTr ( "Name already in use" )
}
]
input.clearable: true
input.rightPadding: 16
2024-03-02 10:48:11 +00:00
input.tabNavItem: addressInput
2023-12-29 15:40:14 +00:00
2024-01-10 13:31:44 +00:00
onKeyPressed: {
d . submit ( event )
}
2023-12-29 15:40:14 +00:00
}
2022-03-01 10:14:13 +00:00
2024-01-10 13:31:44 +00:00
StatusInput {
id: addressInput
implicitWidth: d . componentWidth
anchors.horizontalCenter: parent . horizontalCenter
label: qsTr ( "Address" )
objectName: "savedAddressAddressInput"
input.edit.objectName: "savedAddressAddressInputEdit"
placeholderText: qsTr ( "Ethereum address" )
maximumHeight: 66
input.implicitHeight: Math . min ( Math . max ( input . edit . contentHeight + topPadding + bottomPadding , minimumHeight ) , maximumHeight ) // setting height instead does not work
enabled: ! ( d . editMode || d . addAddress )
input.edit.textFormat: TextEdit . RichText
2024-03-02 10:48:11 +00:00
input.rightComponent: ( d . resolvingEnsNameInProgress || d . checkingContactsAddressInProgress ) ?
loadingIndicator : null
2024-01-26 15:28:49 +00:00
input.asset.name: d . addressInputValid && ! d . editMode ? "checkbox" : ""
2024-01-10 13:31:44 +00:00
input.asset.color: enabled ? Theme.palette.primaryColor1 : Theme . palette . baseColor1
2024-03-02 10:48:11 +00:00
input.asset.width: 17
input.asset.height: 17
2024-01-10 13:31:44 +00:00
input.rightPadding: 16
input.leftIcon: false
2024-03-02 10:48:11 +00:00
input.tabNavItem: nameInput
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
multiline: true
2023-02-20 10:57:45 +00:00
2024-01-26 15:28:49 +00:00
property string plainText: input . edit . getText ( 0 , text . length ) . trim ( )
2023-02-20 10:57:45 +00:00
2024-03-02 10:48:11 +00:00
Component {
id: loadingIndicator
StatusLoadingIndicator { }
}
2024-01-10 13:31:44 +00:00
onTextChanged: {
if ( skipTextUpdate || ! d . initialized )
return
2023-02-20 10:57:45 +00:00
2024-01-26 15:28:49 +00:00
plainText = input . edit . getText ( 0 , text . length ) . trim ( )
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
if ( input . edit . previousText != plainText ) {
let newText = plainText
const prefixAndAddress = Utils . splitToChainPrefixAndAddress ( plainText )
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
if ( ! Utils . isLikelyEnsName ( plainText ) ) {
newText = WalletUtils . colorizedChainPrefix ( prefixAndAddress . prefix ) +
prefixAndAddress . address
}
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
setRichText ( newText )
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
// Reset
2024-01-26 15:28:49 +00:00
d . resetAddressValues ( plainText . length == 0 )
if ( plainText . length > 0 ) {
// Update root values
if ( Utils . isLikelyEnsName ( plainText ) ) {
d . ens = plainText
2024-05-28 10:22:07 +00:00
d . address = Constants . zeroAddress
2024-01-26 15:28:49 +00:00
d . chainShortNames = ""
}
else {
d . ens = ""
d . address = prefixAndAddress . address
d . chainShortNames = prefixAndAddress . prefix
2024-06-15 21:33:12 +00:00
Qt . callLater ( ( ) = > {
// Sync chain short names with model. This could result in removing networks from this text
// Call it later to avoid binding loop warnings
d . networkSelection = store . getNetworkIds ( d . chainShortNames ) . split ( ":" ) . filter ( Boolean ) . map ( Number )
} )
2024-01-26 15:28:49 +00:00
}
2024-01-10 13:31:44 +00:00
}
2024-01-26 15:28:49 +00:00
d . checkForAddressInputErrorsWarnings ( )
2023-02-20 10:57:45 +00:00
}
}
2024-01-10 13:31:44 +00:00
onKeyPressed: {
d . submit ( event )
}
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
property bool skipTextUpdate: false
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
function setPlainText ( newText ) {
text = newText
}
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
function setRichText ( val ) {
skipTextUpdate = true
input . edit . previousText = plainText
const curPos = input . cursorPosition
setPlainText ( val )
input . cursorPosition = curPos
skipTextUpdate = false
}
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
function getUnknownPrefixes ( prefixes ) {
2024-06-15 21:33:12 +00:00
const networksCount = root . flatNetworks . rowCount ( )
2024-01-10 13:31:44 +00:00
let unknownPrefixes = prefixes . filter ( e = > {
2024-06-15 21:33:12 +00:00
for ( let i = 0 ; i < networksCount ; i ++ ) {
if ( e == StatusQUtils . ModelUtils . get ( root . flatNetworks , i ) . shortName )
2024-01-10 13:31:44 +00:00
return false
}
return true
} )
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
return unknownPrefixes
2023-02-20 10:57:45 +00:00
}
2024-01-10 13:31:44 +00:00
// Add all chain short names from model, while keeping existing
function syncChainPrefixWithModel ( prefix , model ) {
let prefixes = prefix . split ( ":" ) . filter ( Boolean )
let prefixStr = ""
// Keep unknown prefixes from user input, the rest must be taken
// from the model
for ( let i = 0 ; i < model . count ; i ++ ) {
const item = model . get ( i )
prefixStr += item . shortName + ":"
// Remove all added prefixes from initial array
prefixes = prefixes . filter ( e = > e !== item . shortName )
}
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
const unknownPrefixes = getUnknownPrefixes ( prefixes )
if ( unknownPrefixes . length > 0 ) {
prefixStr += unknownPrefixes . join ( ":" ) + ":"
}
return prefixStr
}
2022-03-01 10:14:13 +00:00
}
2023-02-20 10:57:45 +00:00
2024-01-26 15:28:49 +00:00
Column {
width: scrollView . availableWidth
visible: d . cardsModel . count > 0
spacing: Style . current . halfPadding
Repeater {
model: d . cardsModel
StatusListItem {
width: d . componentWidth
border.width: 1
border.color: Theme . palette . baseColor2
anchors.horizontalCenter: parent . horizontalCenter
title: model . title
subTitle: model . address
statusListItemSubTitle.font.pixelSize: 12
sensor.hoverEnabled: false
statusListItemIcon.badge.visible: model . type === AddEditSavedAddressPopup . CardType . Contact
statusListItemIcon.badge.color: model . type === AddEditSavedAddressPopup . CardType . Contact && model . onlineStatus === 1 ?
Theme . palette . successColor1
: Theme . palette . baseColor1
statusListItemIcon.hoverEnabled: false
ringSettings.ringSpecModel: model . type === AddEditSavedAddressPopup . CardType . Contact ? model.colorHash : ""
asset {
width: 40
height: 40
name: model . icon
isImage: model . icon !== ""
emoji: model . emoji
color: model . color
isLetterIdenticon: ! model . icon
2024-05-17 17:45:27 +00:00
letterIdenticonBgWithAlpha: model . type === AddEditSavedAddressPopup . CardType . SavedAddress
2024-05-17 14:34:25 +00:00
charactersLen: 2
2024-01-26 15:28:49 +00:00
}
}
}
}
2024-01-10 13:31:44 +00:00
StatusColorSelectorGrid {
id: colorSelection
objectName: "addSavedAddressColor"
width: d . componentWidth
anchors.horizontalCenter: parent . horizontalCenter
model: Theme . palette . customisationColorsArray
title.color: Theme . palette . directColor1
title.font.pixelSize: Constants . addAccountPopup . labelFontSize1
title.text: qsTr ( "Colour" )
selectedColorIndex: - 1
onSelectedColorChanged: {
d . colorId = Utils . getIdForColor ( selectedColor )
}
2023-12-29 13:10:55 +00:00
}
2024-01-10 13:31:44 +00:00
StatusNetworkSelector {
id: networkSelector
2024-03-02 10:48:11 +00:00
2024-01-10 13:31:44 +00:00
objectName: "addSavedAddressNetworkSelector"
2024-05-27 21:29:31 +00:00
title: qsTr ( "Network preference" )
2024-01-10 13:31:44 +00:00
implicitWidth: d . componentWidth
anchors.horizontalCenter: parent . horizontalCenter
2023-02-20 10:57:45 +00:00
2024-01-26 15:28:49 +00:00
enabled: d . addressInputValid && ! d . addressInputIsENS
2024-05-27 21:29:31 +00:00
visible: ! ( d . editMode && d . addressInputIsENS )
defaultItemText: qsTr ( "Add networks" )
2024-01-10 13:31:44 +00:00
defaultItemImageSource: "add"
rightButtonVisible: true
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
itemsModel: SortFilterProxyModel {
2024-06-15 21:33:12 +00:00
sourceModel: root . flatNetworks
filters: FastExpressionFilter {
readonly property var filteredNetworks: d . networkSelection
expression: {
return filteredNetworks . length > 0 && filteredNetworks . includes ( model . chainId )
}
expectedRoles: [ "chainId" ]
2024-01-10 13:31:44 +00:00
}
onCountChanged: {
2024-06-15 21:33:12 +00:00
if ( d . initialized ) {
2024-01-10 13:31:44 +00:00
// Initially source model is empty, filter proxy is also empty, but does
// extra work and mistakenly overwrites d.chainShortNames property
if ( sourceModel . count != 0 ) {
const prefixAndAddress = Utils . splitToChainPrefixAndAddress ( addressInput . plainText )
const syncedPrefix = addressInput . syncChainPrefixWithModel ( prefixAndAddress . prefix , this )
2024-06-15 21:33:12 +00:00
if ( addressInput . text !== syncedPrefix + prefixAndAddress . address )
addressInput . setPlainText ( syncedPrefix + prefixAndAddress . address )
2024-01-10 13:31:44 +00:00
}
2023-02-20 10:57:45 +00:00
}
}
}
2024-01-10 13:31:44 +00:00
addButton.highlighted: networkSelectPopup . visible
addButton.onClicked: {
2024-06-15 21:33:12 +00:00
networkSelectPopup . openAtPosition ( addButton . x , addButton . height + Style . current . xlPadding )
2024-01-10 13:31:44 +00:00
}
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
onItemClicked: function ( item , index , mouse ) {
// Append first item
if ( index === 0 && defaultItem . visible )
2024-06-15 21:33:12 +00:00
networkSelectPopup . openAtPosition ( defaultItem . x , defaultItem . height + Style . current . xlPadding )
2024-01-10 13:31:44 +00:00
}
2023-02-20 10:57:45 +00:00
2024-01-10 13:31:44 +00:00
onItemRightButtonClicked: function ( item , index , mouse ) {
2024-06-15 21:33:12 +00:00
let networkSelection = [ . . . d . networkSelection ]
d . networkSelection = networkSelection . filter ( n = > n !== item . modelRef . chainId )
2024-01-10 13:31:44 +00:00
d . chainShortNamesDirty = true
}
2024-03-02 10:48:11 +00:00
readonly property int animationDuration: 350
states: [
// As when networks seclector becomes invisible, spacing before it disappears as well, we see jumping height
// To overcome this, we animate bottom padding to 0 and when spacing disappears, reset bottom padding to spacing to compensate it
State {
name: d . networksHiddenState
PropertyChanges { target: networkSelector ; height: 0 }
PropertyChanges { target: networkSelector ; opacity: 0 }
PropertyChanges { target: column ; bottomPadding: 0 }
}
]
transitions: [
Transition {
NumberAnimation { property: "height" ; duration: networkSelector . animationDuration ; easing.type: Easing . OutCirc }
NumberAnimation { property: "opacity" ; duration: networkSelector . animationDuration ; easing.type: Easing . OutCirc }
SequentialAnimation {
NumberAnimation { property: "bottomPadding" ; duration: networkSelector . animationDuration ; easing.type: Easing . OutCirc }
PropertyAction { target: column ; property: "bottomPadding" ; value: column . spacing }
}
}
]
2023-02-20 10:57:45 +00:00
2024-06-15 21:33:12 +00:00
NetworkSelectPopup {
id: networkSelectPopup
2023-02-20 10:57:45 +00:00
2024-06-15 21:33:12 +00:00
function openAtPosition ( x , y ) {
networkSelectPopup . x = x
networkSelectPopup . y = y
networkSelectPopup . open ( )
}
2023-02-20 10:57:45 +00:00
2024-06-15 21:33:12 +00:00
flatNetworks: root . flatNetworks
selection: d . networkSelection
multiSelection: true
2023-02-20 10:57:45 +00:00
2024-06-15 21:33:12 +00:00
onSelectionChanged: {
if ( d . networkSelection !== networkSelectPopup . selection ) {
d . networkSelection = networkSelectPopup . selection
d . chainShortNamesDirty = true
}
}
2023-02-20 10:57:45 +00:00
2024-06-15 21:33:12 +00:00
closePolicy: Popup . CloseOnEscape | Popup . CloseOnPressOutside
2023-02-20 10:57:45 +00:00
2024-06-15 21:33:12 +00:00
modal: true
dim: false
}
}
}
2022-03-01 10:14:13 +00:00
}
2024-01-10 13:31:44 +00:00
rightButtons: [
StatusButton {
text: d . editMode ? qsTr ( "Save" ) : qsTr ( "Add address" )
2024-01-26 15:28:49 +00:00
enabled: d . valid && d . dirty
2024-01-10 13:31:44 +00:00
onClicked: {
d . submit ( )
2022-07-25 15:16:22 +00:00
}
2024-01-10 13:31:44 +00:00
objectName: "addSavedAddress"
2022-03-01 10:14:13 +00:00
}
2024-01-10 13:31:44 +00:00
]
2022-03-01 10:14:13 +00:00
}