2023-11-22 19:58:02 +00:00
import QtQuick 2.15
import QtQuick . Controls 2.15
import QtQuick . Layouts 1.15
2021-10-05 20:50:22 +00:00
2022-07-13 12:29:38 +00:00
import StatusQ . Core 0.1
2022-08-24 15:47:26 +00:00
import StatusQ . Core . Theme 0.1
2022-08-08 21:12:12 +00:00
import StatusQ . Controls 0.1
import StatusQ . Components 0.1
2023-11-22 19:58:02 +00:00
import StatusQ . Popups 0.1
import StatusQ . Popups . Dialog 0.1
import StatusQ . Models 0.1
import StatusQ . Internal 0.1
2022-08-08 21:12:12 +00:00
import SortFilterProxyModel 0.2
2022-07-13 12:29:38 +00:00
2021-10-05 20:50:22 +00:00
import utils 1.0
2023-11-22 19:58:02 +00:00
import shared . stores 1.0
2022-11-23 17:58:22 +00:00
import shared . controls 1.0
2023-11-22 19:58:02 +00:00
import shared . popups 1.0
2021-10-05 20:50:22 +00:00
2023-11-22 19:58:02 +00:00
StatusScrollView {
2022-08-08 21:12:12 +00:00
id: root
2023-11-22 19:58:02 +00:00
// expected roles: name, symbol, enabledNetworkBalance, enabledNetworkCurrencyBalance, currencyPrice, changePct24hour, communityId, communityName, communityImage
required property var assets
2023-03-15 09:17:25 +00:00
property var networkConnectionStore
2023-11-22 19:58:02 +00:00
property var overview
2022-08-08 21:12:12 +00:00
property bool assetDetailsLaunched: false
signal assetClicked ( var token )
2023-11-22 19:58:02 +00:00
signal sendRequested ( string symbol )
signal receiveRequested ( string symbol )
signal switchToCommunityRequested ( string communityId )
signal manageTokensRequested ( )
contentWidth: availableWidth
2022-08-08 21:12:12 +00:00
QtObject {
id: d
property int selectedAssetIndex: - 1
2022-03-25 08:46:47 +00:00
2023-11-22 19:58:02 +00:00
readonly property bool isCustomView: d . controller . hasSettings // TODO add respect other predefined orders (#12517)
2021-10-05 20:50:22 +00:00
2023-11-22 19:58:02 +00:00
function symbolIsVisible ( symbol , balance ) {
if ( symbol === "ETH" ) // always visible
return true
if ( ! d . controller . filterAcceptsSymbol ( symbol ) ) // explicitely hidden
return false
if ( symbol === "SNT" || symbol === "DAI" ) // visible by default
return true
return ! ! balance && ! ! balance . amount // visible with non-zero balance
}
readonly property var regularAssetsModel: SortFilterProxyModel {
sourceModel: root . assets
2023-01-10 13:04:23 +00:00
2023-11-22 19:58:02 +00:00
filters: [
ExpressionFilter {
expression: {
d . controller . settingsDirty
return d . symbolIsVisible ( model . symbol , model . enabledNetworkBalance ) && ! model . communityId
}
}
// TODO add other sort/filter using ManageTokensController (#12517)
]
sorters: ExpressionSorter {
expression: {
d . controller . settingsDirty
return d . controller . lessThan ( modelLeft . symbol , modelRight . symbol )
}
enabled: d . isCustomView
}
2023-03-22 22:08:36 +00:00
}
2023-11-22 19:58:02 +00:00
readonly property var communityAssetsModel: SortFilterProxyModel {
sourceModel: root . assets
filters: [
ExpressionFilter {
expression: {
d . controller . settingsDirty
return d . symbolIsVisible ( model . symbol , model . enabledNetworkBalance ) && ! ! model . communityId
}
}
// TODO add other sort/filter using ManageTokensController (#12517)
]
sorters: ExpressionSorter {
expression: {
d . controller . settingsDirty
return d . controller . lessThan ( modelLeft . symbol , modelRight . symbol )
}
enabled: d . isCustomView
}
}
readonly property bool hasCommunityAssets: d . communityAssetsModel . count
readonly property var controller: ManageTokensController {
settingsKey: "WalletAssets"
}
function hideAllCommunityTokens ( communityId ) {
const tokenSymbols = ModelUtils . getAll ( communityAssetsModel , "symbol" , "communityId" , communityId )
d . controller . settingsHideCommunityTokens ( communityId , tokenSymbols )
2022-08-08 21:12:12 +00:00
}
2023-01-10 13:04:23 +00:00
}
2022-08-24 15:47:26 +00:00
2023-11-22 19:58:02 +00:00
ColumnLayout {
width: root . availableWidth
spacing: 0
StatusListView {
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
interactive: false
objectName: "assetViewStatusListView"
model: d . regularAssetsModel
delegate: delegateLoader
}
StatusDialogDivider {
Layout.fillWidth: true
Layout.topMargin: Style . current . padding
Layout.bottomMargin: Style . current . halfPadding
visible: d . hasCommunityAssets
}
RowLayout {
Layout.fillWidth: true
Layout.leftMargin: Style . current . padding
Layout.rightMargin: Style . current . smallPadding
Layout.bottomMargin: 4
visible: d . hasCommunityAssets
StatusBaseText {
text: qsTr ( "Community assets" )
color: Theme . palette . baseColor1
}
Item { Layout.fillWidth: true }
StatusFlatButton {
Layout.preferredWidth: 32
Layout.preferredHeight: 32
icon.name: "info"
textColor: Theme . palette . baseColor1
horizontalPadding: 0
verticalPadding: 0
onClicked: Global . openPopup ( communityInfoPopupCmp )
}
}
StatusListView {
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
interactive: false
objectName: "communityAssetViewStatusListView"
model: d . communityAssetsModel
delegate: delegateLoader
}
Component {
id: delegateLoader
Loader {
property var modelData: model
property int index: index
width: ListView . view . width
sourceComponent: model . loading ? loadingTokenDelegate: tokenDelegate
}
}
Component {
id: loadingTokenDelegate
LoadingTokenDelegate {
objectName: "AssetView_LoadingTokenDelegate_" + index
}
}
Component {
id: tokenDelegate
TokenDelegate {
objectName: "AssetView_TokenListItem_" + ( ! ! modelData ? modelData.symbol : "" )
readonly property string balance: ! ! modelData ? "%1" . arg ( modelData . enabledNetworkBalance . amount ) : "" // Needed for the tests
errorTooltipText_1: ! ! modelData && ! ! networkConnectionStore ? networkConnectionStore . getBlockchainNetworkDownTextForToken ( modelData . balances ) : ""
errorTooltipText_2: ! ! networkConnectionStore ? networkConnectionStore . getMarketNetworkDownText ( ) : ""
subTitle: {
if ( ! modelData ) {
return ""
}
if ( networkConnectionStore && networkConnectionStore . noTokenBalanceAvailable ) {
return ""
}
return LocaleUtils . currencyAmountToLocaleString ( modelData . enabledNetworkBalance )
}
errorMode: ! ! networkConnectionStore ? networkConnectionStore . noBlockchainConnectionAndNoCache && ! networkConnectionStore.noMarketConnectionAndNoCache : false
errorIcon.tooltip.text: ! ! networkConnectionStore ? networkConnectionStore.noBlockchainConnectionAndNoCacheText : ""
onClicked: ( itemId , mouse ) = > {
if ( mouse . button === Qt . LeftButton ) {
RootStore . getHistoricalDataForToken ( modelData . symbol , RootStore . currencyStore . currentCurrency )
d . selectedAssetIndex = index
assetClicked ( modelData )
} else if ( mouse . button === Qt . RightButton ) {
Global . openMenu ( tokenContextMenu , this ,
{ symbol: modelData . symbol , assetName: modelData . name , assetImage: symbolUrl ,
communityId: modelData . communityId , communityName: modelData . communityName , communityImage: modelData . communityImage } )
}
2023-06-06 06:13:22 +00:00
}
2023-11-22 19:58:02 +00:00
onSwitchToCommunityRequested: root . switchToCommunityRequested ( communityId )
Component.onCompleted: {
// on Model reset if the detail view is shown, update the data in background.
if ( root . assetDetailsLaunched && index === d . selectedAssetIndex )
assetClicked ( modelData )
2023-06-06 06:13:22 +00:00
}
}
2023-11-22 19:58:02 +00:00
}
Component {
id: tokenContextMenu
StatusMenu {
onClosed: destroy ( )
property string symbol
property string assetName
property string assetImage
property string communityId
property string communityName
property string communityImage
StatusAction {
enabled: root . networkConnectionStore . sendBuyBridgeEnabled && ! root . overview . isWatchOnlyAccount && root . overview . canSend
icon.name: "send"
text: qsTr ( "Send" )
onTriggered: root . sendRequested ( symbol )
}
StatusAction {
icon.name: "receive"
text: qsTr ( "Receive" )
onTriggered: root . receiveRequested ( symbol )
}
StatusMenuSeparator { }
StatusAction {
icon.name: "settings"
text: qsTr ( "Manage tokens" )
onTriggered: root . manageTokensRequested ( )
}
StatusAction {
enabled: symbol !== "ETH"
type: StatusAction . Type . Danger
icon.name: "hide"
text: qsTr ( "Hide asset" )
onTriggered: Global . openPopup ( confirmHideAssetPopup , { symbol , assetName , assetImage , communityId } )
}
StatusAction {
enabled: ! ! communityId
type: StatusAction . Type . Danger
icon.name: "hide"
text: qsTr ( "Hide all assets from this community" )
onTriggered: Global . openPopup ( confirmHideCommunityAssetsPopup , { communityId , communityName , communityImage } )
}
2022-08-08 21:12:12 +00:00
}
2023-11-22 19:58:02 +00:00
}
Component {
id: communityInfoPopupCmp
StatusDialog {
destroyOnClose: true
title: qsTr ( "What are community assets?" )
standardButtons: Dialog . Ok
width: 520
contentItem: StatusBaseText {
wrapMode: Text . Wrap
text: qsTr ( "Community assets are assets that have been minted by a community. As these assets cannot be verified, always double check their origin and validity before interacting with them. If in doubt, ask a trusted member or admin of the relevant community." )
}
}
}
Component {
id: confirmHideAssetPopup
ConfirmationDialog {
property string symbol
property string assetName
property string assetImage
property string communityId
readonly property string formattedName: assetName + ( communityId ? " (" + qsTr ( "community asset" ) + ")" : "" )
width: 520
destroyOnClose: true
confirmButtonLabel: qsTr ( "Hide %1" ) . arg ( assetName )
cancelBtnType: ""
showCancelButton: true
headerSettings.title: qsTr ( "Hide %1" ) . arg ( formattedName )
headerSettings.asset.name: assetImage
confirmationText: qsTr ( "Are you sure you want to hide %1? You will no longer see or be able to interact with this asset anywhere inside Status." ) . arg ( formattedName )
onCancelButtonClicked: close ( )
onConfirmButtonClicked: {
d . controller . settingsHideToken ( symbol )
close ( )
Global . displayToastMessage (
qsTr ( "%1 was successfully hidden. You can toggle asset visibility via %2." ) . arg ( formattedName )
. arg ( ` < a style = "text-decoration:none" href = "#${Constants.appSection.profile}/${Constants.settingsSubsection.wallet}" > ` + qsTr ( "Settings" , "Go to Settings" ) + "</a>" ) ,
"" ,
"checkmark-circle" ,
false ,
Constants . ephemeralNotificationType . success ,
""
)
}
}
}
Component {
id: confirmHideCommunityAssetsPopup
ConfirmationDialog {
property string communityId
property string communityName
property string communityImage
width: 520
destroyOnClose: true
confirmButtonLabel: qsTr ( "Hide all assets minted by this community" )
cancelBtnType: ""
showCancelButton: true
headerSettings.title: qsTr ( "Hide %1 community assets" ) . arg ( communityName )
headerSettings.asset.name: communityImage
confirmationText: qsTr ( "Are you sure you want to hide all community assets minted by %1? You will no longer see or be able to interact with these assets anywhere inside Status." ) . arg ( communityName )
onCancelButtonClicked: close ( )
onConfirmButtonClicked: {
d . hideAllCommunityTokens ( communityId )
close ( )
Global . displayToastMessage (
qsTr ( "%1 community assets were successfully hidden. You can toggle asset visibility via %2." ) . arg ( communityName )
. arg ( ` < a style = "text-decoration:none" href = "#${Constants.appSection.profile}/${Constants.settingsSubsection.wallet}" > ` + qsTr ( "Settings" , "Go to Settings" ) + "</a>" ) ,
"" ,
"checkmark-circle" ,
false ,
Constants . ephemeralNotificationType . success ,
""
)
}
2022-08-08 21:12:12 +00:00
}
2022-07-14 11:03:36 +00:00
}
2021-10-05 20:50:22 +00:00
}
}