2025-04-04 13:14:36 +02:00

163 lines
5.6 KiB
TypeScript

import React, { memo, useMemo, useRef } from '../../../../lib/teact/teact';
import { withGlobal } from '../../../../global';
import type { ApiMessage, ApiPeer } from '../../../../api/types';
import type { ApiMessageActionStarGiftUnique } from '../../../../api/types/messageActions';
import { getPeerTitle } from '../../../../global/helpers/peers';
import {
selectCanPlayAnimatedEmojis,
selectPeer,
selectSender,
selectUser,
} from '../../../../global/selectors';
import buildClassName from '../../../../util/buildClassName';
import buildStyle from '../../../../util/buildStyle';
import { getGiftAttributes, getStickerFromGift } from '../../../common/helpers/gifts';
import { renderPeerLink } from '../helpers/messageActions';
import { type ObserveFn } from '../../../../hooks/useIntersectionObserver';
import useLang from '../../../../hooks/useLang';
import GiftRibbon from '../../../common/gift/GiftRibbon';
import MiniTable, { type TableEntry } from '../../../common/MiniTable';
import RadialPatternBackground from '../../../common/profile/RadialPatternBackground';
import Sparkles from '../../../common/Sparkles';
import StickerView from '../../../common/StickerView';
import styles from '../ActionMessage.module.scss';
type OwnProps = {
message: ApiMessage;
action: ApiMessageActionStarGiftUnique;
observeIntersectionForLoading?: ObserveFn;
observeIntersectionForPlaying?: ObserveFn;
onClick?: NoneToVoidFunction;
};
type StateProps = {
canPlayAnimatedEmojis: boolean;
sender?: ApiPeer;
recipient?: ApiPeer;
};
const STICKER_SIZE = 120;
const StarGiftAction = ({
action,
message,
canPlayAnimatedEmojis,
sender,
recipient,
onClick,
observeIntersectionForLoading,
observeIntersectionForPlaying,
}: OwnProps & StateProps) => {
// eslint-disable-next-line no-null/no-null
const stickerRef = useRef<HTMLDivElement>(null);
const lang = useLang();
const { isOutgoing } = message;
const sticker = getStickerFromGift(action.gift)!;
const attributes = getGiftAttributes(action.gift)!;
const model = attributes.model!;
const pattern = attributes.pattern!;
const backdrop = attributes.backdrop!;
const backgroundColors = [backdrop.centerColor, backdrop.edgeColor];
const adaptedPatternColor = `${backdrop.patternColor.slice(0, 7)}55`;
const tableData = useMemo((): TableEntry[] => [
[lang('ActionStarGiftUniqueModel'), model.name],
[lang('ActionStarGiftUniqueBackdrop'), backdrop.name],
[lang('ActionStarGiftUniqueSymbol'), pattern.name],
], [lang, model, pattern, backdrop]);
const shouldShowFrom = !isOutgoing || action.isUpgrade;
const peer = shouldShowFrom && !action.isUpgrade ? sender : recipient;
const fallbackPeerTitle = lang('ActionFallbackSomeone');
const peerTitle = peer && getPeerTitle(lang, peer);
const isSelf = sender?.id === recipient?.id;
return (
<div
className={buildClassName(styles.contentBox, styles.starGift, styles.uniqueGift)}
tabIndex={0}
role="button"
onClick={onClick}
>
<div className={styles.uniqueBackgroundWrapper}>
<RadialPatternBackground
className={styles.uniqueBackground}
backgroundColors={backgroundColors}
patternColor={backdrop.patternColor}
patternIcon={pattern.sticker}
clearBottomSector
/>
</div>
<div
ref={stickerRef}
className={styles.stickerWrapper}
style={`width: ${STICKER_SIZE}px; height: ${STICKER_SIZE}px`}
>
{sticker && (
<StickerView
containerRef={stickerRef}
sticker={sticker}
size={STICKER_SIZE}
observeIntersectionForLoading={observeIntersectionForLoading}
observeIntersectionForPlaying={observeIntersectionForPlaying}
noLoad={!canPlayAnimatedEmojis}
/>
)}
</div>
<GiftRibbon
color={adaptedPatternColor}
text={lang('ActionStarGiftUniqueRibbon')}
/>
<div className={styles.info}>
<h3 className={styles.title}>
{isSelf ? lang('ActionStarGiftSelf') : lang(
shouldShowFrom ? 'ActionStarGiftFrom' : 'ActionStarGiftTo',
{
peer: renderPeerLink(peer?.id, peerTitle || fallbackPeerTitle),
},
{
withNodes: true,
},
)}
</h3>
<div className={styles.subtitle} style={`color: ${backdrop.textColor}`}>
{lang('GiftUnique', { title: action.gift.title, number: action.gift.number })}
</div>
<MiniTable data={tableData} style={`color: ${backdrop.textColor}`} valueClassName={styles.uniqueValue} />
</div>
<div
className={styles.actionButton}
style={buildStyle(adaptedPatternColor && `background-color: ${adaptedPatternColor}`)}
>
<Sparkles preset="button" />
{lang('ActionViewButton')}
</div>
</div>
);
};
export default memo(withGlobal<OwnProps>(
(global, { message, action }): StateProps => {
const currentUser = selectUser(global, global.currentUserId!);
const canPlayAnimatedEmojis = selectCanPlayAnimatedEmojis(global);
const messageSender = selectSender(global, message);
const giftSender = action.fromId ? selectPeer(global, action.fromId) : undefined;
const messageRecipient = message.isOutgoing ? selectPeer(global, message.chatId) : currentUser;
const giftRecipient = action.peerId ? selectPeer(global, action.peerId) : undefined;
return {
canPlayAnimatedEmojis,
sender: giftSender || messageSender,
recipient: giftRecipient || messageRecipient,
};
},
)(StarGiftAction));