Refactor contacts models to have a single model, remove useless properties and improve updating (#16667)

* 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.

* chore(contacts): remove useless and duplicated contact properties

OptionalName and isSyncing were never used.
DefaultDisplayName was not really used and is actually a duplication of preferredDisplayName, so I replaced the limited usages of DefaultDisplayName by preferredDisplayName

* refactor(contacts): improve updates by not removing and re-adding

We used to update contact items by removing them from the models and re-adding them. This is highly inefficient.
Instead, the proper way is to update only the values that changed.

* user_model: onItemChanged signal removed

* user_model: sorting by online status no longer needed on nim side

* Chat/RootStore: contactsModel property removed

* ContactsStore encapsulation improved

* ContactsStore: contacts model adaptor moved outside store

---------

Co-authored-by: Michał Cieślak <michalcieslak@status.im>
This commit is contained in:
Jonathan Rainville 2024-11-28 09:15:34 -05:00 committed by GitHub
parent f1395a3a0a
commit 50132c5a0e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
34 changed files with 391 additions and 437 deletions

View File

@ -331,7 +331,7 @@ method toggleReactionFromOthers*(self: Module, messageId: string, emojiId: int,
if(item.shouldAddReaction(emojiIdAsEnum, reactionFrom)):
let userWhoAddedThisReaction = self.controller.getContactById(reactionFrom)
self.view.pinnedModel().addReaction(messageId, emojiIdAsEnum, didIReactWithThisEmoji = false,
userWhoAddedThisReaction.id, userWhoAddedThisReaction.userDefaultDisplayName(), reactionId)
userWhoAddedThisReaction.id, userWhoAddedThisReaction.userDefaultDisplayName(), reactionId)
else:
self.view.pinnedModel().removeReaction(messageId, emojiIdAsEnum, reactionId, didIRemoveThisReaction = false)
else:

View File

@ -1272,8 +1272,6 @@ method getContactDetailsAsJson*[T](self: Module[T], publicKey: string, getVerifi
let jsonObj = %* {
# contact details props
"defaultDisplayName": contactDetails.defaultDisplayName,
"optionalName": contactDetails.optionalName,
"icon": contactDetails.icon,
"isCurrentUser": contactDetails.isCurrentUser,
"colorId": contactDetails.colorId,
@ -1294,7 +1292,6 @@ method getContactDetailsAsJson*[T](self: Module[T], publicKey: string, getVerifi
"isBlocked": contactDetails.dto.isBlocked,
"isContactRequestReceived": contactDetails.dto.isContactRequestReceived,
"isContactRequestSent": contactDetails.dto.isContactRequestSent,
"isSyncing": contactDetails.dto.isSyncing,
"removed": contactDetails.dto.removed,
"trustStatus": contactDetails.dto.trustStatus.int,
"contactRequestState": contactDetails.dto.contactRequestState.int,

View File

@ -35,19 +35,19 @@ proc init*(self: Controller) =
self.events.on(SIGNAL_CONTACT_ADDED) do(e: Args):
var args = ContactArgs(e)
self.delegate.contactAdded(args.contactId)
self.delegate.addOrUpdateContactItem(args.contactId)
self.events.on(SIGNAL_CONTACT_BLOCKED) do(e: Args):
var args = ContactArgs(e)
self.delegate.contactBlocked(args.contactId)
self.delegate.addOrUpdateContactItem(args.contactId)
self.events.on(SIGNAL_CONTACT_UNBLOCKED) do(e: Args):
var args = ContactArgs(e)
self.delegate.contactUnblocked(args.contactId)
self.delegate.addOrUpdateContactItem(args.contactId)
self.events.on(SIGNAL_CONTACT_REMOVED) do(e: Args):
var args = ContactArgs(e)
self.delegate.contactRemoved(args.contactId)
self.delegate.addOrUpdateContactItem(args.contactId)
self.events.on(SIGNAL_CONTACT_NICKNAME_CHANGED) do(e: Args):
var args = ContactArgs(e)
@ -67,7 +67,7 @@ proc init*(self: Controller) =
self.events.on(SIGNAL_CONTACT_UPDATED) do(e: Args):
var args = ContactArgs(e)
self.delegate.contactUpdated(args.contactId)
self.delegate.addOrUpdateContactItem(args.contactId)
self.events.on(SIGNAL_CONTACTS_STATUS_UPDATED) do(e: Args):
let args = ContactsStatusUpdatedArgs(e)

View File

@ -62,16 +62,7 @@ method removeContact*(self: AccessInterface, publicKey: string) {.base.} =
# Controller Delegate Interface
method contactAdded*(self: AccessInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method contactBlocked*(self: AccessInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method contactUnblocked*(self: AccessInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method contactRemoved*(self: AccessInterface, publicKey: string) {.base.} =
method addOrUpdateContactItem*(self: AccessInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method contactNicknameChanged*(self: AccessInterface, publicKey: string) {.base.} =
@ -80,9 +71,6 @@ method contactNicknameChanged*(self: AccessInterface, publicKey: string) {.base.
method contactTrustStatusChanged*(self: AccessInterface, publicKey: string, trustStatus: TrustStatus) {.base.} =
raise newException(ValueError, "No implementation available")
method contactUpdated*(self: AccessInterface, publicKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
method contactsStatusUpdated*(self: AccessInterface, statusUpdates: seq[StatusUpdateDto]) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -4,7 +4,6 @@ import io_interface, view, controller, json
import ../../../shared_models/user_item
import ../../../shared_models/user_model
import ../io_interface as delegate_interface
import ../../../../global/global_singleton
import ../../../../core/eventemitter
import app_service/common/types
@ -87,8 +86,6 @@ proc createItemFromPublicKey(self: Module, publicKey: string): UserItem =
isBlocked = contactDetails.dto.isBlocked(),
isCurrentUser = contactDetails.isCurrentUser,
contactRequest = toContactStatus(contactDetails.dto.contactRequestState),
defaultDisplayName = contactDetails.defaultDisplayName,
optionalName = contactDetails.optionalName,
lastUpdated = contactDetails.dto.lastUpdated,
lastUpdatedLocally = contactDetails.dto.lastUpdatedLocally,
bio = contactDetails.dto.bio,
@ -96,7 +93,6 @@ proc createItemFromPublicKey(self: Module, publicKey: string): UserItem =
largeImage = contactDetails.dto.image.large,
isContactRequestReceived = contactDetails.dto.isContactRequestReceived,
isContactRequestSent = contactDetails.dto.isContactRequestSent,
isSyncing = contactDetails.dto.isSyncing,
isRemoved = contactDetails.dto.removed,
trustStatus = contactDetails.dto.trustStatus,
)
@ -105,8 +101,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 +118,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,81 +157,51 @@ method removeContact*(self: Module, publicKey: string) =
method changeContactNickname*(self: Module, publicKey: string, nickname: string) =
self.controller.changeContactNickname(publicKey, nickname)
proc addItemToAppropriateModel(self: Module, item: UserItem) =
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)
method addOrUpdateContactItem*(self: Module, publicKey: string) =
let ind = self.view.contactsModel().findIndexByPubKey(publicKey)
let item = self.createItemFromPublicKey(publicKey)
self.addItemToAppropriateModel(item)
method contactAdded*(self: Module, publicKey: string) =
self.removeIfExistsAndAddToAppropriateModel(publicKey)
method contactBlocked*(self: Module, publicKey: string) =
self.removeIfExistsAndAddToAppropriateModel(publicKey)
method contactUnblocked*(self: Module, publicKey: string) =
self.removeIfExistsAndAddToAppropriateModel(publicKey)
method contactRemoved*(self: Module, publicKey: string) =
self.removeIfExistsAndAddToAppropriateModel(publicKey)
method contactUpdated*(self: Module, publicKey: string) =
self.removeIfExistsAndAddToAppropriateModel(publicKey)
if ind == -1:
self.view.contactsModel().addItem(item)
return
self.view.contactsModel().updateItem(
publicKey,
item.displayName,
item.ensName,
item.isEnsVerified,
item.localNickname,
item.alias,
item.icon,
item.trustStatus,
item.onlineStatus,
item.isContact,
item.isBlocked,
item.contactRequest,
item.lastUpdated,
item.lastUpdatedLocally,
item.bio,
item.thumbnailImage,
item.largeImage,
item.isContactRequestReceived,
item.isContactRequestSent,
item.isRemoved,
)
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)
@ -259,7 +217,7 @@ method requestContactInfo*(self: Module, publicKey: string) =
method onContactInfoRequestFinished*(self: Module, publicKey: string, ok: bool) =
if ok:
self.removeIfExistsAndAddToAppropriateModel(publicKey)
self.addOrUpdateContactItem(publicKey)
self.view.onContactInfoRequestFinished(publicKey, ok)
method shareUserUrlWithData*(self: Module, pubkey: string): string =

View File

@ -1,6 +1,6 @@
import NimQml
import ../../../shared_models/user_model
import ../../../shared_models/[user_model]
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,60 +70,8 @@ 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)
proc sendContactRequest*(self: View, publicKey: string, message: string) {.slot.} =
self.delegate.sendContactRequest(publicKey, message)

View File

@ -37,8 +37,6 @@ type
contactRequest: ContactRequest
#Contact extra details
isCurrentUser: bool
defaultDisplayName: string
optionalName: string
lastUpdated: int64
lastUpdatedLocally: int64
bio: string
@ -46,7 +44,6 @@ type
largeImage: string
isContactRequestReceived: bool
isContactRequestSent: bool
isSyncing: bool
isRemoved: bool
trustStatus: TrustStatus
@ -66,8 +63,6 @@ proc setup*(self: UserItem,
contactRequest: ContactRequest,
#TODO: #14964 - remove defaults
isCurrentUser: bool = false,
defaultDisplayName: string = "",
optionalName: string = "",
lastUpdated: int64 = 0,
lastUpdatedLocally: int64 = 0,
bio: string = "",
@ -75,7 +70,6 @@ proc setup*(self: UserItem,
largeImage: string = "",
isContactRequestReceived: bool = false,
isContactRequestSent: bool = false,
isSyncing: bool = false,
isRemoved: bool = false,
trustStatus: TrustStatus = TrustStatus.Unknown,
) =
@ -93,8 +87,6 @@ proc setup*(self: UserItem,
self.isBlocked = isBlocked
self.contactRequest = contactRequest
self.isCurrentUser = isCurrentUser
self.defaultDisplayName = defaultDisplayName
self.optionalName = optionalName
self.lastUpdated = lastUpdated
self.lastUpdatedLocally = lastUpdatedLocally
self.bio = bio
@ -102,7 +94,6 @@ proc setup*(self: UserItem,
self.largeImage = largeImage
self.isContactRequestReceived = isContactRequestReceived
self.isContactRequestSent = isContactRequestSent
self.isSyncing = isSyncing
self.isRemoved = isRemoved
self.trustStatus = trustStatus
@ -123,8 +114,6 @@ proc initUserItem*(
isBlocked: bool,
contactRequest: ContactRequest = ContactRequest.None,
isCurrentUser: bool = false,
defaultDisplayName: string = "",
optionalName: string = "",
lastUpdated: int64 = 0,
lastUpdatedLocally: int64 = 0,
bio: string = "",
@ -132,7 +121,6 @@ proc initUserItem*(
largeImage: string = "",
isContactRequestReceived: bool = false,
isContactRequestSent: bool = false,
isSyncing: bool = false,
isRemoved: bool = false,
trustStatus: TrustStatus = TrustStatus.Unknown,
): UserItem =
@ -152,8 +140,6 @@ proc initUserItem*(
isBlocked = isBlocked,
contactRequest = contactRequest,
isCurrentUser = isCurrentUser,
defaultDisplayName = defaultDisplayName,
optionalName = optionalName,
lastUpdated = lastUpdated,
lastUpdatedLocally = lastUpdatedLocally,
bio = bio,
@ -161,7 +147,6 @@ proc initUserItem*(
largeImage = largeImage,
isContactRequestReceived = isContactRequestReceived,
isContactRequestSent = isContactRequestSent,
isSyncing = isSyncing,
isRemoved = isRemoved,
trustStatus = trustStatus,
)
@ -182,8 +167,6 @@ proc `$`*(self: UserItem): string =
isBlocked: {self.isBlocked},
contactRequest: {$self.contactRequest.int},
isCurrentUser: {self.isCurrentUser},
defaultDisplayName: {self.defaultDisplayName},
optionalName: {self.optionalName},
lastUpdated: {self.lastUpdated},
lastUpdatedLocally: {self.lastUpdatedLocally},
bio: {self.bio},
@ -191,7 +174,6 @@ proc `$`*(self: UserItem): string =
largeImage: {self.largeImage},
isContactRequestReceived: {self.isContactRequestReceived},
isContactRequestSent: {self.isContactRequestSent},
isSyncing: {self.isSyncing},
isRemoved: {self.isRemoved},
trustStatus: {$self.trustStatus.int},
]"""
@ -277,18 +259,6 @@ proc isCurrentUser*(self: UserItem): bool {.inline.} =
proc `isCurrentUser=`*(self: UserItem, value: bool) {.inline.} =
self.isCurrentUser = value
proc defaultDisplayName*(self: UserItem): string {.inline.} =
self.defaultDisplayName
proc `defaultDisplayName=`*(self: UserItem, value: string) {.inline.} =
self.defaultDisplayName = value
proc optionalName*(self: UserItem): string {.inline.} =
self.optionalName
proc `optionalName=`*(self: UserItem, value: string) {.inline.} =
self.optionalName = value
proc lastUpdated*(self: UserItem): int64 {.inline.} =
self.lastUpdated
@ -331,12 +301,6 @@ proc isContactRequestSent*(self: UserItem): bool {.inline.} =
proc `isContactRequestSent=`*(self: UserItem, value: bool) {.inline.} =
self.isContactRequestSent = value
proc isSyncing*(self: UserItem): bool {.inline.} =
self.isSyncing
proc `isSyncing=`*(self: UserItem, value: bool) {.inline.} =
self.isSyncing = value
proc isRemoved*(self: UserItem): bool {.inline.} =
self.isRemoved

View File

@ -26,8 +26,6 @@ type
IsBlocked
ContactRequest
IsCurrentUser
DefaultDisplayName
OptionalName
LastUpdated
LastUpdatedLocally
Bio
@ -35,7 +33,6 @@ type
LargeImage
IsContactRequestReceived
IsContactRequestSent
IsSyncing
IsRemoved
TrustStatus
@ -56,7 +53,6 @@ QtObject:
result.setup
proc countChanged(self: Model) {.signal.}
proc itemChanged(self: Model, pubKey: string) {.signal.}
proc setItems*(self: Model, items: seq[UserItem]) =
self.beginResetModel()
@ -64,9 +60,6 @@ QtObject:
self.endResetModel()
self.countChanged()
for item in items:
self.itemChanged(item.pubKey)
proc `$`*(self: Model): string =
for i in 0 ..< self.items.len:
result &= fmt"""User Model:
@ -102,8 +95,6 @@ QtObject:
ModelRole.IsBlocked.int: "isBlocked",
ModelRole.ContactRequest.int: "contactRequest",
ModelRole.IsCurrentUser.int: "isCurrentUser",
ModelRole.DefaultDisplayName.int: "defaultDisplayName",
ModelRole.OptionalName.int: "optionalName",
ModelRole.LastUpdated.int: "lastUpdated",
ModelRole.LastUpdatedLocally.int: "lastUpdatedLocally",
ModelRole.Bio.int: "bio",
@ -111,7 +102,6 @@ QtObject:
ModelRole.LargeImage.int: "largeImage",
ModelRole.IsContactRequestReceived.int: "isContactRequestReceived",
ModelRole.IsContactRequestSent.int: "isContactRequestSent",
ModelRole.IsSyncing.int: "isSyncing",
ModelRole.IsRemoved.int: "isRemoved",
ModelRole.TrustStatus.int: "trustStatus",
}.toTable
@ -164,10 +154,6 @@ QtObject:
result = newQVariant(item.contactRequest.int)
of ModelRole.IsCurrentUser:
result = newQVariant(item.isCurrentUser)
of ModelRole.DefaultDisplayName:
result = newQVariant(item.defaultDisplayName)
of ModelRole.OptionalName:
result = newQVariant(item.optionalName)
of ModelRole.LastUpdated:
result = newQVariant(item.lastUpdated)
of ModelRole.LastUpdatedLocally:
@ -182,8 +168,6 @@ QtObject:
result = newQVariant(item.isContactRequestReceived)
of ModelRole.IsContactRequestSent:
result = newQVariant(item.isContactRequestSent)
of ModelRole.IsSyncing:
result = newQVariant(item.isSyncing)
of ModelRole.IsRemoved:
result = newQVariant(item.isRemoved)
of ModelRole.TrustStatus:
@ -205,21 +189,19 @@ QtObject:
self.endInsertRows()
self.countChanged()
for item in items:
self.itemChanged(item.pubKey)
proc findIndexByPubKey*(self: Model, pubKey: string): int =
for i in 0 ..< self.items.len:
if self.items[i].pubKey == pubKey:
return i
return -1
proc addItem*(self: Model, item: UserItem) =
# we need to maintain online contact on top, that means
# if we add an item online status we add it as the last online item (before the first offline item)
# if we add an item with offline status we add it as the first offline item (after the last online item)
var position = -1
for i in 0 ..< self.items.len:
if(self.items[i].onlineStatus == OnlineStatus.Inactive):
position = i
break
let ind = self.findIndexByPubKey(item.pubKey)
if ind != -1:
return
if(position == -1):
position = self.items.len
let position = self.items.len
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
@ -228,19 +210,16 @@ QtObject:
self.items.insert(item, position)
self.endInsertRows()
self.countChanged()
self.itemChanged(item.pubKey)
proc clear*(self: Model) =
self.beginResetModel()
self.items = @[]
self.endResetModel()
proc findIndexByPubKey(self: Model, pubKey: string): int =
for i in 0 ..< self.items.len:
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()
@ -252,9 +231,6 @@ QtObject:
self.endRemoveRows()
self.countChanged()
self.itemChanged(pubKey)
# TODO: rename to `containsItem`
proc isContactWithIdAdded*(self: Model, id: string): bool =
return self.findIndexByPubKey(id) != -1
@ -283,7 +259,6 @@ QtObject:
let index = self.createIndex(ind, 0, nil)
defer: index.delete
self.dataChanged(index, index, roles)
self.itemChanged(pubKey)
proc setIcon*(self: Model, pubKey: string, icon: string) =
let ind = self.findIndexByPubKey(pubKey)
@ -295,7 +270,6 @@ QtObject:
let index = self.createIndex(ind, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.Icon.int])
self.itemChanged(pubKey)
proc updateItem*(
self: Model,
@ -307,6 +281,18 @@ QtObject:
alias: string,
icon: string,
trustStatus: TrustStatus,
onlineStatus: OnlineStatus,
isContact: bool,
isBlocked: bool,
contactRequest: ContactRequest,
lastUpdated: int64,
lastUpdatedLocally: int64,
bio: string,
thumbnailImage: string,
largeImage: string,
isContactRequestReceived: bool,
isContactRequestSent: bool,
isRemoved: bool,
) =
let ind = self.findIndexByPubKey(pubKey)
if ind == -1:
@ -326,6 +312,18 @@ QtObject:
updateRole(alias, Alias)
updateRole(icon, Icon)
updateRole(trustStatus, TrustStatus)
updateRole(onlineStatus, OnlineStatus)
updateRole(isContact, IsContact)
updateRole(isBlocked, IsBlocked)
updateRole(contactRequest, ContactRequest)
updateRole(lastUpdated, LastUpdated)
updateRole(lastUpdatedLocally, LastUpdatedLocally)
updateRole(bio, Bio)
updateRole(thumbnailImage, ThumbnailImage)
updateRole(largeImage, LargeImage)
updateRole(isContactRequestReceived, IsContactRequestReceived)
updateRole(isContactRequestSent, IsContactRequestSent)
updateRole(isRemoved, IsRemoved)
if preferredDisplayNameChanged:
roles.add(ModelRole.PreferredDisplayName.int)
@ -334,13 +332,54 @@ QtObject:
roles.add(ModelRole.IsUntrustworthy.int)
roles.add(ModelRole.IsVerified.int)
# The image is actually a URL that doesn't change. We need to force refresh it just in case
roles.add(ModelRole.ThumbnailImage.int)
roles.add(ModelRole.LargeImage.int)
if roles.len == 0:
return
let index = self.createIndex(ind, 0, nil)
defer: index.delete
self.dataChanged(index, index, roles)
self.itemChanged(pubKey)
proc updateItem*(
self: Model,
pubKey: string,
displayName: string,
ensName: string,
isEnsVerified: bool,
localNickname: string,
alias: string,
icon: string,
trustStatus: TrustStatus,
) =
let ind = self.findIndexByPubKey(pubKey)
if ind == -1:
return
let item = self.items[ind]
self.updateItem(
pubKey,
displayName,
ensName,
isEnsVerified,
localNickname,
alias,
icon,
trustStatus,
item.onlineStatus,
item.isContact,
item.isBlocked,
item.contactRequest,
item.lastUpdated,
item.lastUpdatedLocally,
item.bio,
item.thumbnailImage,
item.largeImage,
item.isContactRequestReceived,
item.isContactRequestSent,
item.isRemoved,
)
proc updateTrustStatus*(self: Model, pubKey: string, trustStatus: TrustStatus) =
let ind = self.findIndexByPubKey(pubKey)
@ -355,7 +394,6 @@ QtObject:
let index = self.createIndex(ind, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.TrustStatus.int, ModelRole.IsUntrustworthy.int, ModelRole.IsVerified.int])
self.itemChanged(pubKey)
proc setOnlineStatus*(self: Model, pubKey: string, onlineStatus: OnlineStatus) =
let ind = self.findIndexByPubKey(pubKey)
@ -370,7 +408,6 @@ QtObject:
let index = self.createIndex(ind, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.OnlineStatus.int])
self.itemChanged(pubKey)
# TODO: rename me to removeItemByPubkey
@ -384,6 +421,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

@ -31,7 +31,6 @@ type ContactsDto* = object
added*: bool
blocked*: bool
hasAddedUs*: bool
isSyncing*: bool
removed*: bool
trustStatus*: TrustStatus
contactRequestState*: ContactRequestState
@ -58,7 +57,6 @@ proc `$`*(self: ContactsDto): string =
added:{self.added},
blocked:{self.blocked},
hasAddedUs:{self.hasAddedUs},
isSyncing:{self.isSyncing},
removed:{self.removed},
trustStatus:{self.trustStatus},
contactRequestState:{self.contactRequestState},
@ -116,7 +114,6 @@ proc toContactsDto*(jsonObj: JsonNode): ContactsDto =
discard jsonObj.getProp("added", result.added)
discard jsonObj.getProp("blocked", result.blocked)
discard jsonObj.getProp("hasAddedUs", result.hasAddedUs)
discard jsonObj.getProp("IsSyncing", result.isSyncing)
discard jsonObj.getProp("Removed", result.removed)
proc userExtractedName(contact: ContactsDto): string =

View File

@ -1,22 +1,14 @@
import QtQml 2.15
import QtTest 1.15
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import SortFilterProxyModel 0.2
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import Storybook 1.0
import utils 1.0
import Models 1.0
import AppLayouts.Profile.helpers 1.0
import AppLayouts.Profile.stores 1.0
import QtTest 1.15
SplitView {
id: root
@ -160,15 +152,13 @@ SplitView {
isUntrustworthy: false,
isBlocked: false,
contactRequestState: 3,
defaaaultDisplayName: "defaultDisplayName",
optionalName: "optionalName",
preferredDisplayName: "preferredDisplayName",
lastUpdated: 1234567890,
lastUpdatedLocally: 1234567890,
thumbnailImage: "thumbnailImage",
largeImage: "largeImage",
isContactRequestReceived: false,
isContactRequestSent: false,
isSyncing: false,
removed: false,
trustStatus: 1,
bio: "bio"
@ -185,7 +175,7 @@ SplitView {
readonly property int colorId: 1
readonly property var colorHash: {}
readonly property int currentUserStatus: 1
readonly property string defaultDisplayName: "myDefaultDisplayName"
readonly property string preferredDisplayName: "myPreferredDisplayName"
readonly property string thumbnailImage: "myThumbnailImage"
readonly property string largeImage: "myLargeImage"
readonly property string bio: "myBio"
@ -199,3 +189,6 @@ SplitView {
}
}
// category: Contacts
// Page is working in general but throwing multiple "Cannot read property" when changing id via combo box
// status: decent

View File

@ -40,7 +40,11 @@ SplitView {
QtObject {
function getContactDetailsAsJson() {
return JSON.stringify({ ensVerified: false })
return JSON.stringify({
ensVerified: false,
isCurrentUser: false,
contactRequestState: Constants.ContactRequestState.Mutual
})
}
Component.onCompleted: {
@ -53,18 +57,18 @@ SplitView {
}
}
ChatStores.RootStore {
id: rootStoreMock
ListModel {
id: contacts
readonly property var contactsModel: ListModel {
id: contactsModel
Component.onCompleted: {
for(let i=0; i < 20; i++) {
append(usersModelEditor.getNewUser(i))
}
Component.onCompleted: {
for(let i=0; i < 20; i++) {
append(usersModelEditor.getNewUser(i))
}
}
}
ChatStores.RootStore {
id: rootStoreMock
readonly property var contactsStore: QtObject {
readonly property var mainModuleInst: null
@ -187,6 +191,8 @@ SplitView {
return true
}
}
contactsModel: contacts
}
}
}
@ -205,6 +211,8 @@ SplitView {
sourceComponent: MembersEditSelectorView {
rootStore: rootStoreMock
usersStore: usersStoreMock
contactsModel: contacts
}
}
}
@ -241,11 +249,11 @@ SplitView {
UsersModelEditor {
id: usersModelEditor
anchors.fill: parent
model: contactsModel
model: contacts
onRemoveClicked: contactsModel.remove(index, 1)
onRemoveAllClicked: contactsModel.clear()
onAddClicked: contactsModel.append(usersModelEditor.getNewUser(contactsModel.count))
onRemoveClicked: contacts.remove(index, 1)
onRemoveAllClicked: contacts.clear()
onAddClicked: contacts.append(usersModelEditor.getNewUser(contacts.count))
}
}
}

View File

@ -46,15 +46,13 @@ Item {
isUntrustworthy: false,
isBlocked: false,
contactRequest: 3,
defaultDisplayName: "defaultDisplayName",
optionalName: "optionalName",
preferredDisplayName: "preferredDisplayName",
lastUpdated: 1234567890,
lastUpdatedLocally: 1234567890,
thumbnailImage: "thumbnailImage",
largeImage: "largeImage",
isContactRequestReceived: false,
isContactRequestSent: false,
isSyncing: false,
isRemoved: false,
trustStatus: 1,
bio: "bio"
@ -74,7 +72,7 @@ Item {
readonly property int colorId: 1
readonly property var colorHash: {1}
readonly property int currentUserStatus: 1
readonly property string defaultDisplayName: "myDefaultDisplayName"
readonly property string preferredDisplayName: "myPreferredDisplayName"
readonly property string thumbnailImage: "myThumbnailImage"
readonly property string largeImage: "myLargeImage"
readonly property string bio: "myBio"
@ -149,13 +147,11 @@ Item {
compare(contactDetails.isUntrustworthy, false, "Expected the isUntrustworthy flag to be set")
compare(contactDetails.isBlocked, false, "Expected the isBlocked flag to be set")
compare(contactDetails.contactRequestState, 3, "Expected the contactRequestState flag to be set")
compare(contactDetails.defaultDisplayName, "defaultDisplayName", "Expected the defaultDisplayName to be set")
compare(contactDetails.optionalName, "optionalName", "Expected the optionalName to be set")
compare(contactDetails.preferredDisplayName, "preferredDisplayName", "Expected the preferredDisplayName to be set")
compare(contactDetails.lastUpdated, 1234567890, "Expected the lastUpdated to be set")
compare(contactDetails.lastUpdatedLocally, 1234567890, "Expected the lastUpdatedLocally to be set")
compare(contactDetails.isContactRequestReceived, false, "Expected the isContactRequestReceived flag to be set")
compare(contactDetails.isContactRequestSent, false, "Expected the isContactRequestSent flag to be set")
compare(contactDetails.isSyncing, false, "Expected the isSyncing to be set")
compare(contactDetails.removed, false, "Expected the removed flag to be set")
compare(contactDetails.trustStatus, 1, "Expected the trustStatus flag to be set")
}
@ -256,15 +252,13 @@ Item {
isUntrustworthy: true,
isBlocked: true,
contactRequest: 2,
defaultDisplayName: "newDefaultDisplayName",
optionalName: "newOptionalName",
preferredDisplayName: "newPreferredDisplayName",
lastUpdated: 1234567891,
lastUpdatedLocally: 1234567891,
thumbnailImage: "newThumbnailImage",
largeImage: "newLargeImage",
isContactRequestReceived: true,
isContactRequestSent: true,
isSyncing: true,
isRemoved: true,
trustStatus: 2,
bio: "newBio"
@ -289,13 +283,11 @@ Item {
compare(contactDetails.isUntrustworthy, true, "Expected the isUntrustworthy flag to be set")
compare(contactDetails.isBlocked, true, "Expected the isBlocked flag to be set")
compare(contactDetails.contactRequestState, 2, "Expected the contactRequestState flag to be set")
compare(contactDetails.defaultDisplayName, "newDefaultDisplayName", "Expected the defaultDisplayName to be set")
compare(contactDetails.optionalName, "newOptionalName", "Expected the optionalName to be set")
compare(contactDetails.preferredDisplayName, "newPreferredDisplayName", "Expected the preferredDisplayName to be set")
compare(contactDetails.lastUpdated, 1234567891, "Expected the lastUpdated to be set")
compare(contactDetails.lastUpdatedLocally, 1234567891, "Expected the lastUpdatedLocally to be set")
compare(contactDetails.isContactRequestReceived, true, "Expected the isContactRequestReceived flag to be set")
compare(contactDetails.isContactRequestSent, true, "Expected the isContactRequestSent flag to be set")
compare(contactDetails.isSyncing, true, "Expected the isSyncing to be set")
compare(contactDetails.removed, true, "Expected the removed flag to be set")
compare(contactDetails.trustStatus, 2, "Expected the trustStatus flag to be set")
}
@ -325,4 +317,4 @@ Item {
compare(contactDetails.localNickname, "localNickname", "Expected the local nickname to be set")
}
}
}
}

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

@ -30,8 +30,6 @@ QtObject {
property bool openCreateChat: false
property var contactsModel: root.contactsStore.myContactsModel
// Important:
// Each `ChatLayout` has its own chatCommunitySectionModule
// (on the backend chat and community sections share the same module since they are actually the same)

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,6 +349,7 @@ Item {
usersStore: UsersStore {
usersModule: root.chatContentModule.usersModule
}
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

@ -3,8 +3,9 @@ import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQml.Models 2.15
import StatusQ.Controls 0.1
import StatusQ 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
@ -22,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
@ -63,6 +67,7 @@ Page {
rootStore: root.rootStore
utilsStore: root.utilsStore
contactsModel: root.mutualContactsModel
function createChat() {
if (model.count === 0) {
@ -178,7 +183,7 @@ Page {
StatusBaseText {
anchors.centerIn: parent
width: Math.min(553, parent.width - 2 * Theme.padding)
visible: root.rootStore.contactsModel.count === 0
visible: root.mutualContacts.ModelCount.empty
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap

View File

@ -100,10 +100,10 @@ MembersSelectorBase {
return
}
const hasPendingContactRequest = root.rootStore.contactsStore.hasPendingContactRequest(contactDetails.publicKey)
const hasPendingContactRequest = contactDetails.contactRequestState === Constants.ContactRequestState.Sent
if ((root.model.count === 0 && hasPendingContactRequest) ||
contactDetails.publicKey === root.rootStore.contactsStore.myPublicKey || contactDetails.isBlocked) {
contactDetails.isCurrentUser || contactDetails.isBlocked) {
// List is empty and we have a contact request
// OR it's our own chat key or a banned user
// Then open the contact's profile popup
@ -154,7 +154,8 @@ MembersSelectorBase {
Connections {
enabled: root.visible
target: root.rootStore.contactsStore.mainModuleInst
target: root.rootStore.contactsStore
function onResolvedENS(resolvedPubKey: string, resolvedAddress: string, uuid: string) {
if (resolvedPubKey === "") {
root.suggestionsDialog.forceHide = false

View File

@ -19,6 +19,8 @@ InlineSelectorPanel {
property ChatStores.RootStore rootStore
property alias contactsModel: suggestionsModel.sourceModel
readonly property int membersLimit: 20 // see: https://github.com/status-im/status-mobile/issues/13066
property bool limitReached: model.count >= membersLimit
@ -29,9 +31,7 @@ InlineSelectorPanel {
warningLabel.visible: limitReached
suggestionsModel: SortFilterProxyModel {
id: _suggestionsModel
sourceModel: root.rootStore.contactsModel
id: suggestionsModel
function searchPredicate(displayName, localNickname, nameAlias) {
return displayName.toLowerCase().includes(root.edit.text.toLowerCase()) ||
@ -52,14 +52,14 @@ InlineSelectorPanel {
enabled: root.edit.text !== "" && root.pastedChatKey == ""
expression: {
root.edit.text // ensure expression is reevaluated when edit.text changes
return _suggestionsModel.searchPredicate(model.displayName, model.localNickname, model.alias)
return suggestionsModel.searchPredicate(model.displayName, model.localNickname, model.alias)
}
expectedRoles: ["displayName", "localNickname", "alias"]
},
FastExpressionFilter {
expression: {
root.model.count // ensure expression is reevaluated when members model changes
return _suggestionsModel.notAMemberPredicate(model.pubKey)
return suggestionsModel.notAMemberPredicate(model.pubKey)
}
expectedRoles: ["pubKey"]
},

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

@ -32,15 +32,13 @@ QObject {
readonly property bool isUntrustworthy: d.contactDetails.isUntrustworthy ?? false
readonly property bool isBlocked: d.contactDetails.isBlocked ?? false
readonly property int contactRequestState: d.contactDetails.contactRequest ?? Constants.ContactRequestState.None
readonly property string defaultDisplayName: d.contactDetails.defaultDisplayName ?? ""
readonly property string optionalName: d.contactDetails.optionalName ?? ""
readonly property string preferredDisplayName: d.contactDetails.preferredDisplayName ?? ""
readonly property int lastUpdated: d.contactDetails.lastUpdated ?? 0
readonly property int lastUpdatedLocally: d.contactDetails.lastUpdatedLocally ?? 0
readonly property string thumbnailImage: d.contactDetails.thumbnailImage ?? ""
readonly property string largeImage: d.contactDetails.largeImage ?? ""
readonly property bool isContactRequestReceived: d.contactDetails.isContactRequestReceived ?? false
readonly property bool isContactRequestSent: d.contactDetails.isContactRequestSent ?? false
readonly property bool isSyncing: d.contactDetails.isSyncing ?? false
readonly property bool removed: d.contactDetails.isRemoved ?? false
readonly property int trustStatus: d.contactDetails.trustStatus ?? Constants.trustStatus.unknown
readonly property string bio: d.contactDetails.bio ?? ""
@ -76,6 +74,8 @@ QObject {
readonly property string ensName: root.profileStore.name
readonly property bool isEnsVerified: root.profileStore.name !== "" && Utils.isValidEns(root.profileStore.name)
readonly property string localNickname: ""
readonly property string preferredDisplayName: root.profileStore.preferredDisplayName
readonly property string name: preferredDisplayName
readonly property string alias: root.profileStore.username
readonly property string icon: root.profileStore.icon
readonly property int colorId: root.profileStore.colorId
@ -87,16 +87,12 @@ QObject {
readonly property bool isUntrustworthy: false
readonly property bool isBlocked: false
readonly property int contactRequestState: Constants.ContactRequestState.None
readonly property string defaultDisplayName: root.profileStore.defaultDisplayName
readonly property string optionalName: defaultDisplayName
readonly property string name: defaultDisplayName
readonly property int lastUpdated: 0
readonly property int lastUpdatedLocally: 0
readonly property string thumbnailImage: root.profileStore.thumbnailImage
readonly property string largeImage: root.profileStore.largeImage
readonly property bool isContactRequestReceived: Constants.ContactRequestState.None
readonly property bool isContactRequestSent: Constants.ContactRequestState.None
readonly property bool isSyncing: false
readonly property bool removed: false
readonly property int trustStatus: Constants.trustStatus.unknown
readonly property string bio: root.profileStore.bio

View File

@ -103,7 +103,7 @@ Item {
width: ListView.view.width
name: model.preferredDisplayName
iconSource: model.icon
iconSource: model.thumbnailImage
subTitle: model.ensVerified ? "" : Utils.getElidedCompressedPk(model.pubKey)
pubKeyColor: Utils.colorForPubkey(model.pubKey)

View File

@ -78,7 +78,8 @@ StatusModal {
}
Connections {
target: contactsStore.mainModuleInst
target: root.contactsStore
function onResolvedENS(resolvedPubKey: string, resolvedAddress: string, uuid: string) {
if(!d.showChatKeyValidationIndicator){
d.showPasteButton = false

View File

@ -1,42 +1,47 @@
import QtQuick 2.13
import utils 1.0
import QtQuick 2.15
import StatusQ 0.1
import utils 1.0
QtObject {
id: root
property var contactsModule
readonly property QtObject _d: QtObject {
id: d
property var globalUtilsInst: globalUtils
property var mainModuleInst: Global.appIsReady? mainModule : null
readonly property var contactsModuleInst: profileSectionModule.contactsModule
readonly property var mainModuleInst: mainModule
readonly property var globalUtilsInst: globalUtils
property string myPublicKey: userProfile.pubKey
Component.onCompleted: {
mainModuleInst.resolvedENS.connect(root.resolvedENS)
}
}
readonly property string myPublicKey: userProfile.pubKey
// 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 contactsModel: d.contactsModuleInst.contactsModel
readonly property var showcasePublicKey: contactsModule.showcasePublicKey
readonly property var showcasePublicKey: d.contactsModuleInst.showcasePublicKey
// Showcase models for a contact with showcasePublicKey
readonly property var showcaseContactCommunitiesModel: contactsModule.showcaseContactCommunitiesModel
readonly property var showcaseContactAccountsModel: contactsModule.showcaseContactAccountsModel
readonly property var showcaseContactCollectiblesModel: contactsModule.showcaseContactCollectiblesModel
readonly property var showcaseContactAssetsModel: contactsModule.showcaseContactAssetsModel
readonly property var showcaseContactSocialLinksModel: contactsModule.showcaseContactSocialLinksModel
readonly property var showcaseContactCommunitiesModel: d.contactsModuleInst.showcaseContactCommunitiesModel
readonly property var showcaseContactAccountsModel: d.contactsModuleInst.showcaseContactAccountsModel
readonly property var showcaseContactCollectiblesModel: d.contactsModuleInst.showcaseContactCollectiblesModel
readonly property var showcaseContactAssetsModel: d.contactsModuleInst.showcaseContactAssetsModel
readonly property var showcaseContactSocialLinksModel: d.contactsModuleInst.showcaseContactSocialLinksModel
readonly property bool isShowcaseForAContactLoading: contactsModule.showcaseForAContactLoading
readonly property bool isShowcaseForAContactLoading: d.contactsModuleInst.showcaseForAContactLoading
// Support models for showcase for a contact with showcasePublicKey
readonly property var showcaseCollectiblesModel: contactsModule.showcaseCollectiblesModel
readonly property var showcaseCollectiblesModel: d.contactsModuleInst.showcaseCollectiblesModel
signal resolvedENS(string resolvedPubKey, string resolvedAddress, string uuid)
// Sets showcasePublicKey and updates showcase models with corresponding data
function requestProfileShowcase(publicKey) {
root.contactsModule.requestProfileShowcase(publicKey)
d.contactsModuleInst.requestProfileShowcase(publicKey)
}
// Temporary commented until we provide appropriate flags on the `status-go` side to cover all sections.
@ -44,44 +49,32 @@ QtObject {
// property var sentButRejectedContactRequestsModel: contactsModule.sentButRejectedContactRequestsModel
function resolveENS(value) {
root.mainModuleInst.resolveENS(value, "")
d.mainModuleInst.resolveENS(value, "")
}
function generateAlias(pubKey) {
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)
return d.globalUtilsInst.generateAlias(pubKey)
}
function joinPrivateChat(pubKey) {
Global.changeAppSectionBySectionType(Constants.appSection.chat)
root.contactsModule.switchToOrCreateOneToOneChat(pubKey)
d.contactsModuleInst.switchToOrCreateOneToOneChat(pubKey)
}
function unblockContact(pubKey) {
root.contactsModule.unblockContact(pubKey)
d.contactsModuleInst.unblockContact(pubKey)
}
function blockContact(pubKey) {
root.contactsModule.blockContact(pubKey)
d.contactsModuleInst.blockContact(pubKey)
}
function removeContact(pubKey) {
root.contactsModule.removeContact(pubKey)
d.contactsModuleInst.removeContact(pubKey)
}
function changeContactNickname(pubKey, nickname, displayName, isEdit) {
root.contactsModule.changeContactNickname(pubKey, nickname)
d.contactsModuleInst.changeContactNickname(pubKey, nickname)
let message = ""
if (nickname === "") { // removed nickname
@ -98,37 +91,37 @@ QtObject {
}
function sendContactRequest(pubKey, message) {
root.contactsModule.sendContactRequest(pubKey, message)
d.contactsModuleInst.sendContactRequest(pubKey, message)
Global.displaySuccessToastMessage(qsTr("Contact request sent"))
}
function acceptContactRequest(pubKey, contactRequestId) {
root.contactsModule.acceptContactRequest(pubKey, contactRequestId)
d.contactsModuleInst.acceptContactRequest(pubKey, contactRequestId)
}
function dismissContactRequest(pubKey, contactRequestId) {
root.contactsModule.dismissContactRequest(pubKey, contactRequestId)
d.contactsModuleInst.dismissContactRequest(pubKey, contactRequestId)
}
function getLatestContactRequestForContactAsJson(pubKey) {
let resp = root.contactsModule.getLatestContactRequestForContactAsJson(pubKey)
let resp = d.contactsModuleInst.getLatestContactRequestForContactAsJson(pubKey)
return JSON.parse(resp)
}
function markAsTrusted(pubKey) {
root.contactsModule.markAsTrusted(pubKey)
d.contactsModuleInst.markAsTrusted(pubKey)
}
function markUntrustworthy(pubKey) {
root.contactsModule.markUntrustworthy(pubKey)
d.contactsModuleInst.markUntrustworthy(pubKey)
}
function removeTrustStatus(pubKey) {
root.contactsModule.removeTrustStatus(pubKey)
d.contactsModuleInst.removeTrustStatus(pubKey)
}
function requestContactInfo(publicKey) {
root.contactsModule.requestContactInfo(publicKey)
d.contactsModuleInst.requestContactInfo(publicKey)
}
function getContactPublicKeyByAddress(address) {
@ -136,6 +129,6 @@ QtObject {
}
function getLinkToProfile(publicKey) {
return root.contactsModule.shareUserUrlWithData(publicKey)
return d.contactsModuleInst.shareUserUrlWithData(publicKey)
}
}

View File

@ -20,9 +20,7 @@ QtObject {
readonly property bool fetchingUpdate: aboutModuleInst.fetching
property ContactsStore contactsStore: ContactsStore {
contactsModule: profileSectionModuleInst.contactsModule
}
property ContactsStore contactsStore: ContactsStore {}
property AdvancedStore advancedStore: AdvancedStore {
walletModule: profileSectionModuleInst.walletModule

View File

@ -24,9 +24,7 @@ QtObject {
readonly property var thumbnailImage: userProfile.thumbnailImage
readonly property var largeImage: userProfile.largeImage
readonly property int colorId: Utils.colorIdForPubkey(root.pubkey)
readonly property var colorHash: Utils.getColorHashAsJson(root.pubkey)
readonly property string defaultDisplayName: ProfileUtils.displayName("", name, displayName, username)
readonly property string bio: profileModule.bio
readonly property string socialLinksJson: profileModule.socialLinksJson

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
@ -593,6 +600,9 @@ Item {
walletCollectiblesStore: appMain.walletCollectiblesStore
buyCryptoStore: appMain.buyCryptoStore
networkConnectionStore: appMain.networkConnectionStore
mutualContactsModel: contactsModelAdaptor.mutualContacts
isDevBuild: !production
onOpenExternalLink: globalConns.onOpenLink(link)
@ -1074,8 +1084,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: {
@ -1563,6 +1573,8 @@ Item {
stickersPopup: statusStickersPopupLoader.item
sendViaPersonalChatEnabled: featureFlagsStore.sendViaPersonalChatEnabled && appMain.networkConnectionStore.sendBuyBridgeEnabled
mutualContactsModel: contactsModelAdaptor.mutualContacts
onProfileButtonClicked: {
Global.changeAppSectionBySectionType(Constants.appSection.profile);
}
@ -1635,6 +1647,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
}
@ -1728,6 +1745,8 @@ Item {
walletAssetsStore: appMain.walletAssetsStore
currencyStore: appMain.currencyStore
mutualContactsModel: contactsModelAdaptor.mutualContacts
onProfileButtonClicked: {
Global.changeAppSectionBySectionType(Constants.appSection.profile);
}
@ -1768,6 +1787,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

View File

@ -1218,7 +1218,7 @@ Loader {
onRemoveTrustStatus: root.rootStore.contactsStore.removeTrustStatus(profileContextMenu.pubKey)
onRemoveContact: Global.removeContactRequested(profileContextMenu.pubKey)
onBlockContact: Global.blockContactRequested(profileContextMenu.pubKey)
onRemoveFromGroup: root.store.removeMemberFromGroupChat(profileContextMenu.pubKey)
onRemoveFromGroup: root.rootStore.removeMemberFromGroupChat(profileContextMenu.pubKey)
onMarkAsTrusted: Global.openMarkAsIDVerifiedPopup(profileContextMenu.pubKey, null)
onRemoveTrustedMark: Global.openRemoveIDVerificationDialog(profileContextMenu.pubKey, null)

View File

@ -776,8 +776,6 @@ QtObject {
function getContactDetailsAsJson(publicKey, getVerificationRequest=true, getOnlineStatus=false, includeDetails=false) {
const defaultValue = {
defaultDisplayName: "",
optionalName: "",
icon: "",
isCurrentUser: "",
colorId: "",
@ -797,7 +795,6 @@ QtObject {
isBlocked: false,
isContactRequestReceived: false,
isContactRequestSent: false,
isSyncing: false,
removed: false,
trustStatus: Constants.trustStatus.unknown,
contactRequestState: Constants.ContactRequestState.None,