Unique gifts: Follow up (#5397)
This commit is contained in:
parent
783a5c2c01
commit
683384074a
@ -14,6 +14,7 @@ import type {
|
||||
ApiKeyboardButton,
|
||||
ApiMessage,
|
||||
ApiMessageActionStarGift,
|
||||
ApiMessageActionStarGiftUnique,
|
||||
ApiMessageEntity,
|
||||
ApiMessageForwardInfo,
|
||||
ApiMessageReportResult,
|
||||
@ -380,6 +381,24 @@ function buildApiMessageActionStarGift(action: GramJs.MessageActionStarGift) : A
|
||||
};
|
||||
}
|
||||
|
||||
function buildApiMessageActionStarGiftUnique(
|
||||
action: GramJs.MessageActionStarGiftUnique,
|
||||
): ApiMessageActionStarGiftUnique {
|
||||
const {
|
||||
gift, canExportAt, refunded, saved, transferStars, transferred, upgrade,
|
||||
} = action;
|
||||
|
||||
return {
|
||||
gift: buildApiStarGift(gift),
|
||||
canExportAt,
|
||||
isRefunded: refunded,
|
||||
isSaved: saved,
|
||||
transferStars: transferStars?.toJSNumber(),
|
||||
isTransferred: transferred,
|
||||
isUpgrade: upgrade,
|
||||
};
|
||||
}
|
||||
|
||||
function buildAction(
|
||||
action: GramJs.TypeMessageAction,
|
||||
senderId: string | undefined,
|
||||
@ -395,7 +414,7 @@ function buildAction(
|
||||
let call: Partial<ApiGroupCall> | undefined;
|
||||
let amount: number | undefined;
|
||||
let stars: number | undefined;
|
||||
let starGift: ApiMessageActionStarGift | undefined;
|
||||
let starGift: ApiMessageActionStarGift | ApiMessageActionStarGiftUnique | undefined;
|
||||
let currency: string | undefined;
|
||||
let giftCryptoInfo: {
|
||||
currency: string;
|
||||
@ -710,6 +729,7 @@ function buildAction(
|
||||
transactionId = action.transactionId;
|
||||
} else if (action instanceof GramJs.MessageActionStarGift && action.gift instanceof GramJs.StarGift) {
|
||||
type = 'starGift';
|
||||
starGift = buildApiMessageActionStarGift(action);
|
||||
if (isOutgoing) {
|
||||
text = 'ActionGiftOutbound';
|
||||
translationValues.push('%gift_payment_amount%');
|
||||
@ -725,7 +745,15 @@ function buildAction(
|
||||
|
||||
amount = action.gift.stars.toJSNumber();
|
||||
currency = STARS_CURRENCY_CODE;
|
||||
starGift = buildApiMessageActionStarGift(action);
|
||||
} else if (action instanceof GramJs.MessageActionStarGiftUnique && action.gift instanceof GramJs.StarGiftUnique) {
|
||||
type = 'starGiftUnique';
|
||||
text = isOutgoing ? 'Notification.StarsGift.UpgradeYou' : 'Notification.StarsGift.Upgrade';
|
||||
starGift = buildApiMessageActionStarGiftUnique(action);
|
||||
|
||||
if (targetPeerId) {
|
||||
targetUserIds.push(targetPeerId);
|
||||
targetChatId = targetPeerId;
|
||||
}
|
||||
} else {
|
||||
text = 'ChatList.UnsupportedMessage';
|
||||
}
|
||||
|
||||
@ -467,6 +467,16 @@ export interface ApiMessageActionStarGift {
|
||||
starsToConvert?: number;
|
||||
}
|
||||
|
||||
export interface ApiMessageActionStarGiftUnique {
|
||||
isUpgrade?: true;
|
||||
isTransferred?: true;
|
||||
isSaved?: true;
|
||||
isRefunded?: true;
|
||||
gift: ApiStarGift;
|
||||
canExportAt?: number;
|
||||
transferStars?: number;
|
||||
}
|
||||
|
||||
export interface ApiAction {
|
||||
mediaType: 'action';
|
||||
text: string;
|
||||
@ -487,6 +497,7 @@ export interface ApiAction {
|
||||
| 'giftCode'
|
||||
| 'prizeStars'
|
||||
| 'starGift'
|
||||
| 'starGiftUnique'
|
||||
| 'other';
|
||||
photo?: ApiPhoto;
|
||||
amount?: number;
|
||||
@ -497,7 +508,7 @@ export interface ApiAction {
|
||||
currency: string;
|
||||
amount: number;
|
||||
};
|
||||
starGift?: ApiMessageActionStarGift;
|
||||
starGift?: ApiMessageActionStarGift | ApiMessageActionStarGiftUnique;
|
||||
translationValues: string[];
|
||||
call?: Partial<ApiGroupCall>;
|
||||
phoneCall?: PhoneCallAction;
|
||||
|
||||
@ -93,6 +93,10 @@ export function renderActionMessageText(
|
||||
.replace('un2', '%action_origin%')
|
||||
.replace(/\*\*/g, '');
|
||||
}
|
||||
if (translationKey.startsWith('Notification.StarsGift.Upgrade')) {
|
||||
unprocessed = unprocessed
|
||||
.replace('%@', '%action_origin%');
|
||||
}
|
||||
if (translationKey === 'BoostingReceivedPrizeFrom') {
|
||||
unprocessed = unprocessed
|
||||
.replace('**%s**', '%target_chat%')
|
||||
|
||||
@ -6,7 +6,9 @@
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(var(--_bg-1), var(--_bg-2)), radial-gradient(circle, #ffffff32, #ffffff00);
|
||||
background-image:
|
||||
radial-gradient(circle closest-side, #ffffff32, #ffffff00),
|
||||
radial-gradient(closest-side, var(--_bg-1), var(--_bg-2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -13,14 +13,14 @@ import { preloadImage } from '../../../util/files';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import useMedia from '../../../hooks/useMedia';
|
||||
import useResizeObserver from '../../../hooks/useResizeObserver';
|
||||
import { useSignalEffect } from '../../../hooks/useSignalEffect';
|
||||
import useDevicePixelRatio from '../../../hooks/window/useDevicePixelRatio';
|
||||
|
||||
import styles from './RadialPatternBackground.module.scss';
|
||||
|
||||
type OwnProps = {
|
||||
backgroundColors: string[];
|
||||
patternColor: string;
|
||||
patternIcon: ApiSticker;
|
||||
patternColor?: string;
|
||||
patternIcon?: ApiSticker;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
@ -28,32 +28,33 @@ const RINGS = 3;
|
||||
const BASE_RING_ITEM_COUNT = 8;
|
||||
const RING_INCREMENT = 0.5;
|
||||
const CENTER_EMPTINESS = 0.05;
|
||||
const MAX_RADIUS = 0.5;
|
||||
const MAX_RADIUS = 0.4;
|
||||
const BASE_ICON_SIZE = 20;
|
||||
|
||||
const MIN_SIZE = 200;
|
||||
const MIN_SIZE = 250;
|
||||
|
||||
const PATTERN_POSITIONS = (() => {
|
||||
const coordinates: { x: number; y: number; alpha: number; sizeFactor: number }[] = [];
|
||||
const coordinates: { x: number; y: number; sizeFactor: number }[] = [];
|
||||
for (let ring = 1; ring <= RINGS; ring++) {
|
||||
const ringItemCount = Math.floor(BASE_RING_ITEM_COUNT * (1 + (ring - 1) * RING_INCREMENT));
|
||||
const ringProgress = ring / RINGS;
|
||||
const ringRadius = CENTER_EMPTINESS + (MAX_RADIUS - CENTER_EMPTINESS) * ringProgress;
|
||||
|
||||
const angleShift = ring % 2 === 0 ? Math.PI / ringItemCount : 0;
|
||||
|
||||
for (let i = 0; i < ringItemCount; i++) {
|
||||
const angle = (i / ringItemCount) * Math.PI * 2;
|
||||
const angle = (i / ringItemCount) * Math.PI * 2 + angleShift;
|
||||
// Slightly oval
|
||||
const xOffset = ringRadius * 1.71 * Math.cos(angle);
|
||||
const yOffset = ringRadius * Math.sin(angle);
|
||||
|
||||
const x = 0.5 + xOffset;
|
||||
const y = 0.5 + yOffset;
|
||||
const alpha = 0.2 + Math.min((1 - ringProgress + (Math.random() / 2 - 0.5)), 0) * 0.8;
|
||||
|
||||
const sizeFactor = 1.4 - ringProgress * Math.random();
|
||||
|
||||
coordinates.push({
|
||||
x, y, alpha, sizeFactor,
|
||||
x, y, sizeFactor,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -73,9 +74,11 @@ const RadialPatternBackground = ({
|
||||
|
||||
const [getContainerSize, setContainerSize] = useSignal({ width: 0, height: 0 });
|
||||
|
||||
const dpr = useDevicePixelRatio();
|
||||
|
||||
const [emojiImage, setEmojiImage] = useState<HTMLImageElement | undefined>();
|
||||
|
||||
const previewMediaHash = getStickerMediaHash(patternIcon, 'preview');
|
||||
const previewMediaHash = patternIcon && getStickerMediaHash(patternIcon, 'preview');
|
||||
const previewUrl = useMedia(previewMediaHash);
|
||||
|
||||
useEffect(() => {
|
||||
@ -109,22 +112,34 @@ const RadialPatternBackground = ({
|
||||
|
||||
ctx.save();
|
||||
PATTERN_POSITIONS.forEach(({
|
||||
x, y, alpha, sizeFactor,
|
||||
x, y, sizeFactor,
|
||||
}) => {
|
||||
const centerShift = (width - Math.max(width, MIN_SIZE)) / 2; // Shift coords if canvas is smaller than `MIN_SIZE`
|
||||
const renderX = x * Math.max(width, MIN_SIZE) + centerShift;
|
||||
const renderY = y * Math.max(height, MIN_SIZE) + centerShift;
|
||||
const centerShift = (width - Math.max(width, MIN_SIZE * dpr)) / 2; // Shift coords if canvas is smaller than `MIN_SIZE`
|
||||
const renderX = x * Math.max(width, MIN_SIZE * dpr) + centerShift;
|
||||
const renderY = y * Math.max(height, MIN_SIZE * dpr) + centerShift;
|
||||
|
||||
const size = BASE_ICON_SIZE * sizeFactor * (centerShift ? 0.8 : 1);
|
||||
const size = BASE_ICON_SIZE * dpr * sizeFactor * (centerShift ? 0.8 : 1);
|
||||
|
||||
ctx.globalAlpha = alpha;
|
||||
ctx.drawImage(emojiImage, renderX - size / 2, renderY - size / 2, size, size);
|
||||
});
|
||||
ctx.restore();
|
||||
|
||||
if (patternColor) {
|
||||
ctx.save();
|
||||
ctx.fillStyle = patternColor;
|
||||
ctx.globalCompositeOperation = 'source-atop';
|
||||
ctx.fillRect(0, 0, width, height);
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
const radialGradient = ctx.createRadialGradient(width / 2, height / 2, 0, width / 2, height / 2, width / 2);
|
||||
radialGradient.addColorStop(0, '#FFFFFF00');
|
||||
radialGradient.addColorStop(1, '#FFFFFF');
|
||||
|
||||
// Alpha mask
|
||||
ctx.save();
|
||||
ctx.fillStyle = patternColor;
|
||||
ctx.globalCompositeOperation = 'source-atop';
|
||||
ctx.globalCompositeOperation = 'destination-out';
|
||||
ctx.fillStyle = radialGradient;
|
||||
ctx.fillRect(0, 0, width, height);
|
||||
ctx.restore();
|
||||
});
|
||||
@ -133,7 +148,7 @@ const RadialPatternBackground = ({
|
||||
draw();
|
||||
}, [emojiImage]);
|
||||
|
||||
useSignalEffect(() => {
|
||||
useEffect(() => {
|
||||
const { width, height } = getContainerSize();
|
||||
const canvas = canvasRef.current!;
|
||||
if (!width || !height) {
|
||||
@ -141,14 +156,13 @@ const RadialPatternBackground = ({
|
||||
}
|
||||
|
||||
const maxSide = Math.max(width, height);
|
||||
const dpr = window.devicePixelRatio;
|
||||
requestMutation(() => {
|
||||
canvas.width = maxSide * dpr;
|
||||
canvas.height = maxSide * dpr;
|
||||
|
||||
draw();
|
||||
});
|
||||
}, [getContainerSize]);
|
||||
}, [getContainerSize, dpr]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@ -5,7 +5,7 @@ import React, {
|
||||
import { getActions, getGlobal, withGlobal } from '../../global';
|
||||
|
||||
import type {
|
||||
ApiChat, ApiMessage, ApiSticker, ApiTopic, ApiUser,
|
||||
ApiChat, ApiMessage, ApiMessageActionStarGift, ApiSticker, ApiTopic, ApiUser,
|
||||
} from '../../api/types';
|
||||
import type { ObserveFn } from '../../hooks/useIntersectionObserver';
|
||||
import type { FocusDirection, MessageListType, ThreadId } from '../../types';
|
||||
@ -28,6 +28,7 @@ import {
|
||||
} from '../../global/selectors';
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
import { formatInteger, formatIntegerCompact } from '../../util/textFormat';
|
||||
import { getGiftAttributes, getStickerFromGift } from '../common/helpers/gifts';
|
||||
import { renderActionMessageText } from '../common/helpers/renderActionMessageText';
|
||||
import renderText from '../common/helpers/renderText';
|
||||
import { renderTextWithEntities } from '../common/helpers/renderTextWithEntities';
|
||||
@ -45,6 +46,7 @@ import useFocusMessage from './message/hooks/useFocusMessage';
|
||||
import AnimatedIconFromSticker from '../common/AnimatedIconFromSticker';
|
||||
import Avatar from '../common/Avatar';
|
||||
import GiftRibbon from '../common/gift/GiftRibbon';
|
||||
import RadialPatternBackground from '../common/profile/RadialPatternBackground';
|
||||
import Sparkles from '../common/Sparkles';
|
||||
import ActionMessageSuggestedAvatar from './ActionMessageSuggestedAvatar';
|
||||
import ActionMessageUpdatedAvatar from './ActionMessageUpdatedAvatar';
|
||||
@ -163,6 +165,7 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
|
||||
const isJoinedMessage = isJoinedChannelMessage(message);
|
||||
const isStarsGift = message.content.action?.type === 'giftStars';
|
||||
const isStarGift = message.content.action?.type === 'starGift';
|
||||
const isStarGiftUnique = message.content.action?.type === 'starGiftUnique';
|
||||
const isPrizeStars = message.content.action?.type === 'prizeStars';
|
||||
|
||||
const withServiceReactions = Boolean(message.areReactionsPossible && message?.reactions);
|
||||
@ -318,7 +321,7 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
|
||||
const giftMessage = message.content.action?.message;
|
||||
return (
|
||||
<span
|
||||
className="action-message-gift action-message-gift-code"
|
||||
className="action-message-gift action-message-centered"
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
onClick={handleGiftCodeClick}
|
||||
@ -366,7 +369,7 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
|
||||
function renderStarsGift() {
|
||||
return (
|
||||
<span
|
||||
className="action-message-gift action-message-gift-code"
|
||||
className="action-message-gift action-message-centered"
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
onClick={handleStarGiftClick}
|
||||
@ -421,9 +424,9 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
|
||||
}
|
||||
|
||||
function renderStarGiftUserDescription() {
|
||||
const starGift = message.content.action?.starGift;
|
||||
const starGift = message.content.action?.starGift as ApiMessageActionStarGift;
|
||||
const targetUser = targetUsers && targetUsers[0]?.firstName;
|
||||
const starGiftMessage = message.content.action?.starGift?.message;
|
||||
const starGiftMessage = starGift?.message;
|
||||
if (!starGift) return undefined;
|
||||
|
||||
if (starGiftMessage) {
|
||||
@ -468,11 +471,11 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
|
||||
|
||||
function renderStarGift() {
|
||||
const starGift = message.content.action?.starGift;
|
||||
if (!starGift || starGift.gift.type === 'starGiftUnique') return undefined;
|
||||
if (!starGift || starGift.gift.type !== 'starGift') return undefined;
|
||||
|
||||
return (
|
||||
<span
|
||||
className="action-message-gift action-message-gift-code action-message-star-gift"
|
||||
className="action-message-gift action-message-centered"
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
onClick={handleStarGiftClick}
|
||||
@ -507,12 +510,83 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
|
||||
);
|
||||
}
|
||||
|
||||
function renderStarGiftUnique() {
|
||||
const starGift = message.content.action?.starGift;
|
||||
if (!starGift || starGift.gift.type !== 'starGiftUnique') return undefined;
|
||||
|
||||
const sticker = getStickerFromGift(starGift.gift)!;
|
||||
const attributes = getGiftAttributes(starGift.gift);
|
||||
const { backdrop, pattern, model } = attributes || {};
|
||||
|
||||
if (!backdrop || !pattern || !model) return undefined;
|
||||
|
||||
const backgroundColors = [backdrop.centerColor, backdrop.edgeColor];
|
||||
|
||||
return (
|
||||
<span
|
||||
className="action-message-gift action-message-centered action-message-unique"
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
onClick={handleStarGiftClick}
|
||||
>
|
||||
<div className="action-message-unique-background-wrapper">
|
||||
<RadialPatternBackground
|
||||
className="action-message-unique-background"
|
||||
backgroundColors={backgroundColors}
|
||||
patternColor={backdrop.patternColor}
|
||||
patternIcon={pattern.sticker}
|
||||
/>
|
||||
</div>
|
||||
<AnimatedIconFromSticker
|
||||
sticker={sticker}
|
||||
play={canPlayAnimatedEmojis}
|
||||
noLoop
|
||||
nonInteractive
|
||||
size={STAR_GIFT_STICKER_SIZE}
|
||||
/>
|
||||
{renderStarGiftUserCaption()}
|
||||
<div className="action-message-unique-title" style={`color: ${backdrop.textColor}`}>
|
||||
{starGift.gift.title} #{starGift.gift.number}
|
||||
</div>
|
||||
<div className="action-message-unique-properties" style={`color: ${backdrop.textColor}`}>
|
||||
<div className="action-message-unique-property">
|
||||
{oldLang('Gift2AttributeModel')}
|
||||
</div>
|
||||
<div className="action-message-unique-value">
|
||||
{model.name}
|
||||
</div>
|
||||
<div className="action-message-unique-property">
|
||||
{oldLang('Gift2AttributeBackdrop')}
|
||||
</div>
|
||||
<div className="action-message-unique-value">
|
||||
{backdrop.name}
|
||||
</div>
|
||||
<div className="action-message-unique-property">
|
||||
{oldLang('Gift2AttributeSymbol')}
|
||||
</div>
|
||||
<div className="action-message-unique-value">
|
||||
{pattern.name}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="action-message-button">
|
||||
<Sparkles preset="button" />
|
||||
{oldLang('Gift2UniqueView')}
|
||||
</div>
|
||||
<GiftRibbon
|
||||
color={backdrop.patternColor || 'blue'}
|
||||
text={oldLang('ActionStarGift')}
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function renderPrizeStars() {
|
||||
const isUnclaimed = message.content.action?.isUnclaimed;
|
||||
|
||||
return (
|
||||
<span
|
||||
className="action-message-gift action-message-gift-code"
|
||||
className="action-message-gift action-message-centered"
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
onClick={handlePrizeStarsClick}
|
||||
@ -577,6 +651,7 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
|
||||
{isGiftCode && renderGiftCode()}
|
||||
{isStarsGift && renderStarsGift()}
|
||||
{isStarGift && renderStarGift()}
|
||||
{isStarGiftUnique && renderStarGiftUnique()}
|
||||
{isPrizeStars && renderPrizeStars()}
|
||||
{isSuggestedAvatar && (
|
||||
<ActionMessageSuggestedAvatar message={message} renderContent={renderContent} />
|
||||
|
||||
@ -286,12 +286,37 @@
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
|
||||
.action-message-gift-code {
|
||||
.action-message-centered {
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.action-message-unique {
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -0.25rem;
|
||||
background: var(--pattern-color);
|
||||
border-radius: calc(var(--border-radius-messages) + 0.25rem);
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
|
||||
.action-message-unique-background-wrapper {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
overflow: hidden;
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
||||
.action-message-unique-background {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
top: -6rem;
|
||||
}
|
||||
|
||||
.action-message-user-caption,
|
||||
.action-message-stars-balance {
|
||||
position: relative;
|
||||
margin-top: 0.5rem;
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
@ -305,6 +330,31 @@
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
|
||||
.action-message-unique-title {
|
||||
position: relative;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.action-message-unique-properties {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 0.375rem;
|
||||
font-size: 0.875rem;
|
||||
margin-top: 0.5rem;
|
||||
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.action-message-unique-value {
|
||||
color: white;
|
||||
justify-self: flex-start;
|
||||
}
|
||||
|
||||
.action-message-unique-property {
|
||||
justify-self: flex-end;
|
||||
font-weight: var(--font-weight-normal);
|
||||
}
|
||||
|
||||
.action-message-user-avatar {
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
@ -316,6 +366,7 @@
|
||||
}
|
||||
|
||||
.action-message-gift-subtitle {
|
||||
position: relative;
|
||||
font-weight: normal;
|
||||
text-wrap: balance;
|
||||
font-size: 0.8125rem;
|
||||
|
||||
@ -3,7 +3,8 @@
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
gap: 1rem;
|
||||
padding-inline: 1rem !important;
|
||||
max-height: min(92vh, 40rem) !important;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ type OwnProps = {
|
||||
footer?: TeactNode;
|
||||
buttonText?: string;
|
||||
className?: string;
|
||||
hasBackdrop?: boolean;
|
||||
onClose: NoneToVoidFunction;
|
||||
onButtonClick?: NoneToVoidFunction;
|
||||
};
|
||||
@ -41,6 +42,7 @@ const TableInfoModal = ({
|
||||
footer,
|
||||
buttonText,
|
||||
className,
|
||||
hasBackdrop,
|
||||
onClose,
|
||||
onButtonClick,
|
||||
}: OwnProps) => {
|
||||
@ -55,6 +57,7 @@ const TableInfoModal = ({
|
||||
isOpen={isOpen}
|
||||
hasCloseButton={Boolean(title)}
|
||||
hasAbsoluteCloseButton={!title}
|
||||
absoluteCloseButtonColor={hasBackdrop ? 'translucent-white' : undefined}
|
||||
isSlim
|
||||
title={title}
|
||||
className={className}
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
text-align: center;
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
@ -53,8 +52,8 @@
|
||||
.radialPattern {
|
||||
position: absolute;
|
||||
top: -3rem;
|
||||
left: -1.5rem;
|
||||
right: -1.5rem;
|
||||
left: -1rem;
|
||||
right: -1rem;
|
||||
height: 16.5rem;
|
||||
|
||||
z-index: -1;
|
||||
@ -77,4 +76,8 @@
|
||||
font-size: 1.25rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,14 +138,12 @@ const GiftInfoModal = ({
|
||||
const isVisibleForMe = isNameHidden && targetUser;
|
||||
|
||||
const description = (() => {
|
||||
if (!userGift) {
|
||||
return lang('GiftInfoSoldOutDescription');
|
||||
}
|
||||
if (gift.type === 'starGiftUnique') {
|
||||
return lang('GiftInfoCollectible', {
|
||||
number: gift.number,
|
||||
});
|
||||
}
|
||||
if (!userGift) return lang('GiftInfoSoldOutDescription');
|
||||
if (!canUpdate && !isSender) return undefined;
|
||||
if (!starsToConvert || canConvertDifference < 0) return undefined;
|
||||
if (isConverted) {
|
||||
@ -186,8 +184,8 @@ const GiftInfoModal = ({
|
||||
})();
|
||||
|
||||
function getTitle() {
|
||||
if (!userGift) return lang('GiftInfoSoldOutTitle');
|
||||
if (gift?.type === 'starGiftUnique') return gift.title;
|
||||
if (!userGift) return lang('GiftInfoSoldOutTitle');
|
||||
|
||||
return canUpdate ? lang('GiftInfoReceived') : lang('GiftInfoTitle');
|
||||
}
|
||||
@ -219,7 +217,7 @@ const GiftInfoModal = ({
|
||||
</p>
|
||||
)}
|
||||
{description && (
|
||||
<p className={buildClassName(styles.description, !userGift && styles.soldOut)}>
|
||||
<p className={buildClassName(styles.description, !userGift && gift?.type === 'starGift' && styles.soldOut)}>
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
@ -457,6 +455,7 @@ const GiftInfoModal = ({
|
||||
<TableInfoModal
|
||||
isOpen={isOpen}
|
||||
header={modalData?.header}
|
||||
hasBackdrop={Boolean(radialPatternBackdrop)}
|
||||
tableData={modalData?.tableData}
|
||||
footer={modalData?.footer}
|
||||
className={styles.modal}
|
||||
|
||||
@ -16,7 +16,7 @@ import useOldLang from '../../hooks/useOldLang';
|
||||
import useShowTransition from '../../hooks/useShowTransition';
|
||||
|
||||
import Icon from '../common/icons/Icon';
|
||||
import Button from './Button';
|
||||
import Button, { type OwnProps as ButtonProps } from './Button';
|
||||
import Portal from './Portal';
|
||||
|
||||
import './Modal.scss';
|
||||
@ -33,6 +33,7 @@ export type OwnProps = {
|
||||
isSlim?: boolean;
|
||||
hasCloseButton?: boolean;
|
||||
hasAbsoluteCloseButton?: boolean;
|
||||
absoluteCloseButtonColor?: ButtonProps['color'];
|
||||
noBackdrop?: boolean;
|
||||
noBackdropClose?: boolean;
|
||||
children: React.ReactNode;
|
||||
@ -57,6 +58,7 @@ const Modal: FC<OwnProps> = ({
|
||||
header,
|
||||
hasCloseButton,
|
||||
hasAbsoluteCloseButton,
|
||||
absoluteCloseButtonColor = 'translucent',
|
||||
noBackdrop,
|
||||
noBackdropClose,
|
||||
children,
|
||||
@ -137,7 +139,7 @@ const Modal: FC<OwnProps> = ({
|
||||
<Button
|
||||
className={buildClassName(hasAbsoluteCloseButton && 'modal-absolute-close-button')}
|
||||
round
|
||||
color="translucent"
|
||||
color={absoluteCloseButtonColor}
|
||||
size="smaller"
|
||||
ariaLabel={lang('Close')}
|
||||
onClick={onClose}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { ApiUserStarGift } from '../../../api/types';
|
||||
import type { ApiMessageActionStarGift, ApiUserStarGift } from '../../../api/types';
|
||||
import type { ActionReturnType } from '../../types';
|
||||
|
||||
import { getCurrentTabId } from '../../../util/establishMultitabRole';
|
||||
@ -242,8 +242,14 @@ addActionHandler('openGiftInfoModalFromMessage', (global, actions, payload): Act
|
||||
if (!message || !message.content.action) return;
|
||||
|
||||
const action = message.content.action;
|
||||
if (action.type === 'starGiftUnique') {
|
||||
actions.openGiftInfoModal({ gift: action.starGift?.gift!, tabId });
|
||||
return;
|
||||
}
|
||||
|
||||
if (action.type !== 'starGift') return;
|
||||
const starGift = action.starGift!;
|
||||
|
||||
const starGift = action.starGift! as ApiMessageActionStarGift;
|
||||
|
||||
const giftReceiverId = message.isOutgoing ? message.chatId : global.currentUserId!;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user