parent
aed61b68b1
commit
085bf762a5
|
@ -209,7 +209,8 @@ proc newModule*[T](
|
|||
result, events, tokenService, collectibleService, currencyService,
|
||||
transactionService, walletAccountService,
|
||||
settingsService, savedAddressService, networkService, accountsService,
|
||||
keycardService, nodeService, networkConnectionService, devicesService
|
||||
keycardService, nodeService, networkConnectionService, devicesService,
|
||||
communityTokensService
|
||||
)
|
||||
result.browserSectionModule = browser_section_module.newModule(
|
||||
result, events, bookmarkService, settingsService, networkService,
|
||||
|
|
|
@ -8,6 +8,7 @@ import app_service/service/wallet_account/service as wallet_account_service
|
|||
import app/modules/shared_models/currency_amount
|
||||
import app_service/service/currency/dto
|
||||
import app_service/service/settings/service as settings_service
|
||||
import app_service/service/community_tokens/service as community_tokens_service
|
||||
|
||||
type
|
||||
Controller* = ref object of RootObj
|
||||
|
@ -16,6 +17,7 @@ type
|
|||
tokenService: token_service.Service
|
||||
walletAccountService: wallet_account_service.Service
|
||||
settingsService: settings_service.Service
|
||||
communityTokensService: community_tokens_service.Service
|
||||
displayAssetsBelowBalanceThreshold: CurrencyAmount
|
||||
|
||||
proc newController*(
|
||||
|
@ -23,7 +25,8 @@ proc newController*(
|
|||
events: EventEmitter,
|
||||
tokenService: token_service.Service,
|
||||
walletAccountService: wallet_account_service.Service,
|
||||
settingsService: settings_service.Service
|
||||
settingsService: settings_service.Service,
|
||||
communityTokensService: community_tokens_service.Service
|
||||
): Controller =
|
||||
result = Controller()
|
||||
result.events = events
|
||||
|
@ -31,6 +34,7 @@ proc newController*(
|
|||
result.tokenService = tokenService
|
||||
result.walletAccountService = walletAccountService
|
||||
result.settingsService = settingsService
|
||||
result.communityTokensService = communityTokensService
|
||||
|
||||
proc delete*(self: Controller) =
|
||||
discard
|
||||
|
@ -85,6 +89,12 @@ proc getTokensDetailsLoading*(self: Controller): bool =
|
|||
proc getTokensMarketValuesLoading*(self: Controller): bool =
|
||||
self.tokenService.getTokensMarketValuesLoading()
|
||||
|
||||
proc getCommunityTokenDescription*(self: Controller, addressPerChain: seq[AddressPerChain]): string =
|
||||
self.communityTokensService.getCommunityTokenDescription(addressPerChain)
|
||||
|
||||
proc getCommunityTokenDescription*(self: Controller, chainId: int, address: string): string =
|
||||
self.communityTokensService.getCommunityTokenDescription(chainId, address)
|
||||
|
||||
proc updateTokenPreferences*(self: Controller, tokenPreferencesJson: string) =
|
||||
self.tokenService.updateTokenPreferences(tokenPreferencesJson)
|
||||
|
||||
|
|
|
@ -114,9 +114,11 @@ QtObject:
|
|||
of ModelRole.CommunityId:
|
||||
result = newQVariant(item.communityId)
|
||||
of ModelRole.Description:
|
||||
let tokenDetails = self.delegate.getTokenDetails(item.symbol)
|
||||
result = if not tokenDetails.isNil: newQVariant(tokenDetails.description)
|
||||
else: newQVariant("")
|
||||
result = if not item.communityId.isEmptyOrWhitespace:
|
||||
newQVariant(self.delegate.getCommunityTokenDescription(item.chainId, item.address))
|
||||
else:
|
||||
if self.delegate.getTokensDetailsLoading(): newQVariant("")
|
||||
else: newQVariant(self.delegate.getTokenDetails(item.symbol).description)
|
||||
of ModelRole.WebsiteUrl:
|
||||
let tokenDetails = self.delegate.getTokenDetails(item.symbol)
|
||||
result = if not tokenDetails.isNil: newQVariant(tokenDetails.assetWebsiteUrl)
|
||||
|
|
|
@ -10,6 +10,7 @@ type
|
|||
FlatTokenModelDataSource* = tuple[
|
||||
getFlatTokensList: proc(): var seq[TokenItem],
|
||||
getTokenDetails: proc(symbol: string): TokenDetailsItem,
|
||||
getCommunityTokenDescription: proc(chainId: int, address: string): string,
|
||||
getTokensDetailsLoading: proc(): bool,
|
||||
getTokensMarketValuesLoading: proc(): bool,
|
||||
]
|
||||
|
@ -17,6 +18,7 @@ type
|
|||
TokenBySymbolModelDataSource* = tuple[
|
||||
getTokenBySymbolList: proc(): var seq[TokenBySymbolItem],
|
||||
getTokenDetails: proc(symbol: string): TokenDetailsItem,
|
||||
getCommunityTokenDescription: proc(addressPerChain: seq[AddressPerChain]): string,
|
||||
getTokensDetailsLoading: proc(): bool,
|
||||
getTokensMarketValuesLoading: proc(): bool,
|
||||
]
|
||||
|
|
|
@ -11,6 +11,7 @@ import app_service/service/wallet_account/service as wallet_account_service
|
|||
import app_service/service/token/dto
|
||||
import app_service/service/currency/service
|
||||
import app_service/service/settings/service as settings_service
|
||||
import app_service/service/community_tokens/service as community_tokens_service
|
||||
|
||||
export io_interface
|
||||
|
||||
|
@ -28,13 +29,14 @@ proc newModule*(
|
|||
events: EventEmitter,
|
||||
tokenService: token_service.Service,
|
||||
walletAccountService: wallet_account_service.Service,
|
||||
settingsService: settings_service.Service
|
||||
settingsService: settings_service.Service,
|
||||
communityTokensService: community_tokens_service.Service
|
||||
): Module =
|
||||
result = Module()
|
||||
result.delegate = delegate
|
||||
result.events = events
|
||||
result.view = newView(result)
|
||||
result.controller = controller.newController(result, events, tokenService, walletAccountService, settingsService)
|
||||
result.controller = controller.newController(result, events, tokenService, walletAccountService, settingsService, communityTokensService)
|
||||
result.moduleLoaded = false
|
||||
result.addresses = @[]
|
||||
|
||||
|
@ -67,6 +69,8 @@ method load*(self: Module) =
|
|||
self.events.on(SIGNAL_TOKEN_PREFERENCES_UPDATED) do(e: Args):
|
||||
let args = ResultArgs(e)
|
||||
self.view.tokenPreferencesUpdated(args.success)
|
||||
self.events.on(SIGNAL_COMMUNITY_TOKENS_DETAILS_LOADED) do(e: Args):
|
||||
self.view.tokensDetailsUpdated()
|
||||
|
||||
self.events.on(SIGNAL_CURRENCY_FORMATS_UPDATED) do(e:Args):
|
||||
self.view.currencyFormatsUpdated()
|
||||
|
@ -109,6 +113,7 @@ method getFlatTokenModelDataSource*(self: Module): FlatTokenModelDataSource =
|
|||
return (
|
||||
getFlatTokensList: proc(): var seq[TokenItem] = self.controller.getFlatTokensList(),
|
||||
getTokenDetails: proc(symbol: string): TokenDetailsItem = self.controller.getTokenDetails(symbol),
|
||||
getCommunityTokenDescription: proc(chainId: int, address: string): string = self.controller.getCommunityTokenDescription(chainId, address),
|
||||
getTokensDetailsLoading: proc(): bool = self.controller.getTokensDetailsLoading(),
|
||||
getTokensMarketValuesLoading: proc(): bool = self.controller.getTokensMarketValuesLoading()
|
||||
)
|
||||
|
@ -117,6 +122,7 @@ method getTokenBySymbolModelDataSource*(self: Module): TokenBySymbolModelDataSou
|
|||
return (
|
||||
getTokenBySymbolList: proc(): var seq[TokenBySymbolItem] = self.controller.getTokenBySymbolList(),
|
||||
getTokenDetails: proc(symbol: string): TokenDetailsItem = self.controller.getTokenDetails(symbol),
|
||||
getCommunityTokenDescription: proc(addressPerChain: seq[AddressPerChain]): string = self.controller.getCommunityTokenDescription(addressPerChain),
|
||||
getTokensDetailsLoading: proc(): bool = self.controller.getTokensDetailsLoading(),
|
||||
getTokensMarketValuesLoading: proc(): bool = self.controller.getTokensMarketValuesLoading()
|
||||
)
|
||||
|
|
|
@ -116,7 +116,10 @@ QtObject:
|
|||
of ModelRole.CommunityId:
|
||||
result = newQVariant(item.communityId)
|
||||
of ModelRole.Description:
|
||||
result = if not item.communityId.isEmptyOrWhitespace or self.delegate.getTokensDetailsLoading() : newQVariant("")
|
||||
result = if not item.communityId.isEmptyOrWhitespace:
|
||||
newQVariant(self.delegate.getCommunityTokenDescription(item.addressPerChainId))
|
||||
else:
|
||||
if self.delegate.getTokensDetailsLoading() : newQVariant("")
|
||||
else: newQVariant(self.delegate.getTokenDetails(item.symbol).description)
|
||||
of ModelRole.WebsiteUrl:
|
||||
result = if not item.communityId.isEmptyOrWhitespace or self.delegate.getTokensDetailsLoading() : newQVariant("")
|
||||
|
|
|
@ -37,6 +37,7 @@ import app_service/service/accounts/service as accounts_service
|
|||
import app_service/service/node/service as node_service
|
||||
import app_service/service/network_connection/service as network_connection_service
|
||||
import app_service/service/devices/service as devices_service
|
||||
import app_service/service/community_tokens/service as community_tokens_service
|
||||
|
||||
import backend/collectibles as backend_collectibles
|
||||
import backend/activity as backend_activity
|
||||
|
@ -107,7 +108,8 @@ proc newModule*(
|
|||
keycardService: keycard_service.Service,
|
||||
nodeService: node_service.Service,
|
||||
networkConnectionService: network_connection_service.Service,
|
||||
devicesService: devices_service.Service
|
||||
devicesService: devices_service.Service,
|
||||
communityTokensService: community_tokens_service.Service
|
||||
): Module =
|
||||
result = Module()
|
||||
result.delegate = delegate
|
||||
|
@ -121,7 +123,7 @@ proc newModule*(
|
|||
result.controller = newController(result, settingsService, walletAccountService, currencyService, networkService)
|
||||
|
||||
result.accountsModule = accounts_module.newModule(result, events, walletAccountService, networkService, currencyService)
|
||||
result.allTokensModule = all_tokens_module.newModule(result, events, tokenService, walletAccountService, settingsService)
|
||||
result.allTokensModule = all_tokens_module.newModule(result, events, tokenService, walletAccountService, settingsService, communityTokensService)
|
||||
let allCollectiblesModule = all_collectibles_module.newModule(result, events, collectibleService, networkService, walletAccountService, settingsService)
|
||||
result.allCollectiblesModule = allCollectiblesModule
|
||||
result.assetsModule = assets_module.newModule(result, events, walletAccountService, networkService, tokenService,
|
||||
|
|
|
@ -843,6 +843,20 @@ QtObject:
|
|||
if token.chainId == chainId and token.address == address:
|
||||
return token
|
||||
|
||||
proc getCommunityTokenDescription*(self: Service, chainId: int, address: string): string =
|
||||
let communityTokens = self.getAllCommunityTokens()
|
||||
for token in communityTokens:
|
||||
if token.chainId == chainId and cmpIgnoreCase(token.address, address) == 0:
|
||||
return token.description
|
||||
return ""
|
||||
|
||||
proc getCommunityTokenDescription*(self: Service, addressPerChain: seq[AddressPerChain]): string =
|
||||
for apC in addressPerChain:
|
||||
let description = self.getCommunityTokenDescription(apC.chainId, apC.address)
|
||||
if not description.isEmptyOrWhitespace:
|
||||
return description
|
||||
return ""
|
||||
|
||||
proc getCommunityTokenBurnState*(self: Service, chainId: int, contractAddress: string): ContractTransactionStatus =
|
||||
let burnTransactions = self.transactionService.getPendingTransactionsForType(PendingTransactionTypeDto.BurnCommunityToken)
|
||||
for transaction in burnTransactions:
|
||||
|
|
|
@ -131,6 +131,13 @@ SplitView {
|
|||
onManageTokensRequested: logs.logEvent("onManageTokensRequested")
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Button {
|
||||
text: "go back"
|
||||
onClicked: stack.currentIndex = 0
|
||||
}
|
||||
AssetsDetailView {
|
||||
id: detailsView
|
||||
Layout.fillHeight: true
|
||||
|
@ -138,17 +145,12 @@ SplitView {
|
|||
currencyStore: d.currencyStore
|
||||
allNetworksModel: NetworksModel.allNetworks
|
||||
networkFilters: d.networksChainsCurrentlySelected
|
||||
Button {
|
||||
anchors.top: parent.top
|
||||
text: "go back"
|
||||
onClicked: stack.currentIndex = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
SplitView.minimumWidth: 300
|
||||
SplitView.preferredWidth: 300
|
||||
SplitView.preferredWidth: 250
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 12
|
||||
|
|
|
@ -107,7 +107,7 @@ ListModel {
|
|||
decimals: 0,
|
||||
type: 1,
|
||||
communityId: "ddls",
|
||||
description: "",
|
||||
description: "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout." ,
|
||||
websiteUrl: "",
|
||||
marketDetails: {
|
||||
marketCap: ({amount: 0, symbol: "USD", displayDecimals: 2, stripTrailingZeroes: false}),
|
||||
|
@ -159,7 +159,7 @@ ListModel {
|
|||
decimals: 0,
|
||||
type: 1,
|
||||
communityId: "ddls",
|
||||
description: "",
|
||||
description: "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. ",
|
||||
websiteUrl: "",
|
||||
marketDetails: {
|
||||
marketCap: ({amount: 0, symbol: "USD", displayDecimals: 2, stripTrailingZeroes: false}),
|
||||
|
|
|
@ -122,7 +122,7 @@ Page {
|
|||
property bool isTimeRange: false
|
||||
|
||||
leftPadding: 0
|
||||
width: implicitWidth
|
||||
width: visible ? implicitWidth: 0
|
||||
onClicked: {
|
||||
root.headerTabClicked(privateIdentifier, isTimeRange);
|
||||
}
|
||||
|
@ -144,6 +144,7 @@ Page {
|
|||
for (var j = 0; j < graphsModel.length; j++) {
|
||||
var graphTab = tabButton.createObject(root, { text: graphsModel[j].text,
|
||||
enabled: graphsModel[j].enabled,
|
||||
visible: graphsModel[j].visible,
|
||||
isTimeRange: false,
|
||||
privateIdentifier: typeof graphsModel[j].id !== "undefined" ? graphsModel[j].id : null});
|
||||
graphsTabBar.addItem(graphTab);
|
||||
|
|
|
@ -284,6 +284,10 @@ QtObject {
|
|||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
function stripHttpsAndwwwFromUrl(text) {
|
||||
return text.replace(/http(s)?(:)?(\/\/)?|(\/\/)?(www\.)?(\/)/gim, '')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ StatusScrollView {
|
|||
regexValidator.regularExpression: Constants.regularExpressions.ascii
|
||||
regexValidator.errorMessage: qsTr("Only A-Z, 0-9 and standard punctuation allowed")
|
||||
|
||||
onTextChanged: root.token.description
|
||||
onTextChanged: root.token.description = text
|
||||
}
|
||||
|
||||
CustomStatusInput {
|
||||
|
|
|
@ -13,7 +13,7 @@ InformationTag {
|
|||
tagPrimaryLabel.color: Theme.palette.directColor1
|
||||
tagSecondaryLabel.color: Theme.palette.directColor1
|
||||
middleLabel.color: Theme.palette.baseColor1
|
||||
iconAsset.color: Theme.palette.primaryColor1
|
||||
asset.color: Theme.palette.primaryColor1
|
||||
secondarylabelMaxWidth: 1000
|
||||
height: 32
|
||||
customBackground: Component {
|
||||
|
|
|
@ -88,7 +88,8 @@ ColumnLayout {
|
|||
InformationTag {
|
||||
id: networkTag
|
||||
readonly property bool isNetworkValid: networkShortName !== ""
|
||||
image.source: isNetworkValid && networkIconURL !== "" ? Style.svg("tiny/" + networkIconURL) : ""
|
||||
asset.name: isNetworkValid && networkIconURL !== "" ? Style.svg("tiny/" + networkIconURL) : ""
|
||||
asset.isImage: true
|
||||
tagPrimaryLabel.text: isNetworkValid ? networkShortName : "---"
|
||||
tagPrimaryLabel.color: isNetworkValid ? networkColor : "black"
|
||||
visible: isNetworkValid
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtQuick.Controls 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import utils 1.0
|
||||
|
||||
Control {
|
||||
id: root
|
||||
|
||||
property alias primaryText: primaryText.text
|
||||
property alias primaryLabel: primaryText
|
||||
property alias content: content.sourceComponent
|
||||
|
||||
padding: 12
|
||||
|
||||
background: Rectangle {
|
||||
radius: Style.current.radius
|
||||
border.width: 1
|
||||
border.color: Theme.palette.baseColor2
|
||||
color: Style.current.transparent
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 4
|
||||
StatusBaseText {
|
||||
id: primaryText
|
||||
Layout.fillWidth: true
|
||||
font.pixelSize: 13
|
||||
lineHeight: 18
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: Theme.palette.directColor5
|
||||
visible: text
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
Loader {
|
||||
id: content
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,3 +10,4 @@ ManageTokenMenuButton 1.0 ManageTokenMenuButton.qml
|
|||
ManageTokensCommunityTag 1.0 ManageTokensCommunityTag.qml
|
||||
ManageTokensDelegate 1.0 ManageTokensDelegate.qml
|
||||
ManageTokensGroupDelegate 1.0 ManageTokensGroupDelegate.qml
|
||||
InformationTileAssetDetails 1.0 InformationTileAssetDetails.qml
|
||||
|
|
|
@ -62,7 +62,7 @@ Column {
|
|||
return qsTr("to")
|
||||
}
|
||||
}
|
||||
iconAsset.icon: "history"
|
||||
asset.name: "history"
|
||||
visible: activityFilterMenu.selectedTime !== Constants.TransactionTimePeriod.All
|
||||
onClosed: activityFilterStore.setSelectedTimestamp(Constants.TransactionTimePeriod.All)
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ Column {
|
|||
console.warn("Unhandled type :: ",activityFilterStore.typeFilters[index])
|
||||
return ""
|
||||
}
|
||||
iconAsset.icon: switch(activityFilterStore.typeFilters[index]) {
|
||||
asset.name: switch(activityFilterStore.typeFilters[index]) {
|
||||
case Constants.TransactionType.Send:
|
||||
return "send"
|
||||
case Constants.TransactionType.Receive:
|
||||
|
@ -126,7 +126,7 @@ Column {
|
|||
console.warn("Unhandled status :: ",activityFilterStore.statusFilters[index])
|
||||
return ""
|
||||
}
|
||||
iconAsset.icon: switch(activityFilterStore.statusFilters[index]) {
|
||||
asset.name: switch(activityFilterStore.statusFilters[index]) {
|
||||
case Constants.TransactionStatus.Failed:
|
||||
return Style.svg("transaction/failed")
|
||||
case Constants.TransactionStatus.Pending:
|
||||
|
@ -139,7 +139,7 @@ Column {
|
|||
console.warn("Unhandled status :: ",activityFilterStore.statusFilters[index])
|
||||
return ""
|
||||
}
|
||||
iconAsset.color: "transparent"
|
||||
asset.color: "transparent"
|
||||
onClosed: activityFilterStore.toggleStatus(status, activityFilterMenu.allStatusChecked)
|
||||
}
|
||||
}
|
||||
|
@ -148,8 +148,8 @@ Column {
|
|||
model: activityFilterStore.tokensFilter
|
||||
delegate: ActivityFilterTagItem {
|
||||
tagPrimaryLabel.text: modelData
|
||||
iconAsset.icon: Constants.tokenIcon(modelData)
|
||||
iconAsset.color: "transparent"
|
||||
asset.name: Constants.tokenIcon(modelData)
|
||||
asset.color: "transparent"
|
||||
onClosed: activityFilterStore.toggleToken(modelData)
|
||||
}
|
||||
}
|
||||
|
@ -170,8 +170,8 @@ Column {
|
|||
return "#" + data[2]
|
||||
return ""
|
||||
}
|
||||
iconAsset.icon: activityFilterStore.collectiblesList.getImageUrl(uid)
|
||||
iconAsset.color: "transparent"
|
||||
asset.name: activityFilterStore.collectiblesList.getImageUrl(uid)
|
||||
asset.color: "transparent"
|
||||
onClosed: activityFilterStore.toggleCollectibles(uid)
|
||||
|
||||
Connections {
|
||||
|
|
|
@ -244,7 +244,8 @@ StatusModal {
|
|||
delegate: InformationTag {
|
||||
tagPrimaryLabel.text: model.shortName
|
||||
tagPrimaryLabel.color: model.chainColor
|
||||
image.source: Style.svg("tiny/" + model.iconUrl)
|
||||
asset.name: Style.svg("tiny/" + model.iconUrl)
|
||||
asset.isImage: true
|
||||
visible: d.preferredChainIdsArray.includes(model.chainId.toString())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ import shared.stores 1.0
|
|||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import "../controls"
|
||||
|
||||
/// \beware: heavy shortcuts here, refactor to match the requirements when touching this again
|
||||
/// \todo split into token history and balance views; they have different requirements that introduce unnecessary complexity
|
||||
/// \todo take a declarative approach, move logic into the typed backend and remove multiple source of truth (e.g. time ranges)
|
||||
|
@ -38,6 +40,7 @@ Item {
|
|||
readonly property string symbol: !!root.token? root.token.symbol?? "" : ""
|
||||
property bool marketDetailsLoading: !!root.token? root.token.marketDetailsLoading?? false : false
|
||||
property bool tokenDetailsLoading: !!root.token? root.token.detailsLoading?? false: false
|
||||
property bool isCommunityAsset: !!root.token && token.isCommunityAsset !== undefined ? token.isCommunityAsset : false
|
||||
|
||||
readonly property LeftJoinModel addressPerChainModel: LeftJoinModel {
|
||||
leftModel: token && token.addressPerChain ? token.addressPerChain: null
|
||||
|
@ -66,23 +69,38 @@ Item {
|
|||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
width: parent.width
|
||||
asset.name: token && token.symbol ? Style.png("tokens/%1".arg(token.symbol)) : ""
|
||||
asset.name: {
|
||||
if (!token)
|
||||
return ""
|
||||
if (token.image)
|
||||
return token.image
|
||||
if (token.symbol)
|
||||
return Style.png("tokens/%1".arg(token.symbol))
|
||||
return ""
|
||||
}
|
||||
asset.isImage: true
|
||||
primaryText: token && token.name ? token.name : Constants.dummyText
|
||||
secondaryText: token ? LocaleUtils.currencyAmountToLocaleString(root.currencyStore.getCurrencyAmount(token.currentBalance, token.symbol)) : Constants.dummyText
|
||||
tertiaryText: {
|
||||
if (!d.isCommunityAsset) {
|
||||
let totalCurrencyBalance = token && token.currentCurrencyBalance && token.symbol ? token.currentCurrencyBalance : 0
|
||||
return currencyStore.formatCurrencyAmount(totalCurrencyBalance, token.symbol)
|
||||
return currencyStore.formatCurrencyAmount(totalCurrencyBalance, currencyStore.currentCurrency)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
decimals: token && token.decimals ? token.decimals : 4
|
||||
balances: token && token.balances ? token.balances: null
|
||||
allNetworksModel: root.allNetworksModel
|
||||
isLoading: d.marketDetailsLoading
|
||||
address: root.address
|
||||
errorTooltipText: token && token.balances ? networkConnectionStore.getBlockchainNetworkDownTextForToken(token.balances): ""
|
||||
formatBalance: function(balance){
|
||||
return LocaleUtils.currencyAmountToLocaleString(currencyStore.getCurrencyAmount(balance, token.symbol))
|
||||
}
|
||||
communityTag.visible: d.isCommunityAsset
|
||||
communityTag.tagPrimaryLabel.text: d.isCommunityAsset ? token.communityName: ""
|
||||
communityTag.asset.name: d.isCommunityAsset ? token && !!token.communityImage ? token.communityImage : "" : ""
|
||||
communityTag.asset.isImage: true
|
||||
}
|
||||
|
||||
enum GraphType {
|
||||
|
@ -90,12 +108,24 @@ Item {
|
|||
Balance
|
||||
}
|
||||
|
||||
StatusScrollView {
|
||||
id: scrollView
|
||||
anchors.top: tokenDetailsHeader.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.topMargin: 47
|
||||
|
||||
width: parent.width
|
||||
contentWidth: availableWidth
|
||||
padding: 0
|
||||
|
||||
ColumnLayout {
|
||||
width: scrollView.availableWidth
|
||||
spacing: 40
|
||||
|
||||
Loader {
|
||||
id: graphDetailLoader
|
||||
width: parent.width
|
||||
height: 290
|
||||
anchors.top: tokenDetailsHeader.bottom
|
||||
anchors.topMargin: 24
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 290
|
||||
active: root.visible
|
||||
sourceComponent: StatusChartPanel {
|
||||
id: graphDetail
|
||||
|
@ -127,8 +157,8 @@ Item {
|
|||
}
|
||||
|
||||
graphsModel: [
|
||||
{text: qsTr("Price"), enabled: true, id: AssetsDetailView.GraphType.Price},
|
||||
{text: qsTr("Balance"), enabled: true, id: AssetsDetailView.GraphType.Balance},
|
||||
{text: qsTr("Price"), enabled: true, id: AssetsDetailView.GraphType.Price, visible: !d.isCommunityAsset},
|
||||
{text: qsTr("Balance"), enabled: true, id: AssetsDetailView.GraphType.Balance, visible: true},
|
||||
]
|
||||
defaultTimeRangeIndexShown: ChartStoreBase.TimeRange.All
|
||||
timeRangeModel: dataReady() && selectedStore.timeRangeTabsModel
|
||||
|
@ -293,7 +323,7 @@ Item {
|
|||
Connections {
|
||||
target: balanceStore
|
||||
function onNewDataReady(address, tokenSymbol, currencySymbol, timeRange) {
|
||||
if (timeRange === timeRangeStrToEnum(graphDetail.selectedTimeRange)) {
|
||||
if (timeRange === balanceStore.timeRangeStrToEnum(graphDetail.selectedTimeRange)) {
|
||||
chart.updateToNewData()
|
||||
}
|
||||
}
|
||||
|
@ -311,19 +341,9 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.top: graphDetailLoader.bottom
|
||||
anchors.topMargin: 24
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
width: parent.width
|
||||
|
||||
spacing: Style.current.padding
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
visible: !d.isCommunityAsset
|
||||
InformationTile {
|
||||
maxWidth: parent.width
|
||||
primaryText: qsTr("Market Cap")
|
||||
|
@ -377,58 +397,52 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
StatusTabBar {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.current.xlPadding
|
||||
Flow {
|
||||
id: detailsFlow
|
||||
|
||||
readonly property bool isOverflowing: detailsFlow.width - websiteBlock.width - tokenDescriptionText.width < 24
|
||||
|
||||
Layout.fillWidth: true
|
||||
spacing: 24
|
||||
|
||||
StatusTabBar {
|
||||
width: parent.width
|
||||
StatusTabButton {
|
||||
leftPadding: 0
|
||||
width: implicitWidth
|
||||
text: qsTr("Overview")
|
||||
}
|
||||
visible: tokenDescriptionText.visible
|
||||
}
|
||||
|
||||
StackLayout {
|
||||
id: stack
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
StatusScrollView {
|
||||
id: scrollView
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: parent.height
|
||||
topPadding: 8
|
||||
bottomPadding: 8
|
||||
contentWidth: availableWidth
|
||||
Flow {
|
||||
id: detailsFlow
|
||||
|
||||
readonly property bool isOverflowing: detailsFlow.width - tagsLayout.width - tokenDescriptionText.width < 24
|
||||
|
||||
spacing: 24
|
||||
|
||||
width: scrollView.availableWidth
|
||||
StatusTextWithLoadingState {
|
||||
id: tokenDescriptionText
|
||||
width: Math.max(536 , scrollView.availableWidth - tagsLayout.width - 24)
|
||||
width: Math.max(536 , scrollView.availableWidth - websiteBlock.width - 24)
|
||||
|
||||
font.pixelSize: 15
|
||||
lineHeight: 22
|
||||
lineHeightMode: Text.FixedHeight
|
||||
text: token && token.description ? token.description : Constants.dummyText
|
||||
text: token && token.description ? token.description : d.tokenDetailsLoading ? Constants.dummyText: ""
|
||||
customColor: Theme.palette.directColor1
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.Wrap
|
||||
textFormat: Qt.RichText
|
||||
loading: d.tokenDetailsLoading
|
||||
visible: !!text
|
||||
}
|
||||
ColumnLayout {
|
||||
id: tagsLayout
|
||||
spacing: 10
|
||||
InformationTag {
|
||||
id: website
|
||||
Layout.alignment: detailsFlow.isOverflowing ? Qt.AlignLeft : Qt.AlignRight
|
||||
iconAsset.icon: "browser"
|
||||
tagPrimaryLabel.text: qsTr("Website")
|
||||
|
||||
GridLayout{
|
||||
columnSpacing: 10
|
||||
rowSpacing: 10
|
||||
flow: detailsFlow.isOverflowing ? GridLayout.LeftToRight: GridLayout.TopToBottom
|
||||
InformationTileAssetDetails {
|
||||
id: websiteBlock
|
||||
Layout.preferredWidth: 272
|
||||
visible: !d.isCommunityAsset
|
||||
primaryText: qsTr("Website")
|
||||
content: InformationTag {
|
||||
asset.name : "browser"
|
||||
tagPrimaryLabel.text: SQUtils.Utils.stripHttpsAndwwwFromUrl(token.websiteUrl)
|
||||
visible: typeof token != "undefined" && token && token.websiteUrl !== ""
|
||||
customBackground: Component {
|
||||
Rectangle {
|
||||
|
@ -444,21 +458,52 @@ Item {
|
|||
onClicked: Global.openLink(token.websiteUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO :: Issue with not being able to see correct balances after switching assets will be fixed under
|
||||
https://github.com/status-im/status-desktop/issues/12912 */
|
||||
InformationTileAssetDetails {
|
||||
Layout.preferredWidth: 272
|
||||
visible: d.isCommunityAsset
|
||||
primaryText: qsTr("Minted by")
|
||||
content: InformationTag {
|
||||
tagPrimaryLabel.text: token && token.communityName ? token.communityName : ""
|
||||
asset.name: token && token.communityImage ? token.communityImage : ""
|
||||
asset.isImage: true
|
||||
customBackground: Component {
|
||||
Rectangle {
|
||||
color: Theme.palette.baseColor2
|
||||
border.width: 1
|
||||
border.color: "transparent"
|
||||
radius: 36
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: Global.switchToCommunity(token.communityId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InformationTileAssetDetails {
|
||||
Layout.minimumWidth: 272
|
||||
Layout.preferredWidth: implicitWidth
|
||||
primaryText: qsTr("Contract")
|
||||
content: GridLayout {
|
||||
columnSpacing: 10
|
||||
rowSpacing: 10
|
||||
flow: detailsFlow.isOverflowing ? GridLayout.LeftToRight : GridLayout.TopToBottom
|
||||
Repeater {
|
||||
Layout.alignment: detailsFlow.isOverflowing ? Qt.AlignLeft : Qt.AlignRight
|
||||
model: SortFilterProxyModel {
|
||||
sourceModel: d.addressPerChainModel
|
||||
filters: ExpressionFilter {
|
||||
expression: root.networkFilters.split(":").includes(model.chainId+"")
|
||||
}
|
||||
}
|
||||
InformationTag {
|
||||
image.source: Style.svg("tiny/" + model.iconUrl)
|
||||
delegate: InformationTag {
|
||||
asset.name: Style.svg("tiny/" + model.iconUrl)
|
||||
asset.isImage: true
|
||||
tagPrimaryLabel.text: model.chainName
|
||||
tagSecondaryLabel.text: model.address
|
||||
tagSecondaryLabel.text: SQUtils.Utils.elideText(model.address, 2,4)
|
||||
customBackground: Component {
|
||||
Rectangle {
|
||||
color: Theme.palette.baseColor2
|
||||
|
@ -475,3 +520,4 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,10 +23,6 @@ RightTabBaseView {
|
|||
|
||||
signal launchShareAddressModal()
|
||||
|
||||
headerButton.onClicked: {
|
||||
root.launchShareAddressModal()
|
||||
}
|
||||
|
||||
function resetView() {
|
||||
stack.currentIndex = 0
|
||||
root.currentTabIndex = 0
|
||||
|
@ -38,6 +34,11 @@ RightTabBaseView {
|
|||
stack.currentIndex = 0;
|
||||
}
|
||||
|
||||
headerButton.onClicked: {
|
||||
root.launchShareAddressModal()
|
||||
}
|
||||
header.visible: stack.currentIndex === 0
|
||||
|
||||
StackLayout {
|
||||
id: stack
|
||||
anchors.fill: parent
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import utils 1.0
|
||||
import shared.controls 1.0
|
||||
|
@ -19,84 +20,113 @@ Control {
|
|||
property alias primaryText: tokenName.text
|
||||
property alias secondaryText: cryptoBalance.text
|
||||
property alias tertiaryText: fiatBalance.text
|
||||
property alias communityTag: communityTag
|
||||
property var balances
|
||||
property int decimals
|
||||
property var allNetworksModel
|
||||
property bool isLoading: false
|
||||
property string errorTooltipText
|
||||
property string address
|
||||
property StatusAssetSettings asset: StatusAssetSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
width: 25
|
||||
height: 25
|
||||
}
|
||||
property var formatBalance: function(balance){}
|
||||
|
||||
topPadding: Style.current.padding
|
||||
|
||||
contentItem: Column {
|
||||
contentItem: ColumnLayout {
|
||||
id: mainLayout
|
||||
spacing: 4
|
||||
Row {
|
||||
readonly property bool isOverflowing: parent.width - tokenNameAndIcon.width - communityAndBalances.width < 24
|
||||
|
||||
RowLayout {
|
||||
id: tokenNameAndIcon
|
||||
Layout.fillWidth: true
|
||||
spacing: 8
|
||||
StatusSmartIdenticon {
|
||||
id: identiconLoader
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
asset: root.asset
|
||||
loading: root.isLoading
|
||||
}
|
||||
StatusTextWithLoadingState {
|
||||
id: tokenName
|
||||
width: Math.min(root.width - identiconLoader.width - cryptoBalance.width - fiatBalance.width - 24, implicitWidth)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.pixelSize: 22
|
||||
lineHeight: 30
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.maximumWidth: root.width-root.asset.width-8
|
||||
font.pixelSize: 28
|
||||
font.bold: true
|
||||
lineHeight: 38
|
||||
lineHeightMode: Text.FixedHeight
|
||||
elide: Text.ElideRight
|
||||
customColor: Theme.palette.directColor1
|
||||
loading: root.isLoading
|
||||
}
|
||||
StatusSmartIdenticon {
|
||||
Layout.preferredWidth: root.asset.width
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
asset: root.asset
|
||||
loading: root.isLoading
|
||||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
Layout.fillWidth: true
|
||||
rowSpacing: Style.current.halfPadding
|
||||
columnSpacing: Style.current.halfPadding
|
||||
flow: mainLayout.isOverflowing ? GridLayout.TopToBottom: GridLayout.LeftToRight
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.current.halfPadding
|
||||
StatusTextWithLoadingState {
|
||||
id: cryptoBalance
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.pixelSize: 22
|
||||
lineHeight: 30
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
font.pixelSize: 28
|
||||
font.bold: true
|
||||
lineHeight: 38
|
||||
lineHeightMode: Text.FixedHeight
|
||||
customColor: Theme.palette.baseColor1
|
||||
loading: root.isLoading
|
||||
}
|
||||
StatusBaseText {
|
||||
id: dotSeparator
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.verticalCenterOffset: -15
|
||||
font.pixelSize: 50
|
||||
color: Theme.palette.baseColor1
|
||||
text: "."
|
||||
}
|
||||
StatusTextWithLoadingState {
|
||||
id: fiatBalance
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.pixelSize: 22
|
||||
lineHeight: 30
|
||||
Layout.alignment: Qt.AlignBottom
|
||||
Layout.bottomMargin: 2
|
||||
font.pixelSize: 15
|
||||
lineHeight: 22
|
||||
lineHeightMode: Text.FixedHeight
|
||||
customColor: Theme.palette.baseColor1
|
||||
loading: root.isLoading
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Style.current.smallPadding
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: identiconLoader.width
|
||||
Item {
|
||||
id: filler
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: communityAndBalances
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.current.halfPadding
|
||||
InformationTag {
|
||||
id: communityTag
|
||||
}
|
||||
Repeater {
|
||||
id: chainRepeater
|
||||
Layout.alignment: Qt.AlignRight
|
||||
model: root.allNetworksModel
|
||||
delegate: InformationTag {
|
||||
readonly property double aggregatedbalance: balancesAggregator.value/(10 ** root.decimals)
|
||||
SortFilterProxyModel {
|
||||
id: filteredBalances
|
||||
sourceModel: root.balances
|
||||
filters: ValueFilter {
|
||||
filters: [
|
||||
ValueFilter {
|
||||
roleName: "chainId"
|
||||
value: model.chainId
|
||||
},
|
||||
ValueFilter {
|
||||
roleName: "account"
|
||||
value: root.address.toLowerCase()
|
||||
enabled: !!root.address
|
||||
}
|
||||
]
|
||||
}
|
||||
SumAggregator {
|
||||
id: balancesAggregator
|
||||
|
@ -105,11 +135,12 @@ Control {
|
|||
}
|
||||
tagPrimaryLabel.text: root.formatBalance(aggregatedbalance)
|
||||
tagPrimaryLabel.color: model.chainColor
|
||||
image.source: Style.svg("tiny/%1".arg(model.iconUrl))
|
||||
asset.name: Style.svg("tiny/%1".arg(model.iconUrl))
|
||||
asset.isImage: true
|
||||
loading: root.isLoading
|
||||
visible: balancesAggregator.value > 0
|
||||
rightComponent: StatusFlatRoundButton {
|
||||
width: 14
|
||||
width: visible ? 14 : 0
|
||||
height: visible ? 14 : 0
|
||||
icon.width: 14
|
||||
icon.height: 14
|
||||
|
@ -123,3 +154,4 @@ Control {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,11 +11,10 @@ import utils 1.0
|
|||
Control {
|
||||
id: root
|
||||
|
||||
property alias image: image
|
||||
property alias iconAsset: iconAsset
|
||||
property alias tagPrimaryLabel: tagPrimaryLabel
|
||||
property alias tagSecondaryLabel: tagSecondaryLabel
|
||||
property alias middleLabel: middleLabel
|
||||
property alias asset: smartIdenticon.asset
|
||||
property alias rightComponent: rightComponent.sourceComponent
|
||||
property bool loading: false
|
||||
property int secondarylabelMaxWidth: 100
|
||||
|
@ -45,18 +44,15 @@ Control {
|
|||
contentItem: RowLayout {
|
||||
spacing: root.spacing
|
||||
visible: !root.loading
|
||||
// FIXME this could be StatusIcon but it can't load images from an arbitrary URL
|
||||
Image {
|
||||
id: image
|
||||
StatusSmartIdenticon {
|
||||
id: smartIdenticon
|
||||
Layout.maximumWidth: visible ? 16 : 0
|
||||
Layout.maximumHeight: visible ? 16 : 0
|
||||
visible: !!source
|
||||
}
|
||||
StatusIcon {
|
||||
id: iconAsset
|
||||
Layout.maximumWidth: visible ? 16 : 0
|
||||
Layout.maximumHeight: visible ? 16 : 0
|
||||
visible: !!icon
|
||||
asset.width: visible ? 16 : 0
|
||||
asset.height: visible ? 16 : 0
|
||||
asset.bgHeight: visible ? 16 : 0
|
||||
asset.bgWidth: visible ? 16 : 0
|
||||
visible: !!asset.name
|
||||
}
|
||||
StatusBaseText {
|
||||
id: tagPrimaryLabel
|
||||
|
|
Loading…
Reference in New Issue