refactor(section-model): change model to be sorted to fix reorder

Part of #3364

To make the drag and drop reorder work correctly on channels, we needed to change the model again so that it was sorted in the model itself.
That is because the drag and drop gives us the value of the position it is dropped to as a single list, so dragging the second item of the second category would mean from position 5 to position to position 4, but what the backend wants is moving the item 2 to position 1.
Sorting the model enables us to get the category that is the parent of that position and call the service with the right positions and id.
It also enables us to reorder the channel in and out of the category.
See the module code to see how the calculation is done with an explanatory comment.
The model needed some changes to support that. Some of the function where changed from dataChange calls to resetModel calls, since we need to re-sort the model.
I tried using beginMove, but it would crash. Maybe there is a bug in NimQML or I used it badly, I'm not sure.
This commit is contained in:
Jonathan Rainville 2023-04-13 15:19:00 -04:00
parent f507e33cba
commit 2aa759adcf
12 changed files with 201 additions and 124 deletions

View File

@ -51,12 +51,12 @@ proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitt
result.view = view.newView(result) result.view = view.newView(result)
result.viewVariant = newQVariant(result.view) result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events, sectionId, chatId, belongsToCommunity, result.controller = controller.newController(result, events, sectionId, chatId, belongsToCommunity,
isUsersListAvailable, settingsService, nodeConfigurationService, contactService, chatService, communityService, messageService) isUsersListAvailable, settingsService, nodeConfigurationService, contactService, chatService, communityService, messageService)
result.moduleLoaded = false result.moduleLoaded = false
result.inputAreaModule = input_area_module.newModule(result, events, sectionId, chatId, belongsToCommunity, chatService, communityService, gifService) result.inputAreaModule = input_area_module.newModule(result, events, sectionId, chatId, belongsToCommunity, chatService, communityService, gifService)
result.messagesModule = messages_module.newModule(result, events, sectionId, chatId, belongsToCommunity, result.messagesModule = messages_module.newModule(result, events, sectionId, chatId, belongsToCommunity,
contactService, communityService, chatService, messageService, mailserversService) contactService, communityService, chatService, messageService, mailserversService)
result.usersModule = result.usersModule =
if communityUsersModule == nil: if communityUsersModule == nil:
users_module.newModule( events, sectionId, chatId, belongsToCommunity, users_module.newModule( events, sectionId, chatId, belongsToCommunity,

View File

@ -230,7 +230,7 @@ proc init*(self: Controller) =
self.delegate.onCommunityCategoryEdited(args.category, args.chats) self.delegate.onCommunityCategoryEdited(args.category, args.chats)
self.events.on(SIGNAL_COMMUNITY_CATEGORY_REORDERED) do(e:Args): self.events.on(SIGNAL_COMMUNITY_CATEGORY_REORDERED) do(e:Args):
let args = CommunityChatOrderArgs(e) let args = CommunityCategoryOrderArgs(e)
if (args.communityId == self.sectionId): if (args.communityId == self.sectionId):
self.delegate.onReorderCategory(args.categoryId, args.position) self.delegate.onReorderCategory(args.categoryId, args.position)
@ -242,12 +242,17 @@ proc init*(self: Controller) =
self.events.on(SIGNAL_COMMUNITY_CHANNEL_REORDERED) do(e:Args): self.events.on(SIGNAL_COMMUNITY_CHANNEL_REORDERED) do(e:Args):
let args = CommunityChatOrderArgs(e) let args = CommunityChatOrderArgs(e)
if (args.communityId == self.sectionId): if (args.communityId == self.sectionId):
self.delegate.onReorderChat(args.chatId, args.position, args.categoryId, args.prevCategoryId, false) self.delegate.onReorderChat(args.chat)
self.events.on(SIGNAL_COMMUNITY_CHANNELS_REORDERED) do(e:Args):
let args = CommunityChatsOrderArgs(e)
if (args.communityId == self.sectionId):
self.delegate.onReorderChats(args.chats)
self.events.on(SIGNAL_COMMUNITY_CHANNEL_CATEGORY_CHANGED) do(e:Args): self.events.on(SIGNAL_COMMUNITY_CHANNEL_CATEGORY_CHANGED) do(e:Args):
let args = CommunityChatOrderArgs(e) let args = CommunityChatOrderArgs(e)
if (args.communityId == self.sectionId): if (args.communityId == self.sectionId):
self.delegate.onReorderChat(args.chatId, args.position, args.categoryId, args.prevCategoryId, args.prevCategoryDeleted) self.delegate.onReorderChat(args.chat)
self.events.on(SIGNAL_RELOAD_MESSAGES) do(e: Args): self.events.on(SIGNAL_RELOAD_MESSAGES) do(e: Args):
let args = ReloadMessagesArgs(e) let args = ReloadMessagesArgs(e)

View File

@ -141,7 +141,10 @@ method onGroupChatDetailsUpdated*(self: AccessInterface, chatId: string, newName
method onCommunityChannelEdited*(self: AccessInterface, chat: ChatDto) {.base.} = method onCommunityChannelEdited*(self: AccessInterface, chat: ChatDto) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method onReorderChat*(self: AccessInterface, chattId: string, position: int, newCategoryIdForChat: string, prevCategoryId: string, prevCategoryDeleted: bool) {.base.} = method onReorderChat*(self: AccessInterface, updatedChat: ChatDto) {.base.} =
raise newException(ValueError, "No implementation available")
method onReorderChats*(self: AccessInterface, updatedChats: seq[ChatDto]) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method onReorderCategory*(self: AccessInterface, catId: string, position: int) {.base.} = method onReorderCategory*(self: AccessInterface, catId: string, position: int) {.base.} =

View File

@ -273,4 +273,7 @@ proc loaderActive*(self: Item): bool =
self.loaderActive self.loaderActive
proc `loaderActive=`*(self: var Item, value: bool) = proc `loaderActive=`*(self: var Item, value: bool) =
self.loaderActive = value self.loaderActive = value
proc isCategory*(self: Item): bool =
self.`type` == CATEGORY_TYPE

View File

@ -1,4 +1,4 @@
import NimQml, Tables, strutils, strformat, json, sequtils import NimQml, Tables, strutils, strformat, json, sequtils, algorithm
import ../../../../app_service/common/types import ../../../../app_service/common/types
import ../../../../app_service/service/chat/dto/chat import ../../../../app_service/service/chat/dto/chat
from ../../../../app_service/service/contacts/dto/contacts import TrustStatus from ../../../../app_service/service/contacts/dto/contacts import TrustStatus
@ -159,28 +159,63 @@ QtObject:
of ModelRole.OnlineStatus: of ModelRole.OnlineStatus:
result = newQVariant(item.onlineStatus.int) result = newQVariant(item.onlineStatus.int)
of ModelRole.IsCategory: of ModelRole.IsCategory:
result = newQVariant(item.`type` == CATEGORY_TYPE) result = newQVariant(item.isCategory)
of ModelRole.LoaderActive: of ModelRole.LoaderActive:
result = newQVariant(item.loaderActive) result = newQVariant(item.loaderActive)
proc appendItem*(self: Model, item: Item) = proc getItemIdxById(items: seq[Item], id: string): int =
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len)
self.items.add(item)
self.endInsertRows()
self.countChanged()
proc getItemIdxById*(self: Model, id: string): int =
var idx = 0 var idx = 0
for it in self.items: for it in items:
if(it.id == id): if(it.id == id):
return idx return idx
idx.inc idx.inc
return -1 return -1
proc getItemIdxById*(self: Model, id: string): int =
return getItemIdxById(self.items, id)
proc getClosestCategoryAtIndex*(self: Model, index: int): tuple[categoryIem: Item, categoryIndex: int] =
if index > self.items.len:
return (Item(), -1)
# Count down from the index to 0 and find the first category
for i in countdown(index - 1, 0):
if self.items[i].isCategory:
return (self.items[i], i)
return (Item(), -1)
proc cmpChatsAndCats*(x, y: Item): int =
# Sort proc to compare chats and categories
# Compares first by categoryPosition, then by position
result = cmp(x.categoryPosition, y.categoryPosition)
if result == 0:
result = cmp(x.position, y.position)
# IMPORTANT: if you call this function for a chat with a category, make sure the category is appended first
proc appendItem*(self: Model, item: Item, ignoreCategory: bool = false) =
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
var indexToInsertTo = item.position
if item.categoryId != "" and not item.isCategory:
if ignoreCategory:
# We don't care about the category position, just position it at the end
indexToInsertTo = self.items.len
else:
let categoryIdx = self.getItemIdxById(item.categoryId)
if categoryIdx == -1:
return
indexToInsertTo = categoryIdx + item.position + 1
if indexToInsertTo < 0:
indexToInsertTo = 0
elif indexToInsertTo >= self.items.len + 1:
indexToInsertTo = self.items.len
self.beginInsertRows(parentModelIndex, indexToInsertTo, indexToInsertTo)
self.items.insert(item, indexToInsertTo)
self.items.sort(cmpChatsAndCats)
self.endInsertRows()
self.countChanged()
proc changeCategoryOpened*(self: Model, categoryId: string, opened: bool) {.slot.} = proc changeCategoryOpened*(self: Model, categoryId: string, opened: bool) {.slot.} =
for i in 0 ..< self.items.len: for i in 0 ..< self.items.len:
if self.items[i].categoryId == categoryId: if self.items[i].categoryId == categoryId:
@ -337,15 +372,15 @@ QtObject:
proc updateItemsWithCategoryDetailsById*( proc updateItemsWithCategoryDetailsById*(
self: Model, self: Model,
chats: seq[ChatDto], chats: seq[ChatDto],
categoryId, categoryId: string,
newCategoryName: string,
newCategoryPosition: int, newCategoryPosition: int,
) = ) =
self.beginResetModel()
for i in 0 ..< self.items.len: for i in 0 ..< self.items.len:
var item = self.items[i] var item = self.items[i]
if item.`type` == CATEGORY_TYPE: if item.`type` == CATEGORY_TYPE:
continue continue
var hadCategory = item.categoryId == categoryId
var nowHasCategory = false var nowHasCategory = false
var found = false var found = false
for chat in chats: for chat in chats:
@ -354,26 +389,14 @@ QtObject:
found = true found = true
nowHasCategory = chat.categoryId == categoryId nowHasCategory = chat.categoryId == categoryId
item.position = chat.position item.position = chat.position
item.categoryId = categoryId item.categoryId = chat.categoryId
item.categoryPosition = newCategoryPosition item.categoryPosition = if nowHasCategory: newCategoryPosition else: -1
let modelIndex = self.createIndex(i, 0, nil) if not nowHasCategory:
self.dataChanged(modelIndex, modelIndex, @[ item.categoryOpened = true
ModelRole.Position.int,
ModelRole.CategoryId.int,
ModelRole.CategoryPosition.int,
])
break break
if (hadCategory and not found and not nowHasCategory) or (hadCategory and found and not nowHasCategory):
item.categoryId = "" self.items.sort(cmpChatsAndCats)
item.categoryPosition = -1 self.endResetModel()
echo "category changed ", item.name
item.categoryOpened = true
let modelIndex = self.createIndex(i, 0, nil)
self.dataChanged(modelIndex, modelIndex, @[
ModelRole.CategoryId.int,
ModelRole.CategoryPosition.int,
ModelRole.CategoryOpened.int,
])
proc removeCategory*( proc removeCategory*(
self: Model, self: Model,
@ -382,6 +405,7 @@ QtObject:
) = ) =
self.removeItemById(categoryId) self.removeItemById(categoryId)
self.beginResetModel()
for i in 0 ..< self.items.len: for i in 0 ..< self.items.len:
var item = self.items[i] var item = self.items[i]
if item.categoryId != categoryId: if item.categoryId != categoryId:
@ -403,6 +427,9 @@ QtObject:
ModelRole.CategoryOpened.int, ModelRole.CategoryOpened.int,
]) ])
break break
self.items.sort(cmpChatsAndCats)
self.endResetModel()
proc renameCategory*(self: Model, categoryId, newName: string) = proc renameCategory*(self: Model, categoryId, newName: string) =
let index = self.getItemIdxById(categoryId) let index = self.getItemIdxById(categoryId)
@ -461,27 +488,34 @@ QtObject:
let modelIndex = self.createIndex(index, 0, nil) let modelIndex = self.createIndex(index, 0, nil)
self.dataChanged(modelIndex, modelIndex, @[ModelRole.LastMessageTimestamp.int]) self.dataChanged(modelIndex, modelIndex, @[ModelRole.LastMessageTimestamp.int])
proc reorderChatById*( proc reorderChats*(
self: Model, self: Model,
chatId: string, updatedChats: seq[ChatDto],
position: int,
newCategoryId: string,
newCategoryPosition: int,
) = ) =
let index = self.getItemIdxById(chatId) self.beginResetModel()
if index == -1:
return for updatedChat in updatedChats:
var roles = @[ModelRole.Position.int] let index = self.getItemIdxById(updatedChat.id)
if(self.items[index].categoryId != newCategoryId): if index == -1:
self.items[index].categoryId = newCategoryId continue
self.items[index].categoryPosition = newCategoryPosition
roles = roles.concat(@[ if(self.items[index].categoryId != updatedChat.categoryId):
ModelRole.CategoryId.int, if updatedChat.categoryId == "":
ModelRole.CategoryPosition.int, # Moved out of a category
]) self.items[index].categoryId = updatedChat.categoryId
self.items[index].position = position self.items[index].categoryPosition = -1
let modelIndex = self.createIndex(index, 0, nil) else:
self.dataChanged(modelIndex, modelIndex, roles) let category = self.getItemById(updatedChat.categoryId)
if category.id == "":
continue
self.items[index].categoryId = category.id
self.items[index].categoryPosition = category.categoryPosition
self.items[index].position = updatedChat.position
self.items.sort(cmpChatsAndCats)
self.endResetModel()
proc reorderCategoryById*( proc reorderCategoryById*(
self: Model, self: Model,

View File

@ -650,7 +650,6 @@ method onCommunityCategoryEdited*(self: Module, cat: Category, chats: seq[ChatDt
self.view.chatsModel().updateItemsWithCategoryDetailsById( self.view.chatsModel().updateItemsWithCategoryDetailsById(
chats, chats,
cat.id, cat.id,
cat.name,
cat.position, cat.position,
) )
@ -664,7 +663,6 @@ method onCommunityCategoryCreated*(self: Module, cat: Category, chats: seq[ChatD
self.view.chatsModel().updateItemsWithCategoryDetailsById( self.view.chatsModel().updateItemsWithCategoryDetailsById(
chats, chats,
cat.id, cat.id,
cat.name,
cat.position, cat.position,
) )
@ -682,13 +680,11 @@ method setFirstChannelAsActive*(self: Module) =
self.setActiveItem(chat_item.id) self.setActiveItem(chat_item.id)
break break
method onReorderChat*(self: Module, chatId: string, position: int, newCategoryIdForChat: string, prevCategoryId: string, prevCategoryDeleted: bool) = method onReorderChat*(self: Module, updatedChat: ChatDto) =
var newCategoryName = "" self.view.chatsModel().reorderChats(@[updatedChat])
var newCategoryPos = -1
if newCategoryIdForChat != "": method onReorderChats*(self: Module, updatedChats: seq[ChatDto]) =
let newCategory = self.controller.getCommunityCategoryDetails(self.controller.getMySectionId(), newCategoryIdForChat) self.view.chatsModel().reorderChats(updatedChats)
newCategoryPos = newCategory.position
self.view.chatsModel().reorderChatById(chatId, position, newCategoryIdForChat, newCategoryPos)
method onReorderCategory*(self: Module, catId: string, position: int) = method onReorderCategory*(self: Module, catId: string, position: int) =
self.view.chatsModel().reorderCategoryById(catId, position) self.view.chatsModel().reorderCategoryById(catId, position)
@ -1095,13 +1091,26 @@ method prepareEditCategoryModel*(self: Module, categoryId: string) =
c.position, c.position,
categoryId, categoryId,
) )
self.view.editCategoryChannelsModel().appendItem(chatItem) self.view.editCategoryChannelsModel().appendItem(chatItem, ignoreCategory = true)
method reorderCommunityCategories*(self: Module, categoryId: string, position: int) = method reorderCommunityCategories*(self: Module, categoryId: string, position: int) =
self.controller.reorderCommunityCategories(categoryId, position) self.controller.reorderCommunityCategories(categoryId, position)
method reorderCommunityChat*(self: Module, categoryId: string, chatId: string, position: int): string = method reorderCommunityChat*(self: Module, categoryId: string, chatId: string, toPosition: int): string =
self.controller.reorderCommunityChat(categoryId, chatId, position) # Calculate actual position, since the position coming from the UI is assuming a single list where categories are items
# eg: if we have 2 categories with 2 channels each, then it means 6 items (2 categories, 2 chats)
# if we move the 2nd channel of the 2nd category to the 1st position of the 2nd category, then the UI would say
# that we move the chat from position 5 to position 4
# We need to translate that to position 1 of category 2
let (category, categoryIndex) = self.view.chatsModel().getClosestCategoryAtIndex(toPosition + 1)
var categoryId = ""
var newPos = toPosition
if (categoryIndex > -1):
categoryId = category.id
newPos = toPosition - categoryIndex - 1 # position is 0 based
if newPos < 0:
newPos = 0
self.controller.reorderCommunityChat(categoryId, chatId, newPos)
method setLoadingHistoryMessagesInProgress*(self: Module, isLoading: bool) = method setLoadingHistoryMessagesInProgress*(self: Module, isLoading: bool) =
self.view.setLoadingHistoryMessagesInProgress(isLoading) self.view.setLoadingHistoryMessagesInProgress(isLoading)

View File

@ -45,11 +45,11 @@ type
CommunityChatOrderArgs* = ref object of Args CommunityChatOrderArgs* = ref object of Args
communityId*: string communityId*: string
chatId*: string chat*: ChatDto
categoryId*: string
position*: int CommunityChatsOrderArgs* = ref object of Args
prevCategoryId*: string communityId*: string
prevCategoryDeleted*: bool chats*: seq[ChatDto]
CommunityCategoryOrderArgs* = ref object of Args CommunityCategoryOrderArgs* = ref object of Args
communityId*: string communityId*: string
@ -126,6 +126,7 @@ const SIGNAL_COMMUNITIES_UPDATE* = "communityUpdated"
const SIGNAL_COMMUNITY_CHANNEL_CREATED* = "communityChannelCreated" const SIGNAL_COMMUNITY_CHANNEL_CREATED* = "communityChannelCreated"
const SIGNAL_COMMUNITY_CHANNEL_EDITED* = "communityChannelEdited" const SIGNAL_COMMUNITY_CHANNEL_EDITED* = "communityChannelEdited"
const SIGNAL_COMMUNITY_CHANNEL_REORDERED* = "communityChannelReordered" const SIGNAL_COMMUNITY_CHANNEL_REORDERED* = "communityChannelReordered"
const SIGNAL_COMMUNITY_CHANNELS_REORDERED* = "communityChannelsReordered"
const SIGNAL_COMMUNITY_CHANNEL_DELETED* = "communityChannelDeleted" const SIGNAL_COMMUNITY_CHANNEL_DELETED* = "communityChannelDeleted"
const SIGNAL_COMMUNITY_CATEGORY_CREATED* = "communityCategoryCreated" const SIGNAL_COMMUNITY_CATEGORY_CREATED* = "communityCategoryCreated"
const SIGNAL_COMMUNITY_CATEGORY_EDITED* = "communityCategoryEdited" const SIGNAL_COMMUNITY_CATEGORY_EDITED* = "communityCategoryEdited"
@ -406,7 +407,7 @@ QtObject:
if category.position != prev_category.position: if category.position != prev_category.position:
self.events.emit(SIGNAL_COMMUNITY_CATEGORY_REORDERED, self.events.emit(SIGNAL_COMMUNITY_CATEGORY_REORDERED,
CommunityChatOrderArgs( CommunityCategoryOrderArgs(
communityId: community.id, communityId: community.id,
categoryId: category.id, categoryId: category.id,
position: category.position)) position: category.position))
@ -471,8 +472,12 @@ QtObject:
self.events.emit(SIGNAL_COMMUNITY_CHANNEL_CREATED, data) self.events.emit(SIGNAL_COMMUNITY_CHANNEL_CREATED, data)
# if the chat was created by the current user then it's already in the model and should be reordered if necessary # if the chat was created by the current user then it's already in the model and should be reordered if necessary
self.events.emit(SIGNAL_COMMUNITY_CHANNEL_REORDERED, CommunityChatOrderArgs(communityId: community.id, self.events.emit(SIGNAL_COMMUNITY_CHANNEL_REORDERED,
chatId: chat.id, categoryId: chat.categoryId, position: chat.position)) CommunityChatOrderArgs(
communityId: community.id,
chat: chat,
)
)
# channel was removed # channel was removed
elif((community.chats.len-removedChats.len) < prev_community.chats.len): elif((community.chats.len-removedChats.len) < prev_community.chats.len):
@ -491,8 +496,12 @@ QtObject:
let prev_chat = prev_community.chats[index] let prev_chat = prev_community.chats[index]
# Handle position changes # Handle position changes
if chat.position != prev_chat.position: if chat.position != prev_chat.position:
self.events.emit(SIGNAL_COMMUNITY_CHANNEL_REORDERED, CommunityChatOrderArgs(communityId: community.id, self.events.emit(SIGNAL_COMMUNITY_CHANNEL_REORDERED,
chatId: chat.id, categoryId: chat.categoryId, position: chat.position)) CommunityChatOrderArgs(
communityId: community.id,
chat: chat,
)
)
# Handle channel was added/removed to/from category # Handle channel was added/removed to/from category
if chat.categoryId != prev_chat.categoryId: if chat.categoryId != prev_chat.categoryId:
@ -504,8 +513,12 @@ QtObject:
prevCategoryDeleted = true prevCategoryDeleted = true
break break
self.events.emit(SIGNAL_COMMUNITY_CHANNEL_CATEGORY_CHANGED, CommunityChatOrderArgs(communityId: community.id, self.events.emit(SIGNAL_COMMUNITY_CHANNEL_CATEGORY_CHANGED,
chatId: chat.id, categoryId: chat.categoryId, position: chat.position, prevCategoryId: prev_chat.categoryId, prevCategoryDeleted: prevCategoryDeleted)) CommunityChatOrderArgs(
communityId: community.id,
chat: chat,
)
)
# Handle name/description changes # Handle name/description changes
if chat.name != prev_chat.name or chat.description != prev_chat.description or chat.color != prev_chat.color: if chat.name != prev_chat.name or chat.description != prev_chat.description or chat.color != prev_chat.color:
@ -1146,17 +1159,31 @@ QtObject:
let updatedCommunity = response.result["communities"][0].toCommunityDto() let updatedCommunity = response.result["communities"][0].toCommunityDto()
var updatedChats: seq[ChatDto] = @[]
for chat in updatedCommunity.chats: for chat in updatedCommunity.chats:
let prev_chat_idx = findIndexById(chat.id, self.communities[communityId].chats) let prev_chat_idx = findIndexById(chat.id, self.communities[communityId].chats)
if prev_chat_idx > -1: if prev_chat_idx == -1:
let prev_chat = self.communities[communityId].chats[prev_chat_idx] continue
if(chat.position != prev_chat.position and chat.categoryId == categoryId): let prev_chat = self.communities[communityId].chats[prev_chat_idx]
var chatDetails = self.chatService.getChatById(chat.id) # we are free to do this cause channel must be created before we add it to a category
self.communities[communityId].chats[prev_chat_idx].position = chat.position
chatDetails.updateMissingFields(self.communities[communityId].chats[prev_chat_idx])
self.chatService.updateOrAddChat(chatDetails) # we have to update chats stored in the chat service.
self.events.emit(SIGNAL_COMMUNITY_CHANNEL_REORDERED, CommunityChatOrderArgs(communityId: updatedCommunity.id, chatId: chat.id, categoryId: chat.categoryId, position: chat.position))
# we are free to do this cause channel must be created before we add it to a category
var chatDetails = self.chatService.getChatById(chat.id)
if(chat.position != prev_chat.position and chat.categoryId == categoryId):
self.communities[communityId].chats[prev_chat_idx].position = chat.position
elif chat.categoryId != prev_chat.categoryId:
self.communities[communityId].chats[prev_chat_idx].categoryId = chat.categoryId
else:
continue
chatDetails.updateMissingFields(self.communities[communityId].chats[prev_chat_idx])
self.chatService.updateOrAddChat(chatDetails) # we have to update chats stored in the chat service.
updatedChats.add(chat)
self.events.emit(SIGNAL_COMMUNITY_CHANNELS_REORDERED,
CommunityChatsOrderArgs(communityId: updatedCommunity.id, chats: updatedChats))
self.communities[communityId] = updatedCommunity
except Exception as e: except Exception as e:
error "Error reordering community channel", msg = e.msg, communityId, chatId, position, procName="reorderCommunityChat" error "Error reordering community channel", msg = e.msg, communityId, chatId, position, procName="reorderCommunityChat"

View File

@ -29,12 +29,7 @@ class CommunityScreenComponents(Enum):
CHAT_LOG = "chatView_log" CHAT_LOG = "chatView_log"
COMMUNITY_HEADER_BUTTON = "mainWindow_communityHeader_StatusChatInfoButton" COMMUNITY_HEADER_BUTTON = "mainWindow_communityHeader_StatusChatInfoButton"
COMMUNITY_HEADER_NAME_TEXT= "community_ChatInfo_Name_Text" COMMUNITY_HEADER_NAME_TEXT= "community_ChatInfo_Name_Text"
COMMUNITY_CREATE_CHANNEL_OR_CAT_BUTTON = "ma. COMMUNITY_CREATE_CHANNEL_OR_CAT_BUTTON = "mainWindow_createChannelOrCategoryBtn_StatusBaseText"
inWindow_createChannelOrCategoryBtn_StatusBaseText"
COMMUNITY_CREATE_CHANNEL_MENU_ITEM = "create_channel_StatusMenuItem" COMMUNITY_CREATE_CHANNEL_MENU_ITEM = "create_channel_StatusMenuItem"
COMMUNITY_CREATE_CATEGORY_MENU_ITEM = "create_category_StatusMenuItem" COMMUNITY_CREATE_CATEGORY_MENU_ITEM = "create_category_StatusMenuItem"
COMMUNITY_EDIT_CATEGORY_MENU_ITEM = "edit_сategory_StatusMenuItem" COMMUNITY_EDIT_CATEGORY_MENU_ITEM = "edit_сategory_StatusMenuItem"
@ -311,6 +306,14 @@ class StatusCommunityScreen:
chatListObj = get_obj(CommunityScreenComponents.NOT_CATEGORIZED_CHAT_LIST.value) chatListObj = get_obj(CommunityScreenComponents.NOT_CATEGORIZED_CHAT_LIST.value)
verify_equals(chatListObj.statusChatListItems.count, int(count_to_check)) verify_equals(chatListObj.statusChatListItems.count, int(count_to_check))
def check_channel_is_uncategorized(self, channel_name: str):
chatListObj = get_obj(CommunityScreenComponents.NOT_CATEGORIZED_CHAT_LIST.value)
for i in range(chatListObj.statusChatListItems.count):
channelObj = chatListObj.statusChatListItems.itemAtIndex(i)
if channelObj.objectName == channel_name:
return
verify_failure("No channel matches " + channel_name)
def search_and_change_community_channel_emoji(self, emoji_description: str): def search_and_change_community_channel_emoji(self, emoji_description: str):
self._open_edit_channel_popup() self._open_edit_channel_popup()

View File

@ -230,6 +230,10 @@ def step(context, color: str):
@Then("\"|any|\" should be an available option in Community Settings") @Then("\"|any|\" should be an available option in Community Settings")
def step(context, manage_community_option:str): def step(context, manage_community_option:str):
_statusCommunityScreen.verify_option_exists(manage_community_option) _statusCommunityScreen.verify_option_exists(manage_community_option)
@Then("\"|any|\" should be in the list of uncategorized channels")
def step(context, chat_name:str):
_statusCommunityScreen.check_channel_is_uncategorized(chat_name)
########################################################################### ###########################################################################

View File

@ -28,11 +28,12 @@ Feature: Status Desktop community
Scenario Outline: The admin creates a community channel Scenario Outline: The admin creates a community channel
When the admin creates a community channel named "<community_channel_name>", with description "<community_channel_description>", with the method "<method>" When the admin creates a community channel named "<community_channel_name>", with description "<community_channel_description>", with the method "<method>"
Then the channel named "<community_channel_name>" is open Then "<community_channel_name>" should be in the list of uncategorized channels
And the channel named "<community_channel_name>" is open
Examples: Examples:
| community_channel_name | community_channel_description | method | | community_channel_name | community_channel_description | method |
| test-channel | Community channel description tested 1 | bottom_menu | | test-channel | Community channel description tested 1 | bottom_menu |
| test-channel2 | Community channel description tested 2 | right_click_menu | # | test-channel2 | Community channel description tested 2 | right_click_menu |
Scenario Outline: The admin edits a community channel Scenario Outline: The admin edits a community channel
Given the admin creates a community channel named "<community_channel_name>", with description "<community_channel_description>", with the method "bottom_menu" Given the admin creates a community channel named "<community_channel_name>", with description "<community_channel_description>", with the method "bottom_menu"

View File

@ -69,7 +69,7 @@ Item {
const to = chatListDelegate.visualIndex; const to = chatListDelegate.visualIndex;
if (to === from) if (to === from)
return; return;
if (!model.isCategory) { if (!drop.source.isCategory) {
root.chatItemReordered(statusChatListItems.itemAtIndex(from).categoryId, statusChatListItems.itemAtIndex(from).chatId, to); root.chatItemReordered(statusChatListItems.itemAtIndex(from).categoryId, statusChatListItems.itemAtIndex(from).chatId, to);
} else { } else {
root.categoryReordered(statusChatListItems.itemAtIndex(from).categoryId, to); root.categoryReordered(statusChatListItems.itemAtIndex(from).categoryId, to);
@ -77,6 +77,8 @@ Item {
} }
StatusDraggableListItem { StatusDraggableListItem {
readonly property bool isCategory: model.isCategory
id: draggableItem id: draggableItem
width: parent.width width: parent.width
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
@ -93,7 +95,7 @@ Item {
customizable: true customizable: true
Drag.keys: chatListDelegate.keys Drag.keys: chatListDelegate.keys
onClicked: { onClicked: {
if (model.isCategory) { if (draggableItem.isCategory) {
statusChatListCategoryItem.clicked(mouse); statusChatListCategoryItem.clicked(mouse);
} else { } else {
statusChatListItem.clicked(mouse); statusChatListItem.clicked(mouse);
@ -104,7 +106,7 @@ Item {
StatusChatListCategoryItem { StatusChatListCategoryItem {
id: statusChatListCategoryItem id: statusChatListCategoryItem
objectName: "categoryItem" objectName: "categoryItem"
visible: model.isCategory visible: draggableItem.isCategory
function setupPopup() { function setupPopup() {
categoryPopupMenuSlot.item.categoryItem = model categoryPopupMenuSlot.item.categoryItem = model
@ -129,10 +131,10 @@ Item {
highlighted = true; highlighted = true;
categoryPopupMenuSlot.item.popup() categoryPopupMenuSlot.item.popup()
} else if (mouse.button === Qt.LeftButton) { } else if (mouse.button === Qt.LeftButton) {
root.model.sourceModel.changeCategoryOpened(model.categoryId, !statusChatListCategoryItem.opened) root.model.changeCategoryOpened(model.categoryId, !statusChatListCategoryItem.opened)
} }
} }
onToggleButtonClicked: root.model.sourceModel.changeCategoryOpened(model.categoryId, !statusChatListCategoryItem.opened) onToggleButtonClicked: root.model.changeCategoryOpened(model.categoryId, !statusChatListCategoryItem.opened)
onMenuButtonClicked: { onMenuButtonClicked: {
statusChatListCategoryItem.setupPopup() statusChatListCategoryItem.setupPopup()
highlighted = true highlighted = true
@ -148,7 +150,7 @@ Item {
objectName: model.name objectName: model.name
width: root.width width: root.width
height: visible ? (statusChatListItem.implicitHeight + 4) /*spacing between non-collapsed items*/ : 0 height: visible ? (statusChatListItem.implicitHeight + 4) /*spacing between non-collapsed items*/ : 0
visible: (!model.isCategory && model.categoryOpened) visible: (!draggableItem.isCategory && model.categoryOpened)
originalOrder: model.position originalOrder: model.position
chatId: model.itemId chatId: model.itemId
categoryId: model.categoryId categoryId: model.categoryId

View File

@ -7,8 +7,6 @@ import StatusQ.Components 0.1
import StatusQ.Popups 0.1 import StatusQ.Popups 0.1
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import SortFilterProxyModel 0.2
Item { Item {
id: root id: root
@ -83,19 +81,7 @@ Item {
root.categoryAddButtonClicked(id) root.categoryAddButtonClicked(id)
} }
model: SortFilterProxyModel { model: root.model
sourceModel: root.model
sorters: [
RoleSorter {
roleName: "categoryPosition"
priority: 2 // Higher number === higher priority
},
RoleSorter {
roleName: "position"
priority: 1
}
]
}
popupMenu: root.chatListPopupMenu popupMenu: root.chatListPopupMenu
categoryPopupMenu: root.categoryPopupMenu categoryPopupMenu: root.categoryPopupMenu