Message, Chat Folders, Story Toggler: Leverage the new useShowTransition

This commit is contained in:
Alexander Zinchuk 2024-09-06 15:43:17 +02:00
parent b0239f1d43
commit 13f43be77d
6 changed files with 68 additions and 44 deletions

View File

@ -20,11 +20,12 @@ import { captureEvents, SwipeDirection } from '../../../util/captureEvents';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import { IS_TOUCH_ENV } from '../../../util/windowEnvironment';
import useDerivedState from '../../../hooks/useDerivedState';
import { useFolderManagerForUnreadCounters } from '../../../hooks/useFolderManager';
import useHistoryBack from '../../../hooks/useHistoryBack';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import StoryRibbon from '../../story/StoryRibbon';
import TabList from '../../ui/TabList';
@ -100,10 +101,15 @@ const ChatFolders: FC<OwnProps & StateProps> = ({
}, []);
const {
ref,
shouldRender: shouldRenderStoryRibbon,
transitionClassNames: storyRibbonClassNames,
isClosing: isStoryRibbonClosing,
} = useShowTransitionDeprecated(isStoryRibbonShown, undefined, undefined, '');
getIsClosing: getIsStoryRibbonClosing,
} = useShowTransition({
isOpen: isStoryRibbonShown,
className: false,
withShouldRender: true,
});
const isStoryRibbonClosing = useDerivedState(getIsStoryRibbonClosing);
const allChatsFolder: ApiChatFolder = useMemo(() => {
return {
@ -282,8 +288,13 @@ const ChatFolders: FC<OwnProps & StateProps> = ({
}, [currentUserId, folderTabs, openChat, setActiveChatFolder]);
const {
shouldRender: shouldRenderPlaceholder, transitionClassNames,
} = useShowTransitionDeprecated(!orderedFolderIds, undefined, true);
ref: placeholderRef,
shouldRender: shouldRenderPlaceholder,
} = useShowTransition({
isOpen: !orderedFolderIds,
noMountTransition: true,
withShouldRender: true,
});
function renderCurrentTab(isActive: boolean) {
const activeFolder = Object.values(chatFoldersById)
@ -310,11 +321,11 @@ const ChatFolders: FC<OwnProps & StateProps> = ({
return (
<div
ref={ref}
className={buildClassName(
'ChatFolders',
shouldRenderFolders && shouldHideFolderTabs && 'ChatFolders--tabs-hidden',
shouldRenderStoryRibbon && 'with-story-ribbon',
storyRibbonClassNames,
)}
>
{shouldRenderStoryRibbon && <StoryRibbon isClosing={isStoryRibbonClosing} />}
@ -327,7 +338,7 @@ const ChatFolders: FC<OwnProps & StateProps> = ({
areFolders
/>
) : shouldRenderPlaceholder ? (
<div className={buildClassName('tabs-placeholder', transitionClassNames)} />
<div ref={placeholderRef} className="tabs-placeholder" />
) : undefined}
<Transition
ref={transitionRef}

View File

@ -9,7 +9,8 @@ import type {
ApiChatReactions,
ApiMessage,
ApiReaction,
ApiStickerSet, ApiStickerSetInfo,
ApiStickerSet,
ApiStickerSetInfo,
ApiThreadInfo,
} from '../../../api/types';
import type { ActiveDownloads, MessageListType } from '../../../global/types';
@ -46,7 +47,8 @@ import {
selectIsMessageProtected,
selectIsMessageUnread,
selectIsPremiumPurchaseBlocked,
selectIsReactionPickerOpen, selectMessageCustomEmojiSets,
selectIsReactionPickerOpen,
selectMessageCustomEmojiSets,
selectMessageTranslations,
selectRequestedChatTranslationLanguage,
selectRequestedMessageTranslationLanguage,
@ -54,7 +56,6 @@ import {
selectThreadInfo,
selectUserStatus,
} from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import { copyTextToClipboard } from '../../../util/clipboard';
import { getSelectionAsFormattedText } from './helpers/getSelectionAsFormattedText';
import { isSelectionRangeInsideMessage } from './helpers/isSelectionRangeInsideMessage';
@ -63,7 +64,7 @@ import useFlag from '../../../hooks/useFlag';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import useSchedule from '../../../hooks/useSchedule';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import PinMessageModal from '../../common/PinMessageModal.async';
import ReportModal from '../../common/ReportModal';
@ -230,7 +231,11 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
} = getActions();
const lang = useOldLang();
const { transitionClassNames } = useShowTransitionDeprecated(isOpen, onCloseAnimationEnd, undefined, false);
const { ref: containerRef } = useShowTransition({
isOpen,
onCloseAnimationEnd,
className: false,
});
const [isMenuOpen, setIsMenuOpen] = useState(true);
const [isReportModalOpen, setIsReportModalOpen] = useState(false);
const [isPinModalOpen, setIsPinModalOpen] = useState(false);
@ -565,7 +570,7 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
scheduledMaxDate.setFullYear(scheduledMaxDate.getFullYear() + 1);
return (
<div className={buildClassName('ContextMenuContainer', transitionClassNames)}>
<div ref={containerRef} className="ContextMenuContainer">
<MessageContextMenu
isReactionPickerOpen={isReactionPickerOpen}
availableReactions={availableReactions}

View File

@ -132,7 +132,7 @@ import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useResizeObserver from '../../../hooks/useResizeObserver';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import useTextLanguage from '../../../hooks/useTextLanguage';
import useThrottledCallback from '../../../hooks/useThrottledCallback';
import useDetectChatLanguage from './hooks/useDetectChatLanguage';
@ -473,12 +473,12 @@ const Message: FC<OwnProps & StateProps> = ({
setTimeout(markShown, appearanceOrder * APPEARANCE_DELAY);
}, [appearanceOrder, markShown, noAppearanceAnimation]);
const { transitionClassNames } = useShowTransitionDeprecated(
isShown || isJustAdded,
undefined,
noAppearanceAnimation && !isJustAdded,
false,
);
useShowTransition({
ref,
isOpen: isShown || isJustAdded,
noMountTransition: noAppearanceAnimation && !isJustAdded,
className: false,
});
const {
id: messageId, chatId, forwardInfo, viaBotId, isTranscriptionError, factCheck,
@ -688,7 +688,6 @@ const Message: FC<OwnProps & StateProps> = ({
isThreadTop && !withAvatar && 'is-thread-top',
Boolean(message.inlineButtons) && 'has-inline-buttons',
isSwiped && 'is-swiped',
transitionClassNames,
isJustAdded && 'is-just-added',
(hasActiveReactions || shouldPlayEffect) && 'has-active-effect',
isStoryMention && 'is-story-mention',

View File

@ -1,10 +1,6 @@
import type { FC } from '../../../lib/teact/teact';
import React, {
useEffect,
useLayoutEffect,
useRef,
useSignal,
useState,
useEffect, useLayoutEffect, useRef, useSignal, useState,
} from '../../../lib/teact/teact';
import { getActions } from '../../../global';
@ -13,7 +9,10 @@ import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
import { ApiMediaFormat } from '../../../api/types';
import {
getMediaFormat, getMessageMediaThumbDataUri, getVideoMediaHash, hasMessageTtl,
getMediaFormat,
getMessageMediaThumbDataUri,
getVideoMediaHash,
hasMessageTtl,
} from '../../../global/helpers';
import { stopCurrentAudio } from '../../../util/audioPlayer';
import buildClassName from '../../../util/buildClassName';
@ -25,10 +24,10 @@ import { useThrottledSignal } from '../../../hooks/useAsyncResolvers';
import useFlag from '../../../hooks/useFlag';
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
import useLastCallback from '../../../hooks/useLastCallback';
import useMediaTransitionDeprecated from '../../../hooks/useMediaTransitionDeprecated';
import useMediaTransition from '../../../hooks/useMediaTransition';
import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
import usePreviousDeprecated from '../../../hooks/usePreviousDeprecated';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import useShowTransition from '../../../hooks/useShowTransition';
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
import Icon from '../../common/icons/Icon';
@ -101,15 +100,19 @@ const RoundVideo: FC<OwnProps> = ({
const hasThumb = Boolean(getMessageMediaThumbDataUri(message));
const noThumb = !hasThumb || isPlayerReady || shouldRenderSpoiler;
const thumbRef = useBlurredMediaThumbRef(video, noThumb);
const thumbClassNames = useMediaTransitionDeprecated(!noThumb);
useMediaTransition(!noThumb, { ref: thumbRef });
const thumbDataUri = getMessageMediaThumbDataUri(message);
const isTransferring = (isLoadAllowed && !isPlayerReady) || isDownloading;
const wasLoadDisabled = usePreviousDeprecated(isLoadAllowed) === false;
const {
shouldRender: shouldSpinnerRender,
transitionClassNames: spinnerClassNames,
} = useShowTransitionDeprecated(isTransferring, undefined, wasLoadDisabled);
ref: spinnerRef,
shouldRender: shouldRenderSpinner,
} = useShowTransition({
isOpen: isTransferring,
noMountTransition: wasLoadDisabled,
withShouldRender: true,
});
const [isActivated, setIsActivated] = useState(false);
@ -260,7 +263,7 @@ const RoundVideo: FC<OwnProps> = ({
{!shouldRenderSpoiler && (
<canvas
ref={thumbRef}
className={buildClassName('thumbnail', thumbClassNames)}
className="thumbnail"
style={`width: ${ROUND_VIDEO_DIMENSIONS_PX}px; height: ${ROUND_VIDEO_DIMENSIONS_PX}px`}
/>
)}
@ -280,12 +283,12 @@ const RoundVideo: FC<OwnProps> = ({
</svg>
)}
</div>
{shouldSpinnerRender && (
<div className={`media-loading ${spinnerClassNames}`}>
{shouldRenderSpinner && (
<div ref={spinnerRef} className="media-loading">
<ProgressSpinner progress={isDownloading ? downloadProgress : loadProgress} />
</div>
)}
{shouldRenderSpoiler && !shouldSpinnerRender && renderPlayWrapper()}
{shouldRenderSpoiler && !shouldRenderSpinner && renderPlayWrapper()}
{!mediaData && !isLoadAllowed && (
<i className="icon icon-download" />
)}

View File

@ -5,12 +5,11 @@ import type { GlobalState } from '../../global/types';
import { ANIMATION_END_DELAY, PREVIEW_AVATAR_COUNT } from '../../config';
import { selectIsForumPanelOpen, selectPerformanceSettingsValue, selectTabState } from '../../global/selectors';
import buildClassName from '../../util/buildClassName';
import { animateClosing, animateOpening, ANIMATION_DURATION } from './helpers/ribbonAnimation';
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
import useOldLang from '../../hooks/useOldLang';
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
import useShowTransition from '../../hooks/useShowTransition';
import useStoryPreloader from './hooks/useStoryPreloader';
import Avatar from '../common/Avatar';
@ -89,7 +88,11 @@ function StoryToggler({
const isVisible = canShow && isShown;
// For some reason, setting 'slow' here also fixes scroll freezes on iOS when collapsing Story Ribbon
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isVisible, undefined, undefined, 'slow');
const { ref, shouldRender } = useShowTransition<HTMLButtonElement>({
isOpen: isVisible,
className: 'slow',
withShouldRender: true,
});
useEffect(() => {
if (!withAnimation || isForumPanelOpen) return;
@ -108,9 +111,10 @@ function StoryToggler({
return (
<button
ref={ref}
type="button"
id="StoryToggler"
className={buildClassName(styles.root, transitionClassNames)}
className={styles.root}
aria-label={lang('Chat.Context.Peer.OpenStory')}
onClick={() => toggleStoryRibbon({ isShown: true, isArchived })}
dir={lang.isRtl ? 'rtl' : undefined}

View File

@ -3,6 +3,7 @@ import { useLayoutEffect, useRef, useSignal } from '../lib/teact/teact';
import { addExtraClass, toggleExtraClass } from '../lib/teact/teact-dom';
import { requestMeasure } from '../lib/fasterdom/fasterdom';
import useDerivedSignal from './useDerivedSignal';
import useDerivedState from './useDerivedState';
import useLastCallback from './useLastCallback';
import { useStateRef } from './useStateRef';
@ -82,8 +83,8 @@ export default function useShowTransition<RefType extends HTMLElement = HTMLDivE
const element = ref.current;
if (!element) return;
addExtraClass(element, 'opacity-transition');
if (className !== false) {
addExtraClass(element, 'opacity-transition');
addExtraClass(element, className);
}
@ -103,6 +104,7 @@ export default function useShowTransition<RefType extends HTMLElement = HTMLDivE
() => (withShouldRender && getState() !== 'closed'),
[withShouldRender, getState],
);
const getIsClosing = useDerivedSignal(() => getState() === 'closing', [getState]);
return { ref, shouldRender };
return { ref, shouldRender, getIsClosing };
}