ContactsStore: contacts model adaptor moved outside store

Closes #16549
This commit is contained in:
Michał Cieślak 2024-11-15 14:53:04 +01:00
parent cf1ee80dc2
commit 75b2364d99
13 changed files with 174 additions and 118 deletions

View File

@ -37,6 +37,7 @@ StackLayout {
required property WalletStore.WalletAssetsStore walletAssetsStore
required property SharedStores.CurrenciesStore currencyStore
property var mutualContactsModel
property var sectionItemModel
MembersModelAdaptor {
@ -154,8 +155,6 @@ StackLayout {
objectName: "chatViewComponent"
emojiPopup: root.emojiPopup
stickersPopup: root.stickersPopup
contactsStore: root.contactsStore
sharedRootStore: root.sharedRootStore
utilsStore: root.utilsStore
@ -164,6 +163,11 @@ StackLayout {
communitiesStore: root.communitiesStore
walletAssetsStore: root.walletAssetsStore
currencyStore: root.currencyStore
mutualContactsModel: root.mutualContactsModel
emojiPopup: root.emojiPopup
stickersPopup: root.stickersPopup
sendModalPopup: root.sendModalPopup
sectionItemModel: root.sectionItemModel
joinedMembersCount: membersModelAdaptor.joinedMembers.ModelCount.count

View File

@ -22,6 +22,9 @@ Item {
property alias searchButton: searchButton
property RootStore rootStore
property var mutualContactsModel
property var chatContentModule: root.rootStore.currentChatContentModule() || null
property var emojiPopup
property int padding: Theme.halfPadding
@ -346,7 +349,7 @@ Item {
usersStore: UsersStore {
usersModule: root.chatContentModule.usersModule
}
contactsModel: root.rootStore.contactsStore.myContactsModel
contactsModel: root.mutualContactsModel
onConfirmed: root.state = d.stateInfoButtonContent
onRejected: root.state = d.stateInfoButtonContent

View File

@ -48,6 +48,9 @@ StatusSectionLayout {
property CommunitiesStores.CommunitiesStore communitiesStore
required property WalletStore.WalletAssetsStore walletAssetsStore
required property SharedStores.CurrenciesStore currencyStore
property var mutualContactsModel
required property var sendModalPopup
property var sectionItemModel
property int joinedMembersCount
@ -231,8 +234,11 @@ StatusSectionLayout {
id: chatHeaderContentViewComponent
ChatHeaderContentView {
visible: !!root.rootStore.currentChatContentModule()
rootStore: root.rootStore
mutualContactsModel: root.mutualContactsModel
emojiPopup: root.emojiPopup
onSearchButtonClicked: root.openAppSearch()
onDisplayEditChannelPopup: {
Global.openPopup(contactColumnLoader.item.createChannelPopup, {

View File

@ -23,6 +23,9 @@ Page {
property SharedStores.UtilsStore utilsStore
property ChatStores.RootStore rootStore
property ChatStores.CreateChatPropertiesStore createChatPropertiesStore
property var mutualContactsModel
property var emojiPopup: null
property var stickersPopup: null
@ -64,7 +67,7 @@ Page {
rootStore: root.rootStore
utilsStore: root.utilsStore
contactsModel: root.rootStore.contactsStore.myContactsModel
contactsModel: root.mutualContactsModel
function createChat() {
if (model.count === 0) {
@ -180,7 +183,7 @@ Page {
StatusBaseText {
anchors.centerIn: parent
width: Math.min(553, parent.width - 2 * Theme.padding)
visible: root.rootStore.contactsStore.myContactsModel.ModelCount.empty
visible: root.mutualContacts.ModelCount.empty
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap

View File

@ -54,6 +54,11 @@ StatusSectionLayout {
required property CollectiblesStore collectiblesStore
required property SharedStores.CurrenciesStore currencyStore
property var mutualContactsModel
property var blockedContactsModel
property var pendingReceivedRequestContactsModel
property var pendingSentRequestContactsModel
required property bool isCentralizedMetricsEnabled
backButtonName: root.store.backButtonName
@ -108,7 +113,7 @@ StatusSectionLayout {
syncingBadgeCount: root.store.devicesStore.devicesModel.count -
root.store.devicesStore.devicesModel.pairedCount
messagingBadgeCount: root.store.contactsStore.receivedContactRequestsModel.count
messagingBadgeCount: root.pendingReceivedRequestContactsModel.ModelCount.count
}
headerBackground: AccountHeaderGradient {
@ -233,6 +238,11 @@ StatusSectionLayout {
utilsStore: root.utilsStore
sectionTitle: qsTr("Contacts")
contentWidth: d.contentWidth
mutualContactsModel: root.mutualContactsModel
blockedContactsModel: root.blockedContactsModel
pendingReceivedRequestContactsModel: root.pendingReceivedRequestContactsModel
pendingSentRequestContactsModel: root.pendingSentRequestContactsModel
}
}
@ -262,10 +272,11 @@ StatusSectionLayout {
sourceComponent: MessagingView {
implicitWidth: parent.width
implicitHeight: parent.height
messagingStore: root.store.messagingStore
sectionTitle: settingsEntriesModel.getNameForSubsection(Constants.settingsSubsection.messaging)
contactsStore: root.store.contactsStore
contentWidth: d.contentWidth
sectionTitle: settingsEntriesModel.getNameForSubsection(Constants.settingsSubsection.messaging)
requestsCount: root.pendingReceivedRequestContactsModel.ModelCount.count
messagingStore: root.store.messagingStore
}
}

View File

@ -1,81 +0,0 @@
import QtQml 2.15
import StatusQ 0.1
import StatusQ.Models 0.1
import StatusQ.Core.Utils 0.1
import utils 1.0
import SortFilterProxyModel 0.2
QObject {
id: root
/**
Expected model structure:
pubKey [string] - unique identifier of a member, e.g "0x3234235"
displayName [string] - member's chosen name
preferredDisplayName [string] - calculated member name according to priorities (eg: nickname has higher priority)
ensName [string] - member's ENS name
isEnsVerified [bool] - whether the ENS name was verified on chain
localNickname [string] - local nickname set by the current user
alias [string] - generated 3 word name
icon [string] - thumbnail image of the user
colorId [string] - generated color ID for the user's profile
colorHash [string] - generated color hash for the user's profile
onlineStatus [int] - the online status of the member
isContact [bool] - whether the user is a mutual contact or not
isVerified [bool] - wheter the user has been marked as verified or not
isUntrustworthy [bool] - wheter the user has been marked as untrustworthy or not
isBlocked [bool] - whether the user has been blocked or not
contactRequest [int] - state of the contact request that was sent
isCurrentUser [bool] - whether the contact is actually ourselves
lastUpdated [int64] - clock of when last the contact was updated
lastUpdatedLocally [int64] - clock of when last the contact was updated locally
bio [string] - contacts's chosen bio text
thumbnailImage [string] - local url of the user's thumbnail image
largeImage [string] - local url of the user's large image
isContactRequestReceived [bool] - whether we received a contact request from that user
isContactRequestSent [bool] - whether we send a contact request to that user
isRemoved [bool] - whether we removed that contact
trustStatus [int] - the trust status of the user as an enum
**/
property var allContacts
readonly property var mutualContacts: SortFilterProxyModel {
sourceModel: root.allContacts ?? null
filters: ValueFilter {
roleName: "isContact"
value: true
}
}
readonly property var blockedContacts: SortFilterProxyModel {
sourceModel: root.allContacts ?? null
filters: ValueFilter {
roleName: "isBlocked"
value: true
}
}
readonly property var pendingReceivedRequestContacts: SortFilterProxyModel {
sourceModel: root.allContacts ?? null
filters: ValueFilter {
roleName: "contactRequest"
value: Constants.ContactRequestState.Received
}
}
readonly property var pendingSentRequestContacts: SortFilterProxyModel {
sourceModel: root.allContacts ?? null
filters: ValueFilter {
roleName: "contactRequest"
value: Constants.ContactRequestState.Sent
}
}
}

View File

@ -18,21 +18,10 @@ QtObject {
}
}
property string myPublicKey: userProfile.pubKey
readonly property string myPublicKey: userProfile.pubKey
// contactsModel holds all available contacts
property var contactsModel: d.contactsModuleInst.contactsModel
readonly property var contactsModelAdaptor: ContactsModelAdaptor {
allContacts: contactsModel
}
signal resolvedENS(string resolvedPubKey, string resolvedAddress, string uuid)
property var myContactsModel: contactsModelAdaptor.mutualContacts
property var blockedContactsModel: contactsModelAdaptor.blockedContacts
property var receivedContactRequestsModel: contactsModelAdaptor.pendingReceivedRequestContacts
property var sentContactRequestsModel: contactsModelAdaptor.pendingSentRequestContacts
readonly property var contactsModel: d.contactsModuleInst.contactsModel
readonly property var showcasePublicKey: d.contactsModuleInst.showcasePublicKey

View File

@ -2,6 +2,7 @@ import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
@ -27,6 +28,11 @@ SettingsContentBase {
property ContactsStore contactsStore
property SharedStores.UtilsStore utilsStore
property var mutualContactsModel
property var blockedContactsModel
property var pendingReceivedRequestContactsModel
property var pendingSentRequestContactsModel
property alias searchStr: searchBox.text
property bool isPending: false
@ -116,16 +122,16 @@ SettingsContentBase {
id: pendingRequestsBtn
objectName: "ContactsView_PendingRequest_Button"
width: implicitWidth
enabled: root.contactsStore.receivedContactRequestsModel.count > 0 ||
root.contactsStore.sentContactRequestsModel.count > 0
enabled: !root.pendingReceivedRequestContactsModel.ModelCount.empty ||
!root.pendingSentRequestContactsModel.ModelCount.empty
text: qsTr("Pending Requests")
badge.value: root.contactsStore.receivedContactRequestsModel.count
badge.value: root.pendingReceivedRequestContactsModel.ModelCount.count
}
StatusTabButton {
id: blockedBtn
objectName: "ContactsView_Blocked_Button"
width: implicitWidth
enabled: root.contactsStore.blockedContactsModel.count > 0
enabled: !root.blockedContactsModel.ModelCount.empty
text: qsTr("Blocked")
}
}
@ -151,10 +157,11 @@ SettingsContentBase {
spacing: Theme.padding
ContactsListPanel {
id: verifiedContacts
Layout.fillWidth: true
title: qsTr("Trusted Contacts")
visible: !noFriendsItem.visible && count > 0
contactsModel: root.contactsStore.myContactsModel
contactsModel: root.mutualContactsModel
searchString: searchBox.text
onOpenContactContextMenu: root.openContextMenu(contactsModel, publicKey)
panelUsage: Constants.contactsPanelUsage.verifiedMutualContacts
@ -165,10 +172,11 @@ SettingsContentBase {
ContactsListPanel {
id: mutualContacts
Layout.fillWidth: true
visible: !noFriendsItem.visible && count > 0
title: qsTr("Contacts")
contactsModel: root.contactsStore.myContactsModel
contactsModel: root.mutualContactsModel
searchString: searchBox.text
onOpenContactContextMenu: root.openContextMenu(contactsModel, publicKey)
panelUsage: Constants.contactsPanelUsage.mutualContacts
@ -180,9 +188,11 @@ SettingsContentBase {
Item {
id: noFriendsItem
Layout.fillWidth: true
Layout.preferredHeight: visible ? (root.contentHeight - (2*searchBox.height) - contactsTabBar.height - contactsTabBar.anchors.topMargin) : 0
visible: root.contactsStore.myContactsModel.count === 0
visible: root.mutualContactsModel.ModelCount.empty
NoFriendsRectangle {
anchors.centerIn: parent
text: qsTr("You don't have any contacts yet")
@ -204,13 +214,14 @@ SettingsContentBase {
}
ContactsListPanel {
id: receivedRequests
objectName: "receivedRequests_ContactsListPanel"
Layout.fillWidth: true
title: qsTr("Received")
searchString: searchBox.text
visible: count > 0
onOpenContactContextMenu: root.openContextMenu(contactsModel, publicKey)
contactsModel: root.contactsStore.receivedContactRequestsModel
contactsModel: root.pendingReceivedRequestContactsModel
panelUsage: Constants.contactsPanelUsage.receivedContactRequest
onSendMessageActionTriggered: {
@ -228,23 +239,26 @@ SettingsContentBase {
ContactsListPanel {
id: sentRequests
objectName: "sentRequests_ContactsListPanel"
Layout.fillWidth: true
title: qsTr("Sent")
searchString: searchBox.text
visible: count > 0
onOpenContactContextMenu: root.openContextMenu(contactsModel, publicKey)
contactsModel: root.contactsStore.sentContactRequestsModel
contactsModel: root.pendingSentRequestContactsModel
panelUsage: Constants.contactsPanelUsage.sentContactRequest
}
}
// BLOCKED
ContactsListPanel {
id: blockedContacts
Layout.fillWidth: true
searchString: searchBox.text
onOpenContactContextMenu: root.openContextMenu(contactsModel, publicKey)
contactsModel: root.contactsStore.blockedContactsModel
contactsModel: root.blockedContactsModel
panelUsage: Constants.contactsPanelUsage.blockedContacts
visible: (stackLayout.currentIndex === 2)
onVisibleChanged: {

View File

@ -24,7 +24,8 @@ SettingsContentBase {
id: root
property MessagingStore messagingStore
property ContactsStore contactsStore
property alias requestsCount: contactRequestsIndicator.requestsCount
ColumnLayout {
id: generalColumn
@ -75,10 +76,12 @@ SettingsContentBase {
// CONTACTS SECTION
StatusContactRequestsIndicatorListItem {
id: contactRequestsIndicator
objectName: "MessagingView_ContactsListItem_btn"
Layout.fillWidth: true
title: qsTr("Contacts, Requests, and Blocked Users")
requestsCount: root.contactsStore.receivedContactRequestsModel.count
onClicked: Global.changeAppSectionBySectionType(Constants.appSection.profile,
Constants.settingsSubsection.contacts)
}

View File

@ -46,6 +46,7 @@ import AppLayouts.Wallet.popups 1.0 as WalletPopups
import AppLayouts.Wallet.stores 1.0 as WalletStores
import AppLayouts.stores 1.0 as AppStores
import mainui.adaptors 1.0
import mainui.activitycenter.stores 1.0
import mainui.activitycenter.popups 1.0
@ -104,6 +105,12 @@ Item {
// set from main.qml
property var sysPalette
ContactsModelAdaptor {
id: contactsModelAdaptor
allContacts: appMain.profileSectionStore.contactsStore.contactsModel
}
// Central UI point for managing app toasts:
ToastsManager {
id: toastsManager
@ -431,6 +438,9 @@ Item {
walletCollectiblesStore: appMain.walletCollectiblesStore
buyCryptoStore: appMain.buyCryptoStore
networkConnectionStore: appMain.networkConnectionStore
mutualContactsModel: contactsModelAdaptor.mutualContacts
isDevBuild: !production
onOpenExternalLink: globalConns.onOpenLink(link)
@ -906,8 +916,8 @@ Item {
checked: model.active
badge.value: model.notificationsCount
badge.visible: model.sectionType === Constants.appSection.profile &&
appMain.rootStore.contactStore.receivedContactRequestsModel.count ? true // pending CR request
: model.hasNotification
(contactsModelAdaptor.pendingReceivedRequestContacts.ModelCount.empty ? // pending contact request
model.hasNotification : true)
badge.border.color: hovered ? Theme.palette.statusBadge.hoverBorderColor : Theme.palette.statusBadge.borderColor
badge.border.width: 2
onClicked: {
@ -1395,6 +1405,8 @@ Item {
stickersPopup: statusStickersPopupLoader.item
sendViaPersonalChatEnabled: featureFlagsStore.sendViaPersonalChatEnabled && appMain.networkConnectionStore.sendBuyBridgeEnabled
mutualContactsModel: contactsModelAdaptor.mutualContacts
onProfileButtonClicked: {
Global.changeAppSectionBySectionType(Constants.appSection.profile);
}
@ -1467,6 +1479,11 @@ Item {
isCentralizedMetricsEnabled: appMain.isCentralizedMetricsEnabled
settingsSubSubsection: profileLoader.settingsSubSubsection
mutualContactsModel: contactsModelAdaptor.mutualContacts
blockedContactsModel: contactsModelAdaptor.blockedContacts
pendingReceivedRequestContactsModel: contactsModelAdaptor.pendingReceivedRequestContacts
pendingSentRequestContactsModel: contactsModelAdaptor.pendingSentRequestContacts
Binding on settingsSubsection {
value: profileLoader.settingsSubsection
}
@ -1560,6 +1577,8 @@ Item {
walletAssetsStore: appMain.walletAssetsStore
currencyStore: appMain.currencyStore
mutualContactsModel: contactsModelAdaptor.mutualContacts
onProfileButtonClicked: {
Global.changeAppSectionBySectionType(Constants.appSection.profile);
}
@ -1600,6 +1619,9 @@ Item {
chatCommunitySectionModule: appMain.rootStore.mainModuleInst.getChatSectionModule()
}
createChatPropertiesStore: appMain.createChatPropertiesStore
mutualContactsModel: contactsModelAdaptor.mutualContacts
emojiPopup: statusEmojiPopup.item
stickersPopup: statusStickersPopupLoader.item
}

View File

@ -52,6 +52,9 @@ QtObject {
property WalletStores.CollectiblesStore walletCollectiblesStore
property NetworkConnectionStore networkConnectionStore
property WalletStores.BuyCryptoStore buyCryptoStore
property var mutualContactsModel
property bool isDevBuild
signal openExternalLink(string link)
@ -473,7 +476,7 @@ QtObject {
InviteFriendsToCommunityPopup {
rootStore: root.rootStore
contactsModel: root.rootStore.contactStore.myContactsModel
contactsModel: root.mutualContactsModel
onClosed: destroy()
}

View File

@ -0,0 +1,78 @@
import QtQml 2.15
import StatusQ.Core.Utils 0.1
import utils 1.0
import SortFilterProxyModel 0.2
QObject {
id: root
/**
Expected model structure:
pubKey [string] - unique identifier of a member, e.g "0x3234235"
displayName [string] - member's chosen name
preferredDisplayName [string] - calculated member name according to priorities (eg: nickname has higher priority)
ensName [string] - member's ENS name
isEnsVerified [bool] - whether the ENS name was verified on chain
localNickname [string] - local nickname set by the current user
alias [string] - generated 3 word name
icon [string] - thumbnail image of the user
colorId [string] - generated color ID for the user's profile
colorHash [string] - generated color hash for the user's profile
onlineStatus [int] - the online status of the member
isContact [bool] - whether the user is a mutual contact or not
isVerified [bool] - wheter the user has been marked as verified or not
isUntrustworthy [bool] - wheter the user has been marked as untrustworthy or not
isBlocked [bool] - whether the user has been blocked or not
contactRequest [int] - state of the contact request that was sent
isCurrentUser [bool] - whether the contact is actually ourselves
lastUpdated [int64] - clock of when last the contact was updated
lastUpdatedLocally [int64] - clock of when last the contact was updated locally
bio [string] - contacts's chosen bio text
thumbnailImage [string] - local url of the user's thumbnail image
largeImage [string] - local url of the user's large image
isContactRequestReceived [bool] - whether we received a contact request from that user
isContactRequestSent [bool] - whether we send a contact request to that user
isRemoved [bool] - whether we removed that contact
trustStatus [int] - the trust status of the user as an enum
**/
property var allContacts
readonly property var mutualContacts: SortFilterProxyModel {
sourceModel: root.allContacts ?? null
filters: ValueFilter {
roleName: "isContact"
value: true
}
}
readonly property var blockedContacts: SortFilterProxyModel {
sourceModel: root.allContacts ?? null
filters: ValueFilter {
roleName: "isBlocked"
value: true
}
}
readonly property var pendingReceivedRequestContacts: SortFilterProxyModel {
sourceModel: root.allContacts ?? null
filters: ValueFilter {
roleName: "contactRequest"
value: Constants.ContactRequestState.Received
}
}
readonly property var pendingSentRequestContacts: SortFilterProxyModel {
sourceModel: root.allContacts ?? null
filters: ValueFilter {
roleName: "contactRequest"
value: Constants.ContactRequestState.Sent
}
}
}

View File

@ -0,0 +1 @@
ContactsModelAdaptor 1.0 ContactsModelAdaptor.qml