Fix chat forward pagination (#5869)

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
Kristina 2024-06-20 19:37:37 +04:00 committed by GitHub
parent 58af65e29d
commit 30753b4a7a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 23 additions and 16 deletions

View File

@ -17,6 +17,7 @@ import {
type Account, type Account,
type Class, type Class,
type Doc, type Doc,
type DocumentQuery,
getCurrentAccount, getCurrentAccount,
isOtherDay, isOtherDay,
type Ref, type Ref,
@ -31,6 +32,7 @@ import attachment from '@hcengineering/attachment'
import { combineActivityMessages } from '@hcengineering/activity-resources' import { combineActivityMessages } from '@hcengineering/activity-resources'
import chunter from './plugin' import chunter from './plugin'
import { type ChatMessage } from '@hcengineering/chunter'
export type LoadMode = 'forward' | 'backward' export type LoadMode = 'forward' | 'backward'
@ -213,7 +215,7 @@ export class ChannelDataProvider implements IChannelDataProvider {
const start = metadata[startPosition]?.createdOn const start = metadata[startPosition]?.createdOn
if (startPosition === 0) { if (startPosition === 0) {
await this.loadMore('forward', metadata[startPosition]?.createdOn, this.limit, true) await this.loadMore('forward', metadata[startPosition]?.createdOn, this.limit)
} else { } else {
await this.loadMore('backward', start, this.limit / 2) await this.loadMore('backward', start, this.limit / 2)
await this.loadMore('forward', metadata[startPosition - 1]?.createdOn, this.limit / 2) await this.loadMore('forward', metadata[startPosition - 1]?.createdOn, this.limit / 2)
@ -224,7 +226,11 @@ export class ChannelDataProvider implements IChannelDataProvider {
this.isInitialLoadedStore.set(true) this.isInitialLoadedStore.set(true)
} }
private loadTail (start?: Timestamp, afterLoad?: (msgs: ActivityMessage[]) => Promise<ActivityMessage[]>): void { private loadTail (
start?: Timestamp,
afterLoad?: (msgs: ActivityMessage[]) => Promise<ActivityMessage[]>,
query?: DocumentQuery<ActivityMessage>
): void {
if (this.chatId === undefined) { if (this.chatId === undefined) {
this.isTailLoading.set(false) this.isTailLoading.set(false)
return return
@ -238,6 +244,7 @@ export class ChannelDataProvider implements IChannelDataProvider {
this.msgClass, this.msgClass,
{ {
attachedTo: this.chatId, attachedTo: this.chatId,
...query,
...(this.tailStart !== undefined ? { createdOn: { $gte: this.tailStart } } : {}) ...(this.tailStart !== undefined ? { createdOn: { $gte: this.tailStart } } : {})
}, },
async (res) => { async (res) => {
@ -259,7 +266,7 @@ export class ChannelDataProvider implements IChannelDataProvider {
) )
} }
public async loadMore (mode: LoadMode, loadAfter?: Timestamp, limit?: number, loadEqual = false): Promise<void> { public async loadMore (mode: LoadMode, loadAfter?: Timestamp, limit?: number): Promise<void> {
if (this.chatId === undefined || loadAfter === undefined) { if (this.chatId === undefined || loadAfter === undefined) {
return return
} }
@ -273,13 +280,21 @@ export class ChannelDataProvider implements IChannelDataProvider {
const isBackward = mode === 'backward' const isBackward = mode === 'backward'
const isForward = mode === 'forward' const isForward = mode === 'forward'
const chunks = get(this.chunksStore)
const tail = get(this.tailStore)
const lastChunk: Chunk | undefined = isBackward ? chunks[0] : chunks[chunks.length - 1]
const skipIds = (lastChunk?.data ?? [])
.concat(tail)
.filter(({ createdOn }) => createdOn === loadAfter)
.map(({ _id }) => _id) as Array<Ref<ChatMessage>>
if (isForward) { if (isForward) {
const metadata = get(this.metadataStore) const metadata = get(this.metadataStore)
const metaIndex = metadata.findIndex(({ createdOn }) => createdOn === loadAfter) const metaIndex = metadata.findIndex(({ createdOn }) => createdOn === loadAfter)
const shouldLoadTail = metaIndex >= 0 && metaIndex + this.limit >= metadata.length const shouldLoadTail = metaIndex >= 0 && metaIndex + this.limit >= metadata.length
if (shouldLoadTail) { if (shouldLoadTail) {
this.loadTail(metadata[metaIndex + 1]?.createdOn) this.loadTail(metadata[metaIndex + 1]?.createdOn, undefined, { _id: { $nin: skipIds } })
this.isLoadingMoreStore.set(false) this.isLoadingMoreStore.set(false)
return return
} }
@ -290,14 +305,8 @@ export class ChannelDataProvider implements IChannelDataProvider {
chunter.class.ChatMessage, chunter.class.ChatMessage,
{ {
attachedTo: this.chatId, attachedTo: this.chatId,
hidden: { $ne: true }, _id: { $nin: skipIds },
createdOn: isBackward createdOn: isBackward ? { $lte: loadAfter } : { $gte: loadAfter }
? loadEqual
? { $lte: loadAfter }
: { $lt: loadAfter }
: loadEqual
? { $gte: loadAfter }
: { $gt: loadAfter }
}, },
{ {
limit: limit ?? this.limit, limit: limit ?? this.limit,
@ -322,8 +331,6 @@ export class ChannelDataProvider implements IChannelDataProvider {
data: isBackward ? messages.reverse() : messages data: isBackward ? messages.reverse() : messages
} }
const chunks = get(this.chunksStore)
this.chunksStore.set(isBackward ? [chunk, ...chunks] : [...chunks, chunk]) this.chunksStore.set(isBackward ? [chunk, ...chunks] : [...chunks, chunk])
this.isLoadingMoreStore.set(false) this.isLoadingMoreStore.set(false)
} }

View File

@ -55,7 +55,7 @@
const dateSelectorHeight = 30 const dateSelectorHeight = 30
const headerHeight = 52 const headerHeight = 52
const minMsgHeightRem = 4.375 const minMsgHeightRem = 2
const client = getClient() const client = getClient()
const inboxClient = InboxNotificationsClientImpl.getClient() const inboxClient = InboxNotificationsClientImpl.getClient()
@ -236,7 +236,7 @@
const { scrollHeight, scrollTop, clientHeight } = scrollElement const { scrollHeight, scrollTop, clientHeight } = scrollElement
return scrollTop + clientHeight === scrollHeight return Math.ceil(scrollTop + clientHeight) === scrollHeight
} }
let scrollToRestore = 0 let scrollToRestore = 0