Reactions: Raise service messages after adding a reaction (#5431)

This commit is contained in:
Alexander Zinchuk 2025-01-21 18:20:25 +01:00
parent a7ebaf3aa8
commit d0633cb419
3 changed files with 58 additions and 42 deletions

View File

@ -40,6 +40,7 @@ import useFlag from '../../hooks/useFlag';
import { useIsIntersecting, useOnIntersect } from '../../hooks/useIntersectionObserver';
import useLang from '../../hooks/useLang';
import useOldLang from '../../hooks/useOldLang';
import useMessageResizeObserver from '../../hooks/useResizeMessageObserver';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import useFocusMessage from './message/hooks/useFocusMessage';
@ -171,6 +172,8 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
const withServiceReactions = Boolean(message.areReactionsPossible && message?.reactions);
useMessageResizeObserver(ref, isLastInList);
useEffect(() => {
if (noAppearanceAnimation) {
return;

View File

@ -1,6 +1,5 @@
import type { FC } from '../../../lib/teact/teact';
import React, {
beginHeavyAnimation,
memo,
useCallback,
useEffect,
@ -111,17 +110,12 @@ import {
selectUploadProgress,
selectUser,
} from '../../../global/selectors';
import { isAnimatingScroll } from '../../../util/animateScroll';
import buildClassName from '../../../util/buildClassName';
import { isElementInViewport } from '../../../util/isElementInViewport';
import { getMessageKey } from '../../../util/keys/messageKey';
import stopEvent from '../../../util/stopEvent';
import { IS_ANDROID, IS_ELECTRON, IS_TRANSLATION_SUPPORTED } from '../../../util/windowEnvironment';
import {
calculateDimensionsForMessageMedia,
getStickerDimensions,
REM,
} from '../../common/helpers/mediaDimensions';
import { calculateDimensionsForMessageMedia, getStickerDimensions, REM } from '../../common/helpers/mediaDimensions';
import { getPeerColorClass } from '../../common/helpers/peerColor';
import renderText from '../../common/helpers/renderText';
import { getCustomEmojiSize } from '../composer/helpers/customEmoji';
@ -139,10 +133,9 @@ import { useOnIntersect } from '../../../hooks/useIntersectionObserver';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useResizeObserver from '../../../hooks/useResizeObserver';
import useMessageResizeObserver from '../../../hooks/useResizeMessageObserver';
import useShowTransition from '../../../hooks/useShowTransition';
import useTextLanguage from '../../../hooks/useTextLanguage';
import useThrottledCallback from '../../../hooks/useThrottledCallback';
import useDetectChatLanguage from './hooks/useDetectChatLanguage';
import useFocusMessage from './hooks/useFocusMessage';
import useInnerHandlers from './hooks/useInnerHandlers';
@ -322,9 +315,6 @@ const APPEARANCE_DELAY = 10;
const NO_MEDIA_CORNERS_THRESHOLD = 18;
const QUICK_REACTION_SIZE = 1.75 * REM;
const EXTRA_SPACE_FOR_REACTIONS = 2.25 * REM;
const BOTTOM_FOCUS_SCROLL_THRESHOLD = 5;
const THROTTLE_MS = 300;
const RESIZE_ANIMATION_DURATION = 400;
const Message: FC<OwnProps & StateProps> = ({
message,
@ -442,8 +432,6 @@ const Message: FC<OwnProps & StateProps> = ({
// eslint-disable-next-line no-null/no-null
const quickReactionRef = useRef<HTMLDivElement>(null);
const messageHeightRef = useRef(0);
const lang = useOldLang();
const [isTranscriptionHidden, setTranscriptionHidden] = useState(false);
@ -850,34 +838,7 @@ const Message: FC<OwnProps & StateProps> = ({
|| ((asForwarded || isChatWithSelf) && forwardInfo?.postAuthorTitle)
|| undefined;
const shouldFocusOnResize = isLastInList;
const handleResize = useLastCallback((entry: ResizeObserverEntry) => {
const lastHeight = messageHeightRef.current;
const newHeight = entry.contentRect.height;
messageHeightRef.current = newHeight;
if (isAnimatingScroll() || !lastHeight || newHeight <= lastHeight) return;
const container = entry.target.closest<HTMLDivElement>('.MessageList');
if (!container) return;
beginHeavyAnimation(RESIZE_ANIMATION_DURATION);
const resizeDiff = newHeight - lastHeight;
const { offsetHeight, scrollHeight, scrollTop } = container;
const currentScrollBottom = Math.round(scrollHeight - scrollTop - offsetHeight);
const previousScrollBottom = currentScrollBottom - resizeDiff;
if (previousScrollBottom <= BOTTOM_FOCUS_SCROLL_THRESHOLD) {
focusLastMessage();
}
});
const throttledResize = useThrottledCallback(handleResize, [handleResize], THROTTLE_MS, false);
useResizeObserver(ref, throttledResize, !shouldFocusOnResize);
useMessageResizeObserver(ref, isLastInList);
useEffect(() => {
const bottomMarker = bottomMarkerRef.current;

View File

@ -0,0 +1,52 @@
import { beginHeavyAnimation, useRef } from '../lib/teact/teact';
import { getActions } from '../global';
import { isAnimatingScroll } from '../util/animateScroll';
import useLastCallback from './useLastCallback';
import useResizeObserver from './useResizeObserver';
import useThrottledCallback from './useThrottledCallback';
const BOTTOM_FOCUS_SCROLL_THRESHOLD = 5;
const THROTTLE_MS = 300;
const RESIZE_ANIMATION_DURATION = 400;
function useMessageResizeObserver(
ref: React.RefObject<HTMLElement> | undefined,
shouldFocusOnResize = false,
) {
const {
focusLastMessage,
} = getActions();
const messageHeightRef = useRef(0);
const handleResize = useLastCallback(
(entry) => {
const lastHeight = messageHeightRef.current;
const newHeight = entry.contentRect.height;
messageHeightRef.current = newHeight;
if (isAnimatingScroll() || !lastHeight || newHeight <= lastHeight) return;
const container = entry.target.closest('.MessageList');
if (!container) return;
beginHeavyAnimation(RESIZE_ANIMATION_DURATION);
const resizeDiff = newHeight - lastHeight;
const { offsetHeight, scrollHeight, scrollTop } = container;
const currentScrollBottom = Math.round(scrollHeight - scrollTop - offsetHeight);
const previousScrollBottom = currentScrollBottom - resizeDiff;
if (previousScrollBottom <= BOTTOM_FOCUS_SCROLL_THRESHOLD) {
focusLastMessage();
}
},
);
const throttledResize = useThrottledCallback(handleResize, [handleResize], THROTTLE_MS, false);
useResizeObserver(ref, throttledResize, !shouldFocusOnResize);
}
export default useMessageResizeObserver;