Skip to content

refactor: ProfileSectionsStore refactor and modularization pass and remove ContactsStore from MessageView hierarchy #18314

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

noeliaSD
Copy link
Contributor

@noeliaSD noeliaSD commented Jul 6, 2025

Closes #18164 and #18117

What does the PR do

This pull request includes a collection of 15 targeted commits focused on refactoring and modularizing the profile-related stores and their integration across the app. The changes are interrelated but intentionally broken down into small, logical units for clarity and easier review.

🔍 Recommendation: Review commit-by-commit

Each commit has been written to be self-contained, with clear messages and rationales. Reviewing sequentially will help understand the full context and progression.

Summary of Changes

Naming Consistency & Cleanup

  • ProfileStore: Rename pubkey → pubKey for consistency.
  • ProfileStore: Remove redundant privacyStore already provided via ProfileSectionStore.

Decoupling & Scope Isolation

  • ProfileSectionStore: Eliminate indirection by replacing access to child stores with direct references.
  • ProfileLayout: Move isWalletEnabled to WalletStore.
  • WalletView: Remove dependency on ProfileSectionStore in WalletView and children.
  • RootStore: Move production context flag out of UI and into RootStore scope.
  • AboutStore: Extract AboutStore from ProfileSectionStore; simplify and isolate AboutView logic.
  • ProfileLayout: Remove ProfileSectionStore dependency entirely; migrate remaining logic to ProfileStore.

Structural Preparation for Modularization

  • RootStore: Add clarifying comments and reorganize structure by domain (Wallet, Chat, Onboarding, etc.).
  • RootStore: Encapsulate mainModuleInst as private (internal) to reduce external coupling.

Store Responsibility Reassignments

  • Move contact showcase logic from ProfileSectionsStore to ContactsStore and community logic to CommunitiesStore.
  • Rename MessagingStore to MessagingSettingsStore, move to global scope, and improve property encapsulation.
  • Promote ContactsStore to top-level store and unify references throughout the app.
  • Move ContactsStore dependency to AppMain; remove from MessageView hierarchy for better modularity.

Rationale

Many of these changes were discovered progressively—cleaning up one piece revealed tight couplings or outdated patterns in others. This PR:

  • Reduces unnecessary indirection and coupling between stores
  • Makes domain boundaries clearer (e.g., Wallet, About, Messaging, Contacts)
  • Prepares RootStore for future modular breakdowns

Affected areas

Settings and Chat

Architecture compliance

Impact on end user

No impact. It improves and prepares code base for next refactor iterations.

How to test

  • Perform critical Chat related scenarios test.
  • Perform critical Settings related scenarios test.

Risk

This PR touches multiple interrelated stores and view hierarchies. Although changes are largely refactorings and scoped per commit, there is moderate risk of regressions in the following areas:

  • Chat flows: due to changes in MessageView and ContactsStore
  • Settings-related views: due to the restructuring of ProfileSectionStore, migration of the messaging and about stores, and changes in how store data is accessed

noeliaSD added 7 commits July 5, 2025 14:31
…ileStore`

Just a property rename for improving consistency.
…m `profileStore`

Since `ProfileSectionStore` already includes an instance of `PrivacyStore`, the separate `privacyStore` property inside `profileStore` was redundant.
This commit removes the duplicate reference to simplify state structure and avoid potential confusion or desynchronization.
…rection through `ProfileSectionStore` usage

Replaced all indirect access to specific stores via `ProfileSectionStore`  with direct references to each store.

This change improves readability, reduces unnecessary indirection, and clarifies ownership and dependency paths in the codebase.
…Store`

Moved and cleaned up `isWalletEnabled` property from `profileSectionStore` to profile `WalletStore` to improve readability and consistency.
…o view

Moved view related property to view component.
Cleanup related components.
Cleanup `profileSectionStore` dependency on `WalletView` and children components.
…nents to `RootStore`

Moved the `production` context property from UI components to the `RootStore` to ensure global accessibility and decouple environment logic from the view layer.
@status-im-auto
Copy link
Member

status-im-auto commented Jul 6, 2025

Jenkins Builds

Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ 2689937 #1 2025-07-06 08:04:09 ~7 min tests/nim 📄log
✔️ 2689937 #1 2025-07-06 08:07:55 ~10 min macos/aarch64 🍎dmg
2689937 #1 2025-07-06 08:08:06 ~11 min tests/ui 📄log
✔️ 2689937 #1 2025-07-06 08:13:46 ~16 min linux/x86_64 📦tgz
✔️ 2689937 #1 2025-07-06 08:20:02 ~22 min windows/x86_64 💿exe
✔️ c51283f #2 2025-07-06 10:06:03 ~6 min macos/aarch64 🍎dmg
✔️ c51283f #2 2025-07-06 10:06:07 ~6 min tests/nim 📄log
✔️ c51283f #2 2025-07-06 10:09:57 ~10 min tests/ui 📄log
✔️ c51283f #2 2025-07-06 10:12:18 ~13 min linux/x86_64 📦tgz
✔️ c51283f #2 2025-07-06 10:20:55 ~21 min windows/x86_64 💿exe

noeliaSD added 8 commits July 6, 2025 11:58
…onStore`

- Created a new `AboutStore` and moved all about-related logic into it.
- Removed the corresponding about code from `ProfileSectionStore`, simplifying its responsibilities.
- Improved `AboutView`'s API to be more explicit and easier to consume.

This refactor improves separation of concerns, clarifies ownership of about-related data, and makes the `About` module more self-contained and maintainable.
- Cleanup `profileSectionStore` dependency on `ProfileLayout` and children components (`CommunitiesView`).
- Moved `profile store` related code from `ProfileSectionsStore` to `ProfileStore`.
… for future modularization

- Added structured section comments to delineate responsibilities across modules (e.g., SettingsRootStore, ChatRootStore, WalletRootStore, etc.).
- Annotated context properties and module instances with TODO, WIP, and clarification notes to guide future cleanup.
- Reorganized properties and function blocks to group by domain (Profile, Settings, Onboarding, Chat, Communities, Wallet).
- Added notes about deprecated or temporary usage of module instances that should eventually become private/internal to each store.
- No logic changes introduced; purely preparatory work for upcoming RootStore decomposition.

This improves readability, maintains legacy compatibility, and prepares the file for targeted refactoring into more modular root stores.
…Store`

- Moved `mainModuleInst` under `internal` (private) inside `RootStore` to reduce external coupling.
- Replaced all occurrences of `rootStore.mainModuleInst` with `internal.mainModuleInst` within `RootStore` itself.
- Ensured access to all required data (`isOnline`, `sectionsModel`, `activeSection`, etc.) via computed readonly properties.
- Updated all signal handlers using `Connections { target: internal.mainModuleInst }` to preserve behavior while hiding direct module access.
- Declared new `RootStore` signals to expose relevant updates externally without leaking `mainModuleInst`.

This refactoring is part of a broader modularization effort and paves the way for making `mainModuleInst` fully private and internal to `RootStore`.
…actsStore` and community logic to `CommunitiesStore`

- Migrated contacts showcase logic from `ProfileSectionsStore` to `ContactsStore`.
- Migrated community-related logic from `ProfileSectionsStore` to `CommunitiesStore`.
- Updated affected components and references accordingly.
…ngsStore`, move it to global scope, and improve encapsulation

- Renamed `MessagingStore` to `MessagingSettingsStore`
- Moved it out of `Profile` scope to a global location
- Improved internal structure: used `readonly` and private properties where appropriate
- Updated all usages across the codebase
- `ProfileSectionsStore` no longer contains the messaging store
…unify references

- Moved `ContactsStore` out of `ProfileSectionsStore` to a higher-level location, as it's now considered cross-domain.
- Removed redundant references to `ContactsStore`.
- Unified all code to reference the store consistently from the new location.
…nd remove from `MessageView` hierarchy

- Lifted `ContactsStore` dependency to `AppMain` for centralized access.
- Removed previous references to `ContactsStore` from `MessageView` and its component hierarchy.
- Improved coupling and modularization by reducing deep dependencies.
@noeliaSD noeliaSD force-pushed the refactor/issue-18117 branch from 2689937 to c51283f Compare July 6, 2025 09:58
@noeliaSD noeliaSD marked this pull request as ready for review July 7, 2025 07:40
@noeliaSD noeliaSD requested review from micieslak, a team, caybro and alexjba as code owners July 7, 2025 07:40
@noeliaSD noeliaSD requested review from vkjr and Khushboo-dev-cpp and removed request for a team July 7, 2025 07:40
@noeliaSD noeliaSD requested review from jrainville and removed request for vkjr and a team July 7, 2025 07:41
Copy link
Member

@jrainville jrainville left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice clean up!
I had a couple of suggestions and questions

property string latestVersion
property string downloadURL

function setLatestVersionInfo(newVersionAvailable, latestVersion, downloadURL) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this code is used anymore. The new version updater never really worked

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, there is some to-do here:

Connections {
                    target: rootStore.aboutModuleInst
                    function onAppVersionFetched(available: bool, version: string, url: string) {
                        rootStore.setLatestVersionInfo(available, version, url);
                        // TODO when we re-implement check for updates, uncomment this
                        // bannersLayout.processUpdateAvailable()
                    }
                }

Should I remove this code?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so. If we re-add an updater, it will be in a while and will have to be re-thought

@@ -50,6 +69,9 @@ QtObject {

readonly property var sectionDetails: d.sectionDetailsInstantiator.count ? d.sectionDetailsInstantiator.objectAt(0) : null

// TODO: Review if `mainModuleInst.activeSection` is indeed the same as `sectionDetails` here. If yes, this is redundant
readonly property bool joined: root.mainModuleInst.activeSection.joined
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Store is created for each Chat I think. So it's weird that joined here would be using the ActiveSection and not the section it is from.

So this should probably be chatCommunitySectionModule.joined

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right! I'll check it again. I just moved this rootStore.mainModuleInst.activeSection.joined to Chat.RootStore and added a to-do to check it again, since it seemed strange to me too.

As you say I think it should be chatCommunitySectionModule.joined but I need to check all MessageView usages since maybe there are some corner cases to consider, like maybe CommunityMemberMessagesPopup.

@@ -230,6 +237,14 @@ QtObject {
return communitiesModuleInst.isDisplayNameDupeOfCommunityMember(displayName)
}

function leaveCommunity(communityId) {
d.profileSectionModuleInst.communitiesModule.leaveCommunity(communityId)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going through the profile module to call a community function sounds wrong.

We can move the leaveCommunity from the profile module to the community module in nim and use communitiesModuleInst instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. On this first step, I just moved things around to have a better clarity. Next steps will be, reviewing again, the specific stores, and clean them up properly! I'll take this comment into account! Thanks

}

function setCommunityMuted(communityId, mutedType) {
d.profileSectionModuleInst.communitiesModule.setCommunityMuted(communityId, mutedType)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, if we wanted a very thorough cleanup, we could remove those two function from the chat section as well and rely on the communities module instead. We just have to pass the communityId

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I'm planning to do something similar in the qml level, since now Chat.RootStore contains chat + community specific stuff. I'll work on it on following prs. I'll also add this nim code idea.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, feel free to open an issue with my comment(s)


// Here define the needed properties that access to `Context Properties`:
readonly property QtObject _internal: QtObject{
id: internal // Rename to `d` when cleanup done
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to d? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do it in some of the following prs, since here I just separated the code to easily see what is from where and don't want to mix the properties that are now in the existing d, since it will be moved to another context. This is just an intermediate state! Hope it makes sense 🫣

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah but since it's still the same store, it makes sense to finish the cleanup here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as it affects only that file, it should be easy to replace internal. with d. indeed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can mix them yes, but at this point I will not remove the code that is currently on d and should not be on this store. This store cleanup doesn't ends on this pr and what I did is just separation of code as a simple step to continue with the cleanup on another pr. If I mix it with the rest of d props, we will need to do again the exercise of understanding what should be here and what should be moved to another store.

@@ -21,7 +21,7 @@ import "../panels"
import "../popups"
import AppLayouts.Chat.stores 1.0
import AppLayouts.Communities.popups 1.0
import AppLayouts.Profile.stores 1.0
import AppLayouts.stores 1.0 as AppLayoutStores
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this import even needed then? There's no other change in this file that would reference it

@@ -17,6 +17,7 @@ import AppLayouts.Communities.stores 1.0 as CommunitiesStores
import AppLayouts.Chat.stores 1.0 as ChatStores
import AppLayouts.Profile.stores 1.0 as ProfileStores
import AppLayouts.Wallet.stores 1.0 as WalletStore
import AppLayouts.stores 1.0 as AppLayoutStores
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You changed this import but never reference it in this diff?

@@ -0,0 +1,5 @@
import QtQuick 2.14
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import QtQuick 2.14
import QtCore

@@ -0,0 +1,5 @@
import QtQuick 2.14

Item {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Item {
QtObject {

@@ -3,4 +3,6 @@ import QtQuick 2.15
QtObject {
property var chatCommunitySectionModule
property var contactsStore
property bool isChatSectionModule
property var communityId
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
property var communityId
property string communityId

Copy link
Member

@micieslak micieslak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job! I deeply believe it's important to do refactors like this to reach stability in long term. Looks good in general, some minor comments mainly.

@@ -42,7 +42,20 @@ StatusSectionLayout {

property SharedStores.RootStore sharedRootStore
property SharedStores.UtilsStore utilsStore
property ProfileStores.ProfileSectionStore store

property ProfileStores.ProfileSectionStore store // TO BE REMOVED
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't those properties be marked as required?

@@ -36,6 +36,7 @@ SettingsContentBase {
property alias currencySymbol: manageTokensView.currencySymbol

property int settingsSubSubsection
property string backButtonName: ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

within this property we only write to that property, so setting it from outside makes no sense. Therefore it should be readonly. The writable counterpart we can keep in d object and write to that one. And a top level we can expose readonly alias readonly property alias backButtonName: d.backButtonName.

@@ -328,8 +330,11 @@ StatusSectionLayout {
currencySymbol: root.sharedRootStore.currencyStore.currentCurrency
emojiPopup: root.emojiPopup
sectionTitle: settingsEntriesModel.getNameForSubsection(Constants.settingsSubsection.wallet)
backButtonName: d.backButtonName
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this assignment probably is not needed there

@@ -2139,6 +2139,8 @@ Item {
dismissedReceivedRequestContactsModel: contactsModelAdaptor.dimissedReceivedRequestContacts
isKeycardEnabled: featureFlagsStore.keycardEnabled

fnAddressWasShown: WalletStores.RootStore.addressWasShown
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in that case UI components should just emit addresssShown signal. And then we could have

onAddressShown: (address) => WalletStores.RootStore.addressWasShown(address)

It's cleaner and safer bc in signals we have explicitly specified, typed arguments.

@@ -12,6 +12,7 @@ import AppLayouts.Wallet.stores 1.0 as WalletStore
QtObject {
id: root

readonly property var isProduction: production
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not bool?

Comment on lines +50 to +53
currentVersion: getCurrentVersion()
gitCommit: getGitCommit()
statusGoVersion: getStatusGoVersion()
qtRuntimeVersion: qtRuntimeVersion()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to keep those methods now. Please remove them and assign values directly :)


// Here define the needed properties that access to `Context Properties`:
readonly property QtObject _internal: QtObject{
id: internal // Rename to `d` when cleanup done
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as it affects only that file, it should be easy to replace internal. with d. indeed.

@@ -73,8 +162,8 @@ QtObject {
id: d

readonly property var userProfileInst: userProfile
readonly property Connections mainModuleConnections: Connections {
target: root.mainModuleInst
readonly property Connections _settingRelatedMainModuleConnections: Connections {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of setting property names that are not used at all it's handy to change parent from QtObject to our utility QObject and then you can put children directly, no need to assign to property (Connections {}).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also valid and useful for top level component :)

readonly property alias contactShowcaseSocialLinksModel: contactShowcaseModels.adaptedSocialLinksSourceModel

readonly property SQUtils.QObject adaptors: SQUtils.QObject {
ProfileShowcaseModelAdapter {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that's intermediate step, but next we should move that adaptor outside the store.

@@ -285,6 +294,12 @@ Item {

onOpenGifPopupRequest: root.openGifPopupRequest(params, cbOnGifSelected, cbOnClose)

// Contacts related requests:
onChangeContactNicknameRequest: root.changeContactNicknameRequest(pubKey, nickname, displayName, isEdit)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basically qt 6 forces to use function-based syntax:

onChangeContactNicknameRequest: (pubKey, nickname, displayName, isEdit) => {
  root.changeContactNicknameRequest(pubKey, nickname, displayName, isEdit)
}

otherwise it prints warnings.

Alternative solution is to forward signals in Component.onCompleted:

Component.onCompleted: {
  removeTrustStatusRequest.connect(root.removeTrustStatusRequest)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[QML Architecture][Settings] Reorganize profileSectionStore and Inject Stores Directly into Top-Level Components
5 participants