Various fixes for comments in threads (#1280)

This commit is contained in:
Alexander Zinchuk 2021-07-23 23:28:30 +03:00
parent 85ed696721
commit ae0ea5aa0e
7 changed files with 89 additions and 37 deletions

View File

@ -1,4 +1,6 @@
import React, { FC, memo, useCallback } from '../../../lib/teact/teact'; import React, {
FC, memo, useCallback, useEffect,
} from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { withGlobal } from '../../../lib/teact/teactn';
import { import {
@ -10,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 } from '../../../modules/selectors'; import { selectThreadInfo, selectThreadOriginChat } from '../../../modules/selectors';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import Avatar from '../../common/Avatar'; import Avatar from '../../common/Avatar';
@ -26,12 +28,19 @@ 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'>; type DispatchProps = Pick<GlobalActions, 'openChat' | 'requestThreadInfoUpdate'>;
const CommentButton: FC<OwnProps & StateProps & DispatchProps> = ({ const CommentButton: FC<OwnProps & StateProps & DispatchProps> = ({
disabled, threadInfo, usersById, chatsById, openChat, disabled,
threadInfo,
usersById,
chatsById,
shouldRequestThreadUpdate,
openChat,
requestThreadInfoUpdate,
}) => { }) => {
const lang = useLang(); const lang = useLang();
const { const {
@ -42,6 +51,13 @@ 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;
} }
@ -92,6 +108,7 @@ 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;
@ -99,9 +116,11 @@ 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

@ -190,7 +190,7 @@
box-shadow: 0 1px 2px var(--color-default-shadow); box-shadow: 0 1px 2px var(--color-default-shadow);
} }
&.has-solid-background, .is-album & { &.has-solid-background, &.has-background, .is-album & {
background: var(--background-color); background: var(--background-color);
} }

View File

@ -31,7 +31,8 @@ export function buildContentClassName(
} = getMessageContent(message); } = getMessageContent(message);
const classNames = ['message-content']; const classNames = ['message-content'];
const isMediaWithNoText = (photo || video) && !text; const isMedia = photo || video;
const isMediaWithNoText = isMedia && !text;
const isViaBot = Boolean(message.viaBotId); const isViaBot = Boolean(message.viaBotId);
if (isEmojiOnlyMessage(customShape)) { if (isEmojiOnlyMessage(customShape)) {
@ -93,6 +94,10 @@ export function buildContentClassName(
if (!customShape) { if (!customShape) {
classNames.push('has-shadow'); classNames.push('has-shadow');
if (isMedia && hasComments) {
classNames.push('has-background');
}
if (hasReply || asForwarded || !isMediaWithNoText || isViaBot || forceSenderName) { if (hasReply || asForwarded || !isMediaWithNoText || isViaBot || forceSenderName) {
classNames.push('has-solid-background'); classNames.push('has-solid-background');
} }

View File

@ -10,6 +10,7 @@ import {
} from '../../../../modules/helpers'; } from '../../../../modules/helpers';
const MIN_MEDIA_WIDTH = 100; const MIN_MEDIA_WIDTH = 100;
const MIN_MEDIA_WIDTH_WITH_COMMENTS = 238;
const MIN_MEDIA_WIDTH_WITH_TEXT = 175; const MIN_MEDIA_WIDTH_WITH_TEXT = 175;
const MIN_MEDIA_WIDTH_WITH_TEXT_AND_COMMENTS = 238; const MIN_MEDIA_WIDTH_WITH_TEXT_AND_COMMENTS = 238;
const MIN_MEDIA_HEIGHT = 90; const MIN_MEDIA_HEIGHT = 90;
@ -18,7 +19,7 @@ const SMALL_IMAGE_THRESHOLD = 12;
export function getMinMediaWidth(hasText?: boolean, hasCommentButton?: boolean) { export function getMinMediaWidth(hasText?: boolean, hasCommentButton?: boolean) {
return hasText return hasText
? (hasCommentButton ? MIN_MEDIA_WIDTH_WITH_TEXT_AND_COMMENTS : MIN_MEDIA_WIDTH_WITH_TEXT) ? (hasCommentButton ? MIN_MEDIA_WIDTH_WITH_TEXT_AND_COMMENTS : MIN_MEDIA_WIDTH_WITH_TEXT)
: MIN_MEDIA_WIDTH; : (hasCommentButton ? MIN_MEDIA_WIDTH_WITH_COMMENTS : MIN_MEDIA_WIDTH);
} }
export function calculateMediaDimensions(message: ApiMessage, noAvatars?: boolean) { export function calculateMediaDimensions(message: ApiMessage, noAvatars?: boolean) {

View File

@ -176,6 +176,19 @@ addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
const newMessage = selectChatMessage(global, chatId, message.id)!; const newMessage = selectChatMessage(global, chatId, message.id)!;
global = updateChatLastMessage(global, chatId, newMessage); global = updateChatLastMessage(global, chatId, newMessage);
const thread = selectThreadByMessage(global, chatId, message);
// For some reason Telegram requires to manually mark outgoing thread messages read
// For some reason Telegram requires to manually mark outgoing thread messages read
if (thread && thread.threadInfo) {
actions.markMessageListRead({ maxId: message.id });
global = replaceThreadParam(global, chatId, thread.threadInfo.threadId, 'threadInfo', {
...thread.threadInfo,
lastMessageId: message.id,
lastReadInboxMessageId: message.id,
});
}
setGlobal(global); setGlobal(global);
break; break;
@ -432,8 +445,31 @@ function updateWithLocalMedia(
function updateListedAndViewportIds(global: GlobalState, message: ApiMessage) { function updateListedAndViewportIds(global: GlobalState, message: ApiMessage) {
const { id, chatId } = message; const { id, chatId } = message;
const { threadInfo, firstMessageId } = selectThreadByMessage(global, chatId, message) || {};
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);
if (threadInfo) {
if (firstMessageId || !isMessageLocal(message)) {
global = updateListedIds(global, chatId, threadInfo.threadId, [id]);
if (selectIsViewportNewest(global, chatId, threadInfo.threadId)) {
global = addViewportId(global, chatId, threadInfo.threadId, id);
if (!firstMessageId) {
global = replaceThreadParam(global, chatId, threadInfo.threadId, 'firstMessageId', message.id);
}
}
}
global = replaceThreadParam(global, chatId, threadInfo.threadId, 'threadInfo', {
...threadInfo,
lastMessageId: message.id,
messagesCount: threadInfo.messagesCount + 1,
});
}
if (isUnreadChatNotLoaded) { if (isUnreadChatNotLoaded) {
return global; return global;
} }
@ -441,7 +477,7 @@ function updateListedAndViewportIds(global: GlobalState, message: ApiMessage) {
global = updateListedIds(global, chatId, MAIN_THREAD_ID, [id]); global = updateListedIds(global, chatId, MAIN_THREAD_ID, [id]);
if (selectIsViewportNewest(global, chatId, MAIN_THREAD_ID)) { if (selectIsViewportNewest(global, chatId, MAIN_THREAD_ID)) {
// Always keep the first uread message in the viewport list // Always keep the first unread message in the viewport list
const firstUnreadId = selectFirstUnreadId(global, chatId, MAIN_THREAD_ID); const firstUnreadId = selectFirstUnreadId(global, chatId, MAIN_THREAD_ID);
const newGlobal = addViewportId(global, chatId, MAIN_THREAD_ID, id); const newGlobal = addViewportId(global, chatId, MAIN_THREAD_ID, id);
const newViewportIds = selectViewportIds(newGlobal, chatId, MAIN_THREAD_ID); const newViewportIds = selectViewportIds(newGlobal, chatId, MAIN_THREAD_ID);
@ -451,31 +487,6 @@ function updateListedAndViewportIds(global: GlobalState, message: ApiMessage) {
} }
} }
const { threadInfo, firstMessageId } = selectThreadByMessage(global, chatId, message) || {};
if (!firstMessageId && isMessageLocal(message)) {
return global;
}
if (threadInfo) {
global = updateListedIds(global, chatId, threadInfo.threadId, [id]);
if (selectIsViewportNewest(global, chatId, threadInfo.threadId)) {
global = addViewportId(global, chatId, threadInfo.threadId, id);
if (!firstMessageId) {
global = replaceThreadParam(global, chatId, threadInfo.threadId, 'firstMessageId', message.id);
}
if (!threadInfo.lastMessageId) {
global = replaceThreadParam(global, chatId, threadInfo.threadId, 'threadInfo', {
...threadInfo,
lastMessageId: message.id,
});
}
}
}
return global; return global;
} }
@ -553,12 +564,12 @@ function deleteMessages(chatId: number | undefined, ids: number[], actions: Glob
} }
}); });
unique(threadIdsToUpdate).forEach((threadId) => {
actions.requestThreadInfoUpdate({ chatId, threadId });
});
setTimeout(() => { setTimeout(() => {
setGlobal(deleteChatMessages(getGlobal(), chatId, ids)); setGlobal(deleteChatMessages(getGlobal(), chatId, ids));
unique(threadIdsToUpdate).forEach((threadId) => {
actions.requestThreadInfoUpdate({ chatId, threadId });
});
}, ANIMATION_DELAY); }, ANIMATION_DELAY);
return; return;

View File

@ -277,6 +277,10 @@ function filterChatFolder(
includedChatIds?: Set<number>, includedChatIds?: Set<number>,
pinnedChatIds?: Set<number>, pinnedChatIds?: Set<number>,
) { ) {
if (chat.isNotJoined) {
return false;
}
if (excludedChatIds && excludedChatIds.has(chat.id)) { if (excludedChatIds && excludedChatIds.has(chat.id)) {
return false; return false;
} }

View File

@ -180,14 +180,18 @@ export function deleteChatMessages(
const threadIds = Object.keys(global.messages.byChatId[chatId].threadsById).map(Number); const threadIds = Object.keys(global.messages.byChatId[chatId].threadsById).map(Number);
threadIds.forEach((threadId) => { threadIds.forEach((threadId) => {
const threadInfo = selectThreadInfo(global, chatId, threadId);
let listedIds = selectListedIds(global, chatId, threadId); let listedIds = selectListedIds(global, chatId, threadId);
let outlyingIds = selectOutlyingIds(global, chatId, threadId); let outlyingIds = selectOutlyingIds(global, chatId, threadId);
let viewportIds = selectViewportIds(global, chatId, threadId); let viewportIds = selectViewportIds(global, chatId, threadId);
let pinnedIds = selectPinnedIds(global, chatId); let pinnedIds = selectPinnedIds(global, chatId);
let newMessageCount = threadInfo ? threadInfo.messagesCount : undefined;
messageIds.forEach((messageId) => { messageIds.forEach((messageId) => {
if (listedIds && listedIds.includes(messageId)) { if (listedIds && listedIds.includes(messageId)) {
listedIds = listedIds.filter((id) => id !== messageId); listedIds = listedIds.filter((id) => id !== messageId);
if (newMessageCount !== undefined) newMessageCount -= 1;
} }
if (outlyingIds && outlyingIds.includes(messageId)) { if (outlyingIds && outlyingIds.includes(messageId)) {
@ -203,10 +207,18 @@ export function deleteChatMessages(
} }
}); });
global = replaceThreadParam(global, chatId, threadId, 'listedIds', listedIds); global = replaceThreadParam(global, chatId, threadId, 'listedIds', listedIds);
global = replaceThreadParam(global, chatId, threadId, 'outlyingIds', outlyingIds); global = replaceThreadParam(global, chatId, threadId, 'outlyingIds', outlyingIds);
global = replaceThreadParam(global, chatId, threadId, 'viewportIds', viewportIds); global = replaceThreadParam(global, chatId, threadId, 'viewportIds', viewportIds);
global = replaceThreadParam(global, chatId, threadId, 'pinnedIds', pinnedIds); global = replaceThreadParam(global, chatId, threadId, 'pinnedIds', pinnedIds);
if (threadInfo && newMessageCount !== undefined) {
global = replaceThreadParam(global, chatId, threadId, 'threadInfo', {
...threadInfo,
messagesCount: newMessageCount,
});
}
}); });
if (deletedForwardedPosts.length) { if (deletedForwardedPosts.length) {