feat(@desktop/chat): display fetch messages when needed

- it only applies to community chats

closes: #6731
This commit is contained in:
Patryk Osmaczko 2022-09-05 10:25:18 +02:00 committed by osmaczko
parent 98b4aa849e
commit 1218de67b9
6 changed files with 81 additions and 6 deletions

View File

@ -176,6 +176,12 @@ proc init*(self: Controller) =
return
self.delegate.onChatMemberUpdated(args.id, args.admin, args.joined)
self.events.on(SIGNAL_MAILSERVER_SYNCED) do(e: Args):
let args = MailserverSyncedArgs(e)
if (args.chatId != self.chatId):
return
self.delegate.onMailserverSynced(args.syncedFrom)
proc getMySectionId*(self: Controller): string =
return self.sectionId

View File

@ -21,6 +21,9 @@ method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
method updateChatIdentifier*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method updateChatFetchMoreMessages*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method newMessagesLoaded*(self: AccessInterface, messages: seq[MessageDto], reactions: seq[ReactionDto],
pinnedMessages: seq[PinnedMessageDto]) {.base.} =
raise newException(ValueError, "No implementation available")
@ -79,7 +82,7 @@ method getSectionId*(self: AccessInterface): string {.base.} =
method getChatId*(self: AccessInterface): string {.base.} =
raise newException(ValueError, "No implementation available")
method getChatType*(self: AccessInterface): int {.base.} =
raise newException(ValueError, "No implementation available")
@ -129,4 +132,7 @@ method didIJoinedChat*(self: AccessInterface): bool {.base.} =
raise newException(ValueError, "No implementation available")
method getMessages*(self: AccessInterface): seq[message_item.Item] =
raise newException(ValueError, "No implementation available")
raise newException(ValueError, "No implementation available")
method onMailserverSynced*(self: AccessInterface, syncedFrom: int64) =
raise newException(ValueError, "No implementation available")

View File

@ -60,7 +60,8 @@ method isLoaded*(self: Module): bool =
return self.moduleLoaded
method viewDidLoad*(self: Module) =
self.view.model().appendItem(self.createFetchMoreMessagesItem())
if self.controller.getChatDetails().hasMoreMessagesToRequest():
self.view.model().appendItem(self.createFetchMoreMessagesItem())
self.view.model().appendItem(self.createChatIdentifierItem())
self.moduleLoaded = true
@ -237,7 +238,8 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
# messages are sorted from the most recent to the least recent one
viewItems.add(item)
viewItems.add(self.createFetchMoreMessagesItem())
if self.controller.getChatDetails().hasMoreMessagesToRequest():
viewItems.add(self.createFetchMoreMessagesItem())
viewItems.add(self.createChatIdentifierItem())
self.view.model().removeItem(FETCH_MORE_MESSAGES_MESSAGE_ID)
self.view.model().removeItem(CHAT_IDENTIFIER_MESSAGE_ID)
@ -466,6 +468,12 @@ method updateChatIdentifier*(self: Module) =
# Add new loaded messages
self.view.model().appendItem(self.createChatIdentifierItem())
method updateChatFetchMoreMessages*(self: Module) =
self.view.model().removeItem(FETCH_MORE_MESSAGES_MESSAGE_ID)
if (self.controller.getChatDetails().hasMoreMessagesToRequest()):
self.view.model().appendItem(self.createFetchMoreMessagesItem())
method getLinkPreviewData*(self: Module, link: string, uuid: string): string =
return self.controller.getLinkPreviewData(link, uuid)
@ -507,3 +515,8 @@ method onChatMemberUpdated*(self: Module, publicKey: string, admin: bool, joined
method getMessages*(self: Module): seq[message_item.Item] =
return self.view.model().items
method onMailserverSynced*(self: Module, syncedFrom: int64) =
let chatDto = self.controller.getChatDetails()
if (not chatDto.hasMoreMessagesToRequest(syncedFrom)):
self.view.model().removeItem(FETCH_MORE_MESSAGES_MESSAGE_ID)

View File

@ -340,6 +340,7 @@ method onNotificationsUpdated*(self: Module, hasUnreadMessages: bool, notificati
method onChatEdited*(self: Module, chatDto: ChatDto) =
self.view.updateChatDetails(chatDto.name, chatDto.description, chatDto.emoji, chatDto.color, chatDto.icon, chatDto.chatType == ChatType.OneToOne)
self.messagesModule.updateChatFetchMoreMessages()
self.messagesModule.updateChatIdentifier()
method onChatRenamed*(self: Module, newName: string) =

View File

@ -75,6 +75,7 @@ type ChatDto* = object
joined*: int64 # indicates when the user joined the chat last time
syncedTo*: int64
syncedFrom*: int64
firstMessageTimestamp: int64 # valid only for community chats, 0 - undefined, 1 - no messages, >1 valid timestamps
canPost*: bool
position*: int
categoryId*: string
@ -132,6 +133,7 @@ proc `$`*(self: ChatDto): string =
canPost: {self.canPost},
syncedTo: {self.syncedTo},
syncedFrom: {self.syncedFrom},
firstMessageTimestamp: {self.firstMessageTimestamp},
categoryId: {self.categoryId},
position: {self.position},
highlight: {self.highlight}
@ -219,6 +221,7 @@ proc toChatDto*(jsonObj: JsonNode): ChatDto =
discard jsonObj.getProp("joined", result.joined)
discard jsonObj.getProp("syncedTo", result.syncedTo)
discard jsonObj.getProp("syncedFrom", result.syncedFrom)
discard jsonObj.getProp("firstMessageTimestamp", result.firstMessageTimestamp)
discard jsonObj.getProp("highlight", result.highlight)
var permissionObj: JsonNode
if(jsonObj.getProp("permissions", permissionObj)):
@ -309,3 +312,21 @@ proc isPublicChat*(chatDto: ChatDto): bool =
proc isOneToOneChat*(chatDto: ChatDto): bool =
return chatDto.chatType == ChatType.OneToOne
proc hasMoreMessagesToRequest*(chatDto: ChatDto, syncedFrom: int64): bool =
# only for community chat we can determine the first message ever sent to the chat
if chatDto.chatType != ChatType.CommunityChat:
return true
const firstMessageTimestampUndefined = 0
const firstMessageTimestampNoMessages = 1
if chatDto.firstMessageTimestamp == firstMessageTimestampUndefined:
return true
if chatDto.firstMessageTimestamp == firstMessageTimestampNoMessages:
return false
return syncedFrom > chatDto.firstMessageTimestamp
proc hasMoreMessagesToRequest*(chatDto: ChatDto): bool =
chatDto.hasMoreMessagesToRequest(chatDto.syncedFrom)

View File

@ -22,6 +22,10 @@ type
MailserverAvailableArgs* = ref object of Args
MailserverSyncedArgs* = ref object of Args
chatId*: string
syncedFrom*: int64
RequestMoreMessagesTaskArg = ref object of QObjectTaskArg
chatId*: string
@ -33,12 +37,27 @@ type
const SIGNAL_ACTIVE_MAILSERVER_CHANGED* = "activeMailserverChanged"
const SIGNAL_MAILSERVER_AVAILABLE* = "mailserverAvailable"
const SIGNAL_MAILSERVER_NOT_WORKING* = "mailserverNotWorking"
const SIGNAL_MAILSERVER_SYNCED* = "mailserverSynced"
const requestMoreMessagesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[RequestMoreMessagesTaskArg](argEncoded)
try:
info "Requesting additional message history for chat", chatId=arg.chatId
discard status_mailservers.syncChatFromSyncedFrom(arg.chatId)
let response = status_mailservers.syncChatFromSyncedFrom(arg.chatId)
if(not response.error.isNil):
error "Could not request additional messages due to error", errDescription = response.error.message
let syncedFrom = response.result.getInt()
if(syncedFrom != 0):
let resultJson = %* {
"chatId": arg.chatId,
"syncedFrom": syncedFrom
}
arg.finish(%resultJson)
else:
warn "Syncing mailserver failed", errDescription=arg.chatId
except Exception as e:
warn "Could not request additional messages due to error", errDescription=e.msg
@ -88,11 +107,20 @@ QtObject:
let fleet = self.settingsService.getFleet()
discard self.settingsService.pinMailserver(MAILSERVER_ADDRESS, fleet)
proc mailserverSynced*(self: Service, syncInfo: string) {.slot.} =
let syncInfoParsed = parseJson(syncInfo)
let signalData = MailserverSyncedArgs(
chatId: syncInfoParsed["chatId"].getStr(),
syncedFrom: syncInfoParsed["syncedFrom"].getInt()
)
self.events.emit(SIGNAL_MAILSERVER_SYNCED, signalData)
proc requestMoreMessages*(self: Service, chatId: string) =
let arg = RequestMoreMessagesTaskArg(
tptr: cast[ByteAddress](requestMoreMessagesTask),
vptr: cast[ByteAddress](self.vptr),
chatId: chatId
chatId: chatId,
slot: "mailserverSynced"
)
self.threadpool.start(arg)