fix: remove filters on leaving chat
This commit is contained in:
parent
c2ed0da1ca
commit
47b88cab95
|
@ -1,11 +1,9 @@
|
|||
import eventemitter, json
|
||||
import sequtils
|
||||
import eventemitter, json, strutils, sequtils, tables
|
||||
import libstatus/chat as status_chat
|
||||
import chronicles
|
||||
import profile/profile
|
||||
import chat/[chat, message]
|
||||
import ../signals/messages
|
||||
import tables
|
||||
import ens
|
||||
|
||||
type
|
||||
|
@ -33,15 +31,15 @@ type
|
|||
events*: EventEmitter
|
||||
contacts*: Table[string, Profile]
|
||||
channels*: Table[string, Chat]
|
||||
filters*: Table[string, string]
|
||||
msgCursor*: Table[string, string]
|
||||
|
||||
include chat/utils
|
||||
|
||||
proc newChatModel*(events: EventEmitter): ChatModel =
|
||||
result = ChatModel()
|
||||
result.events = events
|
||||
result.contacts = initTable[string, Profile]()
|
||||
result.channels = initTable[string, Chat]()
|
||||
result.filters = initTable[string, string]()
|
||||
result.msgCursor = initTable[string, string]()
|
||||
|
||||
proc delete*(self: ChatModel) =
|
||||
|
@ -73,7 +71,6 @@ proc join*(self: ChatModel, chatId: string, chatType: ChatType) =
|
|||
for topicObj in parsedResult:
|
||||
if ($topicObj["chatId"].getStr == chatId):
|
||||
topics.add($topicObj["topic"].getStr)
|
||||
if(not self.filters.hasKey(chatId)): self.filters[chatId] = topicObj["filterId"].getStr
|
||||
|
||||
if (topics.len == 0):
|
||||
warn "No topics found for chats. Cannot load past messages"
|
||||
|
@ -103,40 +100,22 @@ proc init*(self: ChatModel) =
|
|||
let parsedResult = parseJson(filterResult)["result"]
|
||||
for topicObj in parsedResult:
|
||||
topics.add($topicObj["topic"].getStr)
|
||||
self.filters[$topicObj["chatId"].getStr] = topicObj["filterId"].getStr
|
||||
|
||||
if (topics.len == 0):
|
||||
warn "No topics found for chats. Cannot load past messages"
|
||||
else:
|
||||
self.events.emit("mailserverTopics", TopicArgs(topics: topics));
|
||||
|
||||
proc processChatUpdate(self: ChatModel,response: JsonNode): (seq[Chat], seq[Message]) =
|
||||
var chats: seq[Chat] = @[]
|
||||
var messages: seq[Message] = @[]
|
||||
if response["result"]{"chats"} != nil:
|
||||
for jsonMsg in response["result"]["messages"]:
|
||||
messages.add(jsonMsg.toMessage)
|
||||
if response["result"]{"chats"} != nil:
|
||||
for jsonChat in response["result"]["chats"]:
|
||||
let chat = jsonChat.toChat
|
||||
self.channels[chat.id] = chat
|
||||
chats.add(chat)
|
||||
result = (chats, messages)
|
||||
|
||||
|
||||
proc leave*(self: ChatModel, chatId: string) =
|
||||
self.removeChatFilters(chatId)
|
||||
|
||||
if self.channels[chatId].chatType == ChatType.PrivateGroupChat:
|
||||
let leaveGroupResponse = status_chat.leaveGroupChat(chatId)
|
||||
var (chats, messages) = self.processChatUpdate(parseJson(leaveGroupResponse))
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[]))
|
||||
|
||||
# We still want to be able to receive messages unless we block the 1:1 sender
|
||||
if self.filters.hasKey(chatId) and self.channels[chatId].chatType == ChatType.Public:
|
||||
status_chat.removeFilters(chatId, self.filters[chatId])
|
||||
self.emitUpdate(leaveGroupResponse)
|
||||
|
||||
status_chat.deactivateChat(self.channels[chatId])
|
||||
|
||||
# TODO: REMOVE MAILSERVER TOPIC
|
||||
self.filters.del(chatId)
|
||||
self.channels.del(chatId)
|
||||
discard status_chat.clearChatHistory(chatId)
|
||||
self.events.emit("channelLeft", ChatIdArg(chatId: chatId))
|
||||
|
@ -151,21 +130,9 @@ proc clearHistory*(self: ChatModel, chatId: string) =
|
|||
proc setActiveChannel*(self: ChatModel, chatId: string) =
|
||||
self.events.emit("activeChannelChanged", ChatIdArg(chatId: chatId))
|
||||
|
||||
proc formatChatUpdate(response: JsonNode): (seq[Chat], seq[Message]) =
|
||||
var chats: seq[Chat] = @[]
|
||||
var messages: seq[Message] = @[]
|
||||
if response["result"]{"chats"} != nil:
|
||||
for jsonMsg in response["result"]["messages"]:
|
||||
messages.add(jsonMsg.toMessage)
|
||||
if response["result"]{"chats"} != nil:
|
||||
for jsonChat in response["result"]["chats"]:
|
||||
chats.add(jsonChat.toChat)
|
||||
result = (chats, messages)
|
||||
|
||||
proc sendMessage*(self: ChatModel, chatId: string, msg: string): string =
|
||||
var sentMessage = status_chat.sendChatMessage(chatId, msg)
|
||||
var (chats, messages) = self.processChatUpdate(parseJson(sentMessage))
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[]))
|
||||
self.emitUpdate(sentMessage)
|
||||
sentMessage
|
||||
|
||||
proc chatMessages*(self: ChatModel, chatId: string, initialLoad:bool = true) =
|
||||
|
@ -185,14 +152,12 @@ proc markAllChannelMessagesRead*(self: ChatModel, chatId: string): JsonNode =
|
|||
result = parseJson(response)
|
||||
|
||||
proc confirmJoiningGroup*(self: ChatModel, chatId: string) =
|
||||
var response = parseJson(status_chat.confirmJoiningGroup(chatId))
|
||||
var (chats, messages) = self.processChatUpdate(response)
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[]))
|
||||
var response = status_chat.confirmJoiningGroup(chatId)
|
||||
self.emitUpdate(response)
|
||||
|
||||
proc renameGroup*(self: ChatModel, chatId: string, newName: string) =
|
||||
var response = parseJson(status_chat.renameGroup(chatId, newName))
|
||||
var (chats, messages) = formatChatUpdate(response)
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[]))
|
||||
var response = status_chat.renameGroup(chatId, newName)
|
||||
self.emitUpdate(response)
|
||||
|
||||
proc getUserName*(self: ChatModel, id: string, defaultUserName: string):string =
|
||||
if(self.contacts.hasKey(id)):
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
proc formatChatUpdate(response: JsonNode): (seq[Chat], seq[Message]) =
|
||||
var chats: seq[Chat] = @[]
|
||||
var messages: seq[Message] = @[]
|
||||
if response["result"]{"chats"} != nil:
|
||||
for jsonMsg in response["result"]["messages"]:
|
||||
messages.add(jsonMsg.toMessage)
|
||||
if response["result"]{"chats"} != nil:
|
||||
for jsonChat in response["result"]["chats"]:
|
||||
chats.add(jsonChat.toChat)
|
||||
result = (chats, messages)
|
||||
|
||||
proc processChatUpdate(self: ChatModel, response: JsonNode): (seq[Chat], seq[Message]) =
|
||||
var chats: seq[Chat] = @[]
|
||||
var messages: seq[Message] = @[]
|
||||
if response["result"]{"chats"} != nil:
|
||||
for jsonMsg in response["result"]["messages"]:
|
||||
messages.add(jsonMsg.toMessage)
|
||||
if response["result"]{"chats"} != nil:
|
||||
for jsonChat in response["result"]["chats"]:
|
||||
let chat = jsonChat.toChat
|
||||
self.channels[chat.id] = chat
|
||||
chats.add(chat)
|
||||
result = (chats, messages)
|
||||
|
||||
proc emitUpdate(self: ChatModel, response: string) =
|
||||
var (chats, messages) = self.processChatUpdate(parseJson(response))
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[]))
|
||||
|
||||
proc removeFiltersByChatId(self: ChatModel, chatId: string, filters: JsonNode)
|
||||
|
||||
proc removeChatFilters(self: ChatModel, chatId: string) =
|
||||
# TODO: this code should be handled by status-go / stimbus instead of the client
|
||||
# Clients should not have to care about filters. For more info about filters:
|
||||
# https://github.com/status-im/specs/blob/master/docs/stable/3-whisper-usage.md#keys-management
|
||||
let filters = parseJson(status_chat.loadFilters(@[]))["result"]
|
||||
|
||||
case self.channels[chatId].chatType
|
||||
of ChatType.Public:
|
||||
for filter in filters:
|
||||
if filter["chatId"].getStr == chatId:
|
||||
status_chat.removeFilters(chatId, filter["filterId"].getStr)
|
||||
of ChatType.OneToOne:
|
||||
# Check if user does not belong to any active chat group
|
||||
var inGroup = false
|
||||
for channel in self.channels.values:
|
||||
if channel.isActive and channel.id != chatId and channel.chatType == ChatType.PrivateGroupChat:
|
||||
inGroup = true
|
||||
break
|
||||
if not inGroup: self.removeFiltersByChatId(chatId, filters)
|
||||
of ChatType.PrivateGroupChat:
|
||||
for member in self.channels[chatId].members:
|
||||
# Check that any of the members are not in other active group chats, or that you don’t have a one-to-one open.
|
||||
var hasConversation = false
|
||||
for channel in self.channels.values:
|
||||
if (channel.isActive and channel.chatType == ChatType.OneToOne and channel.id == member.id) or
|
||||
(channel.isActive and channel.id != chatId and channel.chatType == ChatType.PrivateGroupChat and channel.isMember(member.id)):
|
||||
hasConversation = true
|
||||
break
|
||||
if not hasConversation: self.removeFiltersByChatId(member.id, filters)
|
||||
else:
|
||||
error "Unknown chat type removed", chatId
|
||||
|
||||
proc removeFiltersByChatId(self: ChatModel, chatId: string, filters: JsonNode) =
|
||||
var partitionedTopic = ""
|
||||
for filter in filters:
|
||||
# Contact code filter should be removed
|
||||
if filter["identity"].getStr == chatId and filter["chatId"].getStr.endsWith("-contact-code"):
|
||||
status_chat.removeFilters(chatId, filter["filterId"].getStr)
|
||||
|
||||
# Remove partitioned topic if no other user in an active group chat or one-to-one is from the
|
||||
# same partitioned topic
|
||||
if filter["identity"].getStr == chatId and filter["chatId"].getStr.startsWith("contact-discovery-"):
|
||||
partitionedTopic = filter["topic"].getStr
|
||||
var samePartitionedTopic = false
|
||||
for f in filters.filterIt(it["topic"].getStr == partitionedTopic and it["filterId"].getStr != filter["filterId"].getStr):
|
||||
let fIdentity = f["identity"].getStr;
|
||||
if self.channels.hasKey(fIdentity) and self.channels[fIdentity].isActive:
|
||||
samePartitionedTopic = true
|
||||
break
|
||||
if not samePartitionedTopic:
|
||||
status_chat.removeFilters(chatId, filter["filterId"].getStr)
|
|
@ -28,6 +28,8 @@ proc removeFilters*(chatId: string, filterId: string) =
|
|||
])
|
||||
|
||||
proc saveChat*(chatId: string, oneToOne: bool = false, active: bool = true, color: string) =
|
||||
# TODO: ideally status-go/stimbus should handle some of these fields instead of having the client
|
||||
# send them: lastMessage, unviewedMEssagesCount, timestamp, lastClockValue, name?
|
||||
discard callPrivateRPC("saveChat".prefix, %* [
|
||||
{
|
||||
"lastClockValue": 0, # TODO:
|
||||
|
|
Loading…
Reference in New Issue