diff --git a/lib/reducers/message-reducer.js b/lib/reducers/message-reducer.js --- a/lib/reducers/message-reducer.js +++ b/lib/reducers/message-reducer.js @@ -607,6 +607,31 @@ updatedThreads[threadID] = threads[threadID]; } + // We don't want to persist an information about startReached for thick + // thread containing more than defaultNumberPerThread messages. The reason + // is that after closing and reopening the app, we're fetching only a subset + // of messages. If we read startReached = true from the DB, we won't attempt + // fetching more batches of messages. + const dbOps = [ + ...newMessageOps, + { + type: 'replace_threads', + payload: { + threads: Object.fromEntries( + Object.entries(updatedThreads).map(([threadID, thread]) => [ + threadID, + threadInfos[threadID].thick + ? { + ...thread, + startReached: + thread.messageIDs.length < defaultNumberPerThread, + } + : thread, + ]), + ), + }, + }, + ]; newMessageOps.push({ type: 'replace_threads', payload: { @@ -641,10 +666,7 @@ }; return { - messageStoreOperations: [ - ...updateWithLatestThreadInfosOps, - ...newMessageOps, - ], + messageStoreOperations: [...updateWithLatestThreadInfosOps, ...dbOps], messageStore, }; } diff --git a/lib/shared/message-utils.js b/lib/shared/message-utils.js --- a/lib/shared/message-utils.js +++ b/lib/shared/message-utils.js @@ -27,17 +27,20 @@ import { type PlatformDetails } from '../types/device-types.js'; import type { Media } from '../types/media-types.js'; import { messageTypes } from '../types/message-types-enum.js'; -import type { - ComposableMessageInfo, - MessageData, - MessageInfo, - MessageStore, - MultimediaMessageData, - RawComposableMessageInfo, - RawMessageInfo, - RawMultimediaMessageInfo, - RobotextMessageInfo, - ThreadMessageInfo, +import { + type ComposableMessageInfo, + type FetchMessageInfosPayload, + type MessageData, + type MessageInfo, + type MessageStore, + type MultimediaMessageData, + type RawComposableMessageInfo, + type RawMessageInfo, + type RawMultimediaMessageInfo, + type RobotextMessageInfo, + type ThreadMessageInfo, + defaultNumberPerThread, + messageTruncationStatus, } from '../types/message-types.js'; import type { EditMessageInfo, @@ -56,11 +59,13 @@ import { threadTypeIsThick } from '../types/thread-types-enum.js'; import type { LegacyRawThreadInfo } from '../types/thread-types.js'; import type { UserInfos } from '../types/user-types.js'; +import { getConfig } from '../utils/config.js'; import { type EntityText, ET, useEntityTextAsString, } from '../utils/entity-text.js'; +import { translateClientDBMessageInfoToRawMessageInfo } from '../utils/message-ops-utils.js'; import { useDispatchActionPromise } from '../utils/redux-promise-utils.js'; import { useSelector } from '../utils/redux-utils.js'; @@ -685,6 +690,29 @@ return timePerKeyserver; } +async function fetchThickThreadMessages( + threadID: string, + limit: number, + offset: number, +): Promise { + const { sqliteAPI } = getConfig(); + const dbMessages = await sqliteAPI.fetchMessages(threadID, limit + 1, offset); + const isFetchExhaustive = dbMessages.length !== limit + 1; + const messagesToReturn = isFetchExhaustive + ? dbMessages + : dbMessages.slice(0, -1); + const messages = messagesToReturn.map( + translateClientDBMessageInfoToRawMessageInfo, + ); + return { + threadID, + rawMessageInfos: messages, + truncationStatus: isFetchExhaustive + ? messageTruncationStatus.EXHAUSTIVE + : messageTruncationStatus.UNCHANGED, + }; +} + function useFetchMessages(threadInfo: ThreadInfo): () => Promise { const oldestMessageServerID = useOldestMessageServerID(threadInfo.id); const callFetchMessagesBeforeCursor = useFetchMessagesBeforeCursor(); @@ -696,9 +724,25 @@ registerFetchKey(fetchMostRecentMessagesActionTypes); }, []); + const threadID = threadInfo.id; + const messageIDs = useSelector( + state => state.messageStore.threads[threadID].messageIDs, + ); + return React.useCallback(async () => { - const threadID = threadInfo.id; if (threadTypeIsThick(threadInfo.type)) { + const promise = (async () => { + const currentNumberOfFetchedMessages = messageIDs?.length ?? 0; + return await fetchThickThreadMessages( + threadID, + defaultNumberPerThread, + currentNumberOfFetchedMessages, + ); + })(); + await dispatchActionPromise( + fetchMessagesBeforeCursorActionTypes, + promise, + ); return; } if (oldestMessageServerID) { @@ -719,8 +763,9 @@ callFetchMessagesBeforeCursor, callFetchMostRecentMessages, dispatchActionPromise, + messageIDs?.length, oldestMessageServerID, - threadInfo.id, + threadID, threadInfo.type, ]); }