Forum Panel: Optimize opening animation on Android (#2856)

This commit is contained in:
Alexander Zinchuk 2023-03-30 18:25:14 -05:00
parent fd7c7b5dc2
commit 1ad2e816a2
5 changed files with 51 additions and 22 deletions

View File

@ -64,7 +64,11 @@ const ArchivedChats: FC<OwnProps> = ({
transitionClassNames: titleClassNames, transitionClassNames: titleClassNames,
} = useShowTransition(!isForumPanelOpen); } = useShowTransition(!isForumPanelOpen);
const { shouldRenderForumPanel, handleForumPanelAnimationEnd } = useForumPanelRender(isForumPanelOpen); const {
shouldRenderForumPanel, handleForumPanelAnimationEnd,
handleForumPanelAnimationStart, isAnimationStarted,
} = useForumPanelRender(isForumPanelOpen);
const isForumPanelVisible = isForumPanelOpen && isAnimationStarted;
return ( return (
<div className="ArchivedChats"> <div className="ArchivedChats">
@ -78,7 +82,7 @@ const ArchivedChats: FC<OwnProps> = ({
ariaLabel="Return to chat list" ariaLabel="Return to chat list"
className={buildClassName( className={buildClassName(
lang.isRtl && 'rtl', lang.isRtl && 'rtl',
isForumPanelOpen && lang.isRtl && 'right-aligned', isForumPanelVisible && lang.isRtl && 'right-aligned',
shouldDisableDropdownMenuTransitionRef.current && lang.isRtl && 'disable-transition', shouldDisableDropdownMenuTransitionRef.current && lang.isRtl && 'disable-transition',
)} )}
onTransitionEnd={handleDropdownMenuTransitionEnd} onTransitionEnd={handleDropdownMenuTransitionEnd}
@ -101,7 +105,7 @@ const ArchivedChats: FC<OwnProps> = ({
<ChatList <ChatList
folderType="archived" folderType="archived"
isActive={isActive} isActive={isActive}
isForumPanelOpen={isForumPanelOpen} isForumPanelOpen={isForumPanelVisible}
onSettingsScreenSelect={onSettingsScreenSelect} onSettingsScreenSelect={onSettingsScreenSelect}
onLeftColumnContentChange={onLeftColumnContentChange} onLeftColumnContentChange={onLeftColumnContentChange}
foldersDispatch={foldersDispatch} foldersDispatch={foldersDispatch}
@ -111,6 +115,7 @@ const ArchivedChats: FC<OwnProps> = ({
<ForumPanel <ForumPanel
isOpen={isForumPanelOpen} isOpen={isForumPanelOpen}
onTopicSearch={onTopicSearch} onTopicSearch={onTopicSearch}
onOpenAnimationStart={handleForumPanelAnimationStart}
onCloseAnimationEnd={handleForumPanelAnimationEnd} onCloseAnimationEnd={handleForumPanelAnimationEnd}
/> />
)} )}

View File

@ -15,7 +15,7 @@ import { captureEvents, SwipeDirection } from '../../../util/captureEvents';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import captureEscKeyListener from '../../../util/captureEscKeyListener'; import captureEscKeyListener from '../../../util/captureEscKeyListener';
import { selectCurrentLimit } from '../../../global/selectors/limits'; import { selectCurrentLimit } from '../../../global/selectors/limits';
import { selectTabState, selectIsForumPanelOpen } from '../../../global/selectors'; import { selectTabState } from '../../../global/selectors';
import useShowTransition from '../../../hooks/useShowTransition'; import useShowTransition from '../../../hooks/useShowTransition';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import useHistoryBack from '../../../hooks/useHistoryBack'; import useHistoryBack from '../../../hooks/useHistoryBack';
@ -30,6 +30,7 @@ type OwnProps = {
foldersDispatch: FolderEditDispatch; foldersDispatch: FolderEditDispatch;
onLeftColumnContentChange: (content: LeftColumnContent) => void; onLeftColumnContentChange: (content: LeftColumnContent) => void;
shouldHideFolderTabs?: boolean; shouldHideFolderTabs?: boolean;
isForumPanelOpen?: boolean;
}; };
type StateProps = { type StateProps = {
@ -37,7 +38,6 @@ type StateProps = {
orderedFolderIds?: number[]; orderedFolderIds?: number[];
activeChatFolder: number; activeChatFolder: number;
currentUserId?: string; currentUserId?: string;
isForumPanelOpen?: boolean;
lastSyncTime?: number; lastSyncTime?: number;
shouldSkipHistoryAnimations?: boolean; shouldSkipHistoryAnimations?: boolean;
maxFolders: number; maxFolders: number;
@ -275,7 +275,6 @@ export default memo(withGlobal<OwnProps>(
orderedFolderIds, orderedFolderIds,
activeChatFolder, activeChatFolder,
currentUserId, currentUserId,
isForumPanelOpen: selectIsForumPanelOpen(global),
lastSyncTime, lastSyncTime,
shouldSkipHistoryAnimations, shouldSkipHistoryAnimations,
hasArchivedChats: Boolean(archived?.length), hasArchivedChats: Boolean(archived?.length),

View File

@ -20,6 +20,7 @@ import { getOrderedTopics } from '../../../global/helpers';
import captureEscKeyListener from '../../../util/captureEscKeyListener'; import captureEscKeyListener from '../../../util/captureEscKeyListener';
import { waitForTransitionEnd } from '../../../util/cssAnimationEndListeners'; import { waitForTransitionEnd } from '../../../util/cssAnimationEndListeners';
import { captureEvents, SwipeDirection } from '../../../util/captureEvents'; import { captureEvents, SwipeDirection } from '../../../util/captureEvents';
import { fastRaf } from '../../../util/schedulers';
import useInfiniteScroll from '../../../hooks/useInfiniteScroll'; import useInfiniteScroll from '../../../hooks/useInfiniteScroll';
import { useIntersectionObserver, useOnIntersect } from '../../../hooks/useIntersectionObserver'; import { useIntersectionObserver, useOnIntersect } from '../../../hooks/useIntersectionObserver';
@ -46,6 +47,7 @@ type OwnProps = {
isHidden?: boolean; isHidden?: boolean;
onTopicSearch?: NoneToVoidFunction; onTopicSearch?: NoneToVoidFunction;
onCloseAnimationEnd?: VoidFunction; onCloseAnimationEnd?: VoidFunction;
onOpenAnimationStart?: VoidFunction;
}; };
type StateProps = { type StateProps = {
@ -65,6 +67,7 @@ const ForumPanel: FC<OwnProps & StateProps> = ({
lastSyncTime, lastSyncTime,
onTopicSearch, onTopicSearch,
onCloseAnimationEnd, onCloseAnimationEnd,
onOpenAnimationStart,
animationLevel, animationLevel,
}) => { }) => {
const { const {
@ -143,20 +146,27 @@ const ForumPanel: FC<OwnProps & StateProps> = ({
useEffect(() => { useEffect(() => {
if (prevIsVisible !== isVisible) { if (prevIsVisible !== isVisible) {
const dispatchHeavyAnimationStop = dispatchHeavyAnimationEvent(); // For performance reasons, we delay animation of the topic list panel to the next animation frame
waitForTransitionEnd(ref.current!, () => { fastRaf(() => {
dispatchHeavyAnimationStop(); if (!ref.current) return;
});
if (isVisible) { const dispatchHeavyAnimationStop = dispatchHeavyAnimationEvent();
shouldRenderRef.current = true; waitForTransitionEnd(ref.current, () => {
ref.current!.style.transform = 'none'; dispatchHeavyAnimationStop();
} else { });
shouldRenderRef.current = false;
ref.current!.style.transform = ''; 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(() => { useEffect(() => {
if (!IS_TOUCH_ENV) { if (!IS_TOUCH_ENV) {

View File

@ -2,6 +2,7 @@ import type { FC } from '../../../lib/teact/teact';
import React, { import React, {
memo, useCallback, useEffect, useRef, useState, memo, useCallback, useEffect, useRef, useState,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { getActions } from '../../../global';
import type { SettingsScreens } from '../../../types'; import type { SettingsScreens } from '../../../types';
import { LeftColumnContent } from '../../../types'; import { LeftColumnContent } from '../../../types';
@ -23,7 +24,6 @@ import Button from '../../ui/Button';
import ForumPanel from './ForumPanel'; import ForumPanel from './ForumPanel';
import './LeftMain.scss'; import './LeftMain.scss';
import { getActions } from '../../../global';
type OwnProps = { type OwnProps = {
content: LeftColumnContent; content: LeftColumnContent;
@ -66,8 +66,12 @@ const LeftMain: FC<OwnProps> = ({
const { closeForumPanel } = getActions(); const { closeForumPanel } = getActions();
const [isNewChatButtonShown, setIsNewChatButtonShown] = useState(IS_TOUCH_ENV); const [isNewChatButtonShown, setIsNewChatButtonShown] = useState(IS_TOUCH_ENV);
const { shouldRenderForumPanel, handleForumPanelAnimationEnd } = useForumPanelRender(isForumPanelOpen); const {
const isForumPanelVisible = isForumPanelOpen && content === LeftColumnContent.ChatList; shouldRenderForumPanel, handleForumPanelAnimationEnd,
handleForumPanelAnimationStart, isAnimationStarted,
} = useForumPanelRender(isForumPanelOpen);
const isForumPanelRendered = isForumPanelOpen && content === LeftColumnContent.ChatList;
const isForumPanelVisible = isForumPanelRendered && isAnimationStarted;
const { const {
shouldRender: shouldRenderUpdateButton, shouldRender: shouldRenderUpdateButton,
@ -178,6 +182,7 @@ const LeftMain: FC<OwnProps> = ({
onSettingsScreenSelect={onSettingsScreenSelect} onSettingsScreenSelect={onSettingsScreenSelect}
onLeftColumnContentChange={onContentChange} onLeftColumnContentChange={onContentChange}
foldersDispatch={foldersDispatch} foldersDispatch={foldersDispatch}
isForumPanelOpen={isForumPanelVisible}
/> />
); );
case LeftColumnContent.GlobalSearch: case LeftColumnContent.GlobalSearch:
@ -209,8 +214,9 @@ const LeftMain: FC<OwnProps> = ({
{shouldRenderForumPanel && ( {shouldRenderForumPanel && (
<ForumPanel <ForumPanel
isOpen={isForumPanelOpen} isOpen={isForumPanelOpen}
isHidden={!isForumPanelVisible} isHidden={!isForumPanelRendered}
onTopicSearch={onTopicSearch} onTopicSearch={onTopicSearch}
onOpenAnimationStart={handleForumPanelAnimationStart}
onCloseAnimationEnd={handleForumPanelAnimationEnd} onCloseAnimationEnd={handleForumPanelAnimationEnd}
/> />
)} )}

View File

@ -5,6 +5,7 @@ import useSyncEffect from './useSyncEffect';
export default function useForumPanelRender(isForumPanelOpen = false) { export default function useForumPanelRender(isForumPanelOpen = false) {
const shouldRenderForumPanelRef = useRef(isForumPanelOpen); const shouldRenderForumPanelRef = useRef(isForumPanelOpen);
const isAnimationStartedRef = useRef(false);
const forceUpdate = useForceUpdate(); const forceUpdate = useForceUpdate();
useSyncEffect(() => { useSyncEffect(() => {
@ -15,11 +16,19 @@ export default function useForumPanelRender(isForumPanelOpen = false) {
const handleForumPanelAnimationEnd = useCallback(() => { const handleForumPanelAnimationEnd = useCallback(() => {
shouldRenderForumPanelRef.current = false; shouldRenderForumPanelRef.current = false;
isAnimationStartedRef.current = false;
forceUpdate(); forceUpdate();
}, [forceUpdate]); }, [forceUpdate]);
const handleForumPanelAnimationStart = useCallback(() => {
isAnimationStartedRef.current = true;
forceUpdate();
}, []);
return { return {
shouldRenderForumPanel: shouldRenderForumPanelRef.current, shouldRenderForumPanel: shouldRenderForumPanelRef.current,
isAnimationStarted: isAnimationStartedRef.current,
handleForumPanelAnimationEnd, handleForumPanelAnimationEnd,
handleForumPanelAnimationStart,
}; };
} }