fix: Keep only one place to store contacts and index (#37)
This commit is contained in:
parent
3655396b57
commit
23db2d1216
|
@ -1,5 +1,6 @@
|
|||
import json, strutils, sequtils, tables, chronicles, times, sugar, algorithm
|
||||
import statusgo_backend/chat as status_chat
|
||||
import statusgo_backend/contacts as status_contacts
|
||||
import statusgo_backend/chatCommands as status_chat_commands
|
||||
import types/[message, status_update, activity_center_notification,
|
||||
sticker, removed_message]
|
||||
|
@ -31,7 +32,6 @@ type
|
|||
chats*: seq[Chat]
|
||||
messages*: seq[Message]
|
||||
pinnedMessages*: seq[Message]
|
||||
contacts*: seq[Profile]
|
||||
emojiReactions*: seq[Reaction]
|
||||
communities*: seq[Community]
|
||||
communityMembershipRequests*: seq[CommunityMembershipRequest]
|
||||
|
@ -80,7 +80,6 @@ type ChatModel* = ref object
|
|||
events*: EventEmitter
|
||||
communitiesToFetch*: seq[string]
|
||||
mailserverReady*: bool
|
||||
contacts*: Table[string, Profile]
|
||||
channels*: Table[string, Chat]
|
||||
msgCursor: Table[string, string]
|
||||
pinnedMsgCursor: Table[string, string]
|
||||
|
@ -93,13 +92,20 @@ proc newChatModel*(events: EventEmitter): ChatModel =
|
|||
result.events = events
|
||||
result.mailserverReady = false
|
||||
result.communitiesToFetch = @[]
|
||||
result.contacts = initTable[string, Profile]()
|
||||
result.channels = initTable[string, Chat]()
|
||||
result.msgCursor = initTable[string, string]()
|
||||
result.pinnedMsgCursor = initTable[string, string]()
|
||||
result.emojiCursor = initTable[string, string]()
|
||||
result.lastMessageTimestamps = initTable[string, int64]()
|
||||
|
||||
proc getContacts*(self: ChatModel): Table[string, Profile] =
|
||||
let (index, usedCache) = status_contacts.getContactsIndex()
|
||||
if not usedCache:
|
||||
let (contacts, _) = status_contacts.getContacts()
|
||||
self.events.emit("contactUpdate", ContactUpdateArgs(contacts: contacts))
|
||||
|
||||
return index
|
||||
|
||||
proc update*(self: ChatModel, chats: seq[Chat], messages: seq[Message], emojiReactions: seq[Reaction], communities: seq[Community], communityMembershipRequests: seq[CommunityMembershipRequest], pinnedMessages: seq[Message], activityCenterNotifications: seq[ActivityCenterNotification], statusUpdates: seq[StatusUpdate], deletedMessages: seq[RemovedMessage]) =
|
||||
for chat in chats:
|
||||
self.channels[chat.id] = chat
|
||||
|
@ -113,7 +119,7 @@ proc update*(self: ChatModel, chats: seq[Chat], messages: seq[Message], emojiRea
|
|||
if self.lastMessageTimestamps[chatId] > ts:
|
||||
self.lastMessageTimestamps[chatId] = ts
|
||||
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages,chats: chats, contacts: @[], emojiReactions: emojiReactions, communities: communities, communityMembershipRequests: communityMembershipRequests, pinnedMessages: pinnedMessages, activityCenterNotifications: activityCenterNotifications, statusUpdates: statusUpdates, deletedMessages: deletedMessages))
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages,chats: chats, emojiReactions: emojiReactions, communities: communities, communityMembershipRequests: communityMembershipRequests, pinnedMessages: pinnedMessages, activityCenterNotifications: activityCenterNotifications, statusUpdates: statusUpdates, deletedMessages: deletedMessages))
|
||||
|
||||
proc parseChatResponse(self: ChatModel, response: string): (seq[Chat], seq[Message]) =
|
||||
var parsedResponse = parseJson(response)
|
||||
|
@ -131,7 +137,7 @@ proc parseChatResponse(self: ChatModel, response: string): (seq[Chat], seq[Messa
|
|||
|
||||
proc emitUpdate(self: ChatModel, response: string) =
|
||||
var (chats, messages) = self.parseChatResponse(response)
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[]))
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats))
|
||||
|
||||
proc removeFiltersByChatId(self: ChatModel, chatId: string, filters: JsonNode)
|
||||
|
||||
|
@ -225,11 +231,6 @@ proc createPublicChat*(self: ChatModel, chatId: string) =
|
|||
self.emitTopicAndJoin(chat)
|
||||
|
||||
|
||||
proc updateContacts*(self: ChatModel, contacts: seq[Profile]) =
|
||||
for c in contacts:
|
||||
self.contacts[c.id] = c
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(contacts: contacts))
|
||||
|
||||
proc requestMissingCommunityInfos*(self: ChatModel) =
|
||||
if (self.communitiesToFetch.len == 0):
|
||||
return
|
||||
|
@ -252,7 +253,8 @@ proc sortChats(x, y: chat_type.Chat): int =
|
|||
proc init*(self: ChatModel, pubKey: string) =
|
||||
self.publicKey = pubKey
|
||||
|
||||
var contacts = getAddedContacts()
|
||||
var (contacts, _) = status_contacts.getContacts()
|
||||
contacts = contacts.filter(c => c.systemTags.contains(contactAdded))
|
||||
var chatList = status_chat.loadChats()
|
||||
chatList.sort(sortChats)
|
||||
|
||||
|
@ -295,15 +297,10 @@ proc init*(self: ChatModel, pubKey: string) =
|
|||
|
||||
self.events.emit("chatsLoaded", ChatArgs(chats: chatList))
|
||||
|
||||
|
||||
self.events.once("mailserverAvailable") do(a: Args):
|
||||
self.mailserverReady = true
|
||||
self.requestMissingCommunityInfos()
|
||||
|
||||
self.events.on("contactUpdate") do(a: Args):
|
||||
var evArgs = ContactUpdateArgs(a)
|
||||
self.updateContacts(evArgs.contacts)
|
||||
|
||||
proc statusUpdates*(self: ChatModel) =
|
||||
let statusUpdates = status_chat.statusUpdates()
|
||||
self.events.emit("messagesLoaded", MsgsLoadedArgs(statusUpdates: statusUpdates))
|
||||
|
@ -369,7 +366,7 @@ proc sendSticker*(self: ChatModel, chatId: string, replyTo: string, sticker: Sti
|
|||
var response = status_chat.sendStickerMessage(chatId, replyTo, sticker)
|
||||
self.events.emit("stickerSent", StickerArgs(sticker: sticker, save: true))
|
||||
var (chats, messages) = self.parseChatResponse(response)
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[]))
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats))
|
||||
self.events.emit("sendingMessage", MessageArgs(id: messages[0].id, channel: messages[0].chatId))
|
||||
|
||||
proc addEmojiReaction*(self: ChatModel, chatId: string, messageId: string, emojiId: int) =
|
||||
|
@ -385,7 +382,7 @@ proc onMarkMessagesRead(self: ChatModel, response: string, chatId: string): Json
|
|||
if self.channels.hasKey(chatId):
|
||||
self.channels[chatId].unviewedMessagesCount = 0
|
||||
self.channels[chatId].mentionsCount = 0
|
||||
self.events.emit("channelUpdate", ChatUpdateArgs(messages: @[], chats: @[self.channels[chatId]], contacts: @[]))
|
||||
self.events.emit("channelUpdate", ChatUpdateArgs(messages: @[], chats: @[self.channels[chatId]]))
|
||||
|
||||
proc onAsyncMarkMessagesRead*(self: ChatModel, response: string) =
|
||||
let parsedResponse = parseJson(response)
|
||||
|
@ -408,8 +405,9 @@ proc renameGroup*(self: ChatModel, chatId: string, newName: string) =
|
|||
self.emitUpdate(response)
|
||||
|
||||
proc getUserName*(self: ChatModel, id: string, defaultUserName: string):string =
|
||||
if(self.contacts.hasKey(id)):
|
||||
return userNameOrAlias(self.contacts[id])
|
||||
let contacts = self.getContacts()
|
||||
if(contacts.hasKey(id)):
|
||||
return userNameOrAlias(contacts[id])
|
||||
else:
|
||||
return defaultUserName
|
||||
|
||||
|
@ -418,7 +416,7 @@ proc processGroupChatCreation*(self: ChatModel, result: string) =
|
|||
var (chats, messages) = formatChatUpdate(response)
|
||||
let chat = chats[0]
|
||||
self.channels[chat.id] = chat
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[]))
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats))
|
||||
self.events.emit("activeChannelChanged", ChatIdArg(chatId: chat.id))
|
||||
|
||||
proc createGroup*(self: ChatModel, groupName: string, pubKeys: seq[string]) =
|
||||
|
@ -446,11 +444,11 @@ proc resendMessage*(self: ChatModel, messageId: string) =
|
|||
|
||||
proc muteChat*(self: ChatModel, chat: Chat) =
|
||||
discard status_chat.muteChat(chat.id)
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: @[], chats: @[chat], contacts: @[]))
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: @[], chats: @[chat]))
|
||||
|
||||
proc unmuteChat*(self: ChatModel, chat: Chat) =
|
||||
discard status_chat.unmuteChat(chat.id)
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: @[], chats: @[chat], contacts: @[]))
|
||||
self.events.emit("chatUpdate", ChatUpdateArgs(messages: @[], chats: @[chat]))
|
||||
|
||||
proc processUpdateForTransaction*(self: ChatModel, messageId: string, response: string) =
|
||||
var (chats, messages) = self.processMessageUpdateAfterSend(response)
|
||||
|
@ -741,8 +739,9 @@ proc userNameOrAlias*(self: ChatModel, pubKey: string,
|
|||
## Returns ens name or alias, in case if prettyForm is true and ens name
|
||||
## ends with ".stateofus.eth" that part will be removed.
|
||||
var alias: string
|
||||
if self.contacts.hasKey(pubKey):
|
||||
alias = ens.userNameOrAlias(self.contacts[pubKey])
|
||||
let contacts = self.getContacts()
|
||||
if contacts.hasKey(pubKey):
|
||||
alias = ens.userNameOrAlias(contacts[pubKey])
|
||||
else:
|
||||
alias = generateAlias(pubKey)
|
||||
|
||||
|
@ -755,9 +754,9 @@ proc chatName*(self: ChatModel, chatItem: Chat): string =
|
|||
if (not chatItem.chatType.isOneToOne):
|
||||
return chatItem.name
|
||||
|
||||
if (self.contacts.hasKey(chatItem.id) and
|
||||
self.contacts[chatItem.id].hasNickname()):
|
||||
return self.contacts[chatItem.id].localNickname
|
||||
let contacts = self.getContacts()
|
||||
if (contacts.hasKey(chatItem.id) and contacts[chatItem.id].hasNickname()):
|
||||
return contacts[chatItem.id].localNickname
|
||||
|
||||
if chatItem.ensName != "":
|
||||
return "@" & userName(chatItem.ensName).userName(true)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import json, sequtils, sugar, chronicles
|
||||
import json, chronicles
|
||||
import statusgo_backend/contacts as status_contacts
|
||||
import statusgo_backend/accounts as status_accounts
|
||||
import statusgo_backend/chat as status_chat
|
||||
|
@ -19,6 +19,13 @@ proc newContactModel*(events: EventEmitter): ContactModel =
|
|||
result = ContactModel()
|
||||
result.events = events
|
||||
|
||||
proc saveContact(self: ContactModel, contact: Profile): string =
|
||||
var thumbnail = ""
|
||||
if contact.identityImage != nil:
|
||||
thumbnail = contact.identityImage.thumbnail
|
||||
|
||||
return status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, thumbnail, contact.systemTags, contact.localNickname)
|
||||
|
||||
proc getContactByID*(self: ContactModel, id: string): Profile =
|
||||
let response = status_contacts.getContactByID(id)
|
||||
# TODO: change to options
|
||||
|
@ -31,24 +38,21 @@ proc getContactByID*(self: ContactModel, id: string): Profile =
|
|||
proc blockContact*(self: ContactModel, id: string): string =
|
||||
var contact = self.getContactByID(id)
|
||||
contact.systemTags.add(contactBlocked)
|
||||
discard status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, contact.identityImage.thumbnail, contact.systemTags, contact.localNickname)
|
||||
discard self.saveContact(contact)
|
||||
self.events.emit("contactBlocked", Args())
|
||||
|
||||
proc unblockContact*(self: ContactModel, id: string): string =
|
||||
var contact = self.getContactByID(id)
|
||||
contact.systemTags.delete(contact.systemTags.find(contactBlocked))
|
||||
discard status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, contact.identityImage.thumbnail, contact.systemTags, contact.localNickname)
|
||||
discard self.saveContact(contact)
|
||||
self.events.emit("contactUnblocked", Args())
|
||||
|
||||
proc getAllContacts*(): seq[Profile] =
|
||||
result = map(status_contacts.getContacts().getElems(), proc(x: JsonNode): Profile = x.toProfileModel())
|
||||
proc getContacts*(self: ContactModel, useCache: bool = true): seq[Profile] =
|
||||
let (contacts, usedCache) = status_contacts.getContacts(useCache)
|
||||
if not usedCache:
|
||||
self.events.emit("contactUpdate", ContactUpdateArgs(contacts: contacts))
|
||||
|
||||
proc getAddedContacts*(): seq[Profile] =
|
||||
result = getAllContacts().filter(c => c.systemTags.contains(contactAdded))
|
||||
|
||||
proc getContacts*(self: ContactModel): seq[Profile] =
|
||||
result = getAllContacts()
|
||||
self.events.emit("contactUpdate", ContactUpdateArgs(contacts: result))
|
||||
return contacts
|
||||
|
||||
proc getOrCreateContact*(self: ContactModel, id: string): Profile =
|
||||
result = self.getContactByID(id)
|
||||
|
@ -66,7 +70,7 @@ proc getOrCreateContact*(self: ContactModel, id: string): Profile =
|
|||
systemTags: @[]
|
||||
)
|
||||
|
||||
proc setNickName*(self: ContactModel, id: string, localNickname: string): string =
|
||||
proc setNickName*(self: ContactModel, id: string, localNickname: string, accountKeyUID: string): string =
|
||||
var contact = self.getOrCreateContact(id)
|
||||
let nickname =
|
||||
if (localNickname == ""):
|
||||
|
@ -76,18 +80,16 @@ proc setNickName*(self: ContactModel, id: string, localNickname: string): string
|
|||
else:
|
||||
localNickname
|
||||
|
||||
var thumbnail = ""
|
||||
if contact.identityImage != nil:
|
||||
thumbnail = contact.identityImage.thumbnail
|
||||
result = status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, thumbnail, contact.systemTags, nickname)
|
||||
contact.localNickname = nickname
|
||||
result = self.saveContact(contact)
|
||||
self.events.emit("contactAdded", Args())
|
||||
discard requestContactUpdate(contact.id)
|
||||
discard sendContactUpdate(contact.id, accountKeyUID)
|
||||
|
||||
|
||||
proc addContact*(self: ContactModel, id: string): string =
|
||||
proc addContact*(self: ContactModel, id: string, accountKeyUID: string): string =
|
||||
var contact = self.getOrCreateContact(id)
|
||||
|
||||
let updating = contact.systemTags.contains(contactAdded)
|
||||
|
||||
if not updating:
|
||||
contact.systemTags.add(contactAdded)
|
||||
discard status_chat.createProfileChat(contact.id)
|
||||
|
@ -96,13 +98,9 @@ proc addContact*(self: ContactModel, id: string): string =
|
|||
if (index > -1):
|
||||
contact.systemTags.delete(index)
|
||||
|
||||
var thumbnail = ""
|
||||
if contact.identityImage != nil:
|
||||
thumbnail = contact.identityImage.thumbnail
|
||||
|
||||
result = status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, thumbnail, contact.systemTags, contact.localNickname)
|
||||
result = self.saveContact(contact)
|
||||
self.events.emit("contactAdded", Args())
|
||||
discard requestContactUpdate(contact.id)
|
||||
discard sendContactUpdate(contact.id, accountKeyUID)
|
||||
|
||||
if updating:
|
||||
let profile = Profile(
|
||||
|
@ -122,11 +120,7 @@ proc removeContact*(self: ContactModel, id: string) =
|
|||
let contact = self.getContactByID(id)
|
||||
contact.systemTags.delete(contact.systemTags.find(contactAdded))
|
||||
|
||||
var thumbnail = ""
|
||||
if contact.identityImage != nil:
|
||||
thumbnail = contact.identityImage.thumbnail
|
||||
|
||||
discard status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, thumbnail, contact.systemTags, contact.localNickname)
|
||||
discard self.saveContact(contact)
|
||||
self.events.emit("contactRemoved", Args())
|
||||
|
||||
proc isAdded*(self: ContactModel, id: string): bool =
|
||||
|
@ -143,9 +137,5 @@ proc rejectContactRequest*(self: ContactModel, id: string) =
|
|||
let contact = self.getContactByID(id)
|
||||
contact.systemTags.delete(contact.systemTags.find(contactRequest))
|
||||
|
||||
var thumbnail = ""
|
||||
if contact.identityImage != nil:
|
||||
thumbnail = contact.identityImage.thumbnail
|
||||
|
||||
discard status_contacts.saveContact(contact.id, contact.ensVerified, contact.ensName, contact.alias, contact.identicon, thumbnail, contact.systemTags, contact.localNickname)
|
||||
discard self.saveContact(contact)
|
||||
self.events.emit("contactRemoved", Args())
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import json, strmisc, atomics
|
||||
import core, ../utils
|
||||
import tables, json, strmisc, atomics, sugar, sequtils, json_serialization, chronicles
|
||||
import ./core, ./settings, ./accounts, ../utils, ../types/[profile, setting]
|
||||
|
||||
var
|
||||
contacts {.threadvar.}: JsonNode
|
||||
contacts {.threadvar.}: seq[Profile]
|
||||
contactsIndex {.threadvar.}: Table[string, Profile]
|
||||
contactsInited {.threadvar.}: bool
|
||||
dirty: Atomic[bool]
|
||||
|
||||
|
@ -10,20 +11,35 @@ proc getContactByID*(id: string): string =
|
|||
result = callPrivateRPC("getContactByID".prefix, %* [id])
|
||||
dirty.store(true)
|
||||
|
||||
proc getContacts*(): JsonNode =
|
||||
let cacheIsDirty = (not contactsInited) or dirty.load
|
||||
proc getContacts*(useCache: bool = true): (seq[Profile], bool) =
|
||||
let cacheIsDirty = (not useCache) or (not contactsInited) or dirty.load
|
||||
if not cacheIsDirty:
|
||||
result = contacts
|
||||
return (contacts, true)
|
||||
|
||||
let payload = %* []
|
||||
let response = callPrivateRPC("contacts".prefix, payload).parseJson
|
||||
dirty.store(false)
|
||||
contactsIndex = initTable[string, Profile]()
|
||||
contactsInited = true
|
||||
|
||||
if response["result"].kind == JNull:
|
||||
contacts = @[]
|
||||
return (contacts, false)
|
||||
|
||||
contacts = map(response["result"].getElems(), proc(x: JsonNode): Profile = x.toProfileModel())
|
||||
for contact in contacts:
|
||||
contactsIndex[contact.id] = contact
|
||||
|
||||
return (contacts, false)
|
||||
|
||||
proc getContactsIndex*(): (Table[string, Profile], bool)=
|
||||
let cacheIsDirty = (not contactsInited) or dirty.load
|
||||
|
||||
if not cacheIsDirty:
|
||||
return (contactsIndex, true)
|
||||
else:
|
||||
let payload = %* []
|
||||
let response = callPrivateRPC("contacts".prefix, payload).parseJson
|
||||
if response["result"].kind == JNull:
|
||||
result = %* []
|
||||
else:
|
||||
result = response["result"]
|
||||
dirty.store(false)
|
||||
contacts = result
|
||||
contactsInited = true
|
||||
discard getContacts()
|
||||
return (contactsIndex, false)
|
||||
|
||||
proc saveContact*(id: string, ensVerified: bool, ensName: string, alias: string, identicon: string, thumbnail: string, systemTags: seq[string], localNickname: string): string =
|
||||
let payload = %* [{
|
||||
|
@ -40,6 +56,15 @@ proc saveContact*(id: string, ensVerified: bool, ensName: string, alias: string,
|
|||
result = callPrivateRPC("saveContact".prefix, payload)
|
||||
dirty.store(true)
|
||||
|
||||
proc requestContactUpdate*(publicKey: string): string =
|
||||
result = callPrivateRPC("sendContactUpdate".prefix, %* [publicKey, "", ""])
|
||||
proc sendContactUpdate*(publicKey: string, accountKeyUID: string) : string =
|
||||
let preferredUsername = getSetting[string](Setting.PreferredUsername, "")
|
||||
let usernames = getSetting[seq[string]](Setting.Usernames, @[])
|
||||
var ensName = ""
|
||||
if len(preferredUsername) > 0:
|
||||
ensName = preferredUsername
|
||||
elif len(usernames) >= 1:
|
||||
ensName = usernames[0]
|
||||
|
||||
let identityImage = getIdentityImage(accountKeyUID)
|
||||
result = callPrivateRPC("sendContactUpdate".prefix, %* [publicKey, ensName, identityImage.thumbnail])
|
||||
dirty.store(true)
|
||||
|
|
|
@ -16,7 +16,7 @@ type Profile* = ref object
|
|||
systemTags*: seq[string]
|
||||
|
||||
proc `$`*(self: Profile): string =
|
||||
return fmt"Profile(id:{self.id}, username:{self.username})"
|
||||
return fmt"Profile(id:{self.id}, username:{self.username}, systemTags: {self.systemTags}, ensName: {self.ensName})"
|
||||
|
||||
proc toProfileModel*(profile: JsonNode): Profile =
|
||||
var systemTags: seq[string] = @[]
|
||||
|
|
Loading…
Reference in New Issue