feat: show last message and unread message count
This commit is contained in:
parent
ac5c6389d3
commit
2eee8c7a2d
|
@ -0,0 +1,18 @@
|
|||
type ChatItem* = ref object
|
||||
name*: string
|
||||
lastMessage*: string
|
||||
timestamp*: int64
|
||||
unviewedMessagesCount*: int
|
||||
|
||||
proc newChatItem*(): ChatItem =
|
||||
new(result)
|
||||
result.name = ""
|
||||
result.lastMessage = ""
|
||||
result.timestamp = 0
|
||||
result.unviewedMessagesCount = 0
|
||||
|
||||
proc findByName*(self: seq[ChatItem], name: string): int =
|
||||
result = -1
|
||||
for item in self:
|
||||
inc result
|
||||
if(item.name == name): break
|
|
@ -2,9 +2,10 @@ import NimQml
|
|||
import json, eventemitter
|
||||
import ../../status/chat as status_chat
|
||||
import view
|
||||
import chatItem
|
||||
import messages
|
||||
import ../signals/types
|
||||
import ../../models/chat
|
||||
import ../../models/chat as chat_model
|
||||
|
||||
type ChatController* = ref object of SignalSubscriber
|
||||
view*: ChatsView
|
||||
|
@ -40,9 +41,18 @@ proc load*(self: ChatController, chatId: string) =
|
|||
discard self.view.joinChat(chatId)
|
||||
self.view.setActiveChannelByIndex(0)
|
||||
|
||||
proc onSignal(self: ChatController, data: Signal) =
|
||||
var chatSignal = cast[ChatSignal](data)
|
||||
for message in chatSignal.messages:
|
||||
method onSignal(self: ChatController, data: Signal) =
|
||||
var messageSignal = cast[MessageSignal](data)
|
||||
|
||||
for c in messageSignal.chats:
|
||||
let channel = newChatitem()
|
||||
channel.name = c.name
|
||||
channel.lastMessage = c.lastMessage.text
|
||||
channel.timestamp = c.timestamp
|
||||
channel.unviewedMessagesCount = c.unviewedMessagesCount
|
||||
self.view.updateChat(channel)
|
||||
|
||||
for message in messageSignal.messages:
|
||||
let chatMessage = newChatMessage()
|
||||
chatMessage.userName = message.alias
|
||||
chatMessage.message = message.text
|
||||
|
|
|
@ -2,17 +2,21 @@ import NimQml
|
|||
import Tables
|
||||
import messages
|
||||
import messageList
|
||||
import chatItem
|
||||
import ../../models/chat
|
||||
|
||||
type
|
||||
RoleNames {.pure.} = enum
|
||||
Name = UserRole + 1,
|
||||
LastMessage = UserRole + 2
|
||||
Timestamp = UserRole + 3
|
||||
UnreadMessages = UserRole + 4
|
||||
|
||||
QtObject:
|
||||
type
|
||||
ChatsView* = ref object of QAbstractListModel
|
||||
model: ChatModel
|
||||
names*: seq[string]
|
||||
chats: seq[ChatItem]
|
||||
callResult: string
|
||||
messageList: Table[string, ChatMessageList]
|
||||
activeChannel: string
|
||||
|
@ -24,7 +28,7 @@ QtObject:
|
|||
proc newChatsView*(model: ChatModel): ChatsView =
|
||||
new(result, delete)
|
||||
result.model = model
|
||||
result.names = @[]
|
||||
result.chats = @[]
|
||||
result.activeChannel = ""
|
||||
result.messageList = initTable[string, ChatMessageList]()
|
||||
result.setup()
|
||||
|
@ -33,17 +37,29 @@ QtObject:
|
|||
if not self.messageList.hasKey(channel):
|
||||
self.messageList[channel] = newChatMessageList()
|
||||
|
||||
method rowCount(self: ChatsView, index: QModelIndex = nil): int = self.names.len
|
||||
method rowCount(self: ChatsView, index: QModelIndex = nil): int = self.chats.len
|
||||
|
||||
method data(self: ChatsView, index: QModelIndex, role: int): QVariant =
|
||||
if not index.isValid:
|
||||
return
|
||||
if index.row < 0 or index.row >= self.names.len:
|
||||
if index.row < 0 or index.row >= self.chats.len:
|
||||
return
|
||||
return newQVariant(self.names[index.row])
|
||||
|
||||
let chatItem = self.chats[index.row]
|
||||
let chatItemRole = role.RoleNames
|
||||
case chatItemRole:
|
||||
of RoleNames.Name: result = newQVariant(chatItem.name)
|
||||
of RoleNames.Timestamp: result = newQVariant($chatItem.timestamp)
|
||||
of RoleNames.LastMessage: result = newQVariant(chatItem.lastMessage)
|
||||
of RoleNames.UnreadMessages: result = newQVariant(chatItem.unviewedMessagesCount)
|
||||
|
||||
method roleNames(self: ChatsView): Table[int, string] =
|
||||
{ RoleNames.Name.int:"name"}.toTable
|
||||
{
|
||||
RoleNames.Name.int:"name",
|
||||
RoleNames.Timestamp.int:"timestamp",
|
||||
RoleNames.LastMessage.int: "lastMessage",
|
||||
RoleNames.UnreadMessages.int: "unviewedMessagesCount"
|
||||
}.toTable
|
||||
|
||||
proc onSend*(self: ChatsView, inputJSON: string) {.slot.} =
|
||||
discard self.model.sendMessage(self.activeChannel, inputJSON)
|
||||
|
@ -57,8 +73,8 @@ QtObject:
|
|||
proc activeChannelChanged*(self: ChatsView) {.signal.}
|
||||
|
||||
proc setActiveChannelByIndex*(self: ChatsView, index: int) {.slot.} =
|
||||
if self.activeChannel == self.names[index]: return
|
||||
self.activeChannel = self.names[index]
|
||||
if self.activeChannel == self.chats[index].name: return
|
||||
self.activeChannel = self.chats[index].name
|
||||
self.activeChannelChanged()
|
||||
|
||||
QtProperty[string] activeChannel:
|
||||
|
@ -80,18 +96,27 @@ QtObject:
|
|||
|
||||
proc addToList(self: ChatsView, channel: string): int =
|
||||
if(self.activeChannel == ""): self.setActiveChannel(channel)
|
||||
|
||||
self.beginInsertRows(newQModelIndex(), self.names.len, self.names.len)
|
||||
self.names.add(channel)
|
||||
var chatItem = newChatItem()
|
||||
chatItem.name = channel
|
||||
self.upsertChannel(channel)
|
||||
self.beginInsertRows(newQModelIndex(), self.chats.len, self.chats.len)
|
||||
self.chats.add(chatItem)
|
||||
self.endInsertRows()
|
||||
|
||||
result = self.names.len - 1
|
||||
result = self.chats.len - 1
|
||||
|
||||
proc joinChat*(self: ChatsView, channel: string): int {.slot.} =
|
||||
self.setActiveChannel(channel)
|
||||
if self.model.hasChannel(channel):
|
||||
result = self.names.find(channel)
|
||||
result = self.chats.findByName(channel)
|
||||
else:
|
||||
self.model.join(channel)
|
||||
result = self.addToList(channel)
|
||||
|
||||
proc updateChat*(self: ChatsView, chat: ChatItem) =
|
||||
var idx = self.chats.findByName(chat.name)
|
||||
if idx > -1:
|
||||
self.chats[idx] = chat
|
||||
var x = self.createIndex(idx,0,nil)
|
||||
var y = self.createIndex(idx,0,nil)
|
||||
self.dataChanged(x, y, @[RoleNames.Timestamp.int, RoleNames.LastMessage.int, RoleNames.UnreadMessages.int])
|
||||
|
|
|
@ -1,33 +1,57 @@
|
|||
import json
|
||||
import types
|
||||
|
||||
proc toMessage(jsonMsg: JsonNode): Message
|
||||
proc toChat(jsonChat: JsonNode): Chat
|
||||
|
||||
proc fromEvent*(event: JsonNode): Signal =
|
||||
var signal:ChatSignal = ChatSignal()
|
||||
var signal:MessageSignal = MessageSignal()
|
||||
signal.messages = @[]
|
||||
|
||||
if event["event"]{"messages"} != nil:
|
||||
for jsonMsg in event["event"]["messages"]:
|
||||
let msg = Message(
|
||||
alias: jsonMsg{"alias"}.getStr,
|
||||
chatId: jsonMsg{"chatId"}.getStr,
|
||||
clock: $jsonMsg{"clock"}.getInt,
|
||||
contentType: jsonMsg{"contentType"}.getInt,
|
||||
ensName: jsonMsg{"ensName"}.getStr,
|
||||
fromAuthor: jsonMsg{"from"}.getStr,
|
||||
id: jsonMsg{"identicon"}.getStr,
|
||||
identicon: jsonMsg{"identicon"}.getStr,
|
||||
lineCount: jsonMsg{"lineCount"}.getInt,
|
||||
localChatId: jsonMsg{"localChatId"}.getStr,
|
||||
messageType: jsonMsg{"messageType"}.getStr,
|
||||
replace: jsonMsg{"replace"}.getStr,
|
||||
responseTo: jsonMsg{"responseTo"}.getStr,
|
||||
rtl: jsonMsg{"rtl"}.getBool,
|
||||
seen: jsonMsg{"seen"}.getBool,
|
||||
text: jsonMsg{"text"}.getStr,
|
||||
timestamp: $jsonMsg{"timestamp"}.getInt,
|
||||
whisperTimestamp: $jsonMsg{"whisperTimestamp"}.getInt,
|
||||
isCurrentUser: false # TODO: this must compare the fromAuthor against current user because the messages received from the mailserver will arrive as signals too, and those include the current user messages
|
||||
)
|
||||
signal.messages.add(msg)
|
||||
signal.messages.add(jsonMsg.toMessage)
|
||||
|
||||
result = signal
|
||||
if event["event"]{"chats"} != nil:
|
||||
for jsonChat in event["event"]["chats"]:
|
||||
signal.chats.add(jsonChat.toChat)
|
||||
|
||||
result = signal
|
||||
|
||||
proc toChat(jsonChat: JsonNode): Chat =
|
||||
result = Chat(
|
||||
id: jsonChat{"id"}.getStr,
|
||||
name: jsonChat{"name"}.getStr,
|
||||
color: jsonChat{"color"}.getStr,
|
||||
active: jsonChat{"active"}.getBool,
|
||||
chatType: ChatType(jsonChat{"chatType"}.getInt),
|
||||
timestamp: jsonChat{"timestamp"}.getBiggestInt,
|
||||
lastClockValue: jsonChat{"lastClockValue"}.getBiggestInt,
|
||||
deletedAtClockValue: jsonChat{"deletedAtClockValue"}.getBiggestInt,
|
||||
unviewedMessagesCount: jsonChat{"unviewedMessagesCount"}.getInt,
|
||||
lastMessage: jsonChat{"lastMessage"}.toMessage
|
||||
)
|
||||
|
||||
|
||||
proc toMessage(jsonMsg: JsonNode): Message =
|
||||
result = Message(
|
||||
alias: jsonMsg{"alias"}.getStr,
|
||||
chatId: jsonMsg{"chatId"}.getStr,
|
||||
clock: $jsonMsg{"clock"}.getInt,
|
||||
contentType: jsonMsg{"contentType"}.getInt,
|
||||
ensName: jsonMsg{"ensName"}.getStr,
|
||||
fromAuthor: jsonMsg{"from"}.getStr,
|
||||
id: jsonMsg{"identicon"}.getStr,
|
||||
identicon: jsonMsg{"identicon"}.getStr,
|
||||
lineCount: jsonMsg{"lineCount"}.getInt,
|
||||
localChatId: jsonMsg{"localChatId"}.getStr,
|
||||
messageType: jsonMsg{"messageType"}.getStr,
|
||||
replace: jsonMsg{"replace"}.getStr,
|
||||
responseTo: jsonMsg{"responseTo"}.getStr,
|
||||
rtl: jsonMsg{"rtl"}.getBool,
|
||||
seen: jsonMsg{"seen"}.getBool,
|
||||
text: jsonMsg{"text"}.getStr,
|
||||
timestamp: $jsonMsg{"timestamp"}.getInt,
|
||||
whisperTimestamp: $jsonMsg{"whisperTimestamp"}.getInt,
|
||||
isCurrentUser: false # TODO: this must compare the fromAuthor against current user because the messages received from the mailserver will arrive as signals too, and those include the current user messages
|
||||
)
|
|
@ -1,3 +1,5 @@
|
|||
import chronicles
|
||||
|
||||
type SignalSubscriber* = ref object of RootObj
|
||||
|
||||
type Signal* = ref object of RootObj
|
||||
|
@ -30,10 +32,32 @@ type Message* = object
|
|||
whisperTimestamp*: string
|
||||
isCurrentUser*: bool
|
||||
|
||||
|
||||
type ChatSignal* = ref object of Signal
|
||||
messages*: seq[Message]
|
||||
|
||||
# Override this method
|
||||
method onSignal*(self: SignalSubscriber, data: Signal) {.base.} =
|
||||
echo "Received a signal" # TODO: log signal received
|
||||
discard
|
||||
# TODO: log signal received
|
||||
|
||||
type ChatType* = enum
|
||||
ChatTypeOneToOne = 1,
|
||||
ChatTypePublic = 2,
|
||||
ChatTypePrivateGroupChat = 3
|
||||
|
||||
type Chat* = 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
|
||||
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
|
||||
# Group chat fields
|
||||
# members ?
|
||||
# membershipUpdateEvents # ?
|
||||
|
||||
|
||||
type MessageSignal* = ref object of Signal
|
||||
messages*: seq[Message]
|
||||
chats*: seq[Chat]
|
|
@ -75,7 +75,6 @@ proc mainProc() =
|
|||
|
||||
appState.subscribe(proc () =
|
||||
for channel in appState.channels:
|
||||
echo channel.name
|
||||
chat.load(channel.name)
|
||||
)
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@ SplitView {
|
|||
}
|
||||
Text {
|
||||
id: lastChatMessage
|
||||
text: "Chatting blah blah..."
|
||||
text: lastMessage || qsTr("No messages")
|
||||
anchors.right: contactNumberChatsCircle.left
|
||||
anchors.rightMargin: Theme.smallPadding
|
||||
elide: Text.ElideRight
|
||||
|
@ -194,7 +194,7 @@ SplitView {
|
|||
}
|
||||
Text {
|
||||
id: contactTime
|
||||
text: "12:22 AM"
|
||||
text: timestamp
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.padding
|
||||
anchors.top: parent.top
|
||||
|
@ -212,9 +212,10 @@ SplitView {
|
|||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.padding
|
||||
color: Theme.blue
|
||||
visible: unviewedMessagesCount > 0
|
||||
Text {
|
||||
id: contactNumberChats
|
||||
text: qsTr("1")
|
||||
text: unviewedMessagesCount
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: "white"
|
||||
|
|
Loading…
Reference in New Issue