diff --git a/src/components/middle/ActionMessage.tsx b/src/components/middle/ActionMessage.tsx index d77035b74..1ff49695e 100644 --- a/src/components/middle/ActionMessage.tsx +++ b/src/components/middle/ActionMessage.tsx @@ -9,6 +9,7 @@ import type { } from '../../api/types'; import type { FocusDirection } from '../../types'; import type { PinnedIntersectionChangedCallback } from './hooks/usePinnedMessage'; +import type { MessageListType } from '../../global/types'; import { selectUser, @@ -17,6 +18,7 @@ import { selectChat, selectTopicFromMessage, selectTabState, + selectCurrentMessageIds, } from '../../global/selectors'; import { getMessageHtmlId, isChatChannel } from '../../global/helpers'; import buildClassName from '../../util/buildClassName'; @@ -38,6 +40,7 @@ import ActionMessageSuggestedAvatar from './ActionMessageSuggestedAvatar'; type OwnProps = { message: ApiMessage; threadId?: number; + messageListType?: MessageListType; observeIntersectionForReading?: ObserveFn; observeIntersectionForLoading?: ObserveFn; observeIntersectionForPlaying?: ObserveFn; @@ -60,6 +63,7 @@ type StateProps = { topic?: ApiTopic; focusDirection?: FocusDirection; noFocusHighlight?: boolean; + viewportIds?: number[]; premiumGiftSticker?: ApiSticker; }; @@ -79,6 +83,7 @@ const ActionMessage: FC = ({ isFocused, focusDirection, noFocusHighlight, + viewportIds, premiumGiftSticker, isInsideTopic, topic, @@ -97,7 +102,7 @@ const ActionMessage: FC = ({ useOnIntersect(ref, observeIntersectionForReading); useEnsureMessage(message.chatId, message.replyToMessageId, targetMessage); - useFocusMessage(ref, message.chatId, isFocused, focusDirection, noFocusHighlight); + useFocusMessage(ref, message.id, message.chatId, isFocused, focusDirection, noFocusHighlight, viewportIds); useEffect(() => { if (!message.isPinned) return undefined; @@ -247,13 +252,17 @@ const ActionMessage: FC = ({ }; export default memo(withGlobal( - (global, { message, threadId }): StateProps => { + (global, { message, threadId, messageListType }): StateProps => { + const { + chatId, senderId, replyToMessageId, content, + } = message; + const { byId: usersById } = global.users; - const userId = message.senderId; - const { targetUserIds, targetChatId } = message.content.action || {}; - const targetMessageId = message.replyToMessageId; + const userId = senderId; + const { targetUserIds, targetChatId } = content.action || {}; + const targetMessageId = replyToMessageId; const targetMessage = targetMessageId - ? selectChatMessage(global, message.chatId, targetMessageId) + ? selectChatMessage(global, chatId, targetMessageId) : undefined; const isFocused = threadId ? selectIsMessageFocused(global, message, threadId) : false; @@ -262,8 +271,8 @@ export default memo(withGlobal( noHighlight: noFocusHighlight, } = (isFocused && selectTabState(global).focusedMessage) || {}; - const chat = selectChat(global, message.chatId); - const isChat = chat && (isChatChannel(chat) || userId === message.chatId); + const chat = selectChat(global, chatId); + const isChat = chat && (isChatChannel(chat) || userId === chatId); const senderUser = !isChat && userId ? selectUser(global, userId) : undefined; const senderChat = isChat ? chat : undefined; const premiumGiftSticker = global.premiumGifts?.stickers?.[0]; @@ -279,7 +288,13 @@ export default memo(withGlobal( isFocused, premiumGiftSticker, topic, - ...(isFocused && { focusDirection, noFocusHighlight }), + ...(isFocused && { + focusDirection, + noFocusHighlight, + viewportIds: threadId && messageListType + ? selectCurrentMessageIds(global, chatId, threadId, messageListType) + : undefined, + }), }; }, )(ActionMessage)); diff --git a/src/components/middle/MessageListContent.tsx b/src/components/middle/MessageListContent.tsx index 3322ddb9f..55b68cc71 100644 --- a/src/components/middle/MessageListContent.tsx +++ b/src/components/middle/MessageListContent.tsx @@ -150,6 +150,7 @@ const MessageListContent: FC = ({ key={message.id} message={message} threadId={threadId} + messageListType={type} isInsideTopic={Boolean(threadId && threadId !== MAIN_THREAD_ID)} observeIntersectionForReading={observeIntersectionForReading} observeIntersectionForLoading={observeIntersectionForLoading} diff --git a/src/components/middle/message/Message.tsx b/src/components/middle/message/Message.tsx index 9e236a845..44dd02c17 100644 --- a/src/components/middle/message/Message.tsx +++ b/src/components/middle/message/Message.tsx @@ -647,7 +647,10 @@ const Message: FC = ({ replyMessage, message.id, ); - useFocusMessage(ref, chatId, isFocused, focusDirection, noFocusHighlight, isResizingContainer, viewportIds); + + useFocusMessage( + ref, messageId, chatId, isFocused, focusDirection, noFocusHighlight, viewportIds, isResizingContainer, + ); const shouldFocusOnResize = isLastInGroup; diff --git a/src/components/middle/message/hooks/useFocusMessage.ts b/src/components/middle/message/hooks/useFocusMessage.ts index 1a34cf392..ce2b25a24 100644 --- a/src/components/middle/message/hooks/useFocusMessage.ts +++ b/src/components/middle/message/hooks/useFocusMessage.ts @@ -1,6 +1,6 @@ import type { FocusDirection } from '../../../../types'; -import { useLayoutEffect } from '../../../../lib/teact/teact'; +import { useLayoutEffect, useMemo } from '../../../../lib/teact/teact'; import fastSmoothScroll from '../../../../util/fastSmoothScroll'; // This is used when the viewport was replaced. @@ -9,13 +9,23 @@ const FOCUS_MARGIN = 20; export default function useFocusMessage( elementRef: { current: HTMLDivElement | null }, + messageId: number, chatId: string, isFocused?: boolean, focusDirection?: FocusDirection, noFocusHighlight?: boolean, - isResizingContainer?: boolean, viewportIds?: number[], + isResizingContainer?: boolean, ) { + const viewportIndex = useMemo(() => { + if (!viewportIds) { + return 0; + } + + const index = viewportIds.indexOf(messageId); + return Math.min(index, viewportIds.length - index - 1); + }, [messageId, viewportIds]); + useLayoutEffect(() => { if (isFocused && elementRef.current) { const messagesContainer = elementRef.current.closest('.MessageList')!; @@ -33,6 +43,6 @@ export default function useFocusMessage( ); } }, [ - elementRef, chatId, isFocused, focusDirection, noFocusHighlight, isResizingContainer, viewportIds, + elementRef, chatId, isFocused, focusDirection, noFocusHighlight, isResizingContainer, viewportIndex, ]); }