Skip to content

Commit c887f77

Browse files
Fix reaction animation frame glitch on Android (#4404)
1 parent c244450 commit c887f77

5 files changed

Lines changed: 61 additions & 30 deletions

File tree

packages/react-components/src/components/MeetingReactionOverlay.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export interface MeetingReactionOverlayProps {
5252
* Emoji max size
5353
* @internal
5454
*/
55-
const DEFAULT_EMOJI_MAX_SIZE_PX = 100;
55+
const DEFAULT_EMOJI_MAX_SIZE_PX = 70;
5656
/* @conditional-compile-remove(reaction) */
5757
/**
5858
* Emoji min size

packages/react-components/src/components/VideoGallery/ParticipantVideoTileOverlay.tsx

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ import React, { useCallback, useEffect, useState } from 'react';
66
/* @conditional-compile-remove(reaction) */
77
import { Reaction, ReactionResources } from '../../types';
88
/* @conditional-compile-remove(reaction) */
9-
import { getEmojiFrameCount, getEmojiResource } from './utils/videoGalleryLayoutUtils';
9+
import { getEmojiFrameCount, getEmojiFrameSize, getEmojiResource } from './utils/videoGalleryLayoutUtils';
1010
/* @conditional-compile-remove(reaction) */
1111
import { Stack, mergeStyles } from '@fluentui/react';
1212
/* @conditional-compile-remove(reaction) */
1313
import { reactionRenderingStyle, videoContainerStyles } from '../styles/VideoTile.styles';
1414
/* @conditional-compile-remove(reaction) */
1515
import {
16+
REACTION_DEFAULT_RESOURCE_FRAME_SIZE_PX,
17+
REACTION_NUMBER_OF_ANIMATION_FRAMES,
1618
REACTION_SCREEN_SHARE_ANIMATION_TIME_MS,
1719
REACTION_START_DISPLAY_SIZE,
1820
getReceivedUnixTime
@@ -41,6 +43,11 @@ export const ParticipantVideoTileOverlay = React.memo(
4143
? getEmojiFrameCount(reaction?.reactionType, reactionResources)
4244
: undefined;
4345

46+
const frameSize =
47+
reaction !== undefined && reactionResources !== undefined
48+
? getEmojiFrameSize(reaction?.reactionType, reactionResources)
49+
: undefined;
50+
4451
const currentUnixTimeStamp = Date.now();
4552
const receivedUnixTimestamp = reaction ? getReceivedUnixTime(reaction.receivedOn) : undefined;
4653
const canRenderReaction =
@@ -66,11 +73,12 @@ export const ParticipantVideoTileOverlay = React.memo(
6673
const reactionContainerStyles = useCallback(
6774
() =>
6875
reactionRenderingStyle({
69-
spriteImageUrl,
76+
spriteImageUrl: spriteImageUrl ?? '',
7077
emojiSize: emojiSize,
71-
frameCount
78+
frameCount: frameCount ?? REACTION_NUMBER_OF_ANIMATION_FRAMES,
79+
rawFrameSize: frameSize ?? REACTION_DEFAULT_RESOURCE_FRAME_SIZE_PX
7280
}),
73-
[spriteImageUrl, emojiSize, frameCount]
81+
[spriteImageUrl, emojiSize, frameCount, frameSize]
7482
);
7583

7684
return (
@@ -84,7 +92,13 @@ export const ParticipantVideoTileOverlay = React.memo(
8492
>
8593
<div style={{ height: '33.33%' }}></div>
8694
{canRenderReaction && isValidImageSource && (
87-
<div style={{ minHeight: '84px', height: '84px', width: '84px' }}>
95+
<div
96+
style={{
97+
minHeight: `${emojiSize}px`,
98+
height: `${emojiSize}px`,
99+
width: `${emojiSize}px`
100+
}}
101+
>
88102
<div className={reactionContainerStyles()} />
89103
</div>
90104
)}

packages/react-components/src/components/VideoGallery/utils/reactionUtils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ export const REACTION_NUMBER_OF_ANIMATION_FRAMES = 51;
1010
/* @conditional-compile-remove(reaction) */
1111
/** @private */
1212
export const REACTION_SCREEN_SHARE_ANIMATION_TIME_MS = 4133;
13+
/* @conditional-compile-remove(reaction) */
14+
/** @private */
15+
export const REACTION_DEFAULT_RESOURCE_FRAME_SIZE_PX = 128;
1316

1417
/* @conditional-compile-remove(reaction) */
1518
/** @private */

packages/react-components/src/components/VideoGallery/utils/videoGalleryLayoutUtils.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,24 @@ export const getEmojiFrameCount = (reactionName: string, reactionResources: Reac
284284
return 0;
285285
}
286286
};
287+
288+
/* @conditional-compile-remove(reaction) */
289+
/**
290+
* @private
291+
*/
292+
export const getEmojiFrameSize = (reactionName: string, reactionResources: ReactionResources): number | undefined => {
293+
switch (reactionName) {
294+
case 'like':
295+
return reactionResources.likeReaction?.size;
296+
case 'heart':
297+
return reactionResources.heartReaction?.size;
298+
case 'laugh':
299+
return reactionResources.laughReaction?.size;
300+
case 'applause':
301+
return reactionResources.applauseReaction?.size;
302+
case 'surprised':
303+
return reactionResources.surprisedReaction?.size;
304+
default:
305+
return undefined;
306+
}
307+
};

packages/react-components/src/components/styles/VideoTile.styles.ts

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,8 @@
44
import { IButtonStyles, IStyle, mergeStyles, Theme, ITheme } from '@fluentui/react';
55
/* @conditional-compile-remove(reaction) */
66
import { keyframes, memoizeFunction } from '@fluentui/react';
7-
87
/* @conditional-compile-remove(reaction) */
9-
/**
10-
* @private
11-
*/
12-
const DEFAULT_ORIGINAL_EMOJI_SIZE = 84;
8+
import { REACTION_SCREEN_SHARE_ANIMATION_TIME_MS } from '../VideoGallery/utils/reactionUtils';
139

1410
/**
1511
* @private
@@ -186,13 +182,13 @@ export const raiseHandLimitedSpaceStyles: IStyle = {
186182
/**
187183
* @private
188184
*/
189-
export const playFrames = memoizeFunction(() =>
185+
export const playFrames = memoizeFunction((frameHightPx: number, frameCount: number) =>
190186
keyframes({
191187
from: {
192-
backgroundPosition: '0px 8568px'
188+
backgroundPosition: `0px 0px`
193189
},
194190
to: {
195-
backgroundPosition: '0px 0px'
191+
backgroundPosition: `0px ${frameCount * -frameHightPx}px`
196192
}
197193
})
198194
);
@@ -202,30 +198,27 @@ export const playFrames = memoizeFunction(() =>
202198
* @private
203199
*/
204200
export const reactionRenderingStyle = (args: {
205-
spriteImageUrl?: string;
201+
spriteImageUrl: string;
206202
emojiSize: number;
207-
frameCount?: number;
203+
rawFrameSize: number;
204+
frameCount: number;
208205
}): string => {
209206
const imageUrl = `url(${args.spriteImageUrl})`;
210-
const steps = args.frameCount ?? 51;
207+
const steps = args.frameCount ?? 0;
208+
const frameSizePx = args.rawFrameSize;
211209
return mergeStyles({
212-
height: '100%',
213-
width: '100%',
210+
height: `${frameSizePx}px`,
211+
width: `${frameSizePx}px`,
214212
overflow: 'hidden',
215-
animationName: playFrames(),
213+
animationName: playFrames(frameSizePx, steps),
216214
backgroundImage: imageUrl,
217-
animationDuration: '5.12s',
215+
animationDuration: `${REACTION_SCREEN_SHARE_ANIMATION_TIME_MS / 1000}s`,
218216
animationTimingFunction: `steps(${steps})`,
219-
backgroundSize: `cover`,
220217
animationPlayState: 'running',
221218
animationIterationCount: 'infinite',
222-
justifyContent: 'center',
223-
alignItems: 'center',
224-
backgroundPosition: `center`,
225-
transform: `scale(${
226-
DEFAULT_ORIGINAL_EMOJI_SIZE < args.emojiSize
227-
? DEFAULT_ORIGINAL_EMOJI_SIZE / args.emojiSize
228-
: args.emojiSize / DEFAULT_ORIGINAL_EMOJI_SIZE
229-
})`
219+
220+
// Scale the emoji to fit the parent container
221+
transform: `scale(${args.emojiSize / frameSizePx})`,
222+
transformOrigin: 'top left'
230223
});
231224
};

0 commit comments

Comments
 (0)