feat(@desktop/wallet): implement jump to activity details screen from collectible details activity tab
Fixes #13721
This commit is contained in:
parent
f3bf194187
commit
96d9acf1f0
|
@ -3,7 +3,6 @@ import tables, stint, sets
|
|||
|
||||
import model
|
||||
import entry
|
||||
import entry_details
|
||||
import recipients_model
|
||||
import collectibles_model
|
||||
import collectibles_item
|
||||
|
@ -11,6 +10,8 @@ import events_handler
|
|||
import status
|
||||
import utils
|
||||
|
||||
import details_controller as details_controller
|
||||
|
||||
import web3/conversions
|
||||
|
||||
import app/core/eventemitter
|
||||
|
@ -48,7 +49,8 @@ QtObject:
|
|||
currencyService: currency_service.Service
|
||||
tokenService: token_service.Service
|
||||
savedAddressService: saved_address_service.Service
|
||||
activityDetails: ActivityDetails
|
||||
|
||||
detailsController: details_controller.Controller
|
||||
|
||||
eventsHandler: EventsHandler
|
||||
status: Status
|
||||
|
@ -114,30 +116,17 @@ QtObject:
|
|||
ae = entry.newTransactionActivityEntry(backendEntry, self.addresses, extraData, amountToCurrencyConvertor)
|
||||
result.add(ae)
|
||||
|
||||
proc fetchTxDetails*(self: Controller, entryIndex: int) {.slot.} =
|
||||
let amountToCurrencyConvertor = proc(amount: UInt256, symbol: string): CurrencyAmount =
|
||||
return currencyAmountToItem(self.currencyService.parseCurrencyValue(symbol, amount),
|
||||
self.currencyService.getCurrencyFormat(symbol))
|
||||
|
||||
self.activityDetails = nil
|
||||
let entry = self.model.getEntry(entryIndex)
|
||||
proc fetchTxDetails*(self: Controller, txID: string) {.slot.} =
|
||||
let index = self.model.getIndex(txID)
|
||||
if index == -1:
|
||||
error "entry index not found"
|
||||
return
|
||||
let entry = self.model.getEntry(index)
|
||||
if entry == nil:
|
||||
error "failed to find entry with index: ", entryIndex
|
||||
error "entry not found"
|
||||
return
|
||||
|
||||
try:
|
||||
self.activityDetails = newActivityDetails(entry.getMetadata(), amountToCurrencyConvertor)
|
||||
except Exception as e:
|
||||
error "error: ", e.msg
|
||||
return
|
||||
|
||||
proc getActivityDetails(self: Controller): QVariant {.slot.} =
|
||||
if self.activityDetails == nil:
|
||||
return newQVariant()
|
||||
return newQVariant(self.activityDetails)
|
||||
|
||||
QtProperty[QVariant] activityDetails:
|
||||
read = getActivityDetails
|
||||
self.detailsController.setActivityEntry(entry)
|
||||
|
||||
proc processResponse(self: Controller, response: JsonNode) =
|
||||
defer: self.status.setLoadingData(false)
|
||||
|
@ -307,6 +296,7 @@ QtObject:
|
|||
)
|
||||
|
||||
proc newController*(requestId: int32,
|
||||
detailsController: details_controller.Controller,
|
||||
currencyService: currency_service.Service,
|
||||
tokenService: token_service.Service,
|
||||
savedAddressService: saved_address_service.Service,
|
||||
|
@ -325,6 +315,7 @@ QtObject:
|
|||
result.status = newStatus()
|
||||
|
||||
result.currencyService = currencyService
|
||||
result.detailsController = detailsController
|
||||
|
||||
result.filterTokenCodes = initHashSet[string]()
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
import NimQml, logging, stint
|
||||
|
||||
import entry
|
||||
import entry_details
|
||||
|
||||
import app_service/service/currency/service as currency_service
|
||||
|
||||
import app/modules/shared/wallet_utils
|
||||
import app/modules/shared_models/currency_amount
|
||||
|
||||
QtObject:
|
||||
type
|
||||
Controller* = ref object of QObject
|
||||
activityEntry: ActivityEntry
|
||||
activityDetails: ActivityDetails
|
||||
currencyService: currency_service.Service
|
||||
|
||||
proc setup(self: Controller) =
|
||||
self.QObject.setup
|
||||
|
||||
proc delete*(self: Controller) =
|
||||
self.QObject.delete
|
||||
|
||||
proc newController*(currencyService: currency_service.Service): Controller =
|
||||
new(result, delete)
|
||||
|
||||
result.currencyService = currencyService
|
||||
|
||||
result.setup()
|
||||
|
||||
proc activityEntryChanged*(self: Controller) {.signal.}
|
||||
proc getActivityEntry(self: Controller): QVariant {.slot.} =
|
||||
if self.activityEntry == nil:
|
||||
return newQVariant()
|
||||
return newQVariant(self.activityEntry)
|
||||
|
||||
QtProperty[QVariant] activityEntry:
|
||||
read = getActivityEntry
|
||||
notify = activityEntryChanged
|
||||
|
||||
proc activityDetailsChanged*(self: Controller) {.signal.}
|
||||
proc getActivityDetails(self: Controller): QVariant {.slot.} =
|
||||
if self.activityDetails == nil:
|
||||
return newQVariant()
|
||||
return newQVariant(self.activityDetails)
|
||||
|
||||
QtProperty[QVariant] activityDetails:
|
||||
read = getActivityDetails
|
||||
notify = activityDetailsChanged
|
||||
|
||||
proc setActivityEntry*(self: Controller, entry: ActivityEntry) =
|
||||
self.activityEntry = entry
|
||||
self.activityEntryChanged()
|
||||
|
||||
if self.activityDetails != nil:
|
||||
self.activityDetails = nil
|
||||
self.activityDetailsChanged()
|
||||
|
||||
proc resetActivityEntry*(self: Controller) {.slot.} =
|
||||
self.setActivityEntry(nil)
|
||||
|
||||
proc fetchExtraTxDetails*(self: Controller) {.slot.} =
|
||||
let amountToCurrencyConvertor = proc(amount: UInt256, symbol: string): CurrencyAmount =
|
||||
return currencyAmountToItem(self.currencyService.parseCurrencyValue(symbol, amount),
|
||||
self.currencyService.getCurrencyFormat(symbol))
|
||||
if self.activityEntry == nil:
|
||||
error "activity entry is not set"
|
||||
return
|
||||
|
||||
try:
|
||||
self.activityDetails = newActivityDetails(self.activityEntry.getMetadata(), amountToCurrencyConvertor)
|
||||
self.activityDetailsChanged()
|
||||
except Exception as e:
|
||||
error "error: ", e.msg
|
||||
return
|
|
@ -15,6 +15,7 @@ import ./overview/module as overview_module
|
|||
import ./send/module as send_module
|
||||
|
||||
import ./activity/controller as activityc
|
||||
import ./activity/details_controller as activity_detailsc
|
||||
import ./wallet_connect/controller as wcc
|
||||
|
||||
import app/modules/shared_models/collectibles_model as collectiblesm
|
||||
|
@ -90,6 +91,7 @@ type
|
|||
# We need one for each app "layer" that simultaneously needs to show a different list of activity
|
||||
# entries (e.g. send popup is one "layer" above the collectible details activity tab)
|
||||
tmpActivityControllers: ActivityControllerArray
|
||||
activityDetailsController: activity_detailsc.Controller
|
||||
|
||||
wcController: wcc.Controller
|
||||
|
||||
|
@ -141,20 +143,36 @@ proc newModule*(
|
|||
result.networksService = networkService
|
||||
|
||||
result.transactionService = transactionService
|
||||
result.activityController = activityc.newController(int32(ActivityID.History), currencyService, tokenService,
|
||||
savedAddressService, events)
|
||||
result.activityDetailsController = activity_detailsc.newController(currencyService)
|
||||
result.activityController = activityc.newController(
|
||||
int32(ActivityID.History),
|
||||
result.activityDetailsController,
|
||||
currencyService,
|
||||
tokenService,
|
||||
savedAddressService,
|
||||
events)
|
||||
result.tmpActivityControllers = [
|
||||
activityc.newController(int32(ActivityID.Temporary0), currencyService, tokenService,
|
||||
savedAddressService, events),
|
||||
activityc.newController(int32(ActivityID.Temporary1), currencyService, tokenService,
|
||||
savedAddressService, events)
|
||||
activityc.newController(
|
||||
int32(ActivityID.Temporary0),
|
||||
result.activityDetailsController,
|
||||
currencyService,
|
||||
tokenService,
|
||||
savedAddressService,
|
||||
events),
|
||||
activityc.newController(
|
||||
int32(ActivityID.Temporary1),
|
||||
result.activityDetailsController,
|
||||
currencyService,
|
||||
tokenService,
|
||||
savedAddressService,
|
||||
events)
|
||||
]
|
||||
result.collectibleDetailsController = collectible_detailsc.newController(int32(backend_collectibles.CollectiblesRequestID.WalletAccount), networkService, events)
|
||||
result.filter = initFilter(result.controller)
|
||||
|
||||
result.wcController = wcc.newController(events, walletAccountService)
|
||||
|
||||
result.view = newView(result, result.activityController, result.tmpActivityControllers, result.collectibleDetailsController, result.wcController)
|
||||
result.view = newView(result, result.activityController, result.tmpActivityControllers, result.activityDetailsController, result.collectibleDetailsController, result.wcController)
|
||||
|
||||
method delete*(self: Module) =
|
||||
self.accountsModule.delete
|
||||
|
@ -169,6 +187,7 @@ method delete*(self: Module) =
|
|||
self.activityController.delete
|
||||
for i in 0..self.tmpActivityControllers.len-1:
|
||||
self.tmpActivityControllers[i].delete
|
||||
self.activityDetailsController.delete
|
||||
self.collectibleDetailsController.delete
|
||||
self.wcController.delete
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import NimQml, json
|
||||
|
||||
import ./activity/controller as activityc
|
||||
import ./activity/details_controller as activity_detailsc
|
||||
import app/modules/shared_modules/collectible_details/controller as collectible_detailsc
|
||||
import ./io_interface
|
||||
import ../../shared_models/currency_amount
|
||||
|
@ -20,6 +21,7 @@ QtObject:
|
|||
tmpSymbol: string # shouldn't be used anywhere except in prepare*/getPrepared* procs
|
||||
activityController: activityc.Controller
|
||||
tmpActivityControllers: ActivityControllerArray
|
||||
activityDetailsController: activity_detailsc.Controller
|
||||
collectibleDetailsController: collectible_detailsc.Controller
|
||||
isNonArchivalNode: bool
|
||||
keypairOperabilityForObservedAccount: string
|
||||
|
@ -34,11 +36,17 @@ QtObject:
|
|||
proc delete*(self: View) =
|
||||
self.QObject.delete
|
||||
|
||||
proc newView*(delegate: io_interface.AccessInterface, activityController: activityc.Controller, tmpActivityControllers: ActivityControllerArray, collectibleDetailsController: collectible_detailsc.Controller, wcController: wcc.Controller): View =
|
||||
proc newView*(delegate: io_interface.AccessInterface,
|
||||
activityController: activityc.Controller,
|
||||
tmpActivityControllers: ActivityControllerArray,
|
||||
activityDetailsController: activity_detailsc.Controller,
|
||||
collectibleDetailsController: collectible_detailsc.Controller,
|
||||
wcController: wcc.Controller): View =
|
||||
new(result, delete)
|
||||
result.delegate = delegate
|
||||
result.activityController = activityController
|
||||
result.tmpActivityControllers = tmpActivityControllers
|
||||
result.activityDetailsController = activityDetailsController
|
||||
result.collectibleDetailsController = collectibleDetailsController
|
||||
result.wcController = wcController
|
||||
|
||||
|
@ -164,6 +172,11 @@ QtObject:
|
|||
QtProperty[QVariant] tmpActivityController1:
|
||||
read = getTmpActivityController1
|
||||
|
||||
proc getActivityDetailsController(self: View): QVariant {.slot.} =
|
||||
return newQVariant(self.activityDetailsController)
|
||||
QtProperty[QVariant] activityDetailsController:
|
||||
read = getActivityDetailsController
|
||||
|
||||
proc getLatestBlockNumber*(self: View, chainId: int): string {.slot.} =
|
||||
return self.delegate.getLatestBlockNumber(chainId)
|
||||
|
||||
|
|
|
@ -137,21 +137,16 @@ SplitView {
|
|||
id: transactionData
|
||||
|
||||
property int chainId: 1
|
||||
property string blockNumber: "0x124"
|
||||
property int timestamp: Date.now() / 1000
|
||||
property int txStatus: 0
|
||||
property string type: "eth"
|
||||
property string nonce: "0x123"
|
||||
property string from: "0x29D7d1dd5B6f9C864d9db560D72a247c178aE86B"
|
||||
property string to: "0x4de3f6278C0DdFd3F29df9DcD979038F5c7bbc35"
|
||||
property string contract: "0x4de3f6278C0DdFd3F29df9DcD979038F5c7bbc35"
|
||||
property bool isNFT: false
|
||||
property string input: "0x40e8d703000000000000000000000000670dca62b3418bddd08cbc69cb4490a5a3382a9f0000000000000000000000000000000000000000000000000000000000000064ddd08cbc69cb4490a5a3382a9f0000000000"
|
||||
property string tokenID: "4981676894159712808201908443964193325271219637660871887967796332739046670337"
|
||||
property string nftName: "Happy Meow"
|
||||
property string nftImageUrl: Style.png("collectibles/HappyMeow")
|
||||
property string symbol: "ETH"
|
||||
property string txHash: "0x4de3f6278C0DdFd3F29df9DcD979038F5c7bbc35"
|
||||
|
||||
readonly property var value: QtObject {
|
||||
property real amount: amountSpinbox.realValue
|
||||
|
@ -159,6 +154,17 @@ SplitView {
|
|||
property int displayDecimals: 5
|
||||
property bool stripTrailingZeroes: true
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: transactionDetails
|
||||
|
||||
property string nonce: "0x123"
|
||||
property string blockNumber: "0x124"
|
||||
property string txHash: "0x4de3f6278C0DdFd3F29df9DcD979038F5c7bbc35"
|
||||
property string txHashOut: "0x4de3f6278C0DdFd3F29df9DcD979038F5c7bbc35"
|
||||
property string input: "0x40e8d703000000000000000000000000670dca62b3418bddd08cbc69cb4490a5a3382a9f0000000000000000000000000000000000000000000000000000000000000064ddd08cbc69cb4490a5a3382a9f0000000000"
|
||||
property string contract: "0x4de3f6278C0DdFd3F29df9DcD979038F5c7bbc35"
|
||||
|
||||
readonly property var totalFees: QtObject {
|
||||
property real amount: (transactionData.value / 15) * Math.pow(10, 9)
|
||||
|
@ -167,10 +173,6 @@ SplitView {
|
|||
property bool stripTrailingZeroes: true
|
||||
}
|
||||
|
||||
readonly property var gasPrice: QtObject {
|
||||
property real amount: 0.0000005
|
||||
property string symbol: "ETH"
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
|
@ -179,6 +181,25 @@ SplitView {
|
|||
property var mixedcaseAddress: root.isIncoming ? transactionData.to : transactionData.from
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: controllerMockup
|
||||
|
||||
property var activityEntry: transactionData
|
||||
property var activityDetails
|
||||
|
||||
function fetchExtraTxDetails() {
|
||||
extraDetailsTimer.start()
|
||||
}
|
||||
|
||||
readonly property Timer extraDetailsTimer: Timer {
|
||||
id: extraDetailsTimer
|
||||
interval: 1000
|
||||
onTriggered: {
|
||||
controllerMockup.activityDetails = transactionDetails
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SplitView {
|
||||
orientation: Qt.Vertical
|
||||
SplitView.fillWidth: true
|
||||
|
@ -203,7 +224,7 @@ SplitView {
|
|||
active: root.globalUtilsReady && root.mainModuleReady && root.rootStoreReady
|
||||
sourceComponent: TransactionDetailView {
|
||||
contactsStore: contactsStoreMockup
|
||||
transaction: transactionData
|
||||
controller: controllerMockup
|
||||
overview: overviewMockup
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ QtObject {
|
|||
property var activityController: walletSectionInst.activityController
|
||||
property var tmpActivityController0: walletSectionInst.tmpActivityController0
|
||||
property var tmpActivityController1: walletSectionInst.tmpActivityController1
|
||||
property var activityDetailsController: walletSectionInst.activityDetailsController
|
||||
property string signingPhrase: walletSectionInst.signingPhrase
|
||||
property string mnemonicBackedUp: walletSectionInst.isMnemonicBackedUp
|
||||
property var walletConnectController: walletSectionInst.walletConnectController
|
||||
|
|
|
@ -208,9 +208,8 @@ RightTabBaseView {
|
|||
showAllAccounts: RootStore.showAllAccounts
|
||||
sendModal: root.sendModal
|
||||
filterVisible: filterButton.checked
|
||||
onLaunchTransactionDetail: function (entryIndex) {
|
||||
transactionDetailView.transactionIndex = entryIndex
|
||||
transactionDetailView.transaction = Qt.binding(() => selectedTransaction)
|
||||
onLaunchTransactionDetail: function (txID) {
|
||||
RootStore.activityController.fetchTxDetails(txID)
|
||||
stack.currentIndex = 3
|
||||
}
|
||||
}
|
||||
|
@ -218,6 +217,10 @@ RightTabBaseView {
|
|||
}
|
||||
}
|
||||
CollectibleDetailView {
|
||||
id: collectibleDetailView
|
||||
|
||||
visible : (stack.currentIndex === 1)
|
||||
|
||||
collectible: RootStore.collectiblesStore.detailedCollectible
|
||||
isCollectibleLoading: RootStore.collectiblesStore.isDetailedCollectibleLoading
|
||||
activityModel: d.detailedCollectibleActivityController.model
|
||||
|
@ -230,6 +233,14 @@ RightTabBaseView {
|
|||
RootStore.resetCurrentViewedHolding(Constants.TokenType.ERC721)
|
||||
}
|
||||
}
|
||||
|
||||
onLaunchTransactionDetail: function (txID) {
|
||||
d.detailedCollectibleActivityController.fetchTxDetails(txID)
|
||||
stack.currentIndex = 3
|
||||
|
||||
// Take user to the activity view when they press the "Back" button
|
||||
walletTabBar.currentIndex = 2
|
||||
}
|
||||
}
|
||||
AssetsDetailView {
|
||||
id: assetDetailView
|
||||
|
@ -252,6 +263,7 @@ RightTabBaseView {
|
|||
|
||||
TransactionDetailView {
|
||||
id: transactionDetailView
|
||||
controller: RootStore.activityDetailsController
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
if (!!transaction) {
|
||||
|
@ -261,7 +273,7 @@ RightTabBaseView {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
transaction = null
|
||||
controller.resetActivityEntry()
|
||||
}
|
||||
}
|
||||
showAllAccounts: RootStore.showAllAccounts
|
||||
|
|
|
@ -29,33 +29,44 @@ Item {
|
|||
property var contactsStore
|
||||
property var communitiesStore
|
||||
property var networkConnectionStore
|
||||
property var transaction
|
||||
property int transactionIndex
|
||||
property var controller
|
||||
property var sendModal
|
||||
property bool showAllAccounts: false
|
||||
readonly property bool isTransactionValid: transaction !== undefined && !!transaction
|
||||
|
||||
onTransactionChanged: {
|
||||
d.reEvaluateSender = !d.reEvaluateSender
|
||||
d.reEvaluateRecipient = !d.reEvaluateRecipient
|
||||
d.reEvaluateSender = !d.reEvaluateSender
|
||||
d.reEvaluateRecipient = !d.reEvaluateRecipient
|
||||
|
||||
d.updateTransactionDetails()
|
||||
}
|
||||
readonly property alias transaction: d.transaction
|
||||
|
||||
Component.onCompleted: d.updateTransactionDetails()
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property var transaction: root.controller.activityEntry
|
||||
readonly property bool isTransactionValid: transaction !== undefined && !!transaction
|
||||
|
||||
onTransactionChanged: {
|
||||
d.reEvaluateSender = !d.reEvaluateSender
|
||||
d.reEvaluateRecipient = !d.reEvaluateRecipient
|
||||
d.reEvaluateSender = !d.reEvaluateSender
|
||||
d.reEvaluateRecipient = !d.reEvaluateRecipient
|
||||
|
||||
d.updateTransactionDetails()
|
||||
}
|
||||
|
||||
property bool reEvaluateSender: true
|
||||
property bool reEvaluateRecipient: true
|
||||
|
||||
property var details: null
|
||||
property var details: root.controller.activityDetails
|
||||
readonly property bool isDetailsValid: details !== undefined && !!details
|
||||
|
||||
onDetailsChanged: {
|
||||
if (!!d.details && !!d.details.input && d.details.input !== "0x") {
|
||||
d.loadingInputDate = true
|
||||
RootStore.fetchDecodedTxData(d.details.txHashOut, d.details.input)
|
||||
}
|
||||
}
|
||||
|
||||
readonly property bool isIncoming: transactionType === Constants.TransactionType.Received || transactionType === Constants.TransactionType.ContractDeployment
|
||||
readonly property string networkShortName: root.isTransactionValid ? RootStore.getNetworkShortName(transaction.chainId) : ""
|
||||
readonly property string networkShortName: d.isTransactionValid ? RootStore.getNetworkShortName(transaction.chainId) : ""
|
||||
readonly property string networkIcon: isTransactionValid ? RootStore.getNetworkIcon(transaction.chainId) : "network/Network=Custom"
|
||||
readonly property int blockNumber: isDetailsValid ? details.blockNumber : 0
|
||||
readonly property int blockNumberIn: isDetailsValid ? details.blockNumberIn : 0
|
||||
|
@ -67,30 +78,30 @@ Item {
|
|||
readonly property string outSymbol: isTransactionValid ? transaction.outSymbol : ""
|
||||
readonly property var multichainNetworks: [] // TODO fill icon for networks for multichain
|
||||
readonly property string fiatValueFormatted: {
|
||||
if (!root.isTransactionValid || transactionHeader.isMultiTransaction || !symbol)
|
||||
if (!d.isTransactionValid || transactionHeader.isMultiTransaction || !symbol)
|
||||
return ""
|
||||
return RootStore.formatCurrencyAmount(transactionHeader.fiatValue, RootStore.currentCurrency)
|
||||
}
|
||||
readonly property string cryptoValueFormatted: {
|
||||
if (!root.isTransactionValid || transactionHeader.isMultiTransaction)
|
||||
if (!d.isTransactionValid || transactionHeader.isMultiTransaction)
|
||||
return ""
|
||||
const formatted = RootStore.formatCurrencyAmount(transaction.amount, transaction.symbol)
|
||||
return symbol || (!d.isDetailsValid || !d.details.contract) ? formatted : "%1 (%2)".arg(formatted).arg(Utils.compactAddress(transaction.tokenAddress, 4))
|
||||
}
|
||||
readonly property string outFiatValueFormatted: {
|
||||
if (!root.isTransactionValid || !transactionHeader.isMultiTransaction || !outSymbol)
|
||||
if (!d.isTransactionValid || !transactionHeader.isMultiTransaction || !outSymbol)
|
||||
return ""
|
||||
return RootStore.formatCurrencyAmount(transactionHeader.outFiatValue, RootStore.currentCurrency)
|
||||
}
|
||||
readonly property string outCryptoValueFormatted: {
|
||||
if (!root.isTransactionValid || !transactionHeader.isMultiTransaction)
|
||||
if (!d.isTransactionValid || !transactionHeader.isMultiTransaction)
|
||||
return ""
|
||||
const formatted = RootStore.formatCurrencyAmount(transaction.outAmount, transaction.outSymbol)
|
||||
return outSymbol || !transaction.tokenOutAddress ? formatted : "%1 (%2)".arg(formatted).arg(Utils.compactAddress(transaction.tokenOutAddress, 4))
|
||||
}
|
||||
readonly property real feeEthValue: d.details ? RootStore.getFeeEthValue(d.details.totalFees) : 0
|
||||
readonly property real feeFiatValue: root.isTransactionValid ? RootStore.getFiatValue(d.feeEthValue, Constants.ethToken) : 0
|
||||
readonly property int transactionType: root.isTransactionValid ? transaction.txType : Constants.TransactionType.Send
|
||||
readonly property real feeFiatValue: d.isTransactionValid ? RootStore.getFiatValue(d.feeEthValue, Constants.ethToken) : 0
|
||||
readonly property int transactionType: d.isTransactionValid ? transaction.txType : Constants.TransactionType.Send
|
||||
readonly property bool isBridge: d.transactionType === Constants.TransactionType.Bridge
|
||||
|
||||
property string decodedInputData: ""
|
||||
|
@ -102,23 +113,17 @@ Item {
|
|||
|
||||
function updateTransactionDetails() {
|
||||
d.decodedInputData = ""
|
||||
if (!transaction)
|
||||
if (!d.transaction)
|
||||
return
|
||||
|
||||
RootStore.fetchTxDetails(transactionIndex)
|
||||
d.details = RootStore.getTxDetails()
|
||||
|
||||
if (!!d.details && !!d.details.input) {
|
||||
d.loadingInputDate = true
|
||||
RootStore.fetchDecodedTxData(d.details.txHashOut, d.details.input)
|
||||
}
|
||||
root.controller.fetchExtraTxDetails()
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: RootStore.walletSectionInst
|
||||
function onTxDecoded(txHash: string, dataDecoded: string) {
|
||||
if (!root.isTransactionValid || (d.isDetailsValid && txHash !== d.details.txHashOut))
|
||||
if (!d.isTransactionValid || (d.isDetailsValid && txHash !== d.details.txHashOut))
|
||||
return
|
||||
if (!dataDecoded) {
|
||||
d.loadingInputDate = false
|
||||
|
@ -165,7 +170,7 @@ Item {
|
|||
|
||||
showAllAccounts: root.showAllAccounts
|
||||
modelData: transaction
|
||||
timeStampText: root.isTransactionValid ? qsTr("Signed at %1").arg(LocaleUtils.formatDateTime(transaction.timestamp * 1000, Locale.LongFormat)): ""
|
||||
timeStampText: d.isTransactionValid ? qsTr("Signed at %1").arg(LocaleUtils.formatDateTime(transaction.timestamp * 1000, Locale.LongFormat)): ""
|
||||
rootStore: RootStore
|
||||
walletRootStore: WalletStores.RootStore
|
||||
community: isModelDataValid && communityId && communitiesStore ? communitiesStore.getCommunityDetailsAsJson(communityId) : null
|
||||
|
@ -179,18 +184,18 @@ Item {
|
|||
WalletTxProgressBlock {
|
||||
id: progressBlock
|
||||
width: Math.min(513, root.width)
|
||||
readonly property int latestBlockNumber: root.isTransactionValid && !pending && !error ? WalletStores.RootStore.getEstimatedLatestBlockNumber(root.transaction.chainId) : 0
|
||||
readonly property int latestBlockNumberIn: root.isTransactionValid && !pending && !error && transactionHeader.isMultiTransaction && d.isBridge ? WalletStores.RootStore.getEstimatedLatestBlockNumber(root.transaction.chainIdIn) : 0
|
||||
readonly property int latestBlockNumber: d.isTransactionValid && !pending && !error ? WalletStores.RootStore.getEstimatedLatestBlockNumber(d.transaction.chainId) : 0
|
||||
readonly property int latestBlockNumberIn: d.isTransactionValid && !pending && !error && transactionHeader.isMultiTransaction && d.isBridge ? WalletStores.RootStore.getEstimatedLatestBlockNumber(d.transaction.chainIdIn) : 0
|
||||
error: transactionHeader.transactionStatus === Constants.TransactionStatus.Failed
|
||||
pending: transactionHeader.transactionStatus === Constants.TransactionStatus.Pending
|
||||
outNetworkLayer: root.isTransactionValid ? Number(RootStore.getNetworkLayer(transactionHeader.isMultiTransaction ? root.transaction.chainIdOut : root.transaction.chainId)) : 0
|
||||
inNetworkLayer: root.isTransactionValid && transactionHeader.isMultiTransaction && d.isBridge ? Number(RootStore.getNetworkLayer(root.transaction.chainIdIn)) : 0
|
||||
outNetworkTimestamp: root.isTransactionValid ? root.transaction.timestamp : 0
|
||||
inNetworkTimestamp: root.isTransactionValid ? root.transaction.timestamp : 0
|
||||
outNetworkLayer: d.isTransactionValid ? Number(RootStore.getNetworkLayer(transactionHeader.isMultiTransaction ? d.transaction.chainIdOut : d.transaction.chainId)) : 0
|
||||
inNetworkLayer: d.isTransactionValid && transactionHeader.isMultiTransaction && d.isBridge ? Number(RootStore.getNetworkLayer(d.transaction.chainIdIn)) : 0
|
||||
outNetworkTimestamp: d.isTransactionValid ? d.transaction.timestamp : 0
|
||||
inNetworkTimestamp: d.isTransactionValid ? d.transaction.timestamp : 0
|
||||
outChainName: transactionHeader.isMultiTransaction ? transactionHeader.networkNameOut : transactionHeader.networkName
|
||||
inChainName: transactionHeader.isMultiTransaction && d.isBridge ? transactionHeader.networkNameIn : ""
|
||||
outNetworkConfirmations: root.isTransactionValid && latestBlockNumber > 0 ? latestBlockNumber - d.blockNumberOut : 0
|
||||
inNetworkConfirmations: root.isTransactionValid && latestBlockNumberIn > 0 ? latestBlockNumberIn - d.blockNumberIn : 0
|
||||
outNetworkConfirmations: d.isTransactionValid && latestBlockNumber > 0 ? latestBlockNumber - d.blockNumberOut : 0
|
||||
inNetworkConfirmations: d.isTransactionValid && latestBlockNumberIn > 0 ? latestBlockNumberIn - d.blockNumberIn : 0
|
||||
}
|
||||
|
||||
Separator {
|
||||
|
@ -198,13 +203,13 @@ Item {
|
|||
}
|
||||
|
||||
WalletNftPreview {
|
||||
visible: root.isTransactionValid && transactionHeader.isNFT && !!transaction.nftImageUrl
|
||||
visible: d.isTransactionValid && transactionHeader.isNFT && !!transaction.nftImageUrl
|
||||
width: Math.min(304, progressBlock.width)
|
||||
nftName: root.isTransactionValid ? transaction.nftName : ""
|
||||
nftUrl: root.isTransactionValid && !!transaction.nftImageUrl ? transaction.nftImageUrl : ""
|
||||
nftName: d.isTransactionValid ? transaction.nftName : ""
|
||||
nftUrl: d.isTransactionValid && !!transaction.nftImageUrl ? transaction.nftImageUrl : ""
|
||||
strikethrough: d.transactionType === Constants.TransactionType.Destroy
|
||||
tokenId: root.isTransactionValid ? transaction.tokenID : ""
|
||||
tokenAddress: root.isTransactionValid ? transaction.tokenAddress : ""
|
||||
tokenId: d.isTransactionValid ? transaction.tokenID : ""
|
||||
tokenAddress: d.isTransactionValid ? transaction.tokenAddress : ""
|
||||
areTestNetworksEnabled: WalletStores.RootStore.areTestNetworksEnabled
|
||||
isGoerliEnabled: WalletStores.RootStore.isGoerliEnabled
|
||||
}
|
||||
|
@ -237,7 +242,7 @@ Item {
|
|||
Layout.fillHeight: true
|
||||
title: qsTr("From")
|
||||
subTitle: {
|
||||
if (!root.isTransactionValid)
|
||||
if (!d.isTransactionValid)
|
||||
return ""
|
||||
switch(d.transactionType) {
|
||||
case Constants.TransactionType.Swap:
|
||||
|
@ -249,13 +254,13 @@ Item {
|
|||
}
|
||||
}
|
||||
asset.name: {
|
||||
if (!root.isTransactionValid)
|
||||
if (!d.isTransactionValid)
|
||||
return ""
|
||||
switch(d.transactionType) {
|
||||
case Constants.TransactionType.Swap:
|
||||
return Constants.tokenIcon(d.outSymbol)
|
||||
case Constants.TransactionType.Bridge:
|
||||
return Style.svg(RootStore.getNetworkIcon(root.transaction.chainIdOut)) ?? Style.svg("network/Network=Custom")
|
||||
return Style.svg(RootStore.getNetworkIcon(d.transaction.chainIdOut)) ?? Style.svg("network/Network=Custom")
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
@ -282,7 +287,7 @@ Item {
|
|||
case Constants.TransactionType.Swap:
|
||||
return Constants.tokenIcon(d.inSymbol)
|
||||
case Constants.TransactionType.Bridge:
|
||||
return Style.svg(RootStore.getNetworkIcon(root.transaction.chainIdIn)) ?? Style.svg("network/Network=Custom")
|
||||
return Style.svg(RootStore.getNetworkIcon(d.transaction.chainIdIn)) ?? Style.svg("network/Network=Custom")
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
@ -294,7 +299,7 @@ Item {
|
|||
width: parent.width
|
||||
title: d.transactionType === Constants.TransactionType.Swap || d.transactionType === Constants.TransactionType.Bridge ?
|
||||
qsTr("In") : qsTr("From")
|
||||
addresses: root.isTransactionValid && d.reEvaluateSender? [root.transaction.sender] : []
|
||||
addresses: d.isTransactionValid && d.reEvaluateSender? [d.transaction.sender] : []
|
||||
contactsStore: root.contactsStore
|
||||
rootStore: WalletStores.RootStore
|
||||
onButtonClicked: {
|
||||
|
@ -337,7 +342,7 @@ Item {
|
|||
TransactionAddressTile {
|
||||
width: parent.width
|
||||
title: qsTr("To")
|
||||
addresses: root.isTransactionValid && visible && d.reEvaluateRecipient? [root.transaction.recipient] : []
|
||||
addresses: d.isTransactionValid && visible && d.reEvaluateRecipient? [d.transaction.recipient] : []
|
||||
contactsStore: root.contactsStore
|
||||
rootStore: WalletStores.RootStore
|
||||
onButtonClicked: addressMenu.openReceiverMenu(this, addresses[0], [d.networkShortName])
|
||||
|
@ -388,7 +393,7 @@ Item {
|
|||
// Used to display contract address for any network
|
||||
address: d.isDetailsValid ? d.details.contractIn : ""
|
||||
symbol: {
|
||||
if (!root.isTransactionValid)
|
||||
if (!d.isTransactionValid)
|
||||
return ""
|
||||
return d.symbol ? d.symbol : "(%1)".arg(Utils.compactAddress(transaction.tokenAddress, 4))
|
||||
}
|
||||
|
@ -407,7 +412,7 @@ Item {
|
|||
TransactionContractTile {
|
||||
// Used for Bridge and Swap to display 'To' network token contract address
|
||||
address: {
|
||||
if (!root.isTransactionValid)
|
||||
if (!d.isTransactionValid)
|
||||
return ""
|
||||
switch(d.transactionType) {
|
||||
case Constants.TransactionType.Swap:
|
||||
|
@ -418,7 +423,7 @@ Item {
|
|||
}
|
||||
}
|
||||
symbol: {
|
||||
if (!root.isTransactionValid)
|
||||
if (!d.isTransactionValid)
|
||||
return ""
|
||||
switch(d.transactionType) {
|
||||
case Constants.TransactionType.Swap:
|
||||
|
@ -431,7 +436,7 @@ Item {
|
|||
}
|
||||
networkName: transactionHeader.networkNameIn
|
||||
shortNetworkName: d.networkShortNameIn
|
||||
visible: root.isTransactionValid && !!subTitle
|
||||
visible: d.isTransactionValid && !!subTitle
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -567,7 +572,7 @@ Item {
|
|||
width: parent.width
|
||||
title: !!transactionHeader.networkNameOut ? qsTr("Included in Block on %1").arg(transactionHeader.networkNameOut) : qsTr("Included on Block")
|
||||
subTitle: d.blockNumberOut
|
||||
tertiaryTitle: root.isTransactionValid ? LocaleUtils.formatDateTime(transaction.timestamp * 1000, Locale.LongFormat) : ""
|
||||
tertiaryTitle: d.isTransactionValid ? LocaleUtils.formatDateTime(transaction.timestamp * 1000, Locale.LongFormat) : ""
|
||||
visible: d.blockNumberOut > 0 && transactionHeader.isMultiTransaction
|
||||
}
|
||||
TransactionDataTile {
|
||||
|
@ -577,7 +582,7 @@ Item {
|
|||
readonly property string networkName: transactionHeader.isMultiTransaction ? transactionHeader.networkNameIn : transactionHeader.networkName
|
||||
title: !!networkName ? qsTr("Included in Block on %1").arg(networkName) : qsTr("Included on Block")
|
||||
subTitle: blockNumber
|
||||
tertiaryTitle: root.isTransactionValid ? LocaleUtils.formatDateTime(transaction.timestamp * 1000, Locale.LongFormat) : ""
|
||||
tertiaryTitle: d.isTransactionValid ? LocaleUtils.formatDateTime(transaction.timestamp * 1000, Locale.LongFormat) : ""
|
||||
visible: blockNumber > 0
|
||||
}
|
||||
}
|
||||
|
@ -603,7 +608,7 @@ Item {
|
|||
Layout.alignment: Qt.AlignRight
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor5
|
||||
text: root.isTransactionValid ? qsTr("as of %1").arg(LocaleUtils.formatDateTime(transaction.timestamp * 1000, Locale.LongFormat)) : ""
|
||||
text: d.isTransactionValid ? qsTr("as of %1").arg(LocaleUtils.formatDateTime(transaction.timestamp * 1000, Locale.LongFormat)) : ""
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
@ -633,7 +638,7 @@ Item {
|
|||
width: parent.width
|
||||
title: transactionHeader.transactionStatus === Constants.TransactionStatus.Pending ? qsTr("Amount to receive") : qsTr("Amount received")
|
||||
subTitle: {
|
||||
if (!root.isTransactionValid || transactionHeader.isNFT)
|
||||
if (!d.isTransactionValid || transactionHeader.isNFT)
|
||||
return ""
|
||||
const type = d.transactionType
|
||||
if (type === Constants.TransactionType.Swap) {
|
||||
|
@ -661,7 +666,7 @@ Item {
|
|||
width: parent.width
|
||||
title: d.symbol ? qsTr("Fees") : qsTr("Estimated max fee")
|
||||
subTitle: {
|
||||
if (!root.isTransactionValid || transactionHeader.isNFT || !d.isDetailsValid)
|
||||
if (!d.isTransactionValid || transactionHeader.isNFT || !d.isDetailsValid)
|
||||
return ""
|
||||
if (!d.symbol) {
|
||||
const maxFeeEth = RootStore.getFeeEthValue(d.details.maxTotalFees)
|
||||
|
@ -749,7 +754,7 @@ Item {
|
|||
|
||||
RowLayout {
|
||||
width: progressBlock.width
|
||||
visible: root.isTransactionValid
|
||||
visible: d.isTransactionValid
|
||||
spacing: 8
|
||||
StatusButton {
|
||||
Layout.fillWidth: true
|
||||
|
@ -757,10 +762,10 @@ Item {
|
|||
text: qsTr("Repeat transaction")
|
||||
size: StatusButton.Small
|
||||
|
||||
property alias tx: root.transaction
|
||||
property alias tx: d.transaction
|
||||
|
||||
visible: {
|
||||
if (!root.isTransactionValid || root.overview.isWatchOnlyAccount)
|
||||
if (!d.isTransactionValid || root.overview.isWatchOnlyAccount)
|
||||
return false
|
||||
|
||||
return WalletStores.RootStore.isTxRepeatable(tx)
|
||||
|
@ -809,7 +814,7 @@ Item {
|
|||
width: parent.width
|
||||
height: {
|
||||
// Using childrenRect and transactionvalid properties to refresh this binding
|
||||
if (!isTransactionValid || detailsColumn.childrenRect.height === 0)
|
||||
if (!d.isTransactionValid || detailsColumn.childrenRect.height === 0)
|
||||
return 0
|
||||
|
||||
// Height is calculated from visible children because Column doesn't handle
|
||||
|
|
|
@ -19,6 +19,8 @@ import "../../controls"
|
|||
Item {
|
||||
id: root
|
||||
|
||||
signal launchTransactionDetail(string txID)
|
||||
|
||||
required property var rootStore
|
||||
required property var walletRootStore
|
||||
required property var communitiesStore
|
||||
|
@ -212,7 +214,11 @@ Item {
|
|||
community: isModelDataValid && !!communityId && !!root.communitiesStore ? root.communitiesStore.getCommunityDetailsAsJson(communityId) : null
|
||||
loading: false
|
||||
onClicked: {
|
||||
// TODO: Implement switch to transaction details screen
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
// TODO: Implement context menu
|
||||
} else {
|
||||
root.launchTransactionDetail(modelData.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ StatusListItem {
|
|||
|
||||
readonly property bool isModelDataValid: modelData !== undefined && !!modelData
|
||||
|
||||
readonly property string txID: isModelDataValid ? modelData.id : "INVALID"
|
||||
readonly property int transactionStatus: isModelDataValid ? modelData.status : Constants.TransactionStatus.Pending
|
||||
readonly property bool isMultiTransaction: isModelDataValid && modelData.isMultiTransaction
|
||||
readonly property string currentCurrency: rootStore.currentCurrency
|
||||
|
@ -176,11 +177,6 @@ StatusListItem {
|
|||
}
|
||||
|
||||
function getDetailsString(detailsObj) {
|
||||
if (!detailsObj) {
|
||||
rootStore.fetchTxDetails(index)
|
||||
detailsObj = rootStore.getTxDetails()
|
||||
}
|
||||
|
||||
let details = ""
|
||||
const endl = "\n"
|
||||
const endl2 = endl + endl
|
||||
|
|
|
@ -208,12 +208,13 @@ QtObject {
|
|||
walletSectionInst.fetchDecodedTxData(txHash, input)
|
||||
}
|
||||
|
||||
function fetchTxDetails(modelIndex) {
|
||||
walletSectionInst.activityController.fetchTxDetails(modelIndex)
|
||||
function fetchTxDetails(txID) {
|
||||
walletSectionInst.activityController.fetchTxDetails(txID)
|
||||
walletSectionInst.activityDetailsController.fetchExtraTxDetails()
|
||||
}
|
||||
|
||||
function getTxDetails() {
|
||||
return walletSectionInst.activityController.activityDetails
|
||||
return walletSectionInst.activityDetailsController.activityDetails
|
||||
}
|
||||
|
||||
property bool marketHistoryIsLoading: Global.appIsReady? walletSectionAllTokens.marketHistoryIsLoading : false
|
||||
|
|
|
@ -37,11 +37,9 @@ ColumnLayout {
|
|||
property bool hideVerticalScrollbar: false
|
||||
property int firstItemOffset: 0
|
||||
|
||||
property var selectedTransaction
|
||||
|
||||
property real yPosition: transactionListRoot.visibleArea.yPosition * transactionListRoot.contentHeight
|
||||
|
||||
signal launchTransactionDetail(int entryIndex)
|
||||
signal launchTransactionDetail(string txID)
|
||||
|
||||
function resetView() {
|
||||
if (!!filterPanelLoader.item) {
|
||||
|
@ -102,18 +100,13 @@ ColumnLayout {
|
|||
|
||||
property string openTxDetailsHash
|
||||
|
||||
function openTxDetails(txHash) {
|
||||
function openTxDetails(txID) {
|
||||
// Prevent opening details when loading, that will invalidate the model data
|
||||
if (RootStore.loadingHistoryTransactions) {
|
||||
return false
|
||||
}
|
||||
|
||||
const index = WalletStores.RootStore.currentActivityFiltersStore.transactionsList.getIndex(txHash)
|
||||
if (index < 0)
|
||||
return false
|
||||
const entry = transactionListRoot.itemAtIndex(index)
|
||||
root.selectedTransaction = Qt.binding(() => entry.modelData)
|
||||
root.launchTransactionDetail(index)
|
||||
root.launchTransactionDetail(txID)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -391,7 +384,11 @@ ColumnLayout {
|
|||
if (delegateMenu.transaction.sender !== delegateMenu.transaction.recipient) {
|
||||
WalletStores.RootStore.addressWasShown(delegateMenu.transaction.recipient)
|
||||
}
|
||||
RootStore.copyToClipboard(delegateMenu.transactionDelegate.getDetailsString())
|
||||
|
||||
RootStore.fetchTxDetails(delegateMenu.transaction.id)
|
||||
let detailsObj = RootStore.getTxDetails()
|
||||
let detailsString = delegateMenu.transactionDelegate.getDetailsString(detailsObj)
|
||||
RootStore.copyToClipboard(detailsString)
|
||||
}
|
||||
}
|
||||
StatusMenuSeparator {
|
||||
|
@ -496,8 +493,7 @@ ColumnLayout {
|
|||
if (mouse.button === Qt.RightButton) {
|
||||
delegateMenu.openMenu(this, mouse, modelData)
|
||||
} else {
|
||||
root.selectedTransaction = Qt.binding(() => transactionDelegate.model.activityEntry)
|
||||
launchTransactionDetail(transactionDelegate.index)
|
||||
launchTransactionDetail(modelData.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue