diff --git a/app/actions/remote/thread.ts b/app/actions/remote/thread.ts index 0549c6ae1de..109dcaf336b 100644 --- a/app/actions/remote/thread.ts +++ b/app/actions/remote/thread.ts @@ -291,7 +291,7 @@ export const syncThreadsIfNeeded = async (serverUrl: string, isCRTEnabled: boole if (teams?.length) { for (const team of teams) { - promises.push(syncTeamThreads(serverUrl, team.id, true, true)); + promises.push(syncTeamThreads(serverUrl, team.id, {excludeDirect: true, fetchOnly: true})); } } @@ -317,7 +317,21 @@ export const syncThreadsIfNeeded = async (serverUrl: string, isCRTEnabled: boole } }; -export const syncTeamThreads = async (serverUrl: string, teamId: string, excludeDirect = false, fetchOnly = false) => { +type SyncThreadOptions = { + excludeDirect?: boolean; + fetchOnly?: boolean; + refresh?: boolean; +} + +export const syncTeamThreads = async ( + serverUrl: string, + teamId: string, + { + excludeDirect = false, + fetchOnly = false, + refresh = false, + }: SyncThreadOptions = {}, +) => { try { const {database, operator} = DatabaseManager.getServerDatabaseAndOperator(serverUrl); const syncData = await getTeamThreadsSyncData(database, teamId); @@ -354,36 +368,53 @@ export const syncTeamThreads = async (serverUrl: string, teamId: string, exclude return {error: allUnreadThreads.error || latestThreads.error}; } - const dedupe = new Set(latestThreads.threads?.map((t) => t.id)); - if (latestThreads.threads?.length) { // We are fetching the threads for the first time. We get "latest" and "earliest" values. + // At this point we may receive threads without replies, so we also check the post.create_at timestamp. const {earliestThread, latestThread} = getThreadsListEdges(latestThreads.threads); - syncDataUpdate.latest = latestThread.last_reply_at; - syncDataUpdate.earliest = earliestThread.last_reply_at; + syncDataUpdate.latest = latestThread.last_reply_at || latestThread.post.create_at; + syncDataUpdate.earliest = earliestThread.last_reply_at || earliestThread.post.create_at; threads.push(...latestThreads.threads); } if (allUnreadThreads.threads?.length) { + const dedupe = new Set(latestThreads.threads?.map((t) => t.id)); const unread = allUnreadThreads.threads.filter((u) => !dedupe.has(u.id)); threads.push(...unread); } } else { - const allNewThreads = await fetchThreads( - serverUrl, - teamId, - {deleted: true, since: syncData.latest + 1, excludeDirect}, - ); + const [allUnreadThreads, allNewThreads] = await Promise.all([ + fetchThreads( + serverUrl, + teamId, + {unread: true, excludeDirect}, + Direction.Down, + ), + fetchThreads( + serverUrl, + teamId, + {deleted: true, since: refresh ? undefined : syncData.latest + 1, excludeDirect}, + undefined, + 1, + ), + ]); + if (allNewThreads.error) { return {error: allNewThreads.error}; } if (allNewThreads.threads?.length) { // As we are syncing, we get all new threads and we will update the "latest" value. const {latestThread} = getThreadsListEdges(allNewThreads.threads); - syncDataUpdate.latest = latestThread.last_reply_at; + const latestDate = latestThread.last_reply_at || latestThread.post.create_at; + syncDataUpdate.latest = Math.max(syncData.latest, latestDate); threads.push(...allNewThreads.threads); } + if (allUnreadThreads.threads?.length) { + const dedupe = new Set(allNewThreads.threads?.map((t) => t.id)); + const unread = allUnreadThreads.threads.filter((u) => !dedupe.has(u.id)); + threads.push(...unread); + } } const models: Model[] = []; diff --git a/app/queries/servers/thread.ts b/app/queries/servers/thread.ts index 287d72209b0..d011171af7e 100644 --- a/app/queries/servers/thread.ts +++ b/app/queries/servers/thread.ts @@ -123,7 +123,7 @@ export const prepareThreadsFromReceivedPosts = async (operator: ServerDataOperat id: post.id, participants: post.participants, reply_count: post.reply_count, - last_reply_at: post.last_reply_at, + last_reply_at: post.last_reply_at || post.create_at, is_following: post.is_following, lastFetchedAt: post.create_at, } as ThreadWithLastFetchedAt); diff --git a/app/screens/global_threads/threads_list/threads_list.tsx b/app/screens/global_threads/threads_list/threads_list.tsx index 665d1e74979..c5b74890ddd 100644 --- a/app/screens/global_threads/threads_list/threads_list.tsx +++ b/app/screens/global_threads/threads_list/threads_list.tsx @@ -126,7 +126,7 @@ const ThreadsList = ({ const handleRefresh = useCallback(() => { setRefreshing(true); - syncTeamThreads(serverUrl, teamId).finally(() => { + syncTeamThreads(serverUrl, teamId, {refresh: true}).finally(() => { setRefreshing(false); }); }, [serverUrl, teamId]); diff --git a/app/utils/thread/index.ts b/app/utils/thread/index.ts index 099411b1943..33bf1c34101 100644 --- a/app/utils/thread/index.ts +++ b/app/utils/thread/index.ts @@ -35,7 +35,9 @@ export function processIsCRTEnabled(preferences: PreferenceModel[]|PreferenceTyp export const getThreadsListEdges = (threads: Thread[]) => { // Sort a clone of 'threads' array by last_reply_at const sortedThreads = [...threads].sort((a, b) => { - return a.last_reply_at - b.last_reply_at; + const aDate = a.last_reply_at || a.post.create_at; + const bDate = b.last_reply_at || b.post.create_at; + return aDate - bDate; }); const earliestThread = sortedThreads[0];