TelegramPWA/src/components/left/main/StatusButton.tsx
2023-09-15 16:44:43 +02:00

105 lines
3.5 KiB
TypeScript

import type { FC } from '../../../lib/teact/teact';
import React, { memo, useCallback, useRef } from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
import type { ApiEmojiStatus, ApiSticker } from '../../../api/types';
import { EMOJI_STATUS_LOOP_LIMIT } from '../../../config';
import { selectUser } from '../../../global/selectors';
import { getServerTimeOffset } from '../../../util/serverTime';
import useAppLayout from '../../../hooks/useAppLayout';
import useEffectWithPrevDeps from '../../../hooks/useEffectWithPrevDeps';
import useFlag from '../../../hooks/useFlag';
import useTimeout from '../../../hooks/useTimeout';
import CustomEmoji from '../../common/CustomEmoji';
import PremiumIcon from '../../common/PremiumIcon';
import CustomEmojiEffect from '../../common/reactions/CustomEmojiEffect';
import Button from '../../ui/Button';
import StatusPickerMenu from './StatusPickerMenu.async';
interface StateProps {
emojiStatus?: ApiEmojiStatus;
}
const EFFECT_DURATION_MS = 1500;
const EMOJI_STATUS_SIZE = 24;
const StatusButton: FC<StateProps> = ({ emojiStatus }) => {
const { setEmojiStatus, loadCurrentUser } = getActions();
// eslint-disable-next-line no-null/no-null
const buttonRef = useRef<HTMLButtonElement>(null);
const [shouldShowEffect, markShouldShowEffect, unmarkShouldShowEffect] = useFlag(false);
const [isEffectShown, showEffect, hideEffect] = useFlag(false);
const [isStatusPickerOpen, openStatusPicker, closeStatusPicker] = useFlag(false);
const { isMobile } = useAppLayout();
const delay = emojiStatus?.until ? emojiStatus.until * 1000 - Date.now() + getServerTimeOffset() * 1000 : undefined;
useTimeout(loadCurrentUser, delay);
useEffectWithPrevDeps(([prevEmojiStatus]) => {
if (shouldShowEffect && emojiStatus && prevEmojiStatus && emojiStatus.documentId !== prevEmojiStatus.documentId) {
showEffect();
unmarkShouldShowEffect();
}
}, [emojiStatus, shouldShowEffect, showEffect, unmarkShouldShowEffect]);
const handleEmojiStatusSet = useCallback((sticker: ApiSticker) => {
markShouldShowEffect();
setEmojiStatus({ emojiStatus: sticker });
}, [markShouldShowEffect, setEmojiStatus]);
useTimeout(hideEffect, isEffectShown ? EFFECT_DURATION_MS : undefined);
const handleEmojiStatusClick = useCallback(() => {
openStatusPicker();
}, [openStatusPicker]);
return (
<div className="extra-spacing">
{Boolean(isEffectShown && emojiStatus) && (
<CustomEmojiEffect
reaction={emojiStatus!}
isLottie
className="emoji-status-effect"
/>
)}
<Button
round
ref={buttonRef}
ripple={!isMobile}
size="smaller"
color="translucent"
className="emoji-status"
onClick={handleEmojiStatusClick}
>
{emojiStatus ? (
<CustomEmoji
key={emojiStatus.documentId}
documentId={emojiStatus.documentId}
size={EMOJI_STATUS_SIZE}
loopLimit={EMOJI_STATUS_LOOP_LIMIT}
/>
) : <PremiumIcon />}
</Button>
<StatusPickerMenu
statusButtonRef={buttonRef}
isOpen={isStatusPickerOpen}
onEmojiStatusSelect={handleEmojiStatusSet}
onClose={closeStatusPicker}
/>
</div>
);
};
export default memo(withGlobal((global): StateProps => {
const { currentUserId } = global;
const currentUser = currentUserId ? selectUser(global, currentUserId) : undefined;
return {
emojiStatus: currentUser?.emojiStatus,
};
})(StatusButton));