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 return
self.delegate.onChatMemberUpdated(args.id, args.admin, args.joined) 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 = proc getMySectionId*(self: Controller): string =
return self.sectionId return self.sectionId

View File

@ -21,6 +21,9 @@ method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
method updateChatIdentifier*(self: AccessInterface) {.base.} = method updateChatIdentifier*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available") 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], method newMessagesLoaded*(self: AccessInterface, messages: seq[MessageDto], reactions: seq[ReactionDto],
pinnedMessages: seq[PinnedMessageDto]) {.base.} = pinnedMessages: seq[PinnedMessageDto]) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
@ -130,3 +133,6 @@ method didIJoinedChat*(self: AccessInterface): bool {.base.} =
method getMessages*(self: AccessInterface): seq[message_item.Item] = 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,6 +60,7 @@ method isLoaded*(self: Module): bool =
return self.moduleLoaded return self.moduleLoaded
method viewDidLoad*(self: Module) = method viewDidLoad*(self: Module) =
if self.controller.getChatDetails().hasMoreMessagesToRequest():
self.view.model().appendItem(self.createFetchMoreMessagesItem()) self.view.model().appendItem(self.createFetchMoreMessagesItem())
self.view.model().appendItem(self.createChatIdentifierItem()) self.view.model().appendItem(self.createChatIdentifierItem())
@ -237,6 +238,7 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
# messages are sorted from the most recent to the least recent one # messages are sorted from the most recent to the least recent one
viewItems.add(item) viewItems.add(item)
if self.controller.getChatDetails().hasMoreMessagesToRequest():
viewItems.add(self.createFetchMoreMessagesItem()) viewItems.add(self.createFetchMoreMessagesItem())
viewItems.add(self.createChatIdentifierItem()) viewItems.add(self.createChatIdentifierItem())
self.view.model().removeItem(FETCH_MORE_MESSAGES_MESSAGE_ID) self.view.model().removeItem(FETCH_MORE_MESSAGES_MESSAGE_ID)
@ -466,6 +468,12 @@ method updateChatIdentifier*(self: Module) =
# Add new loaded messages # Add new loaded messages
self.view.model().appendItem(self.createChatIdentifierItem()) 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 = method getLinkPreviewData*(self: Module, link: string, uuid: string): string =
return self.controller.getLinkPreviewData(link, uuid) 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] = method getMessages*(self: Module): seq[message_item.Item] =
return self.view.model().items 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) = method onChatEdited*(self: Module, chatDto: ChatDto) =
self.view.updateChatDetails(chatDto.name, chatDto.description, chatDto.emoji, chatDto.color, chatDto.icon, chatDto.chatType == ChatType.OneToOne) self.view.updateChatDetails(chatDto.name, chatDto.description, chatDto.emoji, chatDto.color, chatDto.icon, chatDto.chatType == ChatType.OneToOne)
self.messagesModule.updateChatFetchMoreMessages()
self.messagesModule.updateChatIdentifier() self.messagesModule.updateChatIdentifier()
method onChatRenamed*(self: Module, newName: string) = 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 joined*: int64 # indicates when the user joined the chat last time
syncedTo*: int64 syncedTo*: int64
syncedFrom*: int64 syncedFrom*: int64
firstMessageTimestamp: int64 # valid only for community chats, 0 - undefined, 1 - no messages, >1 valid timestamps
canPost*: bool canPost*: bool
position*: int position*: int
categoryId*: string categoryId*: string
@ -132,6 +133,7 @@ proc `$`*(self: ChatDto): string =
canPost: {self.canPost}, canPost: {self.canPost},
syncedTo: {self.syncedTo}, syncedTo: {self.syncedTo},
syncedFrom: {self.syncedFrom}, syncedFrom: {self.syncedFrom},
firstMessageTimestamp: {self.firstMessageTimestamp},
categoryId: {self.categoryId}, categoryId: {self.categoryId},
position: {self.position}, position: {self.position},
highlight: {self.highlight} highlight: {self.highlight}
@ -219,6 +221,7 @@ proc toChatDto*(jsonObj: JsonNode): ChatDto =
discard jsonObj.getProp("joined", result.joined) discard jsonObj.getProp("joined", result.joined)
discard jsonObj.getProp("syncedTo", result.syncedTo) discard jsonObj.getProp("syncedTo", result.syncedTo)
discard jsonObj.getProp("syncedFrom", result.syncedFrom) discard jsonObj.getProp("syncedFrom", result.syncedFrom)
discard jsonObj.getProp("firstMessageTimestamp", result.firstMessageTimestamp)
discard jsonObj.getProp("highlight", result.highlight) discard jsonObj.getProp("highlight", result.highlight)
var permissionObj: JsonNode var permissionObj: JsonNode
if(jsonObj.getProp("permissions", permissionObj)): if(jsonObj.getProp("permissions", permissionObj)):
@ -309,3 +312,21 @@ proc isPublicChat*(chatDto: ChatDto): bool =
proc isOneToOneChat*(chatDto: ChatDto): bool = proc isOneToOneChat*(chatDto: ChatDto): bool =
return chatDto.chatType == ChatType.OneToOne 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 MailserverAvailableArgs* = ref object of Args
MailserverSyncedArgs* = ref object of Args
chatId*: string
syncedFrom*: int64
RequestMoreMessagesTaskArg = ref object of QObjectTaskArg RequestMoreMessagesTaskArg = ref object of QObjectTaskArg
chatId*: string chatId*: string
@ -33,12 +37,27 @@ type
const SIGNAL_ACTIVE_MAILSERVER_CHANGED* = "activeMailserverChanged" const SIGNAL_ACTIVE_MAILSERVER_CHANGED* = "activeMailserverChanged"
const SIGNAL_MAILSERVER_AVAILABLE* = "mailserverAvailable" const SIGNAL_MAILSERVER_AVAILABLE* = "mailserverAvailable"
const SIGNAL_MAILSERVER_NOT_WORKING* = "mailserverNotWorking" const SIGNAL_MAILSERVER_NOT_WORKING* = "mailserverNotWorking"
const SIGNAL_MAILSERVER_SYNCED* = "mailserverSynced"
const requestMoreMessagesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = const requestMoreMessagesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[RequestMoreMessagesTaskArg](argEncoded) let arg = decode[RequestMoreMessagesTaskArg](argEncoded)
try: try:
info "Requesting additional message history for chat", chatId=arg.chatId 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: except Exception as e:
warn "Could not request additional messages due to error", errDescription=e.msg warn "Could not request additional messages due to error", errDescription=e.msg
@ -88,11 +107,20 @@ QtObject:
let fleet = self.settingsService.getFleet() let fleet = self.settingsService.getFleet()
discard self.settingsService.pinMailserver(MAILSERVER_ADDRESS, fleet) 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) = proc requestMoreMessages*(self: Service, chatId: string) =
let arg = RequestMoreMessagesTaskArg( let arg = RequestMoreMessagesTaskArg(
tptr: cast[ByteAddress](requestMoreMessagesTask), tptr: cast[ByteAddress](requestMoreMessagesTask),
vptr: cast[ByteAddress](self.vptr), vptr: cast[ByteAddress](self.vptr),
chatId: chatId chatId: chatId,
slot: "mailserverSynced"
) )
self.threadpool.start(arg) self.threadpool.start(arg)