refactor: extract messages from chat view

refactor: extract messages from chat view

refactor: extract messages from chat view

refactor: extract messages from chat view

update references to messageView

fix setup

remove duplicated method
This commit is contained in:
Iuri Matias 2021-06-21 15:35:32 -04:00
parent 702f52f6ed
commit f8e5b25a09
22 changed files with 546 additions and 459 deletions

View File

@ -36,7 +36,8 @@ proc init*(self: ChatController) =
let pubKey = self.status.settings.getSetting[:string](Setting.PublicKey, "0x0")
let messagesFromContactsOnly = self.status.settings.getSetting[:bool](Setting.MessagesFromContactsOnly, false, true)
self.view.pubKey = pubKey
# self.view.pubKey = pubKey
self.view.setPubKey(pubKey)
self.status.chat.init(pubKey, messagesFromContactsOnly)
self.status.stickers.init()
self.view.reactions.init()

View File

@ -26,7 +26,7 @@ proc handleSignals(self: ChatController) =
for messageId in data.messageIds:
if self.status.messages.messages.hasKey(messageId):
let chatId = self.status.messages.messages[messageId].chatId
self.view.messageList[chatId].checkTimeout(messageId)
self.view.messageView.messageList[chatId].checkTimeout(messageId)
self.status.events.on(SignalType.CommunityFound.event) do(e: Args):
var data = CommunitySignal(e)
@ -41,4 +41,3 @@ proc handleSignals(self: ChatController) =
# TODO: retry mailserver request up to N times or change mailserver
# If > N, then
self.view.hideLoadingIndicator()

View File

@ -9,7 +9,7 @@ import ../../status/ens as status_ens
import ../../status/chat/[chat, message]
import ../../status/profile/profile
import web3/[conversions, ethtypes]
import views/[channels_list, message_list, chat_item, suggestions_list, reactions, stickers, groups, transactions, communities, community_list, community_item, format_input, ens, activity_notification_list, channel]
import views/[channels_list, message_list, chat_item, suggestions_list, reactions, stickers, groups, transactions, communities, community_list, community_item, format_input, ens, activity_notification_list, channel, messages]
import ../utils/image_utils
import ../../status/tasks/[qt, task_runner_impl]
import ../../status/tasks/marathon/mailserver/worker
@ -23,14 +23,10 @@ logScope:
topics = "chats-view"
type
ChatViewRoles {.pure.} = enum
MessageList = UserRole + 1
GetLinkPreviewDataTaskArg = ref object of QObjectTaskArg
link: string
uuid: string
AsyncActivityNotificationLoadTaskArg = ref object of QObjectTaskArg
AsyncMessageLoadTaskArg = ref object of QObjectTaskArg
chatId: string
const getLinkPreviewDataTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[GetLinkPreviewDataTaskArg](argEncoded)
@ -50,34 +46,6 @@ proc getLinkPreviewData[T](self: T, slot: string, link: string, uuid: string) =
)
self.status.tasks.threadpool.start(arg)
const asyncMessageLoadTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncMessageLoadTaskArg](argEncoded)
var messages: JsonNode
var msgCallSuccess: bool
let msgCallResult = status_chat.rpcChatMessages(arg.chatId, newJString(""), 20, msgCallSuccess)
if(msgCallSuccess):
messages = msgCallResult.parseJson()["result"]
var reactions: JsonNode
var reactionsCallSuccess: bool
let reactionsCallResult = status_chat.rpcReactions(arg.chatId, newJString(""), 20, reactionsCallSuccess)
if(reactionsCallSuccess):
reactions = reactionsCallResult.parseJson()["result"]
var pinnedMessages: JsonNode
var pinnedMessagesCallSuccess: bool
let pinnedMessagesCallResult = status_chat.rpcPinnedChatMessages(arg.chatId, newJString(""), 20, pinnedMessagesCallSuccess)
if(pinnedMessagesCallSuccess):
pinnedMessages = pinnedMessagesCallResult.parseJson()["result"]
let responseJson = %*{
"chatId": arg.chatId,
"messages": messages,
"reactions": reactions,
"pinnedMessages": pinnedMessages
}
arg.finish(responseJson)
const asyncActivityNotificationLoadTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncActivityNotificationLoadTaskArg](argEncoded)
var activityNotifications: JsonNode
@ -91,15 +59,6 @@ const asyncActivityNotificationLoadTask: Task = proc(argEncoded: string) {.gcsaf
}
arg.finish(responseJson)
proc asyncMessageLoad[T](self: T, slot: string, chatId: string) =
let arg = AsyncMessageLoadTaskArg(
tptr: cast[ByteAddress](asyncMessageLoadTask),
vptr: cast[ByteAddress](self.vptr),
slot: slot,
chatId: chatId
)
self.status.tasks.threadpool.start(arg)
proc asyncActivityNotificationLoad[T](self: T, slot: string) =
let arg = AsyncActivityNotificationLoadTaskArg(
tptr: cast[ByteAddress](asyncActivityNotificationLoadTask),
@ -115,21 +74,17 @@ QtObject:
formatInputView: FormatInputView
ensView: EnsView
channelView*: ChannelView
messageView*: MessageView
currentSuggestions*: SuggestionsList
activityNotificationList*: ActivityNotificationList
callResult: string
messageList*: OrderedTable[string, ChatMessageList]
pinnedMessagesList*: OrderedTable[string, ChatMessageList]
reactions*: ReactionView
stickers*: StickersView
groups*: GroupsView
transactions*: TransactionsView
communities*: CommunitiesView
replyTo: string
channelOpenTime*: Table[string, int64]
connected: bool
unreadMessageCnt: int
loadingMessages: bool
timelineChat: Chat
pubKey*: string
@ -140,18 +95,11 @@ QtObject:
self.ensView.delete
self.currentSuggestions.delete
self.activityNotificationList.delete
for msg in self.messageList.values:
msg.delete
for msg in self.pinnedMessagesList.values:
msg.delete
self.reactions.delete
self.stickers.delete
self.groups.delete
self.transactions.delete
self.messageList = initOrderedTable[string, ChatMessageList]()
self.pinnedMessagesList = initOrderedTable[string, ChatMessageList]()
self.communities.delete
self.channelOpenTime = initTable[string, int64]()
self.QAbstractListModel.delete
proc newChatsView*(status: Status): ChatsView =
@ -161,21 +109,21 @@ QtObject:
result.ensView = newEnsView(status)
result.communities = newCommunitiesView(status)
result.channelView = newChannelView(status, result.communities)
result.messageView = newMessageView(status, result.channelView, result.communities)
result.connected = false
result.currentSuggestions = newSuggestionsList()
result.activityNotificationList = newActivityNotificationList(status)
result.messageList = initOrderedTable[string, ChatMessageList]()
result.pinnedMessagesList = initOrderedTable[string, ChatMessageList]()
result.reactions = newReactionView(status, result.messageList.addr, result.channelView.activeChannel)
result.reactions = newReactionView(status, result.messageView.messageList.addr, result.channelView.activeChannel)
result.stickers = newStickersView(status, result.channelView.activeChannel)
result.groups = newGroupsView(status,result.channelView.activeChannel)
result.transactions = newTransactionsView(status)
result.unreadMessageCnt = 0
result.loadingMessages = false
result.messageList[status_utils.getTimelineChatId()] = newChatMessageList(status_utils.getTimelineChatId(), result.status, false)
result.setup()
proc setPubKey*(self: ChatsView, pubKey: string) =
self.pubKey = pubKey
self.messageView.pubKey = pubKey
proc getFormatInput(self: ChatsView): QVariant {.slot.} = newQVariant(self.formatInputView)
QtProperty[QVariant] formatInputView:
read = getFormatInput
@ -198,70 +146,13 @@ QtObject:
self.channelView.activeChannelChanged()
self.triggerActiveChannelChange()
proc getMessageListIndexById(self: ChatsView, id: string): int
proc replaceMentionsWithPubKeys(self: ChatsView, mentions: seq[string], contacts: seq[Profile], message: string, predicate: proc (contact: Profile): string): string =
var updatedMessage = message
for mention in mentions:
let matches = contacts.filter(c => "@" & predicate(c).toLowerAscii == mention.toLowerAscii).map(c => c.address)
if matches.len > 0:
let pubKey = matches[0]
var startIndex = 0
var index = updatedMessage.find(mention)
while index > -1:
if index == 0 or updatedMessage[index-1] == ' ':
updatedMessage = updatedMessage.replaceWord(mention, '@' & pubKey)
startIndex = index + mention.len
index = updatedMessage.find(mention, startIndex)
result = updatedMessage
proc getMessageView*(self: ChatsView): QVariant {.slot.} = newQVariant(self.messageView)
QtProperty[QVariant] messageView:
read = getMessageView
proc plainText(self: ChatsView, input: string): string {.slot.} =
result = plain_text(input)
proc sendMessage*(self: ChatsView, message: string, replyTo: string, contentType: int = ContentType.Message.int, isStatusUpdate: bool = false, contactsString: string = "") {.slot.} =
let aliasPattern = re(r"(@[A-z][a-z]+ [A-z][a-z]* [A-z][a-z]*)", flags = {reStudy, reIgnoreCase})
let ensPattern = re(r"(@\w+(?=(\.stateofus)?\.eth))", flags = {reStudy, reIgnoreCase})
let namePattern = re(r"(@\w+)", flags = {reStudy, reIgnoreCase})
var contacts: seq[Profile]
if (contactsString == ""):
contacts = self.status.contacts.getContacts()
else:
let contactsJSON = parseJson(contactsString)
contacts = @[]
for contact in contactsJSON:
contacts.add(Profile(
address: contact["address"].str,
alias: contact["alias"].str,
ensName: contact["ensName"].str
))
let aliasMentions = findAll(message, aliasPattern)
let ensMentions = findAll(message, ensPattern)
let nameMentions = findAll(message, namePattern)
var m = self.replaceMentionsWithPubKeys(aliasMentions, contacts, message, (c => c.alias))
m = self.replaceMentionsWithPubKeys(ensMentions, contacts, m, (c => c.ensName))
m = self.replaceMentionsWithPubKeys(nameMentions, contacts, m, (c => c.ensName.split(".")[0]))
var channelId = self.channelView.activeChannel.id
if isStatusUpdate:
channelId = "@" & self.pubKey
self.status.chat.sendMessage(channelId, m, replyTo, contentType)
proc verifyMessageSent*(self: ChatsView, data: string) {.slot.} =
let messageData = data.parseJson
self.messageList[messageData["chatId"].getStr].checkTimeout(messageData["id"].getStr)
proc resendMessage*(self: ChatsView, chatId: string, messageId: string) {.slot.} =
self.status.messages.trackMessage(messageId, chatId)
self.status.chat.resendMessage(messageId)
self.messageList[chatId].resetTimeOut(messageId)
proc sendImage*(self: ChatsView, imagePath: string, isStatusUpdate: bool = false): string {.slot.} =
result = ""
try:
@ -297,12 +188,8 @@ QtObject:
error "Error sending images", msg = e.msg
result = fmt"Error sending images: {e.msg}"
proc sendingMessage*(self: ChatsView) {.signal.}
proc appReady*(self: ChatsView) {.signal.}
proc sendingMessageFailed*(self: ChatsView) {.signal.}
proc alias*(self: ChatsView, pubKey: string): string {.slot.} =
if (pubKey == ""):
return ""
@ -328,49 +215,6 @@ QtObject:
read = getActivityNotificationList
notify = activityNotificationsChanged
proc upsertChannel(self: ChatsView, channel: string) =
var chat: Chat = nil
if self.status.chat.channels.hasKey(channel):
chat = self.status.chat.channels[channel]
else:
chat = self.communities.getChannel(channel)
if not self.messageList.hasKey(channel):
self.beginInsertRows(newQModelIndex(), self.messageList.len, self.messageList.len)
self.messageList[channel] = newChatMessageList(channel, self.status, not chat.isNil and chat.chatType != ChatType.Profile)
self.channelOpenTime[channel] = now().toTime.toUnix * 1000
self.endInsertRows();
if not self.pinnedMessagesList.hasKey(channel):
self.pinnedMessagesList[channel] = newChatMessageList(channel, self.status, false)
proc messagePushed*(self: ChatsView, messageIndex: int) {.signal.}
proc newMessagePushed*(self: ChatsView) {.signal.}
proc messageNotificationPushed*(self: ChatsView, chatId: string, text: string, messageType: string, chatType: int, timestamp: string, identicon: string, username: string, hasMention: bool, isAddedContact: bool, channelName: string) {.signal.}
proc messagesCleared*(self: ChatsView) {.signal.}
proc clearMessages*(self: ChatsView, id: string) =
let channel = self.channelView.getChannelById(id)
if (channel == nil):
return
self.messageList[id].clear(not channel.isNil and channel.chatType != ChatType.Profile)
self.messagesCleared()
proc isAddedContact*(self: ChatsView, id: string): bool {.slot.} =
result = self.status.contacts.isAdded(id)
proc pushPinnedMessages*(self:ChatsView, pinnedMessages: var seq[Message]) =
for msg in pinnedMessages.mitems:
self.upsertChannel(msg.chatId)
var message = self.messageList[msg.chatId].getMessageById(msg.id)
message.pinnedBy = msg.pinnedBy
message.isPinned = true
self.pinnedMessagesList[msg.chatId].add(message)
# put the message as pinned in the message list
self.messageList[msg.chatId].changeMessagePinned(msg.id, true, msg.pinnedBy)
proc pushActivityCenterNotifications*(self:ChatsView, activityCenterNotifications: seq[ActivityCenterNotification]) =
self.activityNotificationList.addActivityNotificationItemsToList(activityCenterNotifications)
self.activityNotificationsChanged()
@ -386,42 +230,11 @@ QtObject:
self.channelView.activeChannel.setChatItem(self.timelineChat)
self.activeChannelChanged()
proc pushMessages*(self:ChatsView, messages: var seq[Message]) =
for msg in messages.mitems:
self.upsertChannel(msg.chatId)
msg.userName = self.status.chat.getUserName(msg.fromAuthor, msg.alias)
var msgIndex:int;
if self.status.chat.channels.hasKey(msg.chatId):
let chat = self.status.chat.channels[msg.chatId]
if (chat.chatType == ChatType.Profile):
let timelineChatId = status_utils.getTimelineChatId()
self.messageList[timelineChatId].add(msg)
if self.channelView.activeChannel.id == timelineChatId: self.activeChannelChanged()
msgIndex = self.messageList[timelineChatId].messages.len - 1
else:
self.messageList[msg.chatId].add(msg)
msgIndex = self.messageList[msg.chatId].messages.len - 1
self.messagePushed(msgIndex)
if self.channelOpenTime.getOrDefault(msg.chatId, high(int64)) < msg.timestamp.parseFloat.fromUnixFloat.toUnix:
var channel = self.channelView.chats.getChannelById(msg.chatId)
if (channel == nil):
channel = self.communities.getChannel(msg.chatId)
if (channel == nil):
continue
if msg.chatId == self.channelView.activeChannel.id:
discard self.status.chat.markMessagesSeen(msg.chatId, @[msg.id])
self.newMessagePushed()
if not channel.muted:
let isAddedContact = channel.chatType.isOneToOne and self.isAddedContact(channel.id)
self.messageNotificationPushed(msg.chatId, escape_html(msg.text), msg.messageType, channel.chatType.int, msg.timestamp, msg.identicon, msg.userName, msg.hasMention, isAddedContact, channel.name)
proc updateUsernames*(self:ChatsView, contacts: seq[Profile]) =
if contacts.len > 0:
# Updating usernames for all the messages list
for k in self.messageList.keys:
self.messageList[k].updateUsernames(contacts)
for k in self.messageView.messageList.keys:
self.messageView.messageList[k].updateUsernames(contacts)
self.channelView.activeChannel.contactsUpdated()
proc updateChannelForContacts*(self: ChatsView, contacts: seq[Profile]) =
@ -441,44 +254,10 @@ QtObject:
self.channelView.activeChannel.setChatItem(channel)
self.activeChannelChanged()
proc markMessageAsSent*(self:ChatsView, chat: string, messageId: string) =
if self.messageList.contains(chat):
self.messageList[chat].markMessageAsSent(messageId)
else:
error "Message could not be marked as sent", chat, messageId
proc getMessageIndex(self: ChatsView, chatId: string, messageId: string): int {.slot.} =
if (not self.messageList.hasKey(chatId)):
return -1
result = self.messageList[chatId].getMessageIndex(messageId)
proc getMessageData(self: ChatsView, chatId: string, index: int, data: string): string {.slot.} =
if (not self.messageList.hasKey(chatId)):
return
return self.messageList[chatId].getMessageData(index, data)
proc getMessageList(self: ChatsView): QVariant {.slot.} =
self.upsertChannel(self.channelView.activeChannel.id)
return newQVariant(self.messageList[self.channelView.activeChannel.id])
QtProperty[QVariant] messageList:
read = getMessageList
notify = triggerActiveChannelChange
proc getPinnedMessagesList(self: ChatsView): QVariant {.slot.} =
self.upsertChannel(self.channelView.activeChannel.id)
return newQVariant(self.pinnedMessagesList[self.channelView.activeChannel.id])
QtProperty[QVariant] pinnedMessagesList:
read = getPinnedMessagesList
notify = triggerActiveChannelChange
proc pushChatItem*(self: ChatsView, chatItem: Chat) =
discard self.channelView.chats.addChatItemToList(chatItem)
self.messagePushed(self.messageList[chatItem.id].messages.len - 1)
self.messageView.messagePushed(self.messageView.messageList[chatItem.id].messages.len - 1)
proc setTimelineChat*(self: ChatsView, chatItem: Chat) =
self.timelineChat = chatItem
@ -499,54 +278,9 @@ QtObject:
return -1
selectedChannel.chatType.int
proc messagesLoaded*(self: ChatsView) {.signal.}
proc loadMoreMessages*(self: ChatsView) {.slot.} =
trace "Loading more messages", chaId = self.channelView.activeChannel.id
self.status.chat.chatMessages(self.channelView.activeChannel.id, false)
self.status.chat.chatReactions(self.channelView.activeChannel.id, false)
self.messagesLoaded();
proc loadMoreMessagesWithIndex*(self: ChatsView, channelIndex: int) {.slot.} =
if (self.channelView.chats.chats.len == 0): return
let selectedChannel = self.channelView.getChannel(channelIndex)
if (selectedChannel == nil): return
trace "Loading more messages", chaId = selectedChannel.id
self.status.chat.chatMessages(selectedChannel.id, false)
self.status.chat.chatReactions(selectedChannel.id, false)
self.messagesLoaded();
proc loadingMessagesChanged*(self: ChatsView, value: bool) {.signal.}
proc asyncMessageLoad*(self: ChatsView, chatId: string) {.slot.} =
self.asyncMessageLoad("asyncMessageLoaded", chatId)
proc asyncActivityNotificationLoad*(self: ChatsView) {.slot.} =
self.asyncActivityNotificationLoad("asyncActivityNotificationLoaded")
proc asyncMessageLoaded*(self: ChatsView, rpcResponse: string) {.slot.} =
let
rpcResponseObj = rpcResponse.parseJson
chatId = rpcResponseObj{"chatId"}.getStr
if chatId == "": # .getStr() returns "" when field is not found
return
let messages = rpcResponseObj{"messages"}
if(messages != nil and messages.kind != JNull):
let chatMessages = libstatus_chat.parseChatMessagesResponse(messages)
self.status.chat.chatMessages(chatId, true, chatMessages[0], chatMessages[1])
let rxns = rpcResponseObj{"reactions"}
if(rxns != nil and rxns.kind != JNull):
let reactions = status_chat.parseReactionsResponse(chatId, rxns)
self.status.chat.chatReactions(chatId, true, reactions[0], reactions[1])
let pinnedMsgs = rpcResponseObj{"pinnedMessages"}
if(pinnedMsgs != nil and pinnedMsgs.kind != JNull):
let pinnedMessages = libstatus_chat.parseChatMessagesResponse(pinnedMsgs)
self.status.chat.pinnedMessagesByChatID(chatId, pinnedMessages[0], pinnedMessages[1])
proc asyncActivityNotificationLoaded*(self: ChatsView, rpcResponse: string) {.slot.} =
let rpcResponseObj = rpcResponse.parseJson
@ -554,77 +288,32 @@ QtObject:
let activityNotifications = parseActivityCenterNotifications(rpcResponseObj["activityNotifications"])
self.status.chat.activityCenterNotifications(activityNotifications[0], activityNotifications[1])
proc hideLoadingIndicator*(self: ChatsView) {.slot.} =
self.loadingMessages = false
self.loadingMessagesChanged(false)
proc setLoadingMessages*(self: ChatsView, value: bool) {.slot.} =
self.loadingMessages = value
self.loadingMessagesChanged(value)
proc isLoadingMessages(self: ChatsView): QVariant {.slot.} =
return newQVariant(self.loadingMessages)
QtProperty[QVariant] loadingMessages:
read = isLoadingMessages
write = setLoadingMessages
notify = loadingMessagesChanged
proc requestMoreMessages*(self: ChatsView, fetchRange: int) {.slot.} =
self.loadingMessages = true
self.loadingMessagesChanged(true)
let mailserverWorker = self.status.tasks.marathon[MailserverWorker().name]
let task = RequestMessagesTaskArg( `method`: "requestMoreMessages", chatId: self.channelView.activeChannel.id)
mailserverWorker.start(task)
proc fillGaps*(self: ChatsView, messageId: string) {.slot.} =
self.loadingMessages = true
self.loadingMessagesChanged(true)
discard self.status.mailservers.fillGaps(self.channelView.activeChannel.id, @[messageId])
proc removeChat*(self: ChatsView, chatId: string) =
discard self.channelView.chats.removeChatItemFromList(chatId)
if (self.messageList.hasKey(chatId)):
let index = self.getMessageListIndexById(chatId)
if (self.messageView.messageList.hasKey(chatId)):
let index = self.messageView.getMessageListIndexById(chatId)
self.beginRemoveRows(newQModelIndex(), index, index)
self.messageList[chatId].delete
self.messageList.del(chatId)
self.messageView.messageList[chatId].delete
self.messageView.messageList.del(chatId)
self.endRemoveRows()
proc toggleReaction*(self: ChatsView, messageId: string, emojiId: int) {.slot.} =
if self.channelView.activeChannel.id == status_utils.getTimelineChatId():
let message = self.messageList[status_utils.getTimelineChatId()].getMessageById(messageId)
let message = self.messageView.messageList[status_utils.getTimelineChatId()].getMessageById(messageId)
self.reactions.toggle(messageId, message.chatId, emojiId)
else:
self.reactions.toggle(messageId, self.channelView.activeChannel.id, emojiId)
proc removeMessagesFromTimeline*(self: ChatsView, chatId: string) =
self.messageList[status_utils.getTimelineChatId()].deleteMessagesByChatId(chatId)
self.activeChannelChanged()
proc unreadMessages*(self: ChatsView): int {.slot.} =
result = self.unreadMessageCnt
proc unreadMessagesCntChanged*(self: ChatsView) {.signal.}
QtProperty[int] unreadMessagesCount:
read = unreadMessages
notify = unreadMessagesCntChanged
proc calculateUnreadMessages*(self: ChatsView) =
var unreadTotal = 0
for chatItem in self.channelView.chats.chats:
unreadTotal = unreadTotal + chatItem.unviewedMessagesCount
if unreadTotal != self.unreadMessageCnt:
self.unreadMessageCnt = unreadTotal
self.unreadMessagesCntChanged()
self.messageView.messageList[status_utils.getTimelineChatId()].deleteMessagesByChatId(chatId)
self.channelView.activeChannelChanged()
proc updateChats*(self: ChatsView, chats: seq[Chat]) =
for chat in chats:
if (chat.communityId != ""):
self.communities.updateCommunityChat(chat)
return
self.upsertChannel(chat.id)
self.messageView.upsertChannel(chat.id)
self.channelView.chats.updateChat(chat)
if(self.channelView.activeChannel.id == chat.id):
self.channelView.activeChannel.setChatItem(chat)
@ -633,10 +322,7 @@ QtObject:
if self.channelView.contextChannel.id == chat.id:
self.channelView.contextChannel.setChatItem(chat)
self.channelView.contextChannelChanged()
self.calculateUnreadMessages()
proc deleteMessage*(self: ChatsView, channelId: string, messageId: string) =
self.messageList[channelId].deleteMessage(messageId)
self.messageView.calculateUnreadMessages()
proc isConnected*(self: ChatsView): bool {.slot.} =
result = self.status.network.isConnected
@ -675,80 +361,17 @@ QtObject:
QtProperty[QVariant] transactions:
read = getTransactions
method rowCount*(self: ChatsView, index: QModelIndex = nil): int =
result = self.messageList.len
method data(self: ChatsView, index: QModelIndex, role: int): QVariant =
if not index.isValid:
return
if index.row < 0 or index.row >= self.messageList.len:
return
return newQVariant(toSeq(self.messageList.values)[index.row])
method roleNames(self: ChatsView): Table[int, string] =
{
ChatViewRoles.MessageList.int:"messages"
}.toTable
proc removeMessagesByUserId(self: ChatsView, publicKey: string) {.slot.} =
for k in self.messageList.keys:
self.messageList[k].removeMessagesByUserId(publicKey)
proc getMessageListIndex(self: ChatsView): int {.slot.} =
var idx = -1
for msg in toSeq(self.messageList.values):
idx = idx + 1
if(self.channelView.activeChannel.id == msg.id): return idx
return idx
proc getMessageListIndexById(self: ChatsView, id: string): int {.slot.} =
var idx = -1
for msg in toSeq(self.messageList.values):
idx = idx + 1
if(id == msg.id): return idx
return idx
proc addPinMessage*(self: ChatsView, messageId: string, chatId: string, pinnedBy: string) =
self.upsertChannel(chatId)
self.messageList[chatId].changeMessagePinned(messageId, true, pinnedBy)
var message = self.messageList[chatId].getMessageById(messageId)
message.pinnedBy = pinnedBy
self.pinnedMessagesList[chatId].add(message)
proc removePinMessage*(self: ChatsView, messageId: string, chatId: string) =
self.upsertChannel(chatId)
self.messageList[chatId].changeMessagePinned(messageId, false, "")
try:
self.pinnedMessagesList[chatId].remove(messageId)
except Exception as e:
error "Error removing ", msg = e.msg
proc pinMessage*(self: ChatsView, messageId: string, chatId: string) {.slot.} =
self.status.chat.setPinMessage(messageId, chatId, true)
self.addPinMessage(messageId, chatId, self.pubKey)
proc unPinMessage*(self: ChatsView, messageId: string, chatId: string) {.slot.} =
self.status.chat.setPinMessage(messageId, chatId, false)
self.removePinMessage(messageId, chatId)
proc addPinnedMessages*(self: ChatsView, pinnedMessages: seq[Message]) =
for pinnedMessage in pinnedMessages:
if (pinnedMessage.isPinned):
self.addPinMessage(pinnedMessage.id, pinnedMessage.localChatId, pinnedMessage.pinnedBy)
else:
self.removePinMessage(pinnedMessage.id, pinnedMessage.localChatId)
proc isActiveMailserverResult(self: ChatsView, resultEncoded: string) {.slot.} =
let isActiveMailserverAvailable = decode[bool](resultEncoded)
if isActiveMailserverAvailable:
self.setLoadingMessages(true)
self.messageView.setLoadingMessages(true)
let
mailserverWorker = self.status.tasks.marathon[MailserverWorker().name]
task = RequestMessagesTaskArg(`method`: "requestMessages")
mailserverWorker.start(task)
proc requestAllHistoricMessagesResult(self: ChatsView, resultEncoded: string) {.slot.} =
self.setLoadingMessages(true)
self.messageView.setLoadingMessages(true)
proc createCommunityChannel*(self: ChatsView, communityId: string, name: string, description: string, categoryId: string): string {.slot.} =
try:
@ -789,3 +412,45 @@ QtObject:
proc setActiveChannel*(self: ChatsView, channel: string) {.slot.} =
self.channelView.setActiveChannel(channel)
# proc activeChannelChanged*(self: ChatsView) =
# self.channelView.activeChannelChanged()
proc requestMoreMessages*(self: ChatsView, fetchRange: int) {.slot.} =
self.messageView.loadingMessages = true
self.messageView.loadingMessagesChanged(true)
let mailserverWorker = self.status.tasks.marathon[MailserverWorker().name]
let task = RequestMessagesTaskArg( `method`: "requestMoreMessages", chatId: self.channelView.activeChannel.id)
mailserverWorker.start(task)
proc pushMessages*(self: ChatsView, messages: var seq[Message]) =
self.messageView.pushMessages(messages)
proc pushPinnedMessages*(self: ChatsView, pinnedMessages: var seq[Message]) =
self.messageView.pushPinnedMessages(pinnedMessages)
proc hideLoadingIndicator*(self: ChatsView) {.slot.} =
self.messageView.hideLoadingIndicator()
proc deleteMessage*(self: ChatsView, channelId: string, messageId: string) =
self.messageView.deleteMessage(channelId, messageId)
proc addPinnedMessages*(self: ChatsView, pinnedMessages: seq[Message]) =
self.messageView.addPinnedMessages(pinnedMessages)
proc clearMessages*(self: ChatsView, id: string) =
self.messageView.clearMessages(id)
proc asyncMessageLoad*(self: ChatsView, chatId: string) {.slot.} =
self.messageView.asyncMessageLoad(chatId)
proc calculateUnreadMessages*(self: ChatsView) =
self.messageView.calculateUnreadMessages()
proc sendingMessage*(self: ChatsView) =
self.messageView.sendingMessage()
proc sendingMessageFailed*(self: ChatsView) =
self.messageView.sendingMessageFailed()
proc markMessageAsSent*(self: ChatsView, chat: string, messageId: string) =
self.messageView.markMessageAsSent(chat, messageId)

View File

@ -0,0 +1,422 @@
import NimQml, Tables, json, sequtils, chronicles, times, re, sugar, strutils, os, strformat, algorithm
import ../../../status/[status, contacts, types, mailservers]
import ../../../status/signals/types as signal_types
import ../../../status/ens as status_ens
import ../../../status/chat as status_chat
import ../../../status/messages as status_messages
import ../../../status/utils as status_utils
import ../../../status/chat/[chat, message]
import ../../../status/profile/profile
import ../../../status/tasks/[qt, task_runner_impl]
import communities, chat_item, channels_list, communities, community_list, message_list, channel
# TODO: remove me
import ../../../status/libstatus/chat as libstatus_chat
logScope:
topics = "messages-view"
type
ChatViewRoles {.pure.} = enum
MessageList = UserRole + 1
type
AsyncMessageLoadTaskArg = ref object of QObjectTaskArg
chatId: string
const asyncMessageLoadTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncMessageLoadTaskArg](argEncoded)
var messages: JsonNode
var msgCallSuccess: bool
let msgCallResult = status_chat.rpcChatMessages(arg.chatId, newJString(""), 20, msgCallSuccess)
if(msgCallSuccess):
messages = msgCallResult.parseJson()["result"]
var reactions: JsonNode
var reactionsCallSuccess: bool
let reactionsCallResult = status_chat.rpcReactions(arg.chatId, newJString(""), 20, reactionsCallSuccess)
if(reactionsCallSuccess):
reactions = reactionsCallResult.parseJson()["result"]
var pinnedMessages: JsonNode
var pinnedMessagesCallSuccess: bool
let pinnedMessagesCallResult = status_chat.rpcPinnedChatMessages(arg.chatId, newJString(""), 20, pinnedMessagesCallSuccess)
if(pinnedMessagesCallSuccess):
pinnedMessages = pinnedMessagesCallResult.parseJson()["result"]
let responseJson = %*{
"chatId": arg.chatId,
"messages": messages,
"reactions": reactions,
"pinnedMessages": pinnedMessages
}
arg.finish(responseJson)
proc asyncMessageLoad[T](self: T, slot: string, chatId: string) =
let arg = AsyncMessageLoadTaskArg(
tptr: cast[ByteAddress](asyncMessageLoadTask),
vptr: cast[ByteAddress](self.vptr),
slot: slot,
chatId: chatId
)
self.status.tasks.threadpool.start(arg)
QtObject:
type MessageView* = ref object of QAbstractListModel
status: Status
messageList*: OrderedTable[string, ChatMessageList]
pinnedMessagesList*: OrderedTable[string, ChatMessageList]
channelView*: ChannelView
communities*: CommunitiesView
pubKey*: string
loadingMessages*: bool
unreadMessageCnt: int
channelOpenTime*: Table[string, int64]
proc setup(self: MessageView) = self.QAbstractListModel.setup
proc delete*(self: MessageView) =
for msg in self.messageList.values:
msg.delete
for msg in self.pinnedMessagesList.values:
msg.delete
self.messageList = initOrderedTable[string, ChatMessageList]()
self.pinnedMessagesList = initOrderedTable[string, ChatMessageList]()
self.channelOpenTime = initTable[string, int64]()
# self.QObject.delete
self.QAbstractListModel.delete
proc newMessageView*(status: Status, channelView: ChannelView, communitiesView: CommunitiesView): MessageView =
new(result, delete)
result.status = status
result.channelView = channelView
result.communities = communitiesView
result.messageList = initOrderedTable[string, ChatMessageList]()
result.pinnedMessagesList = initOrderedTable[string, ChatMessageList]()
result.messageList[status_utils.getTimelineChatId()] = newChatMessageList(status_utils.getTimelineChatId(), result.status, false)
result.loadingMessages = false
result.unreadMessageCnt = 0
result.setup
# proc getMessageListIndexById(self: MessageView, id: string): int
proc replaceMentionsWithPubKeys(self: MessageView, mentions: seq[string], contacts: seq[Profile], message: string, predicate: proc (contact: Profile): string): string =
var updatedMessage = message
for mention in mentions:
let matches = contacts.filter(c => "@" & predicate(c).toLowerAscii == mention.toLowerAscii).map(c => c.address)
if matches.len > 0:
let pubKey = matches[0]
var startIndex = 0
var index = updatedMessage.find(mention)
while index > -1:
if index == 0 or updatedMessage[index-1] == ' ':
updatedMessage = updatedMessage.replaceWord(mention, '@' & pubKey)
startIndex = index + mention.len
index = updatedMessage.find(mention, startIndex)
result = updatedMessage
proc sendMessage*(self: MessageView, message: string, replyTo: string, contentType: int = ContentType.Message.int, isStatusUpdate: bool = false, contactsString: string = "") {.slot.} =
let aliasPattern = re(r"(@[A-z][a-z]+ [A-z][a-z]* [A-z][a-z]*)", flags = {reStudy, reIgnoreCase})
let ensPattern = re(r"(@\w+(?=(\.stateofus)?\.eth))", flags = {reStudy, reIgnoreCase})
let namePattern = re(r"(@\w+)", flags = {reStudy, reIgnoreCase})
var contacts: seq[Profile]
if (contactsString == ""):
contacts = self.status.contacts.getContacts()
else:
let contactsJSON = parseJson(contactsString)
contacts = @[]
for contact in contactsJSON:
contacts.add(Profile(
address: contact["address"].str,
alias: contact["alias"].str,
ensName: contact["ensName"].str
))
let aliasMentions = findAll(message, aliasPattern)
let ensMentions = findAll(message, ensPattern)
let nameMentions = findAll(message, namePattern)
var m = self.replaceMentionsWithPubKeys(aliasMentions, contacts, message, (c => c.alias))
m = self.replaceMentionsWithPubKeys(ensMentions, contacts, m, (c => c.ensName))
m = self.replaceMentionsWithPubKeys(nameMentions, contacts, m, (c => c.ensName.split(".")[0]))
var channelId = self.channelView.activeChannel.id
if isStatusUpdate:
channelId = "@" & self.pubKey
self.status.chat.sendMessage(channelId, m, replyTo, contentType)
proc verifyMessageSent*(self: MessageView, data: string) {.slot.} =
let messageData = data.parseJson
self.messageList[messageData["chatId"].getStr].checkTimeout(messageData["id"].getStr)
proc resendMessage*(self: MessageView, chatId: string, messageId: string) {.slot.} =
self.status.messages.trackMessage(messageId, chatId)
self.status.chat.resendMessage(messageId)
self.messageList[chatId].resetTimeOut(messageId)
proc sendingMessage*(self: MessageView) {.signal.}
proc sendingMessageFailed*(self: MessageView) {.signal.}
proc messagePushed*(self: MessageView, messageIndex: int) {.signal.}
proc newMessagePushed*(self: MessageView) {.signal.}
proc messagesCleared*(self: MessageView) {.signal.}
proc clearMessages*(self: MessageView, id: string) =
let channel = self.channelView.getChannelById(id)
if (channel == nil):
return
self.messageList[id].clear(not channel.isNil and channel.chatType != ChatType.Profile)
self.messagesCleared()
proc upsertChannel*(self: MessageView, channel: string) =
var chat: Chat = nil
if self.status.chat.channels.hasKey(channel):
chat = self.status.chat.channels[channel]
else:
chat = self.communities.getChannel(channel)
if not self.messageList.hasKey(channel):
self.beginInsertRows(newQModelIndex(), self.messageList.len, self.messageList.len)
self.messageList[channel] = newChatMessageList(channel, self.status, not chat.isNil and chat.chatType != ChatType.Profile)
self.channelOpenTime[channel] = now().toTime.toUnix * 1000
self.endInsertRows();
if not self.pinnedMessagesList.hasKey(channel):
self.pinnedMessagesList[channel] = newChatMessageList(channel, self.status, false)
proc pushPinnedMessages*(self:MessageView, pinnedMessages: var seq[Message]) =
for msg in pinnedMessages.mitems:
self.upsertChannel(msg.chatId)
var message = self.messageList[msg.chatId].getMessageById(msg.id)
message.pinnedBy = msg.pinnedBy
message.isPinned = true
self.pinnedMessagesList[msg.chatId].add(message)
# put the message as pinned in the message list
self.messageList[msg.chatId].changeMessagePinned(msg.id, true, msg.pinnedBy)
proc isAddedContact*(self: MessageView, id: string): bool {.slot.} =
result = self.status.contacts.isAdded(id)
proc messageNotificationPushed*(self: MessageView, chatId: string, text: string, messageType: string, chatType: int, timestamp: string, identicon: string, username: string, hasMention: bool, isAddedContact: bool, channelName: string) {.signal.}
proc pushMessages*(self:MessageView, messages: var seq[Message]) =
for msg in messages.mitems:
self.upsertChannel(msg.chatId)
msg.userName = self.status.chat.getUserName(msg.fromAuthor, msg.alias)
var msgIndex:int;
if self.status.chat.channels.hasKey(msg.chatId):
let chat = self.status.chat.channels[msg.chatId]
if (chat.chatType == ChatType.Profile):
let timelineChatId = status_utils.getTimelineChatId()
self.messageList[timelineChatId].add(msg)
# if self.channelView.activeChannel.id == timelineChatId: self.activeChannelChanged()
if self.channelView.activeChannel.id == timelineChatId: self.channelView.activeChannelChanged()
msgIndex = self.messageList[timelineChatId].messages.len - 1
else:
self.messageList[msg.chatId].add(msg)
msgIndex = self.messageList[msg.chatId].messages.len - 1
self.messagePushed(msgIndex)
if self.channelOpenTime.getOrDefault(msg.chatId, high(int64)) < msg.timestamp.parseFloat.fromUnixFloat.toUnix:
var channel = self.channelView.chats.getChannelById(msg.chatId)
if (channel == nil):
channel = self.communities.getChannel(msg.chatId)
if (channel == nil):
continue
if msg.chatId == self.channelView.activeChannel.id:
discard self.status.chat.markMessagesSeen(msg.chatId, @[msg.id])
self.newMessagePushed()
if not channel.muted:
let isAddedContact = channel.chatType.isOneToOne and self.isAddedContact(channel.id)
self.messageNotificationPushed(msg.chatId, escape_html(msg.text), msg.messageType, channel.chatType.int, msg.timestamp, msg.identicon, msg.userName, msg.hasMention, isAddedContact, channel.name)
proc markMessageAsSent*(self:MessageView, chat: string, messageId: string) =
if self.messageList.contains(chat):
self.messageList[chat].markMessageAsSent(messageId)
else:
error "Message could not be marked as sent", chat, messageId
proc getMessageIndex(self: MessageView, chatId: string, messageId: string): int {.slot.} =
if (not self.messageList.hasKey(chatId)):
return -1
result = self.messageList[chatId].getMessageIndex(messageId)
proc getMessageData(self: MessageView, chatId: string, index: int, data: string): string {.slot.} =
if (not self.messageList.hasKey(chatId)):
return
return self.messageList[chatId].getMessageData(index, data)
proc getMessageList(self: MessageView): QVariant {.slot.} =
self.upsertChannel(self.channelView.activeChannel.id)
return newQVariant(self.messageList[self.channelView.activeChannel.id])
QtProperty[QVariant] messageList:
read = getMessageList
notify = activeChannelChanged
proc getPinnedMessagesList(self: MessageView): QVariant {.slot.} =
self.upsertChannel(self.channelView.activeChannel.id)
return newQVariant(self.pinnedMessagesList[self.channelView.activeChannel.id])
QtProperty[QVariant] pinnedMessagesList:
read = getPinnedMessagesList
notify = activeChannelChanged
proc messagesLoaded*(self: MessageView) {.signal.}
proc loadMoreMessages*(self: MessageView) {.slot.} =
trace "Loading more messages", chaId = self.channelView.activeChannel.id
self.status.chat.chatMessages(self.channelView.activeChannel.id, false)
self.status.chat.chatReactions(self.channelView.activeChannel.id, false)
self.messagesLoaded();
proc loadMoreMessagesWithIndex*(self: MessageView, channelIndex: int) {.slot.} =
if (self.channelView.chats.chats.len == 0): return
let selectedChannel = self.channelView.getChannel(channelIndex)
if (selectedChannel == nil): return
trace "Loading more messages", chaId = selectedChannel.id
self.status.chat.chatMessages(selectedChannel.id, false)
self.status.chat.chatReactions(selectedChannel.id, false)
self.messagesLoaded();
proc loadingMessagesChanged*(self: MessageView, value: bool) {.signal.}
proc asyncMessageLoad*(self: MessageView, chatId: string) {.slot.} =
self.asyncMessageLoad("asyncMessageLoaded", chatId)
proc asyncMessageLoaded*(self: MessageView, rpcResponse: string) {.slot.} =
let
rpcResponseObj = rpcResponse.parseJson
chatId = rpcResponseObj{"chatId"}.getStr
if chatId == "": # .getStr() returns "" when field is not found
return
let messages = rpcResponseObj{"messages"}
if(messages != nil and messages.kind != JNull):
let chatMessages = libstatus_chat.parseChatMessagesResponse(messages)
self.status.chat.chatMessages(chatId, true, chatMessages[0], chatMessages[1])
let rxns = rpcResponseObj{"reactions"}
if(rxns != nil and rxns.kind != JNull):
let reactions = status_chat.parseReactionsResponse(chatId, rxns)
self.status.chat.chatReactions(chatId, true, reactions[0], reactions[1])
let pinnedMsgs = rpcResponseObj{"pinnedMessages"}
if(pinnedMsgs != nil and pinnedMsgs.kind != JNull):
let pinnedMessages = libstatus_chat.parseChatMessagesResponse(pinnedMsgs)
self.status.chat.pinnedMessagesByChatID(chatId, pinnedMessages[0], pinnedMessages[1])
proc hideLoadingIndicator*(self: MessageView) {.slot.} =
self.loadingMessages = false
self.loadingMessagesChanged(false)
proc setLoadingMessages*(self: MessageView, value: bool) {.slot.} =
self.loadingMessages = value
self.loadingMessagesChanged(value)
proc isLoadingMessages(self: MessageView): QVariant {.slot.} =
return newQVariant(self.loadingMessages)
QtProperty[QVariant] loadingMessages:
read = isLoadingMessages
write = setLoadingMessages
notify = loadingMessagesChanged
proc fillGaps*(self: MessageView, messageId: string) {.slot.} =
self.loadingMessages = true
self.loadingMessagesChanged(true)
discard self.status.mailservers.fillGaps(self.channelView.activeChannel.id, @[messageId])
proc unreadMessages*(self: MessageView): int {.slot.} =
result = self.unreadMessageCnt
proc unreadMessagesCntChanged*(self: MessageView) {.signal.}
QtProperty[int] unreadMessagesCount:
read = unreadMessages
notify = unreadMessagesCntChanged
proc calculateUnreadMessages*(self: MessageView) =
var unreadTotal = 0
for chatItem in self.channelView.chats.chats:
unreadTotal = unreadTotal + chatItem.unviewedMessagesCount
if unreadTotal != self.unreadMessageCnt:
self.unreadMessageCnt = unreadTotal
self.unreadMessagesCntChanged()
proc deleteMessage*(self: MessageView, channelId: string, messageId: string) =
self.messageList[channelId].deleteMessage(messageId)
proc removeMessagesByUserId(self: MessageView, publicKey: string) {.slot.} =
for k in self.messageList.keys:
self.messageList[k].removeMessagesByUserId(publicKey)
proc getMessageListIndex(self: MessageView): int {.slot.} =
var idx = -1
for msg in toSeq(self.messageList.values):
idx = idx + 1
if(self.channelView.activeChannel.id == msg.id): return idx
return idx
proc getMessageListIndexById*(self: MessageView, id: string): int {.slot.} =
var idx = -1
for msg in toSeq(self.messageList.values):
idx = idx + 1
if(id == msg.id): return idx
return idx
proc addPinMessage*(self: MessageView, messageId: string, chatId: string, pinnedBy: string) =
self.upsertChannel(chatId)
self.messageList[chatId].changeMessagePinned(messageId, true, pinnedBy)
var message = self.messageList[chatId].getMessageById(messageId)
message.pinnedBy = pinnedBy
self.pinnedMessagesList[chatId].add(message)
proc removePinMessage*(self: MessageView, messageId: string, chatId: string) =
self.upsertChannel(chatId)
self.messageList[chatId].changeMessagePinned(messageId, false, "")
try:
self.pinnedMessagesList[chatId].remove(messageId)
except Exception as e:
error "Error removing ", msg = e.msg
proc pinMessage*(self: MessageView, messageId: string, chatId: string) {.slot.} =
self.status.chat.setPinMessage(messageId, chatId, true)
self.addPinMessage(messageId, chatId, self.pubKey)
proc unPinMessage*(self: MessageView, messageId: string, chatId: string) {.slot.} =
self.status.chat.setPinMessage(messageId, chatId, false)
self.removePinMessage(messageId, chatId)
proc addPinnedMessages*(self: MessageView, pinnedMessages: seq[Message]) =
for pinnedMessage in pinnedMessages:
if (pinnedMessage.isPinned):
self.addPinMessage(pinnedMessage.id, pinnedMessage.localChatId, pinnedMessage.pinnedBy)
else:
self.removePinMessage(pinnedMessage.id, pinnedMessage.localChatId)
method rowCount*(self: MessageView, index: QModelIndex = nil): int =
result = self.messageList.len
method data(self: MessageView, index: QModelIndex, role: int): QVariant =
if not index.isValid:
return
if index.row < 0 or index.row >= self.messageList.len:
return
return newQVariant(toSeq(self.messageList.values)[index.row])
method roleNames(self: MessageView): Table[int, string] =
{
ChatViewRoles.MessageList.int:"messages"
}.toTable

View File

@ -90,14 +90,14 @@ StackLayout {
property var suggestionsObj: ([])
function addSuggestionFromMessageList(i){
const contactAddr = chatsModel.messageList.getMessageData(i, "publicKey");
const contactAddr = chatsModel.messageView.messageList.getMessageData(i, "publicKey");
if(idMap[contactAddr]) return;
suggestionsObj.push({
alias: chatsModel.messageList.getMessageData(i, "alias"),
ensName: chatsModel.messageList.getMessageData(i, "ensName"),
alias: chatsModel.messageView.messageList.getMessageData(i, "alias"),
ensName: chatsModel.messageView.messageList.getMessageData(i, "ensName"),
address: contactAddr,
identicon: chatsModel.messageList.getMessageData(i, "identicon"),
localNickname: chatsModel.messageList.getMessageData(i, "localName")
identicon: chatsModel.messageView.messageList.getMessageData(i, "identicon"),
localNickname: chatsModel.messageView.messageList.getMessageData(i, "localName")
})
chatInput.suggestionsList.append(suggestionsObj[suggestionsObj.length - 1]);
idMap[contactAddr] = true;
@ -123,7 +123,7 @@ StackLayout {
chatInput.suggestionsList.append(suggestionsObj[suggestionsObj.length - 1]);
idMap[contactAddr] = true;
}
const len2 = chatsModel.messageList.rowCount();
const len2 = chatsModel.messageView.messageList.rowCount();
for (let f = 0; f < len2; f++) {
addSuggestionFromMessageList(f);
}
@ -132,12 +132,12 @@ StackLayout {
function showReplyArea() {
isReply = true;
isImage = false;
let replyMessageIndex = chatsModel.messageList.getMessageIndex(SelectedMessage.messageId);
let replyMessageIndex = chatsModel.messageView.messageList.getMessageIndex(SelectedMessage.messageId);
if (replyMessageIndex === -1) return;
let userName = chatsModel.messageList.getMessageData(replyMessageIndex, "userName")
let message = chatsModel.messageList.getMessageData(replyMessageIndex, "message")
let identicon = chatsModel.messageList.getMessageData(replyMessageIndex, "identicon")
let userName = chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "userName")
let message = chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "message")
let identicon = chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "identicon")
chatInput.showReplyArea(userName, message, identicon)
}
@ -165,7 +165,7 @@ StackLayout {
isBlocked = profileModel.contacts.isContactBlocked(activeChatId);
}
onContactBlocked: {
chatsModel.removeMessagesByUserId(publicKey)
chatsModel.messageView.removeMessagesByUserId(publicKey)
}
}
@ -260,7 +260,7 @@ StackLayout {
Layout.fillHeight: true
clip: true
Repeater {
model: chatsModel
model: chatsModel.messageView
Loader {
active: false
sourceComponent: ChatMessages {
@ -273,7 +273,7 @@ StackLayout {
Connections {
target: chatsModel.channelView
onActiveChannelChanged: {
stackLayoutChatMessages.currentIndex = chatsModel.getMessageListIndex(chatsModel.channelView.activeChannelIndex)
stackLayoutChatMessages.currentIndex = chatsModel.messageView.getMessageListIndex(chatsModel.channelView.activeChannelIndex)
if(stackLayoutChatMessages.currentIndex > -1 && !stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].active){
stackLayoutChatMessages.children[stackLayoutChatMessages.currentIndex].active = true;
}
@ -295,7 +295,7 @@ StackLayout {
}
Connections {
target: chatsModel
target: chatsModel.messageView
onMessagePushed: {
addSuggestionFromMessageList(messageIndex);
}
@ -321,9 +321,9 @@ StackLayout {
Layout.preferredWidth: parent.width
height: chatInput.height
Layout.preferredHeight: height
Connections {
target: chatsModel
target: chatsModel.messageView
onLoadingMessagesChanged:
if(value){
loadingMessagesIndicator.active = true
@ -336,7 +336,7 @@ StackLayout {
Loader {
id: loadingMessagesIndicator
active: chatsModel.loadingMessages
active: chatsModel.messageView.loadingMessages
sourceComponent: loadingIndicator
anchors.right: parent.right
anchors.bottom: chatInput.top
@ -396,7 +396,7 @@ StackLayout {
let msg = chatsModel.plainText(Emoji.deparse(chatInput.textInput.text))
if (msg.length > 0){
msg = chatInput.interpretMessage(msg)
chatsModel.sendMessage(msg, chatInput.isReply ? SelectedMessage.messageId : "", Utils.isOnlyEmoji(msg) ? Constants.emojiType : Constants.messageType, false, JSON.stringify(suggestionsObj));
chatsModel.messageView.sendMessage(msg, chatInput.isReply ? SelectedMessage.messageId : "", Utils.isOnlyEmoji(msg) ? Constants.emojiType : Constants.messageType, false, JSON.stringify(suggestionsObj));
if(event) event.accepted = true
sendMessageSound.stop();
Qt.callLater(sendMessageSound.play);

View File

@ -48,7 +48,7 @@ Rectangle {
Item {
property int replyMessageIndex: chatsModel.getMessageIndex(chatId, responseTo)
property string repliedMessageContent: replyMessageIndex > -1 ? chatsModel.getMessageData(chatId, replyMessageIndex, "message") : "";
property string repliedMessageContent: replyMessageIndex > -1 ? chatsModel.messageView.getMessageData(chatId, replyMessageIndex, "message") : "";
onReplyMessageIndexChanged: {

View File

@ -11,7 +11,7 @@ Item {
height: chatInput.height
Connections {
target: chatsModel
target: chatsModel.messageView
onLoadingMessagesChanged:
if(value){
loadingMessagesIndicator.active = true
@ -24,7 +24,7 @@ Item {
Loader {
id: loadingMessagesIndicator
active: chatsModel.loadingMessages
active: chatsModel.messageView.loadingMessages
sourceComponent: loadingIndicator
anchors.right: parent.right
anchors.bottom: chatInput.top
@ -81,7 +81,7 @@ Item {
let msg = chatsModel.plainText(Emoji.deparse(chatInput.textInput.text))
if (msg.length > 0){
msg = chatInput.interpretMessage(msg)
chatsModel.sendMessage(msg, chatInput.isReply ? SelectedMessage.messageId : "", Utils.isOnlyEmoji(msg) ? Constants.emojiType : Constants.messageType, false, JSON.stringify(suggestionsObj));
chatsModel.messageView.sendMessage(msg, chatInput.isReply ? SelectedMessage.messageId : "", Utils.isOnlyEmoji(msg) ? Constants.emojiType : Constants.messageType, false, JSON.stringify(suggestionsObj));
if(event) event.accepted = true
sendMessageSound.stop();
Qt.callLater(sendMessageSound.play);

View File

@ -170,7 +170,7 @@ ScrollView {
}
Connections {
target: chatsModel
target: chatsModel.messageView
onMessagesLoaded: {
loadingMessages = false;
}
@ -266,7 +266,7 @@ ScrollView {
property var loadMsgs : Backpressure.oneInTime(chatLogView, 500, function() {
if(loadingMessages) return;
loadingMessages = true;
chatsModel.loadMoreMessages();
chatsModel.messageView.loadMoreMessages();
});
onContentYChanged: {

View File

@ -83,14 +83,14 @@ Item {
property bool isExpired: (outgoingStatus === "sending" && (Math.floor(timestamp) + 180000) < Date.now())
property bool isStatusUpdate: false
property int replyMessageIndex: chatsModel.messageList.getMessageIndex(responseTo);
property string repliedMessageAuthor: replyMessageIndex > -1 ? chatsModel.messageList.getMessageData(replyMessageIndex, "userName") : "";
property string repliedMessageAuthorPubkey: replyMessageIndex > -1 ? chatsModel.messageList.getMessageData(replyMessageIndex, "publicKey") : "";
property int replyMessageIndex: chatsModel.messageView.messageList.getMessageIndex(responseTo);
property string repliedMessageAuthor: replyMessageIndex > -1 ? chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "userName") : "";
property string repliedMessageAuthorPubkey: replyMessageIndex > -1 ? chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "publicKey") : "";
property bool repliedMessageAuthorIsCurrentUser: replyMessageIndex > -1 ? repliedMessageAuthorPubkey === profileModel.profile.pubKey : "";
property string repliedMessageContent: replyMessageIndex > -1 ? chatsModel.messageList.getMessageData(replyMessageIndex, "message") : "";
property int repliedMessageType: replyMessageIndex > -1 ? parseInt(chatsModel.messageList.getMessageData(replyMessageIndex, "contentType")) : 0;
property string repliedMessageImage: replyMessageIndex > -1 ? chatsModel.messageList.getMessageData(replyMessageIndex, "image") : "";
property string repliedMessageUserIdenticon: replyMessageIndex > -1 ? chatsModel.messageList.getMessageData(replyMessageIndex, "identicon") : "";
property string repliedMessageContent: replyMessageIndex > -1 ? chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "message") : "";
property int repliedMessageType: replyMessageIndex > -1 ? parseInt(chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "contentType")) : 0;
property string repliedMessageImage: replyMessageIndex > -1 ? chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "image") : "";
property string repliedMessageUserIdenticon: replyMessageIndex > -1 ? chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "identicon") : "";
property string repliedMessageUserImage: replyMessageIndex > -1 ? appMain.getProfileImage(repliedMessageAuthorPubkey, repliedMessageAuthorIsCurrentUser , false) || "" : "";
property var imageClick: function () {}
@ -256,7 +256,7 @@ Item {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
chatsModel.fillGaps(messageId)
chatsModel.messageView.fillGaps(messageId)
root.visible = false;
root.height = 0;
}
@ -323,7 +323,7 @@ Item {
fetchMoreButton.visible = false;
fetchDate.visible = false;
timer.setTimeout(function(){
chatsModel.hideLoadingIndicator();
chatsModel.messageView.hideLoadingIndicator();
fetchLoaderIndicator.active = false;
fetchMoreButton.visible = true;
fetchDate.visible = true;

View File

@ -128,7 +128,7 @@ Loader {
id: stickerId
imageHeight: 56
imageWidth: 56
stickerData: chatsModel.messageList.getMessageData(replyMessageIndex, "sticker")
stickerData: chatsModel.messageView.messageList.getMessageData(replyMessageIndex, "sticker")
contentType: repliedMessageType
container: root.container
}

View File

@ -14,7 +14,7 @@ StyledText {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: {
chatsModel.resendMessage(chatId, messageId)
chatsModel.messageView.resendMessage(chatId, messageId)
}
}
}

View File

@ -52,7 +52,7 @@ StatusIconTabButton {
height: 22
Text {
id: messageCount
font.pixelSize: chatsModel.unreadMessagesCount > 99 ? 10 : 12
font.pixelSize: chatsModel.messageView.unreadMessagesCount > 99 ? 10 : 12
color: Style.current.white
anchors.centerIn: parent
text: unviewedMessagesCount > 99 ? "99+" : unviewedMessagesCount

View File

@ -195,7 +195,7 @@ ModalPopup {
StyledText {
id: nbPinMessagesText
text: chatsModel.pinnedMessagesList.count
text: chatsModel.messageView.pinnedMessagesList.count
anchors.verticalCenter: parent.verticalCenter
padding: 0
font.pixelSize: 15

View File

@ -106,7 +106,7 @@ Item {
Connections {
target: chatsModel.channelView
onActiveChannelChanged: {
chatsModel.hideLoadingIndicator()
chatsModel.messageView.hideLoadingIndicator()
chatGroupsListView.currentIndex = chatsModel.channelView.activeChannelIndex
SelectedMessage.reset();
chatColumn.isReply = false;

View File

@ -17,7 +17,7 @@ PopupMenu {
onTriggered: {
chatsModel.requestMoreMessages(Constants.fetchRangeLast24Hours)
timer.setTimeout(function(){
chatsModel.hideLoadingIndicator()
chatsModel.messageView.hideLoadingIndicator()
}, 3000);
}
}
@ -28,7 +28,7 @@ PopupMenu {
onTriggered: {
chatsModel.requestMoreMessages(Constants.fetchRangeLast2Days)
timer.setTimeout(function(){
chatsModel.hideLoadingIndicator()
chatsModel.messageView.hideLoadingIndicator()
}, 4000);
}
}
@ -39,7 +39,7 @@ PopupMenu {
onTriggered: {
chatsModel.requestMoreMessages(Constants.fetchRangeLast3Days)
timer.setTimeout(function(){
chatsModel.hideLoadingIndicator()
chatsModel.messageView.hideLoadingIndicator()
}, 5000);
}
}
@ -50,7 +50,7 @@ PopupMenu {
onTriggered: {
chatsModel.requestMoreMessages(Constants.fetchRangeLast7Days)
timer.setTimeout(function(){
chatsModel.hideLoadingIndicator()
chatsModel.messageView.hideLoadingIndicator()
}, 7000);
}
}

View File

@ -212,7 +212,7 @@ ModalPopup {
}
StatusSettingsLineButton {
property int pinnedCount: chatsModel.pinnedMessagesList.count
property int pinnedCount: chatsModel.messageView.pinnedMessagesList.count
id: pinnedMessagesBtn
visible: pinnedCount > 0

View File

@ -143,11 +143,11 @@ PopupMenu {
qsTr("Pin")
onTriggered: {
if (pinnedMessage) {
chatsModel.unPinMessage(messageId, chatsModel.channelView.activeChannel.id)
chatsModel.messageView.unPinMessage(messageId, chatsModel.channelView.activeChannel.id)
return
}
chatsModel.pinMessage(messageId, chatsModel.channelView.activeChannel.id)
chatsModel.messageView.pinMessage(messageId, chatsModel.channelView.activeChannel.id)
messageContextMenu.close()
}
icon.source: "../../../img/pin"

View File

@ -55,7 +55,7 @@ ModalPopup {
ListView {
id: pinnedMessageListView
model: chatsModel.pinnedMessagesList
model: chatsModel.messageView.pinnedMessagesList
height: parent.height
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding

View File

@ -83,7 +83,7 @@ ScrollView {
var msg = chatsModel.plainText(Emoji.deparse(statusUpdateInput.textInput.text))
if (msg.length > 0){
msg = statusUpdateInput.interpretMessage(msg)
chatsModel.sendMessage(msg, "", Utils.isOnlyEmoji(msg) ? Constants.emojiType : Constants.messageType, true, "");
chatsModel.messageView.sendMessage(msg, "", Utils.isOnlyEmoji(msg) ? Constants.emojiType : Constants.messageType, true, "");
statusUpdateInput.textInput.text = "";
if(event) event.accepted = true
sendMessageSound.stop()
@ -97,7 +97,7 @@ ScrollView {
anchors.top: statusUpdateInput.bottom
anchors.topMargin: 40
anchors.horizontalCenter: parent.horizontalCenter
visible: chatsModel.messageList.rowCount() === 0
visible: chatsModel.messageView.messageList.rowCount() === 0
}
ListView {

View File

@ -444,7 +444,7 @@ RowLayout {
checked: !chatsModel.communities.activeCommunity.active && sLayout.currentIndex === Utils.getAppSectionIndex(Constants.chat)
Rectangle {
property int badgeCount: chatsModel.unreadMessagesCount + profileModel.contacts.contactRequests.count
property int badgeCount: chatsModel.messageView.unreadMessagesCount + profileModel.contacts.contactRequests.count
id: chatBadge
visible: chatBadge.badgeCount > 0
@ -540,7 +540,7 @@ RowLayout {
Layout.fillHeight: true
// Loaders do not have access to the context, so props need to be set
// Adding a "_" to avoid a binding loop
property var _chatsModel: chatsModel
property var _chatsModel: chatsModel.messageView
property var _walletModel: walletModel
property var _utilsModel: utilsModel
property var _web3Provider: web3Provider

View File

@ -20,7 +20,7 @@ Item {
property string address: ""
property bool resultClickable: true
property bool isAddedContact: pubKey != "" ? chatsModel.isAddedContact(pubKey) : false
property bool isAddedContact: pubKey != "" ? chatsModel.messageView.isAddedContact(pubKey) : false
signal resultClicked(string pubKey)
signal addToContactsButtonClicked(string pubKey)

View File

@ -151,7 +151,7 @@ Item {
property bool hovered: false
id: pinnedMessagesGroup
visible: chatType !== Constants.chatTypePublic && chatsModel.pinnedMessagesList.count > 0
visible: chatType !== Constants.chatTypePublic && chatsModel.messageView.pinnedMessagesList.count > 0
width: childrenRect.width
height: vertiSep.height
anchors.left: chatInfo.right
@ -184,7 +184,7 @@ Item {
StyledText {
id: nbPinnedMessagesText
color: pinnedMessagesGroup.hovered ? Style.current.textColor : Style.current.secondaryText
text: chatsModel.pinnedMessagesList.count
text: chatsModel.messageView.pinnedMessagesList.count
font.pixelSize: 12
font.underline: pinnedMessagesGroup.hovered
anchors.left: pinImg.right