# Introduction This section describes the Architecture & stack, documents APIs & describes how to implement specific things such as functionality that might need to be in a threadpool, adding new sections to the app, etc... # QML UI **This archictecture change is NOT for desktop as a whole, it's just for (existing) QML code.** In order to maintain a clean UI structure and make the UI re-usable and scalable, the [QML Core UI](https://luxoft.github.io/qml-coreui/) architecture is adapted. So far, Wallet2 implements it and the rest sections will follow. Each section of the UI will be divided in views, panels and stores and if necessary controls and popups. ![](https://i.imgur.com/gAKSiMC.png) ### Controls The controls are smaller parts of the UI where no access to the backend is needed and they primarily serve user interactions. For example in a music application, a control could be a play or pause button. All controls of Wallet2 can be found [here](https://github.com/status-im/status-desktop/tree/master/ui/app/AppLayouts/WalletV2/controls) and in general consist of the following files: ``` CollectibleDetailsHeader.qml HeaderButton.qml SavedAddressesError.qml SeedAccountDetailsDelegate.qml WalletButton.qml ``` Having a look at the UI, the WalletButton for example is used in wallet's 2 footer (marked in red): ![](https://i.imgur.com/nYQu8Wg.png) When it comes to [code](https://github.com/status-im/status-desktop/blob/master/ui/app/AppLayouts/WalletV2/controls/WalletButton.qml) it's a simple component consisting of other primitive QML types like Rectangle etc. A control usually needs nothing from the backend, however if there is a case that it needs to access some property from it, then this can be done by property bindings. For example in [SavedAddressesError](https://github.com/status-im/status-desktop/blob/master/ui/app/AppLayouts/WalletV2/controls/SavedAddressesError.qml) the text property of the `StatusBaseText` is exposed. Then in SavedAddressesView, line 229 where SavedAddressesError is instantiated, we see the assignment to it `text: root.store.getSavedAddressErrorText(SavedAddressesView, root.error)` A control can be also something a bit more complex than a single button like for example a list delegate. The main point here is to keep the smallest parts of the UI that help build the bigger parts and are only supposed to provide some basic functionallity to the application. ### Panels The panels are basically a collection of controls and/or other primitive QML types as well as other panels, that represent a smaller section of the UI and similar to the controls, need no access to backend but they serve only to provide certain functionality to the application. For example in wallet2, the [panels](https://github.com/status-im/status-desktop/tree/master/ui/app/AppLayouts/WalletV2/panels) are: ``` AccountNotFoundPanel.qml NetworkFilterPanel.qml NetworkSelectPanel.qml PKeyAccountDetailsPanel.qml SeedPhraseBackupWarningPanel.qml WalletFooterPanel.qml WalletHeaderPanel.qml ``` In the picture above the `WalletFooterPanel.qml` and `WalletHeaderPanel.qml` are showed in the wallet2 UI (marked in red): ![](https://i.imgur.com/HwfkOpv.png) If we have a look at [WalletFooterPanel](https://github.com/status-im/status-desktop/blob/master/ui/app/AppLayouts/WalletV2/panels/WalletFooterPanel.qml) consists of 3 WalletButtons and a Rectangle. On the other hand, the [WalletHeaderPanel](https://github.com/status-im/status-desktop/blob/master/ui/app/AppLayouts/WalletV2/panels/WalletHeaderPanel.qml) consists of `StyledText` controls, a `Rectangle`, a `StatusExpandableAddress` component as well as another panel, `NetworkSelectPanel`. Similar to the controls, the main point here is to keep the smallest parts of the UI that help build the bigger parts and in this case should get into joing with other controls or panels in order to provide some specific to the app functionallity without accessing the backend. If in any case access to some property of the backend is needed for reading purposes, the property bindings should be used. For example, in WalletHeaderPanel, properties *qrCode*, *accountsModel*, *currentAccount*, *enabledNetworksModel*, *allNetworksModel* are exposed and set in WalletV2Layout where WalletHeaderPanel is instantiated. Other than this if there is the need to perform some action in any of the user interactions (for example when the "All networks" button in the upper right side is pressed) then the panel can emit signals so that their handlers are implemented in the panel's instance. In the "All networks" button case, WalletHeaderPanel emits the signal `toggleNetwork(int chainId)` and in WalletV2Layout line 104, this signal is implemented: ``` onToggleNetwork: { walletView.store.walletModelV2Inst.networksView.toggleNetwork(chainId) } ``` ### Popups The Popups are just specific to the application section popups. In the wallet2 [popups](https://github.com/status-im/status-desktop/tree/master/ui/app/AppLayouts/WalletV2/popups) are: ``` AddAccountPopup.qml AddEditSavedAddressPopup.qml CollectibleModal.qml CryptoServicesModal.qml NetworkSelectPopup.qml ShareModal.qml SignPhraseModal.qml ``` Those are just regular QtQuickControls 2 based popups and can consist of everything, from QML primitive types and controls to panels and views. They shall also have access to the backend if needed, by using a property binding to either an entire store or a property of the store - this depends on whether the popup needs access to multiple properties/functions from the store or just one. For example the [AddAccountPopup](https://github.com/status-im/status-desktop/blob/master/ui/app/AppLayouts/WalletV2/popups/AddAccountPopup.qml) accesses the entire store, as it makes use of various properties and functions from it, but the [CryptoServicesModal](https://github.com/status-im/status-desktop/blob/master/ui/app/AppLayouts/WalletV2/popups/CryptoServicesModal.qml) only needs access to `walletV2Model` so it follows the way of panels to only get assigned this specific property, see in its instance in WalletFooterPanel line 58 where the assignment is done `walletV2Model: walletFooterRoot.walletV2Model`. ### Stores The stores are non visual Qt objects consisting of a collection of properties and functions that access the backend. These objects are the only ones that can directly talk to the backend and serve as an interface to the rest of the UI parts (panels, views popups, etc). The RootStore is usually the main store of the application section and contains all logic common to the entire application or parts of it. Multiple stores can be created if one part of the application needs extensive and/or exclusive implementation and these sub-stores can be instantiated in the RootStore and referenced from it. For example in wallet2 the [stores](https://github.com/status-im/status-desktop/tree/master/ui/app/AppLayouts/WalletV2/stores) are: ``` CollectiblesStore.qml RootStore.qml ``` The [CollectiblesStore](https://github.com/status-im/status-desktop/blob/master/ui/app/AppLayouts/Wallet/stores/CollectiblesStore.qml) is instantiated in [RootStore](https://github.com/status-im/status-desktop/blob/master/ui/app/AppLayouts/Wallet/stores/RootStore.qml) as property `property CollectiblesStore collectiblesStore: CollectiblesStore { }` and can be referenced from there as follows `root.store.collectiblesStore` in whichever view that wants to access it and has already access to the main store. Of course if only access to the CollectiblesStore is needed then the view's main store property can be bound exclusively to the CollectiblesStore. Usually there is a single instance of the RootStore in the application's main entry point and the rest of the application parts are gaining access to it via property bindings. In wallet2 that is happening in Wallet2Layout in line 27, `property RootStore store: RootStore { }`. The rest of the views, like for example LeftTabView have their own internal `property var store` properties that are bound to the Wallet2Layout's store. *example Wallet2Layout.qml line 65* ``` leftPanel: LeftTabView { id: leftTab anchors.fill: parent store: walletView.store ``` Stores being the only place with access to backend services doesn't mean backend objects should be used freely all over the place in Store files. The convention is to declare *backendObjectName*Inst properties on the top of the file: `property var globalUtilsInst: globalUtils` This approach has various advantages: - maintenance cost: when backend object is renamed, qml adaptation is easier - increased readability: it is easy to spot which backend services are used by the Store ### Views The views are more complex components consisting of QML primitive types, controls, panels as well as other views. Those are the only UI elements that can access the store via property bindings. For example the LeftTabView, described in the [Stores](https://hackmd.io/Enn35HjGSGy6BY0sYOu5PQ?view#Stores) sections above. In wallet2 the [views](https://github.com/status-im/status-desktop/tree/master/ui/app/AppLayouts/WalletV2/views) are: ``` assets collectibles ActivityView.qml AddAccountView.qml AssetsView.qml CollectiblesView.qml LeftTabView.qml PositionsView.qml SavedAddressesView.qml SeedAddAccountView.qml SettingsTabView.qml StackBaseView.qml StackDetailBase.qml ``` The [assets](https://github.com/status-im/status-desktop/tree/master/ui/app/AppLayouts/WalletV2/views/assets) folder contains other views specific to AssetsView and respectively [collectibles](https://github.com/status-im/status-desktop/tree/master/ui/app/AppLayouts/WalletV2/views/collectibles) other views specific to CollectiblesView. This is done when more than one files referring to the same feature and can be grouped in order to keep the folder structure as clean and readable as possible. In the image below the LeftTabView is represented in red and the AssetsView in orange in the UI. ![](https://i.imgur.com/CCyj17R.png) As all views, both LeftTabView and AssetsView are getting access to the store in Wallet2Layout where they're instantiated. ### Application section main file Finally the application section (eg. wallet2) should have a main strarting point where all the above come together. In wallet2 this is [WalletV2Layout](https://github.com/status-im/status-desktop/blob/master/ui/app/AppLayouts/WalletV2/WalletV2Layout.qml). In there the UI layout is defined as well as the store instance and of course the components that should be visible when opened.