Skip to content

Commit 9474a38

Browse files
committed
feat: activities in a browser wallet
1 parent 40b9562 commit 9474a38

File tree

18 files changed

+208
-124
lines changed

18 files changed

+208
-124
lines changed

src/app/modules/main/browser_section/module.nim

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import ../../../../app_service/service/dapp_permissions/service as dapp_permissi
1414
import ../../../../app_service/service/wallet_account/service as wallet_account_service
1515
import ../../../../app_service/service/token/service as token_service
1616
import ../../../../app_service/service/currency/service as currency_service
17+
import ../../../../app_service/service/saved_address/service as saved_address_service
18+
import ../wallet_section/activity/controller as activity_controller
1719

1820
export io_interface
1921

@@ -27,6 +29,7 @@ type
2729
bookmarkModule: bookmark_module.AccessInterface
2830
dappsModule: dapps_module.AccessInterface
2931
currentAccountModule: current_account_module.AccessInterface
32+
activityController: activity_controller.Controller
3033

3134
proc newModule*(delegate: delegate_interface.AccessInterface,
3235
events: EventEmitter,
@@ -36,12 +39,19 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
3639
dappPermissionsService: dapp_permissions_service.Service,
3740
walletAccountService: wallet_account_service.Service,
3841
tokenService: token_service.Service,
39-
currencyService: currency_service.Service
42+
currencyService: currency_service.Service,
43+
savedAddressService: saved_address_service.Service
4044
): Module =
4145
result = Module()
4246
result.delegate = delegate
4347
result.events = events
44-
result.view = view.newView(result)
48+
result.activityController = activity_controller.newController(
49+
currencyService,
50+
tokenService,
51+
savedAddressService,
52+
networkService,
53+
events)
54+
result.view = view.newView(result, result.activityController)
4555
result.viewVariant = newQVariant(result.view)
4656
result.moduleLoaded = false
4757
result.bookmarkModule = bookmark_module.newModule(result, events, bookmarkService)
@@ -51,6 +61,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
5161
method delete*(self: Module) =
5262
self.view.delete
5363
self.viewVariant.delete
64+
self.activityController.delete
5465
self.bookmarkModule.delete
5566
self.dappsModule.delete
5667
self.currentAccountModule.delete

src/app/modules/main/browser_section/view.nim

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import nimqml
22
import io_interface
3+
import ../wallet_section/activity/controller as activity_controller
34

45
QtObject:
56
type
67
View* = ref object of QObject
78
delegate: io_interface.AccessInterface
9+
activityController: activity_controller.Controller
810

911
proc setup(self: View)
1012
proc delete*(self: View)
11-
proc newView*(delegate: io_interface.AccessInterface): View =
13+
proc newView*(delegate: io_interface.AccessInterface,
14+
activityController: activity_controller.Controller): View =
1215
new(result, delete)
1316
result.delegate = delegate
17+
result.activityController = activityController
1418
result.setup()
1519

1620
proc load*(self: View) =
@@ -20,6 +24,12 @@ QtObject:
2024
proc sendOpenUrlSignal*(self: View, url: string) =
2125
self.openUrl(url)
2226

27+
proc getActivityController*(self: View): QVariant {.slot.} =
28+
return newQVariant(self.activityController)
29+
30+
QtProperty[QVariant] activityController:
31+
read = getActivityController
32+
2333
proc setup(self: View) =
2434
self.QObject.setup
2535

src/app/modules/main/module.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ proc newModule*[T](
227227
result.browserSectionModule = browser_section_module.newModule(
228228
result, events, bookmarkService, settingsService, networkService,
229229
dappPermissionsService, walletAccountService,
230-
tokenService, currencyService
230+
tokenService, currencyService, savedAddressService
231231
)
232232
result.profileSectionModule = profile_section_module.newModule(
233233
result, events, accountsService, settingsService, stickersService,

storybook/pages/TransactionDelegatePage.qml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ SplitView {
9494
}
9595
}
9696
flatNetworks: NetworksModel.flatNetworks
97-
walletRootStore: WalletStores.RootStore
97+
activityStore: WalletStores.RootStore
9898
}
9999
}
100100
}

ui/app/AppLayouts/Browser/popups/BrowserWalletMenu.qml

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@ import StatusQ
77
import StatusQ.Controls
88
import StatusQ.Core
99
import StatusQ.Core.Theme
10+
import StatusQ.Core.Utils as SQUtils
11+
12+
import SortFilterProxyModel
1013

1114
import shared.controls
1215
import shared.views
16+
import shared.stores as SharedStores
1317
import utils
1418

1519
import AppLayouts.Browser.stores as BrowserStores
@@ -30,7 +34,7 @@ Dialog {
3034

3135
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
3236
parent: Overlay.overlay
33-
width: 360
37+
width: 720
3438
height: 480
3539
background: Rectangle {
3640
id: bgPopup
@@ -118,13 +122,24 @@ Dialog {
118122
target: root.browserWalletStore.dappBrowserAccount
119123
function onConnectedAccountDeleted() {
120124
root.reload()
121-
// This is done because when an account is deleted and the account is updated to default one,
122-
// only the properties are updated and we need to listen to those events and update the selected account
125+
// Reset to default account when connected account is deleted
123126
accountSelectorRow.currentAddress = ""
124127
accountSelector.selectedAddress = Qt.binding(function () {return root.browserWalletStore.dappBrowserAccount.address})
125128
}
126129
}
127130

131+
Connections {
132+
target: browserActivityStore.transactionActivityStatus
133+
enabled: root.visible
134+
function onIsFilterDirtyChanged() {
135+
root.browserWalletStore.updateTransactionFilterIfDirty()
136+
}
137+
function onFilterChainsChanged() {
138+
browserActivityStore.currentActivityFiltersStore.updateCollectiblesModel()
139+
browserActivityStore.currentActivityFiltersStore.updateRecipientsModel()
140+
}
141+
}
142+
128143
Item {
129144
property string currentAddress: ""
130145
id: accountSelectorRow
@@ -142,7 +157,6 @@ Dialog {
142157
selectedAddress: root.browserWalletStore.dappBrowserAccount.address
143158
onCurrentAccountAddressChanged: {
144159
if (!accountSelectorRow.currentAddress) {
145-
// We just set the account for the first time. Nothing to do here
146160
accountSelectorRow.currentAddress = currentAccountAddress
147161
return
148162
}
@@ -153,6 +167,12 @@ Dialog {
153167
accountSelectorRow.currentAddress = currentAccountAddress
154168
root.browserWalletStore.switchAccountByAddress(currentAccountAddress)
155169
root.accountChanged(currentAccountAddress)
170+
171+
browserActivityStore.activityController.setFilterAddressesJson(
172+
JSON.stringify([currentAccountAddress])
173+
)
174+
browserActivityStore.activityController.newFilterSession()
175+
156176
reload()
157177
}
158178
}
@@ -182,18 +202,38 @@ Dialog {
182202
}
183203
}
184204

185-
Item {
205+
BrowserStores.BrowserActivityStore {
206+
id: browserActivityStore
207+
browserWalletStore: root.browserWalletStore
208+
}
209+
210+
HistoryView {
186211
id: walletInfoContent
187212
width: parent.width
188213
anchors.top: accountSelectorRow.bottom
189214
anchors.topMargin: Theme.bigPadding
190215
anchors.bottom: parent.bottom
191216

192-
// TODO: Add Assets and History tabs when ready
193-
StatusBaseText {
194-
anchors.centerIn: parent
195-
text: qsTr("Wallet info will appear here")
196-
color: Theme.palette.baseColor1
217+
activityStore: browserActivityStore
218+
overview: root.browserWalletStore.dappBrowserAccount
219+
communitiesStore: null
220+
currencyStore: SharedStores.CurrenciesStore {}
221+
networksStore: SharedStores.NetworksStore {}
222+
showAllAccounts: false
223+
displayValues: true
224+
filterVisible: false
225+
disableShadowOnScroll: true
226+
hideVerticalScrollbar: false
227+
228+
Component.onCompleted: {
229+
const activeChainIds = SQUtils.ModelUtils.modelToFlatArray(networksStore.activeNetworks, "chainId")
230+
if (activeChainIds.length > 0) {
231+
browserActivityStore.activityController.setFilterChainsJson(JSON.stringify(activeChainIds), true)
232+
}
233+
234+
const currentAddress = root.browserWalletStore.dappBrowserAccount.address
235+
browserActivityStore.activityController.setFilterAddressesJson(JSON.stringify([currentAddress]))
236+
browserActivityStore.activityController.newFilterSession()
197237
}
198238
}
199239
onClosed: {
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import QtQuick
2+
import SortFilterProxyModel
3+
4+
import utils
5+
6+
QtObject {
7+
id: root
8+
9+
required property var browserWalletStore
10+
11+
readonly property var activityController: browserSection.activityController
12+
13+
readonly property string selectedAddress: browserWalletStore.dappBrowserAccount.address
14+
readonly property bool isNonArchivalNode: false
15+
readonly property bool showAllAccounts: false
16+
readonly property var transactionActivityStatus: activityController.status
17+
readonly property bool loadingHistoryTransactions: activityController.status.loadingData
18+
readonly property bool newDataAvailable: activityController.status.newDataAvailable
19+
20+
// Show only transactions where current account is sender or recipient
21+
readonly property var historyTransactions: SortFilterProxyModel {
22+
sourceModel: root.activityController.model
23+
readonly property bool hasMore: sourceModel ? sourceModel.hasMore : false
24+
filters: ExpressionFilter {
25+
expression: {
26+
const currentAddr = root.browserWalletStore.dappBrowserAccount.address.toLowerCase()
27+
if (!model.activityEntry) return false
28+
const sender = model.activityEntry.sender ? model.activityEntry.sender.toLowerCase() : ""
29+
const recipient = model.activityEntry.recipient ? model.activityEntry.recipient.toLowerCase() : ""
30+
return sender === currentAddr || recipient === currentAddr
31+
}
32+
}
33+
}
34+
35+
// Browser view doesn't provide transaction filtering UI
36+
readonly property QtObject currentActivityFiltersStore: QtObject {
37+
readonly property bool filtersSet: false
38+
39+
function applyAllFilters() {
40+
root.activityController.updateFilter()
41+
}
42+
43+
function updateCollectiblesModel() {
44+
root.activityController.updateCollectiblesModel()
45+
}
46+
47+
function updateRecipientsModel() {
48+
root.activityController.updateRecipientsModel()
49+
}
50+
}
51+
52+
function updateTransactionFilterIfDirty() {
53+
if (transactionActivityStatus.isFilterDirty) {
54+
activityController.updateFilter()
55+
}
56+
}
57+
58+
function fetchMoreTransactions() {
59+
if (historyTransactions.count === 0
60+
|| !historyTransactions.hasMore
61+
|| loadingHistoryTransactions)
62+
return
63+
activityController.loadMoreItems()
64+
}
65+
66+
function resetActivityData() {
67+
activityController.resetActivityData()
68+
}
69+
70+
function getEtherscanLink(chainID) {
71+
return networksModule.getBlockExplorerTxURL(chainID)
72+
}
73+
74+
function getTransactionType(transaction) {
75+
if (!transaction) return Constants.TransactionType.Send
76+
return transaction.txType
77+
}
78+
79+
function getNameForAddress(address) {
80+
const name = walletSectionAccounts.getNameByAddress(address)
81+
return name.length > 0 ? name : ""
82+
}
83+
84+
function getDappDetails(chainId, contractAddress) {
85+
return undefined
86+
}
87+
88+
function isOwnedAccount(address) {
89+
return walletSectionAccounts.isOwnedAccount(address)
90+
}
91+
}

ui/app/AppLayouts/Browser/stores/BrowserWalletStore.qml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ QtObject {
88
property string defaultCurrency: walletSection.currentCurrency
99
property string signingPhrase: walletSection.signingPhrase // FIXME
1010

11-
function getEtherscanLink(chainID) {
12-
return networksModule.getBlockExplorerTxURL(chainID)
13-
}
14-
1511
function switchAccountByAddress(address) {
1612
browserSectionCurrentAccount.switchAccountByAddress(address)
1713
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
BrowserRootStore 1.0 BrowserRootStore.qml
22
BrowserWalletStore 1.0 BrowserWalletStore.qml
3+
BrowserActivityStore 1.0 BrowserActivityStore.qml
34
BookmarksStore 1.0 BookmarksStore.qml
45
DownloadsStore 1.0 DownloadsStore.qml

ui/app/AppLayouts/Wallet/popups/SavedAddressActivityPopup.qml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ StatusModal {
269269
isWatchOnlyAccount: false,
270270
mixedcaseAddress: d.address
271271
})
272-
walletRootStore: WalletStore.RootStore
272+
activityStore: WalletStore.RootStore
273273
networksStore: root.networksStore
274274
}
275275
}

ui/app/AppLayouts/Wallet/views/RightTabView.qml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ RightTabBaseView {
532532
id: historyView
533533
HistoryView {
534534
overview: RootStore.overview
535-
walletRootStore: RootStore
535+
activityStore: RootStore
536536
communitiesStore: root.communitiesStore
537537
currencyStore: root.sharedRootStore.currencyStore
538538
networksStore: root.networksStore

0 commit comments

Comments
 (0)