refactor(contacts): refactor 5 contact models into one and filter in QML

Fixes #16549

Refactors the 5 types of contact models (all, mutuals, banned, received and sent) into only the `allContacts` and use an Adaptor on the QML side to filter into the needed models.
This cleans the Nim side a lot and makes applying updates to the contacts' model way simpler.

rthh
This commit is contained in:
Jonathan Rainville 2024-10-29 15:48:59 -04:00 committed by Michał Cieślak
parent 1c255175ab
commit 9315dd26e0
5 changed files with 114 additions and 173 deletions

View File

@ -105,8 +105,7 @@ proc buildModel(self: Module, model: Model, group: ContactsGroup) =
var items: seq[UserItem]
let contacts = self.controller.getContacts(group)
for c in contacts:
let item = self.createItemFromPublicKey(c.id)
items.add(item)
items.add(self.createItemFromPublicKey(c.id))
model.addItems(items)
@ -123,13 +122,6 @@ method viewDidLoad*(self: Module) =
method onContactsLoaded*(self: Module) =
self.buildModel(self.view.contactsModel(), ContactsGroup.AllKnownContacts)
self.buildModel(self.view.myMutualContactsModel(), ContactsGroup.MyMutualContacts)
self.buildModel(self.view.blockedContactsModel(), ContactsGroup.BlockedContacts)
self.buildModel(self.view.receivedContactRequestsModel(), ContactsGroup.IncomingPendingContactRequests)
self.buildModel(self.view.sentContactRequestsModel(), ContactsGroup.OutgoingPendingContactRequests)
# Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
# self.buildModel(self.view.receivedButRejectedContactRequestsModel(), ContactsGroup.IncomingRejectedContactRequests)
# self.buildModel(self.view.sentButRejectedContactRequestsModel(), ContactsGroup.IncomingRejectedContactRequests)
method getModuleAsVariant*(self: Module): QVariant =
return self.viewVariant
@ -169,35 +161,15 @@ method removeContact*(self: Module, publicKey: string) =
method changeContactNickname*(self: Module, publicKey: string, nickname: string) =
self.controller.changeContactNickname(publicKey, nickname)
# TODO rename this function
proc addItemToAppropriateModel(self: Module, item: UserItem) =
if(singletonInstance.userProfile.getPubKey() == item.pubKey):
if singletonInstance.userProfile.getPubKey() == item.pubKey:
return
let contact = self.controller.getContact(item.pubKey())
self.view.contactsModel().addItem(item)
if contact.isBlocked():
self.view.blockedContactsModel().addItem(item)
return
case contact.contactRequestState:
of ContactRequestState.Received:
self.view.receivedContactRequestsModel().addItem(item)
of ContactRequestState.Sent:
self.view.sentContactRequestsModel().addItem(item)
of ContactRequestState.Mutual:
self.view.myMutualContactsModel().addItem(item)
else:
return
proc removeItemWithPubKeyFromAllModels(self: Module, publicKey: string) =
self.view.contactsModel().removeItemById(publicKey)
self.view.myMutualContactsModel().removeItemById(publicKey)
self.view.receivedContactRequestsModel().removeItemById(publicKey)
self.view.sentContactRequestsModel().removeItemById(publicKey)
# Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
# self.view.receivedButRejectedContactRequestsModel().removeItemById(publicKey)
# self.view.sentButRejectedContactRequestsModel().removeItemById(publicKey)
self.view.blockedContactsModel().removeItemById(publicKey)
proc removeIfExistsAndAddToAppropriateModel(self: Module, publicKey: string) =
self.removeItemWithPubKeyFromAllModels(publicKey)
@ -221,29 +193,20 @@ method contactUpdated*(self: Module, publicKey: string) =
method contactsStatusUpdated*(self: Module, statusUpdates: seq[StatusUpdateDto]) =
for s in statusUpdates:
let status = toOnlineStatus(s.statusType)
self.view.myMutualContactsModel().setOnlineStatus(s.publicKey, status)
self.view.contactsModel().setOnlineStatus(s.publicKey, status)
self.view.contactsModel().setOnlineStatus(s.publicKey, toOnlineStatus(s.statusType))
method contactNicknameChanged*(self: Module, publicKey: string) =
let contactDetails = self.controller.getContactDetails(publicKey)
let displayName = contactDetails.dto.displayName
let ensName = contactDetails.dto.name
let localNickname = contactDetails.dto.localNickname
self.view.contactsModel().setName(publicKey, displayName, ensName, localNickname)
self.view.myMutualContactsModel().setName(publicKey, displayName, ensName, localNickname)
self.view.receivedContactRequestsModel().setName(publicKey, displayName, ensName, localNickname)
self.view.sentContactRequestsModel().setName(publicKey, displayName, ensName, localNickname)
# Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
# self.view.receivedButRejectedContactRequestsModel().setName(publicKey, displayName, ensName, localNickname)
# self.view.sentButRejectedContactRequestsModel().setName(publicKey, displayName, ensName, localNickname)
self.view.blockedContactsModel().setName(publicKey, displayName, ensName, localNickname)
self.view.contactsModel().setName(
publicKey,
contactDetails.dto.displayName,
contactDetails.dto.name,
contactDetails.dto.localNickname,
)
method contactTrustStatusChanged*(self: Module, publicKey: string, trustStatus: TrustStatus) =
self.view.contactsModel().updateTrustStatus(publicKey, trustStatus)
self.view.myMutualContactsModel().updateTrustStatus(publicKey, trustStatus)
self.view.blockedContactsModel().updateTrustStatus(publicKey, trustStatus)
method markAsTrusted*(self: Module, publicKey: string): void =
self.controller.markAsTrusted(publicKey)

View File

@ -1,6 +1,6 @@
import NimQml
import ../../../shared_models/user_model
import ../../../shared_models/[user_model, user_item]
import ./io_interface
import models/showcase_contact_generic_model
@ -13,19 +13,6 @@ QtObject:
delegate: io_interface.AccessInterface
contactsModel: Model
contactsModelVariant: QVariant
myMutualContactsModel: Model
myMutualContactsModelVariant: QVariant
blockedContactsModel: Model
blockedContactsModelVariant: QVariant
receivedContactRequestsModel: Model
receivedContactRequestsModelVariant: QVariant
sentContactRequestsModel: Model
sentContactRequestsModelVariant: QVariant
# Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
# receivedButRejectedContactRequestsModel: Model
# receivedButRejectedContactRequestsModelVariant: QVariant
# sentButRejectedContactRequestsModel: Model
# sentButRejectedContactRequestsModelVariant: QVariant
showcaseContactCommunitiesModel: ShowcaseContactGenericModel
showcaseContactCommunitiesModelVariant: QVariant
showcaseContactAccountsModel: ShowcaseContactAccountModel
@ -41,19 +28,6 @@ QtObject:
proc delete*(self: View) =
self.contactsModel.delete
self.contactsModelVariant.delete
self.myMutualContactsModel.delete
self.myMutualContactsModelVariant.delete
self.blockedContactsModel.delete
self.blockedContactsModelVariant.delete
self.receivedContactRequestsModel.delete
self.receivedContactRequestsModelVariant.delete
self.sentContactRequestsModel.delete
self.sentContactRequestsModelVariant.delete
# Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
# self.receivedButRejectedContactRequestsModel.delete
# self.receivedButRejectedContactRequestsModelVariant.delete
# self.sentButRejectedContactRequestsModelVariant.delete
# self.sentButRejectedContactRequestsModel.delete
self.showcaseContactCommunitiesModel.delete
self.showcaseContactCommunitiesModelVariant.delete
self.showcaseContactAccountsModel.delete
@ -72,19 +46,6 @@ QtObject:
result.delegate = delegate
result.contactsModel = newModel()
result.contactsModelVariant = newQVariant(result.contactsModel)
result.myMutualContactsModel = newModel()
result.myMutualContactsModelVariant = newQVariant(result.myMutualContactsModel)
result.blockedContactsModel = newModel()
result.blockedContactsModelVariant = newQVariant(result.blockedContactsModel)
result.receivedContactRequestsModel = newModel()
result.receivedContactRequestsModelVariant = newQVariant(result.receivedContactRequestsModel)
result.sentContactRequestsModel = newModel()
result.sentContactRequestsModelVariant = newQVariant(result.sentContactRequestsModel)
# Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
# result.receivedButRejectedContactRequestsModel = newModel()
# result.receivedButRejectedContactRequestsModelVariant = newQVariant(result.receivedButRejectedContactRequestsModel)
# result.sentButRejectedContactRequestsModel = newModel()
# result.sentButRejectedContactRequestsModelVariant = newQVariant(result.sentButRejectedContactRequestsModel)
result.showcaseContactCommunitiesModel = newShowcaseContactGenericModel()
result.showcaseContactCommunitiesModelVariant = newQVariant(result.showcaseContactCommunitiesModel)
result.showcaseContactAccountsModel = newShowcaseContactAccountModel()
@ -102,25 +63,6 @@ QtObject:
proc contactsModel*(self: View): Model =
return self.contactsModel
proc myMutualContactsModel*(self: View): Model =
return self.myMutualContactsModel
proc blockedContactsModel*(self: View): Model =
return self.blockedContactsModel
proc receivedContactRequestsModel*(self: View): Model =
return self.receivedContactRequestsModel
proc sentContactRequestsModel*(self: View): Model =
return self.sentContactRequestsModel
# Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
# proc receivedButRejectedContactRequestsModel*(self: View): Model =
# return self.receivedButRejectedContactRequestsModel
# proc sentButRejectedContactRequestsModel*(self: View): Model =
# return self.sentButRejectedContactRequestsModel
proc contactsModelChanged(self: View) {.signal.}
proc getContactsModel(self: View): QVariant {.slot.} =
return self.contactsModelVariant
@ -128,59 +70,13 @@ QtObject:
read = getContactsModel
notify = contactsModelChanged
proc myMutualContactsModelChanged(self: View) {.signal.}
proc getMyMutualContactsModel(self: View): QVariant {.slot.} =
return self.myMutualContactsModelVariant
QtProperty[QVariant] myMutualContactsModel:
read = getMyMutualContactsModel
notify = myMutualContactsModelChanged
proc blockedContactsModelChanged(self: View) {.signal.}
proc getBlockedContactsModel(self: View): QVariant {.slot.} =
return self.blockedContactsModelVariant
QtProperty[QVariant] blockedContactsModel:
read = getBlockedContactsModel
notify = blockedContactsModelChanged
proc receivedContactRequestsModelChanged(self: View) {.signal.}
proc getReceivedContactRequestsModel(self: View): QVariant {.slot.} =
return self.receivedContactRequestsModelVariant
QtProperty[QVariant] receivedContactRequestsModel:
read = getReceivedContactRequestsModel
notify = receivedContactRequestsModelChanged
proc sentContactRequestsModelChanged(self: View) {.signal.}
proc getSentContactRequestsModel(self: View): QVariant {.slot.} =
return self.sentContactRequestsModelVariant
QtProperty[QVariant] sentContactRequestsModel:
read = getSentContactRequestsModel
notify = sentContactRequestsModelChanged
proc contactInfoRequestFinished(self: View, publicKey: string, ok: bool) {.signal.}
# Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
# proc receivedButRejectedContactRequestsModelChanged(self: View) {.signal.}
# proc getReceivedButRejectedContactRequestsModel(self: View): QVariant {.slot.} =
# return self.receivedButRejectedContactRequestsModelVariant
# QtProperty[QVariant] receivedButRejectedContactRequestsModel:
# read = getReceivedButRejectedContactRequestsModel
# notify = receivedButRejectedContactRequestsModelChanged
# proc sentButRejectedContactRequestsModelChanged(self: View) {.signal.}
# proc getSentButRejectedContactRequestsModel(self: View): QVariant {.slot.} =
# return self.sentButRejectedContactRequestsModelVariant
# QtProperty[QVariant] sentButRejectedContactRequestsModel:
# read = getSentButRejectedContactRequestsModel
# notify = sentButRejectedContactRequestsModelChanged
proc isMyMutualContact*(self: View, publicKey: string): bool {.slot.} =
return self.myMutualContactsModel.isContactWithIdAdded(publicKey)
proc isBlockedContact*(self: View, publicKey: string): bool {.slot.} =
return self.blockedContactsModel.isContactWithIdAdded(publicKey)
proc hasPendingContactRequest*(self: View, publicKey: string): bool {.slot.} =
return self.sentContactRequestsModel.isContactWithIdAdded(publicKey)
if not self.contactsModel.isContactWithIdAdded(publicKey):
return false
let userItem = self.contactsModel.getItemByPubKey(publicKey)
return userItem.contactRequest == ContactRequest.Sent
proc sendContactRequest*(self: View, publicKey: string, message: string) {.slot.} =
self.delegate.sendContactRequest(publicKey, message)

View File

@ -165,8 +165,10 @@ QtObject:
of ModelRole.IsCurrentUser:
result = newQVariant(item.isCurrentUser)
of ModelRole.DefaultDisplayName:
# TODO this is the same as preferred name
result = newQVariant(item.defaultDisplayName)
of ModelRole.OptionalName:
# This seems useless
result = newQVariant(item.optionalName)
of ModelRole.LastUpdated:
result = newQVariant(item.lastUpdated)
@ -183,6 +185,7 @@ QtObject:
of ModelRole.IsContactRequestSent:
result = newQVariant(item.isContactRequestSent)
of ModelRole.IsSyncing:
# TODO not sure what that is and it's never used
result = newQVariant(item.isSyncing)
of ModelRole.IsRemoved:
result = newQVariant(item.isRemoved)
@ -237,11 +240,16 @@ QtObject:
proc findIndexByPubKey(self: Model, pubKey: string): int =
for i in 0 ..< self.items.len:
if(self.items[i].pubKey == pubKey):
if self.items[i].pubKey == pubKey:
return i
return -1
proc getItemByPubKey*(self: Model, pubKey: string): UserItem =
for item in self.items:
if item.pubKey == pubKey:
return item
proc removeItemWithIndex(self: Model, index: int) =
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
@ -254,7 +262,6 @@ QtObject:
self.itemChanged(pubKey)
# TODO: rename to `containsItem`
proc isContactWithIdAdded*(self: Model, id: string): bool =
return self.findIndexByPubKey(id) != -1
@ -384,6 +391,3 @@ QtObject:
# TODO: rename me to getItemsAsPubkeys
proc getItemIds*(self: Model): seq[string] =
return self.items.map(i => i.pubKey)
proc containsItemWithPubKey*(self: Model, pubKey: string): bool =
return self.findIndexByPubKey(pubKey) != -1

View File

@ -0,0 +1,81 @@
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

@ -15,10 +15,15 @@ QtObject {
// contactsModel holds all available contacts
property var contactsModel: contactsModule.contactsModel
property var myContactsModel: contactsModule.myMutualContactsModel
property var blockedContactsModel: contactsModule.blockedContactsModel
property var receivedContactRequestsModel: contactsModule.receivedContactRequestsModel
property var sentContactRequestsModel: contactsModule.sentContactRequestsModel
readonly property var contactsModelAdaptor: ContactsModelAdaptor {
allContacts: contactsModel
}
property var myContactsModel: contactsModelAdaptor.mutualContacts
property var blockedContactsModel: contactsModelAdaptor.blockedContacts
property var receivedContactRequestsModel: contactsModelAdaptor.pendingReceivedRequestContacts
property var sentContactRequestsModel: contactsModelAdaptor.pendingSentRequestContacts
readonly property var showcasePublicKey: contactsModule.showcasePublicKey
@ -51,14 +56,6 @@ QtObject {
return root.globalUtilsInst.generateAlias(pubKey)
}
function isMyMutualContact(pubKey) {
return root.contactsModule.isMyMutualContact(pubKey)
}
function isBlockedContact(pubKey) {
return root.contactsModule.isBlockedContact(pubKey)
}
function hasPendingContactRequest(pubKey) {
return root.contactsModule.hasPendingContactRequest(pubKey)
}