diff --git a/src/app/modules/main/chat_section/chat_content/module.nim b/src/app/modules/main/chat_section/chat_content/module.nim index 39e6002eee2..1fd46b99d3d 100644 --- a/src/app/modules/main/chat_section/chat_content/module.nim +++ b/src/app/modules/main/chat_section/chat_content/module.nim @@ -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: diff --git a/src/app/modules/main/module.nim b/src/app/modules/main/module.nim index 0438986242f..f368e752773 100644 --- a/src/app/modules/main/module.nim +++ b/src/app/modules/main/module.nim @@ -1188,8 +1188,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, @@ -1210,7 +1208,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, diff --git a/src/app/modules/main/profile_section/contacts/controller.nim b/src/app/modules/main/profile_section/contacts/controller.nim index e19d92c1974..103ef6201f3 100644 --- a/src/app/modules/main/profile_section/contacts/controller.nim +++ b/src/app/modules/main/profile_section/contacts/controller.nim @@ -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) diff --git a/src/app/modules/main/profile_section/contacts/io_interface.nim b/src/app/modules/main/profile_section/contacts/io_interface.nim index 5c207780076..9eabd2f89fe 100644 --- a/src/app/modules/main/profile_section/contacts/io_interface.nim +++ b/src/app/modules/main/profile_section/contacts/io_interface.nim @@ -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") diff --git a/src/app/modules/main/profile_section/contacts/module.nim b/src/app/modules/main/profile_section/contacts/module.nim index b3c477d52f2..24603541a32 100644 --- a/src/app/modules/main/profile_section/contacts/module.nim +++ b/src/app/modules/main/profile_section/contacts/module.nim @@ -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 = diff --git a/src/app/modules/main/profile_section/contacts/view.nim b/src/app/modules/main/profile_section/contacts/view.nim index 0752e5a4b16..39757679d26 100644 --- a/src/app/modules/main/profile_section/contacts/view.nim +++ b/src/app/modules/main/profile_section/contacts/view.nim @@ -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) diff --git a/src/app/modules/shared_models/user_item.nim b/src/app/modules/shared_models/user_item.nim index 16006051568..e5a5675aec1 100644 --- a/src/app/modules/shared_models/user_item.nim +++ b/src/app/modules/shared_models/user_item.nim @@ -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 diff --git a/src/app/modules/shared_models/user_model.nim b/src/app/modules/shared_models/user_model.nim index 8c1c3a3b650..57b6b715ada 100644 --- a/src/app/modules/shared_models/user_model.nim +++ b/src/app/modules/shared_models/user_model.nim @@ -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 diff --git a/src/app_service/service/contacts/dto/contacts.nim b/src/app_service/service/contacts/dto/contacts.nim index 6a41a021530..c6c4e145e96 100644 --- a/src/app_service/service/contacts/dto/contacts.nim +++ b/src/app_service/service/contacts/dto/contacts.nim @@ -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 = diff --git a/storybook/pages/ContactDetailsPage.qml b/storybook/pages/ContactDetailsPage.qml index f325aa9488d..4976db93799 100644 --- a/storybook/pages/ContactDetailsPage.qml +++ b/storybook/pages/ContactDetailsPage.qml @@ -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 diff --git a/storybook/pages/MembersSelectorPage.qml b/storybook/pages/MembersSelectorPage.qml index 42d010de80e..57fb8868c8d 100644 --- a/storybook/pages/MembersSelectorPage.qml +++ b/storybook/pages/MembersSelectorPage.qml @@ -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 - - readonly property var contactsModel: ListModel { - id: contactsModel + ListModel { + id: contacts - 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)) } } } diff --git a/storybook/qmlTests/tests/tst_ContactDetails.qml b/storybook/qmlTests/tests/tst_ContactDetails.qml index c4cbd3f7161..ed8feb820ba 100644 --- a/storybook/qmlTests/tests/tst_ContactDetails.qml +++ b/storybook/qmlTests/tests/tst_ContactDetails.qml @@ -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") } } -} \ No newline at end of file +} diff --git a/ui/app/AppLayouts/Chat/ChatLayout.qml b/ui/app/AppLayouts/Chat/ChatLayout.qml index 42345f2a4a4..6d5d8da072e 100644 --- a/ui/app/AppLayouts/Chat/ChatLayout.qml +++ b/ui/app/AppLayouts/Chat/ChatLayout.qml @@ -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 diff --git a/ui/app/AppLayouts/Chat/stores/RootStore.qml b/ui/app/AppLayouts/Chat/stores/RootStore.qml index a0abf76f041..0e37c65da37 100644 --- a/ui/app/AppLayouts/Chat/stores/RootStore.qml +++ b/ui/app/AppLayouts/Chat/stores/RootStore.qml @@ -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) diff --git a/ui/app/AppLayouts/Chat/views/ChatHeaderContentView.qml b/ui/app/AppLayouts/Chat/views/ChatHeaderContentView.qml index 2cb42eb9fed..8df44145640 100644 --- a/ui/app/AppLayouts/Chat/views/ChatHeaderContentView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatHeaderContentView.qml @@ -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 diff --git a/ui/app/AppLayouts/Chat/views/ChatView.qml b/ui/app/AppLayouts/Chat/views/ChatView.qml index ad3925297d9..ada68577138 100644 --- a/ui/app/AppLayouts/Chat/views/ChatView.qml +++ b/ui/app/AppLayouts/Chat/views/ChatView.qml @@ -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, { diff --git a/ui/app/AppLayouts/Chat/views/CreateChatView.qml b/ui/app/AppLayouts/Chat/views/CreateChatView.qml index 2b647212c67..6fb67f1fb02 100644 --- a/ui/app/AppLayouts/Chat/views/CreateChatView.qml +++ b/ui/app/AppLayouts/Chat/views/CreateChatView.qml @@ -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 diff --git a/ui/app/AppLayouts/Chat/views/MembersSelectorView.qml b/ui/app/AppLayouts/Chat/views/MembersSelectorView.qml index 1a94869d015..50e264cefe8 100644 --- a/ui/app/AppLayouts/Chat/views/MembersSelectorView.qml +++ b/ui/app/AppLayouts/Chat/views/MembersSelectorView.qml @@ -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 diff --git a/ui/app/AppLayouts/Chat/views/private/MembersSelectorBase.qml b/ui/app/AppLayouts/Chat/views/private/MembersSelectorBase.qml index cc8b7891e8b..e62d98535b3 100644 --- a/ui/app/AppLayouts/Chat/views/private/MembersSelectorBase.qml +++ b/ui/app/AppLayouts/Chat/views/private/MembersSelectorBase.qml @@ -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"] }, diff --git a/ui/app/AppLayouts/Profile/ProfileLayout.qml b/ui/app/AppLayouts/Profile/ProfileLayout.qml index ea057716f79..361859c9a5a 100644 --- a/ui/app/AppLayouts/Profile/ProfileLayout.qml +++ b/ui/app/AppLayouts/Profile/ProfileLayout.qml @@ -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 } } diff --git a/ui/app/AppLayouts/Profile/helpers/ContactDetails.qml b/ui/app/AppLayouts/Profile/helpers/ContactDetails.qml index d1fb2f2bfc8..afe4cde82c5 100644 --- a/ui/app/AppLayouts/Profile/helpers/ContactDetails.qml +++ b/ui/app/AppLayouts/Profile/helpers/ContactDetails.qml @@ -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 diff --git a/ui/app/AppLayouts/Profile/panels/ContactsListPanel.qml b/ui/app/AppLayouts/Profile/panels/ContactsListPanel.qml index ee05437b7cb..09729068553 100644 --- a/ui/app/AppLayouts/Profile/panels/ContactsListPanel.qml +++ b/ui/app/AppLayouts/Profile/panels/ContactsListPanel.qml @@ -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) diff --git a/ui/app/AppLayouts/Profile/popups/SendContactRequestModal.qml b/ui/app/AppLayouts/Profile/popups/SendContactRequestModal.qml index e13b71a8f2a..b9c5666b626 100644 --- a/ui/app/AppLayouts/Profile/popups/SendContactRequestModal.qml +++ b/ui/app/AppLayouts/Profile/popups/SendContactRequestModal.qml @@ -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 diff --git a/ui/app/AppLayouts/Profile/stores/ContactsStore.qml b/ui/app/AppLayouts/Profile/stores/ContactsStore.qml index 15e2d46ebee..b318492d78a 100644 --- a/ui/app/AppLayouts/Profile/stores/ContactsStore.qml +++ b/ui/app/AppLayouts/Profile/stores/ContactsStore.qml @@ -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 + + readonly property var contactsModuleInst: profileSectionModule.contactsModule + readonly property var mainModuleInst: mainModule + readonly property var globalUtilsInst: globalUtils - property var globalUtilsInst: globalUtils - property var mainModuleInst: Global.appIsReady? mainModule : null + Component.onCompleted: { + mainModuleInst.resolvedENS.connect(root.resolvedENS) + } + } - property string myPublicKey: userProfile.pubKey + 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) } } diff --git a/ui/app/AppLayouts/Profile/stores/ProfileSectionStore.qml b/ui/app/AppLayouts/Profile/stores/ProfileSectionStore.qml index e2a312eea1e..4e2be3b2492 100644 --- a/ui/app/AppLayouts/Profile/stores/ProfileSectionStore.qml +++ b/ui/app/AppLayouts/Profile/stores/ProfileSectionStore.qml @@ -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 diff --git a/ui/app/AppLayouts/Profile/stores/ProfileStore.qml b/ui/app/AppLayouts/Profile/stores/ProfileStore.qml index cca7456df95..2a8406d88c0 100644 --- a/ui/app/AppLayouts/Profile/stores/ProfileStore.qml +++ b/ui/app/AppLayouts/Profile/stores/ProfileStore.qml @@ -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 diff --git a/ui/app/AppLayouts/Profile/views/ContactsView.qml b/ui/app/AppLayouts/Profile/views/ContactsView.qml index 64ab6967495..38e3641aead 100644 --- a/ui/app/AppLayouts/Profile/views/ContactsView.qml +++ b/ui/app/AppLayouts/Profile/views/ContactsView.qml @@ -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: { diff --git a/ui/app/AppLayouts/Profile/views/MessagingView.qml b/ui/app/AppLayouts/Profile/views/MessagingView.qml index 6ff11283ce1..e7c8c3a9565 100644 --- a/ui/app/AppLayouts/Profile/views/MessagingView.qml +++ b/ui/app/AppLayouts/Profile/views/MessagingView.qml @@ -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) } diff --git a/ui/app/mainui/AppMain.qml b/ui/app/mainui/AppMain.qml index e373822fd3a..4c684284718 100644 --- a/ui/app/mainui/AppMain.qml +++ b/ui/app/mainui/AppMain.qml @@ -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 } diff --git a/ui/app/mainui/Popups.qml b/ui/app/mainui/Popups.qml index b584b130a3b..1a2088fe8cd 100644 --- a/ui/app/mainui/Popups.qml +++ b/ui/app/mainui/Popups.qml @@ -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() } diff --git a/ui/app/mainui/adaptors/ContactsModelAdaptor.qml b/ui/app/mainui/adaptors/ContactsModelAdaptor.qml new file mode 100644 index 00000000000..85a43ab0408 --- /dev/null +++ b/ui/app/mainui/adaptors/ContactsModelAdaptor.qml @@ -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 + } + } +} diff --git a/ui/app/mainui/adaptors/qmldir b/ui/app/mainui/adaptors/qmldir new file mode 100644 index 00000000000..11680eeb474 --- /dev/null +++ b/ui/app/mainui/adaptors/qmldir @@ -0,0 +1 @@ +ContactsModelAdaptor 1.0 ContactsModelAdaptor.qml diff --git a/ui/imports/shared/views/chat/MessageView.qml b/ui/imports/shared/views/chat/MessageView.qml index e668c15076e..56327090781 100644 --- a/ui/imports/shared/views/chat/MessageView.qml +++ b/ui/imports/shared/views/chat/MessageView.qml @@ -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) diff --git a/ui/imports/utils/Utils.qml b/ui/imports/utils/Utils.qml index 1c26cb7a198..85be42b67ac 100644 --- a/ui/imports/utils/Utils.qml +++ b/ui/imports/utils/Utils.qml @@ -738,8 +738,6 @@ QtObject { function getContactDetailsAsJson(publicKey, getVerificationRequest=true, getOnlineStatus=false, includeDetails=false) { const defaultValue = { - defaultDisplayName: "", - optionalName: "", icon: "", isCurrentUser: "", colorId: "", @@ -759,7 +757,6 @@ QtObject { isBlocked: false, isContactRequestReceived: false, isContactRequestSent: false, - isSyncing: false, removed: false, trustStatus: Constants.trustStatus.unknown, contactRequestState: Constants.ContactRequestState.None,