refactor(@desktop/chat-communities): `ChannelIdentifierView` component updated

This commit is contained in:
Sale Djenic 2021-12-10 17:11:18 +01:00
parent 7f40ae0f57
commit bfaf1b5250
13 changed files with 457 additions and 351 deletions

View File

@ -3,6 +3,7 @@ import controller_interface
import io_interface import io_interface
import ../../../../../../app_service/service/contacts/service as contact_service import ../../../../../../app_service/service/contacts/service as contact_service
import ../../../../../../app_service/service/chat/service as chat_service
import ../../../../../../app_service/service/message/service as message_service import ../../../../../../app_service/service/message/service as message_service
import ../../../../../core/signals/types import ../../../../../core/signals/types
@ -20,16 +21,19 @@ type
chatId: string chatId: string
belongsToCommunity: bool belongsToCommunity: bool
contactService: contact_service.Service contactService: contact_service.Service
chatService: chat_service.Service
messageService: message_service.Service messageService: message_service.Service
proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter, chatId: string, belongsToCommunity: bool, proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter, chatId: string, belongsToCommunity: bool,
contactService: contact_service.Service, messageService: message_service.Service): Controller = contactService: contact_service.Service, chatService: chat_service.Service, messageService: message_service.Service):
Controller =
result = Controller() result = Controller()
result.delegate = delegate result.delegate = delegate
result.events = events result.events = events
result.chatId = chatId result.chatId = chatId
result.belongsToCommunity = belongsToCommunity result.belongsToCommunity = belongsToCommunity
result.contactService = contactService result.contactService = contactService
result.chatService = chatService
result.messageService = messageService result.messageService = messageService
method delete*(self: Controller) = method delete*(self: Controller) =
@ -57,6 +61,12 @@ method init*(self: Controller) =
method getChatId*(self: Controller): string = method getChatId*(self: Controller): string =
return self.chatId return self.chatId
method getChatDetails*(self: Controller): ChatDto =
return self.chatService.getChatById(self.chatId)
method getOneToOneChatNameAndImage*(self: Controller): tuple[name: string, image: string, isIdenticon: bool] =
return self.chatService.getOneToOneChatNameAndImage(self.chatId)
method belongsToCommunity*(self: Controller): bool = method belongsToCommunity*(self: Controller): bool =
return self.belongsToCommunity return self.belongsToCommunity

View File

@ -1,4 +1,5 @@
import ../../../../../../app_service/service/contacts/service as contact_service import ../../../../../../app_service/service/contacts/dto/[contacts]
import ../../../../../../app_service/service/chat/dto/[chat]
type type
AccessInterface* {.pure inheritable.} = ref object of RootObj AccessInterface* {.pure inheritable.} = ref object of RootObj
@ -13,6 +14,13 @@ method init*(self: AccessInterface) {.base.} =
method getChatId*(self: AccessInterface): string {.base.} = method getChatId*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method getChatDetails*(self: AccessInterface): ChatDto {.base.} =
raise newException(ValueError, "No implementation available")
method getOneToOneChatNameAndImage*(self: AccessInterface): tuple[name: string, image: string, isIdenticon: bool]
{.base.} =
raise newException(ValueError, "No implementation available")
method belongsToCommunity*(self: AccessInterface): bool {.base.} = method belongsToCommunity*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -7,12 +7,15 @@ import ../../../../shared_models/message_item
import ../../../../../global/global_singleton import ../../../../../global/global_singleton
import ../../../../../../app_service/service/contacts/service as contact_service import ../../../../../../app_service/service/contacts/service as contact_service
import ../../../../../../app_service/service/chat/service as chat_service
import ../../../../../../app_service/service/message/service as message_service import ../../../../../../app_service/service/message/service as message_service
import eventemitter import eventemitter
export io_interface export io_interface
const CHAT_IDENTIFIER_MESSAGE_ID = "chat-identifier-message-id"
type type
Module* = ref object of io_interface.AccessInterface Module* = ref object of io_interface.AccessInterface
delegate: delegate_interface.AccessInterface delegate: delegate_interface.AccessInterface
@ -22,16 +25,20 @@ type
moduleLoaded: bool moduleLoaded: bool
proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter, chatId: string, proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter, chatId: string,
belongsToCommunity: bool, contactService: contact_service.Service, messageService: message_service.Service): belongsToCommunity: bool, contactService: contact_service.Service, chatService: chat_service.Service,
messageService: message_service.Service):
Module = Module =
result = Module() result = Module()
result.delegate = delegate result.delegate = delegate
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, chatId, belongsToCommunity, contactService, result.controller = controller.newController(result, events, chatId, belongsToCommunity, contactService, chatService,
messageService) messageService)
result.moduleLoaded = false result.moduleLoaded = false
# Forward declaration
proc createChatIdentifierItem(self: Module): Item
method delete*(self: Module) = method delete*(self: Module) =
self.view.delete self.view.delete
self.viewVariant.delete self.viewVariant.delete
@ -45,15 +52,32 @@ method isLoaded*(self: Module): bool =
return self.moduleLoaded return self.moduleLoaded
method viewDidLoad*(self: Module) = method viewDidLoad*(self: Module) =
# The first message in the model must be always ChatIdentifier message.
self.view.model().appendItem(self.createChatIdentifierItem())
self.moduleLoaded = true self.moduleLoaded = true
self.delegate.messagesDidLoad() self.delegate.messagesDidLoad()
method getModuleAsVariant*(self: Module): QVariant = method getModuleAsVariant*(self: Module): QVariant =
return self.viewVariant return self.viewVariant
proc createChatIdentifierItem(self: Module): Item =
let chatDto = self.controller.getChatDetails()
var chatName = chatDto.name
var chatIcon = chatDto.identicon
var isIdenticon = false
if(chatDto.chatType == ChatType.OneToOne):
(chatName, chatIcon, isIdenticon) = self.controller.getOneToOneChatNameAndImage()
result = initItem(CHAT_IDENTIFIER_MESSAGE_ID, "", chatDto.id, chatName, "", chatIcon, isIdenticon, false, "", "", "",
true, 0, ContentType.ChatIdentifier, -1)
result.chatColorThisMessageBelongsTo = chatDto.color
result.chatTypeThisMessageBelongsTo = chatDto.chatType.int
method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: seq[ReactionDto], method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: seq[ReactionDto],
pinnedMessages: seq[PinnedMessageDto]) = pinnedMessages: seq[PinnedMessageDto]) =
var viewItems: seq[Item] var viewItems: seq[Item]
for m in messages: for m in messages:
let sender = self.controller.getContactById(m.`from`) let sender = self.controller.getContactById(m.`from`)
let senderDisplayName = sender.userNameOrAlias() let senderDisplayName = sender.userNameOrAlias()
@ -77,8 +101,13 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
item.pinned = true item.pinned = true
# messages are sorted from the most recent to the least recent one # messages are sorted from the most recent to the least recent one
viewItems = item & viewItems viewItems.add(item)
# ChatIdentifier message will be always the first message (the oldest one)
viewItems.add(self.createChatIdentifierItem())
# Delete the old ChatIdentifier message first
self.view.model().removeItem(CHAT_IDENTIFIER_MESSAGE_ID)
# Add new loaded messages
self.view.model().prependItems(viewItems) self.view.model().prependItems(viewItems)
method toggleReaction*(self: Module, messageId: string, emojiId: int) = method toggleReaction*(self: Module, messageId: string, emojiId: int) =

View File

@ -48,7 +48,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitt
result.inputAreaModule = input_area_module.newModule(result, chatId, belongsToCommunity, chatService, communityService) result.inputAreaModule = input_area_module.newModule(result, chatId, belongsToCommunity, chatService, communityService)
result.messagesModule = messages_module.newModule(result, events, chatId, belongsToCommunity, contactService, result.messagesModule = messages_module.newModule(result, events, chatId, belongsToCommunity, contactService,
messageService) chatService, messageService)
result.usersModule = users_module.newModule(result, events, sectionId, chatId, belongsToCommunity, isUsersListAvailable, result.usersModule = users_module.newModule(result, events, sectionId, chatId, belongsToCommunity, isUsersListAvailable,
contactService, communityService, messageService) contactService, communityService, messageService)

View File

@ -1,4 +1,4 @@
import Tables, json import Tables, json, strformat
type type
ContentType* {.pure.} = enum ContentType* {.pure.} = enum
@ -41,9 +41,13 @@ type
reactions: OrderedTable[int, seq[tuple[publicKey: string, reactionId: string]]] # [emojiId, list of [user publicKey reacted with the emojiId, reaction id]] reactions: OrderedTable[int, seq[tuple[publicKey: string, reactionId: string]]] # [emojiId, list of [user publicKey reacted with the emojiId, reaction id]]
reactionIds: seq[string] reactionIds: seq[string]
pinned: bool pinned: bool
# used in case of ContentType.ChatIdentifier only
chatTypeThisMessageBelongsTo: int
chatColorThisMessageBelongsTo: string
proc initItem*(id, responseToMessageWithId, senderId, senderDisplayName, senderLocalName, senderIcon: string, isSenderIconIdenticon, amISender: bool, proc initItem*(id, responseToMessageWithId, senderId, senderDisplayName, senderLocalName, senderIcon: string,
outgoingStatus, text, image: string, seen: bool, timestamp: int64, contentType: ContentType, messageType: int): Item = isSenderIconIdenticon, amISender: bool, outgoingStatus, text, image: string, seen: bool, timestamp: int64,
contentType: ContentType, messageType: int): Item =
result = Item() result = Item()
result.id = id result.id = id
result.responseToMessageWithId = responseToMessageWithId result.responseToMessageWithId = responseToMessageWithId
@ -113,6 +117,19 @@ proc pinned*(self: Item): bool {.inline.} =
proc `pinned=`*(self: Item, value: bool) {.inline.} = proc `pinned=`*(self: Item, value: bool) {.inline.} =
self.pinned = value self.pinned = value
proc chatTypeThisMessageBelongsTo*(self: Item): int {.inline.} =
self.chatTypeThisMessageBelongsTo
proc `chatTypeThisMessageBelongsTo=`*(self: Item, value: int) {.inline.} =
self.chatTypeThisMessageBelongsTo = value
proc chatColorThisMessageBelongsTo*(self: Item): string {.inline.} =
self.chatColorThisMessageBelongsTo
proc `chatColorThisMessageBelongsTo=`*(self: Item, value: string) {.inline.} =
self.chatColorThisMessageBelongsTo = value
proc shouldAddReaction*(self: Item, emojiId: int, publicKey: string): bool = proc shouldAddReaction*(self: Item, emojiId: int, publicKey: string): bool =
for k, values in self.reactions: for k, values in self.reactions:
if(k != emojiId): if(k != emojiId):
@ -175,6 +192,21 @@ proc getCountsForReactions*(self: Item): seq[JsonNode] =
result.add(%* {"emojiId": k, "counts": v.len}) result.add(%* {"emojiId": k, "counts": v.len})
proc `$`*(self: Item): string =
result = fmt"""MessageItem(
id: {self.id},
responseToMessageWithId: {self.responseToMessageWithId},
senderId: {self.senderId},
senderDisplayName: {self.senderDisplayName},
senderLocalName: {self.senderLocalName},
timestamp: {self.timestamp},
contentType: {self.contentType.int},
messageType:{self.messageType},
chatTypeThisMessageBelongsTo:{self.chatTypeThisMessageBelongsTo},
chatColorThisMessageBelongsTo:{self.chatColorThisMessageBelongsTo},
pinned:{self.pinned}
]"""
proc toJsonNode*(self: Item): JsonNode = proc toJsonNode*(self: Item): JsonNode =
result = %* { result = %* {
"id": self.id, "id": self.id,

View File

@ -1,4 +1,4 @@
import NimQml, Tables, json, strutils import NimQml, Tables, json, strutils, strformat
import message_item import message_item
@ -25,6 +25,8 @@ type
# GapTo # GapTo
Pinned Pinned
CountsForReactions CountsForReactions
ChatTypeThisMessageBelongsTo
ChatColorThisMessageBelongsTo
QtObject: QtObject:
type type
@ -42,6 +44,12 @@ QtObject:
new(result, delete) new(result, delete)
result.setup result.setup
proc `$`*(self: Model): string =
for i in 0 ..< self.items.len:
result &= fmt"""MessageModel:
[{i}]:({$self.items[i]})
"""
proc countChanged(self: Model) {.signal.} proc countChanged(self: Model) {.signal.}
proc getCount(self: Model): int {.slot.} = proc getCount(self: Model): int {.slot.} =
self.items.len self.items.len
@ -75,6 +83,8 @@ QtObject:
# ModelRole.GapTo.int:"gapTo", # ModelRole.GapTo.int:"gapTo",
ModelRole.Pinned.int:"pinned", ModelRole.Pinned.int:"pinned",
ModelRole.CountsForReactions.int:"countsForReactions", ModelRole.CountsForReactions.int:"countsForReactions",
ModelRole.ChatTypeThisMessageBelongsTo.int:"chatTypeThisMessageBelongsTo",
ModelRole.ChatColorThisMessageBelongsTo.int:"chatColorThisMessageBelongsTo",
}.toTable }.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant = method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -130,6 +140,10 @@ QtObject:
result = newQVariant(item.pinned) result = newQVariant(item.pinned)
of ModelRole.CountsForReactions: of ModelRole.CountsForReactions:
result = newQVariant($(%* item.getCountsForReactions)) result = newQVariant($(%* item.getCountsForReactions))
of ModelRole.ChatTypeThisMessageBelongsTo:
result = newQVariant(item.chatTypeThisMessageBelongsTo)
of ModelRole.ChatColorThisMessageBelongsTo:
result = newQVariant(item.chatColorThisMessageBelongsTo)
proc findIndexForMessageId(self: Model, messageId: string): int = proc findIndexForMessageId(self: Model, messageId: string): int =
for i in 0 ..< self.items.len: for i in 0 ..< self.items.len:

View File

@ -64,6 +64,9 @@ QtObject:
result.msgCursor = initTable[string, string]() result.msgCursor = initTable[string, string]()
result.pinnedMsgCursor = initTable[string, string]() result.pinnedMsgCursor = initTable[string, string]()
proc initialMessagesFetched(self: Service, chatId: string): bool =
return self.msgCursor.hasKey(chatId)
proc getCurrentMessageCursor(self: Service, chatId: string): string = proc getCurrentMessageCursor(self: Service, chatId: string): string =
if(not self.msgCursor.hasKey(chatId)): if(not self.msgCursor.hasKey(chatId)):
self.msgCursor[chatId] = "" self.msgCursor[chatId] = ""
@ -140,6 +143,9 @@ QtObject:
self.threadpool.start(arg) self.threadpool.start(arg)
proc asyncLoadInitialMessagesForChat*(self: Service, chatId: string) = proc asyncLoadInitialMessagesForChat*(self: Service, chatId: string) =
if(self.initialMessagesFetched(chatId)):
return
if(self.getCurrentMessageCursor(chatId).len > 0): if(self.getCurrentMessageCursor(chatId).len > 0):
return return

View File

@ -31,7 +31,6 @@ Item {
property real scrollY: chatLogView.visibleArea.yPosition * chatLogView.contentHeight property real scrollY: chatLogView.visibleArea.yPosition * chatLogView.contentHeight
property int newMessages: 0 property int newMessages: 0
property int countOnStartUp: 0
ListView { ListView {
id: chatLogView id: chatLogView
@ -286,41 +285,16 @@ Item {
// } // }
// } // }
model: messageListDelegate model: messageStore.messageModule.model
section.property: "sectionIdentifier" section.property: "sectionIdentifier"
section.criteria: ViewSection.FullString section.criteria: ViewSection.FullString
// Not Refactored Yet // Not Refactored Yet
//Component.onCompleted: scrollToBottom(true) //Component.onCompleted: scrollToBottom(true)
}
// MessageDialog {
// id: sendingMsgFailedPopup
// standardButtons: StandardButton.Ok
// //% "Failed to send message."
// text: qsTrId("failed-to-send-message-")
// icon: StandardIcon.Critical
// }
Timer {
id: modelLoadingDelayTimer
interval: 1000
onTriggered: {
root.countOnStartUp = messageListDelegate.count;
}
}
DelegateModelGeneralized {
id: messageListDelegate
lessThan: [
function(left, right) { return left.clock > right.clock }
]
model: messageStore.messageModule.model
delegate: MessageView { delegate: MessageView {
id: msgDelegate id: msgDelegate
rootStore: root.store
messageStore: root.messageStore messageStore: root.messageStore
messageId: model.id messageId: model.id
@ -338,6 +312,10 @@ Item {
messageContentType: model.contentType messageContentType: model.contentType
pinnedMessage: model.pinned pinnedMessage: model.pinned
// Used only in case of ChatIdentifier
chatTypeThisMessageBelongsTo: model.chatTypeThisMessageBelongsTo
chatColorThisMessageBelongsTo: model.chatColorThisMessageBelongsTo
// This is possible since we have all data loaded before we load qml. // This is possible since we have all data loaded before we load qml.
// When we fetch messages to fulfill a gap we have to set them at once. // When we fetch messages to fulfill a gap we have to set them at once.
prevMessageIndex: index - 1 prevMessageIndex: index - 1
@ -345,125 +323,16 @@ Item {
nextMessageIndex: index + 1 nextMessageIndex: index + 1
nextMessageAsJsonObj: messageStore.getMessageByIndexAsJson(index + 1) nextMessageAsJsonObj: messageStore.getMessageByIndexAsJson(index + 1)
/////////////TODO Remove
// fromAuthor: model.fromAuthor
// chatId: model.chatId
// userName: model.userName
// alias: model.alias
// localName: model.localName
// message: model.message
// plainText: model.plainText
// identicon: model.identicon
// isCurrentUser: model.isCurrentUser
// timestamp: model.timestamp
// sticker: model.sticker
// contentType: model.contentType
// replaces: model.replaces
// isEdited: model.isEdited
// outgoingStatus: model.outgoingStatus
// responseTo: model.responseTo
// authorCurrentMsg: msgDelegate.ListView.section
// // The previous message is actually the nextSection since we reversed the list order
// authorPrevMsg: msgDelegate.ListView.nextSection
// imageClick: imagePopup.openPopup.bind(imagePopup)
// messageId: model.messageId
// emojiReactions: model.emojiReactions
// linkUrls: model.linkUrls
// communityId: model.communityId
// hasMention: model.hasMention
// stickerPackId: model.stickerPackId
// pinnedMessage: model.isPinned
// pinnedBy: model.pinnedBy
// gapFrom: model.gapFrom
// gapTo: model.gapTo
// visible: !model.hide
// messageContextMenu: root.messageContextMenuInst
// prevMessageIndex: {
// // This is used in order to have access to the previous message and determine the timestamp
// // we can't rely on the index because the sequence of messages is not ordered on the nim side
// if (msgDelegate.DelegateModel.itemsIndex < messageListDelegate.items.count - 1) {
// return messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex + 1).model.index
// }
// return -1;
// }
// nextMessageIndex: {
// if (msgDelegate.DelegateModel.itemsIndex < 1) {
// return -1
// }
// return messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex - 1).model.index
// }
// scrollToBottom: chatLogView.scrollToBottom
// timeout: model.timeout
Component.onCompleted: { Component.onCompleted: {
if ((root.countOnStartUp > 0) && (root.countOnStartUp - 1) < index) { }
//new message, increment z order }
z = index;
} }
// messageStore.messageId = model.id // MessageDialog {
// messageStore.responseToMessageWithId = model.responseToMessageWithId // id: sendingMsgFailedPopup
// messageStore.senderId = model.senderId // standardButtons: StandardButton.Ok
// messageStore.senderDisplayName = model.senderDisplayName // //% "Failed to send message."
// messageStore.senderLocalName = model.senderLocalName // text: qsTrId("failed-to-send-message-")
// messageStore.senderIcon = model.senderIcon // icon: StandardIcon.Critical
// messageStore.isSenderIconIdenticon = model.isSenderIconIdenticon // }
// messageStore.amISender = model.amISender
// messageStore.message = model.messageText
// messageStore.messageImage = model.messageImage
// messageStore.messageTimestamp = model.timestamp
// messageStore.messageOutgoingStatus = model.outgoingStatus
// messageStore.messageContentType = model.contentType
// messageStore.pinnedMessage = model.pinned
// messageStore.fromAuthor = model.fromAuthor;
// messageStore.chatId = model.chatId;
// messageStore.userName = model.userName;
// messageStore.alias = model.alias;
// messageStore.localName = model.localName;
// messageStore.message = model.message;
// messageStore.plainText = model.plainText;
// messageStore.identicon = model.identicon;
// messageStore.isCurrentUser = model.isCurrentUser;
// messageStore.timestamp = model.timestamp;
// messageStore.sticker = model.sticker;
// messageStore.contentType = model.contentType;
// messageStore.replaces = model.replaces;
// messageStore.isEdited = model.isEdited;
// messageStore.outgoingStatus = model.outgoingStatus;
// messageStore.responseTo = model.responseTo;
// messageStore.authorCurrentMsg = msgDelegate.ListView.section;
// // The previous message is actually the nextSection since we reversed the list order
// messageStore.authorPrevMsg = msgDelegate.ListView.nextSection;
// messageStore.imageClick = imagePopup.openPopup.bind(imagePopup);
// messageStore.messageId = model.messageId;
// messageStore.emojiReactions = model.emojiReactions;
// messageStore.linkUrls = model.linkUrls;
// messageStore.communityId = model.communityId;
// messageStore.hasMention = model.hasMention;
// messageStore.stickerPackId = model.stickerPackId;
// messageStore.pinnedMessage = model.isPinned;
// messageStore.pinnedBy = model.pinnedBy;
// messageStore.gapFrom = model.gapFrom;
// messageStore.gapTo = model.gapTo;
// messageStore.messageContextMenu = root.messageContextMenuInst;
// messageStore.prevMessageIndex =
// // This is used in order to have access to the previous message and determine the timestamp
// // we can't rely on the index because the sequence of messages is not ordered on the nim side
// (msgDelegate.DelegateModel.itemsIndex < messageListDelegate.items.count - 1) ?
// messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex + 1).model.index
// : -1;
// messageStore.nextMessageIndex = (msgDelegate.DelegateModel.itemsIndex < 1) ?
// -1 : messageListDelegate.items.get(msgDelegate.DelegateModel.itemsIndex - 1).model.index;
// messageStore.scrollToBottom = chatLogView.scrollToBottom;
// messageStore.timeout = model.timeout;
}
}
Component.onCompleted: {
modelLoadingDelayTimer.start();
}
}
} }

View File

@ -7,14 +7,15 @@ import utils 1.0
Column { Column {
id: root id: root
spacing: Style.current.padding spacing: Style.current.padding
visible: authorCurrentMsg === ""
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
topPadding: visible ? Style.current.bigPadding : 0 topPadding: visible ? Style.current.bigPadding : 0
bottomPadding: visible? 50 : 0 bottomPadding: visible? 50 : 0
property var store property string chatName: ""
property string authorCurrentMsg: "authorCurrentMsg" property int chatType: -1
property string profileImage property string chatColor: ""
property string chatIcon: ""
property bool chatIconIsIdenticon: true
Rectangle { Rectangle {
id: circleId id: circleId
@ -22,38 +23,24 @@ Column {
width: 120 width: 120
height: 120 height: 120
radius: 120 radius: 120
border.width: root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatType.oneToOne ? 2 : 0 border.width: root.chatType === Constants.chatType.oneToOne ? 2 : 0
border.color: Style.current.border border.color: Style.current.border
color: { color: root.chatColor
if (root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatType.oneToOne) {
return Style.current.transparent
}
if (root.store.chatsModelInst.channelView.activeChannel.color) {
return root.store.chatsModelInst.channelView.activeChannel.color
}
const color = root.store.chatsModelInst.channelView.getChannelColor(chatId)
if (!color) {
return Style.current.orange
}
return color
}
RoundedImage { RoundedImage {
visible: root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatType.oneToOne visible: root.chatType === Constants.chatType.oneToOne
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
width: 120 width: 120
height: 120 height: 120
source: root.profileImage || root.store.chatsModelInst.channelView.activeChannel.identicon source: root.chatIcon
smooth: false smooth: false
antialiasing: true antialiasing: true
} }
StyledText { StyledText {
visible: root.store.chatsModelInst.channelView.activeChannel.chatType !== Constants.chatType.oneToOne visible: root.chatType !== Constants.chatType.oneToOne
text: Utils.removeStatusEns((root.store.chatsModelInst.channelView.activeChannel.name.charAt(0) === "#" ? text: root.chatName.charAt(0).toUpperCase()
root.store.chatsModelInst.channelView.activeChannel.name.charAt(1) :
root.store.chatsModelInst.channelView.activeChannel.name.charAt(0)).toUpperCase())
opacity: 0.7 opacity: 0.7
font.weight: Font.Bold font.weight: Font.Bold
font.pixelSize: 51 font.pixelSize: 51
@ -66,13 +53,7 @@ Column {
StyledText { StyledText {
id: channelName id: channelName
wrapMode: Text.Wrap wrapMode: Text.Wrap
text: { text: root.chatName
switch(root.store.chatsModelInst.channelView.activeChannel.chatType) {
case Constants.chatType.publicChat: return "#" + root.store.chatsModelInst.channelView.activeChannel.name;
case Constants.chatType.oneToOne: return Utils.removeStatusEns(root.store.chatsModelInst.userNameOrAlias(chatsModel.channelView.activeChannel.id))
default: return root.store.chatsModelInst.channelView.activeChannel.name
}
}
font.weight: Font.Bold font.weight: Font.Bold
font.pixelSize: 22 font.pixelSize: 22
color: Style.current.textColor color: Style.current.textColor
@ -85,11 +66,13 @@ Column {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: 310 width: 310
text: { text: {
switch(root.store.chatsModelInst.channelView.activeChannel.chatType) { switch(root.chatType) {
case Constants.chatType.privateGroupChat:
//% "Welcome to the beginning of the <span style='color: %1'>%2</span> group!" //% "Welcome to the beginning of the <span style='color: %1'>%2</span> group!"
case Constants.chatType.privateGroupChat: return qsTrId("welcome-to-the-beginning-of-the--span-style--color---1---2--span--group-").arg(Style.current.textColor).arg(root.store.chatsModelInst.channelView.activeChannel.name); return qsTrId("welcome-to-the-beginning-of-the--span-style--color---1---2--span--group-").arg(Style.current.textColor).arg(root.chatName);
case Constants.chatType.oneToOne:
//% "Any messages you send here are encrypted and can only be read by you and <span style='color: %1'>%2</span>" //% "Any messages you send here are encrypted and can only be read by you and <span style='color: %1'>%2</span>"
case Constants.chatType.oneToOne: return qsTrId("any-messages-you-send-here-are-encrypted-and-can-only-be-read-by-you-and--span-style--color---1---2--span-").arg(Style.current.textColor).arg(channelName.text) return qsTrId("any-messages-you-send-here-are-encrypted-and-can-only-be-read-by-you-and--span-style--color---1---2--span-").arg(Style.current.textColor).arg(root.chatName)
default: return ""; default: return "";
} }
} }
@ -100,8 +83,10 @@ Column {
} }
Item { Item {
visible: root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatType.privateGroupChat //NEED TO CHECK THIS
&& root.store.chatsModelInst.channelView.activeChannel.isMemberButNotJoined // visible: root.store.chatsModelInst.channelView.activeChannel.chatType === Constants.chatType.privateGroupChat
// && root.store.chatsModelInst.channelView.activeChannel.isMemberButNotJoined
visible: root.chatType === Constants.chatType.privateGroupChat
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: visible ? joinChat.width : 0 width: visible ? joinChat.width : 0
height: visible ? 100 : 0 height: visible ? 100 : 0
@ -119,7 +104,8 @@ Column {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
root.store.chatsModelInst.groups.join() //NEED TO CHECK THIS
// root.store.chatsModelInst.groups.join()
} }
} }
} }
@ -136,7 +122,8 @@ Column {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
root.store.chatsModelInst.channelView.leaveActiveChat() //NEED TO CHECK THIS
// root.store.chatsModelInst.channelView.leaveActiveChat()
} }
} }
} }

View File

@ -51,57 +51,58 @@ Item {
height: root.veryLongChatText && !root.readMore ? Math.min(implicitHeight, 200) : implicitHeight height: root.veryLongChatText && !root.readMore ? Math.min(implicitHeight, 200) : implicitHeight
clip: height < implicitHeight clip: height < implicitHeight
onLinkActivated: { onLinkActivated: {
root.linkActivated(link) // Not Refactored Yet
if(link.startsWith("#")) { // root.linkActivated(link)
const channelName = link.substring(1); // if(link.startsWith("#")) {
const foundChannelObj = root.store.chatsModelInst.getChannel(channelName); // const channelName = link.substring(1);
// const foundChannelObj = root.store.chatsModelInst.getChannel(channelName);
if (!foundChannelObj) // if (!foundChannelObj)
{ // {
root.store.chatsModelInst.channelView.joinPublicChat(channelName) // root.store.chatsModelInst.channelView.joinPublicChat(channelName)
if(root.store.chatsModelInst.communities.activeCommunity.active) // if(root.store.chatsModelInst.communities.activeCommunity.active)
{ // {
root.store.chatsModelInst.channelView.joinPublicChat(channelName) // root.store.chatsModelInst.channelView.joinPublicChat(channelName)
Global.changeAppSectionBySectionType(Constants.appSection.chat) // Global.changeAppSectionBySectionType(Constants.appSection.chat)
} // }
return // return
} // }
let obj = JSON.parse(foundChannelObj) // let obj = JSON.parse(foundChannelObj)
if(obj.chatType === -1 || obj.chatType === Constants.chatTypePublic) // if(obj.chatType === -1 || obj.chatType === Constants.chatTypePublic)
{ // {
if(root.store.chatsModelInst.communities.activeCommunity.active) { // if(root.store.chatsModelInst.communities.activeCommunity.active) {
root.store.chatsModelInst.channelView.joinPublicChat(channelName) // root.store.chatsModelInst.channelView.joinPublicChat(channelName)
Global.changeAppSectionBySectionType(Constants.appSection.chat) // Global.changeAppSectionBySectionType(Constants.appSection.chat)
} // }
root.store.chatsModelInst.channelView.setActiveChannel(channelName); // root.store.chatsModelInst.channelView.setActiveChannel(channelName);
} // }
else if(obj.communityId === root.store.chatsModelInst.communities.activeCommunity.id && // else if(obj.communityId === root.store.chatsModelInst.communities.activeCommunity.id &&
obj.chatType === Constants.chatTypeCommunity && // obj.chatType === Constants.chatTypeCommunity &&
root.store.chatsModelInst.channelView.activeChannel.id !== obj.id // root.store.chatsModelInst.channelView.activeChannel.id !== obj.id
) // )
{ // {
root.store.chatsModelInst.channelView.setActiveChannel(channelName); // root.store.chatsModelInst.channelView.setActiveChannel(channelName);
} // }
return // return
} // }
if (link.startsWith('//')) { // if (link.startsWith('//')) {
let pk = link.replace("//", ""); // let pk = link.replace("//", "");
const userProfileImage = appMain.getProfileImage(pk) // const userProfileImage = appMain.getProfileImage(pk)
openProfilePopup(root.store.chatsModelInst.userNameOrAlias(pk), pk, userProfileImage || root.store.utilsModelInst.generateIdenticon(pk)) // openProfilePopup(root.store.chatsModelInst.userNameOrAlias(pk), pk, userProfileImage || root.store.utilsModelInst.generateIdenticon(pk))
return; // return;
} // }
const data = Utils.getLinkDataForStatusLinks(link) // const data = Utils.getLinkDataForStatusLinks(link)
if (data && data.callback) { // if (data && data.callback) {
return data.callback() // return data.callback()
} // }
Global.openLink(link) // Global.openLink(link)
} }
onLinkHovered: { onLinkHovered: {

View File

@ -26,18 +26,13 @@ Item {
// Not Refactored Yet // Not Refactored Yet
return false return false
// if (!!rootStore) { // switch (chatTypeThisMessageBelongsTo) {
// switch (rootStore.chatsModelInst.channelView.activeChannel.chatType) {
// case Constants.chatType.oneToOne: return true // case Constants.chatType.oneToOne: return true
// case Constants.chatType.privateGroupChat: return rootStore.chatsModelInst.channelView.activeChannel.isAdmin(userProfile.pubKey) ? true : isCurrentUser // case Constants.chatType.privateGroupChat: return rootStore.chatsModelInst.channelView.activeChannel.isAdmin(userProfile.pubKey) ? true : isCurrentUser
// case Constants.chatType.publicChat: return isCurrentUser // case Constants.chatType.publicChat: return isCurrentUser
// case Constants.chatType.communityChat: return rootStore.chatsModelInst.communities.activeCommunity.admin ? true : isCurrentUser // case Constants.chatType.communityChat: return rootStore.chatsModelInst.communities.activeCommunity.admin ? true : isCurrentUser
// case Constants.chatType.profile: return false // case Constants.chatType.profile: return false
// default: return false // default: return false
// }
// }
// else {
// return false;
// } // }
} }
@ -206,8 +201,10 @@ Item {
} }
StyledText { StyledText {
//% "Pinned by %1" // Not Refactored Yet
text: qsTrId("pinned-by--1").arg(rootStore.chatsModelInst.alias(pinnedBy)) text: ""
// //% "Pinned by %1"
// text: qsTrId("pinned-by--1").arg(rootStore.chatsModelInst.alias(pinnedBy))
anchors.left: pinImage.right anchors.left: pinImage.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 13 font.pixelSize: 13
@ -217,14 +214,15 @@ Item {
} }
Connections { // Not Refactored Yet
enabled: !!rootStore // Connections {
target: enabled ? rootStore.chatsModelInst.messageView : null // enabled: !!rootStore
onMessageEdited: { // target: enabled ? rootStore.chatsModelInst.messageView : null
if(chatReply.item) // onMessageEdited: {
chatReply.item.messageEdited(editedMessageId, editedMessageContent) // if(chatReply.item)
} // chatReply.item.messageEdited(editedMessageId, editedMessageContent)
} // }
// }
ChatReplyPanel { ChatReplyPanel {
id: chatReply id: chatReply
@ -303,7 +301,7 @@ Item {
anchors.left: chatName.right anchors.left: chatName.right
anchors.leftMargin: 4 anchors.leftMargin: 4
color: Style.current.secondaryText color: Style.current.secondaryText
//timestamp: timestamp timestamp: messageTimestamp
} }
Loader { Loader {
@ -376,7 +374,7 @@ Item {
StatusChatInput { StatusChatInput {
id: editTextInput id: editTextInput
chatInputPlaceholder: qsTrId("type-a-message-") chatInputPlaceholder: qsTrId("type-a-message-")
chatType: rootStore.chatsModelInst.channelView.activeChannel.chatType chatType: chatTypeThisMessageBelongsTo
isEdit: true isEdit: true
textInput.text: editMessageLoader.sourceText textInput.text: editMessageLoader.sourceText
onSendMessage: { onSendMessage: {
@ -437,7 +435,8 @@ Item {
visible: !isEdit visible: !isEdit
ChatTextView { ChatTextView {
id: chatText id: chatText
store: rootStore // Not Refactored Yet
// store: rootStore
readonly property int leftPadding: chatImage.anchors.leftMargin + chatImage.width + chatHorizontalPadding readonly property int leftPadding: chatImage.anchors.leftMargin + chatImage.width + chatHorizontalPadding
visible: { visible: {
const urls = linkUrls.split(" ") const urls = linkUrls.split(" ")
@ -544,7 +543,8 @@ Item {
sourceComponent: Component { sourceComponent: Component {
LinksMessageView { LinksMessageView {
store: rootStore // Not Refactored Yet
// store: rootStore
linkUrls: linkUrls linkUrls: linkUrls
container: root.container container: root.container
isCurrentUser: isCurrentUser isCurrentUser: isCurrentUser
@ -585,7 +585,8 @@ Item {
sourceComponent: Component { sourceComponent: Component {
id: invitationBubble id: invitationBubble
InvitationBubbleView { InvitationBubbleView {
store: rootStore // Not Refactored Yet
// store: rootStore
communityId: root.container.communityId communityId: root.container.communityId
} }
} }

View File

@ -16,9 +16,7 @@ Column {
anchors.right: !isCurrentUser ? undefined : parent.right anchors.right: !isCurrentUser ? undefined : parent.right
z: (typeof chatLogView === "undefined") ? 1 : (chatLogView.count - index) z: (typeof chatLogView === "undefined") ? 1 : (chatLogView.count - index)
property var rootStore
property var messageStore property var messageStore
//property var chatsModel: !!root.rootStore ? root.rootStore.chatsModelInst : null
property string messageId: "" property string messageId: ""
property string responseToMessageWithId: "" property string responseToMessageWithId: ""
@ -35,6 +33,10 @@ Column {
property int messageContentType: 1 property int messageContentType: 1
property bool pinnedMessage: false property bool pinnedMessage: false
// Used only in case of ChatIdentifier
property int chatTypeThisMessageBelongsTo: -1
property string chatColorThisMessageBelongsTo: ""
property int prevMessageIndex: -1 property int prevMessageIndex: -1
property var prevMessageAsJsonObj property var prevMessageAsJsonObj
property int nextMessageIndex: -1 property int nextMessageIndex: -1
@ -91,35 +93,18 @@ Column {
property bool shouldRepeatHeader: ((parseInt(timestamp, 10) - parseInt(prevMsgTimestamp, 10)) / 60 / 1000) > Constants.repeatHeaderInterval property bool shouldRepeatHeader: ((parseInt(timestamp, 10) - parseInt(prevMsgTimestamp, 10)) / 60 / 1000) > Constants.repeatHeaderInterval
////////////////////////////////////// //////////////////////////////////////
//TODO REMOVE //TODO CHECCK - REMOVE
// property string fromAuthor: "0x0011223344556677889910"
// property string userName: "Jotaro Kujo"
// property string alias: ""
// property string localName: ""
// property string message: "That's right. We're friends... Of justice, that is."
property string plainText: "That's right. We're friends... Of justice, that is." property string plainText: "That's right. We're friends... Of justice, that is."
// property string identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQAQMAAAC6caSPAAAABlBMVEXMzMz////TjRV2AAAAAWJLR0QB/wIt3gAAACpJREFUGBntwYEAAAAAw6D7Uw/gCtUAAAAAAAAAAAAAAAAAAAAAAAAAgBNPsAABAjKCqQAAAABJRU5ErkJggg=="
// property bool isCurrentUser: false
// property string timestamp: "1234567"
property string sticker: "Qme8vJtyrEHxABcSVGPF95PtozDgUyfr1xGjePmFdZgk9v" property string sticker: "Qme8vJtyrEHxABcSVGPF95PtozDgUyfr1xGjePmFdZgk9v"
// property int contentType: 1 // constants don't work in default props
property string chatId: "chatId"
// property string outgoingStatus: ""
// property string responseTo: ""
// property string messageId: ""
property string emojiReactions: "" property string emojiReactions: ""
// property int prevMessageIndex: -1
// property int nextMessageIndex: -1
property bool timeout: false property bool timeout: false
property bool hasMention: false property bool hasMention: false
property string linkUrls: "" property string linkUrls: ""
property bool placeholderMessage: false property bool placeholderMessage: false
property bool activityCenterMessage: false property bool activityCenterMessage: false
// property bool pinnedMessage: false
property bool read: true property bool read: true
property string pinnedBy property string pinnedBy
property bool forceHoverHandler: false // Used to force the HoverHandler to be active (useful for messages in popups) property bool forceHoverHandler: false // Used to force the HoverHandler to be active (useful for messages in popups)
property string communityId: ""
property int stickerPackId: -1 property int stickerPackId: -1
property int gapFrom: 0 property int gapFrom: 0
property int gapTo: 0 property int gapTo: 0
@ -128,29 +113,8 @@ Column {
property bool isEdited: false property bool isEdited: false
property bool showEdit: true property bool showEdit: true
property var messageContextMenu property var messageContextMenu
// property string displayUserName: { //////////////////////////////////////
// if (isCurrentUser) {
// //% "You"
// return qsTrId("You")
// }
// if (localName !== "") {
// return localName
// }
// if (userName !== "") {
// return Utils.removeStatusEns(userName)
// }
// return Utils.removeStatusEns(alias)
// }
// property string authorCurrentMsg: "authorCurrentMsg"
// property string authorPrevMsg: "authorPrevMsg"
// property string prevMsgTimestamp: !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(prevMessageIndex, "timestamp") : ""
// property string nextMsgTimestamp: !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(nextMessageIndex, "timestamp"): ""
// property bool shouldRepeatHeader: ((parseInt(timestamp, 10) - parseInt(prevMsgTimestamp, 10)) / 60 / 1000) > Constants.repeatHeaderInterval
property bool isEmoji: contentType === Constants.messageContentType.emojiType property bool isEmoji: contentType === Constants.messageContentType.emojiType
property bool isImage: contentType === Constants.messageContentType.imageType property bool isImage: contentType === Constants.messageContentType.imageType
@ -165,30 +129,8 @@ Column {
property bool isStatusUpdate: false property bool isStatusUpdate: false
property int statusAgeEpoch: 0 property int statusAgeEpoch: 0
// TODO: we don't use replyMessageIndex any more, but messageId
// property int replyMessageIndex: !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageIndex(responseTo) : -1
// property string repliedMessageAuthor: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "userName") : "" : "";
// property string repliedMessageAuthorPubkey: replyMessageIndex > -1 ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "publicKey") : "";
// property bool repliedMessageAuthorIsCurrentUser: replyMessageIndex > -1 ? repliedMessageAuthorPubkey === userProfile.pubKey : "";
// property bool repliedMessageIsEdited: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "isEdited") === "true" : false : false;
// property string repliedMessageContent: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "message") : "" : "";
// property int repliedMessageType: replyMessageIndex > -1 ? !!root.chatsModel ? parseInt(root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "contentType")) : 0 : 0;
// property string repliedMessageImage: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "image") : "" : "";
// property string repliedMessageUserIdenticon: replyMessageIndex > -1 ? !!root.chatsModel ? root.chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "identicon") : "" : "";
// property string repliedMessageUserImage: replyMessageIndex > -1 ? appMain.getProfileImage(repliedMessageAuthorPubkey, repliedMessageAuthorIsCurrentUser , false) || "" : "";
property var imageClick: function () {} property var imageClick: function () {}
property var scrollToBottom: function () {} property var scrollToBottom: function () {}
// property string userPubKey: {
// if (contentType === Constants.messageContentType.chatIdentifier) {
// return chatId
// }
// return fromAuthor
// }
// property bool useLargeImage: contentType === Constants.messageContentType.chatIdentifier
// Not Refactored Yet - This will be determined on the backend
// property string profileImageSource: !placeholderMessage && appMain.getProfileImage(userPubKey, isCurrentUser, useLargeImage) || ""
property var emojiReactionsModel: { property var emojiReactionsModel: {
// Not Refactored Yet // Not Refactored Yet
@ -327,7 +269,7 @@ Column {
id: gapComponent id: gapComponent
GapComponent { GapComponent {
onClicked: { onClicked: {
// Not Refactored Yet // Not Refactored Yet - Should do it via messageStore
// root.chatsModel.messageView.fillGaps(messageStore.messageId); // root.chatsModel.messageView.fillGaps(messageStore.messageId);
// root.visible = false; // root.visible = false;
// root.height = 0; // root.height = 0;
@ -338,14 +280,14 @@ Column {
Component { Component {
id: fetchMoreMessagesButtonComponent id: fetchMoreMessagesButtonComponent
FetchMoreMessagesButton { FetchMoreMessagesButton {
// nextMessageIndex: root.messageStore.nextMessageIndex nextMessageIndex: root.nextMessageIndex
// nextMsgTimestamp: root.messageStore.nextMsgTimestamp nextMsgTimestamp: root.nextMsgTimestamp
onClicked: { onClicked: {
// Not Refactored Yet // Not Refactored Yet - Should do it via messageStore
// root.chatsModel.messageView.hideLoadingIndicator(); // root.chatsModel.messageView.hideLoadingIndicator();
} }
onTimerTriggered: { onTimerTriggered: {
// Not Refactored Yet // Not Refactored Yet - Should do it via messageStore
// root.chatsModel.requestMoreMessages(Constants.fetchRangeLast24Hours); // root.chatsModel.requestMoreMessages(Constants.fetchRangeLast24Hours);
} }
} }
@ -353,17 +295,13 @@ Column {
Component { Component {
id: channelIdentifierComponent id: channelIdentifierComponent
Rectangle { ChannelIdentifierView {
color: "blue" chatName: root.senderDisplayName
width: 100 chatType: root.chatTypeThisMessageBelongsTo
height: 100 chatColor: root.chatColorThisMessageBelongsTo
chatIcon: root.senderIcon
chatIconIsIdenticon: root.isSenderIconIdenticon
} }
// Not Refactored Yet
// ChannelIdentifierView {
// store: root.rootStore
// profileImage: profileImageSource
// authorCurrentMsg: root.authorCurrentMsg
// }
} }
// Private group Messages // Private group Messages
@ -402,25 +340,31 @@ Column {
StatusUpdateView { StatusUpdateView {
statusAgeEpoch: root.statusAgeEpoch statusAgeEpoch: root.statusAgeEpoch
container: root container: root
store: root.rootStore // Not Refactored Yet
// store: root.rootStore
messageContextMenu: root.messageContextMenu messageContextMenu: root.messageContextMenu
onAddEmoji: { onAddEmoji: {
root.clickMessage(isProfileClick, isSticker, isImage , image, emojiOnly, hideEmojiPicker); root.clickMessage(isProfileClick, isSticker, isImage , image, emojiOnly, hideEmojiPicker);
} }
onChatImageClicked: { onChatImageClicked: {
messageStore.imageClick(image); // Not Refactored Yet - Should do it via messageStore
// messageStore.imageClick(image);
} }
onUserNameClicked: { onUserNameClicked: {
root.parent.clickMessage(isProfileClick); // Not Refactored Yet - Should do it via messageStore
// root.parent.clickMessage(isProfileClick);
} }
onEmojiBtnClicked: { onEmojiBtnClicked: {
root.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly); // Not Refactored Yet - Should do it via messageStore
// root.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly);
} }
onClickMessage: { onClickMessage: {
root.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly, hideEmojiPicker, isReply); // Not Refactored Yet - Should do it via messageStore
// root.parent.clickMessage(isProfileClick, isSticker, isImage, image, emojiOnly, hideEmojiPicker, isReply);
} }
onSetMessageActive: { onSetMessageActive: {
root.messageStore.setMessageActive(messageId, active);; // Not Refactored Yet - Should do it via messageStore
// root.messageStore.setMessageActive(messageId, active);;
} }
} }
} }

View File

@ -0,0 +1,205 @@
import QtQuick 2.3
import QtGraphicalEffects 1.13
import utils 1.0
import shared 1.0
import shared.panels 1.0
import shared.status 1.0
import shared.panels.chat 1.0
import shared.controls.chat 1.0
import StatusQ.Controls 0.1
MouseArea {
id: root
// property var store
property bool hovered: containsMouse
property var container
property int statusAgeEpoch: 0
property var messageContextMenu
signal userNameClicked(bool isProfileClick)
signal setMessageActive(string messageId, bool active)
signal emojiBtnClicked(bool isProfileClick, bool isSticker, bool isImage, var image, bool emojiOnly)
signal clickMessage(bool isProfileClick, bool isSticker, bool isImage, var image, bool emojiOnly, bool hideEmojiPicker, bool isReply)
// TODO bring those back and remove dynamic scoping
// property var emojiReactionsModel
// property string timestamp: ""
// property bool isCurrentUser: false
// property bool isMessageActive: false
// property string userName: ""
// property string localName: ""
// property string displayUserName: ""
// property bool isImage: false
// property bool isMessage: false
// property string profileImageSource: ""
// property string userIdenticon: ""
anchors.top: parent.top
anchors.topMargin: 0
height: (isImage ? chatImageContent.height : chatText.height) + chatName.height + 2* Style.current.padding + (emojiReactionsModel.length ? 20 : 0)
width: parent.width
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
propagateComposedEvents: true
signal chatImageClicked(string image)
signal addEmoji(bool isProfileClick, bool isSticker, bool isImage , var image, bool emojiOnly, bool hideEmojiPicker)
onClicked: {
mouse.accepted = false
}
Rectangle {
id: rootRect
anchors.fill: parent
radius: Style.current.radius
color: root.hovered ? Style.current.border : Style.current.background
UserImage {
id: chatImage
active: isMessage || isImage
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.top: parent.top
anchors.topMargin: Style.current.halfPadding
// messageContextMenu: root.messageContextMenu
// profileImage: root.profileImageSource
// isMessage: root.isMessage
// identiconImageSource: root.userIdenticon
onClickMessage: {
root.clickMessage(true, false, false, null, false, false, isReplyImage)
}
}
UsernameLabel {
id: chatName
z: 51
visible: chatImage.visible
anchors.leftMargin: Style.current.halfPadding
anchors.top: chatImage.top
anchors.left: chatImage.right
label.font.pixelSize: Style.current.primaryTextFontSize
// messageContextMenu: root.messageContextMenu
// isCurrentUser: root.isCurrentUser
// userName: root.userName
// localName: root.localName
// displayUserName: root.displayUserName
onClickMessage: {
root.userNameClicked(true);
}
}
ChatTimePanel {
id: chatTime
// statusAgeEpoch is used to trigger Qt property update
// since the returned string will be the same in 99% cases, this should not trigger ChatTime re-rendering
text: Utils.formatAgeFromTime(timestamp, statusAgeEpoch)
visible: chatName.visible
anchors.verticalCenter: chatName.verticalCenter
anchors.left: chatName.right
anchors.leftMargin: Style.current.halfPadding
//timestamp: timestamp
}
ChatTextView {
id: chatText
anchors.top: chatName.visible ? chatName.bottom : chatImage.top
anchors.topMargin: chatName.visible ? 6 : 0
anchors.left: chatImage.right
anchors.leftMargin: Style.current.halfPadding
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
// store: root.store
}
Loader {
id: chatImageContent
active: isImage
anchors.left: chatImage.right
anchors.leftMargin: Style.current.halfPadding
anchors.top: chatText.bottom
z: 51
sourceComponent: Component {
StatusChatImage {
imageSource: image
imageWidth: 200
container: root.container
onClicked: {
root.chatImageClicked(image);
}
}
}
}
StatusFlatRoundButton {
id: emojiBtn
width: 32
height: 32
anchors.top: rootRect.top
anchors.topMargin: -height / 4
anchors.right: rootRect.right
anchors.rightMargin: Style.current.halfPadding
visible: root.hovered
icon.name: "reaction-b"
icon.width: 20
icon.height: 20
type: StatusFlatRoundButton.Type.Tertiary
backgroundHoverColor: Style.current.background
onClicked: {
// Set parent, X & Y positions for the messageContextMenu
messageContextMenu.parent = emojiBtn
messageContextMenu.setXPosition = function() { return -messageContextMenu.width + emojiBtn.width}
messageContextMenu.setYPosition = function() { return -messageContextMenu.height - 4}
root.emojiBtnClicked(false, false, false, null, true)
}
}
DropShadow {
anchors.fill: emojiBtn
horizontalOffset: 0
verticalOffset: 2
radius: 10
samples: 12
color: "#22000000"
source: emojiBtn
}
Loader {
id: emojiReactionLoader
active: emojiReactionsModel.length
sourceComponent: emojiReactionsComponent
anchors.left: chatImage.right
anchors.leftMargin: Style.current.halfPadding
anchors.top: isImage ? chatImageContent.bottom : chatText.bottom
anchors.topMargin: Style.current.halfPadding
}
Component {
id: emojiReactionsComponent
EmojiReactionsPanel {
// isMessageActive: root.isMessageActive
// emojiReactionsModel: root.emojiReactionsModel
onAddEmojiClicked: {
root.addEmoji(false, false, false, null, true, false);
// Set parent, X & Y positions for the messageContextMenu
messageContextMenu.parent = emojiReactionLoader
messageContextMenu.setXPosition = function() { return (messageContextMenu.parent.x + 4)}
messageContextMenu.setYPosition = function() { return (-messageContextMenu.height - 4)}
}
onToggleReaction: chatsModel.toggleReaction(messageId, emojiID)
// onSetMessageActive: {
// root.setMessageActive(messageId, active);;
// }
}
}
Separator {
anchors.bottom: parent.bottom
visible: !root.hovered
}
}
}