Threads: Fix some threads are loading forever (#1401)

This commit is contained in:
Alexander Zinchuk 2021-08-20 23:46:48 +03:00
parent 851bde515e
commit 48b6a263cf
7 changed files with 90 additions and 22 deletions

View File

@ -242,6 +242,7 @@ function buildApiMessageForwardInfo(fwdFrom: GramJs.MessageFwdHeader, isChatWith
return { return {
isChannelPost: Boolean(fwdFrom.channelPost), isChannelPost: Boolean(fwdFrom.channelPost),
channelPostId: fwdFrom.channelPost,
isLinkedChannelPost: Boolean(fwdFrom.channelPost && savedFromPeerId && !isChatWithSelf), isLinkedChannelPost: Boolean(fwdFrom.channelPost && savedFromPeerId && !isChatWithSelf),
fromChatId: savedFromPeerId || fromId, fromChatId: savedFromPeerId || fromId,
fromMessageId: fwdFrom.channelPost || fwdFrom.savedFromMsgId, fromMessageId: fwdFrom.channelPost || fwdFrom.savedFromMsgId,

View File

@ -173,6 +173,7 @@ export interface ApiWebPage {
export interface ApiMessageForwardInfo { export interface ApiMessageForwardInfo {
isChannelPost: boolean; isChannelPost: boolean;
channelPostId?: number;
isLinkedChannelPost?: boolean; isLinkedChannelPost?: boolean;
fromChatId?: number; fromChatId?: number;
senderUserId?: number; senderUserId?: number;

View File

@ -1,5 +1,5 @@
import React, { import React, {
FC, memo, useCallback, useEffect, FC, memo, useCallback,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { withGlobal } from '../../../lib/teact/teactn';
@ -12,7 +12,7 @@ import { pick } from '../../../util/iteratees';
import { isChatPrivate } from '../../../modules/helpers'; import { isChatPrivate } from '../../../modules/helpers';
import { formatIntegerCompact } from '../../../util/textFormat'; import { formatIntegerCompact } from '../../../util/textFormat';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { selectThreadInfo, selectThreadOriginChat } from '../../../modules/selectors'; import { selectThreadInfo } from '../../../modules/selectors';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import Avatar from '../../common/Avatar'; import Avatar from '../../common/Avatar';
@ -28,19 +28,16 @@ type StateProps = {
threadInfo: ApiThreadInfo; threadInfo: ApiThreadInfo;
usersById?: Record<number, ApiUser>; usersById?: Record<number, ApiUser>;
chatsById?: Record<number, ApiChat>; chatsById?: Record<number, ApiChat>;
shouldRequestThreadUpdate: boolean;
}; };
type DispatchProps = Pick<GlobalActions, 'openChat' | 'requestThreadInfoUpdate'>; type DispatchProps = Pick<GlobalActions, 'openChat'>;
const CommentButton: FC<OwnProps & StateProps & DispatchProps> = ({ const CommentButton: FC<OwnProps & StateProps & DispatchProps> = ({
disabled, disabled,
threadInfo, threadInfo,
usersById, usersById,
chatsById, chatsById,
shouldRequestThreadUpdate,
openChat, openChat,
requestThreadInfoUpdate,
}) => { }) => {
const lang = useLang(); const lang = useLang();
const { const {
@ -51,12 +48,6 @@ const CommentButton: FC<OwnProps & StateProps & DispatchProps> = ({
openChat({ id: chatId, threadId }); openChat({ id: chatId, threadId });
}, [openChat, chatId, threadId]); }, [openChat, chatId, threadId]);
useEffect(() => {
if (shouldRequestThreadUpdate) {
requestThreadInfoUpdate({ chatId, threadId });
}
}, [chatId, requestThreadInfoUpdate, shouldRequestThreadUpdate, threadId]);
if (messagesCount === undefined) { if (messagesCount === undefined) {
return undefined; return undefined;
} }
@ -107,7 +98,6 @@ export default memo(withGlobal<OwnProps>(
const { threadId, chatId } = message.threadInfo!; const { threadId, chatId } = message.threadInfo!;
const threadInfo = selectThreadInfo(global, chatId, threadId) || message.threadInfo!; const threadInfo = selectThreadInfo(global, chatId, threadId) || message.threadInfo!;
const chat = selectThreadOriginChat(global, chatId, threadId);
const { byId: usersById } = global.users; const { byId: usersById } = global.users;
const { byId: chatsById } = global.chats; const { byId: chatsById } = global.chats;
@ -115,11 +105,9 @@ export default memo(withGlobal<OwnProps>(
threadInfo, threadInfo,
usersById, usersById,
chatsById, chatsById,
shouldRequestThreadUpdate: !!chat && !threadInfo.topMessageId,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [ (setGlobal, actions): DispatchProps => pick(actions, [
'openChat', 'openChat',
'requestThreadInfoUpdate',
]), ]),
)(CommentButton)); )(CommentButton));

View File

@ -94,6 +94,14 @@ addReducer('openChat', (global, actions, payload) => {
actions.toggleChatUnread({ id }); actions.toggleChatUnread({ id });
} }
// Please telegram send us some updates about linked chat 🙏
if (chat && chat.lastMessage && chat.lastMessage.threadInfo) {
actions.requestThreadInfoUpdate({
chatId: chat.lastMessage.threadInfo.chatId,
threadId: chat.lastMessage.threadInfo.threadId,
});
}
if (!chat) { if (!chat) {
if (id === currentUserId) { if (id === currentUserId) {
void callApi('fetchChat', { type: 'self' }); void callApi('fetchChat', { type: 'self' });

View File

@ -30,6 +30,7 @@ import {
replaceScheduledMessages, replaceScheduledMessages,
updateThreadInfos, updateThreadInfos,
updateChat, updateChat,
updateThreadUnreadFromForwardedMessage,
} from '../../reducers'; } from '../../reducers';
import { import {
selectChat, selectChat,
@ -145,14 +146,29 @@ async function loadWithBudget(
} }
addReducer('loadMessage', (global, actions, payload) => { addReducer('loadMessage', (global, actions, payload) => {
const { chatId, messageId, replyOriginForId } = payload!; const {
chatId, messageId, replyOriginForId, threadUpdate,
} = payload!;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) { if (!chat) {
return; return;
} }
void loadMessage(chat, messageId, replyOriginForId); (async () => {
const message = await loadMessage(chat, messageId, replyOriginForId);
if (message && threadUpdate) {
const { lastMessageId, isDeleting } = threadUpdate;
setGlobal(updateThreadUnreadFromForwardedMessage(
getGlobal(),
message,
chatId,
lastMessageId,
isDeleting,
));
}
})();
}); });
addReducer('sendMessage', (global, actions, payload) => { addReducer('sendMessage', (global, actions, payload) => {
@ -683,7 +699,7 @@ async function loadViewportMessages(
async function loadMessage(chat: ApiChat, messageId: number, replyOriginForId: number) { async function loadMessage(chat: ApiChat, messageId: number, replyOriginForId: number) {
const result = await callApi('fetchMessage', { chat, messageId }); const result = await callApi('fetchMessage', { chat, messageId });
if (!result) { if (!result) {
return; return undefined;
} }
if (result === MESSAGE_DELETED) { if (result === MESSAGE_DELETED) {
@ -697,13 +713,15 @@ async function loadMessage(chat: ApiChat, messageId: number, replyOriginForId: n
setGlobal(global); setGlobal(global);
} }
return; return undefined;
} }
let global = getGlobal(); let global = getGlobal();
global = updateChatMessage(global, chat.id, messageId, result.message); global = updateChatMessage(global, chat.id, messageId, result.message);
global = addUsers(global, buildCollectionByKey(result.users, 'id')); global = addUsers(global, buildCollectionByKey(result.users, 'id'));
setGlobal(global); setGlobal(global);
return result.message;
} }
function findClosestIndex(sourceIds: number[], offsetId: number) { function findClosestIndex(sourceIds: number[], offsetId: number) {

View File

@ -15,6 +15,7 @@ import {
replaceThreadParam, replaceThreadParam,
updateScheduledMessage, updateScheduledMessage,
deleteChatScheduledMessages, deleteChatScheduledMessages,
updateThreadUnreadFromForwardedMessage,
} from '../../reducers'; } from '../../reducers';
import { GlobalActions, GlobalState } from '../../../global/types'; import { GlobalActions, GlobalState } from '../../../global/types';
import { import {
@ -46,7 +47,7 @@ addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
case 'newMessage': { case 'newMessage': {
const { chatId, id, message } = update; const { chatId, id, message } = update;
global = updateWithLocalMedia(global, chatId, id, message); global = updateWithLocalMedia(global, chatId, id, message);
global = updateListedAndViewportIds(global, message as ApiMessage); global = updateListedAndViewportIds(global, actions, message as ApiMessage);
if (message.threadInfo) { if (message.threadInfo) {
global = updateThreadInfo( global = updateThreadInfo(
@ -157,7 +158,7 @@ addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
case 'updateMessageSendSucceeded': { case 'updateMessageSendSucceeded': {
const { chatId, localId, message } = update; const { chatId, localId, message } = update;
global = updateListedAndViewportIds(global, message as ApiMessage); global = updateListedAndViewportIds(global, actions, message as ApiMessage);
const currentMessage = selectChatMessage(global, chatId, localId); const currentMessage = selectChatMessage(global, chatId, localId);
@ -443,7 +444,31 @@ function updateWithLocalMedia(
: updateChatMessage(global, chatId, id, message); : updateChatMessage(global, chatId, id, message);
} }
function updateListedAndViewportIds(global: GlobalState, message: ApiMessage) { function updateThreadUnread(global: GlobalState, actions: GlobalActions, message: ApiMessage, isDeleting?: boolean) {
const { chatId } = message;
const { threadInfo } = selectThreadByMessage(global, chatId, message) || {};
if (!threadInfo && message.replyToMessageId) {
const originMessage = selectChatMessage(global, chatId, message.replyToMessageId);
if (originMessage) {
global = updateThreadUnreadFromForwardedMessage(global, originMessage, chatId, message.id, isDeleting);
} else {
actions.loadMessage({
chatId,
messageId: message.replyToMessageId,
threadUpdate: {
isDeleting,
lastMessageId: message.id,
},
});
}
}
return global;
}
function updateListedAndViewportIds(global: GlobalState, actions: GlobalActions, message: ApiMessage) {
const { id, chatId } = message; const { id, chatId } = message;
const { threadInfo, firstMessageId } = selectThreadByMessage(global, chatId, message) || {}; const { threadInfo, firstMessageId } = selectThreadByMessage(global, chatId, message) || {};
@ -451,6 +476,8 @@ function updateListedAndViewportIds(global: GlobalState, message: ApiMessage) {
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
const isUnreadChatNotLoaded = chat && chat.unreadCount && !selectListedIds(global, chatId, MAIN_THREAD_ID); const isUnreadChatNotLoaded = chat && chat.unreadCount && !selectListedIds(global, chatId, MAIN_THREAD_ID);
global = updateThreadUnread(global, actions, message);
if (threadInfo) { if (threadInfo) {
if (firstMessageId || !isMessageLocal(message)) { if (firstMessageId || !isMessageLocal(message)) {
global = updateListedIds(global, chatId, threadInfo.threadId, [id]); global = updateListedIds(global, chatId, threadInfo.threadId, [id]);
@ -559,12 +586,16 @@ function deleteMessages(chatId: number | undefined, ids: number[], actions: Glob
return; return;
} }
global = updateThreadUnread(global, actions, message, true);
const { threadInfo } = selectThreadByMessage(global, chatId, message) || {}; const { threadInfo } = selectThreadByMessage(global, chatId, message) || {};
if (threadInfo) { if (threadInfo) {
threadIdsToUpdate.push(threadInfo.threadId); threadIdsToUpdate.push(threadInfo.threadId);
} }
}); });
setGlobal(global);
setTimeout(() => { setTimeout(() => {
setGlobal(deleteChatMessages(getGlobal(), chatId, ids)); setGlobal(deleteChatMessages(getGlobal(), chatId, ids));

View File

@ -528,3 +528,24 @@ export function exitMessageSelectMode(global: GlobalState): GlobalState {
selectedMessages: undefined, selectedMessages: undefined,
}; };
} }
export function updateThreadUnreadFromForwardedMessage(
global: GlobalState,
originMessage: ApiMessage,
chatId: number,
lastMessageId: number,
isDeleting?: boolean,
) {
const { channelPostId, fromChatId } = originMessage.forwardInfo || {};
if (channelPostId && fromChatId) {
const threadInfoOld = selectThreadInfo(global, chatId, channelPostId);
if (threadInfoOld) {
global = replaceThreadParam(global, chatId, channelPostId, 'threadInfo', {
...threadInfoOld,
lastMessageId,
messagesCount: threadInfoOld.messagesCount + (isDeleting ? -1 : 1),
});
}
}
return global;
}