Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions src/app/modules/main/app_search/location_menu_sub_item.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,31 @@ export base_item
type
SubItem* = ref object of BaseItem
isUserIcon: bool
isImage: bool
colorId: int
colorHash: color_hash_model.Model
position: int
lastMessageTimestamp: int

proc initSubItem*(value, text, image, icon, iconColor: string,
isUserIcon: bool = false, colorId: int = 0, colorHash: seq[ColorHashSegment] = @[]): SubItem =
proc initSubItem*(
value,
text,
image,
icon,
iconColor: string,
isUserIcon: bool,
isImage: bool,
position: int,
lastMessageTimestamp: int,
colorId: int = 0,
colorHash: seq[ColorHashSegment] = @[]
): SubItem =
result = SubItem()
result.setup(value, text, image, icon, iconColor)
result.isUserIcon = isUserIcon
result.isImage = isImage
result.position = position
result.lastMessageTimestamp = lastMessageTimestamp
result.colorId = colorId
result.colorHash = color_hash_model.newModel()
result.colorHash.setItems(map(colorHash, x => color_hash_item.initItem(x.len, x.colorIdx)))
Expand All @@ -26,6 +43,10 @@ proc `$`*(self: SubItem): string =
result = fmt"""SearchMenuSubItem(
value: {self.value},
text: {self.text},
position: {self.position},
lastMessageTimestamp: {self.lastMessageTimestamp},
isUserIcon: {self.isUserIcon},
isImage: {self.isImage},
imageSource: {self.image},
iconName: {self.icon},
iconColor: {self.iconColor},
Expand All @@ -35,17 +56,29 @@ proc toJsonNode*(self: SubItem): JsonNode =
result = %* {
"value": self.value,
"text": self.text,
"position": self.position,
"lastMessageTimestamp": self.lastMessageTimestamp,
"imageSource": self.image,
"iconName": self.icon,
"iconColor": self.iconColor,
"isUserIcon": self.isUserIcon,
"isImage": self.isImage,
"colorId": self.colorId,
"colorHash": self.colorHash.toJson()
}

proc position*(self: SubItem): int =
return self.position

proc lastMessageTimestamp*(self: SubItem): int =
return self.lastMessageTimestamp

proc isUserIcon*(self: SubItem): bool =
return self.isUserIcon

proc isImage*(self: SubItem): bool =
return self.isImage

proc colorId*(self: SubItem): int =
return self.colorId

Expand Down
12 changes: 12 additions & 0 deletions src/app/modules/main/app_search/location_menu_sub_model.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ type
Icon
IconColor
IsUserIcon
IsImage
Position
LastMessageTimestamp
ColorId
ColorHash

Expand Down Expand Up @@ -57,6 +60,9 @@ QtObject:
SubModelRole.Icon.int:"iconName",
SubModelRole.IconColor.int:"iconColor",
SubModelRole.IsUserIcon.int:"isUserIcon",
SubModelRole.IsImage.int:"isImage",
SubModelRole.Position.int:"position",
SubModelRole.LastMessageTimestamp.int:"lastMessageTimestamp",
SubModelRole.ColorId.int:"colorId",
SubModelRole.ColorHash.int:"colorHash"
}.toTable
Expand Down Expand Up @@ -84,6 +90,12 @@ QtObject:
result = newQVariant(item.iconColor)
of SubModelRole.IsUserIcon:
result = newQVariant(item.isUserIcon)
of SubModelRole.IsImage:
result = newQVariant(item.isImage)
of SubModelRole.Position:
result = newQVariant(item.position)
of SubModelRole.LastMessageTimestamp:
result = newQVariant(item.lastMessageTimestamp)
of SubModelRole.ColorId:
result = newQVariant(item.colorId)
of SubModelRole.ColorHash:
Expand Down
57 changes: 48 additions & 9 deletions src/app/modules/main/app_search/module.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import NimQml
import json, strutils, chronicles, sequtils
import json, strutils, chronicles, sequtils, tables, std/algorithm
import io_interface
import ../io_interface as delegate_interface
import view, controller
Expand Down Expand Up @@ -66,32 +66,70 @@ method viewDidLoad*(self: Module) =
method getModuleAsVariant*(self: Module): QVariant =
return self.viewVariant

proc getChatSubItems(self: Module, chats: seq[ChatDto]): seq[location_menu_sub_item.SubItem] =
proc getChatSubItems(self: Module, chats: seq[ChatDto], categories: seq[Category] = @[]): seq[location_menu_sub_item.SubItem] =
var highestPosition = 0
var categoryChats: OrderedTable[int, seq[ChatDto]] = initOrderedTable[int, seq[ChatDto]]()

for chatDto in chats:
if chatDto.isHiddenChat:
if not chatDto.canView and not chatDto.missingEncryptionKey:
continue

var chatName = chatDto.name
var chatImage = chatDto.icon
var colorHash: ColorHashDto = @[]
var colorId: int = 0
let isOneToOneChat = chatDto.chatType == ChatType.OneToOne
if(isOneToOneChat):
if isOneToOneChat:
(chatName, chatImage) = self.controller.getOneToOneChatNameAndImage(chatDto.id)
colorHash = self.controller.getColorHash(chatDto.id)
colorId = self.controller.getColorId(chatDto.id)
elif chatDto.chatType == ChatType.CommunityChat:
if chatDto.categoryId != "":
for cat in categories:
if cat.id == chatDto.categoryId:
if not categoryChats.hasKey(cat.position):
categoryChats[cat.position] = @[]
categoryChats[cat.position].add(chatDto)
break
continue
else:
if chatDto.position > highestPosition:
highestPosition = chatDto.position

let subItem = location_menu_sub_item.initSubItem(
chatDto.id,
chatName,
if (chatImage != ""): chatImage else: chatDto.emoji,
"",
image = if (chatImage != ""): chatImage else: chatDto.emoji,
icon = "",
chatDto.color,
isOneToOneChat,
isImage = chatImage != "",
chatDto.position,
chatDto.timestamp.int,
colorId,
colorHash
colorHash,
)
result.add(subItem)

# Add category chats by adjusting the position by taking into account the category position
let sortedKeys = toSeq(categoryChats.keys).sorted()
for categoryPosition in sortedKeys:
highestPosition.inc()
for chat in categoryChats[categoryPosition]:
let chatPosition = chat.position + highestPosition
result.add(location_menu_sub_item.initSubItem(
chat.id,
chat.name,
chat.emoji,
icon = "",
chat.color,
isUserIcon = false,
isImage = false,
chatPosition,
chat.timestamp.int,
))
highestPosition += categoryChats[categoryPosition].len

proc buildLocationMenuForCommunity(self: Module, community: CommunityDto): location_menu_item.Item =
var item = location_menu_item.initItem(
community.id,
Expand All @@ -101,7 +139,7 @@ proc buildLocationMenuForCommunity(self: Module, community: CommunityDto): locat
community.color
)

var subItems = self.getChatSubItems(community.chats)
var subItems = self.getChatSubItems(community.chats, community.categories)
item.setSubItems(subItems)

return item
Expand All @@ -125,7 +163,8 @@ method prepareLocationMenuModel*(self: Module) =
# Community sections
let communities = self.controller.getJoinedAndSpectatedCommunities()
for c in communities:
items.add(self.buildLocationMenuForCommunity(c))
if c.joined:
items.add(self.buildLocationMenuForCommunity(c))

self.view.locationMenuModel().setItems(items)

Expand Down
8 changes: 0 additions & 8 deletions src/app/modules/main/chat_section/module.nim
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,6 @@ proc buildChatSectionUI(
items.add(self.addCategoryItem(categoryDto, community.memberRole, community.id))

for chatDto in chats:
var categoryPosition = -1

# Add an empty chat item that has the category info
var isActive = false
# restore on a startup last open channel for the section or
Expand All @@ -326,12 +324,6 @@ proc buildChatSectionUI(
selectedItemId = chatDto.id
isActive = true

if chatDto.categoryId != "":
for category in community.categories:
if category.id == chatDto.categoryId:
categoryPosition = category.position
break

items.add(self.addOrUpdateChat(
chatDto,
belongsToCommunity = chatDto.communityId.len > 0,
Expand Down
15 changes: 11 additions & 4 deletions src/app_service/service/chat/dto/chat.nim
Original file line number Diff line number Diff line change
Expand Up @@ -254,10 +254,6 @@ proc toChatDto*(jsonObj: JsonNode): ChatDto =
discard jsonObj.getProp("readMessagesAtClockValue", result.readMessagesAtClockValue)
discard jsonObj.getProp("unviewedMessagesCount", result.unviewedMessagesCount)
discard jsonObj.getProp("unviewedMentionsCount", result.unviewedMentionsCount)
discard jsonObj.getProp("canPostReactions", result.canPostReactions)
discard jsonObj.getProp("canPost", result.canPost)
discard jsonObj.getProp("canView", result.canView)
discard jsonObj.getProp("viewersCanPostReactions", result.viewersCanPostReactions)
discard jsonObj.getProp("alias", result.alias)
discard jsonObj.getProp("muted", result.muted)
discard jsonObj.getProp("categoryId", result.categoryId)
Expand Down Expand Up @@ -286,6 +282,17 @@ proc toChatDto*(jsonObj: JsonNode): ChatDto =
(chatTypeInt >= ord(low(ChatType)) or chatTypeInt <= ord(high(ChatType)))):
result.chatType = ChatType(chatTypeInt)

# Default those properties to true as they are only provided for community chats
# To be refactored with https://github.com/status-im/status-desktop/issues/11694
result.canPostReactions = true
result.canPost = true
result.canView = true
result.viewersCanPostReactions = true
discard jsonObj.getProp("canPostReactions", result.canPostReactions)
discard jsonObj.getProp("canPost", result.canPost)
discard jsonObj.getProp("canView", result.canView)
discard jsonObj.getProp("viewersCanPostReactions", result.viewersCanPostReactions)

var chatImage: string
discard jsonObj.getProp("image", chatImage)
if (result.chatType == ChatType.PrivateGroupChat and len(chatImage) > 0):
Expand Down
45 changes: 31 additions & 14 deletions ui/StatusQ/src/StatusQ/Popups/StatusSearchLocationMenu.qml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import QtQuick 2.14
import QtQml 2.14
import QtQuick.Controls 2.14
import QtQuick 2.15
import QtQml 2.15
import QtQuick.Controls 2.15

import Qt.labs.qmlmodels 1.0

Expand All @@ -9,6 +9,8 @@ import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import StatusQ.Core.Utils 0.1 as StatusQUtils

import SortFilterProxyModel 0.2

StatusMenu {
id: root

Expand All @@ -22,10 +24,10 @@ StatusMenu {
signal setSearchSelection(string text,
string secondaryText,
string imageSource,
string isIdenticon,
bool isIdenticon,
string iconName,
string iconColor,
var isUserIcon,
bool isUserIcon,
int colorId,
string colorHash)

Expand Down Expand Up @@ -78,9 +80,12 @@ StatusMenu {
root.setSearchSelection(text,
"",
"",
assetSettings.isIdenticon,
assetSettings.imgIsIdenticon,
assetSettings.name,
assetSettings.color)
assetSettings.color,
model.isUserIcon,
model.colorId,
JSON.stringify(model.colorHash))
root.itemClicked(model.value, "")
}
}
Expand Down Expand Up @@ -113,21 +118,34 @@ StatusMenu {
readonly property string parentIconName: subMenuDelegate.parentIconName
readonly property string parentImageSource: subMenuDelegate.parentImageSource
readonly property string parentIdenticonColor: subMenuDelegate.parentIdenticonColor
readonly property string parentIsIdenticon: subMenuDelegate.parentIsIdenticon
readonly property bool parentIsIdenticon: subMenuDelegate.parentIsIdenticon

menu: subMenuDelegate
model: subMenuDelegate.subItemsModel
model: SortFilterProxyModel {
sourceModel: subMenuDelegate.subItemsModel
sorters: [
RoleSorter {
roleName: "position"
sortOrder: Qt.AscendingOrder
},
RoleSorter {
roleName: "lastMessageTimestamp"
sortOrder: Qt.DescendingOrder
}
]
}

delegate: StatusSearchPopupMenuItem {
value: model.value
text: model.text
assetSettings.isImage: !!model.imageSource
assetSettings.name: !!StatusQUtils.Emoji.iconSource(model.imageSource) ?
StatusQUtils.Emoji.iconSource(model.imageSource) : model.imageSource

assetSettings.name: model.isImage ? model.imageSource : ""
assetSettings.emoji: !model.isUserIcon ? model.imageSource : ""
assetSettings.color: model.isUserIcon ? Theme.palette.userCustomizationColors[model.colorId] : model.iconColor
assetSettings.bgColor: model.iconColor
assetSettings.charactersLen: model.isUserIcon ? 2 : 1
ringSettings.ringSpecModel: model.colorHash

onTriggered: {
root.resetSearchSelection()
if (menuLoader.parentTitleText === "Chat") {
Expand All @@ -139,7 +157,7 @@ StatusMenu {
model.iconColor,
model.isUserIcon,
model.colorId,
model.colorHash.toJson())
JSON.stringify(model.colorHash))
} else {
root.setSearchSelection(menuLoader.parentTitleText,
model.text,
Expand All @@ -160,5 +178,4 @@ StatusMenu {
}
}
}

}