diff --git a/src/app/chat/view.nim b/src/app/chat/view.nim index 9c9773105e..1a8c95503d 100644 --- a/src/app/chat/view.nim +++ b/src/app/chat/view.nim @@ -3,9 +3,9 @@ import Tables import json import chronicles -import ../../signals/types -import ../../status/chat import ../../status/status +import ../../status/chat as status_chat +import ../../status/chat/[chat, message] import views/channels_list import views/message_list @@ -84,7 +84,7 @@ QtObject: proc messagePushed*(self: ChatsView) {.signal.} - proc pushMessage*(self:ChatsView, message: ChatMessage) = + proc pushMessage*(self:ChatsView, message: Message) = self.upsertChannel(message.chatId) self.messageList[message.chatId].add(message) self.messagePushed() @@ -92,7 +92,7 @@ QtObject: proc pushMessages*(self:ChatsView, messages: seq[Message]) = for msg in messages: self.upsertChannel(msg.chatId) - self.messageList[msg.chatId].add(msg.toChatMessage()) + self.messageList[msg.chatId].add(msg) self.messagePushed() proc getMessageList(self: ChatsView): QVariant {.slot.} = diff --git a/src/app/chat/views/channels_list.nim b/src/app/chat/views/channels_list.nim index ced0504c0e..536fea303d 100644 --- a/src/app/chat/views/channels_list.nim +++ b/src/app/chat/views/channels_list.nim @@ -1,6 +1,5 @@ import NimQml, Tables -import ../../../status/chat -import ../../../signals/types +import ../../../status/chat/[chat, message] type ChannelsRoles {.pure.} = enum diff --git a/src/app/chat/views/chat_item.nim b/src/app/chat/views/chat_item.nim index 37e9bb7598..6653c557d7 100644 --- a/src/app/chat/views/chat_item.nim +++ b/src/app/chat/views/chat_item.nim @@ -1,7 +1,6 @@ import NimQml import std/wrapnils -import ../../../status/chat -import ../../../signals/types +import ../../../status/chat/chat QtObject: type ChatItemView* = ref object of QObject diff --git a/src/app/chat/views/message_list.nim b/src/app/chat/views/message_list.nim index c3c18ade21..96d67efe76 100644 --- a/src/app/chat/views/message_list.nim +++ b/src/app/chat/views/message_list.nim @@ -1,6 +1,6 @@ import NimQml, Tables import ../../../status/chat -import ../../../signals/types +import ../../../status/chat/[message,stickers] type ChatMessageRoles {.pure.} = enum @@ -19,19 +19,17 @@ type QtObject: type ChatMessageList* = ref object of QAbstractListModel - messages*: seq[ChatMessage] + messages*: seq[Message] proc delete(self: ChatMessageList) = self.QAbstractListModel.delete - for message in self.messages: - message.delete self.messages = @[] proc setup(self: ChatMessageList) = self.QAbstractListModel.setup - proc chatIdentifier(self: ChatMessageList, chatId:string): ChatMessage = - result = newChatMessage(); + proc chatIdentifier(self: ChatMessageList, chatId:string): Message = + result = Message() result.contentType = ContentType.ChatIdentifier; result.chatId = chatId @@ -44,7 +42,7 @@ QtObject: method rowCount(self: ChatMessageList, index: QModelIndex = nil): int = return self.messages.len - proc sectionIdentifier(message: ChatMessage): string = + proc sectionIdentifier(message: Message): string = result = message.fromAuthor # Force section change, because group status messages are sent with the # same fromAuthor, and ends up causing the header to not be shown @@ -59,14 +57,14 @@ QtObject: let message = self.messages[index.row] let chatMessageRole = role.ChatMessageRoles case chatMessageRole: - of ChatMessageRoles.UserName: result = newQVariant(message.userName) - of ChatMessageRoles.Message: result = newQVariant(message.message) + of ChatMessageRoles.UserName: result = newQVariant(message.alias) + of ChatMessageRoles.Message: result = newQVariant(message.text) of ChatMessageRoles.Timestamp: result = newQVariant(message.timestamp) of ChatMessageRoles.Clock: result = newQVariant($message.clock) of ChatMessageRoles.Identicon: result = newQVariant(message.identicon) of ChatMessageRoles.IsCurrentUser: result = newQVariant(message.isCurrentUser) of ChatMessageRoles.ContentType: result = newQVariant(message.contentType.int) - of ChatMessageRoles.Sticker: result = newQVariant(message.sticker) + of ChatMessageRoles.Sticker: result = newQVariant(message.stickerHash.decodeContentHash()) of ChatMessageRoles.FromAuthor: result = newQVariant(message.fromAuthor) of ChatMessageRoles.ChatId: result = newQVariant(message.chatId) of ChatMessageRoles.SectionIdentifier: result = newQVariant(sectionIdentifier(message)) @@ -87,12 +85,12 @@ QtObject: ChatMessageRoles.SectionIdentifier.int: "sectionIdentifier" }.toTable - proc add*(self: ChatMessageList, message: ChatMessage) = + proc add*(self: ChatMessageList, message: Message) = self.beginInsertRows(newQModelIndex(), self.messages.len, self.messages.len) self.messages.add(message) self.endInsertRows() - proc add*(self: ChatMessageList, messages: seq[ChatMessage]) = + proc add*(self: ChatMessageList, messages: seq[Message]) = self.beginInsertRows(newQModelIndex(), self.messages.len, self.messages.len) for message in messages: self.messages.add(message) diff --git a/src/signals/messages.nim b/src/signals/messages.nim index 437a0aa666..1e63bb5b7b 100644 --- a/src/signals/messages.nim +++ b/src/signals/messages.nim @@ -1,6 +1,7 @@ import json import types import ../status/libstatus/accounts as status_accounts +import ../status/chat/[chat, message] import random proc toMessage*(jsonMsg: JsonNode): Message diff --git a/src/signals/types.nim b/src/signals/types.nim index 1a4bdd46ee..8f393a4800 100644 --- a/src/signals/types.nim +++ b/src/signals/types.nim @@ -1,6 +1,7 @@ import json import chronicles import ../status/libstatus/types +import ../status/chat/[chat, message] import json_serialization type SignalSubscriber* = ref object of RootObj @@ -17,74 +18,10 @@ type NodeSignal* = ref object of Signal type WalletSignal* = ref object of Signal content*: string -type ContentType* {.pure.} = enum - ChatIdentifier = -1, - Unknown = 0, - Message = 1, - Sticker = 2, - Status = 3, - Emoji = 4, - Transaction = 5, - Group = 6 - -type Message* = object - alias*: string - chatId*: string - clock*: int - # commandParameters*: # ??? - contentType*: ContentType # ??? - ensName*: string # ??? - fromAuthor*: string - id*: string - identicon*: string - lineCount*: int - localChatId*: string - messageType*: string # ??? - # parsedText: # ??? - # quotedMessage: # ??? - replace*: string # ??? - responseTo*: string # ??? - rtl*: bool # ??? - seen*: bool - # sticker: # ??? - text*: string - timestamp*: string - whisperTimestamp*: string - isCurrentUser*: bool - stickerHash*: string - # Override this method method onSignal*(self: SignalSubscriber, data: Signal) {.base.} = error "onSignal must be overriden in controller. Signal is unhandled" -type ChatType* {.pure.}= enum - Unknown = 0, - OneToOne = 1, - Public = 2, - PrivateGroupChat = 3 - -proc isOneToOne*(self: ChatType): bool = self == ChatType.OneToOne - -type ChatMember* = object - admin*: bool - id*: string - joined*: bool - -type Chat* = ref object - id*: string # ID is the id of the chat, for public chats it is the name e.g. status, for one-to-one is the hex encoded public key and for group chats is a random uuid appended with the hex encoded pk of the creator of the chat - name*: string - color*: string - identicon*: string - active*: bool # indicates whether the chat has been soft deleted - chatType*: ChatType - timestamp*: int64 # indicates the last time this chat has received/sent a message - lastClockValue*: int64 # indicates the last clock value to be used when sending messages - deletedAtClockValue*: int64 # indicates the clock value at time of deletion, messages with lower clock value of this should be discarded - unviewedMessagesCount*: int - lastMessage*: Message - members*: seq[ChatMember] - # membershipUpdateEvents # ? - type MessageSignal* = ref object of Signal messages*: seq[Message] chats*: seq[Chat] @@ -102,18 +39,3 @@ type WhisperFilterSignal* = ref object of Signal type DiscoverySummarySignal* = ref object of Signal enodes*: seq[string] - -proc findIndexById*(self: seq[Chat], id: string): int = - result = -1 - var idx = -1 - for item in self: - inc idx - if(item.id == id): - result = idx - break - -proc isMember*(self: Chat, pubKey: string): bool = - for member in self.members: - if member.id == pubKey and member.joined: return true - return false - diff --git a/src/status/chat.nim b/src/status/chat.nim index 302e8c43ef..08571add36 100644 --- a/src/status/chat.nim +++ b/src/status/chat.nim @@ -2,14 +2,10 @@ import eventemitter, json import sequtils import libstatus/chat as status_chat import chronicles -import ../signals/types +import chat/[chat, message] import ../signals/messages -import chat/chat_message import tables -export chat_message -export Chat - type PushMessageArgs* = ref object of Args chats*: seq[Chat] diff --git a/src/status/chat/chat.nim b/src/status/chat/chat.nim new file mode 100644 index 0000000000..15521b21c2 --- /dev/null +++ b/src/status/chat/chat.nim @@ -0,0 +1,44 @@ +import message + +type ChatType* {.pure.}= enum + Unknown = 0, + OneToOne = 1, + Public = 2, + PrivateGroupChat = 3 + +proc isOneToOne*(self: ChatType): bool = self == ChatType.OneToOne + +type ChatMember* = object + admin*: bool + id*: string + joined*: bool + +type Chat* = ref object + id*: string # ID is the id of the chat, for public chats it is the name e.g. status, for one-to-one is the hex encoded public key and for group chats is a random uuid appended with the hex encoded pk of the creator of the chat + name*: string + color*: string + identicon*: string + active*: bool # indicates whether the chat has been soft deleted + chatType*: ChatType + timestamp*: int64 # indicates the last time this chat has received/sent a message + lastClockValue*: int64 # indicates the last clock value to be used when sending messages + deletedAtClockValue*: int64 # indicates the clock value at time of deletion, messages with lower clock value of this should be discarded + unviewedMessagesCount*: int + lastMessage*: Message + members*: seq[ChatMember] + # membershipUpdateEvents # ? + +proc findIndexById*(self: seq[Chat], id: string): int = + result = -1 + var idx = -1 + for item in self: + inc idx + if(item.id == id): + result = idx + break + +proc isMember*(self: Chat, pubKey: string): bool = + for member in self.members: + if member.id == pubKey and member.joined: return true + return false + diff --git a/src/status/chat/chat_message.nim b/src/status/chat/chat_message.nim deleted file mode 100644 index 746e270f70..0000000000 --- a/src/status/chat/chat_message.nim +++ /dev/null @@ -1,59 +0,0 @@ -import json -import ../../signals/types -import stickers - -type ChatMessage* = ref object - userName*: string - message*: string - fromAuthor*: string - timestamp*: string - clock*: int - identicon*: string - isCurrentUser*: bool - contentType*: ContentType - sticker*: string - chatId*: string - -proc delete*(self: ChatMessage) = - discard - -proc newChatMessage*(): ChatMessage = - result = ChatMessage() - result.userName = "" - result.message = "" - result.fromAuthor = "" - result.clock = 0 - result.timestamp = "0" - result.identicon = "" - result.isCurrentUser = false - result.contentType = ContentType.Unknown - result.sticker = "" - result.chatId = "" - -proc toChatMessage*(payload: JsonNode): ChatMessage = - result = ChatMessage( - chatId: payload["localChatId"].str, - fromAuthor: payload["from"].getStr, - userName: payload["alias"].str, - message: payload["text"].str, - timestamp: $payload["timestamp"], - clock: payload["clock"].getInt, - identicon: payload["identicon"].str, - isCurrentUser: payload{"outgoingStatus"}.getStr == "sending", - contentType: ContentType(payload["contentType"].getInt), - sticker: "" # TODO: implement when implementing stickers from user - ) - -proc toChatMessage*(message: Message): ChatMessage = - result = ChatMessage( - chatId: message.chatId, - userName: message.alias, - clock: message.clock, - fromAuthor: message.fromAuthor, - message: message.text, - timestamp: message.timestamp, - identicon: message.identicon, - isCurrentUser: message.isCurrentUser, - contentType: message.contentType, - sticker: message.stickerHash.decodeContentHash() - ) diff --git a/src/status/chat/message.nim b/src/status/chat/message.nim new file mode 100644 index 0000000000..77dd2abf33 --- /dev/null +++ b/src/status/chat/message.nim @@ -0,0 +1,35 @@ +type ContentType* {.pure.} = enum + ChatIdentifier = -1, + Unknown = 0, + Message = 1, + Sticker = 2, + Status = 3, + Emoji = 4, + Transaction = 5, + Group = 6 + +type Message* = object + alias*: string + chatId*: string + clock*: int + # commandParameters*: # ??? + contentType*: ContentType # ??? + ensName*: string # ??? + fromAuthor*: string + id*: string + identicon*: string + lineCount*: int + localChatId*: string + messageType*: string # ??? + # parsedText: # ??? + # quotedMessage: # ??? + replace*: string # ??? + responseTo*: string # ??? + rtl*: bool # ??? + seen*: bool + sticker*: string + text*: string + timestamp*: string + whisperTimestamp*: string + isCurrentUser*: bool + stickerHash*: string \ No newline at end of file diff --git a/src/status/libstatus/chat.nim b/src/status/libstatus/chat.nim index 967135713f..2f2cdb0ee1 100644 --- a/src/status/libstatus/chat.nim +++ b/src/status/libstatus/chat.nim @@ -4,7 +4,7 @@ import utils import times import strutils import chronicles -import ../../signals/types +import ../chat/[chat, message] import ../../signals/messages proc buildFilter*(chatId: string, filterId: string = "", symKeyId: string = "", oneToOne: bool = false, identity: string = "", topic: string = "", discovery: bool = false, negotiated: bool = false, listen: bool = true):JsonNode =