From 1ad2e816a21d19654e3e9fc6d9c919b77265a067 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Thu, 30 Mar 2023 18:25:14 -0500 Subject: [PATCH] Forum Panel: Optimize opening animation on Android (#2856) --- src/components/left/ArchivedChats.tsx | 11 +++++--- src/components/left/main/ChatFolders.tsx | 5 ++-- src/components/left/main/ForumPanel.tsx | 34 +++++++++++++++--------- src/components/left/main/LeftMain.tsx | 14 +++++++--- src/hooks/useForumPanelRender.ts | 9 +++++++ 5 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/components/left/ArchivedChats.tsx b/src/components/left/ArchivedChats.tsx index 086d761b1..342d5533c 100644 --- a/src/components/left/ArchivedChats.tsx +++ b/src/components/left/ArchivedChats.tsx @@ -64,7 +64,11 @@ const ArchivedChats: FC = ({ transitionClassNames: titleClassNames, } = useShowTransition(!isForumPanelOpen); - const { shouldRenderForumPanel, handleForumPanelAnimationEnd } = useForumPanelRender(isForumPanelOpen); + const { + shouldRenderForumPanel, handleForumPanelAnimationEnd, + handleForumPanelAnimationStart, isAnimationStarted, + } = useForumPanelRender(isForumPanelOpen); + const isForumPanelVisible = isForumPanelOpen && isAnimationStarted; return (
@@ -78,7 +82,7 @@ const ArchivedChats: FC = ({ ariaLabel="Return to chat list" className={buildClassName( lang.isRtl && 'rtl', - isForumPanelOpen && lang.isRtl && 'right-aligned', + isForumPanelVisible && lang.isRtl && 'right-aligned', shouldDisableDropdownMenuTransitionRef.current && lang.isRtl && 'disable-transition', )} onTransitionEnd={handleDropdownMenuTransitionEnd} @@ -101,7 +105,7 @@ const ArchivedChats: FC = ({ = ({ )} diff --git a/src/components/left/main/ChatFolders.tsx b/src/components/left/main/ChatFolders.tsx index 1d93db8c8..a5ed269d4 100644 --- a/src/components/left/main/ChatFolders.tsx +++ b/src/components/left/main/ChatFolders.tsx @@ -15,7 +15,7 @@ import { captureEvents, SwipeDirection } from '../../../util/captureEvents'; import buildClassName from '../../../util/buildClassName'; import captureEscKeyListener from '../../../util/captureEscKeyListener'; import { selectCurrentLimit } from '../../../global/selectors/limits'; -import { selectTabState, selectIsForumPanelOpen } from '../../../global/selectors'; +import { selectTabState } from '../../../global/selectors'; import useShowTransition from '../../../hooks/useShowTransition'; import useLang from '../../../hooks/useLang'; import useHistoryBack from '../../../hooks/useHistoryBack'; @@ -30,6 +30,7 @@ type OwnProps = { foldersDispatch: FolderEditDispatch; onLeftColumnContentChange: (content: LeftColumnContent) => void; shouldHideFolderTabs?: boolean; + isForumPanelOpen?: boolean; }; type StateProps = { @@ -37,7 +38,6 @@ type StateProps = { orderedFolderIds?: number[]; activeChatFolder: number; currentUserId?: string; - isForumPanelOpen?: boolean; lastSyncTime?: number; shouldSkipHistoryAnimations?: boolean; maxFolders: number; @@ -275,7 +275,6 @@ export default memo(withGlobal( orderedFolderIds, activeChatFolder, currentUserId, - isForumPanelOpen: selectIsForumPanelOpen(global), lastSyncTime, shouldSkipHistoryAnimations, hasArchivedChats: Boolean(archived?.length), diff --git a/src/components/left/main/ForumPanel.tsx b/src/components/left/main/ForumPanel.tsx index f84cde4f6..10f266b01 100644 --- a/src/components/left/main/ForumPanel.tsx +++ b/src/components/left/main/ForumPanel.tsx @@ -20,6 +20,7 @@ import { getOrderedTopics } from '../../../global/helpers'; import captureEscKeyListener from '../../../util/captureEscKeyListener'; import { waitForTransitionEnd } from '../../../util/cssAnimationEndListeners'; import { captureEvents, SwipeDirection } from '../../../util/captureEvents'; +import { fastRaf } from '../../../util/schedulers'; import useInfiniteScroll from '../../../hooks/useInfiniteScroll'; import { useIntersectionObserver, useOnIntersect } from '../../../hooks/useIntersectionObserver'; @@ -46,6 +47,7 @@ type OwnProps = { isHidden?: boolean; onTopicSearch?: NoneToVoidFunction; onCloseAnimationEnd?: VoidFunction; + onOpenAnimationStart?: VoidFunction; }; type StateProps = { @@ -65,6 +67,7 @@ const ForumPanel: FC = ({ lastSyncTime, onTopicSearch, onCloseAnimationEnd, + onOpenAnimationStart, animationLevel, }) => { const { @@ -143,20 +146,27 @@ const ForumPanel: FC = ({ useEffect(() => { if (prevIsVisible !== isVisible) { - const dispatchHeavyAnimationStop = dispatchHeavyAnimationEvent(); - waitForTransitionEnd(ref.current!, () => { - dispatchHeavyAnimationStop(); - }); + // For performance reasons, we delay animation of the topic list panel to the next animation frame + fastRaf(() => { + if (!ref.current) return; - if (isVisible) { - shouldRenderRef.current = true; - ref.current!.style.transform = 'none'; - } else { - shouldRenderRef.current = false; - ref.current!.style.transform = ''; - } + const dispatchHeavyAnimationStop = dispatchHeavyAnimationEvent(); + waitForTransitionEnd(ref.current, () => { + dispatchHeavyAnimationStop(); + }); + + onOpenAnimationStart?.(); + + if (isVisible) { + shouldRenderRef.current = true; + ref.current!.style.transform = 'none'; + } else { + shouldRenderRef.current = false; + ref.current!.style.transform = ''; + } + }); } - }, [isVisible, prevIsVisible]); + }, [isVisible, onOpenAnimationStart, prevIsVisible]); useEffect(() => { if (!IS_TOUCH_ENV) { diff --git a/src/components/left/main/LeftMain.tsx b/src/components/left/main/LeftMain.tsx index 0bd22aaaf..aa5cdd984 100644 --- a/src/components/left/main/LeftMain.tsx +++ b/src/components/left/main/LeftMain.tsx @@ -2,6 +2,7 @@ import type { FC } from '../../../lib/teact/teact'; import React, { memo, useCallback, useEffect, useRef, useState, } from '../../../lib/teact/teact'; +import { getActions } from '../../../global'; import type { SettingsScreens } from '../../../types'; import { LeftColumnContent } from '../../../types'; @@ -23,7 +24,6 @@ import Button from '../../ui/Button'; import ForumPanel from './ForumPanel'; import './LeftMain.scss'; -import { getActions } from '../../../global'; type OwnProps = { content: LeftColumnContent; @@ -66,8 +66,12 @@ const LeftMain: FC = ({ const { closeForumPanel } = getActions(); const [isNewChatButtonShown, setIsNewChatButtonShown] = useState(IS_TOUCH_ENV); - const { shouldRenderForumPanel, handleForumPanelAnimationEnd } = useForumPanelRender(isForumPanelOpen); - const isForumPanelVisible = isForumPanelOpen && content === LeftColumnContent.ChatList; + const { + shouldRenderForumPanel, handleForumPanelAnimationEnd, + handleForumPanelAnimationStart, isAnimationStarted, + } = useForumPanelRender(isForumPanelOpen); + const isForumPanelRendered = isForumPanelOpen && content === LeftColumnContent.ChatList; + const isForumPanelVisible = isForumPanelRendered && isAnimationStarted; const { shouldRender: shouldRenderUpdateButton, @@ -178,6 +182,7 @@ const LeftMain: FC = ({ onSettingsScreenSelect={onSettingsScreenSelect} onLeftColumnContentChange={onContentChange} foldersDispatch={foldersDispatch} + isForumPanelOpen={isForumPanelVisible} /> ); case LeftColumnContent.GlobalSearch: @@ -209,8 +214,9 @@ const LeftMain: FC = ({ {shouldRenderForumPanel && ( )} diff --git a/src/hooks/useForumPanelRender.ts b/src/hooks/useForumPanelRender.ts index 71367be5a..438d3e478 100644 --- a/src/hooks/useForumPanelRender.ts +++ b/src/hooks/useForumPanelRender.ts @@ -5,6 +5,7 @@ import useSyncEffect from './useSyncEffect'; export default function useForumPanelRender(isForumPanelOpen = false) { const shouldRenderForumPanelRef = useRef(isForumPanelOpen); + const isAnimationStartedRef = useRef(false); const forceUpdate = useForceUpdate(); useSyncEffect(() => { @@ -15,11 +16,19 @@ export default function useForumPanelRender(isForumPanelOpen = false) { const handleForumPanelAnimationEnd = useCallback(() => { shouldRenderForumPanelRef.current = false; + isAnimationStartedRef.current = false; forceUpdate(); }, [forceUpdate]); + const handleForumPanelAnimationStart = useCallback(() => { + isAnimationStartedRef.current = true; + forceUpdate(); + }, []); + return { shouldRenderForumPanel: shouldRenderForumPanelRef.current, + isAnimationStarted: isAnimationStartedRef.current, handleForumPanelAnimationEnd, + handleForumPanelAnimationStart, }; }