Emoji: Remove special effect for eggplant and peach (#2552)
This commit is contained in:
parent
30a36c7908
commit
b4f388d4a8
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -19,10 +19,6 @@ import VoiceMini from '../../../assets/tgs/calls/VoiceMini.tgs';
|
||||
import VoiceMuted from '../../../assets/tgs/calls/VoiceMuted.tgs';
|
||||
import VoiceOutlined from '../../../assets/tgs/calls/VoiceOutlined.tgs';
|
||||
|
||||
import Peach from '../../../assets/tgs/animatedEmojis/Peach.tgs';
|
||||
import Eggplant from '../../../assets/tgs/animatedEmojis/Eggplant.tgs';
|
||||
import Cumshot from '../../../assets/tgs/animatedEmojis/Cumshot.tgs';
|
||||
|
||||
import JoinRequest from '../../../assets/tgs/invites/Requests.tgs';
|
||||
import Invite from '../../../assets/tgs/invites/Invite.tgs';
|
||||
|
||||
@ -45,9 +41,6 @@ export const LOCAL_TGS_URLS = {
|
||||
VoiceMini,
|
||||
VoiceMuted,
|
||||
VoiceOutlined,
|
||||
Peach,
|
||||
Eggplant,
|
||||
Cumshot,
|
||||
JoinRequest,
|
||||
Invite,
|
||||
QrPlane,
|
||||
|
||||
@ -6,7 +6,6 @@ import { getActions } from '../../../global';
|
||||
import type { ActiveEmojiInteraction } from '../../../global/types';
|
||||
|
||||
import safePlay from '../../../util/safePlay';
|
||||
import { selectLocalAnimatedEmojiEffectByName } from '../../../global/selectors';
|
||||
import buildStyle from '../../../util/buildStyle';
|
||||
import { REM } from '../helpers/mediaDimensions';
|
||||
|
||||
@ -23,7 +22,6 @@ export default function useAnimatedEmoji(
|
||||
soundId?: string,
|
||||
activeEmojiInteractions?: ActiveEmojiInteraction[],
|
||||
isOwn?: boolean,
|
||||
localEffect?: string,
|
||||
emoji?: string,
|
||||
preferredSize?: number,
|
||||
) {
|
||||
@ -31,8 +29,6 @@ export default function useAnimatedEmoji(
|
||||
interactWithAnimatedEmoji, sendEmojiInteraction, sendWatchingEmojiInteraction,
|
||||
} = getActions();
|
||||
|
||||
const hasEffect = localEffect || emoji;
|
||||
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
@ -42,7 +38,7 @@ export default function useAnimatedEmoji(
|
||||
const soundMediaData = useMedia(soundId ? `document${soundId}` : undefined, !soundId);
|
||||
|
||||
const size = preferredSize || SIZE;
|
||||
const style = buildStyle(`width: ${size}px`, `height: ${size}px`, (emoji || localEffect) && 'cursor: pointer');
|
||||
const style = buildStyle(`width: ${size}px`, `height: ${size}px`, emoji && 'cursor: pointer');
|
||||
|
||||
const interactions = useRef<number[] | undefined>(undefined);
|
||||
const startedInteractions = useRef<number | undefined>(undefined);
|
||||
@ -54,13 +50,12 @@ export default function useAnimatedEmoji(
|
||||
sendEmojiInteraction({
|
||||
chatId: chatId!,
|
||||
messageId: messageId!,
|
||||
localEffect,
|
||||
emoji: emoji!,
|
||||
interactions: interactions.current!,
|
||||
});
|
||||
startedInteractions.current = undefined;
|
||||
interactions.current = undefined;
|
||||
}, [sendEmojiInteraction, chatId, messageId, localEffect, emoji]);
|
||||
}, [sendEmojiInteraction, chatId, messageId, emoji]);
|
||||
|
||||
const play = useCallback(() => {
|
||||
const audio = audioRef.current;
|
||||
@ -83,14 +78,13 @@ export default function useAnimatedEmoji(
|
||||
|
||||
const container = ref.current;
|
||||
|
||||
if (!hasEffect || !container || !messageId || !chatId) {
|
||||
if (!emoji || !container || !messageId || !chatId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { x, y } = container.getBoundingClientRect();
|
||||
|
||||
interactWithAnimatedEmoji({
|
||||
localEffect,
|
||||
emoji: emoji!,
|
||||
x,
|
||||
y,
|
||||
@ -107,10 +101,7 @@ export default function useAnimatedEmoji(
|
||||
interactions.current.push(startedInteractions.current
|
||||
? (performance.now() - startedInteractions.current) / MS_DIVIDER
|
||||
: TIME_DEFAULT);
|
||||
}, [
|
||||
chatId, emoji, hasEffect, interactWithAnimatedEmoji, isOwn,
|
||||
localEffect, messageId, play, sendInteractionBunch, size,
|
||||
]);
|
||||
}, [chatId, emoji, interactWithAnimatedEmoji, isOwn, messageId, play, sendInteractionBunch, size]);
|
||||
|
||||
// Set an end anchor for remote activated interaction
|
||||
useEffect(() => {
|
||||
@ -132,7 +123,7 @@ export default function useAnimatedEmoji(
|
||||
sendWatchingEmojiInteraction({
|
||||
id,
|
||||
chatId: chatId!,
|
||||
emoticon: localEffect ? selectLocalAnimatedEmojiEffectByName(localEffect)! : emoji!,
|
||||
emoticon: emoji!,
|
||||
startSize: size,
|
||||
x,
|
||||
y,
|
||||
@ -140,9 +131,7 @@ export default function useAnimatedEmoji(
|
||||
});
|
||||
play();
|
||||
});
|
||||
}, [
|
||||
activeEmojiInteractions, chatId, emoji, isOwn, localEffect, messageId, play, sendWatchingEmojiInteraction, size,
|
||||
]);
|
||||
}, [activeEmojiInteractions, chatId, emoji, isOwn, messageId, play, sendWatchingEmojiInteraction, size]);
|
||||
|
||||
return {
|
||||
ref,
|
||||
|
||||
@ -13,7 +13,6 @@ import buildClassName from '../../util/buildClassName';
|
||||
import {
|
||||
selectAnimatedEmojiEffect,
|
||||
} from '../../global/selectors';
|
||||
import { LOCAL_TGS_URLS } from '../common/helpers/animatedAssets';
|
||||
import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
|
||||
|
||||
import AnimatedSticker from '../common/AnimatedSticker';
|
||||
@ -26,7 +25,6 @@ export type OwnProps = {
|
||||
|
||||
type StateProps = {
|
||||
effectAnimationId?: string;
|
||||
localEffectAnimation?: string;
|
||||
};
|
||||
|
||||
const HIDE_ANIMATION_DURATION = 250;
|
||||
@ -35,7 +33,6 @@ const EFFECT_SIZE = 309;
|
||||
|
||||
const EmojiInteractionAnimation: FC<OwnProps & StateProps> = ({
|
||||
effectAnimationId,
|
||||
localEffectAnimation,
|
||||
activeEmojiInteraction,
|
||||
}) => {
|
||||
const { stopActiveEmojiInteraction } = getActions();
|
||||
@ -91,9 +88,6 @@ const EmojiInteractionAnimation: FC<OwnProps & StateProps> = ({
|
||||
}
|
||||
|
||||
const scale = (activeEmojiInteraction.startSize || 0) / EFFECT_SIZE;
|
||||
const tgsUrl = localEffectAnimation && (localEffectAnimation in LOCAL_TGS_URLS)
|
||||
? LOCAL_TGS_URLS[localEffectAnimation as keyof typeof LOCAL_TGS_URLS]
|
||||
: effectTgsUrl;
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -108,7 +102,7 @@ const EmojiInteractionAnimation: FC<OwnProps & StateProps> = ({
|
||||
<AnimatedSticker
|
||||
key={`effect_${effectAnimationId}`}
|
||||
size={EFFECT_SIZE}
|
||||
tgsUrl={tgsUrl}
|
||||
tgsUrl={effectTgsUrl}
|
||||
play={isPlaying}
|
||||
quality={IS_ANDROID ? 0.5 : undefined}
|
||||
forceOnHeavyAnimation
|
||||
@ -125,9 +119,6 @@ export default memo(withGlobal<OwnProps>(
|
||||
&& selectAnimatedEmojiEffect(global, activeEmojiInteraction.animatedEffect);
|
||||
return {
|
||||
effectAnimationId: animatedEffect ? animatedEffect.id : undefined,
|
||||
localEffectAnimation: !animatedEffect && activeEmojiInteraction.animatedEffect
|
||||
&& Object.keys(LOCAL_TGS_URLS).includes(activeEmojiInteraction.animatedEffect)
|
||||
? activeEmojiInteraction.animatedEffect : undefined,
|
||||
};
|
||||
},
|
||||
)(EmojiInteractionAnimation));
|
||||
|
||||
@ -54,7 +54,7 @@ const AnimatedCustomEmoji: FC<OwnProps & StateProps> = ({
|
||||
style,
|
||||
handleClick,
|
||||
} = useAnimatedEmoji(
|
||||
chatId, messageId, soundId, activeEmojiInteractions, isOwn, undefined, effect?.emoji, getCustomEmojiSize(1),
|
||||
chatId, messageId, soundId, activeEmojiInteractions, isOwn, effect?.emoji, getCustomEmojiSize(1),
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@ -6,21 +6,17 @@ import type { ApiSticker } from '../../../api/types';
|
||||
import type { ActiveEmojiInteraction } from '../../../global/types';
|
||||
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||
|
||||
import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets';
|
||||
import { LIKE_STICKER_ID } from '../../common/helpers/mediaDimensions';
|
||||
import {
|
||||
selectAnimatedEmoji,
|
||||
selectAnimatedEmojiEffect,
|
||||
selectAnimatedEmojiSound,
|
||||
selectLocalAnimatedEmoji,
|
||||
selectLocalAnimatedEmojiEffect,
|
||||
} from '../../../global/selectors';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
||||
import useAnimatedEmoji from '../../common/hooks/useAnimatedEmoji';
|
||||
|
||||
import AnimatedIconFromSticker from '../../common/AnimatedIconFromSticker';
|
||||
import AnimatedIconWithPreview from '../../common/AnimatedIconWithPreview';
|
||||
|
||||
import './AnimatedEmoji.scss';
|
||||
|
||||
@ -39,8 +35,6 @@ type OwnProps = {
|
||||
interface StateProps {
|
||||
sticker?: ApiSticker;
|
||||
effect?: ApiSticker;
|
||||
localSticker?: keyof typeof LOCAL_TGS_URLS;
|
||||
localEffect?: string;
|
||||
soundId?: string;
|
||||
}
|
||||
|
||||
@ -56,8 +50,6 @@ const AnimatedEmoji: FC<OwnProps & StateProps> = ({
|
||||
activeEmojiInteractions,
|
||||
sticker,
|
||||
effect,
|
||||
localSticker,
|
||||
localEffect,
|
||||
soundId,
|
||||
}) => {
|
||||
const {
|
||||
@ -65,22 +57,10 @@ const AnimatedEmoji: FC<OwnProps & StateProps> = ({
|
||||
size,
|
||||
style,
|
||||
handleClick,
|
||||
} = useAnimatedEmoji(chatId, messageId, soundId, activeEmojiInteractions, isOwn, localEffect, effect?.emoji);
|
||||
} = useAnimatedEmoji(chatId, messageId, soundId, activeEmojiInteractions, isOwn, effect?.emoji);
|
||||
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
||||
|
||||
return localSticker ? (
|
||||
<AnimatedIconWithPreview
|
||||
tgsUrl={LOCAL_TGS_URLS[localSticker]}
|
||||
size={size}
|
||||
quality={QUALITY}
|
||||
play={isIntersecting}
|
||||
forceOnHeavyAnimation
|
||||
ref={ref}
|
||||
className="AnimatedEmoji media-inner"
|
||||
style={style}
|
||||
onClick={handleClick}
|
||||
/>
|
||||
) : (
|
||||
return (
|
||||
<AnimatedIconFromSticker
|
||||
sticker={sticker}
|
||||
size={size}
|
||||
@ -99,13 +79,9 @@ const AnimatedEmoji: FC<OwnProps & StateProps> = ({
|
||||
};
|
||||
|
||||
export default memo(withGlobal<OwnProps>((global, { emoji, withEffects }) => {
|
||||
const localSticker = selectLocalAnimatedEmoji(global, emoji);
|
||||
|
||||
return {
|
||||
sticker: selectAnimatedEmoji(global, emoji),
|
||||
effect: withEffects ? selectAnimatedEmojiEffect(global, emoji) : undefined,
|
||||
soundId: selectAnimatedEmojiSound(global, emoji),
|
||||
localSticker,
|
||||
localEffect: localSticker && withEffects ? selectLocalAnimatedEmojiEffect(localSticker) : undefined,
|
||||
};
|
||||
})(AnimatedEmoji));
|
||||
|
||||
@ -59,7 +59,6 @@ import {
|
||||
selectDefaultReaction,
|
||||
selectReplySender,
|
||||
selectAnimatedEmoji,
|
||||
selectLocalAnimatedEmoji,
|
||||
selectIsCurrentUserPremium,
|
||||
selectIsChatProtected,
|
||||
selectTopicFromMessage,
|
||||
@ -1262,9 +1261,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
const { query: highlight } = selectCurrentTextSearch(global) || {};
|
||||
|
||||
const singleEmoji = getMessageSingleRegularEmoji(message);
|
||||
const animatedEmoji = singleEmoji && (
|
||||
selectAnimatedEmoji(global, singleEmoji) || selectLocalAnimatedEmoji(global, singleEmoji)
|
||||
) ? singleEmoji : undefined;
|
||||
const animatedEmoji = singleEmoji && selectAnimatedEmoji(global, singleEmoji) ? singleEmoji : undefined;
|
||||
const animatedCustomEmoji = getMessageSingleCustomEmoji(message);
|
||||
|
||||
let isSelected: boolean;
|
||||
|
||||
@ -6,7 +6,6 @@ import {
|
||||
selectChat,
|
||||
selectChatMessage, selectCurrentChat, selectTabState,
|
||||
selectDefaultReaction,
|
||||
selectLocalAnimatedEmojiEffectByName,
|
||||
selectMaxUserReactions,
|
||||
selectMessageIdsByGroupId,
|
||||
selectCurrentMessageList,
|
||||
@ -52,12 +51,12 @@ addActionHandler('loadAvailableReactions', async (global): Promise<void> => {
|
||||
|
||||
addActionHandler('interactWithAnimatedEmoji', (global, actions, payload): ActionReturnType => {
|
||||
const {
|
||||
emoji, x, y, localEffect, startSize, isReversed, tabId = getCurrentTabId(),
|
||||
emoji, x, y, startSize, isReversed, tabId = getCurrentTabId(),
|
||||
} = payload!;
|
||||
|
||||
const activeEmojiInteraction = {
|
||||
id: interactionLocalId++,
|
||||
animatedEffect: emoji || localEffect,
|
||||
animatedEffect: emoji,
|
||||
x: subtractXForEmojiInteraction(global, x) + Math.random()
|
||||
* INTERACTION_RANDOM_OFFSET - INTERACTION_RANDOM_OFFSET / 2,
|
||||
y: y + Math.random() * INTERACTION_RANDOM_OFFSET - INTERACTION_RANDOM_OFFSET / 2,
|
||||
@ -72,19 +71,19 @@ addActionHandler('interactWithAnimatedEmoji', (global, actions, payload): Action
|
||||
|
||||
addActionHandler('sendEmojiInteraction', (global, actions, payload): ActionReturnType => {
|
||||
const {
|
||||
messageId, chatId, emoji, interactions, localEffect,
|
||||
messageId, chatId, emoji, interactions,
|
||||
} = payload!;
|
||||
|
||||
const chat = selectChat(global, chatId);
|
||||
|
||||
if (!chat || (!emoji && !localEffect) || chatId === global.currentUserId) {
|
||||
if (!chat || !emoji || chatId === global.currentUserId) {
|
||||
return;
|
||||
}
|
||||
|
||||
void callApi('sendEmojiInteraction', {
|
||||
chat,
|
||||
messageId,
|
||||
emoticon: emoji || selectLocalAnimatedEmojiEffectByName(localEffect!)!,
|
||||
emoticon: emoji,
|
||||
timestamps: interactions,
|
||||
});
|
||||
});
|
||||
|
||||
@ -48,8 +48,6 @@ import {
|
||||
selectFirstUnreadId,
|
||||
selectChat,
|
||||
selectIsServiceChatReady,
|
||||
selectLocalAnimatedEmojiEffect,
|
||||
selectLocalAnimatedEmoji,
|
||||
selectThreadIdFromMessage,
|
||||
selectTopicFromMessage,
|
||||
selectTabState,
|
||||
@ -153,13 +151,11 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
|
||||
// Workaround for a weird behavior when interaction is received after watching reaction
|
||||
if (getMessageText(message) !== update.emoji) return;
|
||||
|
||||
const localEmoji = selectLocalAnimatedEmoji(global, update.emoji);
|
||||
|
||||
const tabState = selectTabState(global, tabId);
|
||||
global = updateTabState(global, {
|
||||
activeEmojiInteractions: [...(tabState.activeEmojiInteractions || []), {
|
||||
id: tabState.activeEmojiInteractions?.length || 0,
|
||||
animatedEffect: localEmoji ? selectLocalAnimatedEmojiEffect(localEmoji) : update.emoji,
|
||||
animatedEffect: update.emoji,
|
||||
messageId: update.messageId,
|
||||
} as ActiveEmojiInteraction],
|
||||
}, tabId);
|
||||
|
||||
@ -133,20 +133,6 @@ export function selectAnimatedEmojiSound<T extends GlobalState>(global: T, emoji
|
||||
return global?.appConfig?.emojiSounds[cleanEmoji(emoji)];
|
||||
}
|
||||
|
||||
export function selectLocalAnimatedEmoji<T extends GlobalState>(global: T, emoji: string) {
|
||||
const cleanedEmoji = cleanEmoji(emoji);
|
||||
|
||||
return cleanedEmoji === '🍑' ? 'Peach' : (cleanedEmoji === '🍆' ? 'Eggplant' : undefined);
|
||||
}
|
||||
|
||||
export function selectLocalAnimatedEmojiEffect(emoji: string) {
|
||||
return emoji === 'Eggplant' ? 'Cumshot' : undefined;
|
||||
}
|
||||
|
||||
export function selectLocalAnimatedEmojiEffectByName(name: string) {
|
||||
return name === 'Cumshot' ? '🍆' : undefined;
|
||||
}
|
||||
|
||||
export function selectIsAlwaysHighPriorityEmoji<T extends GlobalState>(
|
||||
global: T, stickerSet: ApiStickerSetInfo | ApiStickerSet,
|
||||
) {
|
||||
|
||||
@ -1167,7 +1167,6 @@ export interface ActionPayloads {
|
||||
emoji: string;
|
||||
x: number;
|
||||
y: number;
|
||||
localEffect?: string;
|
||||
startSize: number;
|
||||
isReversed?: boolean;
|
||||
} & WithTabId;
|
||||
@ -1181,7 +1180,6 @@ export interface ActionPayloads {
|
||||
chatId: string;
|
||||
emoji: string;
|
||||
interactions: number[];
|
||||
localEffect?: string;
|
||||
};
|
||||
sendWatchingEmojiInteraction: {
|
||||
chatId: string;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/lib/gramjs/client/__data__/TestLottie1.tgs
Normal file
BIN
src/lib/gramjs/client/__data__/TestLottie1.tgs
Normal file
Binary file not shown.
BIN
src/lib/gramjs/client/__data__/TestLottie2.tgs
Normal file
BIN
src/lib/gramjs/client/__data__/TestLottie2.tgs
Normal file
Binary file not shown.
BIN
src/lib/gramjs/client/__data__/TestLottie3.tgs
Normal file
BIN
src/lib/gramjs/client/__data__/TestLottie3.tgs
Normal file
Binary file not shown.
@ -101,17 +101,17 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"url": "Eggplant.tgs",
|
||||
"url": "TestLottie1.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"url": "Peach.tgs",
|
||||
"url": "TestLottie2.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"url": "Cumshot.tgs",
|
||||
"url": "TestLottie3.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
}
|
||||
]
|
||||
|
||||
@ -77,17 +77,17 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"url": "Eggplant.tgs",
|
||||
"url": "TestLottie1.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"url": "Peach.tgs",
|
||||
"url": "TestLottie2.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"url": "Cumshot.tgs",
|
||||
"url": "TestLottie3.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
}
|
||||
]
|
||||
|
||||
@ -77,17 +77,17 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"url": "Eggplant.tgs",
|
||||
"url": "TestLottie1.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"url": "Peach.tgs",
|
||||
"url": "TestLottie2.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"url": "Cumshot.tgs",
|
||||
"url": "TestLottie3.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
}
|
||||
]
|
||||
|
||||
@ -76,17 +76,17 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"url": "Eggplant.tgs",
|
||||
"url": "TestLottie1.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"url": "Peach.tgs",
|
||||
"url": "TestLottie2.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"url": "Cumshot.tgs",
|
||||
"url": "TestLottie3.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
}
|
||||
]
|
||||
|
||||
@ -57,17 +57,17 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"url": "Eggplant.tgs",
|
||||
"url": "TestLottie1.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"url": "Peach.tgs",
|
||||
"url": "TestLottie2.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"url": "Cumshot.tgs",
|
||||
"url": "TestLottie3.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
}
|
||||
]
|
||||
|
||||
@ -142,17 +142,17 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"url": "Eggplant.tgs",
|
||||
"url": "TestLottie1.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"url": "Peach.tgs",
|
||||
"url": "TestLottie2.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"url": "Cumshot.tgs",
|
||||
"url": "TestLottie3.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
}
|
||||
]
|
||||
|
||||
@ -84,17 +84,17 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"url": "Eggplant.tgs",
|
||||
"url": "TestLottie1.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"url": "Peach.tgs",
|
||||
"url": "TestLottie2.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"url": "Cumshot.tgs",
|
||||
"url": "TestLottie3.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
}
|
||||
]
|
||||
|
||||
@ -79,17 +79,17 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"url": "Eggplant.tgs",
|
||||
"url": "TestLottie1.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"url": "Peach.tgs",
|
||||
"url": "TestLottie2.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"url": "Cumshot.tgs",
|
||||
"url": "TestLottie3.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
}
|
||||
]
|
||||
|
||||
@ -82,17 +82,17 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"url": "Eggplant.tgs",
|
||||
"url": "TestLottie1.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"url": "Peach.tgs",
|
||||
"url": "TestLottie2.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"url": "Cumshot.tgs",
|
||||
"url": "TestLottie3.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
}
|
||||
]
|
||||
|
||||
@ -99,17 +99,17 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"url": "Eggplant.tgs",
|
||||
"url": "TestLottie1.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"url": "Peach.tgs",
|
||||
"url": "TestLottie2.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"url": "Cumshot.tgs",
|
||||
"url": "TestLottie3.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
}
|
||||
]
|
||||
|
||||
@ -182,17 +182,17 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"url": "Eggplant.tgs",
|
||||
"url": "TestLottie1.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"url": "Peach.tgs",
|
||||
"url": "TestLottie2.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"url": "Cumshot.tgs",
|
||||
"url": "TestLottie3.tgs",
|
||||
"mimeType": "application/x-tgsticker"
|
||||
}
|
||||
]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user