diff --git a/src/app/modules/main/chat_section/chat_content/messages/controller.nim b/src/app/modules/main/chat_section/chat_content/messages/controller.nim index fcffedb926..42093228bb 100644 --- a/src/app/modules/main/chat_section/chat_content/messages/controller.nim +++ b/src/app/modules/main/chat_section/chat_content/messages/controller.nim @@ -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 diff --git a/src/app/modules/main/chat_section/chat_content/messages/io_interface.nim b/src/app/modules/main/chat_section/chat_content/messages/io_interface.nim index acdbb08955..08b04068a3 100644 --- a/src/app/modules/main/chat_section/chat_content/messages/io_interface.nim +++ b/src/app/modules/main/chat_section/chat_content/messages/io_interface.nim @@ -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") \ No newline at end of file + raise newException(ValueError, "No implementation available") + +method onMailserverSynced*(self: AccessInterface, syncedFrom: int64) = + raise newException(ValueError, "No implementation available") diff --git a/src/app/modules/main/chat_section/chat_content/messages/module.nim b/src/app/modules/main/chat_section/chat_content/messages/module.nim index 8cd4080d5d..6f34add995 100644 --- a/src/app/modules/main/chat_section/chat_content/messages/module.nim +++ b/src/app/modules/main/chat_section/chat_content/messages/module.nim @@ -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) diff --git a/src/app/modules/main/chat_section/chat_content/module.nim b/src/app/modules/main/chat_section/chat_content/module.nim index 65b0d7fcc9..2d50642682 100644 --- a/src/app/modules/main/chat_section/chat_content/module.nim +++ b/src/app/modules/main/chat_section/chat_content/module.nim @@ -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) = diff --git a/src/app_service/service/chat/dto/chat.nim b/src/app_service/service/chat/dto/chat.nim index 59b7c0e540..f9068776b0 100644 --- a/src/app_service/service/chat/dto/chat.nim +++ b/src/app_service/service/chat/dto/chat.nim @@ -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) diff --git a/src/app_service/service/mailservers/service.nim b/src/app_service/service/mailservers/service.nim index af497f0278..2e2cd0b5ea 100644 --- a/src/app_service/service/mailservers/service.nim +++ b/src/app_service/service/mailservers/service.nim @@ -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)