From 62183cf60b309eb16f2171a8599df28d30e09e16 Mon Sep 17 00:00:00 2001 From: Patryk Osmaczko Date: Fri, 3 Jun 2022 15:24:49 +0200 Subject: [PATCH] chore: refactor/unify user_model and contact_model This is first iteration. Models have been restructured and qml adapted to the changes. What is left to be done: - populate new models with appropriate data (some fields were left default) - use new fields in qml, use StatusMemberItem where possible - fix all #FIXMEs introduced by this commit iterates: #5951 --- .../chat_content/users/module.nim | 87 +++--- .../chat_section/chat_content/users/view.nim | 6 +- src/app/modules/main/chat_section/module.nim | 38 +-- src/app/modules/main/chat_section/view.nim | 14 +- src/app/modules/main/communities/module.nim | 22 +- src/app/modules/main/module.nim | 22 +- .../main/profile_section/contacts/module.nim | 33 ++- .../main/profile_section/contacts/view.nim | 4 +- .../modules/shared_models/contacts_item.nim | 50 ---- .../modules/shared_models/contacts_model.nim | 151 ---------- src/app/modules/shared_models/member_item.nim | 86 ++++++ .../modules/shared_models/member_model.nim | 267 ++++++++++++++++++ .../modules/shared_models/section_item.nim | 8 +- .../modules/shared_models/section_model.nim | 2 +- src/app/modules/shared_models/user_item.nim | 230 +++++++++++---- src/app/modules/shared_models/user_model.nim | 186 +++++++----- ui/StatusQ | 2 +- .../Chat/panels/SuggestionFilterPanel.qml | 8 +- .../AppLayouts/Chat/panels/UserListPanel.qml | 25 +- .../CommunityMembersSettingsPanel.qml | 18 +- .../Profile/panels/ContactPanel.qml | 3 +- .../Profile/panels/ContactsListPanel.qml | 15 +- 22 files changed, 802 insertions(+), 475 deletions(-) delete mode 100644 src/app/modules/shared_models/contacts_item.nim delete mode 100644 src/app/modules/shared_models/contacts_model.nim create mode 100644 src/app/modules/shared_models/member_item.nim create mode 100644 src/app/modules/shared_models/member_model.nim diff --git a/src/app/modules/main/chat_section/chat_content/users/module.nim b/src/app/modules/main/chat_section/chat_content/users/module.nim index bb7d6edc0d..7f954a21be 100644 --- a/src/app/modules/main/chat_section/chat_content/users/module.nim +++ b/src/app/modules/main/chat_section/chat_content/users/module.nim @@ -2,7 +2,7 @@ import NimQml, strutils import io_interface import ../io_interface as delegate_interface import view, controller -import ../../../../shared_models/[user_model, user_item] +import ../../../../shared_models/[member_model, member_item] import ../../../../../global/global_singleton import ../../../../../core/eventemitter import ../../../../../../app_service/service/contacts/service as contact_service @@ -70,16 +70,17 @@ method onNewMessagesLoaded*(self: Module, messages: seq[MessageDto]) = let contactDetails = self.controller.getContactDetails(m.`from`) let statusUpdateDto = self.controller.getStatusForContact(m.`from`) let status = statusUpdateDto.statusType.int.OnlineStatus - self.view.model().addItem(initItem( - m.`from`, - contactDetails.displayName, - contactDetails.details.name, - contactDetails.details.localNickname, - contactDetails.details.alias, - status, - contactDetails.icon, - contactDetails.details.added, - )) + self.view.model().addItem(initMemberItem( + pubKey = m.`from`, + displayName = contactDetails.displayName, + ensName = contactDetails.details.name, # is it correct? + localNickname = contactDetails.details.localNickname, + alias = contactDetails.details.alias, + icon = contactDetails.icon, + onlineStatus = status, + isContact = contactDetails.details.added, + ) + ) method contactNicknameChanged*(self: Module, publicKey: string) = let contactDetails = self.controller.getContactDetails(publicKey) @@ -98,13 +99,13 @@ method contactsStatusUpdated*(self: Module, statusUpdates: seq[StatusUpdateDto]) method contactUpdated*(self: Module, publicKey: string) = let contactDetails = self.controller.getContactDetails(publicKey) self.view.model().updateItem( - publicKey, - contactDetails.displayName, - contactDetails.details.name, - contactDetails.details.localNickname, - contactDetails.details.alias, - contactDetails.icon, - contactDetails.details.added, + pubKey = publicKey, + displayName = contactDetails.displayName, + ensName = contactDetails.details.name, + localNickname = contactDetails.details.localNickname, + alias = contactDetails.details.alias, + icon = contactDetails.icon, + isContact = contactDetails.details.added, #FIXME ) method loggedInUserImageChanged*(self: Module) = @@ -126,25 +127,25 @@ method addChatMember*(self: Module, member: ChatMember) = let isMe = member.id == singletonInstance.userProfile.getPubKey() let contactDetails = self.controller.getContactDetails(member.id) var status = OnlineStatus.Online - if (not isMe): + var displayName = contactDetails.displayName + if (isMe): + displayName = displayName & " (You)" + else: let statusUpdateDto = self.controller.getStatusForContact(member.id) status = statusUpdateDto.statusType.int.OnlineStatus - self.view.model().addItem(initItem( - member.id, - if (isMe): - contactDetails.displayName & " (You)" - else: - contactDetails.displayName, - contactDetails.details.name, - contactDetails.details.localNickname, - contactDetails.details.alias, - status, - contactDetails.icon, - contactDetails.details.added, - member.admin, - member.joined - )) + self.view.model().addItem(initMemberItem( + pubKey = member.id, + displayName = displayName, + ensName = contactDetails.details.name, + localNickname = contactDetails.details.localNickname, + alias = contactDetails.details.alias, + icon = contactDetails.icon, + onlineStatus = status, + isContact = contactDetails.details.added, #FIXME + isAdmin = member.admin, + joined = member.joined) + ) method onChatMembersAdded*(self: Module, ids: seq[string]) = for id in ids: @@ -171,15 +172,15 @@ method onChatMemberRemoved*(self: Module, id: string) = method onChatMemberUpdated*(self: Module, publicKey: string, admin: bool, joined: bool) = let contactDetails = self.controller.getContactDetails(publicKey) self.view.model().updateItem( - publicKey, - contactDetails.displayName, - contactDetails.details.name, - contactDetails.details.localNickname, - contactDetails.details.alias, - contactDetails.icon, - contactDetails.details.added, - admin, - joined) + pubKey = publicKey, + displayName = contactDetails.displayName, + ensName = contactDetails.details.name, + localNickname = contactDetails.details.localNickname, + alias = contactDetails.details.alias, + icon = contactDetails.icon, + isContact = contactDetails.details.added, + isAdmin = admin, + joined = joined) method getMembersPublicKeys*(self: Module): string = let publicKeys = self.controller.getMembersPublicKeys() diff --git a/src/app/modules/main/chat_section/chat_content/users/view.nim b/src/app/modules/main/chat_section/chat_content/users/view.nim index d6cf5b0db4..d319f7df8b 100644 --- a/src/app/modules/main/chat_section/chat_content/users/view.nim +++ b/src/app/modules/main/chat_section/chat_content/users/view.nim @@ -1,5 +1,5 @@ import NimQml -import ../../../../shared_models/user_model +import ../../../../shared_models/member_model import io_interface QtObject: @@ -32,9 +32,9 @@ QtObject: proc getModel(self: View): QVariant {.slot.} = return self.modelVariant - QtProperty[QVariant] model: + QtProperty[QVariant]model: read = getModel notify = modelChanged - + proc getMembersPublicKeys*(self: View): string {.slot.} = return self.delegate.getMembersPublicKeys() diff --git a/src/app/modules/main/chat_section/module.nim b/src/app/modules/main/chat_section/module.nim index 884673d1c5..0431823989 100644 --- a/src/app/modules/main/chat_section/module.nim +++ b/src/app/modules/main/chat_section/module.nim @@ -4,8 +4,8 @@ import io_interface import ../io_interface as delegate_interface import view, controller, item, sub_item, sub_model, base_item import model as chats_model -import ../../shared_models/contacts_item as contacts_item -import ../../shared_models/contacts_model as contacts_model +import ../../shared_models/user_item as user_item +import ../../shared_models/user_model as user_model import chat_content/module as chat_content_module @@ -201,21 +201,21 @@ proc buildChatSectionUI( self.setActiveItemSubItem(selectedItemId, selectedSubItemId) -proc createItemFromPublicKey(self: Module, publicKey: string): contacts_item.Item = +proc createItemFromPublicKey(self: Module, publicKey: string): UserItem = let contactDetails = self.controller.getContactDetails(publicKey) - return contacts_item.initItem( - contactDetails.details.id, - contactDetails.displayName, - contactDetails.icon, - contactDetails.details.isMutualContact(), - contactDetails.details.isBlocked(), - contactDetails.details.isContactVerified(), - contactDetails.details.isContactUntrustworthy() + return initUserItem( + pubKey = contactDetails.details.id, + displayName = contactDetails.displayName, + icon = contactDetails.icon, + isContact = contactDetails.details.isMutualContact(), + isVerified = contactDetails.details.isContactVerified(), + isUntrustworthy = contactDetails.details.isContactUntrustworthy(), + isBlocked = contactDetails.details.isBlocked() ) proc initContactRequestsModel(self: Module) = - var contactsWhoAddedMe: seq[contacts_item.Item] + var contactsWhoAddedMe: seq[UserItem] let contacts = self.controller.getContacts(ContactsGroup.IncomingPendingContactRequests) for c in contacts: let item = self.createItemFromPublicKey(c.id) @@ -227,7 +227,7 @@ proc convertPubKeysToJson(self: Module, pubKeys: string): seq[string] = return map(parseJson(pubKeys).getElems(), proc(x:JsonNode):string = x.getStr) method initListOfMyContacts*(self: Module, pubKeys: string) = - var myContacts: seq[contacts_item.Item] + var myContacts: seq[UserItem] let contacts = self.controller.getContacts(ContactsGroup.MyMutualContacts) for c in contacts: let item = self.createItemFromPublicKey(c.id) @@ -598,11 +598,11 @@ method acceptContactRequest*(self: Module, publicKey: string) = self.controller.addContact(publicKey) method onContactAccepted*(self: Module, publicKey: string) = - self.view.contactRequestsModel().removeItemWithPubKey(publicKey) + self.view.contactRequestsModel().removeItemById(publicKey) self.updateParentBadgeNotifications() method acceptAllContactRequests*(self: Module) = - let pubKeys = self.view.contactRequestsModel().getPublicKeys() + let pubKeys = self.view.contactRequestsModel().getItemIds() for pk in pubKeys: self.acceptContactRequest(pk) @@ -610,11 +610,11 @@ method rejectContactRequest*(self: Module, publicKey: string) = self.controller.rejectContactRequest(publicKey) method onContactRejected*(self: Module, publicKey: string) = - self.view.contactRequestsModel().removeItemWithPubKey(publicKey) + self.view.contactRequestsModel().removeItemById(publicKey) self.updateParentBadgeNotifications() method rejectAllContactRequests*(self: Module) = - let pubKeys = self.view.contactRequestsModel().getPublicKeys() + let pubKeys = self.view.contactRequestsModel().getItemIds() for pk in pubKeys: self.rejectContactRequest(pk) @@ -622,7 +622,7 @@ method blockContact*(self: Module, publicKey: string) = self.controller.blockContact(publicKey) method onContactBlocked*(self: Module, publicKey: string) = - self.view.contactRequestsModel().removeItemWithPubKey(publicKey) + self.view.contactRequestsModel().removeItemById(publicKey) self.view.chatsModel().blockUnblockItemOrSubItemById(publicKey, blocked=true) method onContactUnblocked*(self: Module, publicKey: string) = @@ -635,7 +635,7 @@ method onContactDetailsUpdated*(self: Module, publicKey: string) = if (contactDetails.details.isContactRequestReceived() and not contactDetails.details.isContactRequestSent() and not contactDetails.details.isBlocked() and - not self.view.contactRequestsModel().containsItemWithPubKey(publicKey)): + not self.view.contactRequestsModel().isContactWithIdAdded(publicKey)): let item = self.createItemFromPublicKey(publicKey) self.view.contactRequestsModel().addItem(item) self.updateParentBadgeNotifications() diff --git a/src/app/modules/main/chat_section/view.nim b/src/app/modules/main/chat_section/view.nim index acd17df993..5e5f3b08c4 100644 --- a/src/app/modules/main/chat_section/view.nim +++ b/src/app/modules/main/chat_section/view.nim @@ -1,7 +1,7 @@ import NimQml, json, sequtils import model as chats_model import item, sub_item, active_item -import ../../shared_models/contacts_model as contacts_model +import ../../shared_models/user_model as user_model import io_interface QtObject: @@ -13,9 +13,9 @@ QtObject: activeItem: ActiveItem activeItemVariant: QVariant tmpChatId: string # shouldn't be used anywhere except in prepareChatContentModuleForChatId/getChatContentModule procs - contactRequestsModel: contacts_model.Model + contactRequestsModel: user_model.Model contactRequestsModelVariant: QVariant - listOfMyContacts: contacts_model.Model + listOfMyContacts: user_model.Model listOfMyContactsVariant: QVariant editCategoryChannelsModel: chats_model.Model editCategoryChannelsVariant: QVariant @@ -44,9 +44,9 @@ QtObject: result.editCategoryChannelsVariant = newQVariant(result.editCategoryChannelsModel) result.activeItem = newActiveItem() result.activeItemVariant = newQVariant(result.activeItem) - result.contactRequestsModel = contacts_model.newModel() + result.contactRequestsModel = user_model.newModel() result.contactRequestsModelVariant = newQVariant(result.contactRequestsModel) - result.listOfMyContacts = contacts_model.newModel() + result.listOfMyContacts = user_model.newModel() result.listOfMyContactsVariant = newQVariant(result.listOfMyContacts) result.loadingHistoryMessagesInProgress = false @@ -77,7 +77,7 @@ QtObject: QtProperty[QVariant] editCategoryChannelsModel: read = getEditCategoryChannels - proc contactRequestsModel*(self: View): contacts_model.Model = + proc contactRequestsModel*(self: View): user_model.Model = return self.contactRequestsModel proc getContactRequestsModel(self: View): QVariant {.slot.} = @@ -95,7 +95,7 @@ QtObject: self.delegate.clearListOfMyContacts() self.listOfMyContactsChanged() - proc listOfMyContacts*(self: View): contacts_model.Model = + proc listOfMyContacts*(self: View): user_model.Model = return self.listOfMyContacts proc getListOfMyContacts(self: View): QVariant {.slot.} = diff --git a/src/app/modules/main/communities/module.nim b/src/app/modules/main/communities/module.nim index 52458ffb7b..b4d857ea6c 100644 --- a/src/app/modules/main/communities/module.nim +++ b/src/app/modules/main/communities/module.nim @@ -6,7 +6,7 @@ import ./view, ./controller import ./models/curated_community_item import ./models/curated_community_model import ../../shared_models/section_item -import ../../shared_models/[user_item, user_model, section_model] +import ../../shared_models/[member_item, member_model, section_model] import ../../../global/global_singleton import ../../../core/eventemitter import ../../../../app_service/service/community/service as community_service @@ -96,17 +96,17 @@ method getCommunityItem(self: Module, c: CommunityDto): SectionItem = c.permissions.access, c.permissions.ensOnly, c.muted, - c.members.map(proc(member: Member): user_item.Item = + c.members.map(proc(member: Member): MemberItem = let contactDetails = self.controller.getContactDetails(member.id) - result = user_item.initItem( - member.id, - contactDetails.displayName, - contactDetails.details.name, - contactDetails.details.localNickname, - contactDetails.details.alias, - OnlineStatus.Offline, # TODO get the actual status? - contactDetails.icon, - contactDetails.details.added, + result = initMemberItem( + pubKey = member.id, + displayName = contactDetails.displayName, + ensName = contactDetails.details.name, + localNickname = contactDetails.details.localNickname, + alias = contactDetails.details.alias, + icon = contactDetails.icon, + onlineStatus = OnlineStatus.Offline, # TODO get the actual status? + isContact = contactDetails.details.added, # FIXME )), historyArchiveSupportEnabled = c.settings.historyArchiveSupportEnabled ) diff --git a/src/app/modules/main/module.nim b/src/app/modules/main/module.nim index c1a4ea6d40..c067978f96 100644 --- a/src/app/modules/main/module.nim +++ b/src/app/modules/main/module.nim @@ -3,7 +3,7 @@ import NimQml, tables, json, sugar, sequtils, strformat, marshal, times import io_interface, view, controller, chat_search_item, chat_search_model import ephemeral_notification_item, ephemeral_notification_model import ./communities/models/[pending_request_item, pending_request_model] -import ../shared_models/[user_item, user_model, section_item, section_model, active_section] +import ../shared_models/[member_item, member_model, section_item, section_model, active_section] import ../../global/app_sections_config as conf import ../../global/app_signals import ../../global/global_singleton @@ -221,17 +221,17 @@ proc createChannelGroupItem[T](self: Module[T], c: ChannelGroupDto): SectionItem c.permissions.access, c.permissions.ensOnly, c.muted, - c.members.map(proc(member: ChatMember): user_item.Item = + c.members.map(proc(member: ChatMember): MemberItem = let contactDetails = self.controller.getContactDetails(member.id) - result = user_item.initItem( - member.id, - contactDetails.displayName, - contactDetails.details.name, - contactDetails.details.localNickname, - contactDetails.details.alias, - OnlineStatus.Offline, - contactDetails.icon, - contactDetails.details.added + result = initMemberItem( + pubKey = member.id, + displayName = contactDetails.displayName, + ensName = contactDetails.details.name, + localNickname = contactDetails.details.localNickname, + alias = contactDetails.details.alias, + icon = contactDetails.icon, + onlineStatus = OnlineStatus.Offline, + isContact = contactDetails.details.added # FIXME )), if (isCommunity): communityDetails.pendingRequestsToJoin.map(x => pending_request_item.initItem( x.id, diff --git a/src/app/modules/main/profile_section/contacts/module.nim b/src/app/modules/main/profile_section/contacts/module.nim index 4ee3d0f253..306a1b76d7 100644 --- a/src/app/modules/main/profile_section/contacts/module.nim +++ b/src/app/modules/main/profile_section/contacts/module.nim @@ -1,8 +1,8 @@ import NimQml, chronicles import io_interface, view, controller -import ../../../shared_models/contacts_item -import ../../../shared_models/contacts_model +import ../../../shared_models/user_item +import ../../../shared_models/user_model import ../io_interface as delegate_interface import ../../../../global/global_singleton @@ -38,15 +38,22 @@ proc newModule*(delegate: delegate_interface.AccessInterface, method delete*(self: Module) = self.view.delete -proc createItemFromPublicKey(self: Module, publicKey: string): Item = +proc createItemFromPublicKey(self: Module, publicKey: string): UserItem = let contact = self.controller.getContact(publicKey) let (name, image) = self.controller.getContactNameAndImage(contact.id) - return initItem(contact.id, name, image, contact.isMutualContact(), contact.isBlocked(), - contact.isContactVerified(), contact.isContactUntrustworthy()) + return initUserItem( + pubKey = contact.id, + displayName = name, + icon = image, + isContact = contact.isMutualContact(), + isBlocked = contact.isBlocked(), + isVerified = contact.isContactVerified(), + isUntrustworthy = contact.isContactUntrustworthy() + ) proc buildModel(self: Module, model: Model, group: ContactsGroup) = - var items: seq[Item] + var items: seq[UserItem] let contacts = self.controller.getContacts(group) for c in contacts: let item = self.createItemFromPublicKey(c.id) @@ -100,7 +107,7 @@ method changeContactNickname*(self: Module, publicKey: string, nickname: string) method removeContactRequestRejection*(self: Module, publicKey: string) = self.controller.removeContactRequestRejection(publicKey) -proc addItemToAppropriateModel(self: Module, item: Item) = +proc addItemToAppropriateModel(self: Module, item: UserItem) = if(singletonInstance.userProfile.getPubKey() == item.pubKey): return let contact = self.controller.getContact(item.pubKey()) @@ -122,13 +129,13 @@ proc addItemToAppropriateModel(self: Module, item: Item) = # self.view.sentButRejectedContactRequestsModel().addItem(item) proc removeItemWithPubKeyFromAllModels(self: Module, publicKey: string) = - self.view.myMutualContactsModel().removeItemWithPubKey(publicKey) - self.view.receivedContactRequestsModel().removeItemWithPubKey(publicKey) - self.view.sentContactRequestsModel().removeItemWithPubKey(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().removeItemWithPubKey(publicKey) - # self.view.sentButRejectedContactRequestsModel().removeItemWithPubKey(publicKey) - self.view.blockedContactsModel().removeItemWithPubKey(publicKey) + # self.view.receivedButRejectedContactRequestsModel().removeItemById(publicKey) + # self.view.sentButRejectedContactRequestsModel().removeItemById(publicKey) + self.view.blockedContactsModel().removeItemById(publicKey) method removeIfExistsAndAddToAppropriateModel*(self: Module, publicKey: string) = self.removeItemWithPubKeyFromAllModels(publicKey) diff --git a/src/app/modules/main/profile_section/contacts/view.nim b/src/app/modules/main/profile_section/contacts/view.nim index d50699165b..ab4c73ecb7 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/contacts_model +import ../../../shared_models/user_model import ./io_interface QtObject: @@ -121,7 +121,7 @@ QtObject: # notify = sentButRejectedContactRequestsModelChanged proc isMyMutualContact*(self: View, publicKey: string): bool {.slot.} = - return self.myMutualContactsModel.containsItemWithPubKey(publicKey) + return self.myMutualContactsModel.isContactWithIdAdded(publicKey) proc addContact*(self: View, publicKey: string) {.slot.} = self.delegate.addContact(publicKey) diff --git a/src/app/modules/shared_models/contacts_item.nim b/src/app/modules/shared_models/contacts_item.nim deleted file mode 100644 index aee91f71e4..0000000000 --- a/src/app/modules/shared_models/contacts_item.nim +++ /dev/null @@ -1,50 +0,0 @@ -type - ContactVerificationState* {.pure.} = enum - NotMarked = 0 - Verified - Untrustworthy - -type - Item* = ref object - pubKey: string - name: string - icon: string - isBlocked: bool - isMutualContact: bool - verificationState: ContactVerificationState - -proc initItem*(pubKey, name, icon: string, isMutualContact, isBlocked: bool, - isContactVerified, isContactUntrustworthy: bool): Item = - result = Item() - result.pubKey = pubKey - result.name = name - result.icon = icon - result.isMutualContact = isMutualContact - result.isBlocked = isBlocked - if(isContactVerified): - result.verificationState = ContactVerificationState.Verified - elif(isContactUntrustworthy): - result.verificationState = ContactVerificationState.Untrustworthy - else: - result.verificationState = ContactVerificationState.NotMarked - -proc pubKey*(self: Item): string = - self.pubKey - -proc name*(self: Item): string = - self.name - -proc `name=`*(self: Item, value: string) = - self.name = value - -proc icon*(self: Item): string = - self.icon - -proc isMutualContact*(self: Item): bool = - self.isMutualContact - -proc isBlocked*(self: Item): bool = - self.isBlocked - -proc verificationState*(self: Item): ContactVerificationState = - self.verificationState diff --git a/src/app/modules/shared_models/contacts_model.nim b/src/app/modules/shared_models/contacts_model.nim deleted file mode 100644 index 0c1b5a0263..0000000000 --- a/src/app/modules/shared_models/contacts_model.nim +++ /dev/null @@ -1,151 +0,0 @@ -import NimQml, Tables -import contacts_item - -type - ModelRole {.pure.} = enum - PubKey = UserRole + 1 - Name - Icon - IsMutualContact - IsBlocked - VerificationState - -QtObject: - type Model* = ref object of QAbstractListModel - items*: seq[Item] - - proc setup(self: Model) = - self.QAbstractListModel.setup - - proc delete(self: Model) = - self.items = @[] - self.QAbstractListModel.delete - - proc newModel*(): Model = - new(result, delete) - result.setup - - proc countChanged(self: Model) {.signal.} - proc getCount*(self: Model): int {.slot.} = - self.items.len - QtProperty[int] count: - read = getCount - notify = countChanged - - method rowCount(self: Model, index: QModelIndex = nil): int = - return self.items.len - - method roleNames(self: Model): Table[int, string] = - { - ModelRole.PubKey.int:"pubKey", - ModelRole.Name.int:"name", - ModelRole.Icon.int:"icon", - ModelRole.IsMutualContact.int:"isMutualContact", - ModelRole.IsBlocked.int:"isBlocked", - ModelRole.VerificationState.int:"verificationState" - }.toTable - - method data(self: Model, index: QModelIndex, role: int): QVariant = - if not index.isValid: - return - if index.row < 0 or index.row >= self.items.len: - return - let item = self.items[index.row] - let enumRole = role.ModelRole - - case enumRole: - of ModelRole.PubKey: - result = newQVariant(item.pubKey) - of ModelRole.Name: - result = newQVariant(item.name) - of ModelRole.Icon: - result = newQVariant(item.icon) - of ModelRole.IsMutualContact: - result = newQVariant(item.isMutualContact) - of ModelRole.IsBlocked: - result = newQVariant(item.isBlocked) - of ModelRole.VerificationState: - result = newQVariant(item.verificationState.int) - - 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 addItems*(self: Model, items: seq[Item]) = - if(items.len == 0): - return - - let parentModelIndex = newQModelIndex() - defer: parentModelIndex.delete - - let first = self.items.len - let last = first + items.len - 1 - self.beginInsertRows(parentModelIndex, first, last) - self.items.add(items) - self.endInsertRows() - self.countChanged() - - proc addItem*(self: Model, item: Item) = - let parentModelIndex = newQModelIndex() - defer: parentModelIndex.delete - - self.beginInsertRows(parentModelIndex, self.items.len, self.items.len) - self.items.add(item) - self.endInsertRows() - self.countChanged() - - - proc containsItemWithPubKey*(self: Model, pubKey: string): bool = - return self.findIndexByPubKey(pubKey) != -1 - - proc removeItemWithPubKey*(self: Model, pubKey: string) = - let ind = self.findIndexByPubKey(pubKey) - if(ind == -1): - return - - let parentModelIndex = newQModelIndex() - defer: parentModelIndex.delete - - self.beginRemoveRows(parentModelIndex, ind, ind) - self.items.delete(ind) - self.endRemoveRows() - self.countChanged() - - proc updateItem*(self: Model, item: Item) = - let ind = self.findIndexByPubKey(item.pubKey) - if(ind == -1): - return - - self.items[ind] = item - - let index = self.createIndex(ind, 0, nil) - - self.dataChanged(index, index, @[ - ModelRole.Name.int, - ModelRole.Icon.int, - ModelRole.IsMutualContact.int, - ModelRole.IsBlocked.int, - ModelRole.VerificationState.int - ] - ) - - proc updateName*(self: Model, pubKey: string, name: string) = - let ind = self.findIndexByPubKey(pubKey) - if(ind == -1): - return - - let first = self.createIndex(ind, 0, nil) - let last = self.createIndex(ind, 0, nil) - self.items[ind].name = name - self.dataChanged(first, last, @[ModelRole.Name.int]) - - proc getPublicKeys*(self: Model): seq[string] = - for i in self.items: - result.add(i.pubKey) - - proc clear*(self: Model) = - self.beginResetModel() - self.items = @[] - self.endResetModel() diff --git a/src/app/modules/shared_models/member_item.nim b/src/app/modules/shared_models/member_item.nim new file mode 100644 index 0000000000..90c04f6086 --- /dev/null +++ b/src/app/modules/shared_models/member_item.nim @@ -0,0 +1,86 @@ +import strformat +import user_item + +export user_item + +type + MemberItem* = ref object of UserItem + isAdmin: bool + joined: bool + +# FIXME: remove defaults +proc initMemberItem*( + pubKey: string, + displayName: string, + ensName: string, + localNickname: string, + alias: string, + icon: string, + colorId: int = 0, + colorHash: string = "", + onlineStatus: OnlineStatus = OnlineStatus.Offline, + isContact: bool = false, + isVerified: bool = false, + isUntrustworthy: bool = false, + isBlocked: bool = false, + contactRequest: ContactRequest = ContactRequest.None, + incomingVerification: VerificationRequest = VerificationRequest.None, + outcomingVerification: VerificationRequest = VerificationRequest.None, + isAdmin: bool = false, + joined: bool = false, +): MemberItem = + result = MemberItem() + result.isAdmin = isAdmin + result.joined = joined + result.UserItem.setup( + pubKey = pubKey, + displayName = displayName, + ensName = ensName, + localNickname = localNickname, + alias = alias, + icon = icon, + colorId = colorId, + colorHash = colorHash, + onlineStatus = onlineStatus, + isContact = isContact, + isVerified = isVerified, + isUntrustworthy = isUntrustworthy, + isBlocked = isBlocked, + contactRequest = contactRequest, + incomingVerification = incomingVerification, + outcomingVerification = outcomingVerification + ) + +proc `$`*(self: MemberItem): string = + result = fmt"""Member Item( + pubKey: {self.pubkey}, + displayName: {self.displayName}, + ensName: {self.ensName}, + localNickname: {self.localNickname}, + alias: {self.alias}, + icon: {self.icon}, + colorId: {self.colorId}, + colorHash: {self.colorHash}, + onlineStatus: {$self.onlineStatus.int}, + isContact: {self.isContact}, + isVerified: {self.isVerified}, + isUntrustworthy: {self.isUntrustworthy}, + isBlocked: {self.isBlocked}, + contactRequest: {$self.contactRequest.int}, + incomingVerification: {$self.incomingVerification.int}, + outcomingVerification: {$self.outcomingVerification.int}, + isAdmin: {self.isAdmin}, + joined: {self.joined} + ]""" + +proc isAdmin*(self: MemberItem): bool {.inline.} = + self.isAdmin + +proc `isAdmin=`*(self: MemberItem, value: bool) {.inline.} = + self.isAdmin = value + +proc joined*(self: MemberItem): bool {.inline.} = + self.joined + +proc `joined=`*(self: MemberItem, value: bool) {.inline.} = + self.joined = value diff --git a/src/app/modules/shared_models/member_model.nim b/src/app/modules/shared_models/member_model.nim new file mode 100644 index 0000000000..b701e4c51c --- /dev/null +++ b/src/app/modules/shared_models/member_model.nim @@ -0,0 +1,267 @@ +import NimQml, Tables, strformat, sequtils, sugar + +# TODO: use generics to remove duplication between user_model and member_model + +import member_item + +type + ModelRole {.pure.} = enum + PubKey = UserRole + 1 + DisplayName + EnsName + LocalNickname + Alias + Icon + ColorId + ColorHash + OnlineStatus + IsContact + IsVerified + IsUntrustworthy + IsBlocked + ContactRequest + IncomingVerification + OutcomingVerification + IsAdmin + Joined + +QtObject: + type + Model* = ref object of QAbstractListModel + items: seq[MemberItem] + + proc delete(self: Model) = + self.items = @[] + self.QAbstractListModel.delete + + proc setup(self: Model) = + self.QAbstractListModel.setup + + proc newModel*(): Model = + new(result, delete) + result.setup + + proc countChanged(self: Model) {.signal.} + + proc setItems*(self: Model, items: seq[MemberItem]) = + self.beginResetModel() + self.items = items + self.endResetModel() + self.countChanged() + + proc `$`*(self: Model): string = + for i in 0 ..< self.items.len: + result &= fmt"""Member Model: + [{i}]:({$self.items[i]}) + """ + + proc getCount*(self: Model): int {.slot.} = + self.items.len + + QtProperty[int]count: + read = getCount + notify = countChanged + + method rowCount(self: Model, index: QModelIndex = nil): int = + return self.items.len + + method roleNames(self: Model): Table[int, string] = + { + ModelRole.PubKey.int: "pubKey", + ModelRole.DisplayName.int: "displayName", + ModelRole.EnsName.int: "ensName", + ModelRole.LocalNickname.int: "localNickname", + ModelRole.Alias.int: "alias", + ModelRole.Icon.int: "icon", + ModelRole.ColorId.int: "colorId", + ModelRole.ColorHash.int: "colorHash", + ModelRole.OnlineStatus.int: "onlineStatus", + ModelRole.IsContact.int: "isContact", + ModelRole.IsVerified.int: "isVerified", + ModelRole.IsUntrustworthy.int: "isUntrustworthy", + ModelRole.IsBlocked.int: "isBlocked", + ModelRole.ContactRequest.int: "contactRequest", + ModelRole.IncomingVerification.int: "incomingVerification", + ModelRole.OutcomingVerification.int: "outcomingVerification", + ModelRole.IsAdmin.int: "isAdmin", + ModelRole.Joined.int: "joined", + }.toTable + + method data(self: Model, index: QModelIndex, role: int): QVariant = + if (not index.isValid): + return + + if (index.row < 0 or index.row >= self.items.len): + return + + let item = self.items[index.row] + let enumRole = role.ModelRole + + case enumRole: + of ModelRole.PubKey: + result = newQVariant(item.pubKey) + of ModelRole.DisplayName: + result = newQVariant(item.displayName) + of ModelRole.EnsName: + result = newQVariant(item.ensName) + of ModelRole.LocalNickname: + result = newQVariant(item.localNickname) + of ModelRole.Alias: + result = newQVariant(item.alias) + of ModelRole.Icon: + result = newQVariant(item.icon) + of ModelRole.ColorId: + result = newQVariant(item.colorId) + of ModelRole.ColorHash: + result = newQVariant(item.colorHash) + of ModelRole.OnlineStatus: + result = newQVariant(item.onlineStatus.int) + of ModelRole.IsContact: + result = newQVariant(item.isContact) + of ModelRole.IsVerified: + result = newQVariant(item.isVerified) + of ModelRole.IsUntrustworthy: + result = newQVariant(item.isUntrustworthy) + of ModelRole.IsBlocked: + result = newQVariant(item.isBlocked) + of ModelRole.ContactRequest: + result = newQVariant(item.contactRequest.int) + of ModelRole.IncomingVerification: + result = newQVariant(item.incomingVerification.int) + of ModelRole.OutcomingVerification: + result = newQVariant(item.outcomingVerification.int) + of ModelRole.IsAdmin: + result = newQVariant(item.isAdmin) + of ModelRole.Joined: + result = newQVariant(item.joined) + + proc addItem*(self: Model, item: MemberItem) = + # 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.Offline): + position = i + break + + if(position == -1): + position = self.items.len + + let parentModelIndex = newQModelIndex() + defer: parentModelIndex.delete + + self.beginInsertRows(parentModelIndex, position, position) + self.items.insert(item, position) + self.endInsertRows() + self.countChanged() + + proc findIndexForMessageId(self: Model, pubKey: string): int = + for i in 0 ..< self.items.len: + if(self.items[i].pubKey == pubKey): + return i + + return -1 + + proc removeItemWithIndex(self: Model, index: int) = + let parentModelIndex = newQModelIndex() + defer: parentModelIndex.delete + + self.beginRemoveRows(parentModelIndex, index, index) + self.items.delete(index) + self.endRemoveRows() + self.countChanged() + + proc isContactWithIdAdded*(self: Model, id: string): bool = + return self.findIndexForMessageId(id) != -1 + + proc setName*(self: Model, pubKey: string, displayName: string, + ensName: string, localNickname: string) = + let ind = self.findIndexForMessageId(pubKey) + if(ind == -1): + return + + self.items[ind].displayName = displayName + self.items[ind].ensName = ensName + self.items[ind].localNickname = localNickname + + let index = self.createIndex(ind, 0, nil) + self.dataChanged(index, index, @[ + ModelRole.DisplayName.int, + ModelRole.EnsName.int, + ModelRole.LocalNickname.int, + ]) + + proc setIcon*(self: Model, pubKey: string, icon: string) = + let ind = self.findIndexForMessageId(pubKey) + if(ind == -1): + return + + self.items[ind].icon = icon + + let index = self.createIndex(ind, 0, nil) + self.dataChanged(index, index, @[ModelRole.Icon.int]) + +# FIXME: remove defaults + proc updateItem*( + self: Model, + pubKey: string, + displayName: string, + ensName: string, + localNickname: string, + alias: string, + icon: string, + isContact: bool = false, + isAdmin: bool = false, + joined: bool = false + ) = + let ind = self.findIndexForMessageId(pubKey) + if(ind == -1): + return + + self.items[ind].displayName = displayName + self.items[ind].ensName = ensName + self.items[ind].localNickname = localNickname + self.items[ind].alias = alias + self.items[ind].icon = icon + self.items[ind].isContact = isContact + self.items[ind].isAdmin = isAdmin + self.items[ind].joined = joined + + let index = self.createIndex(ind, 0, nil) + self.dataChanged(index, index, @[ + ModelRole.DisplayName.int, + ModelRole.EnsName.int, + ModelRole.LocalNickname.int, + ModelRole.Alias.int, + ModelRole.Icon.int, + ModelRole.IsContact.int, + ModelRole.IsAdmin.int, + ModelRole.Joined.int, + ]) + + proc setOnlineStatus*(self: Model, pubKey: string, + onlineStatus: OnlineStatus) = + let ind = self.findIndexForMessageId(pubKey) + if(ind == -1): + return + + if(self.items[ind].onlineStatus == onlineStatus): + return + + var item = self.items[ind] + item.onlineStatus = onlineStatus + self.removeItemWithIndex(ind) + self.addItem(item) + +# TODO: rename me to removeItemByPubkey + proc removeItemById*(self: Model, pubKey: string) = + let ind = self.findIndexForMessageId(pubKey) + if(ind == -1): + return + + self.removeItemWithIndex(ind) + +# TODO: rename me to getItemsAsPubkeys + proc getItemIds*(self: Model): seq[string] = + return self.items.map(i => i.pubKey) diff --git a/src/app/modules/shared_models/section_item.nim b/src/app/modules/shared_models/section_item.nim index 16e7c6a0af..f75e2a2741 100644 --- a/src/app/modules/shared_models/section_item.nim +++ b/src/app/modules/shared_models/section_item.nim @@ -1,5 +1,5 @@ import strformat -import ./user_model, ./user_item +import ./member_model, ./member_item import ../main/communities/models/[pending_request_item, pending_request_model] type @@ -37,7 +37,7 @@ type access: int ensOnly: bool muted: bool - membersModel: user_model.Model + membersModel: member_model.Model pendingRequestsToJoinModel: PendingRequestModel historyArchiveSupportEnabled: bool pinMessageAllMembersEnabled: bool @@ -66,7 +66,7 @@ proc initItem*( access: int = 0, ensOnly = false, muted = false, - members: seq[user_item.Item] = @[], + members: seq[MemberItem] = @[], pendingRequestsToJoin: seq[PendingRequestItem] = @[], historyArchiveSupportEnabled = false, pinMessageAllMembersEnabled = false @@ -218,7 +218,7 @@ proc muted*(self: SectionItem): bool {.inline.} = proc `muted=`*(self: var SectionItem, value: bool) {.inline.} = self.muted = value -proc members*(self: SectionItem): user_model.Model {.inline.} = +proc members*(self: SectionItem): member_model.Model {.inline.} = self.membersModel proc hasMember*(self: SectionItem, pubkey: string): bool = diff --git a/src/app/modules/shared_models/section_model.nim b/src/app/modules/shared_models/section_model.nim index 25929e0b26..711498614a 100644 --- a/src/app/modules/shared_models/section_model.nim +++ b/src/app/modules/shared_models/section_model.nim @@ -2,7 +2,7 @@ import NimQml, Tables, strutils, strformat import json, json_serialization -import section_item, user_model +import section_item, member_model type ModelRole {.pure.} = enum diff --git a/src/app/modules/shared_models/user_item.nim b/src/app/modules/shared_models/user_item.nim index 8045fdc1dc..d6327636f2 100644 --- a/src/app/modules/shared_models/user_item.nim +++ b/src/app/modules/shared_models/user_item.nim @@ -8,110 +8,218 @@ type Idle Invisible -# TODO add role when it is needed + ContactRequest* {.pure.} = enum + None = 0 + IncomingPending + IncomingRejected + OutcomingPending + OutcomingRejected + + VerificationRequest* {.pure.} = enum + None = 0 + Pending + Answered + type - Item* = ref object - id: string + UserItem* = ref object of RootObj + pubKey: string displayName: string ensName: string localNickname: string alias: string - onlineStatus: OnlineStatus icon: string - isAdded: bool - isAdmin: bool - joined: bool + colorId: int + colorHash: string + onlineStatus: OnlineStatus + isContact: bool + isVerified: bool + isUntrustworthy: bool + isBlocked: bool + contactRequest: ContactRequest + incomingVerification: VerificationRequest + outcomingVerification: VerificationRequest -proc initItem*( - id: string, +proc setup*(self: UserItem, + pubKey: string, displayName: string, ensName: string, localNickname: string, alias: string, - onlineStatus: OnlineStatus, icon: string, - isAdded: bool = false, - isAdmin: bool = false, - joined: bool = false, -): Item = - result = Item() - result.id = id - result.displayName = displayName - result.ensName = ensName - result.localNickname = localNickname - result.alias = alias - result.onlineStatus = onlineStatus - result.icon = icon - result.isAdded = isAdded - result.isAdmin = isAdmin - result.joined = joined + colorId: int, + colorHash: string, + onlineStatus: OnlineStatus, + isContact: bool, + isVerified: bool, + isUntrustworthy: bool, + isBlocked: bool, + contactRequest: ContactRequest, + incomingVerification: VerificationRequest, + outcomingVerification: VerificationRequest) = + self.pubKey = pubKey + self.displayName = displayName + self.ensName = ensName + self.localNickname = localNickname + self.alias = alias + self.icon = icon + self.colorId = colorId + self.colorHash = colorHash + self.onlineStatus = onlineStatus + self.isContact = isContact + self.isVerified = isVerified + self.isUntrustworthy = isUntrustworthy + self.isBlocked = isBlocked + self.contactRequest = contactRequest + self.incomingVerification = incomingVerification + self.outcomingVerification = outcomingVerification -proc `$`*(self: Item): string = +# FIXME: remove defaults +proc initUserItem*( + pubKey: string, + displayName: string, + ensName: string = "", + localNickname: string = "", + alias: string = "", + icon: string, + colorId: int = 0, + colorHash: string = "", + onlineStatus: OnlineStatus = OnlineStatus.Offline, + isContact: bool, + isVerified: bool, + isUntrustworthy: bool, + isBlocked: bool, + contactRequest: ContactRequest = ContactRequest.None, + incomingVerification: VerificationRequest = VerificationRequest.None, + outcomingVerification: VerificationRequest = VerificationRequest.None +): UserItem = + result = UserItem() + result.setup( + pubKey = pubKey, + displayName = displayName, + ensName = ensName, + localNickname = localNickname, + alias = alias, + icon = icon, + colorId = colorId, + colorHash = colorHash, + onlineStatus = onlineStatus, + isContact = isContact, + isVerified = isVerified, + isUntrustworthy = isUntrustworthy, + isBlocked = isBlocked, + contactRequest = contactRequest, + incomingVerification = incomingVerification, + outcomingVerification = outcomingVerification) + +proc `$`*(self: UserItem): string = result = fmt"""User Item( - id: {self.id}, + pubKey: {self.pubkey}, displayName: {self.displayName}, + ensName: {self.ensName}, localNickname: {self.localNickname}, alias: {self.alias}, - onlineStatus: {$self.onlineStatus.int}, icon: {self.icon}, - isAdded: {$self.isAdded}, - isAdmin: {$self.isAdmin}, - joined: {$self.joined}, + colorId: {self.colorId}, + colorHash: {self.colorHash}, + onlineStatus: {$self.onlineStatus.int}, + isContact: {self.isContact}, + isVerified: {self.isVerified}, + isUntrustworthy: {self.isUntrustworthy}, + isBlocked: {self.isBlocked}, + contactRequest: {$self.contactRequest.int}, + incomingVerification: {$self.incomingVerification.int}, + outcomingVerification: {$self.outcomingVerification.int}, ]""" -proc id*(self: Item): string {.inline.} = - self.id +proc pubKey*(self: UserItem): string {.inline.} = + self.pubKey -proc name*(self: Item): string {.inline.} = +proc displayName*(self: UserItem): string {.inline.} = self.displayName -proc `name=`*(self: Item, value: string) {.inline.} = +proc `displayName=`*(self: UserItem, value: string) {.inline.} = self.displayName = value -proc ensName*(self: Item): string {.inline.} = +proc ensName*(self: UserItem): string {.inline.} = self.ensName -proc `ensName=`*(self: Item, value: string) {.inline.} = +proc `ensName=`*(self: UserItem, value: string) {.inline.} = self.ensName = value -proc localNickname*(self: Item): string {.inline.} = +proc localNickname*(self: UserItem): string {.inline.} = self.localNickname -proc `localNickname=`*(self: Item, value: string) {.inline.} = +proc `localNickname=`*(self: UserItem, value: string) {.inline.} = self.localNickname = value -proc alias*(self: Item): string {.inline.} = +proc alias*(self: UserItem): string {.inline.} = self.alias -proc `alias=`*(self: Item, value: string) {.inline.} = +proc `alias=`*(self: UserItem, value: string) {.inline.} = self.alias = value -proc onlineStatus*(self: Item): OnlineStatus {.inline.} = - self.onlineStatus - -proc `onlineStatus=`*(self: Item, value: OnlineStatus) {.inline.} = - self.onlineStatus = value - -proc icon*(self: Item): string {.inline.} = +proc icon*(self: UserItem): string {.inline.} = self.icon -proc `icon=`*(self: Item, value: string) {.inline.} = +proc `icon=`*(self: UserItem, value: string) {.inline.} = self.icon = value -proc isAdmin*(self: Item): bool {.inline.} = - self.isAdmin +proc colorId*(self: UserItem): int {.inline.} = + self.colorId -proc `isAdmin=`*(self: Item, value: bool) {.inline.} = - self.isAdmin = value +proc `colorId=`*(self: UserItem, value: int) {.inline.} = + self.colorId = value -proc isAdded*(self: Item): bool {.inline.} = - self.isAdded +proc colorHash*(self: UserItem): string {.inline.} = + self.colorHash -proc `isAdded=`*(self: Item, value: bool) {.inline.} = - self.isAdded = value +proc `colorHash=`*(self: UserItem, value: string) {.inline.} = + self.colorHash = value -proc joined*(self: Item): bool {.inline.} = - self.joined +proc onlineStatus*(self: UserItem): OnlineStatus {.inline.} = + self.onlineStatus -proc `joined=`*(self: Item, value: bool) {.inline.} = - self.joined = value +proc `onlineStatus=`*(self: UserItem, value: OnlineStatus) {.inline.} = + self.onlineStatus = value + +proc isContact*(self: UserItem): bool {.inline.} = + self.isContact + +proc `isContact=`*(self: UserItem, value: bool) {.inline.} = + self.isContact = value + +proc isVerified*(self: UserItem): bool {.inline.} = + self.isVerified + +proc `isVerified=`*(self: UserItem, value: bool) {.inline.} = + self.isVerified = value + +proc isUntrustworthy*(self: UserItem): bool {.inline.} = + self.isUntrustworthy + +proc `isUntrustworthy=`*(self: UserItem, value: bool) {.inline.} = + self.isUntrustworthy = value + +proc isBlocked*(self: UserItem): bool {.inline.} = + self.isBlocked + +proc `isBlocked=`*(self: UserItem, value: bool) {.inline.} = + self.isBlocked = value + +proc contactRequest*(self: UserItem): ContactRequest {.inline.} = + self.contactRequest + +proc `contactRequest=`*(self: UserItem, value: ContactRequest) {.inline.} = + self.contactRequest = value + +proc incomingVerification*(self: UserItem): VerificationRequest {.inline.} = + self.incomingVerification + +proc `incomingVerification=`*(self: UserItem, value: VerificationRequest) {.inline.} = + self.incomingVerification = value + +proc outcomingVerification*(self: UserItem): VerificationRequest {.inline.} = + self.outcomingVerification + +proc `outcomingVerification=`*(self: UserItem, value: VerificationRequest) {.inline.} = + self.outcomingVerification = value diff --git a/src/app/modules/shared_models/user_model.nim b/src/app/modules/shared_models/user_model.nim index 61e85ab591..dfcf018d5b 100644 --- a/src/app/modules/shared_models/user_model.nim +++ b/src/app/modules/shared_models/user_model.nim @@ -4,21 +4,27 @@ import user_item type ModelRole {.pure.} = enum - Id = UserRole + 1 - Name + PubKey = UserRole + 1 + DisplayName EnsName - Nickname + LocalNickname Alias - OnlineStatus Icon - IsAdded - IsAdmin - Joined + ColorId + ColorHash + OnlineStatus + IsContact + IsVerified + IsUntrustworthy + IsBlocked + ContactRequest + IncomingVerification + OutcomingVerification QtObject: type Model* = ref object of QAbstractListModel - items: seq[Item] + items: seq[UserItem] proc delete(self: Model) = self.items = @[] @@ -33,7 +39,7 @@ QtObject: proc countChanged(self: Model) {.signal.} - proc setItems*(self: Model, items: seq[Item]) = + proc setItems*(self: Model, items: seq[UserItem]) = self.beginResetModel() self.items = items self.endResetModel() @@ -46,7 +52,7 @@ QtObject: """ proc getCount*(self: Model): int {.slot.} = self.items.len - QtProperty[int] count: + QtProperty[int]count: read = getCount notify = countChanged @@ -55,16 +61,22 @@ QtObject: method roleNames(self: Model): Table[int, string] = { - ModelRole.Id.int:"id", - ModelRole.Name.int:"name", - ModelRole.EnsName.int:"ensName", - ModelRole.Nickname.int:"nickname", - ModelRole.Alias.int:"alias", - ModelRole.OnlineStatus.int:"onlineStatus", - ModelRole.Icon.int:"icon", - ModelRole.IsAdded.int:"isAdded", - ModelRole.IsAdmin.int:"isAdmin", - ModelRole.Joined.int:"joined", + ModelRole.PubKey.int: "pubKey", + ModelRole.DisplayName.int: "displayName", + ModelRole.EnsName.int: "ensName", + ModelRole.LocalNickname.int: "localNickname", + ModelRole.Alias.int: "alias", + ModelRole.Icon.int: "icon", + ModelRole.ColorId.int: "colorId", + ModelRole.ColorHash.int: "colorHash", + ModelRole.OnlineStatus.int: "onlineStatus", + ModelRole.IsContact.int: "isContact", + ModelRole.IsVerified.int: "isVerified", + ModelRole.IsUntrustworthy.int: "isUntrustworthy", + ModelRole.IsBlocked.int: "isBlocked", + ModelRole.ContactRequest.int: "contactRequest", + ModelRole.IncomingVerification.int: "incomingVerification", + ModelRole.OutcomingVerification.int: "outcomingVerification", }.toTable method data(self: Model, index: QModelIndex, role: int): QVariant = @@ -78,28 +90,54 @@ QtObject: let enumRole = role.ModelRole case enumRole: - of ModelRole.Id: - result = newQVariant(item.id) - of ModelRole.Name: - result = newQVariant(item.name) + of ModelRole.PubKey: + result = newQVariant(item.pubKey) + of ModelRole.DisplayName: + result = newQVariant(item.displayName) of ModelRole.EnsName: result = newQVariant(item.ensName) - of ModelRole.Nickname: + of ModelRole.LocalNickname: result = newQVariant(item.localNickname) of ModelRole.Alias: result = newQVariant(item.alias) - of ModelRole.OnlineStatus: - result = newQVariant(item.onlineStatus.int) of ModelRole.Icon: result = newQVariant(item.icon) - of ModelRole.IsAdded: - result = newQVariant(item.isAdded) - of ModelRole.IsAdmin: - result = newQVariant(item.isAdmin) - of ModelRole.Joined: - result = newQVariant(item.joined) + of ModelRole.ColorId: + result = newQVariant(item.colorId) + of ModelRole.ColorHash: + result = newQVariant(item.colorHash) + of ModelRole.OnlineStatus: + result = newQVariant(item.onlineStatus.int) + of ModelRole.IsContact: + result = newQVariant(item.isContact) + of ModelRole.IsVerified: + result = newQVariant(item.isVerified) + of ModelRole.IsUntrustworthy: + result = newQVariant(item.isUntrustworthy) + of ModelRole.IsBlocked: + result = newQVariant(item.isBlocked) + of ModelRole.ContactRequest: + result = newQVariant(item.contactRequest.int) + of ModelRole.IncomingVerification: + result = newQVariant(item.incomingVerification.int) + of ModelRole.OutcomingVerification: + result = newQVariant(item.outcomingVerification.int) - proc addItem*(self: Model, item: Item) = + proc addItems*(self: Model, items: seq[UserItem]) = + if(items.len == 0): + return + + let parentModelIndex = newQModelIndex() + defer: parentModelIndex.delete + + let first = self.items.len + let last = first + items.len - 1 + self.beginInsertRows(parentModelIndex, first, last) + self.items.add(items) + self.endInsertRows() + self.countChanged() + + 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) @@ -120,9 +158,15 @@ QtObject: self.endInsertRows() self.countChanged() - proc findIndexForMessageId(self: Model, id: string): int = + proc clear*(self: Model) = + self.beginResetModel() + self.items = @[] + self.endResetModel() + +# TODO: rename to `findIndexForMessagePubkey` + proc findIndexForMessageId(self: Model, pubKey: string): int = for i in 0 ..< self.items.len: - if(self.items[i].id == id): + if(self.items[i].pubKey == pubKey): return i return -1 @@ -136,27 +180,29 @@ QtObject: self.endRemoveRows() self.countChanged() +# TODO: rename to `containsItem` proc isContactWithIdAdded*(self: Model, id: string): bool = return self.findIndexForMessageId(id) != -1 - proc setName*(self: Model, id: string, name: string, ensName: string, nickname: string) = - let ind = self.findIndexForMessageId(id) + proc setName*(self: Model, pubKey: string, displayName: string, + ensName: string, localNickname: string) = + let ind = self.findIndexForMessageId(pubKey) if(ind == -1): return - self.items[ind].name = name + self.items[ind].displayName = displayName self.items[ind].ensName = ensName - self.items[ind].localNickname = nickname + self.items[ind].localNickname = localNickname let index = self.createIndex(ind, 0, nil) self.dataChanged(index, index, @[ - ModelRole.Name.int, + ModelRole.DisplayName.int, ModelRole.EnsName.int, - ModelRole.Nickname.int, + ModelRole.LocalNickname.int, ]) - proc setIcon*(self: Model, id: string, icon: string) = - let ind = self.findIndexForMessageId(id) + proc setIcon*(self: Model, pubKey: string, icon: string) = + let ind = self.findIndexForMessageId(pubKey) if(ind == -1): return @@ -167,43 +213,51 @@ QtObject: proc updateItem*( self: Model, - id: string, - name: string, + pubKey: string, + displayName: string, ensName: string, localNickname: string, alias: string, - icon: string, - isAdded: bool = false, - isAdmin: bool = false, - joined: bool = false + icon: string ) = - let ind = self.findIndexForMessageId(id) + let ind = self.findIndexForMessageId(pubKey) if(ind == -1): return - self.items[ind].name = name + self.items[ind].displayName = displayName self.items[ind].ensName = ensName self.items[ind].localNickname = localNickname self.items[ind].alias = alias self.items[ind].icon = icon - self.items[ind].isAdded = isAdded - self.items[ind].isAdmin = isAdmin - self.items[ind].joined = joined let index = self.createIndex(ind, 0, nil) self.dataChanged(index, index, @[ - ModelRole.Name.int, + ModelRole.DisplayName.int, ModelRole.EnsName.int, - ModelRole.Nickname.int, + ModelRole.LocalNickname.int, ModelRole.Alias.int, ModelRole.Icon.int, - ModelRole.IsAdded.int, - ModelRole.IsAdmin.int, - ModelRole.Joined.int, + ]) + + proc updateName*( + self: Model, + pubKey: string, + displayName: string + ) = + let ind = self.findIndexForMessageId(pubKey) + if(ind == -1): + return + + self.items[ind].displayName = displayName + + let index = self.createIndex(ind, 0, nil) + self.dataChanged(index, index, @[ + ModelRole.DisplayName.int ]) - proc setOnlineStatus*(self: Model, id: string, onlineStatus: OnlineStatus) = - let ind = self.findIndexForMessageId(id) + proc setOnlineStatus*(self: Model, pubKey: string, + onlineStatus: OnlineStatus) = + let ind = self.findIndexForMessageId(pubKey) if(ind == -1): return @@ -215,12 +269,14 @@ QtObject: self.removeItemWithIndex(ind) self.addItem(item) - proc removeItemById*(self: Model, id: string) = - let ind = self.findIndexForMessageId(id) +# TODO: rename me to removeItemByPubkey + proc removeItemById*(self: Model, pubKey: string) = + let ind = self.findIndexForMessageId(pubKey) if(ind == -1): return self.removeItemWithIndex(ind) +# TODO: rename me to getItemsAsPubkeys proc getItemIds*(self: Model): seq[string] = - return self.items.map(i => i.id) + return self.items.map(i => i.pubKey) diff --git a/ui/StatusQ b/ui/StatusQ index 0e73530b05..5361b56e9f 160000 --- a/ui/StatusQ +++ b/ui/StatusQ @@ -1 +1 @@ -Subproject commit 0e73530b0527627029e90f66bd611392c639b16e +Subproject commit 5361b56e9fb42c33d56257f1a2aa19946d1daf36 diff --git a/ui/app/AppLayouts/Chat/panels/SuggestionFilterPanel.qml b/ui/app/AppLayouts/Chat/panels/SuggestionFilterPanel.qml index 116c773094..329c89209d 100644 --- a/ui/app/AppLayouts/Chat/panels/SuggestionFilterPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/SuggestionFilterPanel.qml @@ -27,13 +27,13 @@ Item { visible: false model: suggestionsPanelRoot.sourceModel delegate: Item { - property string publicKey: model.id - property string name: model.name - property string nickname: model.nickname + property string publicKey: model.pubKey + property string name: model.displayName + property string nickname: model.localNickname property string alias: model.alias property string ensName: model.ensName property string icon: model.icon - property bool isAdded: model.isAdded + property bool isAdded: model.isContact } } diff --git a/ui/app/AppLayouts/Chat/panels/UserListPanel.qml b/ui/app/AppLayouts/Chat/panels/UserListPanel.qml index f28dde47c8..a9a3ff70f5 100644 --- a/ui/app/AppLayouts/Chat/panels/UserListPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/UserListPanel.qml @@ -63,24 +63,25 @@ Item { anchors.right: parent.right anchors.rightMargin: 8 nickName: model.localNickname - userName: model.name - chatKey: model.id - trustIndicator: model.trustIndicator - isMutualContact: model.isMutualContact + userName: model.displayName + pubKey: model.pubKey + isContact: model.isContact + isVerified: model.isVerified + isUntrustworthy: model.isUntrustworthy isAdmin: model.isAdmin image.source: { - if ((!model.isAdded && + if ((!model.isContact && Global.privacyModuleInst.profilePicturesVisibility !== Constants.profilePicturesVisibility.everyone)) { return ""; } return model.icon; } - image.isIdenticon: model.isIdenticon + image.isIdenticon: false - isOnline: model.onlineStatus - icon.color: Theme.palette.userCustomizationColors[Utils.colorIdForPubkey(model.id)] - ringSettings.ringSpecModel: Utils.getColorHashAsJson(model.id) + status: model.onlineStatus + icon.color: Theme.palette.userCustomizationColors[Utils.colorIdForPubkey(model.pubKey)] // FIXME: use model.colorId + ringSettings.ringSpecModel: Utils.getColorHashAsJson(model.pubKey) // FIXME: use model.colorHash onClicked: { if (mouse.button === Qt.RightButton) { // Set parent, X & Y positions for the messageContextMenu @@ -89,12 +90,12 @@ Item { messageContextMenu.setYPosition = function() { return mouse.y + (Style.current.halfPadding/2); } messageContextMenu.isProfile = true messageContextMenu.myPublicKey = userProfile.pubKey - messageContextMenu.selectedUserPublicKey = model.id - messageContextMenu.selectedUserDisplayName = model.name + messageContextMenu.selectedUserPublicKey = model.pubKey + messageContextMenu.selectedUserDisplayName = model.displayName messageContextMenu.selectedUserIcon = image.source messageContextMenu.popup() } else if (mouse.button === Qt.LeftButton && !!messageContextMenu) { - Global.openProfilePopup(model.id); + Global.openProfilePopup(model.pubKey); } } } diff --git a/ui/app/AppLayouts/Chat/panels/communities/CommunityMembersSettingsPanel.qml b/ui/app/AppLayouts/Chat/panels/communities/CommunityMembersSettingsPanel.qml index 018b33a628..aca7071cdb 100644 --- a/ui/app/AppLayouts/Chat/panels/communities/CommunityMembersSettingsPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/communities/CommunityMembersSettingsPanel.qml @@ -94,7 +94,7 @@ SettingsPageLayout { delegate: StatusListItem { id: memberItem - readonly property bool itsMe: model.id.toLowerCase() === userProfile.pubKey.toLowerCase() + readonly property bool itsMe: model.pubKey.toLowerCase() === userProfile.pubKey.toLowerCase() readonly property bool isOnline: model.onlineStatus === Constants.userStatus.online width: memberList.width @@ -108,12 +108,12 @@ SettingsPageLayout { //% "You" return qsTrId("You") } - return !model.name.endsWith(".eth") ? model.name : Utils.removeStatusEns(model.name) + return !model.displayName.endsWith(".eth") ? model.displayName : Utils.removeStatusEns(model.displayName) } - subTitle: Utils.getElidedCompressedPk(model.id) + subTitle: Utils.getElidedCompressedPk(model.pubKey) statusListItemIcon { - name: model.name + name: model.displayName badge { visible: true color: memberItem.isOnline ? Theme.palette.successColor1 : Theme.palette.baseColor1 @@ -129,18 +129,18 @@ SettingsPageLayout { icon { width: 40 height: 40 - color: Utils.colorForPubkey(model.id) + color: Utils.colorForPubkey(model.pubKey) letterSize: Math.max(4, root.imageWidth / 2.4) charactersLen: 2 isLetterIdenticon: true } ringSettings { - ringSpecModel: Utils.getColorHashAsJson(model.id) + ringSpecModel: Utils.getColorHashAsJson(model.pubKey) ringPxSize: Math.max(icon.width / 24.0) } - onClicked: root.userProfileClicked(model.id) + onClicked: root.userProfileClicked(model.pubKey) components: [ StatusButton { @@ -149,7 +149,7 @@ SettingsPageLayout { type: StatusBaseButton.Type.Danger size: StatusBaseButton.Size.Tiny - onClicked: root.banUserClicked(model.id) + onClicked: root.banUserClicked(model.pubKey) }, StatusButton { @@ -158,7 +158,7 @@ SettingsPageLayout { type: StatusBaseButton.Type.Danger size: StatusBaseButton.Size.Tiny - onClicked: root.kickUserClicked(model.id) + onClicked: root.kickUserClicked(model.pubKey) } ] } diff --git a/ui/app/AppLayouts/Profile/panels/ContactPanel.qml b/ui/app/AppLayouts/Profile/panels/ContactPanel.qml index 9ebac9df0f..c53190b1db 100644 --- a/ui/app/AppLayouts/Profile/panels/ContactPanel.qml +++ b/ui/app/AppLayouts/Profile/panels/ContactPanel.qml @@ -28,7 +28,8 @@ StatusListItem { property string icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=" property bool isMutualContact: false property bool isBlocked: false - property int verificationState: Constants.contactVerificationState.notMarked + property bool isVerified: false + property bool isUntrustworthy: false property string searchStr: "" diff --git a/ui/app/AppLayouts/Profile/panels/ContactsListPanel.qml b/ui/app/AppLayouts/Profile/panels/ContactsListPanel.qml index 408be0c26c..c59c718057 100644 --- a/ui/app/AppLayouts/Profile/panels/ContactsListPanel.qml +++ b/ui/app/AppLayouts/Profile/panels/ContactsListPanel.qml @@ -52,11 +52,11 @@ Item { for (var i = 0; i < items.count; ++i) { var item = items.get(i); if (panelUsage === Constants.contactsPanelUsage.verifiedMutualContacts) { - if(item.model.verificationState === Constants.contactVerificationState.verified) + if(item.model.isVerified) visible.push(item); } - else if (panelUsage === Constants.contactsPanelUsage.mutualContacts) { - if(item.model.verificationState !== Constants.contactVerificationState.verified) + else if(panelUsage === Constants.contactsPanelUsage.mutualContacts) { + if(!item.model.isVerified) visible.push(item); } else { @@ -101,16 +101,17 @@ Item { ContactPanel { id: panelDelegate - name: model.name + name: model.displayName publicKey: model.pubKey icon: model.icon - isMutualContact: model.isMutualContact + isMutualContact: model.isContact isBlocked: model.isBlocked - verificationState: model.verificationState + isVerified: model.isVerified + isUntrustworthy: model.isUntrustworthy searchStr: contactListRoot.searchString - showSendMessageButton: model.isMutualContact + showSendMessageButton: model.isContact showRejectContactRequestButton: { if (contactListRoot.panelUsage === Constants.contactsPanelUsage.receivedContactRequest) { return true