Forum Panel: Optimize some animations

This commit is contained in:
Alexander Zinchuk 2023-01-07 04:04:38 +01:00
parent dad789717b
commit cbf9845ab9
8 changed files with 36 additions and 51 deletions

View File

@ -18,10 +18,11 @@ type OwnProps = {
isPinned?: boolean; isPinned?: boolean;
isMuted?: boolean; isMuted?: boolean;
shouldShowOnlyMostImportant?: boolean; shouldShowOnlyMostImportant?: boolean;
forceHidden?: boolean;
}; };
const Badge: FC<OwnProps> = ({ const Badge: FC<OwnProps> = ({
topic, chat, isPinned, isMuted, shouldShowOnlyMostImportant, wasTopicOpened, topic, chat, isPinned, isMuted, shouldShowOnlyMostImportant, wasTopicOpened, forceHidden,
}) => { }) => {
const { const {
unreadMentionsCount = 0, unreadReactionsCount = 0, unreadMentionsCount = 0, unreadReactionsCount = 0,
@ -50,7 +51,7 @@ const Badge: FC<OwnProps> = ({
const hasUnreadMark = topic ? false : chat.hasUnreadMark; const hasUnreadMark = topic ? false : chat.hasUnreadMark;
const isShown = Boolean( const isShown = !forceHidden && Boolean(
unreadCount || unreadMentionsCount || hasUnreadMark || isPinned || unreadReactionsCount unreadCount || unreadMentionsCount || hasUnreadMark || isPinned || unreadReactionsCount
|| isTopicUnopened, || isTopicUnopened,
); );

View File

@ -15,12 +15,12 @@
&.animate-opacity { &.animate-opacity {
will-change: opacity; will-change: opacity;
transition: opacity 0.2s ease-out; transition: opacity 250ms ease;
} }
&.animate-transform { &.animate-transform {
will-change: transform; will-change: transform;
transition: transform 0.2s ease-out; transition: transform 250ms ease;
} }
&:hover, &:hover,
@ -175,28 +175,19 @@
right: 0.5rem; right: 0.5rem;
z-index: 2; z-index: 2;
transition-duration: 0.25s;
transition-timing-function: cubic-bezier(0.16,1.25,0.64,1);
transition-property: opacity, transform;
opacity: 0;
transform: scale(0);
--outline-color: var(--color-background); --outline-color: var(--color-background);
.Badge { .Badge {
box-shadow: 0 0 0 2px var(--outline-color); box-shadow: 0 0 0 2px var(--outline-color);
} }
}
.status-badge-wrapper-visible { .Badge-transition {
opacity: 1; transition: opacity 250ms ease, transform 250ms ease; // Same as Forum Panel
transform: scale(1); }
} }
.info { .info {
transition-duration: 0.25s; transition: opacity 250ms ease, transform 250ms ease; // Same as Forum Panel
transition-property: ease-in-out;
transition-property: opacity, transform;
.subtitle { .subtitle {
margin-top: -0.125rem; margin-top: -0.125rem;

View File

@ -1,6 +1,6 @@
import type { FC } from '../../../lib/teact/teact'; import type { FC } from '../../../lib/teact/teact';
import React, { import React, {
memo, useCallback, useEffect, useRef, memo, useCallback, useEffect, useLayoutEffect, useRef,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global'; import { getActions, withGlobal } from '../../../global';
@ -234,7 +234,7 @@ const Chat: FC<OwnProps & StateProps> = ({
} }
// Animate changing to smaller chat size when navigating to/from forum topic list // Animate changing to smaller chat size when navigating to/from forum topic list
useEffect(() => { useLayoutEffect(() => {
const current = ref.current; const current = ref.current;
if (current && isAnimatingRef.current && isForumPanelActive !== prevIsForumPanelActive) { if (current && isAnimatingRef.current && isForumPanelActive !== prevIsForumPanelActive) {
@ -288,12 +288,8 @@ const Chat: FC<OwnProps & StateProps> = ({
withVideo withVideo
observeIntersection={observeIntersection} observeIntersection={observeIntersection}
/> />
<div className={buildClassName( <div className="status-badge-wrapper">
'status-badge-wrapper', <Badge chat={chat} isMuted={isMuted} shouldShowOnlyMostImportant forceHidden={!isForumPanelActive} />
isForumPanelActive && 'status-badge-wrapper-visible',
)}
>
<Badge chat={chat} isMuted={isMuted} shouldShowOnlyMostImportant />
</div> </div>
{chat.isCallActive && chat.isCallNotEmpty && ( {chat.isCallActive && chat.isCallNotEmpty && (
<ChatCallStatus isSelected={isSelected} isActive={animationLevel !== 0} /> <ChatCallStatus isSelected={isSelected} isActive={animationLevel !== 0} />

View File

@ -18,7 +18,7 @@
border-right: 1px solid var(--color-borders); border-right: 1px solid var(--color-borders);
} }
transition: transform var(--slide-transition); transition: transform 250ms ease; // Same as `.Chat > .info`
transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0);
:global(.chat-list) { :global(.chat-list) {
@ -39,15 +39,17 @@
position: static !important; position: static !important;
} }
.border-bottom { .notch {
width: 100%; width: 100%;
height: 0; height: 0;
transition: 0.1s ease-out border-color; border-bottom: 0.0625rem solid var(--color-borders);
border-bottom: 0.0625rem solid transparent;
transition: 0.1s ease opacity;
opacity: 0;
} }
.scrolled .border-bottom { .scrolled .notch {
border-color: var(--color-borders); opacity: 1;
} }
.scroll-top-handler { .scroll-top-handler {

View File

@ -13,7 +13,6 @@ import {
} from '../../../config'; } from '../../../config';
import { selectChat, selectCurrentMessageList } from '../../../global/selectors'; import { selectChat, selectCurrentMessageList } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { fastRaf } from '../../../util/schedulers';
import { getOrderedTopics } from '../../../global/helpers'; 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';
@ -135,16 +134,13 @@ const ForumPanel: FC<OwnProps & StateProps> = ({
dispatchHeavyAnimationStop(); dispatchHeavyAnimationStop();
}); });
// For performance reasons, we delay animation of the topic list panel to the next animation frame if (isVisible) {
fastRaf(() => { shouldRenderRef.current = true;
if (isVisible) { ref.current!.style.transform = 'none';
shouldRenderRef.current = true; } else {
ref.current!.style.transform = 'none'; shouldRenderRef.current = false;
} else { ref.current!.style.transform = '';
shouldRenderRef.current = false; }
ref.current!.style.transform = '';
}
});
} }
}, [isVisible, prevIsVisible]); }, [isVisible, prevIsVisible]);
@ -212,7 +208,7 @@ const ForumPanel: FC<OwnProps & StateProps> = ({
{chat && <GroupCallTopPane chatId={chat.id} hasPinnedOffset={false} className={styles.groupCall} />} {chat && <GroupCallTopPane chatId={chat.id} hasPinnedOffset={false} className={styles.groupCall} />}
<div className={styles.borderBottom} /> <div className={styles.notch} />
<InfiniteScroll <InfiniteScroll
className="chat-list custom-scroll" className="chat-list custom-scroll"

View File

@ -17,7 +17,7 @@
flex-direction: column; flex-direction: column;
overflow: hidden; overflow: hidden;
transition: 0.25s ease-out transform; transition: transform 250ms ease; // Same as Forum Panel
&--tabs-hidden { &--tabs-hidden {
transform: translateY(-3.125rem); transform: translateY(-3.125rem);

View File

@ -102,9 +102,7 @@
} }
.SearchInput { .SearchInput {
transition-duration: 0.25s; transition: opacity 250ms ease; // Same as Forum Panel
transition-timing-function: ease-out;
transition-property: opacity;
&--hidden { &--hidden {
opacity: 0; opacity: 0;

View File

@ -26,15 +26,16 @@ const ShowTransition: FC<OwnProps> = ({
children, children,
noCloseTransition, noCloseTransition,
}) => { }) => {
const prevIsOpen = usePrevious(isOpen);
const prevChildren = usePrevious(children);
const fromChildrenRef = useRef<React.ReactNode>();
const isFirstRender = prevIsOpen === undefined;
const { const {
shouldRender, shouldRender,
transitionClassNames, transitionClassNames,
} = useShowTransition( } = useShowTransition(
isOpen && !isHidden, undefined, undefined, isCustom ? false : undefined, noCloseTransition, isOpen && !isHidden, undefined, isFirstRender, isCustom ? false : undefined, noCloseTransition,
); );
const prevIsOpen = usePrevious(isOpen);
const prevChildren = usePrevious(children);
const fromChildrenRef = useRef<React.ReactNode>();
if (prevIsOpen && !isOpen) { if (prevIsOpen && !isOpen) {
fromChildrenRef.current = prevChildren; fromChildrenRef.current = prevChildren;