Star Gifts: Support upgrade option (#5475)
This commit is contained in:
parent
8bac803dea
commit
aecd1d216f
@ -2,10 +2,10 @@ src/lib/rlottie/rlottie-wasm.js
|
||||
src/lib/video-preview/polyfill
|
||||
src/lib/fasttextweb/fasttext-wasm.js
|
||||
|
||||
src/lib/gramjs/tl/types-generator/template.js
|
||||
src/lib/gramjs/tl/types-generator/template.ts
|
||||
src/lib/gramjs/tl/api.d.ts
|
||||
src/lib/gramjs/tl/apiTl.ts
|
||||
src/lib/gramjs/tl/schemaTl.js
|
||||
src/lib/gramjs/tl/schemaTl.ts
|
||||
|
||||
src/lib/lovely-chart
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ import { buildStickerFromDocument } from './symbols';
|
||||
export function buildApiStarGift(starGift: GramJs.TypeStarGift): ApiStarGift {
|
||||
if (starGift instanceof GramJs.StarGiftUnique) {
|
||||
const {
|
||||
id, num, ownerId, ownerName, title, attributes, availabilityIssued, availabilityTotal,
|
||||
id, num, ownerId, ownerName, title, attributes, availabilityIssued, availabilityTotal, slug,
|
||||
} = starGift;
|
||||
|
||||
return {
|
||||
@ -28,6 +28,7 @@ export function buildApiStarGift(starGift: GramJs.TypeStarGift): ApiStarGift {
|
||||
title,
|
||||
totalCount: availabilityTotal,
|
||||
issuedCount: availabilityIssued,
|
||||
slug,
|
||||
};
|
||||
}
|
||||
|
||||
@ -125,7 +126,7 @@ export function buildApiStarGiftAttribute(attribute: GramJs.TypeStarGiftAttribut
|
||||
|
||||
export function buildApiUserStarGift(userStarGift: GramJs.UserStarGift): ApiUserStarGift {
|
||||
const {
|
||||
gift, date, convertStars, fromId, message, msgId, nameHidden, unsaved,
|
||||
gift, date, convertStars, fromId, message, msgId, nameHidden, unsaved, upgradeStars, transferStars, canUpgrade,
|
||||
} = userStarGift;
|
||||
|
||||
return {
|
||||
@ -137,5 +138,8 @@ export function buildApiUserStarGift(userStarGift: GramJs.UserStarGift): ApiUser
|
||||
messageId: msgId,
|
||||
isNameHidden: nameHidden,
|
||||
isUnsaved: unsaved,
|
||||
canUpgrade,
|
||||
alreadyPaidUpgradeStars: upgradeStars?.toJSNumber(),
|
||||
transferStars: transferStars?.toJSNumber(),
|
||||
};
|
||||
}
|
||||
|
||||
@ -26,6 +26,8 @@ import type {
|
||||
ApiReplyInfo,
|
||||
ApiReplyKeyboard,
|
||||
ApiSponsoredMessage,
|
||||
ApiStarGiftRegular,
|
||||
ApiStarGiftUnique,
|
||||
ApiSticker,
|
||||
ApiStory,
|
||||
ApiStorySkipped,
|
||||
@ -369,7 +371,7 @@ export function buildApiFactCheck(factCheck: GramJs.FactCheck): ApiFactCheck {
|
||||
|
||||
function buildApiMessageActionStarGift(action: GramJs.MessageActionStarGift) : ApiMessageActionStarGift {
|
||||
const {
|
||||
nameHidden, saved, converted, gift, message, convertStars, canUpgrade, upgraded, upgradeMsgId,
|
||||
nameHidden, saved, converted, gift, message, convertStars, canUpgrade, upgraded, upgradeMsgId, upgradeStars,
|
||||
} = action;
|
||||
|
||||
return {
|
||||
@ -377,12 +379,13 @@ function buildApiMessageActionStarGift(action: GramJs.MessageActionStarGift) : A
|
||||
isNameHidden: Boolean(nameHidden),
|
||||
isSaved: Boolean(saved),
|
||||
isConverted: converted,
|
||||
gift: buildApiStarGift(gift),
|
||||
gift: buildApiStarGift(gift) as ApiStarGiftRegular,
|
||||
message: message && buildApiFormattedText(message),
|
||||
starsToConvert: convertStars?.toJSNumber(),
|
||||
canUpgrade,
|
||||
isUpgraded: upgraded,
|
||||
upgradeMsgId,
|
||||
alreadyPaidUpgradeStars: upgradeStars?.toJSNumber(),
|
||||
};
|
||||
}
|
||||
|
||||
@ -395,7 +398,7 @@ function buildApiMessageActionStarGiftUnique(
|
||||
|
||||
return {
|
||||
type: 'starGiftUnique',
|
||||
gift: buildApiStarGift(gift),
|
||||
gift: buildApiStarGift(gift) as ApiStarGiftUnique,
|
||||
canExportAt,
|
||||
isRefunded: refunded,
|
||||
isSaved: saved,
|
||||
@ -757,7 +760,7 @@ function buildAction(
|
||||
text = action.upgrade ? 'Notification.StarsGift.UpgradeYou' : 'ActionUniqueGiftTransferOutbound';
|
||||
} else {
|
||||
text = action.upgrade ? 'Notification.StarsGift.Upgrade' : 'ActionUniqueGiftTransferInbound';
|
||||
translationValues.push('%action_origin%');
|
||||
translationValues.push('%action_origin_chat%');
|
||||
}
|
||||
|
||||
starGift = buildApiMessageActionStarGiftUnique(action);
|
||||
|
||||
@ -643,13 +643,14 @@ export function buildInputInvoice(invoice: ApiRequestInputInvoice) {
|
||||
|
||||
case 'stargift': {
|
||||
const {
|
||||
user, shouldHideName, giftId, message,
|
||||
user, shouldHideName, giftId, message, shouldUpgrade,
|
||||
} = invoice;
|
||||
return new GramJs.InputInvoiceStarGift({
|
||||
userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser,
|
||||
hideName: shouldHideName || undefined,
|
||||
giftId: BigInt(giftId),
|
||||
message: message && buildInputTextWithEntities(message),
|
||||
includeUpgrade: shouldUpgrade,
|
||||
});
|
||||
}
|
||||
|
||||
@ -673,6 +674,13 @@ export function buildInputInvoice(invoice: ApiRequestInputInvoice) {
|
||||
});
|
||||
}
|
||||
|
||||
case 'stargiftUpgrade': {
|
||||
return new GramJs.InputInvoiceStarGiftUpgrade({
|
||||
msgId: invoice.messageId,
|
||||
keepOriginalDetails: invoice.shouldKeepOriginalDetails,
|
||||
});
|
||||
}
|
||||
|
||||
case 'giveaway':
|
||||
default: {
|
||||
const purpose = buildInputStorePaymentPurpose(invoice.purpose);
|
||||
|
||||
@ -14,6 +14,7 @@ import type {
|
||||
import { DEBUG } from '../../../config';
|
||||
import {
|
||||
buildApiStarGift,
|
||||
buildApiStarGiftAttribute,
|
||||
buildApiUserStarGift,
|
||||
} from '../apiBuilders/gifts';
|
||||
import {
|
||||
@ -646,9 +647,40 @@ export async function fetchUniqueStarGift({ slug }: {
|
||||
}) {
|
||||
const result = await invokeRequest(new GramJs.payments.GetUniqueStarGift({ slug }));
|
||||
|
||||
if (!result) return undefined;
|
||||
|
||||
const gift = buildApiStarGift(result.gift);
|
||||
if (gift.type !== 'starGiftUnique') return undefined;
|
||||
return gift;
|
||||
}
|
||||
|
||||
export async function fetchStarGiftUpgradePreview({
|
||||
giftId,
|
||||
}: {
|
||||
giftId: string;
|
||||
}) {
|
||||
const result = await invokeRequest(new GramJs.payments.GetStarGiftUpgradePreview({
|
||||
giftId: BigInt(giftId),
|
||||
}));
|
||||
|
||||
if (!result) {
|
||||
return undefined;
|
||||
}
|
||||
const gift = buildApiStarGift(result.gift);
|
||||
return gift.type === 'starGiftUnique' ? gift : undefined;
|
||||
|
||||
return result.sampleAttributes.map(buildApiStarGiftAttribute).filter(Boolean);
|
||||
}
|
||||
|
||||
export function upgradeGift({
|
||||
messageId,
|
||||
shouldKeepOriginalDetails,
|
||||
}: {
|
||||
messageId: number;
|
||||
shouldKeepOriginalDetails?: true;
|
||||
}) {
|
||||
return invokeRequest(new GramJs.payments.UpgradeStarGift({
|
||||
msgId: messageId,
|
||||
keepOriginalDetails: shouldKeepOriginalDetails,
|
||||
}), {
|
||||
shouldReturnTrue: true,
|
||||
});
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import type {
|
||||
ApiInputStorePaymentPurpose,
|
||||
ApiLabeledPrice,
|
||||
ApiPremiumGiftCodeOption,
|
||||
ApiStarGift,
|
||||
ApiStarGiftRegular,
|
||||
ApiStarGiftUnique,
|
||||
} from './payments';
|
||||
import type {
|
||||
@ -265,6 +265,7 @@ export type ApiInputInvoiceStarGift = {
|
||||
userId: string;
|
||||
giftId: string;
|
||||
message?: ApiFormattedText;
|
||||
shouldUpgrade?: true;
|
||||
};
|
||||
|
||||
export type ApiInputInvoiceStarsGiveaway = {
|
||||
@ -287,8 +288,14 @@ export type ApiInputInvoiceChatInviteSubscription = {
|
||||
hash: string;
|
||||
};
|
||||
|
||||
export type ApiInputInvoiceStarGiftUpgrade = {
|
||||
type: 'stargiftUpgrade';
|
||||
messageId: number;
|
||||
shouldKeepOriginalDetails?: true;
|
||||
};
|
||||
|
||||
export type ApiInputInvoice = ApiInputInvoiceMessage | ApiInputInvoiceSlug | ApiInputInvoiceGiveaway
|
||||
| ApiInputInvoiceGiftCode | ApiInputInvoiceStars | ApiInputInvoiceStarsGift
|
||||
| ApiInputInvoiceGiftCode | ApiInputInvoiceStars | ApiInputInvoiceStarsGift | ApiInputInvoiceStarGiftUpgrade
|
||||
| ApiInputInvoiceStarsGiveaway | ApiInputInvoiceStarGift | ApiInputInvoiceChatInviteSubscription;
|
||||
|
||||
/* Used for Invoice request */
|
||||
@ -325,6 +332,7 @@ export type ApiRequestInputInvoiceStarGift = {
|
||||
user: ApiUser;
|
||||
giftId: string;
|
||||
message?: ApiFormattedText;
|
||||
shouldUpgrade?: true;
|
||||
};
|
||||
|
||||
export type ApiRequestInputInvoiceChatInviteSubscription = {
|
||||
@ -332,9 +340,15 @@ export type ApiRequestInputInvoiceChatInviteSubscription = {
|
||||
hash: string;
|
||||
};
|
||||
|
||||
export type ApiRequestInputInvoiceStarGiftUpgrade = {
|
||||
type: 'stargiftUpgrade';
|
||||
messageId: number;
|
||||
shouldKeepOriginalDetails?: true;
|
||||
};
|
||||
|
||||
export type ApiRequestInputInvoice = ApiRequestInputInvoiceMessage | ApiRequestInputInvoiceSlug
|
||||
| ApiRequestInputInvoiceGiveaway | ApiRequestInputInvoiceStars | ApiRequestInputInvoiceStarsGiveaway
|
||||
| ApiRequestInputInvoiceChatInviteSubscription | ApiRequestInputInvoiceStarGift;
|
||||
| ApiRequestInputInvoiceChatInviteSubscription | ApiRequestInputInvoiceStarGift | ApiRequestInputInvoiceStarGiftUpgrade;
|
||||
|
||||
export interface ApiInvoice {
|
||||
prices: ApiLabeledPrice[];
|
||||
@ -464,12 +478,13 @@ export interface ApiMessageActionStarGift {
|
||||
isNameHidden: boolean;
|
||||
isSaved: boolean;
|
||||
isConverted?: true;
|
||||
gift: ApiStarGift;
|
||||
gift: ApiStarGiftRegular;
|
||||
message?: ApiFormattedText;
|
||||
starsToConvert?: number;
|
||||
canUpgrade?: true;
|
||||
isUpgraded?: true;
|
||||
upgradeMsgId?: number;
|
||||
alreadyPaidUpgradeStars?: number;
|
||||
}
|
||||
|
||||
export interface ApiMessageActionStarGiftUnique {
|
||||
@ -478,7 +493,7 @@ export interface ApiMessageActionStarGiftUnique {
|
||||
isTransferred?: true;
|
||||
isSaved?: true;
|
||||
isRefunded?: true;
|
||||
gift: ApiStarGift;
|
||||
gift: ApiStarGiftUnique;
|
||||
canExportAt?: number;
|
||||
transferStars?: number;
|
||||
}
|
||||
|
||||
@ -216,6 +216,7 @@ export interface ApiStarGiftUnique {
|
||||
issuedCount: number;
|
||||
totalCount: number;
|
||||
attributes: ApiStarGiftAttribute[];
|
||||
slug: string;
|
||||
}
|
||||
|
||||
export type ApiStarGift = ApiStarGiftRegular | ApiStarGiftUnique;
|
||||
@ -264,6 +265,9 @@ export interface ApiUserStarGift {
|
||||
message?: ApiFormattedText;
|
||||
messageId?: number;
|
||||
starsToConvert?: number;
|
||||
canUpgrade?: true;
|
||||
alreadyPaidUpgradeStars?: number;
|
||||
transferStars?: number;
|
||||
isConverted?: boolean; // Local field, used for Action Message
|
||||
upgradeMsgId?: number; // Local field, used for Action Message
|
||||
}
|
||||
|
||||
1
src/assets/font-icons/auction.svg
Normal file
1
src/assets/font-icons/auction.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path d="M5.274 24.224c-1.958 0-3.575 1.616-3.575 3.575v1.1a1.375 1.375 0 0 0 1.375 1.376A1.375 1.375 0 0 0 4.45 28.9v-1.101c0-.473.353-.825.825-.825h8.8c.472 0 .825.352.825.825v1.1a1.375 1.375 0 0 0 1.375 1.376 1.375 1.375 0 0 0 1.375-1.375v-1.101c0-1.959-1.617-3.575-3.575-3.575z" style="color:#000;fill:#000;stroke-width:1.375;stroke-linecap:round;-inkscape-stroke:none"/><path d="M19.28 1.727c-.778 0-1.557.292-2.141.877a3.03 3.03 0 0 0-.864 2.42L9.45 11.851a3.018 3.018 0 0 0-2.422.863c-1.168 1.168-1.168 3.109 0 4.277l5.448 5.445c1.168 1.169 3.107 1.169 4.275 0 .654-.653.94-1.549.863-2.416l.889-.888 6.807 6.805a3.59 3.59 0 0 0 5.052 0c1.385-1.385 1.385-3.67 0-5.055l-6.802-6.807.886-.887a3.02 3.02 0 0 0 2.416-.863c1.169-1.168 1.17-3.109.002-4.277l-5.445-5.447a3 3 0 0 0-2.139-.875m0 2.726q.098 0 .193.094l5.447 5.445c.124.125.123.264-.002.389-.123.123-.26.123-.383.004l-.006-.004-5.445-5.445v-.002c-.123-.125-.124-.261 0-.385.062-.062.13-.095.195-.096m-1.555 3.012 4.277 4.28-.389.386v.002l-.972.97-4.086 4.085.002.002-.387.386-4.28-4.277zm-8.559 7.1q.1-.002.195.093l5.448 5.446v.002c.123.124.122.264-.002.388-.125.125-.265.125-.39 0l-5.444-5.447c-.125-.125-.125-.262 0-.387q.093-.094.193-.096m12.447 1.456 6.805 6.807a.8.8 0 0 1 0 1.164.804.804 0 0 1-1.166 0l-6.805-6.805Z" style="color:#000;fill:#000;stroke-width:1.375;-inkscape-stroke:none"/><path d="M1.973 27.522a1.375 1.375 0 0 0-1.375 1.375 1.375 1.375 0 0 0 1.375 1.375h15.402a1.375 1.375 0 0 0 1.375-1.375 1.375 1.375 0 0 0-1.375-1.375z" style="color:#000;fill:#000;stroke-width:1.375;stroke-linecap:round;-inkscape-stroke:none"/></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
1
src/assets/font-icons/diamond.svg
Normal file
1
src/assets/font-icons/diamond.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path d="M8.332 2.201a3.58 3.58 0 0 0-2.908 1.496L1.525 9.152a3.59 3.59 0 0 0 .07 4.25L13.16 28.525c1.41 1.844 4.27 1.844 5.68 0l11.564-15.123c.95-1.243.98-2.976.07-4.25l-3.898-5.455a3.58 3.58 0 0 0-2.908-1.496H15.25Zm0 2.75h3.383L9.754 9.525H4.639l3.021-4.23a.82.82 0 0 1 .672-.344m6.918 0h1.5c.334 0 .626.192.758.498l1.746 4.076h-6.508l1.746-4.076a.815.815 0 0 1 .758-.498m5.035 0h3.383a.82.82 0 0 1 .672.344l3.021 4.23h-5.115Zm-16.09 7.324h5.172q.017.074.037.147l3.186 10.832zm8.034 0h7.542L16 25.104Zm10.404 0h5.172L19.41 23.254l3.186-10.832q.02-.074.037-.147" style="color:#000;fill:#000;-inkscape-stroke:none"/></svg>
|
||||
|
After Width: | Height: | Size: 698 B |
1
src/assets/font-icons/trade.svg
Normal file
1
src/assets/font-icons/trade.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path d="M21.357 3.584q-.472 0-1.037.002h-3.24a1.35 1.35 0 0 0-1.35 1.35 1.35 1.35 0 0 0 1.35 1.35h3.24c1.512 0 2.08.07 2.233.148.254.13.46.335.59.59.077.152.146.72.146 2.232v1.058l-.934-.933a1.35 1.35 0 0 0-1.91 0 1.35 1.35 0 0 0 0 1.91l3.24 3.24a1.4 1.4 0 0 0 .256.198 1 1 0 0 0 .12.056 1.4 1.4 0 0 0 .183.076 1 1 0 0 0 .131.03 1.4 1.4 0 0 0 .205.027l.06.008.06-.008a1.4 1.4 0 0 0 .218-.03 1 1 0 0 0 .111-.025 1.4 1.4 0 0 0 .215-.09l.088-.043a1.4 1.4 0 0 0 .22-.168l.042-.03.008-.009 3.232-3.232a1.35 1.35 0 0 0 0-1.91 1.35 1.35 0 0 0-1.908 0l-.936.935v-1.06c0-1.512.07-2.457-.441-3.46a4.05 4.05 0 0 0-1.77-1.769c-.751-.383-1.471-.439-2.422-.443M7.209 16.555a1.35 1.35 0 0 0-.803.386l-3.24 3.24a1.35 1.35 0 0 0 0 1.909 1.35 1.35 0 0 0 1.908 0l.936-.936v1.063c0 1.512-.07 2.455.441 3.457a4.05 4.05 0 0 0 1.77 1.771c1.002.511 1.947.442 3.459.442h5.4a1.35 1.35 0 0 0 1.35-1.352 1.35 1.35 0 0 0-1.35-1.35h-5.4c-1.512 0-2.08-.068-2.233-.146a1.35 1.35 0 0 1-.59-.59c-.077-.153-.146-.72-.146-2.232v-1.06l.934.933a1.35 1.35 0 0 0 1.91 0 1.35 1.35 0 0 0 0-1.908l-3.24-3.24a1.35 1.35 0 0 0-1.106-.387" style="color:#000;fill:#000;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"/><path d="M4.26 2.506c-.784 0-1.521.38-1.977 1.017L.785 5.621a2.44 2.44 0 0 0 .047 2.887L5.43 14.52c.951 1.245 2.91 1.245 3.861 0l4.596-6.011v-.002a2.44 2.44 0 0 0 .047-2.887l-1.496-2.098a2.44 2.44 0 0 0-1.979-1.017Zm.14 2.701h5.92l1.301 1.82-4.262 5.575-4.261-5.575ZM21.541 16.547c-.783 0-1.523.378-1.979 1.015l-1.496 2.098a2.44 2.44 0 0 0 .047 2.889l4.596 6.012c.952 1.244 2.91 1.244 3.861 0l4.598-6.012a2.44 2.44 0 0 0 .047-2.889l-1.498-2.097a2.43 2.43 0 0 0-1.977-1.016zm.139 2.7h5.92l1.302 1.82-4.261 5.574-4.262-5.575z" style="color:#000;fill:#000;-inkscape-stroke:none"/></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@ -1377,15 +1377,18 @@
|
||||
"GiftInfoDescription_other" = "You can keep this gift in your Profile or convert it to **{amount}** Stars.";
|
||||
"GiftInfoDescriptionOut_one" = "{user} can keep this gift in profile or convert it to **{amount}** Star.";
|
||||
"GiftInfoDescriptionOut_other" = "{user} can keep this gift in profile or convert it to **{amount}** Stars.";
|
||||
"GiftInfoDescriptionUpgrade_one" = "You can keep this gift, upgrade it, or sell it for **{amount}** Star.";
|
||||
"GiftInfoDescriptionUpgrade_other" = "You can keep this gift, upgrade it, or sell it for **{amount}** Stars.";
|
||||
"GiftInfoDescriptionConverted_one" = "You converted this gift to **{amount}** Star.";
|
||||
"GiftInfoDescriptionConverted_other" = "You converted this gift to **{amount}** Stars.";
|
||||
"GiftInfoDescriptionOutConverted_one" = "{user} converted this gift to **{amount}** Star.";
|
||||
"GiftInfoDescriptionOutConverted_other" = "{user} converted this gift to **{amount}** Stars.";
|
||||
"GiftInfoDescriptionFreeUpgrade" = "Upgrade this gift for free to turn it to a unique collectible.";
|
||||
"GiftInfoDescriptionFreeUpgradeOut" = "{user} can turn this gift to a unique collectible";
|
||||
"GiftInfoDescriptionUpgraded" = "This gift was turned into a unique collectible.";
|
||||
"GiftInfoFrom" = "From";
|
||||
"GiftInfoDate" = "Date";
|
||||
"GiftInfoValue" = "Value";
|
||||
"GiftInfoMakeVisible" = "Display on my Page";
|
||||
"GiftInfoMakeInvisible" = "Hide from my Page";
|
||||
"GiftInfoConvert_one" = "Convert to {amount} Star";
|
||||
"GiftInfoConvert_other" = "Convert to {amount} Stars";
|
||||
"GiftInfoConvertTitle" = "Convert Gift to Stars";
|
||||
@ -1394,8 +1397,9 @@
|
||||
"GiftInfoConvertDescriptionPeriod_one" = "Conversion is available for the next **{count} days**.";
|
||||
"GiftInfoConvertDescriptionPeriod_other" = "Conversion is available for the next **{count} days**.";
|
||||
"GiftInfoSaved" = "This gift is visible on your profile. {link}";
|
||||
"GiftInfoSavedView" = "View >";
|
||||
"GiftInfoHidden" = "This gift is hidden. Only you can see it.";
|
||||
"GiftInfoSavedHide" = "Hide >";
|
||||
"GiftInfoSavedShow" = "Show >";
|
||||
"GiftInfoHidden" = "This gift is hidden. Only you can see it. {link}";
|
||||
"GiftInfoAvailability" = "Availability";
|
||||
"GiftInfoAvailabilityValue_one" = "{count} of {total} left";
|
||||
"GiftInfoAvailabilityValue_other" = "{count} of {total} left";
|
||||
@ -1418,6 +1422,25 @@
|
||||
"GiftInfoStatus" = "Status";
|
||||
"GiftInfoStatusNonUnique" = "Non-Unique";
|
||||
"GiftInfoViewUpgraded" = "View Upgraded Gift";
|
||||
"GiftInfoUpgradeBadge" = "upgrade";
|
||||
"GiftInfoUpgradeForFree" = "Upgrade For Free";
|
||||
"GiftUpgradeUniqueTitle" = "Unique";
|
||||
"GiftUpgradeUniqueDescription" = "Turn your gift into a unique collectible that you can transfer or auction.";
|
||||
"GiftUpgradeTransferableTitle" = "Transferable";
|
||||
"GiftUpgradeTransferableDescription" = "Send your upgraded gift to any of your friends on Telegram.";
|
||||
"GiftUpgradeTradeableTitle" = "Tradeable";
|
||||
"GiftUpgradeTradeableDescription" = "Sell or auction your gift on third-party NFT marketplaces.";
|
||||
"GiftUpgradeTitle" = "Make unique";
|
||||
"GiftUpgradeText" = "Let {peer} turn your gift into a unique collectible.";
|
||||
"GiftUpgradeTextOwn" = "Turn your gift into a unique collectible that you can transfer or auction.";
|
||||
"GiftUpgradeKeepDetails" = "Keep sender's name and comment";
|
||||
"GiftUpgradeButton" = "Upgrade {amount}";
|
||||
"GiftUpgradedTitle" = "This gift is now a collectible";
|
||||
"GiftUpgradedDescription" = "You have received a unique number, model, backdrop and symbol for your gift.";
|
||||
"GiftMakeUnique" = "Make unique for {stars}";
|
||||
"GiftMakeUniqueAcc" = "Make unique";
|
||||
"GiftMakeUniqueDescription" = "Enable this to let {user} turn your gift into a unique collectible. {link}";
|
||||
"GiftMakeUniqueLink" = "Learn More >";
|
||||
"StarsAmount" = "⭐️{amount}";
|
||||
"StarsAmountText_one" = "{amount} Star";
|
||||
"StarsAmountText_other" = "{amount} Stars";
|
||||
@ -1446,15 +1469,6 @@
|
||||
"GiftFrom" = "Gift from";
|
||||
"ReceivedGift" = "Received Gift";
|
||||
"SentGift" = "Sent Gift";
|
||||
"StarGiftInfoDescriptionInbound" = "You can keep this gift in your Profile or convert it to {count} Stars. {link}";
|
||||
"StarGiftInfoDescriptionOutgoing" = "{user} can keep this gift in Profile or convert it to {count} Stars. {link}";
|
||||
"StarGiftInfoLinkCaption" = "More About Stars >";
|
||||
"StarGiftDisplayOnMyPage" = "Display on on my page";
|
||||
"StarGiftConvertTo" = "Convert to";
|
||||
"StarGiftHideFromMyPage" = "Hide from my page";
|
||||
"StarGiftSenderPrivacyNote" = "Only you can see the sender's name and message.";
|
||||
"StarGiftAvailability" = "Availability";
|
||||
"StarGiftAvailabilityValue" = "{number} of {total} left";
|
||||
"StarsSubscribeText_one" = "Do you want to subscribe to **{chat}** for **{amount} Star** per month?";
|
||||
"StarsSubscribeText_other" = "Do you want to subscribe to **{chat}** for **{amount} Stars** per month?";
|
||||
"StarsSubscribeInfo" = "By subscribing you agree to the {link}";
|
||||
|
||||
@ -8,3 +8,4 @@ export { default as PaidReactionModal } from '../components/modals/paidReaction/
|
||||
export { default as GiftModal } from '../components/modals/gift/GiftModal';
|
||||
export { default as GiftRecipientPicker } from '../components/modals/gift/recipient/GiftRecipientPicker';
|
||||
export { default as GiftInfoModal } from '../components/modals/gift/info/GiftInfoModal';
|
||||
export { default as GiftUpgradeModal } from '../components/modals/gift/upgrade/GiftUpgradeModal';
|
||||
|
||||
@ -94,6 +94,7 @@ const AboutMonetizationModal: FC<OwnProps> = ({
|
||||
isOpen={isOpen}
|
||||
listItemData={modalData.listItemData}
|
||||
headerIconName="cash-circle"
|
||||
withSeparator
|
||||
header={modalData.header}
|
||||
footer={modalData.footer}
|
||||
buttonText={oldLang('RevenueSharingAdsUnderstood')}
|
||||
|
||||
@ -20,7 +20,7 @@ function AnimatedIconFromSticker(props: OwnProps) {
|
||||
} = props;
|
||||
|
||||
const thumbDataUri = sticker?.thumbnail?.dataUri;
|
||||
const localMediaHash = sticker && `sticker${sticker.id}`;
|
||||
const localMediaHash = sticker && getStickerMediaHash(sticker, 'full');
|
||||
const previewBlobUrl = useMedia(
|
||||
sticker ? getStickerMediaHash(sticker, 'preview') : undefined,
|
||||
noLoad && !forcePreview,
|
||||
|
||||
@ -16,6 +16,6 @@
|
||||
height: 100%;
|
||||
|
||||
&:global(.closing) {
|
||||
transition-delay: 150ms;
|
||||
transition-delay: 50ms;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import type {
|
||||
ApiFormattedText,
|
||||
ApiStarGift,
|
||||
ApiStarGiftAttribute,
|
||||
ApiStarGiftAttributeBackdrop,
|
||||
ApiStarGiftAttributeModel,
|
||||
ApiStarGiftAttributeOriginalDetails,
|
||||
@ -40,10 +41,14 @@ export function getGiftMessage(gift: ApiStarGift): ApiFormattedText | undefined
|
||||
export function getGiftAttributes(gift: ApiStarGift): GiftAttributes | undefined {
|
||||
if (gift.type !== 'starGiftUnique') return undefined;
|
||||
|
||||
const model = gift.attributes.find((attr): attr is ApiStarGiftAttributeModel => attr.type === 'model');
|
||||
const backdrop = gift.attributes.find((attr): attr is ApiStarGiftAttributeBackdrop => attr.type === 'backdrop');
|
||||
const pattern = gift.attributes.find((attr): attr is ApiStarGiftAttributePattern => attr.type === 'pattern');
|
||||
const originalDetails = gift.attributes.find((attr): attr is ApiStarGiftAttributeOriginalDetails => (
|
||||
return getGiftAttributesFromList(gift.attributes);
|
||||
}
|
||||
|
||||
export function getGiftAttributesFromList(attributes: ApiStarGiftAttribute[]) {
|
||||
const model = attributes.find((attr): attr is ApiStarGiftAttributeModel => attr.type === 'model');
|
||||
const backdrop = attributes.find((attr): attr is ApiStarGiftAttributeBackdrop => attr.type === 'backdrop');
|
||||
const pattern = attributes.find((attr): attr is ApiStarGiftAttributePattern => attr.type === 'pattern');
|
||||
const originalDetails = attributes.find((attr): attr is ApiStarGiftAttributeOriginalDetails => (
|
||||
attr.type === 'originalDetails'
|
||||
));
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ export function renderActionMessageText(
|
||||
}
|
||||
if (translationKey.startsWith('Notification.StarsGift.Upgrade')) {
|
||||
unprocessed = unprocessed
|
||||
.replace('%@', '%action_origin%');
|
||||
.replace('%@', '%action_origin_chat%');
|
||||
}
|
||||
if (translationKey.startsWith('ActionUniqueGiftTransfer')) {
|
||||
unprocessed = unprocessed
|
||||
@ -138,6 +138,18 @@ export function renderActionMessageText(
|
||||
unprocessed = processed.pop() as string;
|
||||
content.push(...processed);
|
||||
|
||||
processed = processPlaceholder(
|
||||
unprocessed,
|
||||
'%action_origin_chat%',
|
||||
actionOriginChat ? (
|
||||
renderChatContent(oldLang, actionOriginChat, noLinks) || NBSP
|
||||
) : 'Chat',
|
||||
'',
|
||||
);
|
||||
|
||||
unprocessed = processed.pop() as string;
|
||||
content.push(...processed);
|
||||
|
||||
if (unprocessed.includes('%payment_amount%')) {
|
||||
processed = processPlaceholder(
|
||||
unprocessed,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import React, {
|
||||
memo, useEffect, useRef, useSignal, useState,
|
||||
memo, useEffect, useMemo, useRef, useSignal, useState,
|
||||
} from '../../../lib/teact/teact';
|
||||
|
||||
import type { ApiSticker } from '../../../api/types';
|
||||
@ -22,6 +22,7 @@ type OwnProps = {
|
||||
patternColor?: string;
|
||||
patternIcon?: ApiSticker;
|
||||
className?: string;
|
||||
clearBottomSector?: boolean;
|
||||
};
|
||||
|
||||
const RINGS = 3;
|
||||
@ -33,38 +34,11 @@ const BASE_ICON_SIZE = 20;
|
||||
|
||||
const MIN_SIZE = 250;
|
||||
|
||||
const PATTERN_POSITIONS = (() => {
|
||||
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 + 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 sizeFactor = 1.4 - ringProgress * Math.random();
|
||||
|
||||
coordinates.push({
|
||||
x, y, sizeFactor,
|
||||
});
|
||||
}
|
||||
}
|
||||
return coordinates;
|
||||
})();
|
||||
|
||||
const RadialPatternBackground = ({
|
||||
backgroundColors,
|
||||
patternColor,
|
||||
patternIcon,
|
||||
clearBottomSector,
|
||||
className,
|
||||
}: OwnProps) => {
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
@ -86,6 +60,39 @@ const RadialPatternBackground = ({
|
||||
preloadImage(previewUrl).then(setEmojiImage);
|
||||
}, [previewUrl]);
|
||||
|
||||
const patternPositions = useMemo(() => {
|
||||
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 + angleShift;
|
||||
|
||||
if (clearBottomSector && angle > Math.PI * 0.45 && angle < Math.PI * 0.55) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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 sizeFactor = 1.4 - ringProgress * Math.random();
|
||||
|
||||
coordinates.push({
|
||||
x, y, sizeFactor,
|
||||
});
|
||||
}
|
||||
}
|
||||
return coordinates;
|
||||
}, [clearBottomSector]);
|
||||
|
||||
useResizeObserver(containerRef, (entry) => {
|
||||
setContainerSize({
|
||||
width: entry.contentRect.width,
|
||||
@ -111,7 +118,7 @@ const RadialPatternBackground = ({
|
||||
if (!width || !height) return;
|
||||
|
||||
ctx.save();
|
||||
PATTERN_POSITIONS.forEach(({
|
||||
patternPositions.forEach(({
|
||||
x, y, sizeFactor,
|
||||
}) => {
|
||||
const centerShift = (width - Math.max(width, MIN_SIZE * dpr)) / 2; // Shift coords if canvas is smaller than `MIN_SIZE`
|
||||
|
||||
@ -4,7 +4,7 @@ import React, {
|
||||
import { getGlobal } from '../../../../global';
|
||||
|
||||
import type {
|
||||
ApiChat, ApiDraft, ApiMessage, ApiPeer, ApiTopic, ApiTypingStatus, ApiUser,
|
||||
ApiChat, ApiDraft, ApiMessage, ApiPeer, ApiTopic, ApiTypingStatus,
|
||||
StatefulMediaContent,
|
||||
} from '../../../../api/types';
|
||||
import type { ObserveFn } from '../../../../hooks/useIntersectionObserver';
|
||||
@ -21,10 +21,9 @@ import {
|
||||
getMessageSticker,
|
||||
getMessageVideo,
|
||||
isActionMessage,
|
||||
isChatChannel,
|
||||
isChatGroup,
|
||||
isExpiredMessage,
|
||||
} from '../../../../global/helpers';
|
||||
import { isApiPeerChat } from '../../../../global/helpers/peers';
|
||||
import { getMessageReplyInfo } from '../../../../global/helpers/replies';
|
||||
import buildClassName from '../../../../util/buildClassName';
|
||||
import { renderActionMessageText } from '../../../common/helpers/renderActionMessageText';
|
||||
@ -155,15 +154,13 @@ export default function useChatListEntry({
|
||||
}
|
||||
|
||||
if (isAction) {
|
||||
const isChat = chat && (isChatChannel(chat) || isChatGroup(chat));
|
||||
|
||||
return (
|
||||
<p className="last-message shared-canvas-container" dir={oldLang.isRtl ? 'auto' : 'ltr'}>
|
||||
{renderActionMessageText(
|
||||
oldLang,
|
||||
lastMessage,
|
||||
!isChat ? lastMessageSender as ApiUser : undefined,
|
||||
isChat ? chat : undefined,
|
||||
lastMessageSender && !isApiPeerChat(lastMessageSender) ? lastMessageSender : undefined,
|
||||
lastMessageSender && isApiPeerChat(lastMessageSender) ? lastMessageSender : chat,
|
||||
actionTargetUsers,
|
||||
actionTargetMessage,
|
||||
actionTargetChatId,
|
||||
|
||||
@ -128,7 +128,6 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
|
||||
getReceipt,
|
||||
openGiftInfoModalFromMessage,
|
||||
openPrizeStarsTransactionFromGiveaway,
|
||||
showNotification,
|
||||
} = getActions();
|
||||
|
||||
const oldLang = useOldLang();
|
||||
@ -240,16 +239,6 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
|
||||
const handleStarGiftClick = () => {
|
||||
const starGift = message.content.action?.starGift;
|
||||
if (!starGift) return;
|
||||
if (starGift.type === 'starGift' && starGift.canUpgrade && !message.isOutgoing) {
|
||||
showNotification({
|
||||
title: {
|
||||
key: 'ActionUnsupportedTitle',
|
||||
},
|
||||
message: {
|
||||
key: 'ActionUnsupportedDescription',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
openGiftInfoModalFromMessage({
|
||||
chatId: message.chatId,
|
||||
@ -534,7 +523,8 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
|
||||
|
||||
<div className="action-message-button">
|
||||
<Sparkles preset="button" />
|
||||
{starGift.canUpgrade && !message.isOutgoing ? lang('ActionStarGiftUnpack') : oldLang('ActionGiftPremiumView')}
|
||||
{starGift.alreadyPaidUpgradeStars && (!message.isOutgoing || targetUsers?.[0]?.isSelf)
|
||||
? lang('ActionStarGiftUnpack') : oldLang('ActionGiftPremiumView')}
|
||||
</div>
|
||||
{starGift.gift.availabilityTotal && (
|
||||
<GiftRibbon
|
||||
@ -558,11 +548,14 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const backgroundColors = [backdrop.centerColor, backdrop.edgeColor];
|
||||
|
||||
const adaptedPatternColor = `${backdrop.patternColor.slice(0, 7)}55`;
|
||||
|
||||
return (
|
||||
<span
|
||||
className="action-message-gift action-message-centered action-message-unique"
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
style={`--pattern-color: ${adaptedPatternColor}`}
|
||||
onClick={handleStarGiftClick}
|
||||
>
|
||||
<div className="action-message-unique-background-wrapper">
|
||||
@ -571,6 +564,7 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
|
||||
backgroundColors={backgroundColors}
|
||||
patternColor={backdrop.patternColor}
|
||||
patternIcon={pattern.sticker}
|
||||
clearBottomSector
|
||||
/>
|
||||
</div>
|
||||
<AnimatedIconFromSticker
|
||||
@ -610,7 +604,7 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
|
||||
{oldLang('Gift2UniqueView')}
|
||||
</div>
|
||||
<GiftRibbon
|
||||
color={backdrop.patternColor || 'blue'}
|
||||
color={adaptedPatternColor}
|
||||
text={oldLang('ActionStarGift')}
|
||||
/>
|
||||
</span>
|
||||
|
||||
@ -147,8 +147,10 @@ const WebPage: FC<OwnProps & StateProps> = ({
|
||||
const isStory = type === WEBPAGE_STORY_TYPE;
|
||||
const isGift = type === WEBPAGE_GIFT_TYPE;
|
||||
const isExpiredStory = story && 'isDeleted' in story;
|
||||
|
||||
const quickButtonLangKey = !inPreview && !isExpiredStory ? getWebpageButtonLangKey(type) : undefined;
|
||||
const quickButtonTitle = quickButtonLangKey && lang(quickButtonLangKey);
|
||||
|
||||
const truncatedDescription = trimText(description, MAX_TEXT_LENGTH);
|
||||
const isArticle = Boolean(truncatedDescription || title || siteName);
|
||||
let isSquarePhoto = Boolean(stickers);
|
||||
@ -185,6 +187,7 @@ const WebPage: FC<OwnProps & StateProps> = ({
|
||||
size="tiny"
|
||||
color="translucent"
|
||||
isRectangular
|
||||
noForcedUpperCase
|
||||
onClick={handleOpenTelegramLink}
|
||||
>
|
||||
{caption}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import type { RegularLangKey } from '../../../../types/language';
|
||||
|
||||
// https://github.com/telegramdesktop/tdesktop/blob/3da787791f6d227f69b32bf4003bc6071d05e2ac/Telegram/SourceFiles/history/view/history_view_view_button.cpp#L51
|
||||
export function getWebpageButtonLangKey(type?: string) {
|
||||
export function getWebpageButtonLangKey(type?: string): RegularLangKey | undefined {
|
||||
switch (type) {
|
||||
case 'telegram_channel_request':
|
||||
case 'telegram_megagroup_request':
|
||||
|
||||
@ -17,6 +17,7 @@ import EmojiStatusAccessModal from './emojiStatusAccess/EmojiStatusAccessModal.a
|
||||
import PremiumGiftModal from './gift/GiftModal.async';
|
||||
import GiftInfoModal from './gift/info/GiftInfoModal.async';
|
||||
import GiftRecipientPicker from './gift/recipient/GiftRecipientPicker.async';
|
||||
import GiftUpgradeModal from './gift/upgrade/GiftUpgradeModal.async';
|
||||
import GiftCodeModal from './giftcode/GiftCodeModal.async';
|
||||
import InviteViaLinkModal from './inviteViaLink/InviteViaLinkModal.async';
|
||||
import LocationAccessModal from './locationAccess/LocationAccessModal.async';
|
||||
@ -63,7 +64,8 @@ type ModalKey = keyof Pick<TabState,
|
||||
'suggestedStatusModal' |
|
||||
'emojiStatusAccessModal' |
|
||||
'locationAccessModal' |
|
||||
'aboutAdsModal'
|
||||
'aboutAdsModal' |
|
||||
'giftUpgradeModal'
|
||||
>;
|
||||
|
||||
type StateProps = {
|
||||
@ -106,6 +108,7 @@ const MODALS: ModalRegistry = {
|
||||
emojiStatusAccessModal: EmojiStatusAccessModal,
|
||||
locationAccessModal: LocationAccessModal,
|
||||
aboutAdsModal: AboutAdsModal,
|
||||
giftUpgradeModal: GiftUpgradeModal,
|
||||
};
|
||||
const MODAL_KEYS = Object.keys(MODALS) as ModalKey[];
|
||||
const MODAL_ENTRIES = Object.entries(MODALS) as Entries<ModalRegistry>;
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
|
||||
.moreButton {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
top: 0.375rem;
|
||||
right: 0.375rem;
|
||||
}
|
||||
|
||||
.secondary {
|
||||
|
||||
@ -133,6 +133,7 @@ const AboutAdsModal = ({ message, minLevelToRestrictAds }: OwnProps & StateProps
|
||||
isOpen={isOpen}
|
||||
listItemData={modalData?.listItemData}
|
||||
headerIconName="channel"
|
||||
withSeparator
|
||||
header={modalData?.header}
|
||||
footer={modalData?.footer}
|
||||
buttonText={oldLang('RevenueSharingAdsUnderstood')}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
.root :global(.modal-dialog) {
|
||||
width: 26.25rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.title, .description {
|
||||
|
||||
@ -15,10 +15,12 @@ export type TableAboutData = [IconName | undefined, TeactNode, TeactNode][];
|
||||
type OwnProps = {
|
||||
isOpen?: boolean;
|
||||
listItemData?: TableAboutData;
|
||||
headerIconName: IconName;
|
||||
headerIconName?: IconName;
|
||||
header?: TeactNode;
|
||||
footer?: TeactNode;
|
||||
buttonText?: string;
|
||||
hasBackdrop?: boolean;
|
||||
withSeparator?: boolean;
|
||||
onClose: NoneToVoidFunction;
|
||||
onButtonClick?: NoneToVoidFunction;
|
||||
};
|
||||
@ -30,6 +32,8 @@ const TableAboutModal = ({
|
||||
header,
|
||||
footer,
|
||||
buttonText,
|
||||
hasBackdrop,
|
||||
withSeparator,
|
||||
onClose,
|
||||
onButtonClick,
|
||||
}: OwnProps) => {
|
||||
@ -38,9 +42,11 @@ const TableAboutModal = ({
|
||||
isOpen={isOpen}
|
||||
className={styles.root}
|
||||
contentClassName={styles.content}
|
||||
hasAbsoluteCloseButton
|
||||
absoluteCloseButtonColor={hasBackdrop ? 'translucent-white' : undefined}
|
||||
onClose={onClose}
|
||||
>
|
||||
<div className={styles.topIcon}><Icon name={headerIconName} /></div>
|
||||
{headerIconName && <div className={styles.topIcon}><Icon name={headerIconName} /></div>}
|
||||
{header}
|
||||
<div>
|
||||
{listItemData?.map(([icon, title, subtitle]) => {
|
||||
@ -56,7 +62,7 @@ const TableAboutModal = ({
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<Separator className={styles.separator} />
|
||||
{withSeparator && <Separator className={styles.separator} />}
|
||||
{footer}
|
||||
{buttonText && (
|
||||
<Button size="smaller" onClick={onButtonClick || onClose}>{buttonText}</Button>
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
@use "../../../styles/mixins";
|
||||
|
||||
.root {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding-top: 3.5rem;
|
||||
padding-inline: 0.75rem;
|
||||
|
||||
@include mixins.adapt-padding-to-scrollbar(0.75rem);
|
||||
}
|
||||
|
||||
.header {
|
||||
@ -47,9 +53,9 @@
|
||||
}
|
||||
|
||||
.optionsSection {
|
||||
padding: 1rem;
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 0.5rem;
|
||||
box-shadow: 0 1px 2px var(--color-default-shadow);
|
||||
padding-inline: 0.25rem;
|
||||
}
|
||||
|
||||
.checkboxTitle {
|
||||
@ -69,6 +75,9 @@
|
||||
overflow: hidden;
|
||||
flex: 0 0 auto;
|
||||
|
||||
border-bottom-right-radius: var(--border-radius-default);
|
||||
border-bottom-left-radius: var(--border-radius-default);
|
||||
|
||||
background-color: var(--theme-background-color);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
@ -112,18 +121,28 @@
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
padding-top: 0.5rem;
|
||||
margin-inline: -0.75rem; // Account for padding
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
background-color: var(--color-background-secondary);
|
||||
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.switcher {
|
||||
margin-bottom: 0 !important;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.switcherStarIcon {
|
||||
margin-inline: 0 !important;
|
||||
}
|
||||
|
||||
.description {
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.875rem;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.main-button {
|
||||
|
||||
@ -23,6 +23,7 @@ import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import PremiumProgress from '../../common/PremiumProgress';
|
||||
import ActionMessage from '../../middle/ActionMessage';
|
||||
import Button from '../../ui/Button';
|
||||
import Link from '../../ui/Link';
|
||||
import ListItem from '../../ui/ListItem';
|
||||
import Switcher from '../../ui/Switcher';
|
||||
import TextArea from '../../ui/TextArea';
|
||||
@ -61,12 +62,13 @@ function GiftComposer({
|
||||
currentUserId,
|
||||
isPaymentFormLoading,
|
||||
}: OwnProps & StateProps) {
|
||||
const { sendStarGift, openInvoice } = getActions();
|
||||
const { sendStarGift, openInvoice, openGiftUpgradeModal } = getActions();
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
const [giftMessage, setGiftMessage] = useState<string>('');
|
||||
const [shouldHideName, setShouldHideName] = useState<boolean>(false);
|
||||
const [shouldPayForUpgrade, setShouldPayForUpgrade] = useState<boolean>(false);
|
||||
|
||||
const customBackgroundValue = useCustomBackground(theme, customBackground);
|
||||
|
||||
@ -119,6 +121,7 @@ function GiftComposer({
|
||||
} : undefined,
|
||||
isNameHidden: shouldHideName,
|
||||
starsToConvert: gift.starsToConvert,
|
||||
canUpgrade: shouldPayForUpgrade || undefined,
|
||||
isSaved: false,
|
||||
gift,
|
||||
},
|
||||
@ -126,7 +129,7 @@ function GiftComposer({
|
||||
},
|
||||
},
|
||||
} satisfies ApiMessage;
|
||||
}, [currentUserId, gift, giftMessage, isStarGift, shouldHideName, userId]);
|
||||
}, [currentUserId, gift, giftMessage, isStarGift, shouldHideName, shouldPayForUpgrade, userId]);
|
||||
|
||||
const handleGiftMessageChange = useLastCallback((e: ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setGiftMessage(e.target.value);
|
||||
@ -136,6 +139,18 @@ function GiftComposer({
|
||||
setShouldHideName(!shouldHideName);
|
||||
});
|
||||
|
||||
const handleShouldPayForUpgradeChange = useLastCallback(() => {
|
||||
setShouldPayForUpgrade(!shouldPayForUpgrade);
|
||||
});
|
||||
|
||||
const handleOpenUpgradePreview = useLastCallback(() => {
|
||||
if (!isStarGift) return;
|
||||
openGiftUpgradeModal({
|
||||
giftId: gift.id,
|
||||
peerId: userId,
|
||||
});
|
||||
});
|
||||
|
||||
const handleMainButtonClick = useLastCallback(() => {
|
||||
if (isStarGift) {
|
||||
sendStarGift({
|
||||
@ -143,6 +158,7 @@ function GiftComposer({
|
||||
shouldHideName,
|
||||
gift,
|
||||
message: giftMessage ? { text: giftMessage } : undefined,
|
||||
shouldUpgrade: shouldPayForUpgrade,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -159,6 +175,8 @@ function GiftComposer({
|
||||
|
||||
function renderOptionsSection() {
|
||||
const symbolsLeft = captionLimit ? captionLimit - giftMessage.length : undefined;
|
||||
|
||||
const userFullName = getUserFullName(user)!;
|
||||
return (
|
||||
<div className={styles.optionsSection}>
|
||||
<TextArea
|
||||
@ -170,6 +188,31 @@ function GiftComposer({
|
||||
maxLengthIndicator={symbolsLeft && symbolsLeft < LIMIT_DISPLAY_THRESHOLD ? symbolsLeft.toString() : undefined}
|
||||
/>
|
||||
|
||||
{isStarGift && gift.upgradeStars && (
|
||||
<ListItem className={styles.switcher} narrow ripple onClick={handleShouldPayForUpgradeChange}>
|
||||
<span>
|
||||
{lang('GiftMakeUnique', {
|
||||
stars: formatStarsAsIcon(lang, gift.upgradeStars, { className: styles.switcherStarIcon }),
|
||||
}, { withNodes: true })}
|
||||
</span>
|
||||
<Switcher
|
||||
checked={shouldPayForUpgrade}
|
||||
onChange={handleShouldPayForUpgradeChange}
|
||||
label={lang('GiftMakeUniqueAcc')}
|
||||
/>
|
||||
</ListItem>
|
||||
)}
|
||||
{isStarGift && (
|
||||
<div className={styles.description}>
|
||||
{lang('GiftMakeUniqueDescription', {
|
||||
user: userFullName,
|
||||
link: <Link isPrimary onClick={handleOpenUpgradePreview}>{lang('GiftMakeUniqueLink')}</Link>,
|
||||
}, {
|
||||
withNodes: true,
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isStarGift && (
|
||||
<ListItem className={styles.switcher} narrow ripple onClick={handleShouldHideNameChange}>
|
||||
<span>{lang('GiftHideMyName')}</span>
|
||||
@ -180,27 +223,22 @@ function GiftComposer({
|
||||
/>
|
||||
</ListItem>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function renderFooter() {
|
||||
const userFullName = getUserFullName(user)!;
|
||||
|
||||
const amount = isStarGift
|
||||
? formatStarsAsIcon(lang, gift.stars, true)
|
||||
: formatCurrency(gift.amount, gift.currency);
|
||||
|
||||
return (
|
||||
<div className={styles.footer}>
|
||||
{isStarGift && (
|
||||
<div className={styles.description}>
|
||||
{lang('GiftHideNameDescription', { profile: userFullName, receiver: userFullName })}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<div className={styles.spacer} />
|
||||
function renderFooter() {
|
||||
const amount = isStarGift
|
||||
? formatStarsAsIcon(lang, gift.stars + (shouldPayForUpgrade ? gift.upgradeStars! : 0), { asFont: true })
|
||||
: formatCurrency(gift.amount, gift.currency);
|
||||
|
||||
return (
|
||||
<div className={styles.footer}>
|
||||
{isStarGift && gift.availabilityRemains && (
|
||||
<PremiumProgress
|
||||
isPrimary
|
||||
@ -236,7 +274,7 @@ function GiftComposer({
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={buildClassName(styles.root, 'no-scroll')}>
|
||||
<div className={buildClassName(styles.root, 'custom-scroll')}>
|
||||
<div
|
||||
className={buildClassName(styles.actionMessageView, 'MessageList')}
|
||||
// @ts-ignore -- FIXME: Find a way to disable interactions but keep a11y
|
||||
@ -253,6 +291,7 @@ function GiftComposer({
|
||||
<ActionMessage key={isStarGift ? gift.id : gift.months} message={localMessage} />
|
||||
</div>
|
||||
{renderOptionsSection()}
|
||||
<div className={styles.spacer} />
|
||||
{renderFooter()}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -47,7 +47,7 @@ export type GiftOption = ApiPremiumGiftCodeOption | ApiStarGiftRegular;
|
||||
type StateProps = {
|
||||
boostPerSentGift?: number;
|
||||
starGiftsById?: Record<string, ApiStarGiftRegular>;
|
||||
starGiftCategoriesByName: Record<StarGiftCategory, string[]>;
|
||||
starGiftIdsByCategory?: Record<StarGiftCategory, string[]>;
|
||||
starBalance?: ApiStarsAmount;
|
||||
user?: ApiUser;
|
||||
isSelf?: boolean;
|
||||
@ -59,7 +59,7 @@ const INTERSECTION_THROTTLE = 200;
|
||||
const PremiumGiftModal: FC<OwnProps & StateProps> = ({
|
||||
modal,
|
||||
starGiftsById,
|
||||
starGiftCategoriesByName,
|
||||
starGiftIdsByCategory,
|
||||
starBalance,
|
||||
user,
|
||||
isSelf,
|
||||
@ -206,7 +206,7 @@ const PremiumGiftModal: FC<OwnProps & StateProps> = ({
|
||||
function renderStarGifts() {
|
||||
return (
|
||||
<div className={styles.starGiftsContainer}>
|
||||
{starGiftsById && starGiftCategoriesByName[selectedCategory].map((giftId) => {
|
||||
{starGiftsById && starGiftIdsByCategory?.[selectedCategory].map((giftId) => {
|
||||
const gift = starGiftsById[giftId];
|
||||
return (
|
||||
<GiftItemStar
|
||||
@ -331,8 +331,7 @@ const PremiumGiftModal: FC<OwnProps & StateProps> = ({
|
||||
|
||||
export default memo(withGlobal<OwnProps>((global, { modal }): StateProps => {
|
||||
const {
|
||||
starGiftsById,
|
||||
starGiftCategoriesByName,
|
||||
starGifts,
|
||||
stars,
|
||||
currentUserId,
|
||||
} = global;
|
||||
@ -342,8 +341,8 @@ export default memo(withGlobal<OwnProps>((global, { modal }): StateProps => {
|
||||
|
||||
return {
|
||||
boostPerSentGift: global.appConfig?.boostsPerSentGift,
|
||||
starGiftsById,
|
||||
starGiftCategoriesByName,
|
||||
starGiftsById: starGifts?.byId,
|
||||
starGiftIdsByCategory: starGifts?.idsByCategory,
|
||||
starBalance: stars?.balance,
|
||||
user,
|
||||
isSelf,
|
||||
|
||||
@ -19,22 +19,22 @@ type OwnProps = {
|
||||
};
|
||||
|
||||
type StateProps = {
|
||||
starGiftCategoriesByName: Record<StarGiftCategory, string[]>;
|
||||
idsByCategory?: Record<StarGiftCategory, string[]>;
|
||||
};
|
||||
|
||||
const StarGiftCategoryList = ({
|
||||
starGiftCategoriesByName,
|
||||
idsByCategory,
|
||||
onCategoryChanged,
|
||||
}: StateProps & OwnProps) => {
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
const lang = useLang();
|
||||
const starCategories: number[] = useMemo(() => Object.keys(starGiftCategoriesByName)
|
||||
const starCategories: number[] | undefined = useMemo(() => idsByCategory && Object.keys(idsByCategory)
|
||||
.filter((category) => category !== 'all' && category !== 'limited')
|
||||
.map(Number)
|
||||
.sort((a, b) => a - b),
|
||||
[starGiftCategoriesByName]);
|
||||
[idsByCategory]);
|
||||
|
||||
const [selectedCategory, setSelectedCategory] = useState<StarGiftCategory>('all');
|
||||
|
||||
@ -80,17 +80,17 @@ const StarGiftCategoryList = ({
|
||||
{renderCategoryItem('all')}
|
||||
{renderCategoryItem('stock')}
|
||||
{renderCategoryItem('limited')}
|
||||
{starCategories.map(renderCategoryItem)}
|
||||
{starCategories?.map(renderCategoryItem)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(withGlobal(
|
||||
(global): StateProps => {
|
||||
const { starGiftCategoriesByName } = global;
|
||||
const { starGifts } = global;
|
||||
|
||||
return {
|
||||
starGiftCategoriesByName,
|
||||
idsByCategory: starGifts?.idsByCategory,
|
||||
};
|
||||
},
|
||||
)(StarGiftCategoryList));
|
||||
|
||||
55
src/components/modals/gift/UniqueGiftHeader.module.scss
Normal file
55
src/components/modals/gift/UniqueGiftHeader.module.scss
Normal file
@ -0,0 +1,55 @@
|
||||
.root {
|
||||
--_height: 15rem;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
height: var(--_height);
|
||||
margin-bottom: 0.5rem;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.radialPattern {
|
||||
position: absolute;
|
||||
inset: -5%;
|
||||
top: -5rem;
|
||||
height: calc(var(--height) * 1.05);
|
||||
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.sticker {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.transition {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: calc(var(--_height) + 1rem); // Account for top modal padding
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.transitionSlide {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.25rem;
|
||||
color: white;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
max-width: 75%;
|
||||
font-size: 0.875rem;
|
||||
transition: color 150ms ease-in;
|
||||
text-align: center;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.title, .subtitle {
|
||||
margin-bottom: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
80
src/components/modals/gift/UniqueGiftHeader.tsx
Normal file
80
src/components/modals/gift/UniqueGiftHeader.tsx
Normal file
@ -0,0 +1,80 @@
|
||||
import React, { memo, useMemo } from '../../../lib/teact/teact';
|
||||
|
||||
import type {
|
||||
ApiStarGiftAttributeBackdrop, ApiStarGiftAttributeModel, ApiStarGiftAttributePattern,
|
||||
} from '../../../api/types';
|
||||
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import buildStyle from '../../../util/buildStyle';
|
||||
|
||||
import { useTransitionActiveKey } from '../../../hooks/animations/useTransitionActiveKey';
|
||||
|
||||
import AnimatedIconFromSticker from '../../common/AnimatedIconFromSticker';
|
||||
import RadialPatternBackground from '../../common/profile/RadialPatternBackground';
|
||||
import Transition from '../../ui/Transition';
|
||||
|
||||
import styles from './UniqueGiftHeader.module.scss';
|
||||
|
||||
type OwnProps = {
|
||||
modelAttribute: ApiStarGiftAttributeModel;
|
||||
backdropAttribute: ApiStarGiftAttributeBackdrop;
|
||||
patternAttribute: ApiStarGiftAttributePattern;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const STICKER_SIZE = 120;
|
||||
|
||||
const UniqueGiftHeader = ({
|
||||
modelAttribute,
|
||||
backdropAttribute,
|
||||
patternAttribute,
|
||||
title,
|
||||
subtitle,
|
||||
className,
|
||||
}: OwnProps) => {
|
||||
const activeKey = useTransitionActiveKey([modelAttribute, backdropAttribute, patternAttribute]);
|
||||
const subtitleColor = backdropAttribute?.textColor;
|
||||
|
||||
const radialPatternBackdrop = useMemo(() => {
|
||||
const backdropColors = [backdropAttribute.centerColor, backdropAttribute.edgeColor];
|
||||
const patternColor = backdropAttribute.patternColor;
|
||||
|
||||
return (
|
||||
<RadialPatternBackground
|
||||
className={styles.radialPattern}
|
||||
backgroundColors={backdropColors}
|
||||
patternColor={patternColor}
|
||||
patternIcon={patternAttribute.sticker}
|
||||
/>
|
||||
);
|
||||
}, [backdropAttribute, patternAttribute]);
|
||||
|
||||
return (
|
||||
<div className={buildClassName(styles.root, className)}>
|
||||
<Transition
|
||||
className={styles.transition}
|
||||
slideClassName={styles.transitionSlide}
|
||||
activeKey={activeKey}
|
||||
direction={1}
|
||||
name="zoomBounceSemiFade"
|
||||
>
|
||||
{radialPatternBackdrop}
|
||||
<AnimatedIconFromSticker
|
||||
className={styles.sticker}
|
||||
sticker={modelAttribute.sticker}
|
||||
size={STICKER_SIZE}
|
||||
/>
|
||||
</Transition>
|
||||
{title && <h1 className={styles.title}>{title}</h1>}
|
||||
{subtitle && (
|
||||
<p className={styles.subtitle} style={buildStyle(subtitleColor && `color: ${subtitleColor}`)}>
|
||||
{subtitle}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(UniqueGiftHeader);
|
||||
@ -32,11 +32,16 @@
|
||||
color: var(--_color-description, var(--color-text));
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.footerDescription {
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
text-align: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.unknown {
|
||||
@ -82,3 +87,7 @@
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
.starAmountIcon {
|
||||
margin-inline-start: 0 !important;
|
||||
}
|
||||
|
||||
@ -59,6 +59,7 @@ const GiftInfoModal = ({
|
||||
convertGiftToStars,
|
||||
openChatWithInfo,
|
||||
focusMessage,
|
||||
openGiftUpgradeModal,
|
||||
} = getActions();
|
||||
|
||||
const [isConvertConfirmOpen, openConvertConfirm, closeConvertConfirm] = useFlag();
|
||||
@ -81,16 +82,16 @@ const GiftInfoModal = ({
|
||||
const giftSticker = gift && getStickerFromGift(gift);
|
||||
|
||||
const canFocusUpgrade = Boolean(userGift?.upgradeMsgId);
|
||||
const canUpdate = Boolean(userGift?.messageId) && !isSender && !canFocusUpgrade;
|
||||
const canUpdate = Boolean(userGift?.messageId) && targetUser?.id === currentUserId && !canFocusUpgrade;
|
||||
|
||||
const handleClose = useLastCallback(() => {
|
||||
closeGiftInfoModal();
|
||||
});
|
||||
|
||||
const handleFocusUpgraded = useLastCallback(() => {
|
||||
if (!userGift?.upgradeMsgId) return;
|
||||
const { upgradeMsgId, fromId } = userGift;
|
||||
focusMessage({ chatId: fromId!, messageId: upgradeMsgId! });
|
||||
if (!userGift?.upgradeMsgId || !targetUser) return;
|
||||
const { upgradeMsgId } = userGift;
|
||||
focusMessage({ chatId: targetUser.id, messageId: upgradeMsgId! });
|
||||
handleClose();
|
||||
});
|
||||
|
||||
@ -107,9 +108,9 @@ const GiftInfoModal = ({
|
||||
handleClose();
|
||||
});
|
||||
|
||||
const handleOpenProfile = useLastCallback(() => {
|
||||
openChatWithInfo({ id: currentUserId!, profileTab: 'gifts' });
|
||||
handleClose();
|
||||
const handleOpenUpgradeModal = useLastCallback(() => {
|
||||
if (!userGift) return;
|
||||
openGiftUpgradeModal({ giftId: userGift.gift.id, gift: userGift });
|
||||
});
|
||||
|
||||
const giftAttributes = useMemo(() => {
|
||||
@ -136,6 +137,30 @@ const GiftInfoModal = ({
|
||||
);
|
||||
}, [giftAttributes, isOpen]);
|
||||
|
||||
const renderFooterButton = useLastCallback(() => {
|
||||
if (canFocusUpgrade) {
|
||||
return (
|
||||
<Button size="smaller" onClick={handleFocusUpgraded}>
|
||||
{lang('GiftInfoViewUpgraded')}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
if (canUpdate && userGift?.alreadyPaidUpgradeStars && !userGift.upgradeMsgId) {
|
||||
return (
|
||||
<Button size="smaller" isShiny onClick={handleOpenUpgradeModal}>
|
||||
{lang('GiftInfoUpgradeForFree')}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Button size="smaller" onClick={handleClose}>
|
||||
{lang('OK')}
|
||||
</Button>
|
||||
);
|
||||
});
|
||||
|
||||
const modalData = useMemo(() => {
|
||||
if (!typeGift || !gift) {
|
||||
return undefined;
|
||||
@ -154,9 +179,14 @@ const GiftInfoModal = ({
|
||||
});
|
||||
}
|
||||
if (!userGift) return lang('GiftInfoSoldOutDescription');
|
||||
if (userGift.upgradeMsgId) return lang('GiftInfoDescriptionUpgraded');
|
||||
if (userGift.canUpgrade && userGift.alreadyPaidUpgradeStars) {
|
||||
return canUpdate
|
||||
? lang('GiftInfoDescriptionFreeUpgrade')
|
||||
: lang('GiftInfoDescriptionFreeUpgradeOut', { user: getUserFullName(targetUser)! });
|
||||
}
|
||||
if (!canUpdate && !isSender) return undefined;
|
||||
if (!starsToConvert || canConvertDifference < 0) return undefined;
|
||||
if (isConverted) {
|
||||
if (isConverted && starsToConvert) {
|
||||
return canUpdate
|
||||
? lang('GiftInfoDescriptionConverted', {
|
||||
amount: formatInteger(starsToConvert!),
|
||||
@ -175,13 +205,23 @@ const GiftInfoModal = ({
|
||||
});
|
||||
}
|
||||
|
||||
if (userGift.canUpgrade && canUpdate) {
|
||||
return lang('GiftInfoDescriptionUpgrade', {
|
||||
amount: formatInteger(starsToConvert!),
|
||||
}, {
|
||||
pluralValue: starsToConvert!,
|
||||
withNodes: true,
|
||||
withMarkdown: true,
|
||||
});
|
||||
}
|
||||
|
||||
return canUpdate
|
||||
? lang('GiftInfoDescription', {
|
||||
amount: starsToConvert,
|
||||
}, {
|
||||
withNodes: true,
|
||||
withMarkdown: true,
|
||||
pluralValue: starsToConvert,
|
||||
pluralValue: starsToConvert || 0,
|
||||
})
|
||||
: lang('GiftInfoDescriptionOut', {
|
||||
amount: starsToConvert,
|
||||
@ -189,7 +229,7 @@ const GiftInfoModal = ({
|
||||
}, {
|
||||
withNodes: true,
|
||||
withMarkdown: true,
|
||||
pluralValue: starsToConvert,
|
||||
pluralValue: starsToConvert || 0,
|
||||
});
|
||||
})();
|
||||
|
||||
@ -269,10 +309,12 @@ const GiftInfoModal = ({
|
||||
]);
|
||||
}
|
||||
|
||||
const starsValue = gift.stars + (userGift?.alreadyPaidUpgradeStars || 0);
|
||||
|
||||
tableData.push([
|
||||
lang('GiftInfoValue'),
|
||||
<div className={styles.giftValue}>
|
||||
{formatStarsAsIcon(lang, gift.stars)}
|
||||
{formatStarsAsIcon(lang, starsValue, { className: styles.starAmountIcon })}
|
||||
{canUpdate && canConvertDifference > 0 && Boolean(starsToConvert) && (
|
||||
<BadgeButton onClick={openConvertConfirm}>
|
||||
{lang('GiftInfoConvert', { amount: starsToConvert }, { pluralValue: starsToConvert })}
|
||||
@ -296,7 +338,10 @@ const GiftInfoModal = ({
|
||||
if (gift.upgradeStars) {
|
||||
tableData.push([
|
||||
lang('GiftInfoStatus'),
|
||||
lang('GiftInfoStatusNonUnique'),
|
||||
<div className={styles.giftValue}>
|
||||
{lang('GiftInfoStatusNonUnique')}
|
||||
{canUpdate && <BadgeButton onClick={handleOpenUpgradeModal}>{lang('GiftInfoUpgradeBadge')}</BadgeButton>}
|
||||
</div>,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -424,12 +469,11 @@ const GiftInfoModal = ({
|
||||
{canUpdate && (
|
||||
<div className={styles.footerDescription}>
|
||||
<div>
|
||||
{isUnsaved ? lang('GiftInfoHidden')
|
||||
: lang('GiftInfoSaved', {
|
||||
link: <Link isPrimary onClick={handleOpenProfile}>{lang('GiftInfoSavedView')}</Link>,
|
||||
}, {
|
||||
withNodes: true,
|
||||
})}
|
||||
{lang(isUnsaved ? 'GiftInfoHidden' : 'GiftInfoSaved', {
|
||||
link: <Link isPrimary onClick={handleTriggerVisibility}>{lang('GiftInfoSavedHide')}</Link>,
|
||||
}, {
|
||||
withNodes: true,
|
||||
})}
|
||||
</div>
|
||||
{isVisibleForMe && (
|
||||
<div>
|
||||
@ -438,21 +482,7 @@ const GiftInfoModal = ({
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{canFocusUpgrade && (
|
||||
<Button size="smaller" onClick={handleFocusUpgraded}>
|
||||
{lang('GiftInfoViewUpgraded')}
|
||||
</Button>
|
||||
)}
|
||||
{!canUpdate && !canFocusUpgrade && (
|
||||
<Button size="smaller" onClick={handleClose}>
|
||||
{lang('OK')}
|
||||
</Button>
|
||||
)}
|
||||
{canUpdate && (
|
||||
<Button size="smaller" onClick={handleTriggerVisibility}>
|
||||
{lang(isUnsaved ? 'GiftInfoMakeVisible' : 'GiftInfoMakeInvisible')}
|
||||
</Button>
|
||||
)}
|
||||
{renderFooterButton()}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -463,7 +493,7 @@ const GiftInfoModal = ({
|
||||
};
|
||||
}, [
|
||||
typeGift, userGift, targetUser, giftSticker, lang, canUpdate, canConvertDifference, isSender, oldLang, gift,
|
||||
radialPatternBackdrop, giftAttributes, canFocusUpgrade,
|
||||
radialPatternBackdrop, giftAttributes, renderFooterButton,
|
||||
]);
|
||||
|
||||
return (
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
import type { FC } from '../../../../lib/teact/teact';
|
||||
import React from '../../../../lib/teact/teact';
|
||||
|
||||
import type { OwnProps } from './GiftUpgradeModal';
|
||||
|
||||
import { Bundles } from '../../../../util/moduleLoader';
|
||||
|
||||
import useModuleLoader from '../../../../hooks/useModuleLoader';
|
||||
|
||||
const GiftUpgradeModalAsync: FC<OwnProps> = (props) => {
|
||||
const { modal } = props;
|
||||
const GiftUpgradeModal = useModuleLoader(Bundles.Stars, 'GiftUpgradeModal', !modal);
|
||||
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
return GiftUpgradeModal ? <GiftUpgradeModal {...props} /> : undefined;
|
||||
};
|
||||
|
||||
export default GiftUpgradeModalAsync;
|
||||
@ -0,0 +1,11 @@
|
||||
.footer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.footerButton {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
206
src/components/modals/gift/upgrade/GiftUpgradeModal.tsx
Normal file
206
src/components/modals/gift/upgrade/GiftUpgradeModal.tsx
Normal file
@ -0,0 +1,206 @@
|
||||
import React, {
|
||||
memo, useEffect, useMemo, useState,
|
||||
} from '../../../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../../../global';
|
||||
|
||||
import type {
|
||||
ApiPeer,
|
||||
ApiStarGiftAttribute,
|
||||
ApiStarGiftAttributeBackdrop,
|
||||
ApiStarGiftAttributeModel,
|
||||
ApiStarGiftAttributePattern,
|
||||
ApiStarGiftRegular,
|
||||
} from '../../../../api/types';
|
||||
import type { TabState } from '../../../../global/types';
|
||||
import { ApiMediaFormat } from '../../../../api/types';
|
||||
|
||||
import { getPeerTitle, getStickerMediaHash } from '../../../../global/helpers';
|
||||
import { selectPeer } from '../../../../global/selectors';
|
||||
import { formatStarsAsIcon } from '../../../../util/localization/format';
|
||||
import { fetch } from '../../../../util/mediaLoader';
|
||||
|
||||
import useInterval from '../../../../hooks/schedulers/useInterval';
|
||||
import useCurrentOrPrev from '../../../../hooks/useCurrentOrPrev';
|
||||
import useLang from '../../../../hooks/useLang';
|
||||
import useLastCallback from '../../../../hooks/useLastCallback';
|
||||
|
||||
import Button from '../../../ui/Button';
|
||||
import Checkbox from '../../../ui/Checkbox';
|
||||
import TableAboutModal, { type TableAboutData } from '../../common/TableAboutModal';
|
||||
import UniqueGiftHeader from '../UniqueGiftHeader';
|
||||
|
||||
import styles from './GiftUpgradeModal.module.scss';
|
||||
|
||||
export type OwnProps = {
|
||||
modal: TabState['giftUpgradeModal'];
|
||||
};
|
||||
|
||||
type StateProps = {
|
||||
recipient?: ApiPeer;
|
||||
};
|
||||
|
||||
type Attributes = {
|
||||
model: ApiStarGiftAttributeModel;
|
||||
pattern: ApiStarGiftAttributePattern;
|
||||
backdrop: ApiStarGiftAttributeBackdrop;
|
||||
};
|
||||
|
||||
const PREVIEW_UPDATE_INTERVAL = 3000;
|
||||
|
||||
const GiftUpgradeModal = ({ modal, recipient }: OwnProps & StateProps) => {
|
||||
const { closeGiftUpgradeModal, upgradeGift } = getActions();
|
||||
const isOpen = Boolean(modal);
|
||||
|
||||
const renderingModal = useCurrentOrPrev(modal);
|
||||
const renderingRecipient = useCurrentOrPrev(recipient);
|
||||
const [shouldKeepOriginalDetails, setShouldKeepOriginalDetails] = useState(false);
|
||||
|
||||
const [previewAttributes, setPreviewAttributes] = useState<Attributes | undefined>();
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
const handleClose = useLastCallback(() => closeGiftUpgradeModal());
|
||||
|
||||
const handleUpgrade = useLastCallback(() => {
|
||||
const gift = renderingModal?.gift;
|
||||
if (!gift?.messageId) return;
|
||||
upgradeGift({
|
||||
messageId: gift.messageId,
|
||||
shouldKeepOriginalDetails,
|
||||
upgradeStars: !gift.alreadyPaidUpgradeStars ? (gift.gift as ApiStarGiftRegular).upgradeStars : undefined,
|
||||
});
|
||||
handleClose();
|
||||
});
|
||||
|
||||
const updatePreviewAttributes = useLastCallback(() => {
|
||||
if (!renderingModal?.sampleAttributes) return;
|
||||
setPreviewAttributes(getRandomAttributes(renderingModal.sampleAttributes, previewAttributes));
|
||||
});
|
||||
|
||||
useInterval(updatePreviewAttributes, isOpen ? PREVIEW_UPDATE_INTERVAL : undefined, true);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen && renderingModal?.sampleAttributes) {
|
||||
updatePreviewAttributes();
|
||||
}
|
||||
}, [isOpen, renderingModal?.sampleAttributes]);
|
||||
|
||||
// Preload stickers and patterns
|
||||
useEffect(() => {
|
||||
const attributes = renderingModal?.sampleAttributes;
|
||||
if (!attributes) return;
|
||||
const patternStickers = attributes.filter((attr): attr is ApiStarGiftAttributeModel => attr.type === 'pattern')
|
||||
.map((attr) => attr.sticker);
|
||||
const modelStickers = attributes.filter((attr): attr is ApiStarGiftAttributeModel => attr.type === 'model')
|
||||
.map((attr) => attr.sticker);
|
||||
|
||||
const mediaHashes = [...patternStickers, ...modelStickers].map((sticker) => getStickerMediaHash(sticker, 'full'));
|
||||
mediaHashes.forEach((hash) => {
|
||||
fetch(hash, ApiMediaFormat.BlobUrl);
|
||||
});
|
||||
}, [renderingModal?.sampleAttributes]);
|
||||
|
||||
const modalData = useMemo(() => {
|
||||
if (!previewAttributes) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const gift = renderingModal?.gift;
|
||||
|
||||
const listItemData = [
|
||||
['diamond', lang('GiftUpgradeUniqueTitle'), lang('GiftUpgradeUniqueDescription')],
|
||||
['trade', lang('GiftUpgradeTransferableTitle'), lang('GiftUpgradeTransferableDescription')],
|
||||
['auction', lang('GiftUpgradeTradeableTitle'), lang('GiftUpgradeTradeableDescription')],
|
||||
] satisfies TableAboutData;
|
||||
|
||||
const subtitle = renderingRecipient
|
||||
? lang('GiftUpgradeText', { peer: getPeerTitle(lang, renderingRecipient) })
|
||||
: lang('GiftUpgradeTextOwn');
|
||||
|
||||
const header = (
|
||||
<UniqueGiftHeader
|
||||
modelAttribute={previewAttributes.model}
|
||||
backdropAttribute={previewAttributes.backdrop}
|
||||
patternAttribute={previewAttributes.pattern}
|
||||
title={lang('GiftUpgradeTitle')}
|
||||
subtitle={subtitle}
|
||||
/>
|
||||
);
|
||||
|
||||
const footer = (
|
||||
<div className={styles.footer}>
|
||||
{!gift && (
|
||||
<Button className={styles.footerButton} size="smaller" onClick={handleClose}>
|
||||
{lang('OK')}
|
||||
</Button>
|
||||
)}
|
||||
{gift && (
|
||||
<>
|
||||
<Checkbox
|
||||
label={lang('GiftUpgradeKeepDetails')}
|
||||
onCheck={setShouldKeepOriginalDetails}
|
||||
checked={shouldKeepOriginalDetails}
|
||||
/>
|
||||
<Button className={styles.footerButton} size="smaller" isShiny onClick={handleUpgrade}>
|
||||
{gift.alreadyPaidUpgradeStars
|
||||
? lang('GeneralConfirm')
|
||||
: lang('GiftUpgradeButton', {
|
||||
amount: formatStarsAsIcon(lang, (gift.gift as ApiStarGiftRegular).upgradeStars!, { asFont: true }),
|
||||
}, { withNodes: true })}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
return {
|
||||
listItemData,
|
||||
header,
|
||||
footer,
|
||||
};
|
||||
}, [previewAttributes, lang, renderingRecipient, renderingModal?.gift, shouldKeepOriginalDetails]);
|
||||
|
||||
return (
|
||||
<TableAboutModal
|
||||
isOpen={isOpen}
|
||||
header={modalData?.header}
|
||||
footer={modalData?.footer}
|
||||
listItemData={modalData?.listItemData}
|
||||
hasBackdrop
|
||||
onClose={handleClose}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(withGlobal<OwnProps>(
|
||||
(global, { modal }): StateProps => {
|
||||
const recipientId = modal?.recipientId;
|
||||
const recipient = recipientId ? selectPeer(global, recipientId) : undefined;
|
||||
|
||||
return {
|
||||
recipient,
|
||||
};
|
||||
},
|
||||
)(GiftUpgradeModal));
|
||||
|
||||
function getRandomAttributes(list: ApiStarGiftAttribute[], previousSelection?: Attributes): Attributes {
|
||||
const models = list.filter((attr): attr is ApiStarGiftAttributeModel => (
|
||||
attr.type === 'model' && attr.name !== previousSelection?.model.name
|
||||
));
|
||||
const patterns = list.filter((attr): attr is ApiStarGiftAttributePattern => (
|
||||
attr.type === 'pattern' && attr.name !== previousSelection?.pattern.name
|
||||
));
|
||||
const backdrops = list.filter((attr): attr is ApiStarGiftAttributeBackdrop => (
|
||||
attr.type === 'backdrop' && attr.name !== previousSelection?.backdrop.name
|
||||
));
|
||||
|
||||
const randomModel = models[Math.floor(Math.random() * models.length)];
|
||||
const randomPattern = patterns[Math.floor(Math.random() * patterns.length)];
|
||||
const randomBackdrop = backdrops[Math.floor(Math.random() * backdrops.length)];
|
||||
|
||||
return {
|
||||
model: randomModel,
|
||||
pattern: randomPattern,
|
||||
backdrop: randomBackdrop,
|
||||
};
|
||||
}
|
||||
@ -200,7 +200,7 @@ const StarPaymentModal = ({
|
||||
</div>
|
||||
<Button className={styles.paymentButton} size="smaller" onClick={handlePayment} isLoading={isLoading}>
|
||||
{lang(isBotSubscription ? 'StarsSubscribeBotButtonMonth' : 'StarsPay', {
|
||||
amount: formatStarsAsIcon(lang, amount!, true),
|
||||
amount: formatStarsAsIcon(lang, amount!, { asFont: true }),
|
||||
}, {
|
||||
withNodes: true,
|
||||
})}
|
||||
|
||||
@ -86,7 +86,7 @@
|
||||
}
|
||||
|
||||
> .Switcher {
|
||||
margin-left: auto;
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -255,6 +255,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-zoomBounceSemiFade,
|
||||
&-zoomBounceSemiFadeBackwards {
|
||||
> .Transition_slide-from {
|
||||
animation: zoom-bounce 0.25s ease-in-out;
|
||||
}
|
||||
|
||||
> .Transition_slide-to {
|
||||
animation: fade-in-opacity 250ms ease, zoom-bounce 0.25s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
&-fade,
|
||||
&-fadeBackwards {
|
||||
> .Transition_slide-from {
|
||||
@ -741,3 +752,17 @@
|
||||
clip-path: inset(0 100% 0 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zoom-bounce {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
25% {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ import usePreviousDeprecated from '../../hooks/usePreviousDeprecated';
|
||||
import './Transition.scss';
|
||||
|
||||
type AnimationName = (
|
||||
'none' | 'slide' | 'slideRtl' | 'slideFade' | 'zoomFade' | 'slideLayers'
|
||||
'none' | 'slide' | 'slideRtl' | 'slideFade' | 'zoomFade' | 'zoomBounceSemiFade' | 'slideLayers'
|
||||
| 'fade' | 'pushSlide' | 'reveal' | 'slideOptimized' | 'slideOptimizedRtl' | 'semiFade'
|
||||
| 'slideVertical' | 'slideVerticalFade' | 'slideFadeAndroid'
|
||||
);
|
||||
@ -63,7 +63,7 @@ export const ACTIVE_SLIDE_CLASS_NAME = CLASSES.active;
|
||||
export const TO_SLIDE_CLASS_NAME = CLASSES.to;
|
||||
|
||||
const DISABLEABLE_ANIMATIONS = new Set<AnimationName>([
|
||||
'slide', 'slideRtl', 'slideFade', 'zoomFade', 'slideLayers', 'pushSlide', 'reveal',
|
||||
'slide', 'slideRtl', 'slideFade', 'zoomFade', 'zoomBounceSemiFade', 'slideLayers', 'pushSlide', 'reveal',
|
||||
'slideOptimized', 'slideOptimizedRtl', 'slideVertical', 'slideVerticalFade',
|
||||
]);
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import type { ApiInputInvoiceStarGift, ApiRequestInputInvoice } from '../../../api/types';
|
||||
import type {
|
||||
ApiInputInvoice, ApiInputInvoiceStarGift, ApiInputInvoiceStarGiftUpgrade, ApiRequestInputInvoice,
|
||||
} from '../../../api/types';
|
||||
import type { ApiCredentials } from '../../../components/payment/PaymentModal';
|
||||
import type {
|
||||
ActionReturnType, GlobalState, TabArgs,
|
||||
@ -16,7 +18,9 @@ import { isChatChannel, isChatSuperGroup } from '../../helpers';
|
||||
import {
|
||||
getRequestInputInvoice,
|
||||
} from '../../helpers/payments';
|
||||
import { addActionHandler, getGlobal, setGlobal } from '../../index';
|
||||
import {
|
||||
addActionHandler, getActions, getGlobal, setGlobal,
|
||||
} from '../../index';
|
||||
import {
|
||||
closeInvoice,
|
||||
openStarsTransactionFromReceipt,
|
||||
@ -117,62 +121,21 @@ addActionHandler('openInvoice', async (global, actions, payload): Promise<void>
|
||||
setGlobal(global);
|
||||
});
|
||||
|
||||
addActionHandler('sendStarGift', async (global, actions, payload): Promise<void> => {
|
||||
addActionHandler('sendStarGift', (global, actions, payload): ActionReturnType => {
|
||||
const {
|
||||
gift, userId, message, shouldHideName, tabId = getCurrentTabId(),
|
||||
gift, userId, message, shouldHideName, shouldUpgrade, tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
|
||||
const balance = global.stars?.balance;
|
||||
|
||||
if (balance === undefined) return;
|
||||
|
||||
if (balance.amount < gift.stars) {
|
||||
actions.openStarsBalanceModal({ tabId });
|
||||
return;
|
||||
}
|
||||
|
||||
const inputInvoice: ApiInputInvoiceStarGift = {
|
||||
type: 'stargift',
|
||||
userId,
|
||||
giftId: gift.id,
|
||||
message,
|
||||
shouldHideName,
|
||||
shouldUpgrade: shouldUpgrade || undefined,
|
||||
};
|
||||
const requestInputInvoice = getRequestInputInvoice(global, inputInvoice);
|
||||
if (!requestInputInvoice) {
|
||||
return;
|
||||
}
|
||||
|
||||
global = updateTabState(global, {
|
||||
isPaymentFormLoading: true,
|
||||
}, tabId);
|
||||
setGlobal(global);
|
||||
|
||||
const theme = extractCurrentThemeParams();
|
||||
const form = await callApi('getPaymentForm', requestInputInvoice, theme);
|
||||
|
||||
if (!form) {
|
||||
return;
|
||||
}
|
||||
|
||||
global = getGlobal();
|
||||
|
||||
global = updateTabState(global, {
|
||||
isPaymentFormLoading: false,
|
||||
}, tabId);
|
||||
setGlobal(global);
|
||||
|
||||
if ('error' in form) {
|
||||
return;
|
||||
}
|
||||
|
||||
actions.sendStarPaymentForm({
|
||||
starGift: {
|
||||
inputInvoice,
|
||||
formId: form.formId,
|
||||
},
|
||||
tabId,
|
||||
});
|
||||
payInputStarInvoice(global, inputInvoice, gift.stars, tabId);
|
||||
});
|
||||
|
||||
addActionHandler('getReceipt', async (global, actions, payload): Promise<void> => {
|
||||
@ -296,9 +259,9 @@ addActionHandler('sendPaymentForm', async (global, actions, payload): Promise<vo
|
||||
});
|
||||
|
||||
addActionHandler('sendStarPaymentForm', async (global, actions, payload): Promise<void> => {
|
||||
const { starGift, tabId = getCurrentTabId() } = payload;
|
||||
const { directInfo, tabId = getCurrentTabId() } = payload;
|
||||
const starPayment = selectStarsPayment(global, tabId);
|
||||
const inputInvoice = starPayment?.inputInvoice || starGift?.inputInvoice;
|
||||
const inputInvoice = starPayment?.inputInvoice || directInfo?.inputInvoice;
|
||||
if (!inputInvoice) return;
|
||||
|
||||
const requestInputInvoice = getRequestInputInvoice(global, inputInvoice);
|
||||
@ -306,7 +269,7 @@ addActionHandler('sendStarPaymentForm', async (global, actions, payload): Promis
|
||||
return;
|
||||
}
|
||||
|
||||
const formId = (starPayment.form?.formId || starPayment.subscriptionInfo?.subscriptionFormId || starGift?.formId)!;
|
||||
const formId = (starPayment.form?.formId || starPayment.subscriptionInfo?.subscriptionFormId || directInfo?.formId)!;
|
||||
|
||||
global = updateStarsPayment(global, { status: 'pending' }, tabId);
|
||||
setGlobal(global);
|
||||
@ -337,7 +300,7 @@ addActionHandler('sendStarPaymentForm', async (global, actions, payload): Promis
|
||||
|
||||
actions.apiUpdate({
|
||||
'@type': 'updateStarPaymentStateCompleted',
|
||||
paymentState: starGift ? { inputInvoice } : starPayment,
|
||||
paymentState: directInfo ? { inputInvoice } : starPayment,
|
||||
tabId,
|
||||
});
|
||||
actions.loadStarStatus();
|
||||
@ -991,6 +954,90 @@ addActionHandler('launchPrepaidStarsGiveaway', async (global, actions, payload):
|
||||
actions.openBoostStatistics({ chatId, tabId });
|
||||
});
|
||||
|
||||
addActionHandler('upgradeGift', (global, actions, payload): ActionReturnType => {
|
||||
const {
|
||||
messageId, shouldKeepOriginalDetails, upgradeStars, tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
|
||||
global = updateTabState(global, {
|
||||
isWaitingForStarGiftUpgrade: true,
|
||||
}, tabId);
|
||||
|
||||
setGlobal(global);
|
||||
global = getGlobal();
|
||||
|
||||
actions.closeGiftUpgradeModal({ tabId });
|
||||
actions.closeGiftInfoModal({ tabId });
|
||||
|
||||
if (!upgradeStars) {
|
||||
callApi('upgradeGift', {
|
||||
messageId,
|
||||
shouldKeepOriginalDetails: shouldKeepOriginalDetails || undefined,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const invoice: ApiInputInvoiceStarGiftUpgrade = {
|
||||
type: 'stargiftUpgrade',
|
||||
messageId,
|
||||
shouldKeepOriginalDetails: shouldKeepOriginalDetails || undefined,
|
||||
};
|
||||
|
||||
payInputStarInvoice(global, invoice, upgradeStars, tabId);
|
||||
});
|
||||
|
||||
async function payInputStarInvoice<T extends GlobalState>(
|
||||
global: T, inputInvoice: ApiInputInvoice, price: number,
|
||||
...[tabId = getCurrentTabId()]: TabArgs<T>
|
||||
) {
|
||||
const actions = getActions();
|
||||
const balance = global.stars?.balance;
|
||||
|
||||
if (balance === undefined) return;
|
||||
|
||||
if (balance.amount < price) {
|
||||
actions.openStarsBalanceModal({ tabId });
|
||||
return;
|
||||
}
|
||||
|
||||
const requestInputInvoice = getRequestInputInvoice(global, inputInvoice);
|
||||
if (!requestInputInvoice) {
|
||||
return;
|
||||
}
|
||||
|
||||
global = updateTabState(global, {
|
||||
isPaymentFormLoading: true,
|
||||
}, tabId);
|
||||
setGlobal(global);
|
||||
|
||||
const theme = extractCurrentThemeParams();
|
||||
const form = await callApi('getPaymentForm', requestInputInvoice, theme);
|
||||
|
||||
if (!form) {
|
||||
return;
|
||||
}
|
||||
|
||||
global = getGlobal();
|
||||
|
||||
global = updateTabState(global, {
|
||||
isPaymentFormLoading: false,
|
||||
}, tabId);
|
||||
setGlobal(global);
|
||||
|
||||
if ('error' in form) {
|
||||
return;
|
||||
}
|
||||
|
||||
actions.sendStarPaymentForm({
|
||||
directInfo: {
|
||||
inputInvoice,
|
||||
formId: form.formId,
|
||||
},
|
||||
tabId,
|
||||
});
|
||||
}
|
||||
|
||||
addActionHandler('openUniqueGiftBySlug', async (global, actions, payload): Promise<void> => {
|
||||
const {
|
||||
slug, tabId = getCurrentTabId(),
|
||||
|
||||
@ -12,6 +12,7 @@ import {
|
||||
updateStarsBalance,
|
||||
updateStarsSubscriptionLoading,
|
||||
} from '../../reducers';
|
||||
import { updateTabState } from '../../reducers/tabs';
|
||||
import {
|
||||
selectPeer,
|
||||
selectUser,
|
||||
@ -91,16 +92,16 @@ addActionHandler('loadStarGifts', async (global): Promise<void> => {
|
||||
return;
|
||||
}
|
||||
|
||||
const starGiftsById = buildCollectionByKey(result, 'id');
|
||||
const byId = buildCollectionByKey(result, 'id');
|
||||
|
||||
const starGiftCategoriesByName: Record<StarGiftCategory, string[]> = {
|
||||
const idsByCategoryName: Record<StarGiftCategory, string[]> = {
|
||||
all: [],
|
||||
stock: [],
|
||||
limited: [],
|
||||
};
|
||||
|
||||
const allStarGiftIds = Object.keys(starGiftsById);
|
||||
const allStarGifts = Object.values(starGiftsById);
|
||||
const allStarGiftIds = Object.keys(byId);
|
||||
const allStarGifts = Object.values(byId);
|
||||
|
||||
const limitedStarGiftIds = allStarGifts.map((gift) => (gift.isLimited ? gift.id : undefined))
|
||||
.filter(Boolean) as string[];
|
||||
@ -109,23 +110,25 @@ addActionHandler('loadStarGifts', async (global): Promise<void> => {
|
||||
gift.availabilityRemains || !gift.availabilityTotal ? gift.id : undefined
|
||||
)).filter(Boolean) as string[];
|
||||
|
||||
starGiftCategoriesByName.all = allStarGiftIds;
|
||||
starGiftCategoriesByName.limited = limitedStarGiftIds;
|
||||
starGiftCategoriesByName.stock = stockedStarGiftIds;
|
||||
idsByCategoryName.all = allStarGiftIds;
|
||||
idsByCategoryName.limited = limitedStarGiftIds;
|
||||
idsByCategoryName.stock = stockedStarGiftIds;
|
||||
|
||||
allStarGifts.forEach((gift) => {
|
||||
const starsCategory = gift.stars;
|
||||
if (!starGiftCategoriesByName[starsCategory]) {
|
||||
starGiftCategoriesByName[starsCategory] = [];
|
||||
if (!idsByCategoryName[starsCategory]) {
|
||||
idsByCategoryName[starsCategory] = [];
|
||||
}
|
||||
starGiftCategoriesByName[starsCategory].push(gift.id);
|
||||
idsByCategoryName[starsCategory].push(gift.id);
|
||||
});
|
||||
|
||||
global = getGlobal();
|
||||
global = {
|
||||
...global,
|
||||
starGiftsById,
|
||||
starGiftCategoriesByName,
|
||||
starGifts: {
|
||||
byId,
|
||||
idsByCategory: idsByCategoryName,
|
||||
},
|
||||
};
|
||||
setGlobal(global);
|
||||
});
|
||||
@ -218,17 +221,19 @@ addActionHandler('changeGiftVisibility', async (global, actions, payload): Promi
|
||||
const currentUserId = global.currentUserId!;
|
||||
|
||||
const oldGifts = global.users.giftsById[currentUserId];
|
||||
const newGifts = oldGifts.gifts.map((gift) => {
|
||||
if (gift.messageId === messageId) {
|
||||
return {
|
||||
...gift,
|
||||
isUnsaved: shouldUnsave,
|
||||
} satisfies ApiUserStarGift;
|
||||
}
|
||||
return gift;
|
||||
});
|
||||
global = replaceUserGifts(global, currentUserId, newGifts, oldGifts.nextOffset);
|
||||
setGlobal(global);
|
||||
if (oldGifts?.gifts?.length) {
|
||||
const newGifts = oldGifts.gifts.map((gift) => {
|
||||
if (gift.messageId === messageId) {
|
||||
return {
|
||||
...gift,
|
||||
isUnsaved: shouldUnsave,
|
||||
} satisfies ApiUserStarGift;
|
||||
}
|
||||
return gift;
|
||||
});
|
||||
global = replaceUserGifts(global, currentUserId, newGifts, oldGifts.nextOffset);
|
||||
setGlobal(global);
|
||||
}
|
||||
|
||||
const result = await callApi('saveStarGift', {
|
||||
messageId,
|
||||
@ -260,3 +265,27 @@ addActionHandler('convertGiftToStars', async (global, actions, payload): Promise
|
||||
actions.loadUserGifts({ userId: global.currentUserId!, shouldRefresh: true });
|
||||
actions.openStarsBalanceModal({ tabId });
|
||||
});
|
||||
|
||||
addActionHandler('openGiftUpgradeModal', async (global, actions, payload): Promise<void> => {
|
||||
const {
|
||||
giftId, gift, peerId, tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
|
||||
const samples = await callApi('fetchStarGiftUpgradePreview', {
|
||||
giftId,
|
||||
});
|
||||
|
||||
if (!samples) return;
|
||||
|
||||
global = getGlobal();
|
||||
|
||||
global = updateTabState(global, {
|
||||
giftUpgradeModal: {
|
||||
recipientId: peerId,
|
||||
gift,
|
||||
sampleAttributes: samples,
|
||||
},
|
||||
}, tabId);
|
||||
|
||||
setGlobal(global);
|
||||
});
|
||||
|
||||
@ -19,7 +19,8 @@ import {
|
||||
updateStealthMode,
|
||||
updateThreadInfos,
|
||||
} from '../../reducers';
|
||||
import { selectPeerStories, selectPeerStory } from '../../selectors';
|
||||
import { updateTabState } from '../../reducers/tabs';
|
||||
import { selectPeerStories, selectPeerStory, selectTabState } from '../../selectors';
|
||||
|
||||
addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
|
||||
switch (update['@type']) {
|
||||
@ -205,6 +206,35 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
|
||||
|
||||
case 'updateLangPack': {
|
||||
applyLangPackDifference(update.version, update.strings, update.keysToRemove);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'newMessage': {
|
||||
const actionStarGift = update.message.content?.action?.starGift;
|
||||
if (actionStarGift?.type !== 'starGiftUnique' || !update.message.isOutgoing) {
|
||||
return undefined;
|
||||
}
|
||||
Object.values(global.byTabId).forEach(({ id: tabId }) => {
|
||||
const tabState = selectTabState(global, tabId);
|
||||
if (tabState.isWaitingForStarGiftUpgrade) {
|
||||
actions.openUniqueGiftBySlug({
|
||||
slug: actionStarGift.gift.slug,
|
||||
tabId,
|
||||
});
|
||||
|
||||
actions.showNotification({
|
||||
title: { key: 'GiftUpgradedTitle' },
|
||||
message: { key: 'GiftUpgradedDescription' },
|
||||
tabId,
|
||||
});
|
||||
|
||||
actions.requestConfetti({ withStars: true, tabId });
|
||||
|
||||
global = updateTabState(global, {
|
||||
isWaitingForStarGiftUpgrade: undefined,
|
||||
}, tabId);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -264,6 +264,8 @@ addActionHandler('openGiftInfoModalFromMessage', (global, actions, payload): Act
|
||||
messageId: (!message.isOutgoing || chatId === global.currentUserId) ? message.id : undefined,
|
||||
isConverted: starGift.isConverted,
|
||||
upgradeMsgId: starGift.upgradeMsgId,
|
||||
canUpgrade: starGift.canUpgrade,
|
||||
alreadyPaidUpgradeStars: starGift.alreadyPaidUpgradeStars,
|
||||
} satisfies ApiUserStarGift;
|
||||
|
||||
actions.openGiftInfoModal({ userId: giftReceiverId, gift, tabId });
|
||||
@ -291,3 +293,11 @@ addActionHandler('closeGiftInfoModal', (global, actions, payload): ActionReturnT
|
||||
giftInfoModal: undefined,
|
||||
}, tabId);
|
||||
});
|
||||
|
||||
addActionHandler('closeGiftUpgradeModal', (global, actions, payload): ActionReturnType => {
|
||||
const { tabId = getCurrentTabId() } = payload || {};
|
||||
|
||||
return updateTabState(global, {
|
||||
giftUpgradeModal: undefined,
|
||||
}, tabId);
|
||||
});
|
||||
|
||||
@ -20,7 +20,7 @@ export function getRequestInputInvoice<T extends GlobalState>(
|
||||
|
||||
if (inputInvoice.type === 'stargift') {
|
||||
const {
|
||||
userId, shouldHideName, giftId, message,
|
||||
userId, shouldHideName, giftId, message, shouldUpgrade,
|
||||
} = inputInvoice;
|
||||
const user = selectUser(global, userId);
|
||||
|
||||
@ -32,6 +32,7 @@ export function getRequestInputInvoice<T extends GlobalState>(
|
||||
shouldHideName,
|
||||
giftId,
|
||||
message,
|
||||
shouldUpgrade,
|
||||
};
|
||||
}
|
||||
|
||||
@ -172,6 +173,15 @@ export function getRequestInputInvoice<T extends GlobalState>(
|
||||
};
|
||||
}
|
||||
|
||||
if (inputInvoice.type === 'stargiftUpgrade') {
|
||||
const { messageId, shouldKeepOriginalDetails } = inputInvoice;
|
||||
return {
|
||||
type: 'stargiftUpgrade',
|
||||
messageId,
|
||||
shouldKeepOriginalDetails,
|
||||
};
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
@ -181,12 +181,6 @@ export const INITIAL_GLOBAL_STATE: GlobalState = {
|
||||
hash: {},
|
||||
},
|
||||
availableEffectById: {},
|
||||
starGiftsById: {},
|
||||
starGiftCategoriesByName: {
|
||||
all: [],
|
||||
limited: [],
|
||||
stock: [],
|
||||
},
|
||||
|
||||
stickers: {
|
||||
setsById: {},
|
||||
|
||||
@ -681,9 +681,9 @@ export interface ActionPayloads {
|
||||
tipAmount?: number;
|
||||
} & WithTabId;
|
||||
sendStarPaymentForm: {
|
||||
starGift?: {
|
||||
directInfo?: {
|
||||
formId: string;
|
||||
inputInvoice: ApiInputInvoiceStarGift;
|
||||
inputInvoice: ApiInputInvoice;
|
||||
};
|
||||
} & WithTabId;
|
||||
getReceipt: {
|
||||
@ -2311,6 +2311,17 @@ export interface ActionPayloads {
|
||||
gift: ApiStarGift;
|
||||
}) & WithTabId;
|
||||
closeGiftInfoModal: WithTabId | undefined;
|
||||
openGiftUpgradeModal: {
|
||||
giftId: string;
|
||||
peerId?: string;
|
||||
gift?: ApiUserStarGift;
|
||||
} & WithTabId;
|
||||
closeGiftUpgradeModal: WithTabId | undefined;
|
||||
upgradeGift: {
|
||||
messageId: number;
|
||||
shouldKeepOriginalDetails?: boolean;
|
||||
upgradeStars?: number;
|
||||
} & WithTabId;
|
||||
loadUserGifts: {
|
||||
userId: string;
|
||||
shouldRefresh?: boolean;
|
||||
|
||||
@ -298,8 +298,10 @@ export type GlobalState = {
|
||||
};
|
||||
};
|
||||
availableEffectById: Record<string, ApiAvailableEffect>;
|
||||
starGiftsById: Record<string, ApiStarGiftRegular>;
|
||||
starGiftCategoriesByName: Record<StarGiftCategory, string[]>;
|
||||
starGifts?: {
|
||||
byId: Record<string, ApiStarGiftRegular>;
|
||||
idsByCategory: Record<StarGiftCategory, string[]>;
|
||||
};
|
||||
|
||||
stickers: {
|
||||
setsById: Record<string, ApiStickerSet>;
|
||||
|
||||
@ -33,6 +33,7 @@ import type {
|
||||
ApiReactionWithPaid,
|
||||
ApiReceiptRegular,
|
||||
ApiStarGift,
|
||||
ApiStarGiftAttribute,
|
||||
ApiStarGiveawayOption,
|
||||
ApiStarsSubscription,
|
||||
ApiStarsTransaction,
|
||||
@ -713,10 +714,18 @@ export type TabState = {
|
||||
gift: ApiUserStarGift | ApiStarGift;
|
||||
};
|
||||
|
||||
giftUpgradeModal?: {
|
||||
sampleAttributes: ApiStarGiftAttribute[];
|
||||
recipientId?: string;
|
||||
gift?: ApiUserStarGift;
|
||||
};
|
||||
|
||||
suggestedStatusModal?: {
|
||||
botId: string;
|
||||
webAppKey?: string;
|
||||
customEmojiId: string;
|
||||
duration?: number;
|
||||
};
|
||||
|
||||
isWaitingForStarGiftUpgrade?: true;
|
||||
};
|
||||
|
||||
17
src/hooks/animations/useTransitionActiveKey.ts
Normal file
17
src/hooks/animations/useTransitionActiveKey.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { useMemo, useRef } from '../../lib/teact/teact';
|
||||
|
||||
/**
|
||||
* Use this hook to bind `<Transition />` animation to changes in the dependency array.
|
||||
* Use optional parameter `noAnimation` if you want to prevent the animation even if the dependency array changes.
|
||||
*/
|
||||
export function useTransitionActiveKey(deps: unknown[], noAnimation?: boolean): number {
|
||||
const activeKey = useRef(0);
|
||||
let didUpdate = false;
|
||||
|
||||
// eslint-disable-next-line react-hooks-static-deps/exhaustive-deps
|
||||
useMemo(() => { activeKey.current += 1; didUpdate = true; }, deps);
|
||||
|
||||
if (noAnimation && didUpdate) activeKey.current -= 1;
|
||||
|
||||
return activeKey.current;
|
||||
}
|
||||
7
src/lib/gramjs/tl/api.d.ts
vendored
7
src/lib/gramjs/tl/api.d.ts
vendored
@ -20292,6 +20292,11 @@ namespace Api {
|
||||
}>, Bool> {
|
||||
msgId: int;
|
||||
}
|
||||
export class GetUniqueStarGift extends Request<Partial<{
|
||||
slug: string;
|
||||
}>, payments.TypeUniqueStarGift> {
|
||||
slug: string;
|
||||
}
|
||||
export class BotCancelStarsSubscription extends Request<Partial<{
|
||||
// flags: Api.Type;
|
||||
restore?: true;
|
||||
@ -21346,7 +21351,7 @@ namespace Api {
|
||||
| help.GetConfig | help.GetNearestDc | help.GetAppUpdate | help.GetInviteText | help.GetSupport | help.SetBotUpdatesStatus | help.GetCdnConfig | help.GetRecentMeUrls | help.GetTermsOfServiceUpdate | help.AcceptTermsOfService | help.GetDeepLinkInfo | help.GetAppConfig | help.SaveAppLog | help.GetPassportConfig | help.GetSupportName | help.GetUserInfo | help.EditUserInfo | help.GetPromoData | help.HidePromoData | help.DismissSuggestion | help.GetCountriesList | help.GetPremiumPromo | help.GetPeerColors | help.GetPeerProfileColors | help.GetTimezonesList
|
||||
| channels.ReadHistory | channels.DeleteMessages | channels.ReportSpam | channels.GetMessages | channels.GetParticipants | channels.GetParticipant | channels.GetChannels | channels.GetFullChannel | channels.CreateChannel | channels.EditAdmin | channels.EditTitle | channels.EditPhoto | channels.CheckUsername | channels.UpdateUsername | channels.JoinChannel | channels.LeaveChannel | channels.InviteToChannel | channels.DeleteChannel | channels.ExportMessageLink | channels.ToggleSignatures | channels.GetAdminedPublicChannels | channels.EditBanned | channels.GetAdminLog | channels.SetStickers | channels.ReadMessageContents | channels.DeleteHistory | channels.TogglePreHistoryHidden | channels.GetLeftChannels | channels.GetGroupsForDiscussion | channels.SetDiscussionGroup | channels.EditCreator | channels.EditLocation | channels.ToggleSlowMode | channels.GetInactiveChannels | channels.ConvertToGigagroup | channels.GetSendAs | channels.DeleteParticipantHistory | channels.ToggleJoinToSend | channels.ToggleJoinRequest | channels.ReorderUsernames | channels.ToggleUsername | channels.DeactivateAllUsernames | channels.ToggleForum | channels.CreateForumTopic | channels.GetForumTopics | channels.GetForumTopicsByID | channels.EditForumTopic | channels.UpdatePinnedForumTopic | channels.DeleteTopicHistory | channels.ReorderPinnedForumTopics | channels.ToggleAntiSpam | channels.ReportAntiSpamFalsePositive | channels.ToggleParticipantsHidden | channels.UpdateColor | channels.ToggleViewForumAsMessages | channels.GetChannelRecommendations | channels.UpdateEmojiStatus | channels.SetBoostsToUnblockRestrictions | channels.SetEmojiStickers | channels.RestrictSponsoredMessages | channels.SearchPosts
|
||||
| bots.SendCustomRequest | bots.AnswerWebhookJSONQuery | bots.SetBotCommands | bots.ResetBotCommands | bots.GetBotCommands | bots.SetBotMenuButton | bots.GetBotMenuButton | bots.SetBotBroadcastDefaultAdminRights | bots.SetBotGroupDefaultAdminRights | bots.SetBotInfo | bots.GetBotInfo | bots.ReorderUsernames | bots.ToggleUsername | bots.CanSendMessage | bots.AllowSendMessage | bots.InvokeWebViewCustomMethod | bots.GetPopularAppBots | bots.AddPreviewMedia | bots.EditPreviewMedia | bots.DeletePreviewMedia | bots.ReorderPreviewMedias | bots.GetPreviewInfo | bots.GetPreviewMedias | bots.UpdateUserEmojiStatus | bots.ToggleUserEmojiStatusPermission | bots.CheckDownloadFileParams | bots.GetAdminedBots | bots.UpdateStarRefProgram | bots.SetCustomVerification | bots.GetBotRecommendations
|
||||
| payments.GetPaymentForm | payments.GetPaymentReceipt | payments.ValidateRequestedInfo | payments.SendPaymentForm | payments.GetSavedInfo | payments.ClearSavedInfo | payments.GetBankCardData | payments.ExportInvoice | payments.AssignAppStoreTransaction | payments.AssignPlayMarketTransaction | payments.CanPurchasePremium | payments.GetPremiumGiftCodeOptions | payments.CheckGiftCode | payments.ApplyGiftCode | payments.GetGiveawayInfo | payments.LaunchPrepaidGiveaway | payments.GetStarsTopupOptions | payments.GetStarsStatus | payments.GetStarsTransactions | payments.SendStarsForm | payments.RefundStarsCharge | payments.GetStarsRevenueStats | payments.GetStarsRevenueWithdrawalUrl | payments.GetStarsRevenueAdsAccountUrl | payments.GetStarsTransactionsByID | payments.GetStarsGiftOptions | payments.GetStarsSubscriptions | payments.ChangeStarsSubscription | payments.FulfillStarsSubscription | payments.GetStarsGiveawayOptions | payments.GetStarGifts | payments.GetUserStarGifts | payments.SaveStarGift | payments.ConvertStarGift | payments.BotCancelStarsSubscription | payments.GetConnectedStarRefBots | payments.GetConnectedStarRefBot | payments.GetSuggestedStarRefBots | payments.ConnectStarRefBot | payments.EditConnectedStarRefBot | payments.GetStarGiftUpgradePreview | payments.UpgradeStarGift | payments.TransferStarGift | payments.GetUserStarGift | payments.GetUniqueStarGift
|
||||
| payments.GetPaymentForm | payments.GetPaymentReceipt | payments.ValidateRequestedInfo | payments.SendPaymentForm | payments.GetSavedInfo | payments.ClearSavedInfo | payments.GetBankCardData | payments.ExportInvoice | payments.AssignAppStoreTransaction | payments.AssignPlayMarketTransaction | payments.CanPurchasePremium | payments.GetPremiumGiftCodeOptions | payments.CheckGiftCode | payments.ApplyGiftCode | payments.GetGiveawayInfo | payments.LaunchPrepaidGiveaway | payments.GetStarsTopupOptions | payments.GetStarsStatus | payments.GetStarsTransactions | payments.SendStarsForm | payments.RefundStarsCharge | payments.GetStarsRevenueStats | payments.GetStarsRevenueWithdrawalUrl | payments.GetStarsRevenueAdsAccountUrl | payments.GetStarsTransactionsByID | payments.GetStarsGiftOptions | payments.GetStarsSubscriptions | payments.ChangeStarsSubscription | payments.FulfillStarsSubscription | payments.GetStarsGiveawayOptions | payments.GetStarGifts | payments.GetUserStarGifts | payments.SaveStarGift | payments.ConvertStarGift | payments.GetUniqueStarGift | payments.BotCancelStarsSubscription | payments.GetConnectedStarRefBots | payments.GetConnectedStarRefBot | payments.GetSuggestedStarRefBots | payments.ConnectStarRefBot | payments.EditConnectedStarRefBot | payments.GetStarGiftUpgradePreview | payments.UpgradeStarGift | payments.TransferStarGift | payments.GetUserStarGift | payments.GetUniqueStarGift
|
||||
| stickers.CreateStickerSet | stickers.RemoveStickerFromSet | stickers.ChangeStickerPosition | stickers.AddStickerToSet | stickers.SetStickerSetThumb | stickers.CheckShortName | stickers.SuggestShortName | stickers.ChangeSticker | stickers.RenameStickerSet | stickers.DeleteStickerSet | stickers.ReplaceSticker
|
||||
| phone.GetCallConfig | phone.RequestCall | phone.AcceptCall | phone.ConfirmCall | phone.ReceivedCall | phone.DiscardCall | phone.SetCallRating | phone.SaveCallDebug | phone.SendSignalingData | phone.CreateGroupCall | phone.JoinGroupCall | phone.LeaveGroupCall | phone.InviteToGroupCall | phone.DiscardGroupCall | phone.ToggleGroupCallSettings | phone.GetGroupCall | phone.GetGroupParticipants | phone.CheckGroupCall | phone.ToggleGroupCallRecord | phone.EditGroupCallParticipant | phone.EditGroupCallTitle | phone.GetGroupCallJoinAs | phone.ExportGroupCallInvite | phone.ToggleGroupCallStartSubscription | phone.StartScheduledGroupCall | phone.SaveDefaultGroupCallJoinAs | phone.JoinGroupCallPresentation | phone.LeaveGroupCallPresentation | phone.GetGroupCallStreamChannels | phone.GetGroupCallStreamRtmpUrl | phone.SaveCallLog | phone.CreateConferenceCall
|
||||
| langpack.GetLangPack | langpack.GetStrings | langpack.GetDifference | langpack.GetLanguages | langpack.GetLanguage
|
||||
|
||||
@ -1715,6 +1715,10 @@ payments.getUserStarGifts#5e72c7e1 user_id:InputUser offset:string limit:int = p
|
||||
payments.saveStarGift#92fd2aae flags:# unsave:flags.0?true msg_id:int = Bool;
|
||||
payments.convertStarGift#72770c83 msg_id:int = Bool;
|
||||
payments.getUniqueStarGift#a1974d72 slug:string = payments.UniqueStarGift;
|
||||
payments.getStarGiftUpgradePreview#9c9abcb1 gift_id:long = payments.StarGiftUpgradePreview;
|
||||
payments.upgradeStarGift#cf4f0781 flags:# keep_original_details:flags.0?true msg_id:int = Updates;
|
||||
payments.transferStarGift#333fb526 msg_id:int to_id:InputUser = Updates;
|
||||
payments.getUniqueStarGift#a1974d72 slug:string = payments.UniqueStarGift;
|
||||
phone.requestCall#a6c4600c flags:# video:flags.0?true user_id:InputUser conference_call:flags.1?InputGroupCall random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
|
||||
phone.acceptCall#3bd2b4a0 peer:InputPhoneCall g_b:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
|
||||
phone.confirmCall#2efe1722 peer:InputPhoneCall g_a:bytes key_fingerprint:long protocol:PhoneCallProtocol = phone.PhoneCall;
|
||||
|
||||
@ -285,6 +285,31 @@
|
||||
"payments.validateRequestedInfo",
|
||||
"payments.sendPaymentForm",
|
||||
"payments.getSavedInfo",
|
||||
"payments.checkGiftCode",
|
||||
"payments.applyGiftCode",
|
||||
"payments.getGiveawayInfo",
|
||||
"payments.getPremiumGiftCodeOptions",
|
||||
"payments.launchPrepaidGiveaway",
|
||||
"payments.getStarsTopupOptions",
|
||||
"payments.getStarsStatus",
|
||||
"payments.getStarsTransactions",
|
||||
"payments.getStarsTransactionsByID",
|
||||
"payments.getStarsSubscriptions",
|
||||
"payments.changeStarsSubscription",
|
||||
"payments.fulfillStarsSubscription",
|
||||
"payments.sendStarsForm",
|
||||
"payments.getStarsGiftOptions",
|
||||
"payments.getStarsGiveawayOptions",
|
||||
"payments.refundStarsCharge",
|
||||
"payments.getStarsGiftOptions",
|
||||
"payments.getStarGifts",
|
||||
"payments.getUserStarGifts",
|
||||
"payments.saveStarGift",
|
||||
"payments.convertStarGift",
|
||||
"payments.getStarGiftUpgradePreview",
|
||||
"payments.upgradeStarGift",
|
||||
"payments.transferStarGift",
|
||||
"payments.getUniqueStarGift",
|
||||
"langpack.getLangPack",
|
||||
"langpack.getStrings",
|
||||
"langpack.getLanguages",
|
||||
@ -364,27 +389,5 @@
|
||||
"premium.applyBoost",
|
||||
"premium.getMyBoosts",
|
||||
"premium.getBoostsList",
|
||||
"payments.checkGiftCode",
|
||||
"payments.applyGiftCode",
|
||||
"payments.getGiveawayInfo",
|
||||
"payments.getPremiumGiftCodeOptions",
|
||||
"payments.launchPrepaidGiveaway",
|
||||
"payments.getStarsTopupOptions",
|
||||
"payments.getStarsStatus",
|
||||
"payments.getStarsTransactions",
|
||||
"payments.getStarsTransactionsByID",
|
||||
"payments.getStarsSubscriptions",
|
||||
"payments.changeStarsSubscription",
|
||||
"payments.fulfillStarsSubscription",
|
||||
"payments.sendStarsForm",
|
||||
"payments.getStarsGiftOptions",
|
||||
"payments.getStarsGiveawayOptions",
|
||||
"payments.refundStarsCharge",
|
||||
"payments.getStarsGiftOptions",
|
||||
"payments.getStarGifts",
|
||||
"payments.getUserStarGifts",
|
||||
"payments.saveStarGift",
|
||||
"payments.convertStarGift",
|
||||
"payments.getUniqueStarGift",
|
||||
"fragment.getCollectibleInfo"
|
||||
]
|
||||
|
||||
@ -48,232 +48,235 @@ $icons-map: (
|
||||
"arrow-right": "\f111",
|
||||
"ask-support": "\f112",
|
||||
"attach": "\f113",
|
||||
"author-hidden": "\f114",
|
||||
"avatar-archived-chats": "\f115",
|
||||
"avatar-deleted-account": "\f116",
|
||||
"avatar-saved-messages": "\f117",
|
||||
"bold": "\f118",
|
||||
"boost-outline": "\f119",
|
||||
"boost": "\f11a",
|
||||
"boostcircle": "\f11b",
|
||||
"boosts": "\f11c",
|
||||
"bot-command": "\f11d",
|
||||
"bot-commands-filled": "\f11e",
|
||||
"bots": "\f11f",
|
||||
"bug": "\f120",
|
||||
"calendar-filter": "\f121",
|
||||
"calendar": "\f122",
|
||||
"camera-add": "\f123",
|
||||
"camera": "\f124",
|
||||
"car": "\f125",
|
||||
"card": "\f126",
|
||||
"cash-circle": "\f127",
|
||||
"channel-filled": "\f128",
|
||||
"channel": "\f129",
|
||||
"channelviews": "\f12a",
|
||||
"chat-badge": "\f12b",
|
||||
"chats-badge": "\f12c",
|
||||
"check": "\f12d",
|
||||
"clock-edit": "\f12e",
|
||||
"clock": "\f12f",
|
||||
"close-circle": "\f130",
|
||||
"close-topic": "\f131",
|
||||
"close": "\f132",
|
||||
"cloud-download": "\f133",
|
||||
"collapse-modal": "\f134",
|
||||
"collapse": "\f135",
|
||||
"colorize": "\f136",
|
||||
"comments-sticker": "\f137",
|
||||
"comments": "\f138",
|
||||
"copy-media": "\f139",
|
||||
"copy": "\f13a",
|
||||
"darkmode": "\f13b",
|
||||
"data": "\f13c",
|
||||
"delete-filled": "\f13d",
|
||||
"delete-left": "\f13e",
|
||||
"delete-user": "\f13f",
|
||||
"delete": "\f140",
|
||||
"document": "\f141",
|
||||
"double-badge": "\f142",
|
||||
"down": "\f143",
|
||||
"download": "\f144",
|
||||
"eats": "\f145",
|
||||
"edit": "\f146",
|
||||
"email": "\f147",
|
||||
"enter": "\f148",
|
||||
"expand-modal": "\f149",
|
||||
"expand": "\f14a",
|
||||
"eye-closed-outline": "\f14b",
|
||||
"eye-closed": "\f14c",
|
||||
"eye-outline": "\f14d",
|
||||
"eye": "\f14e",
|
||||
"favorite-filled": "\f14f",
|
||||
"favorite": "\f150",
|
||||
"file-badge": "\f151",
|
||||
"flag": "\f152",
|
||||
"folder-badge": "\f153",
|
||||
"folder": "\f154",
|
||||
"fontsize": "\f155",
|
||||
"forums": "\f156",
|
||||
"forward": "\f157",
|
||||
"fullscreen": "\f158",
|
||||
"gifs": "\f159",
|
||||
"gift": "\f15a",
|
||||
"group-filled": "\f15b",
|
||||
"group": "\f15c",
|
||||
"grouped-disable": "\f15d",
|
||||
"grouped": "\f15e",
|
||||
"hand-stop": "\f15f",
|
||||
"hashtag": "\f160",
|
||||
"heart-outline": "\f161",
|
||||
"heart": "\f162",
|
||||
"help": "\f163",
|
||||
"info-filled": "\f164",
|
||||
"info": "\f165",
|
||||
"install": "\f166",
|
||||
"italic": "\f167",
|
||||
"key": "\f168",
|
||||
"keyboard": "\f169",
|
||||
"lamp": "\f16a",
|
||||
"language": "\f16b",
|
||||
"large-pause": "\f16c",
|
||||
"large-play": "\f16d",
|
||||
"link-badge": "\f16e",
|
||||
"link-broken": "\f16f",
|
||||
"link": "\f170",
|
||||
"location": "\f171",
|
||||
"lock-badge": "\f172",
|
||||
"lock": "\f173",
|
||||
"logout": "\f174",
|
||||
"loop": "\f175",
|
||||
"mention": "\f176",
|
||||
"message-failed": "\f177",
|
||||
"message-pending": "\f178",
|
||||
"message-read": "\f179",
|
||||
"message-succeeded": "\f17a",
|
||||
"message": "\f17b",
|
||||
"microphone-alt": "\f17c",
|
||||
"microphone": "\f17d",
|
||||
"monospace": "\f17e",
|
||||
"more-circle": "\f17f",
|
||||
"more": "\f180",
|
||||
"move-caption-down": "\f181",
|
||||
"move-caption-up": "\f182",
|
||||
"mute": "\f183",
|
||||
"muted": "\f184",
|
||||
"my-notes": "\f185",
|
||||
"new-chat-filled": "\f186",
|
||||
"next": "\f187",
|
||||
"nochannel": "\f188",
|
||||
"noise-suppression": "\f189",
|
||||
"non-contacts": "\f18a",
|
||||
"one-filled": "\f18b",
|
||||
"open-in-new-tab": "\f18c",
|
||||
"password-off": "\f18d",
|
||||
"pause": "\f18e",
|
||||
"permissions": "\f18f",
|
||||
"phone-discard-outline": "\f190",
|
||||
"phone-discard": "\f191",
|
||||
"phone": "\f192",
|
||||
"photo": "\f193",
|
||||
"pin-badge": "\f194",
|
||||
"pin-list": "\f195",
|
||||
"pin": "\f196",
|
||||
"pinned-chat": "\f197",
|
||||
"pinned-message": "\f198",
|
||||
"pip": "\f199",
|
||||
"play-story": "\f19a",
|
||||
"play": "\f19b",
|
||||
"poll": "\f19c",
|
||||
"previous": "\f19d",
|
||||
"privacy-policy": "\f19e",
|
||||
"quote-text": "\f19f",
|
||||
"quote": "\f1a0",
|
||||
"readchats": "\f1a1",
|
||||
"recent": "\f1a2",
|
||||
"reload": "\f1a3",
|
||||
"remove-quote": "\f1a4",
|
||||
"remove": "\f1a5",
|
||||
"reopen-topic": "\f1a6",
|
||||
"replace": "\f1a7",
|
||||
"replies": "\f1a8",
|
||||
"reply-filled": "\f1a9",
|
||||
"reply": "\f1aa",
|
||||
"revenue-split": "\f1ab",
|
||||
"revote": "\f1ac",
|
||||
"save-story": "\f1ad",
|
||||
"saved-messages": "\f1ae",
|
||||
"schedule": "\f1af",
|
||||
"search": "\f1b0",
|
||||
"select": "\f1b1",
|
||||
"send-outline": "\f1b2",
|
||||
"send": "\f1b3",
|
||||
"settings-filled": "\f1b4",
|
||||
"settings": "\f1b5",
|
||||
"share-filled": "\f1b6",
|
||||
"share-screen-outlined": "\f1b7",
|
||||
"share-screen-stop": "\f1b8",
|
||||
"share-screen": "\f1b9",
|
||||
"show-message": "\f1ba",
|
||||
"sidebar": "\f1bb",
|
||||
"skip-next": "\f1bc",
|
||||
"skip-previous": "\f1bd",
|
||||
"smallscreen": "\f1be",
|
||||
"smile": "\f1bf",
|
||||
"sort": "\f1c0",
|
||||
"speaker-muted-story": "\f1c1",
|
||||
"speaker-outline": "\f1c2",
|
||||
"speaker-story": "\f1c3",
|
||||
"speaker": "\f1c4",
|
||||
"spoiler-disable": "\f1c5",
|
||||
"spoiler": "\f1c6",
|
||||
"sport": "\f1c7",
|
||||
"star": "\f1c8",
|
||||
"stars-lock": "\f1c9",
|
||||
"stats": "\f1ca",
|
||||
"stealth-future": "\f1cb",
|
||||
"stealth-past": "\f1cc",
|
||||
"stickers": "\f1cd",
|
||||
"stop-raising-hand": "\f1ce",
|
||||
"stop": "\f1cf",
|
||||
"story-caption": "\f1d0",
|
||||
"story-expired": "\f1d1",
|
||||
"story-priority": "\f1d2",
|
||||
"story-reply": "\f1d3",
|
||||
"strikethrough": "\f1d4",
|
||||
"tag-add": "\f1d5",
|
||||
"tag-crossed": "\f1d6",
|
||||
"tag-filter": "\f1d7",
|
||||
"tag-name": "\f1d8",
|
||||
"tag": "\f1d9",
|
||||
"timer": "\f1da",
|
||||
"toncoin": "\f1db",
|
||||
"transcribe": "\f1dc",
|
||||
"truck": "\f1dd",
|
||||
"unarchive": "\f1de",
|
||||
"underlined": "\f1df",
|
||||
"unlock-badge": "\f1e0",
|
||||
"unlock": "\f1e1",
|
||||
"unmute": "\f1e2",
|
||||
"unpin": "\f1e3",
|
||||
"unread": "\f1e4",
|
||||
"up": "\f1e5",
|
||||
"user-filled": "\f1e6",
|
||||
"user-online": "\f1e7",
|
||||
"user": "\f1e8",
|
||||
"video-outlined": "\f1e9",
|
||||
"video-stop": "\f1ea",
|
||||
"video": "\f1eb",
|
||||
"view-once": "\f1ec",
|
||||
"voice-chat": "\f1ed",
|
||||
"volume-1": "\f1ee",
|
||||
"volume-2": "\f1ef",
|
||||
"volume-3": "\f1f0",
|
||||
"web": "\f1f1",
|
||||
"webapp": "\f1f2",
|
||||
"word-wrap": "\f1f3",
|
||||
"zoom-in": "\f1f4",
|
||||
"zoom-out": "\f1f5",
|
||||
"auction": "\f114",
|
||||
"author-hidden": "\f115",
|
||||
"avatar-archived-chats": "\f116",
|
||||
"avatar-deleted-account": "\f117",
|
||||
"avatar-saved-messages": "\f118",
|
||||
"bold": "\f119",
|
||||
"boost-outline": "\f11a",
|
||||
"boost": "\f11b",
|
||||
"boostcircle": "\f11c",
|
||||
"boosts": "\f11d",
|
||||
"bot-command": "\f11e",
|
||||
"bot-commands-filled": "\f11f",
|
||||
"bots": "\f120",
|
||||
"bug": "\f121",
|
||||
"calendar-filter": "\f122",
|
||||
"calendar": "\f123",
|
||||
"camera-add": "\f124",
|
||||
"camera": "\f125",
|
||||
"car": "\f126",
|
||||
"card": "\f127",
|
||||
"cash-circle": "\f128",
|
||||
"channel-filled": "\f129",
|
||||
"channel": "\f12a",
|
||||
"channelviews": "\f12b",
|
||||
"chat-badge": "\f12c",
|
||||
"chats-badge": "\f12d",
|
||||
"check": "\f12e",
|
||||
"clock-edit": "\f12f",
|
||||
"clock": "\f130",
|
||||
"close-circle": "\f131",
|
||||
"close-topic": "\f132",
|
||||
"close": "\f133",
|
||||
"cloud-download": "\f134",
|
||||
"collapse-modal": "\f135",
|
||||
"collapse": "\f136",
|
||||
"colorize": "\f137",
|
||||
"comments-sticker": "\f138",
|
||||
"comments": "\f139",
|
||||
"copy-media": "\f13a",
|
||||
"copy": "\f13b",
|
||||
"darkmode": "\f13c",
|
||||
"data": "\f13d",
|
||||
"delete-filled": "\f13e",
|
||||
"delete-left": "\f13f",
|
||||
"delete-user": "\f140",
|
||||
"delete": "\f141",
|
||||
"diamond": "\f142",
|
||||
"document": "\f143",
|
||||
"double-badge": "\f144",
|
||||
"down": "\f145",
|
||||
"download": "\f146",
|
||||
"eats": "\f147",
|
||||
"edit": "\f148",
|
||||
"email": "\f149",
|
||||
"enter": "\f14a",
|
||||
"expand-modal": "\f14b",
|
||||
"expand": "\f14c",
|
||||
"eye-closed-outline": "\f14d",
|
||||
"eye-closed": "\f14e",
|
||||
"eye-outline": "\f14f",
|
||||
"eye": "\f150",
|
||||
"favorite-filled": "\f151",
|
||||
"favorite": "\f152",
|
||||
"file-badge": "\f153",
|
||||
"flag": "\f154",
|
||||
"folder-badge": "\f155",
|
||||
"folder": "\f156",
|
||||
"fontsize": "\f157",
|
||||
"forums": "\f158",
|
||||
"forward": "\f159",
|
||||
"fullscreen": "\f15a",
|
||||
"gifs": "\f15b",
|
||||
"gift": "\f15c",
|
||||
"group-filled": "\f15d",
|
||||
"group": "\f15e",
|
||||
"grouped-disable": "\f15f",
|
||||
"grouped": "\f160",
|
||||
"hand-stop": "\f161",
|
||||
"hashtag": "\f162",
|
||||
"heart-outline": "\f163",
|
||||
"heart": "\f164",
|
||||
"help": "\f165",
|
||||
"info-filled": "\f166",
|
||||
"info": "\f167",
|
||||
"install": "\f168",
|
||||
"italic": "\f169",
|
||||
"key": "\f16a",
|
||||
"keyboard": "\f16b",
|
||||
"lamp": "\f16c",
|
||||
"language": "\f16d",
|
||||
"large-pause": "\f16e",
|
||||
"large-play": "\f16f",
|
||||
"link-badge": "\f170",
|
||||
"link-broken": "\f171",
|
||||
"link": "\f172",
|
||||
"location": "\f173",
|
||||
"lock-badge": "\f174",
|
||||
"lock": "\f175",
|
||||
"logout": "\f176",
|
||||
"loop": "\f177",
|
||||
"mention": "\f178",
|
||||
"message-failed": "\f179",
|
||||
"message-pending": "\f17a",
|
||||
"message-read": "\f17b",
|
||||
"message-succeeded": "\f17c",
|
||||
"message": "\f17d",
|
||||
"microphone-alt": "\f17e",
|
||||
"microphone": "\f17f",
|
||||
"monospace": "\f180",
|
||||
"more-circle": "\f181",
|
||||
"more": "\f182",
|
||||
"move-caption-down": "\f183",
|
||||
"move-caption-up": "\f184",
|
||||
"mute": "\f185",
|
||||
"muted": "\f186",
|
||||
"my-notes": "\f187",
|
||||
"new-chat-filled": "\f188",
|
||||
"next": "\f189",
|
||||
"nochannel": "\f18a",
|
||||
"noise-suppression": "\f18b",
|
||||
"non-contacts": "\f18c",
|
||||
"one-filled": "\f18d",
|
||||
"open-in-new-tab": "\f18e",
|
||||
"password-off": "\f18f",
|
||||
"pause": "\f190",
|
||||
"permissions": "\f191",
|
||||
"phone-discard-outline": "\f192",
|
||||
"phone-discard": "\f193",
|
||||
"phone": "\f194",
|
||||
"photo": "\f195",
|
||||
"pin-badge": "\f196",
|
||||
"pin-list": "\f197",
|
||||
"pin": "\f198",
|
||||
"pinned-chat": "\f199",
|
||||
"pinned-message": "\f19a",
|
||||
"pip": "\f19b",
|
||||
"play-story": "\f19c",
|
||||
"play": "\f19d",
|
||||
"poll": "\f19e",
|
||||
"previous": "\f19f",
|
||||
"privacy-policy": "\f1a0",
|
||||
"quote-text": "\f1a1",
|
||||
"quote": "\f1a2",
|
||||
"readchats": "\f1a3",
|
||||
"recent": "\f1a4",
|
||||
"reload": "\f1a5",
|
||||
"remove-quote": "\f1a6",
|
||||
"remove": "\f1a7",
|
||||
"reopen-topic": "\f1a8",
|
||||
"replace": "\f1a9",
|
||||
"replies": "\f1aa",
|
||||
"reply-filled": "\f1ab",
|
||||
"reply": "\f1ac",
|
||||
"revenue-split": "\f1ad",
|
||||
"revote": "\f1ae",
|
||||
"save-story": "\f1af",
|
||||
"saved-messages": "\f1b0",
|
||||
"schedule": "\f1b1",
|
||||
"search": "\f1b2",
|
||||
"select": "\f1b3",
|
||||
"send-outline": "\f1b4",
|
||||
"send": "\f1b5",
|
||||
"settings-filled": "\f1b6",
|
||||
"settings": "\f1b7",
|
||||
"share-filled": "\f1b8",
|
||||
"share-screen-outlined": "\f1b9",
|
||||
"share-screen-stop": "\f1ba",
|
||||
"share-screen": "\f1bb",
|
||||
"show-message": "\f1bc",
|
||||
"sidebar": "\f1bd",
|
||||
"skip-next": "\f1be",
|
||||
"skip-previous": "\f1bf",
|
||||
"smallscreen": "\f1c0",
|
||||
"smile": "\f1c1",
|
||||
"sort": "\f1c2",
|
||||
"speaker-muted-story": "\f1c3",
|
||||
"speaker-outline": "\f1c4",
|
||||
"speaker-story": "\f1c5",
|
||||
"speaker": "\f1c6",
|
||||
"spoiler-disable": "\f1c7",
|
||||
"spoiler": "\f1c8",
|
||||
"sport": "\f1c9",
|
||||
"star": "\f1ca",
|
||||
"stars-lock": "\f1cb",
|
||||
"stats": "\f1cc",
|
||||
"stealth-future": "\f1cd",
|
||||
"stealth-past": "\f1ce",
|
||||
"stickers": "\f1cf",
|
||||
"stop-raising-hand": "\f1d0",
|
||||
"stop": "\f1d1",
|
||||
"story-caption": "\f1d2",
|
||||
"story-expired": "\f1d3",
|
||||
"story-priority": "\f1d4",
|
||||
"story-reply": "\f1d5",
|
||||
"strikethrough": "\f1d6",
|
||||
"tag-add": "\f1d7",
|
||||
"tag-crossed": "\f1d8",
|
||||
"tag-filter": "\f1d9",
|
||||
"tag-name": "\f1da",
|
||||
"tag": "\f1db",
|
||||
"timer": "\f1dc",
|
||||
"toncoin": "\f1dd",
|
||||
"trade": "\f1de",
|
||||
"transcribe": "\f1df",
|
||||
"truck": "\f1e0",
|
||||
"unarchive": "\f1e1",
|
||||
"underlined": "\f1e2",
|
||||
"unlock-badge": "\f1e3",
|
||||
"unlock": "\f1e4",
|
||||
"unmute": "\f1e5",
|
||||
"unpin": "\f1e6",
|
||||
"unread": "\f1e7",
|
||||
"up": "\f1e8",
|
||||
"user-filled": "\f1e9",
|
||||
"user-online": "\f1ea",
|
||||
"user": "\f1eb",
|
||||
"video-outlined": "\f1ec",
|
||||
"video-stop": "\f1ed",
|
||||
"video": "\f1ee",
|
||||
"view-once": "\f1ef",
|
||||
"voice-chat": "\f1f0",
|
||||
"volume-1": "\f1f1",
|
||||
"volume-2": "\f1f2",
|
||||
"volume-3": "\f1f3",
|
||||
"web": "\f1f4",
|
||||
"webapp": "\f1f5",
|
||||
"word-wrap": "\f1f6",
|
||||
"zoom-in": "\f1f7",
|
||||
"zoom-out": "\f1f8",
|
||||
);
|
||||
|
||||
.icon-active-sessions::before {
|
||||
@ -333,6 +336,9 @@ $icons-map: (
|
||||
.icon-attach::before {
|
||||
content: map.get($icons-map, "attach");
|
||||
}
|
||||
.icon-auction::before {
|
||||
content: map.get($icons-map, "auction");
|
||||
}
|
||||
.icon-author-hidden::before {
|
||||
content: map.get($icons-map, "author-hidden");
|
||||
}
|
||||
@ -468,6 +474,9 @@ $icons-map: (
|
||||
.icon-delete::before {
|
||||
content: map.get($icons-map, "delete");
|
||||
}
|
||||
.icon-diamond::before {
|
||||
content: map.get($icons-map, "diamond");
|
||||
}
|
||||
.icon-document::before {
|
||||
content: map.get($icons-map, "document");
|
||||
}
|
||||
@ -933,6 +942,9 @@ $icons-map: (
|
||||
.icon-toncoin::before {
|
||||
content: map.get($icons-map, "toncoin");
|
||||
}
|
||||
.icon-trade::before {
|
||||
content: map.get($icons-map, "trade");
|
||||
}
|
||||
.icon-transcribe::before {
|
||||
content: map.get($icons-map, "transcribe");
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -18,6 +18,7 @@ export type FontIconName =
|
||||
| 'arrow-right'
|
||||
| 'ask-support'
|
||||
| 'attach'
|
||||
| 'auction'
|
||||
| 'author-hidden'
|
||||
| 'avatar-archived-chats'
|
||||
| 'avatar-deleted-account'
|
||||
@ -63,6 +64,7 @@ export type FontIconName =
|
||||
| 'delete-left'
|
||||
| 'delete-user'
|
||||
| 'delete'
|
||||
| 'diamond'
|
||||
| 'document'
|
||||
| 'double-badge'
|
||||
| 'down'
|
||||
@ -218,6 +220,7 @@ export type FontIconName =
|
||||
| 'tag'
|
||||
| 'timer'
|
||||
| 'toncoin'
|
||||
| 'trade'
|
||||
| 'transcribe'
|
||||
| 'truck'
|
||||
| 'unarchive'
|
||||
|
||||
@ -565,6 +565,7 @@ export type StarGiftInfo = {
|
||||
gift: ApiStarGiftRegular;
|
||||
shouldHideName?: boolean;
|
||||
message?: ApiFormattedText;
|
||||
shouldUpgrade?: boolean;
|
||||
};
|
||||
|
||||
export interface TabThread {
|
||||
|
||||
64
src/types/language.d.ts
vendored
64
src/types/language.d.ts
vendored
@ -1164,15 +1164,15 @@ export interface LangPair {
|
||||
'GiftInfoSent': undefined;
|
||||
'GiftInfoReceived': undefined;
|
||||
'GiftInfoTitle': undefined;
|
||||
'GiftInfoDescriptionFreeUpgrade': undefined;
|
||||
'GiftInfoDescriptionUpgraded': undefined;
|
||||
'GiftInfoFrom': undefined;
|
||||
'GiftInfoDate': undefined;
|
||||
'GiftInfoValue': undefined;
|
||||
'GiftInfoMakeVisible': undefined;
|
||||
'GiftInfoMakeInvisible': undefined;
|
||||
'GiftInfoConvertTitle': undefined;
|
||||
'GiftInfoConvertDescription2': undefined;
|
||||
'GiftInfoSavedView': undefined;
|
||||
'GiftInfoHidden': undefined;
|
||||
'GiftInfoSavedHide': undefined;
|
||||
'GiftInfoSavedShow': undefined;
|
||||
'GiftInfoAvailability': undefined;
|
||||
'GiftInfoFirstSale': undefined;
|
||||
'GiftInfoLastSale': undefined;
|
||||
@ -1186,6 +1186,21 @@ export interface LangPair {
|
||||
'GiftInfoStatus': undefined;
|
||||
'GiftInfoStatusNonUnique': undefined;
|
||||
'GiftInfoViewUpgraded': undefined;
|
||||
'GiftInfoUpgradeBadge': undefined;
|
||||
'GiftInfoUpgradeForFree': undefined;
|
||||
'GiftUpgradeUniqueTitle': undefined;
|
||||
'GiftUpgradeUniqueDescription': undefined;
|
||||
'GiftUpgradeTransferableTitle': undefined;
|
||||
'GiftUpgradeTransferableDescription': undefined;
|
||||
'GiftUpgradeTradeableTitle': undefined;
|
||||
'GiftUpgradeTradeableDescription': undefined;
|
||||
'GiftUpgradeTitle': undefined;
|
||||
'GiftUpgradeTextOwn': undefined;
|
||||
'GiftUpgradeKeepDetails': undefined;
|
||||
'GiftUpgradedTitle': undefined;
|
||||
'GiftUpgradedDescription': undefined;
|
||||
'GiftMakeUniqueAcc': undefined;
|
||||
'GiftMakeUniqueLink': undefined;
|
||||
'AllGiftsCategory': undefined;
|
||||
'LimitedGiftsCategory': undefined;
|
||||
'StockGiftsCategory': undefined;
|
||||
@ -1200,12 +1215,6 @@ export interface LangPair {
|
||||
'GiftFrom': undefined;
|
||||
'ReceivedGift': undefined;
|
||||
'SentGift': undefined;
|
||||
'StarGiftInfoLinkCaption': undefined;
|
||||
'StarGiftDisplayOnMyPage': undefined;
|
||||
'StarGiftConvertTo': undefined;
|
||||
'StarGiftHideFromMyPage': undefined;
|
||||
'StarGiftSenderPrivacyNote': undefined;
|
||||
'StarGiftAvailability': undefined;
|
||||
'StarsSubscribeInfoLinkText': undefined;
|
||||
'StarsSubscribeInfoLink': undefined;
|
||||
'StarsBalance': undefined;
|
||||
@ -1629,6 +1638,9 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
|
||||
'GiftSend': {
|
||||
'amount': V;
|
||||
};
|
||||
'GiftInfoDescriptionFreeUpgradeOut': {
|
||||
'user': V;
|
||||
};
|
||||
'GiftInfoConvertDescription1': {
|
||||
'user': V;
|
||||
'amount': V;
|
||||
@ -1636,6 +1648,9 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
|
||||
'GiftInfoSaved': {
|
||||
'link': V;
|
||||
};
|
||||
'GiftInfoHidden': {
|
||||
'link': V;
|
||||
};
|
||||
'GiftInfoIssued': {
|
||||
'issued': V;
|
||||
'total': V;
|
||||
@ -1663,6 +1678,19 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
|
||||
'date': V;
|
||||
'text': V;
|
||||
};
|
||||
'GiftUpgradeText': {
|
||||
'peer': V;
|
||||
};
|
||||
'GiftUpgradeButton': {
|
||||
'amount': V;
|
||||
};
|
||||
'GiftMakeUnique': {
|
||||
'stars': V;
|
||||
};
|
||||
'GiftMakeUniqueDescription': {
|
||||
'user': V;
|
||||
'link': V;
|
||||
};
|
||||
'StarsAmount': {
|
||||
'amount': V;
|
||||
};
|
||||
@ -1695,19 +1723,6 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
|
||||
'ActionStarGiftOutDescriptionUpgrade': {
|
||||
'user': V;
|
||||
};
|
||||
'StarGiftInfoDescriptionInbound': {
|
||||
'count': V;
|
||||
'link': V;
|
||||
};
|
||||
'StarGiftInfoDescriptionOutgoing': {
|
||||
'user': V;
|
||||
'count': V;
|
||||
'link': V;
|
||||
};
|
||||
'StarGiftAvailabilityValue': {
|
||||
'number': V;
|
||||
'total': V;
|
||||
};
|
||||
'StarsSubscribeInfo': {
|
||||
'link': V;
|
||||
};
|
||||
@ -1917,6 +1932,9 @@ export interface LangPairPluralWithVariables<V extends unknown = LangVariable> {
|
||||
'user': V;
|
||||
'amount': V;
|
||||
};
|
||||
'GiftInfoDescriptionUpgrade': {
|
||||
'amount': V;
|
||||
};
|
||||
'GiftInfoDescriptionConverted': {
|
||||
'amount': V;
|
||||
};
|
||||
|
||||
@ -3,6 +3,7 @@ import React from '../../lib/teact/teact';
|
||||
import type { LangFn } from './types';
|
||||
|
||||
import { STARS_ICON_PLACEHOLDER } from '../../config';
|
||||
import buildClassName from '../buildClassName';
|
||||
|
||||
import Icon from '../../components/common/icons/Icon';
|
||||
import StarIcon from '../../components/common/icons/StarIcon';
|
||||
@ -11,10 +12,11 @@ export function formatStarsAsText(lang: LangFn, amount: number) {
|
||||
return lang('StarsAmountText', { amount }, { pluralValue: amount });
|
||||
}
|
||||
|
||||
export function formatStarsAsIcon(lang: LangFn, amount: number, asFont?: boolean) {
|
||||
export function formatStarsAsIcon(lang: LangFn, amount: number, options?: { asFont?: boolean; className?: string }) {
|
||||
const { asFont, className } = options || {};
|
||||
const icon = asFont
|
||||
? <Icon name="star" className="star-amount-icon" />
|
||||
: <StarIcon type="gold" className="star-amount-icon" size="adaptive" />;
|
||||
? <Icon name="star" className={buildClassName('star-amount-icon', className)} />
|
||||
: <StarIcon type="gold" className={buildClassName('star-amount-icon', className)} size="adaptive" />;
|
||||
return lang('StarsAmount', { amount }, {
|
||||
withNodes: true,
|
||||
specialReplacement: {
|
||||
|
||||
@ -359,8 +359,8 @@ function getNotificationContent(chat: ApiChat, message: ApiMessage, reaction?: A
|
||||
body = renderActionMessageText(
|
||||
oldTranslate,
|
||||
message,
|
||||
!isChat ? messageSenderUser : undefined,
|
||||
isChat ? chat : undefined,
|
||||
messageSenderUser,
|
||||
chat,
|
||||
actionTargetUsers,
|
||||
actionTargetMessage,
|
||||
actionTargetChatId,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user