Avatar: Animate online status

This commit is contained in:
Alexander Zinchuk 2023-04-17 22:57:07 +02:00
parent c722a3ba30
commit 8be0459193
2 changed files with 31 additions and 19 deletions

View File

@ -124,8 +124,7 @@
} }
} }
&.online { &.online::after {
&::after {
content: ""; content: "";
display: block; display: block;
position: absolute; position: absolute;
@ -137,7 +136,15 @@
border: 2px solid var(--color-background); border: 2px solid var(--color-background);
background-color: #0ac630; background-color: #0ac630;
flex-shrink: 0; flex-shrink: 0;
opacity: 0.5;
transform: scale(0);
transition: opacity 200ms, transform 200ms;
} }
&.online-open::after {
opacity: 1;
transform: scale(1);
} }
&.interactive { &.interactive {

View File

@ -1,6 +1,6 @@
import type { MouseEvent as ReactMouseEvent } from 'react'; import type { MouseEvent as ReactMouseEvent } from 'react';
import React, { import React, {
memo, useCallback, useEffect, useRef, memo, useCallback, useEffect, useMemo, useRef,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { getActions } from '../../global'; import { getActions } from '../../global';
@ -29,7 +29,7 @@ import buildClassName, { createClassNameBuilder } from '../../util/buildClassNam
import renderText from './helpers/renderText'; import renderText from './helpers/renderText';
import useMedia from '../../hooks/useMedia'; import useMedia from '../../hooks/useMedia';
import useShowTransition from '../../hooks/useShowTransition'; import useMediaTransition from '../../hooks/useMediaTransition';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import { useIsIntersecting } from '../../hooks/useIntersectionObserver'; import { useIsIntersecting } from '../../hooks/useIntersectionObserver';
@ -127,7 +127,13 @@ const Avatar: FC<OwnProps> = ({
// `videoBlobUrl` can be taken from memory cache, so we need to check `shouldLoadVideo` again // `videoBlobUrl` can be taken from memory cache, so we need to check `shouldLoadVideo` again
const shouldPlayVideo = Boolean(isIntersectingForVideo && videoBlobUrl && shouldLoadVideo); const shouldPlayVideo = Boolean(isIntersectingForVideo && videoBlobUrl && shouldLoadVideo);
const { transitionClassNames } = useShowTransition(hasBlobUrl, undefined, hasBlobUrl, 'slow'); const transitionClassNames = useMediaTransition(hasBlobUrl);
const isOnline = !isSavedMessages && user && userStatus && isUserOnline(user, userStatus);
const onlineTransitionClassNames = useMediaTransition(isOnline);
const onlineClassNamesPrefixed = useMemo(() => {
return onlineTransitionClassNames.split(' ').map((c) => (c === 'shown' ? 'online' : `online-${c}`)).join(' ');
}, [onlineTransitionClassNames]);
const handleVideoEnded = useCallback((e) => { const handleVideoEnded = useCallback((e) => {
const video = e.currentTarget; const video = e.currentTarget;
@ -193,7 +199,6 @@ const Avatar: FC<OwnProps> = ({
content = getFirstLetters(text, 2); content = getFirstLetters(text, 2);
} }
const isOnline = !isSavedMessages && user && userStatus && isUserOnline(user, userStatus);
const fullClassName = buildClassName( const fullClassName = buildClassName(
`Avatar size-${size}`, `Avatar size-${size}`,
className, className,
@ -202,7 +207,7 @@ const Avatar: FC<OwnProps> = ({
isDeleted && 'deleted-account', isDeleted && 'deleted-account',
isReplies && 'replies-bot-account', isReplies && 'replies-bot-account',
isForum && 'forum', isForum && 'forum',
isOnline && 'online', onlineClassNamesPrefixed,
onClick && 'interactive', onClick && 'interactive',
(!isSavedMessages && !imgBlobUrl) && 'no-photo', (!isSavedMessages && !imgBlobUrl) && 'no-photo',
); );