Message: Fix parallel emoji interactions (#1678)
This commit is contained in:
parent
e33e22c982
commit
74d348b00a
@ -27,7 +27,7 @@ type OwnProps = {
|
|||||||
forceLoadPreview?: boolean;
|
forceLoadPreview?: boolean;
|
||||||
messageId?: number;
|
messageId?: number;
|
||||||
chatId?: string;
|
chatId?: string;
|
||||||
activeEmojiInteraction?: ActiveEmojiInteraction;
|
activeEmojiInteractions?: ActiveEmojiInteraction[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const QUALITY = 1;
|
const QUALITY = 1;
|
||||||
@ -43,7 +43,7 @@ const AnimatedEmoji: FC<OwnProps> = ({
|
|||||||
forceLoadPreview,
|
forceLoadPreview,
|
||||||
messageId,
|
messageId,
|
||||||
chatId,
|
chatId,
|
||||||
activeEmojiInteraction,
|
activeEmojiInteractions,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
markAnimationLoaded,
|
markAnimationLoaded,
|
||||||
@ -53,7 +53,7 @@ const AnimatedEmoji: FC<OwnProps> = ({
|
|||||||
style,
|
style,
|
||||||
handleClick,
|
handleClick,
|
||||||
playKey,
|
playKey,
|
||||||
} = useAnimatedEmoji(size, chatId, messageId, soundId, activeEmojiInteraction, isOwn, undefined, effect?.emoji);
|
} = useAnimatedEmoji(size, chatId, messageId, soundId, activeEmojiInteractions, isOwn, undefined, effect?.emoji);
|
||||||
|
|
||||||
const localMediaHash = `sticker${sticker.id}`;
|
const localMediaHash = `sticker${sticker.id}`;
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ type OwnProps = {
|
|||||||
forceLoadPreview?: boolean;
|
forceLoadPreview?: boolean;
|
||||||
messageId?: number;
|
messageId?: number;
|
||||||
chatId?: string;
|
chatId?: string;
|
||||||
activeEmojiInteraction?: ActiveEmojiInteraction;
|
activeEmojiInteractions?: ActiveEmojiInteraction[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const LocalAnimatedEmoji: FC<OwnProps> = ({
|
const LocalAnimatedEmoji: FC<OwnProps> = ({
|
||||||
@ -35,7 +35,7 @@ const LocalAnimatedEmoji: FC<OwnProps> = ({
|
|||||||
observeIntersection,
|
observeIntersection,
|
||||||
messageId,
|
messageId,
|
||||||
chatId,
|
chatId,
|
||||||
activeEmojiInteraction,
|
activeEmojiInteractions,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
playKey,
|
playKey,
|
||||||
@ -44,7 +44,7 @@ const LocalAnimatedEmoji: FC<OwnProps> = ({
|
|||||||
width,
|
width,
|
||||||
handleClick,
|
handleClick,
|
||||||
markAnimationLoaded,
|
markAnimationLoaded,
|
||||||
} = useAnimatedEmoji(size, chatId, messageId, soundId, activeEmojiInteraction, isOwn, localEffect);
|
} = useAnimatedEmoji(size, chatId, messageId, soundId, activeEmojiInteractions, isOwn, localEffect);
|
||||||
const id = `local_emoji_${localSticker}`;
|
const id = `local_emoji_${localSticker}`;
|
||||||
|
|
||||||
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
||||||
|
|||||||
@ -22,7 +22,7 @@ export default function useAnimatedEmoji(
|
|||||||
chatId?: string,
|
chatId?: string,
|
||||||
messageId?: number,
|
messageId?: number,
|
||||||
soundId?: string,
|
soundId?: string,
|
||||||
activeEmojiInteraction?: ActiveEmojiInteraction,
|
activeEmojiInteractions?: ActiveEmojiInteraction[],
|
||||||
isOwn?: boolean,
|
isOwn?: boolean,
|
||||||
localEffect?: string,
|
localEffect?: string,
|
||||||
emoji?: string,
|
emoji?: string,
|
||||||
@ -120,16 +120,21 @@ export default function useAnimatedEmoji(
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const container = ref.current;
|
const container = ref.current;
|
||||||
|
|
||||||
if (!container || !activeEmojiInteraction) return;
|
if (!container || !activeEmojiInteractions) return;
|
||||||
|
|
||||||
const {
|
activeEmojiInteractions.forEach(({
|
||||||
messageId: selectedMessageId, endX, endY,
|
id,
|
||||||
} = activeEmojiInteraction;
|
startSize,
|
||||||
|
messageId: interactionMessageId,
|
||||||
|
}) => {
|
||||||
|
if (startSize || messageId !== interactionMessageId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!endX && !endY && selectedMessageId === messageId) {
|
|
||||||
const { x, y } = container.getBoundingClientRect();
|
const { x, y } = container.getBoundingClientRect();
|
||||||
|
|
||||||
sendWatchingEmojiInteraction({
|
sendWatchingEmojiInteraction({
|
||||||
|
id,
|
||||||
chatId,
|
chatId,
|
||||||
emoticon: localEffect ? selectLocalAnimatedEmojiEffectByName(localEffect) : emoji,
|
emoticon: localEffect ? selectLocalAnimatedEmojiEffectByName(localEffect) : emoji,
|
||||||
startSize: width,
|
startSize: width,
|
||||||
@ -138,9 +143,9 @@ export default function useAnimatedEmoji(
|
|||||||
isReversed: !isOwn,
|
isReversed: !isOwn,
|
||||||
});
|
});
|
||||||
play();
|
play();
|
||||||
}
|
});
|
||||||
}, [
|
}, [
|
||||||
activeEmojiInteraction, chatId, emoji, isOwn, localEffect, messageId, play, sendWatchingEmojiInteraction, width,
|
activeEmojiInteractions, chatId, emoji, isOwn, localEffect, messageId, play, sendWatchingEmojiInteraction, width,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -5,8 +5,9 @@ import { Bundles } from '../../util/moduleLoader';
|
|||||||
import useModuleLoader from '../../hooks/useModuleLoader';
|
import useModuleLoader from '../../hooks/useModuleLoader';
|
||||||
|
|
||||||
const EmojiInteractionAnimationAsync: FC<OwnProps> = (props) => {
|
const EmojiInteractionAnimationAsync: FC<OwnProps> = (props) => {
|
||||||
const { emojiInteraction } = props;
|
const { activeEmojiInteraction } = props;
|
||||||
const EmojiInteractionAnimation = useModuleLoader(Bundles.Extra, 'EmojiInteractionAnimation', !emojiInteraction);
|
const EmojiInteractionAnimation = useModuleLoader(Bundles.Extra, 'EmojiInteractionAnimation',
|
||||||
|
!activeEmojiInteraction);
|
||||||
|
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
return EmojiInteractionAnimation ? <EmojiInteractionAnimation {...props} /> : undefined;
|
return EmojiInteractionAnimation ? <EmojiInteractionAnimation {...props} /> : undefined;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React, {
|
import React, {
|
||||||
FC, memo, useCallback, useEffect, useLayoutEffect, useState,
|
FC, memo, useCallback, useEffect, useLayoutEffect, useRef, useState,
|
||||||
} from '../../lib/teact/teact';
|
} from '../../lib/teact/teact';
|
||||||
import { getDispatch, withGlobal } from '../../lib/teact/teactn';
|
import { getDispatch, withGlobal } from '../../lib/teact/teactn';
|
||||||
|
|
||||||
@ -21,13 +21,12 @@ import AnimatedSticker from '../common/AnimatedSticker';
|
|||||||
import './EmojiInteractionAnimation.scss';
|
import './EmojiInteractionAnimation.scss';
|
||||||
|
|
||||||
export type OwnProps = {
|
export type OwnProps = {
|
||||||
emojiInteraction: ActiveEmojiInteraction;
|
activeEmojiInteraction: ActiveEmojiInteraction;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StateProps = {
|
type StateProps = {
|
||||||
effectAnimationId?: string;
|
effectAnimationId?: string;
|
||||||
localEffectAnimation?: string;
|
localEffectAnimation?: string;
|
||||||
isReversed?: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const HIDE_ANIMATION_DURATION = 250;
|
const HIDE_ANIMATION_DURATION = 250;
|
||||||
@ -35,41 +34,50 @@ const PLAYING_DURATION = 3000;
|
|||||||
const EFFECT_SIZE = 240;
|
const EFFECT_SIZE = 240;
|
||||||
|
|
||||||
const EmojiInteractionAnimation: FC<OwnProps & StateProps> = ({
|
const EmojiInteractionAnimation: FC<OwnProps & StateProps> = ({
|
||||||
emojiInteraction,
|
|
||||||
effectAnimationId,
|
effectAnimationId,
|
||||||
localEffectAnimation,
|
localEffectAnimation,
|
||||||
isReversed,
|
activeEmojiInteraction,
|
||||||
}) => {
|
}) => {
|
||||||
const { stopActiveEmojiInteraction } = getDispatch();
|
const { stopActiveEmojiInteraction } = getDispatch();
|
||||||
|
|
||||||
const [isHiding, startHiding] = useFlag(false);
|
const [isHiding, startHiding] = useFlag(false);
|
||||||
const [isPlaying, startPlaying] = useFlag(false);
|
const [isPlaying, startPlaying] = useFlag(false);
|
||||||
|
const timeoutRef = useRef<NodeJS.Timeout>();
|
||||||
|
|
||||||
const stop = useCallback(() => {
|
const stop = useCallback(() => {
|
||||||
startHiding();
|
startHiding();
|
||||||
|
if (timeoutRef.current) {
|
||||||
|
clearTimeout(timeoutRef.current);
|
||||||
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
stopActiveEmojiInteraction();
|
stopActiveEmojiInteraction({ id: activeEmojiInteraction.id });
|
||||||
}, HIDE_ANIMATION_DURATION);
|
}, HIDE_ANIMATION_DURATION);
|
||||||
}, [startHiding, stopActiveEmojiInteraction]);
|
}, [activeEmojiInteraction.id, startHiding, stopActiveEmojiInteraction]);
|
||||||
|
|
||||||
|
const handleCancelAnimation = useCallback((e: UIEvent) => {
|
||||||
|
if (!(e.target as HTMLElement)?.closest('.AnimatedEmoji')) {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
}, [stop]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.addEventListener('touchstart', stop);
|
document.addEventListener('touchstart', handleCancelAnimation);
|
||||||
document.addEventListener('touchmove', stop);
|
document.addEventListener('touchmove', handleCancelAnimation);
|
||||||
document.addEventListener('mousedown', stop);
|
document.addEventListener('mousedown', handleCancelAnimation);
|
||||||
document.addEventListener('wheel', stop);
|
document.addEventListener('wheel', handleCancelAnimation);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('touchstart', stop);
|
document.removeEventListener('touchstart', handleCancelAnimation);
|
||||||
document.removeEventListener('touchmove', stop);
|
document.removeEventListener('touchmove', handleCancelAnimation);
|
||||||
document.removeEventListener('mousedown', stop);
|
document.removeEventListener('mousedown', handleCancelAnimation);
|
||||||
document.removeEventListener('wheel', stop);
|
document.removeEventListener('wheel', handleCancelAnimation);
|
||||||
};
|
};
|
||||||
}, [stop]);
|
}, [handleCancelAnimation]);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const dispatchHeavyAnimationStop = dispatchHeavyAnimationEvent();
|
const dispatchHeavyAnimationStop = dispatchHeavyAnimationEvent();
|
||||||
|
|
||||||
setTimeout(() => {
|
timeoutRef.current = setTimeout(() => {
|
||||||
stop();
|
stop();
|
||||||
dispatchHeavyAnimationStop();
|
dispatchHeavyAnimationStop();
|
||||||
}, PLAYING_DURATION);
|
}, PLAYING_DURATION);
|
||||||
@ -86,16 +94,24 @@ const EmojiInteractionAnimation: FC<OwnProps & StateProps> = ({
|
|||||||
}
|
}
|
||||||
}, [localEffectAnimation]);
|
}, [localEffectAnimation]);
|
||||||
|
|
||||||
const scale = (emojiInteraction.startSize || 0) / EFFECT_SIZE;
|
if (!activeEmojiInteraction.startSize) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scale = (activeEmojiInteraction.startSize || 0) / EFFECT_SIZE;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={buildClassName(
|
className={buildClassName(
|
||||||
'EmojiInteractionAnimation', isHiding && 'hiding', isPlaying && 'playing', isReversed && 'reversed',
|
'EmojiInteractionAnimation',
|
||||||
|
isHiding && 'hiding',
|
||||||
|
isPlaying && 'playing',
|
||||||
|
activeEmojiInteraction.isReversed && 'reversed',
|
||||||
)}
|
)}
|
||||||
style={`--scale: ${scale}; --start-x: ${emojiInteraction.x}px; --start-y: ${emojiInteraction.y}px;`}
|
style={`--scale: ${scale}; --start-x: ${activeEmojiInteraction.x}px; --start-y: ${activeEmojiInteraction.y}px;`}
|
||||||
>
|
>
|
||||||
<AnimatedSticker
|
<AnimatedSticker
|
||||||
|
key={`effect_${effectAnimationId}`}
|
||||||
id={`effect_${effectAnimationId}`}
|
id={`effect_${effectAnimationId}`}
|
||||||
size={EFFECT_SIZE}
|
size={EFFECT_SIZE}
|
||||||
animationData={localEffectAnimationData || effectAnimationData}
|
animationData={localEffectAnimationData || effectAnimationData}
|
||||||
@ -110,15 +126,14 @@ const EmojiInteractionAnimation: FC<OwnProps & StateProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default memo(withGlobal<OwnProps>(
|
export default memo(withGlobal<OwnProps>(
|
||||||
(global, { emojiInteraction }): StateProps => {
|
(global, { activeEmojiInteraction }): StateProps => {
|
||||||
const animatedEffect = emojiInteraction.animatedEffect !== undefined
|
const animatedEffect = activeEmojiInteraction.animatedEffect !== undefined
|
||||||
&& selectAnimatedEmojiEffect(global, emojiInteraction.animatedEffect);
|
&& selectAnimatedEmojiEffect(global, activeEmojiInteraction.animatedEffect);
|
||||||
return {
|
return {
|
||||||
effectAnimationId: animatedEffect ? animatedEffect.id : undefined,
|
effectAnimationId: animatedEffect ? animatedEffect.id : undefined,
|
||||||
localEffectAnimation: !animatedEffect && emojiInteraction.animatedEffect
|
localEffectAnimation: !animatedEffect && activeEmojiInteraction.animatedEffect
|
||||||
&& Object.keys(ANIMATED_STICKERS_PATHS).includes(emojiInteraction.animatedEffect)
|
&& Object.keys(ANIMATED_STICKERS_PATHS).includes(activeEmojiInteraction.animatedEffect)
|
||||||
? emojiInteraction.animatedEffect : undefined,
|
? activeEmojiInteraction.animatedEffect : undefined,
|
||||||
isReversed: emojiInteraction.isReversed,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(EmojiInteractionAnimation));
|
)(EmojiInteractionAnimation));
|
||||||
|
|||||||
@ -109,7 +109,7 @@ type StateProps = {
|
|||||||
canSubscribe?: boolean;
|
canSubscribe?: boolean;
|
||||||
canStartBot?: boolean;
|
canStartBot?: boolean;
|
||||||
canRestartBot?: boolean;
|
canRestartBot?: boolean;
|
||||||
activeEmojiInteraction?: ActiveEmojiInteraction;
|
activeEmojiInteractions?: ActiveEmojiInteraction[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const CLOSE_ANIMATION_DURATION = IS_SINGLE_COLUMN_LAYOUT ? 450 + ANIMATION_END_DELAY : undefined;
|
const CLOSE_ANIMATION_DURATION = IS_SINGLE_COLUMN_LAYOUT ? 450 + ANIMATION_END_DELAY : undefined;
|
||||||
@ -150,7 +150,7 @@ const MiddleColumn: FC<StateProps> = ({
|
|||||||
canSubscribe,
|
canSubscribe,
|
||||||
canStartBot,
|
canStartBot,
|
||||||
canRestartBot,
|
canRestartBot,
|
||||||
activeEmojiInteraction,
|
activeEmojiInteractions,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
openChat,
|
openChat,
|
||||||
@ -522,9 +522,15 @@ const MiddleColumn: FC<StateProps> = ({
|
|||||||
onUnpin={handleUnpinAllMessages}
|
onUnpin={handleUnpinAllMessages}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{activeEmojiInteraction && (
|
<div teactFastList>
|
||||||
<EmojiInteractionAnimation emojiInteraction={activeEmojiInteraction} />
|
{activeEmojiInteractions?.map((activeEmojiInteraction, i) => (
|
||||||
)}
|
<EmojiInteractionAnimation
|
||||||
|
teactOrderKey={i}
|
||||||
|
key={activeEmojiInteraction.id}
|
||||||
|
activeEmojiInteraction={activeEmojiInteraction}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -538,7 +544,7 @@ export default memo(withGlobal(
|
|||||||
|
|
||||||
const { messageLists } = global.messages;
|
const { messageLists } = global.messages;
|
||||||
const currentMessageList = selectCurrentMessageList(global);
|
const currentMessageList = selectCurrentMessageList(global);
|
||||||
const { isLeftColumnShown, chats: { listIds }, activeEmojiInteraction } = global;
|
const { isLeftColumnShown, chats: { listIds }, activeEmojiInteractions } = global;
|
||||||
|
|
||||||
const state: StateProps = {
|
const state: StateProps = {
|
||||||
theme,
|
theme,
|
||||||
@ -556,7 +562,7 @@ export default memo(withGlobal(
|
|||||||
isReactorListModalOpen: Boolean(global.reactorModal),
|
isReactorListModalOpen: Boolean(global.reactorModal),
|
||||||
animationLevel: global.settings.byKey.animationLevel,
|
animationLevel: global.settings.byKey.animationLevel,
|
||||||
currentTransitionKey: Math.max(0, global.messages.messageLists.length - 1),
|
currentTransitionKey: Math.max(0, global.messages.messageLists.length - 1),
|
||||||
activeEmojiInteraction,
|
activeEmojiInteractions,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!currentMessageList || !listIds.active) {
|
if (!currentMessageList || !listIds.active) {
|
||||||
|
|||||||
@ -185,7 +185,7 @@ type StateProps = {
|
|||||||
availableReactions?: ApiAvailableReaction[];
|
availableReactions?: ApiAvailableReaction[];
|
||||||
defaultReaction?: string;
|
defaultReaction?: string;
|
||||||
activeReaction?: ActiveReaction;
|
activeReaction?: ActiveReaction;
|
||||||
activeEmojiInteraction?: ActiveEmojiInteraction;
|
activeEmojiInteractions?: ActiveEmojiInteraction[];
|
||||||
};
|
};
|
||||||
|
|
||||||
type MetaPosition =
|
type MetaPosition =
|
||||||
@ -261,7 +261,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
availableReactions,
|
availableReactions,
|
||||||
defaultReaction,
|
defaultReaction,
|
||||||
activeReaction,
|
activeReaction,
|
||||||
activeEmojiInteraction,
|
activeEmojiInteractions,
|
||||||
messageListType,
|
messageListType,
|
||||||
isPinnedList,
|
isPinnedList,
|
||||||
isDownloading,
|
isDownloading,
|
||||||
@ -637,7 +637,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
forceLoadPreview={isLocal}
|
forceLoadPreview={isLocal}
|
||||||
messageId={messageId}
|
messageId={messageId}
|
||||||
chatId={chatId}
|
chatId={chatId}
|
||||||
activeEmojiInteraction={activeEmojiInteraction}
|
activeEmojiInteractions={activeEmojiInteractions}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{localSticker && (
|
{localSticker && (
|
||||||
@ -652,7 +652,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
forceLoadPreview={isLocal}
|
forceLoadPreview={isLocal}
|
||||||
messageId={messageId}
|
messageId={messageId}
|
||||||
chatId={chatId}
|
chatId={chatId}
|
||||||
activeEmojiInteraction={activeEmojiInteraction}
|
activeEmojiInteractions={activeEmojiInteractions}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{isAlbum && (
|
{isAlbum && (
|
||||||
@ -1055,7 +1055,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
availableReactions: global.availableReactions,
|
availableReactions: global.availableReactions,
|
||||||
defaultReaction: isMessageLocal(message) ? undefined : selectDefaultReaction(global, chatId),
|
defaultReaction: isMessageLocal(message) ? undefined : selectDefaultReaction(global, chatId),
|
||||||
activeReaction: reactionMessage && global.activeReactions[reactionMessage.id],
|
activeReaction: reactionMessage && global.activeReactions[reactionMessage.id],
|
||||||
activeEmojiInteraction: global.activeEmojiInteraction,
|
activeEmojiInteractions: global.activeEmojiInteractions,
|
||||||
...(isOutgoing && { outgoingStatus: selectOutgoingStatus(global, message, messageListType === 'scheduled') }),
|
...(isOutgoing && { outgoingStatus: selectOutgoingStatus(global, message, messageListType === 'scheduled') }),
|
||||||
...(typeof uploadProgress === 'number' && { uploadProgress }),
|
...(typeof uploadProgress === 'number' && { uploadProgress }),
|
||||||
...(isFocused && { focusDirection, noFocusHighlight, isResizingContainer }),
|
...(isFocused && { focusDirection, noFocusHighlight, isResizingContainer }),
|
||||||
|
|||||||
@ -65,13 +65,11 @@ export interface MessageList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ActiveEmojiInteraction {
|
export interface ActiveEmojiInteraction {
|
||||||
|
id: number;
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
messageId?: number;
|
messageId?: number;
|
||||||
endX?: number;
|
|
||||||
endY?: number;
|
|
||||||
startSize?: number;
|
startSize?: number;
|
||||||
reaction?: string;
|
|
||||||
animatedEffect?: string;
|
animatedEffect?: string;
|
||||||
isReversed?: boolean;
|
isReversed?: boolean;
|
||||||
}
|
}
|
||||||
@ -332,7 +330,7 @@ export type GlobalState = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
availableReactions?: ApiAvailableReaction[];
|
availableReactions?: ApiAvailableReaction[];
|
||||||
activeEmojiInteraction?: ActiveEmojiInteraction;
|
activeEmojiInteractions?: ActiveEmojiInteraction[];
|
||||||
activeReactions: Record<number, ActiveReaction>;
|
activeReactions: Record<number, ActiveReaction>;
|
||||||
|
|
||||||
localTextSearch: {
|
localTextSearch: {
|
||||||
|
|||||||
@ -15,6 +15,10 @@ import { buildCollectionByKey, omit } from '../../../util/iteratees';
|
|||||||
import { ANIMATION_LEVEL_MAX } from '../../../config';
|
import { ANIMATION_LEVEL_MAX } from '../../../config';
|
||||||
import { isMessageLocal } from '../../helpers';
|
import { isMessageLocal } from '../../helpers';
|
||||||
|
|
||||||
|
const INTERACTION_RANDOM_OFFSET = 40;
|
||||||
|
|
||||||
|
let interactionLocalId = 0;
|
||||||
|
|
||||||
addReducer('loadAvailableReactions', () => {
|
addReducer('loadAvailableReactions', () => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const result = await callApi('getAvailableReactions');
|
const result = await callApi('getAvailableReactions');
|
||||||
@ -45,28 +49,31 @@ addReducer('interactWithAnimatedEmoji', (global, actions, payload) => {
|
|||||||
emoji, x, y, localEffect, startSize, isReversed,
|
emoji, x, y, localEffect, startSize, isReversed,
|
||||||
} = payload!;
|
} = payload!;
|
||||||
|
|
||||||
|
const activeEmojiInteraction = {
|
||||||
|
id: interactionLocalId++,
|
||||||
|
animatedEffect: emoji || localEffect,
|
||||||
|
x: subtractXForEmojiInteraction(global, x) + Math.random()
|
||||||
|
* INTERACTION_RANDOM_OFFSET - INTERACTION_RANDOM_OFFSET / 2,
|
||||||
|
y: y + Math.random() * INTERACTION_RANDOM_OFFSET - INTERACTION_RANDOM_OFFSET / 2,
|
||||||
|
startSize,
|
||||||
|
isReversed,
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...global,
|
...global,
|
||||||
activeEmojiInteraction: {
|
activeEmojiInteractions: [...(global.activeEmojiInteractions || []), activeEmojiInteraction],
|
||||||
animatedEffect: emoji || localEffect,
|
|
||||||
x: subtractXForEmojiInteraction(global, x),
|
|
||||||
y,
|
|
||||||
startSize,
|
|
||||||
isReversed,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
addReducer('sendEmojiInteraction', (global, actions, payload) => {
|
addReducer('sendEmojiInteraction', (global, actions, payload) => {
|
||||||
const {
|
const {
|
||||||
messageId, chatId, emoji, interactions, localEffect,
|
messageId, chatId, emoji, interactions, localEffect,
|
||||||
x, y, startX, startY, startSize,
|
|
||||||
} = payload!;
|
} = payload!;
|
||||||
|
|
||||||
const chat = selectChat(global, chatId);
|
const chat = selectChat(global, chatId);
|
||||||
|
|
||||||
if (!chat || (!emoji && !localEffect) || chatId === global.currentUserId) {
|
if (!chat || (!emoji && !localEffect) || chatId === global.currentUserId) {
|
||||||
return undefined;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void callApi('sendEmojiInteraction', {
|
void callApi('sendEmojiInteraction', {
|
||||||
@ -75,20 +82,6 @@ addReducer('sendEmojiInteraction', (global, actions, payload) => {
|
|||||||
emoticon: emoji || selectLocalAnimatedEmojiEffectByName(localEffect),
|
emoticon: emoji || selectLocalAnimatedEmojiEffectByName(localEffect),
|
||||||
timestamps: interactions,
|
timestamps: interactions,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!global.activeEmojiInteraction) return undefined;
|
|
||||||
|
|
||||||
return {
|
|
||||||
...global,
|
|
||||||
activeEmojiInteraction: {
|
|
||||||
...global.activeEmojiInteraction,
|
|
||||||
endX: subtractXForEmojiInteraction(global, x),
|
|
||||||
endY: y,
|
|
||||||
...(startX && { x: subtractXForEmojiInteraction(global, startX) }),
|
|
||||||
...(startY && { y: startY }),
|
|
||||||
...(startSize && { startSize }),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
addReducer('sendDefaultReaction', (global, actions, payload) => {
|
addReducer('sendDefaultReaction', (global, actions, payload) => {
|
||||||
@ -224,10 +217,12 @@ addReducer('setDefaultReaction', (global, actions, payload) => {
|
|||||||
})();
|
})();
|
||||||
});
|
});
|
||||||
|
|
||||||
addReducer('stopActiveEmojiInteraction', (global) => {
|
addReducer('stopActiveEmojiInteraction', (global, actions, payload) => {
|
||||||
|
const { id } = payload;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...global,
|
...global,
|
||||||
activeEmojiInteraction: undefined,
|
activeEmojiInteractions: global.activeEmojiInteractions?.filter((l) => l.id !== id),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -287,12 +282,12 @@ addReducer('loadMessageReactions', (global, actions, payload) => {
|
|||||||
|
|
||||||
addReducer('sendWatchingEmojiInteraction', (global, actions, payload) => {
|
addReducer('sendWatchingEmojiInteraction', (global, actions, payload) => {
|
||||||
const {
|
const {
|
||||||
chatId, emoticon, x, y, startSize, isReversed,
|
chatId, emoticon, x, y, startSize, isReversed, id,
|
||||||
} = payload;
|
} = payload;
|
||||||
|
|
||||||
const chat = selectChat(global, chatId);
|
const chat = selectChat(global, chatId);
|
||||||
|
|
||||||
if (!chat || !global.activeEmojiInteraction || chatId === global.currentUserId) {
|
if (!chat || !global.activeEmojiInteractions?.some((l) => l.id === id) || chatId === global.currentUserId) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,12 +295,17 @@ addReducer('sendWatchingEmojiInteraction', (global, actions, payload) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...global,
|
...global,
|
||||||
activeEmojiInteraction: {
|
activeEmojiInteractions: global.activeEmojiInteractions.map((activeEmojiInteraction) => {
|
||||||
...global.activeEmojiInteraction,
|
if (activeEmojiInteraction.id === id) {
|
||||||
x: subtractXForEmojiInteraction(global, x),
|
return {
|
||||||
y,
|
...activeEmojiInteraction,
|
||||||
startSize,
|
x: subtractXForEmojiInteraction(global, x),
|
||||||
isReversed,
|
y,
|
||||||
},
|
startSize,
|
||||||
|
isReversed,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return activeEmojiInteraction;
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@ -118,7 +118,7 @@ addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
|
|||||||
case 'updateStartEmojiInteraction': {
|
case 'updateStartEmojiInteraction': {
|
||||||
const { chatId: currentChatId } = selectCurrentMessageList(global) || {};
|
const { chatId: currentChatId } = selectCurrentMessageList(global) || {};
|
||||||
|
|
||||||
if (global.activeEmojiInteraction || currentChatId !== update.id) return;
|
if (currentChatId !== update.id) return;
|
||||||
const message = selectChatMessage(global, currentChatId, update.messageId);
|
const message = selectChatMessage(global, currentChatId, update.messageId);
|
||||||
|
|
||||||
if (!message) return;
|
if (!message) return;
|
||||||
@ -130,10 +130,11 @@ addReducer('apiUpdate', (global, actions, update: ApiUpdate) => {
|
|||||||
|
|
||||||
global = {
|
global = {
|
||||||
...global,
|
...global,
|
||||||
activeEmojiInteraction: {
|
activeEmojiInteractions: [...(global.activeEmojiInteractions || []), {
|
||||||
|
id: global.activeEmojiInteractions?.length || 0,
|
||||||
animatedEffect: localEmoji ? selectLocalAnimatedEmojiEffect(localEmoji) : update.emoji,
|
animatedEffect: localEmoji ? selectLocalAnimatedEmojiEffect(localEmoji) : update.emoji,
|
||||||
messageId: update.messageId,
|
messageId: update.messageId,
|
||||||
} as ActiveEmojiInteraction,
|
} as ActiveEmojiInteraction],
|
||||||
};
|
};
|
||||||
|
|
||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user