status-desktop/ui/app/AppLayouts/Wallet/WalletLayout.qml

421 lines
17 KiB
QML
Raw Normal View History

2020-06-17 19:18:31 +00:00
import QtQuick 2.13
import QtQuick.Controls 2.13
2020-06-17 19:18:31 +00:00
import QtQuick.Layouts 1.13
import StatusQ 0.1
import StatusQ.Layout 0.1
import StatusQ.Core.Utils 0.1 as StatusQUtils
import utils 1.0
import shared.controls 1.0
import shared.popups.keypairimport 1.0
import shared.stores 1.0 as SharedStores
import shared.stores.send 1.0
import AppLayouts.stores 1.0 as AppLayoutsStores
import AppLayouts.Communities.stores 1.0
import AppLayouts.Profile.stores 1.0 as ProfileStores
import "popups"
import "panels"
import "views"
import "stores"
import "controls"
import "popups/swap"
import "popups/buy"
Item {
id: root
2020-11-27 16:21:15 +00:00
property bool hideSignPhraseModal: false
property SharedStores.RootStore sharedRootStore
property AppLayoutsStores.RootStore store
property ProfileStores.ContactsStore contactsStore
property CommunitiesStore communitiesStore
required property TransactionStore transactionStore
property var emojiPopup: null
property SharedStores.NetworkConnectionStore networkConnectionStore
property bool appMainVisible
2020-11-27 16:21:15 +00:00
property bool swapEnabled
property bool dAppsEnabled
property bool dAppsVisible
property bool walletConnectEnabled: true
property bool browserConnectEnabled: true
property var dAppsModel
signal dappPairRequested()
signal dappDisconnectRequested(string dappUrl)
// TODO: remove tokenType parameter from signals below
signal sendTokenRequested(string senderAddress, string tokenId, int tokenType)
signal bridgeTokenRequested(string tokenId, int tokenType)
onAppMainVisibleChanged: {
resetView()
}
onVisibleChanged: {
resetView()
}
Connections {
target: walletSection
function onFilterChanged(address) {
RootStore.selectedAddress = address === "" ? "" : address
}
function onDisplayKeypairImportPopup() {
keypairImport.active = true
}
function onDestroyKeypairImportPopup() {
keypairImport.active = false
}
}
enum LeftPanelSelection {
AllAddresses,
Address,
SavedAddresses
}
enum RightPanelSelection {
Assets,
Collectibles,
Activity
2020-11-27 16:21:15 +00:00
}
function resetView() {
if (!visible || !appMainVisible) {
return
}
d.displayAllAddresses()
d.resetRightPanelStackView()
}
function openDesiredView(leftPanelSelection, rightPanelSelection, data) {
if (leftPanelSelection !== WalletLayout.LeftPanelSelection.AllAddresses &&
leftPanelSelection !== WalletLayout.LeftPanelSelection.SavedAddresses &&
leftPanelSelection !== WalletLayout.LeftPanelSelection.Address) {
console.warn("not supported left selection", leftPanelSelection)
return
}
if (leftPanelSelection === WalletLayout.LeftPanelSelection.SavedAddresses) {
d.displaySavedAddresses()
} else {
let address = data.address ?? ""
if (leftPanelSelection === WalletLayout.LeftPanelSelection.AllAddresses) {
d.displayAllAddresses()
} else if (leftPanelSelection === WalletLayout.LeftPanelSelection.Address) {
if (!!address) {
d.displayAddress(address)
} else {
d.displayAllAddresses()
}
}
if (rightPanelSelection !== WalletLayout.RightPanelSelection.Collectibles &&
rightPanelSelection !== WalletLayout.RightPanelSelection.Assets &&
rightPanelSelection !== WalletLayout.RightPanelSelection.Activity) {
console.warn("not supported right selection", rightPanelSelection)
return
}
rightPanelStackView.currentItem.resetView()
rightPanelStackView.currentItem.currentTabIndex = rightPanelSelection
let savedAddress = data.savedAddress?? ""
if (!!savedAddress) {
RootStore.currentActivityFiltersStore.resetAllFilters()
RootStore.currentActivityFiltersStore.toggleSavedAddress(savedAddress)
}
}
}
QtObject {
id: d
readonly property bool showSavedAddresses: RootStore.showSavedAddresses
onShowSavedAddressesChanged: {
if(showSavedAddresses) {
rightPanelStackView.replace(cmpSavedAddresses)
} else {
rightPanelStackView.replace(walletContainer)
}
RootStore.backButtonName = ""
}
property SwapInputParamsForm swapFormData: SwapInputParamsForm {
selectedAccountAddress: RootStore.selectedAddress
}
property BuyCryptoParamsForm buyFormData: BuyCryptoParamsForm {
selectedWalletAddress: RootStore.selectedAddress
}
function displayAllAddresses() {
RootStore.showSavedAddresses = false
RootStore.selectedAddress = ""
RootStore.setFilterAllAddresses()
}
function displayAddress(address) {
RootStore.showSavedAddresses = false
RootStore.selectedAddress = address
d.resetRightPanelStackView() // Avoids crashing on asset items being destroyed while in signal handler
RootStore.setFilterAddress(address)
}
function displaySavedAddresses() {
RootStore.showSavedAddresses = true
RootStore.selectedAddress = ""
}
function resetRightPanelStackView() {
if (rightPanelStackView.currentItem && !!rightPanelStackView.currentItem.resetView) {
rightPanelStackView.currentItem.resetView()
}
}
function getSelectedOrFirstNonWatchedAddress() {
return !!RootStore.selectedAddress ?
RootStore.selectedAddress :
StatusQUtils.ModelUtils.get(RootStore.nonWatchAccounts, 0, "address")
}
function launchBuyCryptoModal() {
const walletStore = RootStore
d.buyFormData.selectedWalletAddress = d.getSelectedOrFirstNonWatchedAddress()
d.buyFormData.selectedNetworkChainId = StatusQUtils.ModelUtils.getByKey(RootStore.filteredFlatModel, "layer", 1, "chainId")
if(!!walletStore.currentViewedHoldingTokensKey && walletStore.currentViewedHoldingType === Constants.TokenType.ERC20) {
d.buyFormData.selectedTokenKey = walletStore.currentViewedHoldingTokensKey
}
Global.openBuyCryptoModalRequested(d.buyFormData)
}
}
SignPhraseModal {
id: signPhrasePopup
onRemindLaterClicked: hideSignPhraseModal = true
onAcceptClicked: { RootStore.setHideSignPhraseModal(true); }
visible: !root.hideSignPhraseModal && !RootStore.hideSignPhraseModal
}
SeedPhraseBackupWarning {
id: seedPhraseWarning
width: parent.width
anchors.top: parent.top
}
Component {
id: cmpSavedAddresses
SavedAddressesView {
store: root.store
contactsStore: root.contactsStore
networkConnectionStore: root.networkConnectionStore
networkFilter.visible: false
headerButton.text: qsTr("Add new address")
headerButton.onClicked: {
Global.openAddEditSavedAddressesPopup({})
}
onSendToAddressRequested: {
Global.sendToRecipientRequested(address)
}
}
}
Component {
id: walletContainer
RightTabView {
sharedRootStore: root.sharedRootStore
store: root.store
contactsStore: root.contactsStore
communitiesStore: root.communitiesStore
networkConnectionStore: root.networkConnectionStore
swapEnabled: root.swapEnabled
dAppsEnabled: root.dAppsEnabled
dAppsVisible: root.dAppsVisible
walletConnectEnabled: root.walletConnectEnabled
browserConnectEnabled: root.browserConnectEnabled
dAppsModel: root.dAppsModel
headerButton.text: RootStore.overview.ens || StatusQUtils.Utils.elideAndFormatWalletAddress(RootStore.overview.mixedcaseAddress)
headerButton.visible: !RootStore.overview.isAllAccounts
onLaunchShareAddressModal: Global.openShowQRPopup({
switchingAccounsEnabled: true,
hasFloatingButtons: true
})
onLaunchSwapModal: {
d.swapFormData.selectedAccountAddress = d.getSelectedOrFirstNonWatchedAddress()
d.swapFormData.selectedNetworkChainId = StatusQUtils.ModelUtils.getByKey(RootStore.filteredFlatModel, "layer", 1, "chainId")
d.swapFormData.fromTokensKey = tokensKey
d.swapFormData.defaultToTokenKey = RootStore.areTestNetworksEnabled ? Constants.swap.testStatusTokenKey : Constants.swap.mainnetStatusTokenKey
Global.openSwapModalRequested(d.swapFormData)
}
onDappPairRequested: root.dappPairRequested()
onDappDisconnectRequested: (dappUrl) => root.dappDisconnectRequested(dappUrl)
onLaunchBuyCryptoModal: d.launchBuyCryptoModal()
onSendTokenRequested: root.sendTokenRequested(senderAddress, tokenId, tokenType)
}
}
StatusSectionLayout {
anchors.top: seedPhraseWarning.bottom
height: root.height - seedPhraseWarning.height
width: root.width
backButtonName: RootStore.backButtonName
notificationCount: activityCenterStore.unreadNotificationsCount
hasUnseenNotifications: activityCenterStore.hasUnseenNotifications
onNotificationButtonClicked: Global.openActivityCenterPopup()
onBackButtonClicked: {
rightPanelStackView.currentItem.resetStack();
}
leftPanel: LeftTabView {
id: leftTab
anchors.fill: parent
emojiPopup: root.emojiPopup
networkConnectionStore: root.networkConnectionStore
2023-04-27 13:22:27 +00:00
changeSelectedAccount: function(address) {
d.displayAddress(address)
2023-05-12 07:11:44 +00:00
}
selectAllAccounts: function() {
d.displayAllAddresses()
}
selectSavedAddresses: function() {
d.displaySavedAddresses()
}
}
centerPanel: StackView {
id: rightPanelStackView
anchors.fill: parent
anchors.leftMargin: 64
anchors.rightMargin: 64
initialItem: walletContainer
replaceEnter: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 400; easing.type: Easing.OutCubic }
}
replaceExit: Transition {
NumberAnimation { property: "opacity"; from: 1; to: 0; duration: 400; easing.type: Easing.OutCubic }
}
2020-05-27 20:50:39 +00:00
}
headerBackground: AccountHeaderGradient {
width: parent.width
overview: RootStore.overview
}
footer: WalletFooter {
id: footer
readonly property bool isHoldingSelected: {
if (!rightPanelStackView.currentItem || rightPanelStackView.currentItem.currentTabIndex !== WalletLayout.RightPanelSelection.Collectibles) {
return false
}
return !!walletStore.currentViewedCollectible && walletStore.currentViewedHoldingID !== ""
}
readonly property bool isCommunityCollectible: !!walletStore.currentViewedCollectible ? walletStore.currentViewedCollectible.communityId !== "" : false
readonly property bool isOwnerCommunityCollectible: isCommunityCollectible ? (walletStore.currentViewedCollectible.communityPrivilegesLevel === Constants.TokenPrivilegesLevel.Owner) : false
visible: anyActionAvailable
width: parent.width
height: visible ? 61: implicitHeight
walletStore: RootStore
transactionStore: root.transactionStore
swapEnabled: root.swapEnabled
networkConnectionStore: root.networkConnectionStore
isCommunityOwnershipTransfer: footer.isHoldingSelected && footer.isOwnerCommunityCollectible
communityName: {
if (selectedCommunityForCollectible.available)
return selectedCommunityForCollectible.item.name
if (isCommunityCollectible)
return Utils.compactAddress(walletStore.currentViewedCollectible.communityId, 4)
return ""
}
onLaunchShareAddressModal: Global.openShowQRPopup({
switchingAccounsEnabled: true,
hasFloatingButtons: true
})
onLaunchSendModal: (fromAddress) => {
if(isCommunityOwnershipTransfer) {
const tokenItem = walletStore.currentViewedCollectible
const ownership = StatusQUtils.ModelUtils.get(tokenItem.ownership, 0)
Global.openTransferOwnershipPopup(tokenItem.communityId,
footer.communityName,
tokenItem.communityImage,
{
key: tokenItem.tokenId,
privilegesLevel: tokenItem.communityPrivilegesLevel,
chainId: tokenItem.chainId,
name: tokenItem.name,
artworkSource: tokenItem.artworkSource,
accountAddress: fromAddress,
tokenAddress: tokenItem.contractAddress
})
return
}
// Common send modal popup:
root.sendTokenRequested(fromAddress,
walletStore.currentViewedHoldingTokensKey,
walletStore.currentViewedHoldingType)
}
onLaunchBridgeModal: {
root.bridgeTokenRequested(walletStore.currentViewedHoldingID,
walletStore.currentViewedHoldingType)
}
onLaunchSwapModal: {
d.swapFormData.fromTokensKey = ""
d.swapFormData.selectedAccountAddress = d.getSelectedOrFirstNonWatchedAddress()
d.swapFormData.selectedNetworkChainId = StatusQUtils.ModelUtils.getByKey(RootStore.filteredFlatModel, "layer", 1, "chainId")
if(!!walletStore.currentViewedHoldingTokensKey && walletStore.currentViewedHoldingType === Constants.TokenType.ERC20) {
d.swapFormData.fromTokensKey = walletStore.currentViewedHoldingTokensKey
}
d.swapFormData.defaultToTokenKey = RootStore.areTestNetworksEnabled ? Constants.swap.testStatusTokenKey : Constants.swap.mainnetStatusTokenKey
Global.openSwapModalRequested(d.swapFormData)
}
onLaunchBuyCryptoModal: d.launchBuyCryptoModal()
ModelEntry {
id: selectedCommunityForCollectible
sourceModel: !!footer.walletStore.currentViewedCollectible && footer.isCommunityCollectible ? root.communitiesStore.communitiesList : null
key: "id"
value: footer.walletStore.currentViewedCollectible.communityId
}
}
}
Loader {
id: keypairImport
active: false
asynchronous: true
sourceComponent: KeypairImportPopup {
store.keypairImportModule: RootStore.keypairImportModule
}
onLoaded: {
keypairImport.item.open()
}
}
}