Comments: Fix thread bugs (#6698)
This commit is contained in:
parent
fec5e07b7d
commit
fc498a222b
@ -2,7 +2,9 @@ import { Api as GramJs } from '../../../lib/gramjs';
|
|||||||
|
|
||||||
import type {
|
import type {
|
||||||
ApiAttachment,
|
ApiAttachment,
|
||||||
|
ApiBaseThreadInfo,
|
||||||
ApiChat,
|
ApiChat,
|
||||||
|
ApiCommentsInfo,
|
||||||
ApiContact,
|
ApiContact,
|
||||||
ApiDice,
|
ApiDice,
|
||||||
ApiDraft,
|
ApiDraft,
|
||||||
@ -15,6 +17,7 @@ import type {
|
|||||||
ApiMessageEntity,
|
ApiMessageEntity,
|
||||||
ApiMessageForwardInfo,
|
ApiMessageForwardInfo,
|
||||||
ApiMessageReportResult,
|
ApiMessageReportResult,
|
||||||
|
ApiMessageThreadInfo,
|
||||||
ApiNewMediaTodo,
|
ApiNewMediaTodo,
|
||||||
ApiNewPoll,
|
ApiNewPoll,
|
||||||
ApiPeer,
|
ApiPeer,
|
||||||
@ -759,44 +762,51 @@ export function buildApiThreadInfoFromMessage(
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return buildApiThreadInfo(mtpMessage.replies, mtpMessage.id, chatId);
|
return buildApiThreadInfo(chatId, mtpMessage.id, mtpMessage.replies, mtpMessage.fwdFrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildApiThreadInfo(
|
export function buildApiThreadInfo(
|
||||||
messageReplies: GramJs.TypeMessageReplies, messageId: number, chatId: string,
|
chatId: string,
|
||||||
|
messageId: number,
|
||||||
|
messageReplies: GramJs.TypeMessageReplies,
|
||||||
|
messageForwardInfo?: GramJs.MessageFwdHeader,
|
||||||
): ApiThreadInfo | undefined {
|
): ApiThreadInfo | undefined {
|
||||||
const {
|
const {
|
||||||
channelId, replies, maxId, readMaxId, recentRepliers, comments,
|
channelId, replies, maxId, recentRepliers, comments, readMaxId,
|
||||||
} = messageReplies;
|
} = messageReplies;
|
||||||
|
|
||||||
|
const { fromId, channelPost } = messageForwardInfo || {};
|
||||||
|
|
||||||
const apiChannelId = channelId ? buildApiPeerId(channelId, 'channel') : undefined;
|
const apiChannelId = channelId ? buildApiPeerId(channelId, 'channel') : undefined;
|
||||||
if (apiChannelId === DELETED_COMMENTS_CHANNEL_ID) {
|
if (apiChannelId === DELETED_COMMENTS_CHANNEL_ID) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseThreadInfo = {
|
const baseThreadInfo: Partial<ApiBaseThreadInfo> = {
|
||||||
messagesCount: replies,
|
messagesCount: replies,
|
||||||
...(maxId && { lastMessageId: maxId }),
|
lastMessageId: maxId,
|
||||||
...(readMaxId && { lastReadMessageId: readMaxId }),
|
recentReplierIds: recentRepliers?.map(getApiChatIdFromMtpPeer),
|
||||||
...(recentRepliers && { recentReplierIds: recentRepliers.map(getApiChatIdFromMtpPeer) }),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (comments) {
|
if (comments) {
|
||||||
return {
|
return omitUndefined<ApiCommentsInfo>({
|
||||||
...baseThreadInfo,
|
...baseThreadInfo,
|
||||||
isCommentsInfo: true,
|
isCommentsInfo: true,
|
||||||
chatId: apiChannelId!,
|
chatId: apiChannelId!,
|
||||||
originChannelId: chatId,
|
originChannelId: chatId,
|
||||||
originMessageId: messageId,
|
originMessageId: messageId,
|
||||||
};
|
hasUnread: Boolean(readMaxId && maxId && readMaxId < maxId),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return omitUndefined<ApiMessageThreadInfo>({
|
||||||
...baseThreadInfo,
|
...baseThreadInfo,
|
||||||
isCommentsInfo: false,
|
isCommentsInfo: false,
|
||||||
chatId,
|
chatId,
|
||||||
threadId: messageId,
|
threadId: messageId,
|
||||||
};
|
fromChannelId: fromId && channelPost ? getApiChatIdFromMtpPeer(fromId) : undefined,
|
||||||
|
fromMessageId: channelPost,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildApiQuickReply(reply: GramJs.TypeQuickReply): ApiQuickReply {
|
export function buildApiQuickReply(reply: GramJs.TypeQuickReply): ApiQuickReply {
|
||||||
|
|||||||
@ -74,6 +74,7 @@ import {
|
|||||||
buildApiSearchPostsFlood,
|
buildApiSearchPostsFlood,
|
||||||
buildApiSponsoredMessage,
|
buildApiSponsoredMessage,
|
||||||
buildApiThreadInfo,
|
buildApiThreadInfo,
|
||||||
|
buildApiThreadInfoFromMessage,
|
||||||
buildLocalForwardedMessage,
|
buildLocalForwardedMessage,
|
||||||
buildLocalMessage,
|
buildLocalMessage,
|
||||||
buildPreparedInlineMessage,
|
buildPreparedInlineMessage,
|
||||||
@ -1383,7 +1384,7 @@ export async function fetchMessageViews({
|
|||||||
id,
|
id,
|
||||||
views,
|
views,
|
||||||
forwards,
|
forwards,
|
||||||
threadInfo: replies ? buildApiThreadInfo(replies, id, chat.id) : undefined,
|
threadInfo: replies ? buildApiThreadInfo(chat.id, id, replies) : undefined,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1456,16 +1457,23 @@ export async function fetchDiscussionMessage({
|
|||||||
const messages = topMessages.concat(replies.messages);
|
const messages = topMessages.concat(replies.messages);
|
||||||
const threadId = result.messages[result.messages.length - 1]?.id;
|
const threadId = result.messages[result.messages.length - 1]?.id;
|
||||||
|
|
||||||
if (!threadId) return undefined;
|
const chatId = topMessages[0]?.chatId;
|
||||||
|
if (!chatId || !threadId) return undefined;
|
||||||
|
|
||||||
const { maxId } = result;
|
const { maxId } = result;
|
||||||
const threadReadState = buildThreadReadState(result);
|
const threadReadState = buildThreadReadState(result);
|
||||||
|
|
||||||
|
const topMessageWithReplies = result.messages.find((message): message is GramJs.Message => (
|
||||||
|
message instanceof GramJs.Message && Boolean(message.replies)
|
||||||
|
))!;
|
||||||
|
const threadInfo = buildApiThreadInfoFromMessage(topMessageWithReplies);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
messages,
|
messages,
|
||||||
topMessages,
|
topMessages,
|
||||||
threadId,
|
threadId,
|
||||||
threadReadState,
|
threadReadState,
|
||||||
|
threadInfo,
|
||||||
lastMessageId: maxId,
|
lastMessageId: maxId,
|
||||||
chatId: topMessages[0]?.chatId,
|
chatId: topMessages[0]?.chatId,
|
||||||
firstMessageId: replies.messages[0]?.id,
|
firstMessageId: replies.messages[0]?.id,
|
||||||
|
|||||||
@ -826,6 +826,7 @@ export interface ApiCommentsInfo extends ApiBaseThreadInfo {
|
|||||||
threadId?: never;
|
threadId?: never;
|
||||||
originChannelId: string;
|
originChannelId: string;
|
||||||
originMessageId: number;
|
originMessageId: number;
|
||||||
|
hasUnread?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApiMessageThreadInfo extends ApiBaseThreadInfo {
|
export interface ApiMessageThreadInfo extends ApiBaseThreadInfo {
|
||||||
|
|||||||
@ -239,7 +239,7 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{renderBackButton()}
|
{renderBackButton(currentTransitionKey === 0)}
|
||||||
<h3>
|
<h3>
|
||||||
{messagesCount !== undefined ? (
|
{messagesCount !== undefined ? (
|
||||||
messageListType === 'thread' ? (
|
messageListType === 'thread' ? (
|
||||||
|
|||||||
@ -242,7 +242,7 @@
|
|||||||
|
|
||||||
width: 0.5rem;
|
width: 0.5rem;
|
||||||
height: 0.5rem;
|
height: 0.5rem;
|
||||||
margin-inline-start: 0.75rem;
|
margin-inline-start: 0.5rem;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
||||||
background: var(--accent-color);
|
background: var(--accent-color);
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { memo, useMemo } from '../../../lib/teact/teact';
|
|||||||
import { getActions, getGlobal } from '../../../global';
|
import { getActions, getGlobal } from '../../../global';
|
||||||
|
|
||||||
import type { ApiCommentsInfo } from '../../../api/types';
|
import type { ApiCommentsInfo } from '../../../api/types';
|
||||||
import type { ThreadReadState } from '../../../types';
|
|
||||||
|
|
||||||
import { selectIsCurrentUserFrozen, selectPeer } from '../../../global/selectors';
|
import { selectIsCurrentUserFrozen, selectPeer } from '../../../global/selectors';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
@ -22,7 +21,6 @@ import './CommentButton.scss';
|
|||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
threadInfo?: ApiCommentsInfo;
|
threadInfo?: ApiCommentsInfo;
|
||||||
threadReadState?: ThreadReadState;
|
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
isCustomShape?: boolean;
|
isCustomShape?: boolean;
|
||||||
@ -33,7 +31,6 @@ const SHOW_LOADER_DELAY = 450;
|
|||||||
const CommentButton = ({
|
const CommentButton = ({
|
||||||
isCustomShape,
|
isCustomShape,
|
||||||
threadInfo,
|
threadInfo,
|
||||||
threadReadState,
|
|
||||||
disabled,
|
disabled,
|
||||||
isLoading,
|
isLoading,
|
||||||
}: OwnProps) => {
|
}: OwnProps) => {
|
||||||
@ -44,9 +41,8 @@ const CommentButton = ({
|
|||||||
const oldLang = useOldLang();
|
const oldLang = useOldLang();
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
const {
|
const {
|
||||||
originMessageId, chatId, messagesCount, lastMessageId, recentReplierIds, originChannelId,
|
originMessageId, chatId, messagesCount, recentReplierIds, originChannelId, hasUnread,
|
||||||
} = threadInfo || {};
|
} = threadInfo || {};
|
||||||
const { lastReadInboxMessageId } = threadReadState || {};
|
|
||||||
|
|
||||||
const handleClick = useLastCallback(() => {
|
const handleClick = useLastCallback(() => {
|
||||||
const global = getGlobal();
|
const global = getGlobal();
|
||||||
@ -93,8 +89,6 @@ const CommentButton = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasUnread = Boolean(lastReadInboxMessageId && lastMessageId && lastReadInboxMessageId < lastMessageId);
|
|
||||||
|
|
||||||
const commentsText = messagesCount ? (oldLang('CommentsCount', '%COMMENTS_COUNT%', undefined, messagesCount))
|
const commentsText = messagesCount ? (oldLang('CommentsCount', '%COMMENTS_COUNT%', undefined, messagesCount))
|
||||||
.split('%')
|
.split('%')
|
||||||
.map((s) => {
|
.map((s) => {
|
||||||
|
|||||||
@ -39,7 +39,6 @@ import type {
|
|||||||
TextSummary,
|
TextSummary,
|
||||||
ThemeKey,
|
ThemeKey,
|
||||||
ThreadId,
|
ThreadId,
|
||||||
ThreadReadState,
|
|
||||||
} from '../../../types';
|
} from '../../../types';
|
||||||
import type { Signal } from '../../../util/signals';
|
import type { Signal } from '../../../util/signals';
|
||||||
import { MAIN_THREAD_ID } from '../../../api/types';
|
import { MAIN_THREAD_ID } from '../../../api/types';
|
||||||
@ -125,7 +124,7 @@ import {
|
|||||||
selectMessageTimestampableDuration,
|
selectMessageTimestampableDuration,
|
||||||
} from '../../../global/selectors/media';
|
} from '../../../global/selectors/media';
|
||||||
import { selectSharedSettings } from '../../../global/selectors/sharedState';
|
import { selectSharedSettings } from '../../../global/selectors/sharedState';
|
||||||
import { selectThread, selectThreadReadState } from '../../../global/selectors/threads';
|
import { selectThreadInfo, selectThreadReadState } from '../../../global/selectors/threads';
|
||||||
import { IS_TAURI } from '../../../util/browser/globalEnvironment';
|
import { IS_TAURI } from '../../../util/browser/globalEnvironment';
|
||||||
import { IS_ANDROID, IS_TRANSLATION_SUPPORTED } from '../../../util/browser/windowEnvironment';
|
import { IS_ANDROID, IS_TRANSLATION_SUPPORTED } from '../../../util/browser/windowEnvironment';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
@ -295,7 +294,6 @@ type StateProps = {
|
|||||||
shouldLoopStickers?: boolean;
|
shouldLoopStickers?: boolean;
|
||||||
autoLoadFileMaxSizeMb: number;
|
autoLoadFileMaxSizeMb: number;
|
||||||
repliesThreadInfo?: ApiThreadInfo;
|
repliesThreadInfo?: ApiThreadInfo;
|
||||||
repliesReadState?: ThreadReadState;
|
|
||||||
reactionMessage?: ApiMessage;
|
reactionMessage?: ApiMessage;
|
||||||
availableReactions?: ApiAvailableReaction[];
|
availableReactions?: ApiAvailableReaction[];
|
||||||
defaultReaction?: ApiReaction;
|
defaultReaction?: ApiReaction;
|
||||||
@ -429,7 +427,6 @@ const Message = ({
|
|||||||
shouldLoopStickers,
|
shouldLoopStickers,
|
||||||
autoLoadFileMaxSizeMb,
|
autoLoadFileMaxSizeMb,
|
||||||
repliesThreadInfo,
|
repliesThreadInfo,
|
||||||
repliesReadState,
|
|
||||||
hasUnreadReaction,
|
hasUnreadReaction,
|
||||||
memoFirstUnreadIdRef,
|
memoFirstUnreadIdRef,
|
||||||
senderAdminMember,
|
senderAdminMember,
|
||||||
@ -842,7 +839,6 @@ const Message = ({
|
|||||||
const phoneCall = action?.type === 'phoneCall' ? action : undefined;
|
const phoneCall = action?.type === 'phoneCall' ? action : undefined;
|
||||||
|
|
||||||
const commentsThreadInfo = repliesThreadInfo?.isCommentsInfo ? repliesThreadInfo : undefined;
|
const commentsThreadInfo = repliesThreadInfo?.isCommentsInfo ? repliesThreadInfo : undefined;
|
||||||
const commentsReadState = repliesThreadInfo?.isCommentsInfo ? repliesReadState : undefined;
|
|
||||||
const isLocalWithCommentButton = hasLinkedChat && isChannel && isLocal;
|
const isLocalWithCommentButton = hasLinkedChat && isChannel && isLocal;
|
||||||
|
|
||||||
const isMediaWithCommentButton = (commentsThreadInfo || isLocalWithCommentButton)
|
const isMediaWithCommentButton = (commentsThreadInfo || isLocalWithCommentButton)
|
||||||
@ -1895,7 +1891,6 @@ const Message = ({
|
|||||||
{withCommentButton && isCustomShape && (
|
{withCommentButton && isCustomShape && (
|
||||||
<CommentButton
|
<CommentButton
|
||||||
threadInfo={commentsThreadInfo}
|
threadInfo={commentsThreadInfo}
|
||||||
threadReadState={commentsReadState}
|
|
||||||
disabled={noComments || !commentsThreadInfo}
|
disabled={noComments || !commentsThreadInfo}
|
||||||
isLoading={isLoadingComments}
|
isLoading={isLoadingComments}
|
||||||
isCustomShape
|
isCustomShape
|
||||||
@ -1927,7 +1922,6 @@ const Message = ({
|
|||||||
{withCommentButton && !isCustomShape && (
|
{withCommentButton && !isCustomShape && (
|
||||||
<CommentButton
|
<CommentButton
|
||||||
threadInfo={commentsThreadInfo}
|
threadInfo={commentsThreadInfo}
|
||||||
threadReadState={commentsReadState}
|
|
||||||
disabled={noComments || !commentsThreadInfo}
|
disabled={noComments || !commentsThreadInfo}
|
||||||
isLoading={isLoadingComments}
|
isLoading={isLoadingComments}
|
||||||
/>
|
/>
|
||||||
@ -2095,8 +2089,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const downloadableMedia = selectMessageDownloadableMedia(global, message);
|
const downloadableMedia = selectMessageDownloadableMedia(global, message);
|
||||||
const isDownloading = downloadableMedia && getIsDownloading(activeDownloads, downloadableMedia);
|
const isDownloading = downloadableMedia && getIsDownloading(activeDownloads, downloadableMedia);
|
||||||
|
|
||||||
const repliesThread = selectThread(global, chatId, album?.commentsMessage?.id || id);
|
const repliesThreadInfo = selectThreadInfo(global, chatId, album?.commentsMessage?.id || id);
|
||||||
const { threadInfo: repliesThreadInfo, readState: repliesReadState } = repliesThread || {};
|
|
||||||
|
|
||||||
const isInDocumentGroup = Boolean(message.groupedId) && !message.isInAlbum;
|
const isInDocumentGroup = Boolean(message.groupedId) && !message.isInAlbum;
|
||||||
const documentGroupFirstMessageId = isInDocumentGroup
|
const documentGroupFirstMessageId = isInDocumentGroup
|
||||||
@ -2200,7 +2193,6 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
autoLoadFileMaxSizeMb: global.settings.byKey.autoLoadFileMaxSizeMb,
|
autoLoadFileMaxSizeMb: global.settings.byKey.autoLoadFileMaxSizeMb,
|
||||||
shouldLoopStickers: selectShouldLoopStickers(global),
|
shouldLoopStickers: selectShouldLoopStickers(global),
|
||||||
repliesThreadInfo,
|
repliesThreadInfo,
|
||||||
repliesReadState,
|
|
||||||
availableReactions: global.reactions.availableReactions,
|
availableReactions: global.reactions.availableReactions,
|
||||||
defaultReaction: isMessageLocal(message) || messageListType === 'scheduled'
|
defaultReaction: isMessageLocal(message) || messageListType === 'scheduled'
|
||||||
? undefined : selectDefaultReaction(global, chatId),
|
? undefined : selectDefaultReaction(global, chatId),
|
||||||
|
|||||||
@ -422,22 +422,9 @@ addActionHandler('openThread', async (global, actions, payload): Promise<void> =
|
|||||||
|
|
||||||
global = getGlobal();
|
global = getGlobal();
|
||||||
global = addMessages(global, result.messages);
|
global = addMessages(global, result.messages);
|
||||||
|
global = updateThreadInfo(global, result.threadInfo);
|
||||||
global = updateThreadReadState(global, chatId, result.threadId, result.threadReadState);
|
global = updateThreadReadState(global, chatId, result.threadId, result.threadReadState);
|
||||||
global = updateThreadInfoLastMessageId(global, chatId, result.threadId, result.lastMessageId);
|
global = updateThreadInfoLastMessageId(global, chatId, result.threadId, result.lastMessageId);
|
||||||
|
|
||||||
if (isComments) {
|
|
||||||
const lastMessageId = threadInfo?.lastMessageId !== undefined ? threadInfo.lastMessageId
|
|
||||||
: threadInfo?.messagesCount === 0 ? result.threadId : undefined;
|
|
||||||
|
|
||||||
global = updateThreadInfo(global, {
|
|
||||||
isCommentsInfo: false,
|
|
||||||
threadId,
|
|
||||||
chatId,
|
|
||||||
fromChannelId: loadingChatId,
|
|
||||||
fromMessageId: loadingThreadId,
|
|
||||||
lastMessageId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
global = replaceThreadLocalStateParam(global, chatId, threadId, 'firstMessageId', result.firstMessageId);
|
global = replaceThreadLocalStateParam(global, chatId, threadId, 'firstMessageId', result.firstMessageId);
|
||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
|
|
||||||
|
|||||||
@ -247,6 +247,13 @@ addActionHandler('loadViewportMessages', (global, actions, payload): ActionRetur
|
|||||||
// Prevent unnecessary requests in threads
|
// Prevent unnecessary requests in threads
|
||||||
if (offsetId === threadId && direction === LoadMoreDirection.Backwards) return;
|
if (offsetId === threadId && direction === LoadMoreDirection.Backwards) return;
|
||||||
|
|
||||||
|
if (direction === LoadMoreDirection.Forwards && offsetId) {
|
||||||
|
const threadInfo = selectThreadInfo(global, chatId, threadId);
|
||||||
|
if (threadInfo?.lastMessageId && offsetId >= threadInfo.lastMessageId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const isOutlying = Boolean(listedIds && offsetId && !listedIds.includes(offsetId));
|
const isOutlying = Boolean(listedIds && offsetId && !listedIds.includes(offsetId));
|
||||||
const historyIds = (isOutlying
|
const historyIds = (isOutlying
|
||||||
? selectOutlyingListByMessageId(global, chatId, threadId, offsetId!) : listedIds)!;
|
? selectOutlyingListByMessageId(global, chatId, threadId, offsetId!) : listedIds)!;
|
||||||
|
|||||||
@ -23,7 +23,12 @@ import {
|
|||||||
updateUsers,
|
updateUsers,
|
||||||
} from '../../reducers';
|
} from '../../reducers';
|
||||||
import { updateTabState } from '../../reducers/tabs';
|
import { updateTabState } from '../../reducers/tabs';
|
||||||
import { updateThreadInfo, updateThreadLocalState } from '../../reducers/threads';
|
import {
|
||||||
|
replaceThreadLocalStateParam,
|
||||||
|
updateThreadInfo,
|
||||||
|
updateThreadLocalState,
|
||||||
|
updateThreadReadState,
|
||||||
|
} from '../../reducers/threads';
|
||||||
import {
|
import {
|
||||||
selectChat,
|
selectChat,
|
||||||
selectChatMessage,
|
selectChatMessage,
|
||||||
@ -179,6 +184,14 @@ async function loadAndReplaceMessages<T extends GlobalState>(global: T, actions:
|
|||||||
}
|
}
|
||||||
|
|
||||||
global = addChatMessagesById(global, currentChatId, byId);
|
global = addChatMessagesById(global, currentChatId, byId);
|
||||||
|
if (resultDiscussion) {
|
||||||
|
global = updateThreadInfo(global, resultDiscussion.threadInfo);
|
||||||
|
global = updateThreadReadState(global, currentChatId, activeThreadId, resultDiscussion.threadReadState);
|
||||||
|
global = replaceThreadLocalStateParam(
|
||||||
|
global, currentChatId, activeThreadId, 'firstMessageId', resultDiscussion.firstMessageId,
|
||||||
|
);
|
||||||
|
global = addChatMessagesById(global, currentChatId, buildCollectionByKey(resultDiscussion.topMessages, 'id'));
|
||||||
|
}
|
||||||
global = updateListedIds(global, currentChatId, activeThreadId, listedIds);
|
global = updateListedIds(global, currentChatId, activeThreadId, listedIds);
|
||||||
|
|
||||||
Object.entries(messagesThreads).forEach(([id, thread]) => {
|
Object.entries(messagesThreads).forEach(([id, thread]) => {
|
||||||
|
|||||||
@ -41,7 +41,7 @@ import {
|
|||||||
updateFocusedMessage,
|
updateFocusedMessage,
|
||||||
} from '../../reducers';
|
} from '../../reducers';
|
||||||
import { updateTabState } from '../../reducers/tabs';
|
import { updateTabState } from '../../reducers/tabs';
|
||||||
import { replaceTabThreadParam, replaceThreadLocalStateParam } from '../../reducers/threads';
|
import { replaceTabThreadParam, replaceThreadLocalStateParam, updateThreadReadState } from '../../reducers/threads';
|
||||||
import {
|
import {
|
||||||
selectAllowedMessageActionsSlow,
|
selectAllowedMessageActionsSlow,
|
||||||
selectCanForwardMessage,
|
selectCanForwardMessage,
|
||||||
@ -495,6 +495,7 @@ addActionHandler('scrollMessageListToBottom', (global, actions, payload): Action
|
|||||||
blurTimeout = window.setTimeout(() => {
|
blurTimeout = window.setTimeout(() => {
|
||||||
global = getGlobal();
|
global = getGlobal();
|
||||||
global = updateFocusedMessage(global, undefined, tabId);
|
global = updateFocusedMessage(global, undefined, tabId);
|
||||||
|
global = updateThreadReadState(global, chatId, threadId, { unreadCount: 0 });
|
||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
}, FOCUS_NO_HIGHLIGHT_DURATION);
|
}, FOCUS_NO_HIGHLIGHT_DURATION);
|
||||||
|
|
||||||
|
|||||||
@ -140,7 +140,7 @@ export function updateLinkedThreadInfo<T extends GlobalState>(
|
|||||||
return global;
|
return global;
|
||||||
}
|
}
|
||||||
|
|
||||||
const valuesToUpdate = pick(update, ['messagesCount', 'lastMessageId', 'recentReplierIds']);
|
const valuesToUpdate = pick(update, ['messagesCount', 'lastMessageId']);
|
||||||
const newThreadInfo: ApiThreadInfo = {
|
const newThreadInfo: ApiThreadInfo = {
|
||||||
...threadInfo,
|
...threadInfo,
|
||||||
...valuesToUpdate,
|
...valuesToUpdate,
|
||||||
|
|||||||
@ -783,6 +783,11 @@ export function selectRealLastReadId<T extends GlobalState>(global: T, chatId: s
|
|||||||
|
|
||||||
// `lastReadInboxMessageId` is empty for new chats
|
// `lastReadInboxMessageId` is empty for new chats
|
||||||
if (!readState.lastReadInboxMessageId) {
|
if (!readState.lastReadInboxMessageId) {
|
||||||
|
// For new comments, mark thread start as the last read
|
||||||
|
if (threadId !== MAIN_THREAD_ID && readState.unreadCount && typeof threadId === 'number') {
|
||||||
|
return threadId;
|
||||||
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import {
|
|||||||
DEBUG, STRICTERDOM_ENABLED,
|
DEBUG, STRICTERDOM_ENABLED,
|
||||||
} from './config';
|
} from './config';
|
||||||
import { enableStrict, requestMutation } from './lib/fasterdom/fasterdom';
|
import { enableStrict, requestMutation } from './lib/fasterdom/fasterdom';
|
||||||
import { selectTabState } from './global/selectors';
|
import { selectChat, selectChatFullInfo, selectCurrentMessageList, selectTabState } from './global/selectors';
|
||||||
import { selectSharedSettings } from './global/selectors/sharedState';
|
import { selectSharedSettings } from './global/selectors/sharedState';
|
||||||
import { betterView } from './util/betterView';
|
import { betterView } from './util/betterView';
|
||||||
import { IS_TAURI } from './util/browser/globalEnvironment';
|
import { IS_TAURI } from './util/browser/globalEnvironment';
|
||||||
@ -104,10 +104,21 @@ async function init() {
|
|||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
document.addEventListener('dblclick', () => {
|
document.addEventListener('dblclick', () => {
|
||||||
|
const currentGlobal = getGlobal();
|
||||||
|
const currentMessageList = selectCurrentMessageList(currentGlobal);
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.warn('TAB STATE', selectTabState(getGlobal()));
|
console.warn('TAB STATE', selectTabState(currentGlobal));
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.warn('GLOBAL STATE', getGlobal());
|
console.warn('GLOBAL STATE', currentGlobal);
|
||||||
|
if (currentMessageList) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.warn(
|
||||||
|
'CURRENT MESSAGE LIST',
|
||||||
|
selectChat(currentGlobal, currentMessageList.chatId),
|
||||||
|
selectChatFullInfo(currentGlobal, currentMessageList.chatId),
|
||||||
|
currentGlobal.messages.byChatId[currentMessageList.chatId],
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user