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 {
isChannelPost: Boolean(fwdFrom.channelPost),
channelPostId: fwdFrom.channelPost,
isLinkedChannelPost: Boolean(fwdFrom.channelPost && savedFromPeerId && !isChatWithSelf),
fromChatId: savedFromPeerId || fromId,
fromMessageId: fwdFrom.channelPost || fwdFrom.savedFromMsgId,

View File

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

View File

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

View File

@ -94,6 +94,14 @@ addReducer('openChat', (global, actions, payload) => {
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 (id === currentUserId) {
void callApi('fetchChat', { type: 'self' });

View File

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

View File

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

View File

@ -528,3 +528,24 @@ export function exitMessageSelectMode(global: GlobalState): GlobalState {
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;
}