From 060072da2d78cac236096fa919ac11429113e062 Mon Sep 17 00:00:00 2001 From: Michal Iskierko Date: Tue, 4 Oct 2022 16:21:19 +0200 Subject: [PATCH] fix(@desktop/chat): Fix moving channels between categories Fix #7422 --- .../modules/main/chat_section/controller.nim | 4 +- .../main/chat_section/io_interface.nim | 2 +- src/app/modules/main/chat_section/model.nim | 111 +++++++++++++++--- src/app/modules/main/chat_section/module.nim | 9 +- .../modules/main/chat_section/sub_item.nim | 3 +- src/app_service/service/community/service.nim | 13 +- 6 files changed, 113 insertions(+), 29 deletions(-) diff --git a/src/app/modules/main/chat_section/controller.nim b/src/app/modules/main/chat_section/controller.nim index b5f1fa05b3..c37c32a04b 100644 --- a/src/app/modules/main/chat_section/controller.nim +++ b/src/app/modules/main/chat_section/controller.nim @@ -159,7 +159,7 @@ proc init*(self: Controller) = self.events.on(SIGNAL_COMMUNITY_CATEGORY_REORDERED) do(e:Args): let args = CommunityChatOrderArgs(e) if (args.communityId == self.sectionId): - self.delegate.onReorderChatOrCategory(args.categoryId, args.position) + self.delegate.onReorderChatOrCategory(args.categoryId, args.position, args.categoryId) self.events.on(SIGNAL_COMMUNITY_CATEGORY_NAME_EDITED) do(e:Args): let args = CommunityCategoryArgs(e) @@ -169,7 +169,7 @@ proc init*(self: Controller) = self.events.on(SIGNAL_COMMUNITY_CHANNEL_REORDERED) do(e:Args): let args = CommunityChatOrderArgs(e) if (args.communityId == self.sectionId): - self.delegate.onReorderChatOrCategory(args.chatId, args.position) + self.delegate.onReorderChatOrCategory(args.chatId, args.position, args.categoryId) self.events.on(SIGNAL_RELOAD_MESSAGES) do(e: Args): let args = ReloadMessagesArgs(e) diff --git a/src/app/modules/main/chat_section/io_interface.nim b/src/app/modules/main/chat_section/io_interface.nim index 40eccad618..ac2e5a987f 100644 --- a/src/app/modules/main/chat_section/io_interface.nim +++ b/src/app/modules/main/chat_section/io_interface.nim @@ -121,7 +121,7 @@ method onGroupChatDetailsUpdated*(self: AccessInterface, chatId: string, newName method onCommunityChannelEdited*(self: AccessInterface, chat: ChatDto) {.base.} = raise newException(ValueError, "No implementation available") -method onReorderChatOrCategory*(self: AccessInterface, chatOrCatId: string, position: int) {.base.} = +method onReorderChatOrCategory*(self: AccessInterface, chatOrCatId: string, position: int, newCategoryIdForChat: string) {.base.} = raise newException(ValueError, "No implementation available") method onCommunityCategoryCreated*(self: AccessInterface, category: Category, chats: seq[ChatDto]) {.base.} = diff --git a/src/app/modules/main/chat_section/model.nim b/src/app/modules/main/chat_section/model.nim index 4edb987ce8..f19baddc8d 100644 --- a/src/app/modules/main/chat_section/model.nim +++ b/src/app/modules/main/chat_section/model.nim @@ -173,8 +173,15 @@ QtObject: idx.inc return -1 - proc removeItemById*(self: Model, id: string) = - let idx = self.getItemIdxById(id) + proc getItemIdxByCategory*(self: Model, category: string): int = + var idx = 0 + for it in self.items: + if(it.categoryId == category): + return idx + idx.inc + return -1 + + proc removeItemByIndex(self: Model, idx: int) = if idx == -1: return @@ -187,6 +194,23 @@ QtObject: self.countChanged() + proc removeItemById*(self: Model, id: string) = + let idx = self.getItemIdxById(id) + if idx != -1: + self.removeItemByIndex(idx) + + proc removeItemOrSubitemById*(self: Model, id: string) = + let idx = self.getItemIdxById(id) + if idx != -1: + self.removeItemByIndex(idx) + return + else: + for it in self.items: + let subItemIndex = it.subItems.getItemIdxById(id) + if subItemIndex != -1: + it.subItems.removeItemById(id) + return + proc getItemAtIndex*(self: Model, index: int): Item = if(index < 0 or index >= self.items.len): return @@ -204,6 +228,17 @@ QtObject: if(it.id == id): return it + proc getCategoryAndPosition*(self: Model, id: string): (string, int) = + let item = self.getItemById(id) + if (not item.isNil): + return ("", item.position) + else: + for it in self.items: + let item = it.subItems.getItemById(id) + if(not item.isNil): + return (it.categoryId, item.position) + return ("", -1) + proc getSubItemById*(self: Model, id: string): SubItem = for it in self.items: let item = it.subItems.getItemById(id) @@ -234,6 +269,14 @@ QtObject: if(found): return jsonObj + proc getItemOrSubItemByIdAsBase*(self: Model, id: string): BaseItem = + for it in self.items: + if(it.id == id): + return BaseItem(it) + let subItem = it.subItems.getItemById(id) + if (not subItem.isNil): + return BaseItem(subItem) + proc muteUnmuteItemOrSubItemById*(self: Model, id: string, mute: bool) = for i in 0 ..< self.items.len: if(self.items[i].id == id): @@ -353,24 +396,64 @@ QtObject: result.hasNotifications = result.hasNotifications or self.items[i].BaseItem.hasUnreadMessages result.notificationsCount = result.notificationsCount + self.items[i].BaseItem.notificationsCount + proc reorderModel*(self: Model, id: string, position: int) = + let index = self.getItemIdxById(id) + if index == -1: + return + if(self.items[index].BaseItem.position == position): + return + self.items[index].BaseItem.position = position + let modelIndex = self.createIndex(index, 0, nil) + self.dataChanged(modelIndex, modelIndex, @[ModelRole.Position.int]) + proc reorderSubModel(self: Model, chatId: string, position: int) = for it in self.items: if(it.subItems.getCount() > 0): it.subItems.reorder(chatId, position) - proc reorder*(self: Model, chatOrCategoryId: string, position: int) = - let index = self.getItemIdxById(chatOrCategoryId) - if(index == -1): - self.reorderSubModel(chatOrCategoryId, position) + proc moveItemFromTo(self: Model, chatId: string, oldCategoryId: string, oldPosition: int, newCategoryId: string, newPosition: int) = + if (oldCategoryId == newCategoryId): + # move position only + if (oldCategoryId == ""): + self.reorderModel(chatId, newPosition) + else: + self.reorderSubModel(chatId, newPosition) + else: + # move between categories + let baseItemToMove = self.getItemOrSubItemByIdAsBase(chatId) + var oldCategoryItem = self.getItemById(oldCategoryId) + + if not oldCategoryItem.isNil: + oldCategoryItem.subItems().removeItemById(chatId) + else: + self.removeItemById(chatId) + + if newCategoryId != "": + let channelItem = initSubItem(baseItemToMove.id, newCategoryId, baseItemToMove.name, baseItemToMove.icon, + baseItemToMove.color, baseItemToMove.emoji, baseItemToMove.description, baseItemToMove.type, + baseItemToMove.amIChatAdmin, baseItemToMove.lastMessageTimestamp, baseItemToMove.hasUnreadMessages, + baseItemToMove.notificationsCount, baseItemToMove.muted, baseItemToMove.blocked, + baseItemToMove.active, newPosition) + let newCategoryItem = self.getItemById(newCategoryId) + newCategoryItem.appendSubItem(channelItem) + else: + let channelItem = initItem(baseItemToMove.id, baseItemToMove.name, baseItemToMove.icon, + baseItemToMove.color, baseItemToMove.emoji, baseItemToMove.description, baseItemToMove.type, baseItemToMove.amIChatAdmin, + baseItemToMove.lastMessageTimestamp, baseItemToMove.hasUnreadMessages, baseItemToMove.notificationsCount, + baseItemToMove.muted, baseItemToMove.blocked, baseItemToMove.active, newPosition, categoryId="") + self.appendItem(channelItem) + + + proc reorder*(self: Model, chatOrCategoryId: string, position: int, newCategoryIdForChat: string) = + let indexOfCategoryItem = self.getItemIdxByCategory(chatOrCategoryId) # chats have empty categoryId + if(indexOfCategoryItem == -1): + # reorder chat + let (currentCat, currentPos) = self.getCategoryAndPosition(chatOrCategoryId) + if (currentPos != -1): + self.moveItemFromTo(chatOrCategoryId, currentCat, currentPos, newCategoryIdForChat, position) return - - if(self.items[index].BaseItem.position == position): - return - - self.items[index].BaseItem.position = position - - let modelIndex = self.createIndex(index, 0, nil) - self.dataChanged(modelIndex, modelIndex, @[ModelRole.Position.int]) + # reorder categories + self.reorderModel(chatOrCategoryId, position) proc clearItems*(self: Model) = self.beginResetModel() diff --git a/src/app/modules/main/chat_section/module.nim b/src/app/modules/main/chat_section/module.nim index 9ac2b834d0..a7e40d7146 100644 --- a/src/app/modules/main/chat_section/module.nim +++ b/src/app/modules/main/chat_section/module.nim @@ -433,7 +433,7 @@ method addNewChat*( if chatDto.categoryId.len == 0: let item = initItem(chatDto.id, chatName, chatImage, chatDto.color, chatDto.emoji, chatDto.description, chatDto.chatType.int, amIChatAdmin, chatDto.timestamp.int, hasNotification, notificationsCount, - chatDto.muted, blocked=false, active=false, position = 0, chatDto.categoryId, colorId, colorHash, chatDto.highlight, + chatDto.muted, blocked=false, active=false, chatDto.position, chatDto.categoryId, colorId, colorHash, chatDto.highlight, onlineStatus = onlineStatus) self.addSubmodule(chatDto.id, belongsToCommunity, isUsersListAvailable, events, settingsService, contactService, chatService, communityService, messageService, gifService, mailserversService) @@ -480,7 +480,6 @@ method doesTopLevelChatExist*(self: Module, chatId: string): bool = method removeCommunityChat*(self: Module, chatId: string) = if(not self.chatContentModules.contains(chatId)): return - self.controller.removeCommunityChat(chatId) method onCommunityCategoryCreated*(self: Module, cat: Category, chats: seq[ChatDto]) = @@ -537,8 +536,8 @@ method setFirstChannelAsActive*(self: Module) = let subItem = item.subItems.getItemAtIndex(0) self.setActiveItemSubItem(item.id, subItem.id) -method onReorderChatOrCategory*(self: Module, chatOrCatId: string, position: int) = - self.view.chatsModel().reorder(chatOrCatId, position) +method onReorderChatOrCategory*(self: Module, chatOrCatId: string, position: int, newCategoryIdForChat: string) = + self.view.chatsModel().reorder(chatOrCatId, position, newCategoryIdForChat) method onCategoryNameChanged*(self: Module, category: Category) = self.view.chatsModel().renameItem(category.id, category.name) @@ -572,7 +571,7 @@ method onCommunityCategoryEdited*(self: Module, cat: Category, chats: seq[ChatDt method onCommunityChannelDeletedOrChatLeft*(self: Module, chatId: string) = if(not self.chatContentModules.contains(chatId)): return - self.view.chatsModel().removeItemById(chatId) + self.view.chatsModel().removeItemOrSubitemById(chatId) self.removeSubmodule(chatId) self.setFirstChannelAsActive() diff --git a/src/app/modules/main/chat_section/sub_item.nim b/src/app/modules/main/chat_section/sub_item.nim index f29cba5c11..65d2bd9da3 100644 --- a/src/app/modules/main/chat_section/sub_item.nim +++ b/src/app/modules/main/chat_section/sub_item.nim @@ -57,5 +57,6 @@ proc toJsonNode*(self: SubItem): JsonNode = "muted": self.muted, "blocked": self.blocked, "active": self.active, - "position": self.position + "position": self.position, + "categoryId": "" } diff --git a/src/app_service/service/community/service.nim b/src/app_service/service/community/service.nim index 22af670e3f..e27074451b 100644 --- a/src/app_service/service/community/service.nim +++ b/src/app_service/service/community/service.nim @@ -187,7 +187,6 @@ QtObject: self.events.on(SignalType.Message.event) do(e: Args): var receivedData = MessageSignal(e) - # Handling community updates if (receivedData.communities.len > 0): # Channel added removed is notified in the chats param @@ -305,7 +304,6 @@ QtObject: proc handleCommunityUpdates(self: Service, communities: seq[CommunityDto], updatedChats: seq[ChatDto]) = var community = communities[0] - if(not self.allCommunities.hasKey(community.id)): self.allCommunities[community.id] = community self.events.emit(SIGNAL_COMMUNITY_ADDED, CommunityArgs(community: community)) @@ -391,7 +389,7 @@ QtObject: # but something is different for prev_chat in prev_community.chats: # Handle position changes - if(chat.id == prev_chat.id and chat.position != prev_chat.position): + if(chat.id == prev_chat.id and (chat.position != prev_chat.position or chat.categoryId != prev_chat.categoryId)): self.events.emit(SIGNAL_COMMUNITY_CHANNEL_REORDERED, CommunityChatOrderArgs(communityId: community.id, chatId: chat.id, categoryId: chat.categoryId, position: chat.position)) @@ -913,9 +911,14 @@ QtObject: if(not response.result.getProp("chats", chatsJArr)): raise newException(RpcException, fmt"createCommunityChannel; there is no `chats` key in the response for community id: {communityId}") + let chatsForCategory = self.getChats(communityId, categoryId) + let maxPosition = if chatsForCategory.len > 0: chatsForCategory[^1].position else: -1 + for chatObj in chatsJArr: var chatDto = chatObj.toChatDto(communityId) + chatDto.position = maxPosition + 1 self.chatService.updateOrAddChat(chatDto) + self.joinedCommunities[communityId].chats.add(chatDto) let data = CommunityChatArgs(chat: chatDto) self.events.emit(SIGNAL_COMMUNITY_CHANNEL_CREATED, data) except Exception as e: @@ -1004,7 +1007,6 @@ QtObject: proc deleteCommunityChat*(self: Service, communityId: string, chatId: string) = try: let response = status_go.deleteCommunityChat(communityId, chatId) - if not response.error.isNil: let error = Json.decode($response.error, RpcError) raise newException(RpcException, "Error deleting community chat: " & error.message) @@ -1012,8 +1014,7 @@ QtObject: if response.result.isNil or response.result.kind == JNull: error "response is invalid", procName="deleteCommunityChat" - var shortChatId = chatId.replace(communityId, "") - let idx = findIndexById(shortChatId, self.joinedCommunities[communityId].chats) + let idx = findIndexById(chatId, self.joinedCommunities[communityId].chats) if (idx != -1): self.joinedCommunities[communityId].chats.delete(idx)