Threads: Fix some threads are loading forever (#1401)
This commit is contained in:
parent
851bde515e
commit
48b6a263cf
@ -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,
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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));
|
||||||
|
|||||||
@ -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' });
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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));
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user