Skip to content

Commit 5b9cea4

Browse files
committed
refactor(UsersStore): Decouple users store from UI components and centralize instantiation in Chat.RootStore
This refactor separates the `UsersStore` usage from low-level UI components by lifting its instantiation up to the `Chat.RootStore`. All components now use this single centralized instance, eliminating multiple unnecessary store instantiations and improving state consistency and maintainability across the app. No functional changes to user flows; implementation is cleaner and more maintainable. Updated all affected components and flows: - User mentions list in the status chat input (for both standard and edit chat input modes) - Right-side members/users column - Group chat members management Closes #18000
1 parent c109265 commit 5b9cea4

File tree

11 files changed

+151
-64
lines changed

11 files changed

+151
-64
lines changed

ui/app/AppLayouts/Chat/ChatLayout.qml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,19 @@ StackLayout {
6868
property var cbGetCompressedPk: function (publicKey) { console.error("Implement me"); return ""}
6969
property var cbGetEmojiHash: function (publicKey) { console.error("Implement me"); return ""}
7070

71+
// Users related data:
72+
readonly property bool amIChatAdmin: root.rootStore.amIChatAdmin()
73+
property var usersModel
74+
75+
// Users related but just for group chats:
76+
property var temporaryUsersModel
77+
78+
// Users related signals
79+
signal updateGroupMembers()
80+
signal resetTemporaryUsersModel()
81+
signal appendTemporaryUsersModel(string pubKey, string displayName)
82+
signal removeFromTemporaryUsersModel(string pubKey)
83+
7184
signal profileButtonClicked()
7285
signal openAppSearch()
7386
signal buyStickerPackRequested(string packId, int price)
@@ -184,6 +197,7 @@ StackLayout {
184197
sectionItemModel: root.sectionItemModel
185198
joinedMembersCount: membersModelAdaptor.joinedMembers.ModelCount.count
186199
areTestNetworksEnabled: root.networksStore.areTestNetworksEnabled
200+
amIChatAdmin: root.rootStore.amIChatAdmin()
187201
amIMember: sectionItem.amIMember
188202
amISectionAdmin: root.sectionItemModel.memberRole === Constants.memberRole.owner ||
189203
root.sectionItemModel.memberRole === Constants.memberRole.admin ||
@@ -246,6 +260,15 @@ StackLayout {
246260
cbGetCompressedPk: root.cbGetCompressedPk
247261
cbGetEmojiHash: root.cbGetEmojiHash
248262

263+
// Users related data:
264+
usersModel: root.usersModel
265+
temporaryUsersModel: root.temporaryUsersModel
266+
267+
onUpdateGroupMembers: root.updateGroupMembers()
268+
onResetTemporaryUsersModel: root.resetTemporaryUsersModel()
269+
onAppendTemporaryUsersModel: root.appendTemporaryUsersModel(pubKey, displayName)
270+
onRemoveFromTemporaryUsersModel: root.removeFromTemporaryUsersModel(pubKey)
271+
249272
onFinaliseOwnershipClicked: Global.openFinaliseOwnershipPopup(communityId)
250273
onCommunityInfoButtonClicked: root.currentIndex = 1
251274
onCommunityManageButtonClicked: root.currentIndex = 1

ui/app/AppLayouts/Chat/stores/RootStore.qml

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ import utils 1.0
1616
QtObject {
1717
id: root
1818

19+
// Backend Entry Point:
20+
// Important:
21+
// Each `ChatLayout` has its own chatCommunitySectionModule
22+
// (on the backend chat and community sections share the same module since they are actually the same)
23+
property var chatCommunitySectionModule
24+
25+
readonly property var activeChatContentModule: root.currentChatContentModule()
26+
1927
property ContactsStore contactsStore
2028
property CommunityTokensStore communityTokensStore
2129
property WalletStore.RootStore walletStore
@@ -28,12 +36,17 @@ QtObject {
2836
chatCommunitySectionModuleInst: chatCommunitySectionModule
2937
}
3038

39+
// Unique instance for all the chat / channel related low-level UI components
40+
readonly property UsersStore usersStore: UsersStore {
41+
property var chatDetails: !!root.activeChatContentModule ? root.activeChatContentModule.chatDetails : null
42+
43+
isFullCommunityMembers: chatDetails.belongsToCommunity && !chatDetails.requiresPermissions
44+
usersModule: !!root.activeChatContentModule ? root.activeChatContentModule.usersModule : null
45+
chatCommunitySectionModule: root.chatCommunitySectionModule
46+
}
47+
3148
property bool openCreateChat: false
3249

33-
// Important:
34-
// Each `ChatLayout` has its own chatCommunitySectionModule
35-
// (on the backend chat and community sections share the same module since they are actually the same)
36-
property var chatCommunitySectionModule
3750
readonly property var sectionDetails: d.sectionDetailsInstantiator.count ? d.sectionDetailsInstantiator.objectAt(0) : null
3851

3952
property var communityItemsModel: chatCommunitySectionModule.model

ui/app/AppLayouts/Chat/stores/UsersStore.qml

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,33 @@ import QtQuick 2.15
33
QtObject {
44
id: root
55

6-
property var chatCommunitySectionModule
7-
property var chatDetails
8-
property var usersModule
6+
// External properties:
7+
required property var chatCommunitySectionModule
8+
required property var usersModule
9+
required property bool isFullCommunityMembers
910

11+
// Public API:
1012
readonly property var usersModel: {
11-
if (!chatDetails && !chatCommunitySectionModule) {
12-
return null
13-
}
14-
let isFullCommunityList = !chatDetails.requiresPermissions
15-
if (chatDetails.belongsToCommunity && isFullCommunityList && !!chatCommunitySectionModule) {
13+
if (root.isFullCommunityMembers) {
1614
// Community channel with no permisisons. We can use the section's membersModel
17-
return chatCommunitySectionModule.membersModel
15+
return root.chatCommunitySectionModule ? root.chatCommunitySectionModule.membersModel : null
1816
}
19-
return usersModule ? usersModule.model : null
17+
return root.usersModule ? root.usersModule.model : null
2018
}
21-
readonly property var temporaryModel: usersModule ? usersModule.temporaryModel : null
19+
20+
// Used for editing:
21+
readonly property var temporaryModel: root.usersModule ? root.usersModule.temporaryModel : null
2222

2323
function appendTemporaryModel(pubKey, displayName) {
24-
usersModule.appendTemporaryModel(pubKey, displayName)
24+
root.usersModule.appendTemporaryModel(pubKey, displayName)
2525
}
2626
function removeFromTemporaryModel(pubKey) {
27-
usersModule.removeFromTemporaryModel(pubKey)
27+
root.usersModule.removeFromTemporaryModel(pubKey)
2828
}
2929
function resetTemporaryModel() {
30-
usersModule.resetTemporaryModel()
30+
root.usersModule.resetTemporaryModel()
3131
}
3232
function updateGroupMembers() {
33-
usersModule.updateGroupMembers()
33+
root.usersModule.updateGroupMembers()
3434
}
3535
}

ui/app/AppLayouts/Chat/views/ChatColumnView.qml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ Item {
6666
property var cbGetCompressedPk: function (publicKey) { console.error("Implement me"); return ""}
6767
property var cbGetEmojiHash: function (publicKey) { console.error("Implement me"); return ""}
6868

69+
// Users related data:
70+
property var usersModel
71+
6972
signal openStickerPackPopup(string stickerPackId)
7073
signal tokenPaymentRequested(string recipientAddress, string symbol, string rawAmount, int chainId)
7174

@@ -114,12 +117,6 @@ Item {
114117
model: !!d.activeChatContentModule ? d.activeChatContentModule.inputAreaModule.urlsModel : null
115118
}
116119

117-
readonly property ChatStores.UsersStore activeUsersStore: ChatStores.UsersStore {
118-
usersModule: !!d.activeChatContentModule ? d.activeChatContentModule.usersModule : null
119-
chatDetails: !!d.activeChatContentModule ? d.activeChatContentModule.chatDetails : null
120-
chatCommunitySectionModule: root.rootStore.chatCommunitySectionModule
121-
}
122-
123120
readonly property ChatStores.MessageStore activeMessagesStore: ChatStores.MessageStore {
124121
messageModule: d.activeChatContentModule ? d.activeChatContentModule.messagesModule : null
125122
chatSectionModule: root.rootStore.chatCommunitySectionModule
@@ -213,7 +210,7 @@ Item {
213210
preservedText = d.activeChatContentModule.inputAreaModule.preservedProperties.text
214211

215212
d.activeChatContentModule.inputAreaModule.clearLinkPreviewCache()
216-
// Call later to make sure activeUsersStore and activeMessagesStore bindings are updated
213+
// Call later to make sure usersStore and activeMessagesStore bindings are updated
217214
Qt.callLater(d.restoreInputState, preservedText)
218215
}
219216

@@ -236,6 +233,7 @@ Item {
236233
// The best would be if we made qml to follow the struct we have on the backend side.
237234

238235
ColumnLayout {
236+
239237
anchors.fill: parent
240238
spacing: 0
241239

@@ -276,6 +274,8 @@ Item {
276274
cbGetCompressedPk: root.cbGetCompressedPk
277275
cbGetEmojiHash: root.cbGetEmojiHash
278276

277+
usersModel: root.usersModel
278+
279279
onOpenStickerPackPopup: {
280280
root.openStickerPackPopup(stickerPackId)
281281
}
@@ -329,7 +329,7 @@ Item {
329329
&& !d.sendingInProgress
330330
}
331331

332-
usersModel: d.activeUsersStore.usersModel
332+
usersModel: root.usersModel
333333
linkPreviewModel: !!d.activeChatContentModule ? d.activeChatContentModule.inputAreaModule.linkPreviewModel : null
334334
paymentRequestModel: !!d.activeChatContentModule ? d.activeChatContentModule.inputAreaModule.paymentRequestModel : null
335335
formatBalance: d.formatBalance

ui/app/AppLayouts/Chat/views/ChatContentView.qml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ ColumnLayout {
4343

4444
property var emojiPopup
4545
property var stickersPopup
46-
property UsersStore usersStore: UsersStore {
47-
chatCommunitySectionModule: root.rootStore.chatCommunitySectionModule
48-
}
46+
47+
// Users related data:
48+
property var usersModel
4949

5050
signal openStickerPackPopup(string stickerPackId)
5151
signal tokenPaymentRequested(string recipientAddress, string symbol, string rawAmount, int chainId)
@@ -80,11 +80,6 @@ ColumnLayout {
8080
objectName: "chatContentViewColumn"
8181
spacing: 0
8282

83-
onChatContentModuleChanged: if (!!chatContentModule) {
84-
root.usersStore.chatDetails = root.chatContentModule.chatDetails
85-
root.usersStore.usersModule = root.chatContentModule.usersModule
86-
}
87-
8883
Loader {
8984
Layout.fillWidth: true
9085
active: root.isBlocked
@@ -109,7 +104,6 @@ ColumnLayout {
109104
formatBalance: root.formatBalance
110105
emojiPopup: root.emojiPopup
111106
stickersPopup: root.stickersPopup
112-
usersStore: root.usersStore
113107
stickersLoaded: root.stickersLoaded
114108
chatId: root.chatId
115109
isOneToOne: root.chatType === Constants.chatType.oneToOne
@@ -119,6 +113,7 @@ ColumnLayout {
119113
sendViaPersonalChatEnabled: root.sendViaPersonalChatEnabled
120114
disabledTooltipText: root.disabledTooltipText
121115
areTestNetworksEnabled: root.areTestNetworksEnabled
116+
usersModel: root.usersModel
122117

123118
// Unfurling related data:
124119
gifUnfurlingEnabled: root.gifUnfurlingEnabled

ui/app/AppLayouts/Chat/views/ChatHeaderContentView.qml

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ Item {
2929
property var emojiPopup
3030
property int padding: Theme.halfPadding
3131

32+
property var usersModel
33+
property var temporaryUsersModel
34+
property var amIChatAdmin
35+
36+
signal updateGroupMembers()
37+
signal resetTemporaryUsersModel()
38+
signal appendTemporaryUsersModel(string pubKey, string displayName)
39+
signal removeFromTemporaryUsersModel(string pubKey)
40+
3241
signal searchButtonClicked()
3342
signal displayEditChannelPopup(string chatId,
3443
string chatName,
@@ -345,16 +354,19 @@ Item {
345354
id: membersSelector
346355

347356
MembersEditSelectorView {
348-
rootStore: root.rootStore
349-
usersStore: UsersStore {
350-
chatDetails: chatContentModule.chatDetails
351-
chatCommunitySectionModule: root.rootStore.chatCommunitySectionModule
352-
usersModule: root.chatContentModule.usersModule
353-
}
354357
contactsModel: root.mutualContactsModel
358+
usersModel: root.usersModel
359+
temporaryUsersModel: root.temporaryUsersModel
360+
361+
amIChatAdmin: root.amIChatAdmin
355362

356363
onConfirmed: root.state = d.stateInfoButtonContent
357364
onRejected: root.state = d.stateInfoButtonContent
365+
366+
onUpdateGroupMembers: root.updateGroupMembers()
367+
onResetTemporaryUsersModel: root.resetTemporaryUsersModel()
368+
onAppendTemporaryUsersModel: root.appendTemporaryUsersModel(pubKey, displayName)
369+
onRemoveFromTemporaryUsersModel: root.removeFromTemporaryUsersModel(pubKey)
358370
}
359371
}
360372
}

ui/app/AppLayouts/Chat/views/ChatMessagesView.qml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@ Item {
3333

3434
property RootStore rootStore
3535
property MessageStore messageStore
36-
property UsersStore usersStore
3736
property ContactsStore contactsStore
3837
property string channelEmoji
3938
property var formatBalance
4039

40+
// Users related data:
41+
property var usersModel
42+
4143
property var emojiPopup
4244
property var stickersPopup
4345
property bool areTestNetworksEnabled
@@ -297,14 +299,14 @@ Item {
297299

298300
rootStore: root.rootStore
299301
messageStore: root.messageStore
300-
usersStore: root.usersStore
301302
contactsStore: root.contactsStore
302303
channelEmoji: root.channelEmoji
303304
emojiPopup: root.emojiPopup
304305
stickersPopup: root.stickersPopup
305306
chatLogView: ListView.view
306307
chatContentModule: root.chatContentModule
307308
formatBalance: root.formatBalance
309+
usersModel: root.usersModel
308310

309311
isChatBlocked: root.isChatBlocked
310312

ui/app/AppLayouts/Chat/views/ChatView.qml

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,17 @@ StatusSectionLayout {
114114
property var cbGetCompressedPk: function (publicKey) { console.error("Implement me"); return ""}
115115
property var cbGetEmojiHash: function (publicKey) { console.error("Implement me"); return ""}
116116

117+
// Users related data:
118+
property var usersModel
119+
property var temporaryUsersModel
120+
property bool amIChatAdmin
121+
122+
// Users related signals
123+
signal updateGroupMembers()
124+
signal resetTemporaryUsersModel()
125+
signal appendTemporaryUsersModel(string pubKey, string displayName)
126+
signal removeFromTemporaryUsersModel(string pubKey)
127+
117128
// Community transfer ownership related props:
118129
required property bool isPendingOwnershipRequest
119130
signal finaliseOwnershipClicked
@@ -195,12 +206,6 @@ StatusSectionLayout {
195206
rightPanel: Component {
196207
id: userListComponent
197208
UserListPanel {
198-
readonly property var usersStore: ChatStores.UsersStore {
199-
usersModule: !!root.chatContentModule ? root.chatContentModule.usersModule : null
200-
chatDetails: !!root.chatContentModule ? root.chatContentModule.chatDetails : null
201-
chatCommunitySectionModule: root.rootStore.chatCommunitySectionModule
202-
}
203-
204209
anchors.fill: parent
205210

206211
chatType: root.chatContentModule.chatDetails.type
@@ -210,7 +215,7 @@ StatusSectionLayout {
210215
communityMemberReevaluationStatus: root.rootStore.communityMemberReevaluationStatus
211216

212217
usersModel: SortFilterProxyModel {
213-
sourceModel: usersStore.usersModel
218+
sourceModel: root.usersModel
214219

215220
proxyRoles: FastExpressionRole {
216221
name: "emojiHash"
@@ -255,6 +260,10 @@ StatusSectionLayout {
255260
mutualContactsModel: root.mutualContactsModel
256261
emojiPopup: root.emojiPopup
257262

263+
usersModel: root.usersModel
264+
temporaryUsersModel: root.temporaryUsersModel
265+
amIChatAdmin: root.amIChatAdmin
266+
258267
onSearchButtonClicked: root.openAppSearch()
259268
onDisplayEditChannelPopup: {
260269
Global.openPopup(contactColumnLoader.item.createChannelPopup, {
@@ -270,6 +279,11 @@ StatusSectionLayout {
270279
hideIfPermissionsNotMet: hideIfPermissionsNotMet
271280
});
272281
}
282+
283+
onUpdateGroupMembers: root.updateGroupMembers()
284+
onResetTemporaryUsersModel: root.resetTemporaryUsersModel()
285+
onAppendTemporaryUsersModel: root.appendTemporaryUsersModel(pubKey, displayName)
286+
onRemoveFromTemporaryUsersModel: root.removeFromTemporaryUsersModel(pubKey)
273287
}
274288
}
275289

@@ -310,6 +324,9 @@ StatusSectionLayout {
310324
cbGetCompressedPk: root.cbGetCompressedPk
311325
cbGetEmojiHash: root.cbGetEmojiHash
312326

327+
// Users related data:
328+
usersModel: root.usersModel
329+
313330
onOpenStickerPackPopup: {
314331
Global.openPopup(statusStickerPackClickPopup, {packId: stickerPackId, store: root.stickersPopup.store} )
315332
}

0 commit comments

Comments
 (0)