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 {
@ -10,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 } from '../../../modules/selectors';
import { selectThreadInfo, selectThreadOriginChat } from '../../../modules/selectors';
import useLang from '../../../hooks/useLang';
import Avatar from '../../common/Avatar';
@ -26,12 +28,19 @@ type StateProps = {
threadInfo: ApiThreadInfo;
usersById?: Record<number, ApiUser>;
chatsById?: Record<number, ApiChat>;
shouldRequestThreadUpdate: boolean;
};
type DispatchProps = Pick<GlobalActions, 'openChat'>;
type DispatchProps = Pick<GlobalActions, 'openChat' | 'requestThreadInfoUpdate'>;
const CommentButton: FC<OwnProps & StateProps & DispatchProps> = ({
disabled, threadInfo, usersById, chatsById, openChat,
disabled,
threadInfo,
usersById,
chatsById,
shouldRequestThreadUpdate,
openChat,
requestThreadInfoUpdate,
}) => {
const lang = useLang();
const {
@ -42,6 +51,13 @@ 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;
}
@ -92,6 +108,7 @@ 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;
@ -99,9 +116,11 @@ export default memo(withGlobal<OwnProps>(
threadInfo,
usersById,
chatsById,
shouldRequestThreadUpdate: !!chat && !threadInfo.topMessageId,
};
},
(setGlobal, actions): DispatchProps => pick(actions, [
'openChat',
'requestThreadInfoUpdate',
]),
)(CommentButton));

View File

@ -190,7 +190,7 @@
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);
}

View File

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

View File

@ -10,6 +10,7 @@ import {
} from '../../../../modules/helpers';
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_AND_COMMENTS = 238;
const MIN_MEDIA_HEIGHT = 90;
@ -18,7 +19,7 @@ const SMALL_IMAGE_THRESHOLD = 12;
export function getMinMediaWidth(hasText?: boolean, hasCommentButton?: boolean) {
return hasText
? (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) {

View File

@ -176,6 +176,19 @@ addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
const newMessage = selectChatMessage(global, chatId, message.id)!;
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);
break;
@ -432,8 +445,31 @@ function updateWithLocalMedia(
function updateListedAndViewportIds(global: GlobalState, message: ApiMessage) {
const { id, chatId } = message;
const { threadInfo, firstMessageId } = selectThreadByMessage(global, chatId, message) || {};
const chat = selectChat(global, chatId);
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) {
return global;
}
@ -441,7 +477,7 @@ function updateListedAndViewportIds(global: GlobalState, message: ApiMessage) {
global = updateListedIds(global, chatId, MAIN_THREAD_ID, [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 newGlobal = addViewportId(global, chatId, MAIN_THREAD_ID, 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;
}
@ -553,12 +564,12 @@ function deleteMessages(chatId: number | undefined, ids: number[], actions: Glob
}
});
unique(threadIdsToUpdate).forEach((threadId) => {
actions.requestThreadInfoUpdate({ chatId, threadId });
});
setTimeout(() => {
setGlobal(deleteChatMessages(getGlobal(), chatId, ids));
unique(threadIdsToUpdate).forEach((threadId) => {
actions.requestThreadInfoUpdate({ chatId, threadId });
});
}, ANIMATION_DELAY);
return;

View File

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

View File

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