diff --git a/src/api/gramjs/apiBuilders/messages.ts b/src/api/gramjs/apiBuilders/messages.ts index 1103120a5..12b39124d 100644 --- a/src/api/gramjs/apiBuilders/messages.ts +++ b/src/api/gramjs/apiBuilders/messages.ts @@ -1359,6 +1359,8 @@ export function buildLocalForwardedMessage({ isInAlbum, isForwardingAllowed: true, replyToTopMessageId: toThreadId, + ...(toThreadId && toChat?.isForum && { isTopicReply: true }), + ...(emojiOnlyCount && { emojiOnlyCount }), // Forward info doesn't get added when users forwards his own messages, also when forwarding audio ...(message.chatId !== currentUserId && !isAudio && !noAuthors && { diff --git a/src/api/types/chats.ts b/src/api/types/chats.ts index 21c31e823..cb07da3f8 100644 --- a/src/api/types/chats.ts +++ b/src/api/types/chats.ts @@ -41,6 +41,7 @@ export interface ApiChat { fakeType?: ApiFakeType; isForum?: boolean; topics?: Record; + listedTopicIds?: number[]; topicsCount?: number; orderedPinnedTopicIds?: number[]; diff --git a/src/components/left/main/Chat.tsx b/src/components/left/main/Chat.tsx index 396c71151..961743f1d 100644 --- a/src/components/left/main/Chat.tsx +++ b/src/components/left/main/Chat.tsx @@ -198,7 +198,7 @@ const Chat: FC = ({ // Load the forum topics to display unread count badge useEffect(() => { - if (isIntersecting && lastSyncTime && isForum && chat && chat.topics === undefined) { + if (isIntersecting && lastSyncTime && isForum && chat && chat.listedTopicIds === undefined) { loadTopics({ chatId }); } }, [chat, chatId, isForum, isIntersecting, lastSyncTime, loadTopics]); diff --git a/src/global/actions/api/chats.ts b/src/global/actions/api/chats.ts index 16b5974b6..4f433054e 100644 --- a/src/global/actions/api/chats.ts +++ b/src/global/actions/api/chats.ts @@ -41,7 +41,7 @@ import { updateTopics, deleteTopic, updateTopic, - updateThreadInfo, + updateThreadInfo, updateListedTopicIds, } from '../../reducers'; import { selectChat, selectUser, selectChatListType, selectIsChatPinned, @@ -1338,18 +1338,22 @@ addActionHandler('loadTopics', async (global, actions, payload) => { const chat = selectChat(global, chatId); if (!chat) return; - if (!force && chat.topics && Object.values(chat.topics).length === chat.topicsCount) { + if (!force && chat.listedTopicIds && chat.listedTopicIds.length === chat.topicsCount) { return; } - const offsetTopic = !force && chat.topics ? Object.values(chat.topics).reduce((acc, el) => { - if (!acc || el.lastMessageId < acc.lastMessageId) { + const offsetTopic = !force && chat.listedTopicIds ? chat.listedTopicIds.reduce((acc, el) => { + const topic = chat.topics?.[el]; + const accTopic = chat.topics?.[acc]; + if (!topic) return acc; + if (!accTopic || topic.lastMessageId < accTopic.lastMessageId) { return el; } return acc; }) : undefined; - const { id: offsetTopicId, date: offsetDate, lastMessageId: offsetId } = offsetTopic || {}; + const { id: offsetTopicId, date: offsetDate, lastMessageId: offsetId } = (offsetTopic + && chat.topics?.[offsetTopic]) || {}; const result = await callApi('fetchTopics', { chat, offsetTopicId, offsetId, offsetDate, limit: offsetTopicId ? TOPICS_SLICE : TOPICS_SLICE_SECOND_LOAD, }); @@ -1361,6 +1365,7 @@ addActionHandler('loadTopics', async (global, actions, payload) => { global = addChats(global, buildCollectionByKey(result.chats, 'id')); global = addMessages(global, result.messages); global = updateTopics(global, chatId, result.count, result.topics); + global = updateListedTopicIds(global, chatId, result.topics.map((topic) => topic.id)); Object.entries(result.draftsById || {}).forEach(([threadId, draft]) => { global = replaceThreadParam(global, chatId, Number(threadId), 'draft', draft?.formattedText); global = replaceThreadParam(global, chatId, Number(threadId), 'replyingToId', draft?.replyingToId); diff --git a/src/global/actions/apiUpdaters/messages.ts b/src/global/actions/apiUpdaters/messages.ts index 7cd2d6c7d..0e1c45a25 100644 --- a/src/global/actions/apiUpdaters/messages.ts +++ b/src/global/actions/apiUpdaters/messages.ts @@ -769,6 +769,13 @@ function updateChatLastMessage( const chat = chats.byId[chatId]; const currentLastMessage = chat?.lastMessage; + const topic = chat?.isForum ? selectTopicFromMessage(global, message) : undefined; + if (topic) { + global = updateTopic(global, chatId, topic.id, { + lastMessageId: message.id, + }); + } + if (currentLastMessage && !force) { const isSameOrNewer = ( currentLastMessage.id === message.id || currentLastMessage.id === message.previousLocalId @@ -780,12 +787,6 @@ function updateChatLastMessage( } global = updateChat(global, chatId, { lastMessage: message }); - const topic = chat?.isForum ? selectTopicFromMessage(global, message) : undefined; - if (topic) { - global = updateTopic(global, chatId, topic.id, { - lastMessageId: message.id, - }); - } return global; } diff --git a/src/global/reducers/chats.ts b/src/global/reducers/chats.ts index b7912d3f3..7dfb3601f 100644 --- a/src/global/reducers/chats.ts +++ b/src/global/reducers/chats.ts @@ -5,7 +5,7 @@ import type { import { ARCHIVED_FOLDER_ID } from '../../config'; import { - areSortedArraysEqual, buildCollectionByKey, omit, + areSortedArraysEqual, buildCollectionByKey, omit, unique, } from '../../util/iteratees'; import { selectChat, selectChatListType } from '../selectors'; import { updateThread, updateThreadInfo } from './messages'; @@ -252,6 +252,17 @@ export function addChatMembers(global: GlobalState, chat: ApiChat, membersToAdd: }); } +export function updateListedTopicIds( + global: GlobalState, chatId: string, topicIds: number[], +): GlobalState { + return updateChat(global, chatId, { + listedTopicIds: unique([ + ...(global.chats.byId[chatId]?.listedTopicIds || []), + ...topicIds, + ]), + }); +} + export function updateTopics( global: GlobalState, chatId: string, topicsCount: number, topics: ApiTopic[], ): GlobalState {