[Refactoring] RLottie: Make size required

This commit is contained in:
Alexander Zinchuk 2023-04-23 18:33:21 +04:00
parent cfc71da0c1
commit 649fb46777
7 changed files with 27 additions and 49 deletions

View File

@ -28,7 +28,7 @@ export type OwnProps = {
playSegment?: [number, number];
speed?: number;
noLoop?: boolean;
size?: number;
size: number;
quality?: number;
color?: [number, number, number];
isLowPriority?: boolean;
@ -126,14 +126,14 @@ const AnimatedSticker: FC<OwnProps> = ({
tgsUrl,
container,
renderId || generateIdFor(ID_STORE, true),
viewId,
{
noLoop,
size,
noLoop,
quality,
isLowPriority,
coords: sharedCanvasCoords,
},
viewId,
color,
onLoad,
onEnded,
@ -152,18 +152,12 @@ const AnimatedSticker: FC<OwnProps> = ({
]);
useEffect(() => {
if (animation || !tgsUrl || (sharedCanvas && !sharedCanvasCoords)) {
return;
}
if (RLottie) {
init();
} else {
ensureLottie().then(() => {
requestMeasure(init);
});
ensureLottie().then(init);
}
}, [animation, init, sharedCanvas, sharedCanvasCoords, tgsUrl]);
}, [init]);
const throttledInit = useThrottledCallback(init, [init], THROTTLE_MS);
useSharedIntersectionObserver(sharedCanvas, throttledInit);

View File

@ -10,7 +10,7 @@ import { EMOJI_SIZE_PICKER } from '../../config';
import buildClassName from '../../util/buildClassName';
import { getDocumentMediaHash, isSameReaction } from '../../global/helpers';
import useBoundsInSharedCanvas from '../../hooks/useBoundsInSharedCanvas';
import useCoordsInSharedCanvas from '../../hooks/useCoordsInSharedCanvas';
import useMediaTransition from '../../hooks/useMediaTransition';
import useMedia from '../../hooks/useMedia';
@ -49,7 +49,7 @@ const ReactionEmoji: FC<OwnProps> = ({
), [availableReactions, reaction]);
const thumbDataUri = availableReaction?.staticIcon?.thumbnail?.dataUri;
const animationId = availableReaction?.selectAnimation?.id;
const bounds = useBoundsInSharedCanvas(ref, sharedCanvasHqRef);
const coords = useCoordsInSharedCanvas(ref, sharedCanvasHqRef);
const mediaData = useMedia(
availableReaction?.selectAnimation ? getDocumentMediaHash(availableReaction.selectAnimation) : undefined,
!animationId,
@ -91,7 +91,7 @@ const ReactionEmoji: FC<OwnProps> = ({
size={EMOJI_SIZE_PICKER}
className={transitionClassNames}
sharedCanvas={sharedCanvasHqRef!.current || undefined}
sharedCanvasCoords={bounds.coords}
sharedCanvasCoords={coords}
/>
)}
</div>

View File

@ -17,7 +17,7 @@ import { useIsIntersecting } from '../../hooks/useIntersectionObserver';
import useThumbnail from '../../hooks/useThumbnail';
import useMediaTransition from '../../hooks/useMediaTransition';
import useFlag from '../../hooks/useFlag';
import useBoundsInSharedCanvas from '../../hooks/useBoundsInSharedCanvas';
import useCoordsInSharedCanvas from '../../hooks/useCoordsInSharedCanvas';
import useHeavyAnimationCheck, { isHeavyAnimating } from '../../hooks/useHeavyAnimationCheck';
import AnimatedSticker from './AnimatedSticker';
@ -118,7 +118,7 @@ const StickerView: FC<OwnProps> = ({
const fullMediaClassNames = useMediaTransition(isFullMediaReady);
const noTransition = isLottie && preloadedPreviewData;
const bounds = useBoundsInSharedCanvas(containerRef, sharedCanvasRef);
const coords = useCoordsInSharedCanvas(containerRef, sharedCanvasRef);
// Preload preview for Message Input and local message
useMedia(previewMediaHash, !shouldLoad || !shouldPreloadPreview, undefined, cacheBuster);
@ -160,7 +160,7 @@ const StickerView: FC<OwnProps> = ({
forceOnHeavyAnimation={forceOnHeavyAnimation}
isLowPriority={isSmall && !selectIsAlwaysHighPriorityEmoji(getGlobal(), stickerSetInfo)}
sharedCanvas={sharedCanvasRef?.current || undefined}
sharedCanvasCoords={bounds.coords}
sharedCanvasCoords={coords}
onLoad={markPlayerReady}
onLoop={onAnimatedStickerLoop}
onEnded={onAnimatedStickerLoop}

View File

@ -15,7 +15,7 @@ import { getStickerPreviewHash } from '../../../global/helpers';
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
import useMedia from '../../../hooks/useMedia';
import useMediaTransition from '../../../hooks/useMediaTransition';
import useBoundsInSharedCanvas from '../../../hooks/useBoundsInSharedCanvas';
import useCoordsInSharedCanvas from '../../../hooks/useCoordsInSharedCanvas';
import AnimatedSticker from '../../common/AnimatedSticker';
import OptimizedVideo from '../../ui/OptimizedVideo';
@ -54,7 +54,7 @@ const StickerSetCover: FC<OwnProps> = ({
const isReady = mediaData || staticMediaData;
const transitionClassNames = useMediaTransition(isReady);
const bounds = useBoundsInSharedCanvas(containerRef, sharedCanvasRef);
const coords = useCoordsInSharedCanvas(containerRef, sharedCanvasRef);
useEffect(() => {
if (isIntersecting && !stickerSet.stickers?.length) {
@ -74,11 +74,11 @@ const StickerSetCover: FC<OwnProps> = ({
<AnimatedSticker
className={transitionClassNames}
tgsUrl={mediaData}
size={size || bounds.size}
size={size}
play={isIntersecting && !noAnimate}
isLowPriority={!selectIsAlwaysHighPriorityEmoji(getGlobal(), stickerSet)}
sharedCanvas={sharedCanvasRef?.current || undefined}
sharedCanvasCoords={bounds.coords}
sharedCanvasCoords={coords}
/>
) : (isVideo && !shouldFallbackToStatic) ? (
<OptimizedVideo

View File

@ -200,12 +200,12 @@ function createPlayer({
mediaUrl,
isHq ? sharedCanvasHqRef.current! : sharedCanvasRef.current!,
renderId,
viewId,
{
size: SIZE,
coords: position,
isLowPriority: !isHq,
},
viewId,
customEmoji.shouldUseTextColor ? textColor : undefined,
);

View File

@ -10,13 +10,12 @@ import useSharedIntersectionObserver from './useSharedIntersectionObserver';
const THROTTLE_MS = 150;
export default function useBoundsInSharedCanvas(
export default function useCoordsInSharedCanvas(
containerRef: React.RefObject<HTMLDivElement>,
sharedCanvasRef?: React.RefObject<HTMLCanvasElement>,
) {
const [x, setX] = useState<number>();
const [y, setY] = useState<number>();
const [size, setSize] = useState<number>();
const recalculate = useCallback(() => {
const container = containerRef.current;
@ -43,7 +42,6 @@ export default function useBoundsInSharedCanvas(
// Factor coords are used to support rendering while being rescaled (e.g. message appearance animation)
setX(round((targetBounds.left - canvasBounds.left) / canvasBounds.width, 4) || 0);
setY(round((targetBounds.top - canvasBounds.top) / canvasBounds.height, 4) || 0);
setSize(Math.round(targetBounds.width));
}, [containerRef, sharedCanvasRef]);
useEffect(recalculate, [recalculate]);
@ -52,7 +50,5 @@ export default function useBoundsInSharedCanvas(
useResizeObserver(sharedCanvasRef, throttledRecalculate);
useSharedIntersectionObserver(sharedCanvasRef, throttledRecalculate);
const coords = useMemo(() => (x !== undefined && y !== undefined ? { x, y } : undefined), [x, y]);
return { coords, size };
return useMemo(() => (x !== undefined && y !== undefined ? { x, y } : undefined), [x, y]);
}

View File

@ -11,8 +11,8 @@ import cycleRestrict from '../../util/cycleRestrict';
import generateIdFor from '../../util/generateIdFor';
interface Params {
size: number;
noLoop?: boolean;
size?: number;
quality?: number;
isLowPriority?: boolean;
coords?: { x: number; y: number };
@ -96,8 +96,8 @@ class RLottie {
const [
, canvas,
renderId,
viewId = generateIdFor(ID_STORE, true),
params, ,
params,
viewId = generateIdFor(ID_STORE, true), ,
onLoad,
] = args;
let instance = instancesByRenderId.get(renderId);
@ -117,8 +117,8 @@ class RLottie {
private tgsUrl: string,
private container: HTMLDivElement | HTMLCanvasElement,
private renderId: string,
private params: Params,
viewId: string = generateIdFor(ID_STORE, true),
private params: Params = {},
private customColor?: [number, number, number],
private onLoad?: NoneToVoidFunction | undefined,
private onEnded?: (isDestroyed?: boolean) => void,
@ -264,19 +264,7 @@ class RLottie {
throw new Error('[RLottie] Container is not mounted');
}
let { size } = this.params;
if (!size) {
size = (
container.offsetWidth
|| parseInt(container.style.width, 10)
|| container.parentNode.offsetWidth
);
if (!size) {
throw new Error('[RLottie] Failed to detect width from container');
}
}
const { size } = this.params;
imgSize = Math.round(size * sizeFactor);
@ -309,7 +297,7 @@ class RLottie {
const canvas = container;
const ctx = canvas.getContext('2d')!;
imgSize = Math.round(this.params.size! * sizeFactor);
imgSize = Math.round(this.params.size * sizeFactor);
if (!this.imgSize) {
this.imgSize = imgSize;
@ -323,8 +311,8 @@ class RLottie {
ctx,
isSharedCanvas: true,
coords: {
x: Math.round((coords?.x || 0) * canvasWidth),
y: Math.round((coords?.y || 0) * canvasHeight),
x: Math.round(coords!.x * canvasWidth),
y: Math.round(coords!.y * canvasHeight),
},
onLoad,
});
@ -337,8 +325,8 @@ class RLottie {
private calcSizeFactor() {
const {
isLowPriority,
size,
isLowPriority,
// Reduced quality only looks acceptable on big enough images
quality = isLowPriority && (!size || size > LOW_PRIORITY_QUALITY_SIZE_THRESHOLD)
? LOW_PRIORITY_QUALITY : HIGH_PRIORITY_QUALITY,