From ae0ea5aa0eedf3252ce7bcb7f6ecce63a4155422 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Fri, 23 Jul 2021 23:28:30 +0300 Subject: [PATCH] Various fixes for comments in threads (#1280) --- .../middle/message/CommentButton.tsx | 27 +++++-- .../middle/message/_message-content.scss | 2 +- .../message/helpers/buildContentClassName.ts | 7 +- .../middle/message/helpers/mediaDimensions.ts | 3 +- src/modules/actions/apiUpdaters/messages.ts | 71 +++++++++++-------- src/modules/helpers/chats.ts | 4 ++ src/modules/reducers/messages.ts | 12 ++++ 7 files changed, 89 insertions(+), 37 deletions(-) diff --git a/src/components/middle/message/CommentButton.tsx b/src/components/middle/message/CommentButton.tsx index 5e5c54315..a035b8000 100644 --- a/src/components/middle/message/CommentButton.tsx +++ b/src/components/middle/message/CommentButton.tsx @@ -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; chatsById?: Record; + shouldRequestThreadUpdate: boolean; }; -type DispatchProps = Pick; +type DispatchProps = Pick; const CommentButton: FC = ({ - disabled, threadInfo, usersById, chatsById, openChat, + disabled, + threadInfo, + usersById, + chatsById, + shouldRequestThreadUpdate, + openChat, + requestThreadInfoUpdate, }) => { const lang = useLang(); const { @@ -42,6 +51,13 @@ const CommentButton: FC = ({ 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( 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( threadInfo, usersById, chatsById, + shouldRequestThreadUpdate: !!chat && !threadInfo.topMessageId, }; }, (setGlobal, actions): DispatchProps => pick(actions, [ 'openChat', + 'requestThreadInfoUpdate', ]), )(CommentButton)); diff --git a/src/components/middle/message/_message-content.scss b/src/components/middle/message/_message-content.scss index 4eceaadd4..ee8e34dda 100644 --- a/src/components/middle/message/_message-content.scss +++ b/src/components/middle/message/_message-content.scss @@ -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); } diff --git a/src/components/middle/message/helpers/buildContentClassName.ts b/src/components/middle/message/helpers/buildContentClassName.ts index bae47ae53..4e237a85f 100644 --- a/src/components/middle/message/helpers/buildContentClassName.ts +++ b/src/components/middle/message/helpers/buildContentClassName.ts @@ -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'); } diff --git a/src/components/middle/message/helpers/mediaDimensions.ts b/src/components/middle/message/helpers/mediaDimensions.ts index 9cb2c1b4a..3d7da05df 100644 --- a/src/components/middle/message/helpers/mediaDimensions.ts +++ b/src/components/middle/message/helpers/mediaDimensions.ts @@ -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) { diff --git a/src/modules/actions/apiUpdaters/messages.ts b/src/modules/actions/apiUpdaters/messages.ts index fa9496499..c31e3653a 100644 --- a/src/modules/actions/apiUpdaters/messages.ts +++ b/src/modules/actions/apiUpdaters/messages.ts @@ -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; diff --git a/src/modules/helpers/chats.ts b/src/modules/helpers/chats.ts index 365a9b925..034eb6d56 100644 --- a/src/modules/helpers/chats.ts +++ b/src/modules/helpers/chats.ts @@ -277,6 +277,10 @@ function filterChatFolder( includedChatIds?: Set, pinnedChatIds?: Set, ) { + if (chat.isNotJoined) { + return false; + } + if (excludedChatIds && excludedChatIds.has(chat.id)) { return false; } diff --git a/src/modules/reducers/messages.ts b/src/modules/reducers/messages.ts index 427d4741e..d5006a42b 100644 --- a/src/modules/reducers/messages.ts +++ b/src/modules/reducers/messages.ts @@ -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) {