From 1eb030b2d8ffeeb19e77342ee42cd13293a8c715 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Wed, 31 Aug 2022 15:00:36 +0200 Subject: [PATCH] Introduce Gift Premium (#1967) --- src/api/gramjs/apiBuilders/messages.ts | 15 + src/api/gramjs/methods/index.ts | 2 +- src/api/gramjs/methods/symbols.ts | 15 + src/api/types/messages.ts | 1 + src/assets/fonts/icomoon.woff | Bin 48392 -> 49364 bytes src/assets/fonts/icomoon.woff2 | Bin 22788 -> 23192 bytes src/assets/mir.svg | 1 + src/bundles/extra.ts | 1 + .../common/helpers/detectCardType.ts | 6 + .../helpers/renderActionMessageText.tsx | 19 + src/components/main/Main.tsx | 3 + .../main/premium/GiftOption.module.scss | 110 +++++ src/components/main/premium/GiftOption.tsx | 64 +++ .../main/premium/GiftPremiumModal.async.tsx | 17 + .../main/premium/GiftPremiumModal.module.scss | 44 ++ .../main/premium/GiftPremiumModal.tsx | 166 ++++++++ .../premium/PremiumFeatureItem.module.scss | 6 +- .../premium/PremiumFeatureModal.module.scss | 18 +- .../main/premium/PremiumMainModal.module.scss | 16 +- .../main/premium/PremiumMainModal.tsx | 74 ++-- src/components/middle/ActionMessage.tsx | 75 +++- src/components/middle/HeaderMenuContainer.tsx | 24 +- src/components/middle/MessageList.scss | 25 ++ src/components/middle/MessageListContent.tsx | 2 + src/components/middle/MiddleColumn.tsx | 5 + src/components/payment/CardInput.tsx | 3 + src/components/ui/Link.module.scss | 19 + src/components/ui/Link.scss | 11 - src/components/ui/Link.tsx | 7 +- src/global/actions/api/chats.ts | 4 + src/global/actions/api/payments.ts | 33 +- src/global/actions/api/symbols.ts | 14 + src/global/actions/apiUpdaters/payments.ts | 8 +- src/global/types.ts | 21 + src/styles/Telegram T.json | 385 ++++++++++-------- src/styles/icons.scss | 3 + src/util/langProvider.ts | 6 +- 37 files changed, 974 insertions(+), 249 deletions(-) create mode 100644 src/assets/mir.svg create mode 100644 src/components/main/premium/GiftOption.module.scss create mode 100644 src/components/main/premium/GiftOption.tsx create mode 100644 src/components/main/premium/GiftPremiumModal.async.tsx create mode 100644 src/components/main/premium/GiftPremiumModal.module.scss create mode 100644 src/components/main/premium/GiftPremiumModal.tsx create mode 100644 src/components/ui/Link.module.scss delete mode 100644 src/components/ui/Link.scss diff --git a/src/api/gramjs/apiBuilders/messages.ts b/src/api/gramjs/apiBuilders/messages.ts index ae3abd7d9..e5319ac88 100644 --- a/src/api/gramjs/apiBuilders/messages.ts +++ b/src/api/gramjs/apiBuilders/messages.ts @@ -813,6 +813,7 @@ function buildAction( let type: ApiAction['type'] = 'other'; let photo: ApiPhoto | undefined; let score: number | undefined; + let months: number | undefined; const targetUserIds = 'users' in action ? action.users && action.users.map((id) => buildApiPeerId(id, 'user')) @@ -944,6 +945,19 @@ function buildAction( } else if (action instanceof GramJs.MessageActionWebViewDataSent) { text = 'Notification.WebAppSentData'; translationValues.push(action.text); + } else if (action instanceof GramJs.MessageActionGiftPremium) { + text = isOutgoing ? 'ActionGiftOutbound' : 'ActionGiftInbound'; + if (isOutgoing) { + translationValues.push('%gift_payment_amount%'); + } else { + translationValues.push('%action_origin%', '%gift_payment_amount%'); + } + if (targetPeerId) { + targetUserIds.push(targetPeerId); + } + currency = action.currency; + amount = action.amount.toJSNumber(); + months = action.months; } else { text = 'ChatList.UnsupportedMessage'; } @@ -965,6 +979,7 @@ function buildAction( call, phoneCall, score, + months, }; } diff --git a/src/api/gramjs/methods/index.ts b/src/api/gramjs/methods/index.ts index c1bab2ee6..6b3249733 100644 --- a/src/api/gramjs/methods/index.ts +++ b/src/api/gramjs/methods/index.ts @@ -41,7 +41,7 @@ export { fetchStickerSets, fetchRecentStickers, fetchFavoriteStickers, fetchFeaturedStickers, faveSticker, fetchStickers, fetchSavedGifs, saveGif, searchStickers, installStickerSet, uninstallStickerSet, searchGifs, fetchAnimatedEmojis, fetchStickersForEmoji, fetchEmojiKeywords, fetchAnimatedEmojiEffects, - removeRecentSticker, clearRecentStickers, + removeRecentSticker, clearRecentStickers, fetchPremiumGifts, } from './symbols'; export { diff --git a/src/api/gramjs/methods/symbols.ts b/src/api/gramjs/methods/symbols.ts index d8d7fa04c..27320b2f0 100644 --- a/src/api/gramjs/methods/symbols.ts +++ b/src/api/gramjs/methods/symbols.ts @@ -163,6 +163,21 @@ export async function fetchAnimatedEmojiEffects() { }; } +export async function fetchPremiumGifts() { + const result = await invokeRequest(new GramJs.messages.GetStickerSet({ + stickerset: new GramJs.InputStickerSetPremiumGifts(), + })); + + if (!(result instanceof GramJs.messages.StickerSet)) { + return undefined; + } + + return { + set: buildStickerSet(result.set), + stickers: processStickerResult(result.documents), + }; +} + export async function searchStickers({ query, hash = '0' }: { query: string; hash?: string }) { const result = await invokeRequest(new GramJs.messages.SearchStickerSets({ q: query, diff --git a/src/api/types/messages.ts b/src/api/types/messages.ts index 4e043b3a7..34a325efc 100644 --- a/src/api/types/messages.ts +++ b/src/api/types/messages.ts @@ -235,6 +235,7 @@ export interface ApiAction { call?: Partial; phoneCall?: PhoneCallAction; score?: number; + months?: number; } export interface ApiWebPage { diff --git a/src/assets/fonts/icomoon.woff b/src/assets/fonts/icomoon.woff index c4d15655ab5d5c233773bda057201cb21b334de8..aa72514772a82226b47279cb56cc73b1e09f764e 100644 GIT binary patch delta 1485 zcmbtUO>7%Q6rMM;JG)-TfBWlAnmXQ1Y$(O?Uu@H2qoOtvKW#50;($RWP2xjCgIcNO zv@M6K*D9BCfD=7Hl}pn?3W=zoNN^?<6^eigi3l-8*{?8Fu`fbfVzuO2lW)?b&gg_UGmqa+z-&E&2#|5^A zxw;j}`J->mA$Eh1Rm4}J4e3mB8b>3=A$B%8`5HT;lwG# zHVL6$iCDk&+%HFu&0t+?{e2V_!gCkDJXu)ioWjAM4PfI)7}sI*jn2X>V!N^CtcZ7> zkNmlK?Dz@1&z19k9fswl7vTk1Ubz5oUI`ePBA3`Q{gA}TFu@)pTdqx1bAHz2mT6a< z2UF|8^fV(zI&J(N?hF&h!NhbN^ZqlPatwhP&P}n2Fp3MQa&1d5+b6ODvr*KFLxA!=csVp!tCVdt$bG@zUs|iDLeff^ z99w+0OIQ;Z##IwSD5CIO9=SRi>=P}RD1<~D@}WN_N(%4{w8Frnukau@4xv^B#RP?F z84yvnaaIE2c(ggTjzi8*|zK9_3a>(;ynj*pLxm?>6{N+c3d2?55wx zQm*?uXd!#gh*4M9(@LxSE8|QJJfLY)-&brjV<{du&QcNR&dH z8L_rF$gG>p3}iW#nZjn}2+gy&BFT`a5qVbCfU$!TgEXj$q)5}UCc`w|+f63*aU+=o zH>JBnuH6VSnY!%`_TF{%Md2~rQf?vvW5Rmx7G+Rw&_h6XJT|m%c<`ynfSa`TW{WR# zh^VSM35p6*aWH98V3P7g!uBJv-scY+_0UPd{~9Ir+Eq#7c*APk;ZIU7QKmCBIwU7K zV=8dDt#U?XsV#F*2ULl(XPL%dS7Q_?t>S|*8a}i@$U*1q2d^cbzDuH#coE1C-uHXA w|4To9RENte>5spl@)XhsRyMEAfOX`RSFr+n$z}Ks-w^Rpe5Q?+nNKgmzh(38)&Kwi delta 505 zcmcc8$lURZNvz!8&5ePP0SNYTFmQwDJ$o1!Cm%c@JW*4u{&I3|VgUmKV+K$>1cb%I zE*qyO7K6n00QnqHERdd4nFbU)!oaZQ2MA|`y1&UtO-x~6*alK(2EvLaryDbXfcP z+X1Li0gU%E-pNbMO$CZ20M)dC@Juhx-v#-_B|v|?nE1z^am{2OMsLP7n`bZM;2IxwlSAlqn*6X$L{5D@1xLJS#3=H?VoTtO+$xC*bGj7~`XV+mSM$^qp_9in5 Y)`0bGWW2?|3s%kqiqg&c`28wZXD8z`G)LWtWT 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%0Dsg)ad26-YmbD{W>4TiM2% z$1&aLOjr2OaNq3KxvRVGXf$j;FEHUm%2(NGzch6qS@! zRMj+V(W*_m4xPGm>(Q%EzX5}W3>z_O%(w}YrpU-CD5TBuSE#BuSDaNs<}>00000K$0X$k|Zf2A|fIpA|j%ys;a80s;X*cW@ct)W@hF@ Prv_YZ4=8Gm*Vp+0N7hz| literal 22788 zcmV)0K+eB+Pew8T0RR9109gb84FCWD0L1hF09dI20RR9100000000000000000000 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 bh=_=Y00000003CA>Oj*ClUQKc%>w`cm-G?w diff --git a/src/assets/mir.svg b/src/assets/mir.svg new file mode 100644 index 000000000..e0ce80883 --- /dev/null +++ b/src/assets/mir.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/bundles/extra.ts b/src/bundles/extra.ts index f4c34825f..e2dcb09f9 100644 --- a/src/bundles/extra.ts +++ b/src/bundles/extra.ts @@ -13,6 +13,7 @@ export { default as BotTrustModal } from '../components/main/BotTrustModal'; export { default as BotAttachModal } from '../components/main/BotAttachModal'; export { default as DeleteFolderDialog } from '../components/main/DeleteFolderDialog'; export { default as PremiumMainModal } from '../components/main/premium/PremiumMainModal'; +export { default as GiftPremiumModal } from '../components/main/premium/GiftPremiumModal'; export { default as PremiumLimitReachedModal } from '../components/main/premium/common/PremiumLimitReachedModal'; export { default as AboutAdsModal } from '../components/common/AboutAdsModal'; diff --git a/src/components/common/helpers/detectCardType.ts b/src/components/common/helpers/detectCardType.ts index 7002e93fd..34f6df6ef 100644 --- a/src/components/common/helpers/detectCardType.ts +++ b/src/components/common/helpers/detectCardType.ts @@ -1,17 +1,20 @@ const VISA = /^4[0-9]{12}(?:[0-9]{1,3})?$/; const MASTERCARD1 = /^5[1-5][0-9]{11,14}$/; const MASTERCARD2 = /^2[2-7][0-9]{11,14}$/; +const MIR = /^220[0-4]/; export enum CardType { Default, Visa, Mastercard, + Mir, } const cards: Record = { [CardType.Default]: '', [CardType.Visa]: 'visa', [CardType.Mastercard]: 'mastercard', + [CardType.Mir]: 'mir', }; export function detectCardType(cardNumber: string): number { @@ -19,6 +22,9 @@ export function detectCardType(cardNumber: string): number { if (VISA.test(cardNumber)) { return CardType.Visa; } + if (MIR.test(cardNumber)) { + return CardType.Mir; + } if (MASTERCARD1.test(cardNumber) || MASTERCARD2.test(cardNumber)) { return CardType.Mastercard; } diff --git a/src/components/common/helpers/renderActionMessageText.tsx b/src/components/common/helpers/renderActionMessageText.tsx index 90b04b88c..2f9a5e992 100644 --- a/src/components/common/helpers/renderActionMessageText.tsx +++ b/src/components/common/helpers/renderActionMessageText.tsx @@ -55,6 +55,15 @@ export function renderActionMessageText( if (translationKey.includes('ScoredInGame')) { // Translation hack for games unprocessed = unprocessed.replace('un1', '%action_origin%').replace('un2', '%message%'); } + if (translationKey === 'ActionGiftOutbound') { // Translation hack for Premium Gift + unprocessed = unprocessed.replace('un2', '%gift_payment_amount%').replace(/\*\*/g, ''); + } + if (translationKey === 'ActionGiftInbound') { // Translation hack for Premium Gift + unprocessed = unprocessed + .replace('un1', '%action_origin%') + .replace('un2', '%gift_payment_amount%') + .replace(/\*\*/g, ''); + } let processed: TextPart[]; if (unprocessed.includes('%payment_amount%')) { @@ -80,6 +89,16 @@ export function renderActionMessageText( unprocessed = processed.pop() as string; content.push(...processed); + if (unprocessed.includes('%gift_payment_amount%')) { + processed = processPlaceholder( + unprocessed, + '%gift_payment_amount%', + formatCurrency(amount!, currency!, lang.code), + ); + unprocessed = processed.pop() as string; + content.push(...processed); + } + if (unprocessed.includes('%score%')) { processed = processPlaceholder( unprocessed, diff --git a/src/components/main/Main.tsx b/src/components/main/Main.tsx index 772bd2ed8..d93d9ee9d 100644 --- a/src/components/main/Main.tsx +++ b/src/components/main/Main.tsx @@ -169,6 +169,7 @@ const Main: FC = ({ loadCountryList, loadAvailableReactions, loadStickerSets, + loadPremiumGifts, loadAddedStickers, loadFavoriteStickers, ensureTimeFormat, @@ -206,10 +207,12 @@ const Main: FC = ({ loadEmojiKeywords({ language: BASE_EMOJI_KEYWORD_LANG }); loadAttachMenuBots(); loadContactList(); + loadPremiumGifts(); } }, [ lastSyncTime, loadAnimatedEmojis, loadEmojiKeywords, loadNotificationExceptions, loadNotificationSettings, loadTopInlineBots, updateIsOnline, loadAvailableReactions, loadAppConfig, loadAttachMenuBots, loadContactList, + loadPremiumGifts, ]); // Language-based API calls diff --git a/src/components/main/premium/GiftOption.module.scss b/src/components/main/premium/GiftOption.module.scss new file mode 100644 index 000000000..e29731157 --- /dev/null +++ b/src/components/main/premium/GiftOption.module.scss @@ -0,0 +1,110 @@ +.wrapper { + position: relative; + display: block; + padding-inline: 4.5rem 1rem; + margin-bottom: 1.5rem; + border-radius: var(--border-radius-default); + background: var(--color-background); + box-shadow: 0 0 0 0.0625rem var(--color-borders-input); + + cursor: pointer; + + line-height: 1.5rem; +} + +.active { + box-shadow: 0 0 0 0.125rem var(--color-primary); +} + +.input { + position: absolute; + z-index: var(--z-below); + opacity: 0; + + &:checked ~ .content { + &::before { + border-color: var(--color-primary); + } + + &::after { + opacity: 1; + } + } +} + +.content { + display: grid; + grid-template-areas: "left_top right" "left_bottom right"; + grid-template-columns: 1fr auto; + justify-content: start; + padding: 0.5rem 0; + gap: 0.25rem; + + &::before, + &::after { + content: ""; + display: block; + position: absolute; + inset-inline-start: 1.0625rem; + top: 50%; + width: 1.25rem; + height: 1.25rem; + transform: translateY(-50%); + } + + &::before { + border: 2px solid var(--color-borders-input); + border-radius: 50%; + background-color: var(--color-background); + opacity: 1; + transition: border-color 0.1s ease, opacity 0.1s ease; + } + + &::after { + inset-inline-start: 1.375rem; + width: 0.625rem; + height: 0.625rem; + border-radius: 50%; + background: var(--color-primary); + opacity: 0; + transition: opacity 0.1s ease; + } +} + +.month { + grid-area: left_top; + white-space: nowrap; +} + +.perMonth { + grid-area: left_bottom; + align-self: end; + display: flex; + flex-direction: row-reverse; + margin-inline-end: auto; + + font-size: 0.875rem; + color: var(--color-text-secondary); + + @media (max-width: 450px) { + flex-direction: column-reverse; + } +} + +.amount { + grid-area: right; + align-self: center; + justify-self: end; + padding-inline-start: 1.5rem; + color: var(--color-text-secondary); +} + +.discount { + color: var(--color-white); + background: var(--color-primary); + border-radius: var(--border-radius-default-small); + padding: 0 0.5rem; + unicode-bidi: plaintext; + margin-inline-end: 0.5rem; + align-self: baseline; +} diff --git a/src/components/main/premium/GiftOption.tsx b/src/components/main/premium/GiftOption.tsx new file mode 100644 index 000000000..a2dc12afe --- /dev/null +++ b/src/components/main/premium/GiftOption.tsx @@ -0,0 +1,64 @@ +import type { ChangeEvent } from 'react'; +import React, { memo, useCallback, useMemo } from '../../../lib/teact/teact'; + +import type { FC } from '../../../lib/teact/teact'; +import type { ApiPremiumGiftOption } from '../../../api/types'; + +import { formatCurrency } from '../../../util/formatCurrency'; +import buildClassName from '../../../util/buildClassName'; +import useLang from '../../../hooks/useLang'; + +import styles from './GiftOption.module.scss'; + +type OwnProps = { + option: ApiPremiumGiftOption; + checked?: boolean; + fullMonthlyAmount?: number; + onChange: (month: number) => void; +}; + +const GiftOption: FC = ({ + option, checked, fullMonthlyAmount, onChange, +}) => { + const lang = useLang(); + + const { months, amount, currency } = option; + const perMonth = Math.floor(amount / months); + + const discount = useMemo(() => { + return fullMonthlyAmount && fullMonthlyAmount > perMonth + ? Math.ceil(100 - perMonth / (fullMonthlyAmount / 100)) + : undefined; + }, [fullMonthlyAmount, perMonth]); + + const handleChange = useCallback((e: ChangeEvent) => { + if (e.target.checked) { + onChange(months); + } + }, [months, onChange]); + + return ( + + ); +}; + +export default memo(GiftOption); diff --git a/src/components/main/premium/GiftPremiumModal.async.tsx b/src/components/main/premium/GiftPremiumModal.async.tsx new file mode 100644 index 000000000..1c5e0abd8 --- /dev/null +++ b/src/components/main/premium/GiftPremiumModal.async.tsx @@ -0,0 +1,17 @@ +import type { FC } from '../../../lib/teact/teact'; +import React, { memo } from '../../../lib/teact/teact'; +import { Bundles } from '../../../util/moduleLoader'; + +import type { OwnProps } from './GiftPremiumModal'; + +import useModuleLoader from '../../../hooks/useModuleLoader'; + +const GiftPremiumModalAsync: FC = (props) => { + const { isOpen } = props; + const GiftPremiumModal = useModuleLoader(Bundles.Extra, 'GiftPremiumModal', !isOpen); + + // eslint-disable-next-line react/jsx-props-no-spreading + return GiftPremiumModal ? : undefined; +}; + +export default memo(GiftPremiumModalAsync); diff --git a/src/components/main/premium/GiftPremiumModal.module.scss b/src/components/main/premium/GiftPremiumModal.module.scss new file mode 100644 index 000000000..bfe8e82bb --- /dev/null +++ b/src/components/main/premium/GiftPremiumModal.module.scss @@ -0,0 +1,44 @@ +@media (min-width: 451px) { + .modalDialog :global(.modal-dialog) { + max-width: 32rem !important; + } +} + +.closeButton { + position: absolute; + top: 0.5rem; + left: 0.5rem; +} + +.avatar { + margin: 0 auto 1.5rem; +} + +.headerText { + font-size: 1.5rem; + font-weight: 500; + text-align: center; +} + +.description, +.premiumFeatures { + text-align: center; + margin: 0 auto 2rem; + max-width: 25rem; +} + +.premiumFeatures { + font-size: 0.9375rem; + color: var(--color-text-secondary); +} + +.options { + margin-bottom: 2.5rem; +} + +.button { + height: 3rem; + background: linear-gradient(88.39deg, #6C93FF -2.56%, #976FFF 51.27%, #DF69D1 107.39%); + font-size: 1rem; + font-weight: 600; +} diff --git a/src/components/main/premium/GiftPremiumModal.tsx b/src/components/main/premium/GiftPremiumModal.tsx new file mode 100644 index 000000000..d4f96c777 --- /dev/null +++ b/src/components/main/premium/GiftPremiumModal.tsx @@ -0,0 +1,166 @@ +import React, { + memo, useCallback, useEffect, useMemo, useState, +} from '../../../lib/teact/teact'; +import { getActions, withGlobal } from '../../../global'; + +import type { FC } from '../../../lib/teact/teact'; +import type { ApiPremiumGiftOption, ApiUser } from '../../../api/types'; + +import { formatCurrency } from '../../../util/formatCurrency'; +import renderText from '../../common/helpers/renderText'; +import { getUserFirstOrLastName } from '../../../global/helpers'; +import { selectUser } from '../../../global/selectors'; + +import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev'; +import useLang from '../../../hooks/useLang'; + +import Modal from '../../ui/Modal'; +import Button from '../../ui/Button'; +import Link from '../../ui/Link'; +import Avatar from '../../common/Avatar'; +import GiftOption from './GiftOption'; + +import styles from './GiftPremiumModal.module.scss'; + +export type OwnProps = { + isOpen?: boolean; +}; + +type StateProps = { + user?: ApiUser; + gifts?: ApiPremiumGiftOption[]; + monthlyCurrency?: string; + monthlyAmount?: number; +}; + +const GiftPremiumModal: FC = ({ + isOpen, user, gifts, monthlyCurrency, monthlyAmount, +}) => { + const { openPremiumModal, closeGiftPremiumModal, openUrl } = getActions(); + + const lang = useLang(); + const renderedUser = useCurrentOrPrev(user, true); + const renderedGifts = useCurrentOrPrev(gifts, true); + const [selectedOption, setSelectedOption] = useState(); + const firstGift = renderedGifts?.[0]; + const fullMonthlyAmount = useMemo(() => { + if (!renderedGifts || renderedGifts.length === 0 || !firstGift) { + return undefined; + } + + const cheaperGift = renderedGifts.reduce((acc, gift) => { + return gift.amount < firstGift?.amount ? gift : firstGift; + }, firstGift); + + return cheaperGift.currency === monthlyCurrency && monthlyAmount + ? monthlyAmount + : Math.floor(cheaperGift.amount / cheaperGift.months); + }, [firstGift, renderedGifts, monthlyAmount, monthlyCurrency]); + + useEffect(() => { + if (isOpen) { + setSelectedOption(firstGift?.months); + } + }, [firstGift?.months, isOpen]); + + const selectedGift = useMemo(() => { + return renderedGifts?.find((gift) => gift.months === selectedOption); + }, [renderedGifts, selectedOption]); + + const handleSubmit = useCallback(() => { + if (!selectedGift) { + return; + } + + closeGiftPremiumModal(); + openUrl({ url: selectedGift.botUrl }); + }, [closeGiftPremiumModal, openUrl, selectedGift]); + + const handlePremiumClick = useCallback(() => { + openPremiumModal(); + }, [openPremiumModal]); + + function renderPremiumFeaturesLink() { + const info = lang('GiftPremiumListFeaturesAndTerms'); + // Translation hack for rendering component inside string + const parts = info.match(/([^*]*)\*([^*]+)\*(.*)/); + + if (!parts || parts.length < 4) { + return undefined; + } + + return ( +

+ {parts[1]} + {parts[2]} + {parts[3]} +

+ ); + } + + return ( + +
+ + +

+ {lang('GiftTelegramPremiumTitle')} +

+

+ {renderText( + lang('GiftTelegramPremiumDescription', getUserFirstOrLastName(renderedUser)), + ['emoji', 'simple_markdown'], + )} +

+ +
+ {renderedGifts?.map((gift) => ( + + ))} +
+ + {renderPremiumFeaturesLink()} +
+ + +
+ ); +}; + +export default memo(withGlobal((global): StateProps => { + const { forUserId, monthlyCurrency, monthlyAmount } = global.giftPremiumModal || {}; + const user = forUserId ? selectUser(global, forUserId) : undefined; + const gifts = user ? user.fullInfo?.premiumGifts : undefined; + + return { + user, + gifts, + monthlyCurrency, + monthlyAmount: monthlyAmount ? Number(monthlyAmount) : undefined, + }; +})(GiftPremiumModal)); diff --git a/src/components/main/premium/PremiumFeatureItem.module.scss b/src/components/main/premium/PremiumFeatureItem.module.scss index 4ab359ab5..42ed3e106 100644 --- a/src/components/main/premium/PremiumFeatureItem.module.scss +++ b/src/components/main/premium/PremiumFeatureItem.module.scss @@ -14,11 +14,11 @@ } .description { - font-size: 14px; + font-size: 0.875rem; color: var(--color-text-secondary); white-space: pre-wrap; - line-height: 20px; - min-height: 40px; + line-height: 1.25rem; + min-height: 2.5rem; } .icon { diff --git a/src/components/main/premium/PremiumFeatureModal.module.scss b/src/components/main/premium/PremiumFeatureModal.module.scss index 40b70af58..2dda6c4c0 100644 --- a/src/components/main/premium/PremiumFeatureModal.module.scss +++ b/src/components/main/premium/PremiumFeatureModal.module.scss @@ -4,8 +4,8 @@ .button { font-weight: 600; - font-size: 16px; - height: 48px; + font-size: 1rem; + height: 3rem; } .button-premium { @@ -63,17 +63,17 @@ .limits-content { overflow: auto; padding: 1rem; - margin-top: 59px; + margin-top: 3.6875rem; height: calc(var(--vh) * 55 + 41px); } .header { padding-left: 4rem; - font-size: 20px; + font-size: 1.25rem; font-weight: 500; padding-top: 0.875rem; padding-bottom: 0.875rem; - border-bottom: 1px solid var(--color-borders); + border-bottom: 0.0625rem solid var(--color-borders); position: absolute; background: var(--color-background); width: 100%; @@ -101,7 +101,7 @@ } .title { - font-size: 20px; + font-size: 1.25rem; font-weight: 500; text-align: center; color: var(--color-text); @@ -109,16 +109,16 @@ } .description { - font-size: 16px; + font-size: 1rem; font-weight: 400; - line-height: 22px; + line-height: 1.375rem; text-align: center; color: var(--color-text-secondary); padding: 0 5%; } .footer { - border-top: 1px solid var(--color-borders); + border-top: 0.0625rem solid var(--color-borders); position: absolute; bottom: 0; left: 0; diff --git a/src/components/main/premium/PremiumMainModal.module.scss b/src/components/main/premium/PremiumMainModal.module.scss index 223d80c42..3cda07669 100644 --- a/src/components/main/premium/PremiumMainModal.module.scss +++ b/src/components/main/premium/PremiumMainModal.module.scss @@ -26,8 +26,8 @@ .button { font-weight: 600; background: var(--premium-gradient); - font-size: 16px; - height: 48px; + font-size: 1rem; + height: 3rem; } .main { @@ -46,7 +46,7 @@ } .header-text { - font-size: 24px; + font-size: 1.5rem; font-weight: 500; text-align: center; } @@ -57,7 +57,7 @@ } .list { - margin-bottom: 80px; + margin-bottom: 5rem; width: 100%; } @@ -69,12 +69,12 @@ z-index: 2; display: flex; align-items: center; - border-bottom: 1px solid var(--color-borders); + border-bottom: 0.0625rem solid var(--color-borders); position: absolute; width: 100%; left: 0; top: 0; - height: 56px; + height: 3.5rem; padding: 0.5rem; background: var(--color-background); transition: 0.25s ease-out transform; @@ -92,7 +92,7 @@ } .premium-header-text { - font-size: 20px; + font-size: 1.25rem; font-weight: 500; margin: 0 0 0 3rem; } @@ -111,7 +111,7 @@ position: absolute; width: 100%; background: var(--color-background); - border-top: 1px solid var(--color-borders); + border-top: 0.0625rem solid var(--color-borders); left: 0; bottom: 0; padding: 1rem; diff --git a/src/components/main/premium/PremiumMainModal.tsx b/src/components/main/premium/PremiumMainModal.tsx index ddbed16f2..a8568f6aa 100644 --- a/src/components/main/premium/PremiumMainModal.tsx +++ b/src/components/main/premium/PremiumMainModal.tsx @@ -65,12 +65,16 @@ export type OwnProps = { }; type StateProps = { + currentUserId?: string; promo?: ApiPremiumPromo; isClosing?: boolean; fromUser?: ApiUser; + toUser?: ApiUser; initialSection?: string; isPremium?: boolean; isSuccess?: boolean; + isGift?: boolean; + monthsAmount?: number; limitChannels: number; limitPins: number; limitLinks: number; @@ -83,6 +87,7 @@ type StateProps = { const PremiumMainModal: FC = ({ isOpen, + currentUserId, fromUser, promo, initialSection, @@ -96,6 +101,9 @@ const PremiumMainModal: FC = ({ premiumBotUsername, isClosing, isSuccess, + isGift, + toUser, + monthsAmount, premiumPromoOrder, }) => { // eslint-disable-next-line no-null/no-null @@ -170,6 +178,42 @@ const PremiumMainModal: FC = ({ if (!promo) return undefined; + function getHeaderText() { + if (isGift) { + return fromUser?.id === currentUserId + ? lang('TelegramPremiumUserGiftedPremiumOutboundDialogTitle', [getUserFullName(toUser), monthsAmount]) + : lang('TelegramPremiumUserGiftedPremiumDialogTitle', [getUserFullName(fromUser), monthsAmount]); + } + + return fromUser + ? lang('TelegramPremiumUserDialogTitle', getUserFullName(fromUser)) + : lang(isPremium ? 'TelegramPremiumSubscribedTitle' : 'TelegramPremium'); + } + + function getHeaderDescription() { + if (isGift) { + return fromUser?.id === currentUserId + ? lang('TelegramPremiumUserGiftedPremiumOutboundDialogSubtitle', getUserFullName(toUser)) + : lang('TelegramPremiumUserGiftedPremiumDialogSubtitle'); + } + + return fromUser + ? lang('TelegramPremiumUserDialogSubtitle') + : lang(isPremium ? 'TelegramPremiumSubscribedSubtitle' : 'TelegramPremiumSubtitle'); + } + + function renderFooterText() { + if (!promo || (isGift && fromUser?.id === currentUserId)) { + return undefined; + } + + return ( +
+ {renderTextWithEntities(promo.statusText, promo.statusEntities)} +
+ ); + } + return ( = ({

- {renderText( - fromUser - ? lang('TelegramPremiumUserDialogTitle', getUserFullName(fromUser)) - : lang(isPremium ? 'TelegramPremiumSubscribedTitle' : 'TelegramPremium'), - ['simple_markdown', 'emoji'], - )} + {renderText(getHeaderText(), ['simple_markdown', 'emoji'])}

- {renderText( - lang(fromUser ? 'TelegramPremiumUserDialogSubtitle' - : (isPremium ? 'TelegramPremiumSubscribedSubtitle' : 'TelegramPremiumSubtitle')), - ['simple_markdown'], - )} + {renderText(getHeaderDescription(), ['simple_markdown', 'emoji'])}

@@ -240,18 +275,7 @@ const PremiumMainModal: FC = ({ {renderText(lang('AboutPremiumDescription2'), ['simple_markdown'])}

-
- {renderTextWithEntities( - promo.statusText, - promo.statusEntities, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - )} -
+ {renderFooterText()} {!isPremium && (
@@ -280,10 +304,14 @@ const PremiumMainModal: FC = ({ export default memo(withGlobal((global): StateProps => { return { + currentUserId: global.currentUserId, promo: global.premiumModal?.promo, isClosing: global.premiumModal?.isClosing, isSuccess: global.premiumModal?.isSuccess, + isGift: global.premiumModal?.isGift, + monthsAmount: global.premiumModal?.monthsAmount, fromUser: global.premiumModal?.fromUserId ? selectUser(global, global.premiumModal.fromUserId) : undefined, + toUser: global.premiumModal?.toUserId ? selectUser(global, global.premiumModal.toUserId) : undefined, initialSection: global.premiumModal?.initialSection, isPremium: selectIsCurrentUserPremium(global), limitChannels: selectPremiumLimit(global, 'channels'), diff --git a/src/components/middle/ActionMessage.tsx b/src/components/middle/ActionMessage.tsx index 88df0e00e..cd08ac709 100644 --- a/src/components/middle/ActionMessage.tsx +++ b/src/components/middle/ActionMessage.tsx @@ -2,9 +2,11 @@ import type { FC } from '../../lib/teact/teact'; import React, { memo, useEffect, useMemo, useRef, } from '../../lib/teact/teact'; -import { withGlobal } from '../../global'; +import { getActions, withGlobal } from '../../global'; -import type { ApiUser, ApiMessage, ApiChat } from '../../api/types'; +import type { + ApiUser, ApiMessage, ApiChat, ApiSticker, +} from '../../api/types'; import type { FocusDirection } from '../../types'; import { @@ -16,24 +18,27 @@ import { import { getMessageHtmlId, isChatChannel } from '../../global/helpers'; import buildClassName from '../../util/buildClassName'; import { renderActionMessageText } from '../common/helpers/renderActionMessageText'; +import { preventMessageInputBlur } from './helpers/preventMessageInputBlur'; import useEnsureMessage from '../../hooks/useEnsureMessage'; import useContextMenuHandlers from '../../hooks/useContextMenuHandlers'; import type { ObserveFn } from '../../hooks/useIntersectionObserver'; -import { useOnIntersect } from '../../hooks/useIntersectionObserver'; +import { useIsIntersecting, useOnIntersect } from '../../hooks/useIntersectionObserver'; import useFocusMessage from './message/hooks/useFocusMessage'; import useLang from '../../hooks/useLang'; - -import ContextMenuContainer from './message/ContextMenuContainer.async'; import useFlag from '../../hooks/useFlag'; import useShowTransition from '../../hooks/useShowTransition'; -import { preventMessageInputBlur } from './helpers/preventMessageInputBlur'; + +import ContextMenuContainer from './message/ContextMenuContainer.async'; +import AnimatedIconFromSticker from '../common/AnimatedIconFromSticker'; type OwnProps = { message: ApiMessage; observeIntersection?: ObserveFn; + observeIntersectionForAnimation?: ObserveFn; isEmbedded?: boolean; appearanceOrder?: number; isLastInList?: boolean; + memoFirstUnreadIdRef?: { current: number | undefined }; }; type StateProps = { @@ -46,6 +51,7 @@ type StateProps = { isFocused: boolean; focusDirection?: FocusDirection; noFocusHighlight?: boolean; + premiumGiftSticker?: ApiSticker; }; const APPEARANCE_DELAY = 10; @@ -53,6 +59,7 @@ const APPEARANCE_DELAY = 10; const ActionMessage: FC = ({ message, observeIntersection, + observeIntersectionForAnimation, isEmbedded, appearanceOrder = 0, isLastInList, @@ -65,7 +72,13 @@ const ActionMessage: FC = ({ isFocused, focusDirection, noFocusHighlight, + premiumGiftSticker, + memoFirstUnreadIdRef, }) => { + const { openPremiumModal, requestConfetti } = getActions(); + + const lang = useLang(); + // eslint-disable-next-line no-null/no-null const ref = useRef(null); @@ -73,10 +86,10 @@ const ActionMessage: FC = ({ useEnsureMessage(message.chatId, message.replyToMessageId, targetMessage); useFocusMessage(ref, message.chatId, isFocused, focusDirection, noFocusHighlight); - const lang = useLang(); - const noAppearanceAnimation = appearanceOrder <= 0; const [isShown, markShown] = useFlag(noAppearanceAnimation); + const isGift = Boolean(message.content.action?.text.startsWith('ActionGift')); + useEffect(() => { if (noAppearanceAnimation) { return; @@ -84,6 +97,21 @@ const ActionMessage: FC = ({ setTimeout(markShown, appearanceOrder * APPEARANCE_DELAY); }, [appearanceOrder, markShown, noAppearanceAnimation]); + + const isVisible = useIsIntersecting(ref, observeIntersectionForAnimation); + + const shouldShowConfettiRef = useRef((() => { + const isUnread = memoFirstUnreadIdRef?.current && message.id >= memoFirstUnreadIdRef.current; + return isGift && !message.isOutgoing && isUnread; + })()); + + useEffect(() => { + if (isVisible && shouldShowConfettiRef.current) { + shouldShowConfettiRef.current = false; + requestConfetti(); + } + }, [isVisible, requestConfetti]); + const { transitionClassNames } = useShowTransition(isShown, undefined, noAppearanceAnimation, false); const targetUsers = useMemo(() => { @@ -114,13 +142,41 @@ const ActionMessage: FC = ({ handleBeforeContextMenu(e); }; + const handlePremiumGiftClick = () => { + openPremiumModal({ + isGift: true, + fromUserId: senderUser?.id, + toUserId: targetUserIds?.[0], + monthsAmount: message.content.action?.months || 0, + }); + }; + if (isEmbedded) { return {content}; } + function renderGift() { + return ( + + + {lang('ActionGiftPremiumTitle')} + {lang('ActionGiftPremiumSubtitle', lang('Months', message.content.action?.months, 'i'))} + + {lang('ActionGiftPremiumView')} + + ); + } + const className = buildClassName( 'ActionMessage message-list-item', isFocused && !noFocusHighlight && 'focused', + isGift && 'premium-gift', isContextMenuShown && 'has-menu-open', isLastInList && 'last-in-list', transitionClassNames, @@ -136,6 +192,7 @@ const ActionMessage: FC = ({ onContextMenu={handleContextMenu} > {content} + {isGift && renderGift()} {contextMenuPosition && ( ( const isChat = chat && (isChatChannel(chat) || userId === message.chatId); const senderUser = !isChat && userId ? selectUser(global, userId) : undefined; const senderChat = isChat ? chat : undefined; + const premiumGiftSticker = global.premiumGifts?.stickers?.[0]; return { usersById, @@ -176,6 +234,7 @@ export default memo(withGlobal( targetUserIds, targetMessage, isFocused, + premiumGiftSticker, ...(isFocused && { focusDirection, noFocusHighlight }), }; }, diff --git a/src/components/middle/HeaderMenuContainer.tsx b/src/components/middle/HeaderMenuContainer.tsx index a367fb0d1..acdcd475b 100644 --- a/src/components/middle/HeaderMenuContainer.tsx +++ b/src/components/middle/HeaderMenuContainer.tsx @@ -11,7 +11,7 @@ import { REPLIES_USER_ID } from '../../config'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment'; import { disableScrolling, enableScrolling } from '../../util/scrollLock'; import { - selectChat, selectNotifySettings, selectNotifyExceptions, selectUser, selectChatBot, + selectChat, selectNotifySettings, selectNotifyExceptions, selectUser, selectChatBot, selectIsPremiumPurchaseBlocked, } from '../../global/selectors'; import { isUserId, getCanDeleteChat, selectIsChatMuted, getCanAddContact, isChatChannel, isChatGroup, @@ -73,6 +73,7 @@ type StateProps = { canAddContact?: boolean; canReportChat?: boolean; canDeleteChat?: boolean; + canGiftPremium?: boolean; hasLinkedChat?: boolean; }; @@ -98,6 +99,7 @@ const HeaderMenuContainer: FC = ({ isMuted, canReportChat, canDeleteChat, + canGiftPremium, hasLinkedChat, canAddContact, onSubscribeChannel, @@ -116,6 +118,7 @@ const HeaderMenuContainer: FC = ({ openAddContactDialog, requestCall, toggleStatistics, + openGiftPremiumModal, } = getActions(); const [isMenuOpen, setIsMenuOpen] = useState(true); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); @@ -181,6 +184,11 @@ const HeaderMenuContainer: FC = ({ closeMenu(); }, [chatId, closeMenu, openLinkedChat]); + const handleGiftPremiumClick = useCallback(() => { + openGiftPremiumModal({ forUserId: chatId }); + closeMenu(); + }, [openGiftPremiumModal, chatId, closeMenu]); + const handleAddContactClick = useCallback(() => { openAddContactDialog({ userId: chatId }); closeMenu(); @@ -358,6 +366,14 @@ const HeaderMenuContainer: FC = ({ )} {botButtons} + {canGiftPremium && ( + + {lang('GiftPremium')} + + )} {canLeave && ( ( const canReportChat = isChatChannel(chat) || isChatGroup(chat) || (user && !user.isSelf); const chatBot = chatId !== REPLIES_USER_ID ? selectChatBot(global, chatId) : undefined; + const canGiftPremium = Boolean( + global.lastSyncTime + && user?.fullInfo?.premiumGifts?.length + && !selectIsPremiumPurchaseBlocked(global), + ); return { chat, @@ -410,6 +431,7 @@ export default memo(withGlobal( canAddContact, canReportChat, canDeleteChat: getCanDeleteChat(chat), + canGiftPremium, hasLinkedChat: Boolean(chat?.fullInfo?.linkedChatId), botCommands: chatBot?.fullInfo?.botInfo?.commands, }; diff --git a/src/components/middle/MessageList.scss b/src/components/middle/MessageList.scss index 15625b7db..4c425105e 100644 --- a/src/components/middle/MessageList.scss +++ b/src/components/middle/MessageList.scss @@ -259,6 +259,31 @@ } } + .ActionMessage.premium-gift { + display: flex; + flex-direction: column; + align-items: center; + } + + .action-message-gift { + display: flex !important; + flex-direction: column; + align-items: center; + line-height: 1rem !important; + padding-bottom: 0.75rem !important; + margin-top: 0.5rem; + cursor: pointer; + outline: none; + } + + .action-message-button { + display: inline-block; + border-radius: var(--border-radius-default); + padding: 0.5rem 0.75rem; + margin-top: 0.5rem; + background-color: var(--pattern-color); + } + .sticky-date { margin-top: 1rem; margin-bottom: 1rem; diff --git a/src/components/middle/MessageListContent.tsx b/src/components/middle/MessageListContent.tsx index 3f148fe60..317f36b50 100644 --- a/src/components/middle/MessageListContent.tsx +++ b/src/components/middle/MessageListContent.tsx @@ -144,6 +144,8 @@ const MessageListContent: FC = ({ key={message.id} message={message} observeIntersection={observeIntersectionForReading} + observeIntersectionForAnimation={observeIntersectionForAnimatedStickers} + memoFirstUnreadIdRef={memoFirstUnreadIdRef} appearanceOrder={messageCountToAnimate - ++appearanceIndex} isLastInList={isLastInList} />, diff --git a/src/components/middle/MiddleColumn.tsx b/src/components/middle/MiddleColumn.tsx index 44e5eb364..bb8002e3f 100644 --- a/src/components/middle/MiddleColumn.tsx +++ b/src/components/middle/MiddleColumn.tsx @@ -71,6 +71,7 @@ import UnpinAllMessagesModal from '../common/UnpinAllMessagesModal.async'; import SeenByModal from '../common/SeenByModal.async'; import EmojiInteractionAnimation from './EmojiInteractionAnimation.async'; import ReactorListModal from './ReactorListModal.async'; +import GiftPremiumModal from '../main/premium/GiftPremiumModal.async'; import './MiddleColumn.scss'; import styles from './MiddleColumn.module.scss'; @@ -98,6 +99,7 @@ type StateProps = { isSelectModeActive?: boolean; isSeenByModalOpen: boolean; isReactorListModalOpen: boolean; + isGiftPremiumModalOpen?: boolean; animationLevel?: number; shouldSkipHistoryAnimations?: boolean; currentTransitionKey: number; @@ -140,6 +142,7 @@ const MiddleColumn: FC = ({ isSelectModeActive, isSeenByModalOpen, isReactorListModalOpen, + isGiftPremiumModalOpen, animationLevel, shouldSkipHistoryAnimations, currentTransitionKey, @@ -551,6 +554,7 @@ const MiddleColumn: FC = ({ /> ))}
+ ); }; @@ -580,6 +584,7 @@ export default memo(withGlobal( isSelectModeActive: selectIsInSelectMode(global), isSeenByModalOpen: Boolean(global.seenByModal), isReactorListModalOpen: Boolean(global.reactorModal), + isGiftPremiumModalOpen: global.giftPremiumModal?.isOpen, animationLevel: global.settings.byKey.animationLevel, currentTransitionKey: Math.max(0, messageLists.length - 1), activeEmojiInteractions, diff --git a/src/components/payment/CardInput.tsx b/src/components/payment/CardInput.tsx index 635e15dea..0e9d21b55 100644 --- a/src/components/payment/CardInput.tsx +++ b/src/components/payment/CardInput.tsx @@ -14,6 +14,7 @@ import './CardInput.scss'; import mastercardIconPath from '../../assets/mastercard.svg'; import visaIconPath from '../../assets/visa.svg'; +import mirIconPath from '../../assets/mir.svg'; const CARD_NUMBER_MAX_LENGTH = 23; @@ -73,6 +74,8 @@ function getCardIcon(cardType: CardType) { return ; case CardType.Visa: return ; + case CardType.Mir: + return ; default: return undefined; } diff --git a/src/components/ui/Link.module.scss b/src/components/ui/Link.module.scss new file mode 100644 index 000000000..ad93cba37 --- /dev/null +++ b/src/components/ui/Link.module.scss @@ -0,0 +1,19 @@ +.link { + color: inherit; + + &:hover { + color: inherit; + + &:global(.GroupCallLink) { + text-decoration: none; + } + } +} + +.isPrimary { + color: var(--color-primary); + + &:hover { + color: var(--color-primary); + } +} diff --git a/src/components/ui/Link.scss b/src/components/ui/Link.scss deleted file mode 100644 index c68289c5d..000000000 --- a/src/components/ui/Link.scss +++ /dev/null @@ -1,11 +0,0 @@ -.Link { - color: inherit; - - &:hover { - color: inherit; - - &.GroupCallLink { - text-decoration: none; - } - } -} diff --git a/src/components/ui/Link.tsx b/src/components/ui/Link.tsx index bc488d8cc..23993fbde 100644 --- a/src/components/ui/Link.tsx +++ b/src/components/ui/Link.tsx @@ -3,17 +3,18 @@ import React, { useCallback } from '../../lib/teact/teact'; import buildClassName from '../../util/buildClassName'; -import './Link.scss'; +import styles from './Link.module.scss'; type OwnProps = { children: React.ReactNode; className?: string; isRtl?: boolean; + isPrimary?: boolean; onClick?: (e: React.MouseEvent) => void; }; const Link: FC = ({ - children, className, isRtl, onClick, + children, isPrimary, className, isRtl, onClick, }) => { const handleClick = useCallback((e: React.MouseEvent) => { e.preventDefault(); @@ -23,7 +24,7 @@ const Link: FC = ({ return ( diff --git a/src/global/actions/api/chats.ts b/src/global/actions/api/chats.ts index d14b57a4c..0cc9c990c 100644 --- a/src/global/actions/api/chats.ts +++ b/src/global/actions/api/chats.ts @@ -642,6 +642,10 @@ addActionHandler('openTelegramLink', (global, actions, payload) => { chatId, messageId, }); + } else if (part1.startsWith('$')) { + actions.openInvoice({ + slug: part1.substring(1), + }); } else if (part1 === 'invoice') { actions.openInvoice({ slug: part2, diff --git a/src/global/actions/api/payments.ts b/src/global/actions/api/payments.ts index b428af158..f9aa3a7b7 100644 --- a/src/global/actions/api/payments.ts +++ b/src/global/actions/api/payments.ts @@ -376,7 +376,9 @@ addActionHandler('closePremiumModal', (global, actions, payload) => { }); addActionHandler('openPremiumModal', async (global, actions, payload) => { - const { initialSection, fromUserId, isSuccess } = payload || {}; + const { + initialSection, fromUserId, isSuccess, isGift, monthsAmount, toUserId, + } = payload || {}; actions.loadPremiumStickers(); @@ -393,7 +395,36 @@ addActionHandler('openPremiumModal', async (global, actions, payload) => { initialSection, isOpen: true, fromUserId, + toUserId, + isGift, + monthsAmount, isSuccess, }, }); }); + +addActionHandler('openGiftPremiumModal', async (global, actions, payload) => { + const { forUserId } = payload || {}; + const result = await callApi('fetchPremiumPromo'); + if (!result) return; + + global = getGlobal(); + global = addUsers(global, buildCollectionByKey(result.users, 'id')); + + setGlobal({ + ...global, + giftPremiumModal: { + isOpen: true, + forUserId, + monthlyCurrency: result.promo.currency, + monthlyAmount: result.promo.monthlyAmount, + }, + }); +}); + +addActionHandler('closeGiftPremiumModal', (global) => { + setGlobal({ + ...global, + giftPremiumModal: { isOpen: false }, + }); +}); diff --git a/src/global/actions/api/symbols.ts b/src/global/actions/api/symbols.ts index f50223210..28ef0aa14 100644 --- a/src/global/actions/api/symbols.ts +++ b/src/global/actions/api/symbols.ts @@ -109,6 +109,20 @@ addActionHandler('loadFeaturedStickers', (global) => { void loadFeaturedStickers(hash); }); +addActionHandler('loadPremiumGifts', async () => { + const stickerSet = await callApi('fetchPremiumGifts'); + if (!stickerSet) { + return; + } + + const { set, stickers } = stickerSet; + + setGlobal({ + ...getGlobal(), + premiumGifts: { ...set, stickers }, + }); +}); + addActionHandler('loadStickers', (global, actions, payload) => { const { stickerSetId, stickerSetShortName } = payload!; let { stickerSetAccessHash } = payload!; diff --git a/src/global/actions/apiUpdaters/payments.ts b/src/global/actions/apiUpdaters/payments.ts index 6cfc40de8..cf0e29c1c 100644 --- a/src/global/actions/apiUpdaters/payments.ts +++ b/src/global/actions/apiUpdaters/payments.ts @@ -7,16 +7,16 @@ addActionHandler('apiUpdate', (global, actions, update) => { switch (update['@type']) { case 'updatePaymentStateCompleted': { const { inputInvoice } = global.payment; - if (update.slug && inputInvoice && 'slug' in inputInvoice && inputInvoice.slug !== update.slug) { - return undefined; - } - // On the production host, the payment frame receives a message with the payment event, // after which the payment form closes. In other cases, the payment form must be closed manually. if (!IS_PRODUCTION_HOST) { global = clearPayment(global); } + if (update.slug && inputInvoice && 'slug' in inputInvoice && inputInvoice.slug !== update.slug) { + return !IS_PRODUCTION_HOST ? global : undefined; + } + return { ...global, payment: { diff --git a/src/global/types.ts b/src/global/types.ts index 06e3fcedd..1c0170766 100644 --- a/src/global/types.ts +++ b/src/global/types.ts @@ -314,6 +314,7 @@ export type GlobalState = { animatedEmojis?: ApiStickerSet; animatedEmojiEffects?: ApiStickerSet; + premiumGifts?: ApiStickerSet; emojiKeywords: Partial>; gifs: { @@ -638,9 +639,19 @@ export type GlobalState = { promo: ApiPremiumPromo; initialSection?: string; fromUserId?: string; + toUserId?: string; + isGift?: boolean; + monthsAmount?: number; isSuccess?: boolean; }; + giftPremiumModal?: { + isOpen?: boolean; + forUserId?: string; + monthlyCurrency?: string; + monthlyAmount?: string; + }; + transcriptions: Record; limitReachedModal?: { @@ -1062,7 +1073,10 @@ export interface ActionPayloads { openPremiumModal: { initialSection?: string; fromUserId?: string; + toUserId?: string; isSuccess?: boolean; + isGift?: boolean; + monthsAmount?: number; }; closePremiumModal: never | { isClosed?: boolean; @@ -1073,10 +1087,17 @@ export interface ActionPayloads { messageId: number; }; + loadPremiumGifts: never; loadPremiumStickers: { hash?: string; }; + openGiftPremiumModal: { + forUserId?: string; + }; + + closeGiftPremiumModal: never; + // Invoice openInvoice: ApiInputInvoice; } diff --git a/src/styles/Telegram T.json b/src/styles/Telegram T.json index be51033b8..ba27c9300 100644 --- a/src/styles/Telegram T.json +++ b/src/styles/Telegram T.json @@ -2,7 +2,7 @@ "metadata": { "name": "Telegram T", "lastOpened": 0, - "created": 1659146815066 + "created": 1660758480766 }, "iconSets": [ { @@ -157,13 +157,21 @@ }, { "selection": [ + { + "order": 737, + "id": 77, + "name": "gift", + "prevSize": 32, + "code": 59821, + "tempChar": "" + }, { "order": 734, "id": 76, "name": "sort", "prevSize": 32, "code": 59820, - "tempChar": "" + "tempChar": "" }, { "order": 732, @@ -171,7 +179,7 @@ "name": "web", "prevSize": 32, "code": 59819, - "tempChar": "" + "tempChar": "" }, { "order": 731, @@ -179,7 +187,7 @@ "name": "transcribe", "prevSize": 32, "code": 59818, - "tempChar": "" + "tempChar": "" }, { "order": 719, @@ -187,7 +195,7 @@ "name": "add-one-badge", "prevSize": 32, "code": 59803, - "tempChar": "" + "tempChar": "" }, { "order": 720, @@ -195,7 +203,7 @@ "name": "chat-badge", "prevSize": 32, "code": 59808, - "tempChar": "" + "tempChar": "" }, { "order": 721, @@ -203,7 +211,7 @@ "name": "chats-badge", "prevSize": 32, "code": 59809, - "tempChar": "" + "tempChar": "" }, { "order": 722, @@ -211,7 +219,7 @@ "name": "double-badge", "prevSize": 32, "code": 59810, - "tempChar": "" + "tempChar": "" }, { "order": 723, @@ -219,7 +227,7 @@ "name": "file-badge", "prevSize": 32, "code": 59811, - "tempChar": "" + "tempChar": "" }, { "order": 724, @@ -227,7 +235,7 @@ "name": "folder-badge", "prevSize": 32, "code": 59812, - "tempChar": "" + "tempChar": "" }, { "order": 726, @@ -235,7 +243,7 @@ "name": "link-badge", "prevSize": 32, "code": 59813, - "tempChar": "" + "tempChar": "" }, { "order": 725, @@ -243,7 +251,7 @@ "name": "pin-badge", "prevSize": 32, "code": 59814, - "tempChar": "" + "tempChar": "" }, { "order": 727, @@ -251,7 +259,7 @@ "name": "premium", "prevSize": 32, "code": 59815, - "tempChar": "" + "tempChar": "" }, { "order": 728, @@ -259,7 +267,7 @@ "name": "unlock-badge", "prevSize": 32, "code": 59816, - "tempChar": "" + "tempChar": "" }, { "order": 729, @@ -267,7 +275,7 @@ "name": "lock-badge", "prevSize": 32, "code": 59817, - "tempChar": "" + "tempChar": "" }, { "order": 715, @@ -275,7 +283,7 @@ "name": "key", "prevSize": 32, "code": 59802, - "tempChar": "" + "tempChar": "" }, { "order": 714, @@ -283,7 +291,7 @@ "name": "heart-outline", "prevSize": 32, "code": 59806, - "tempChar": "" + "tempChar": "" }, { "order": 713, @@ -291,7 +299,7 @@ "name": "heart", "prevSize": 32, "code": 59807, - "tempChar": "" + "tempChar": "" }, { "order": 712, @@ -299,7 +307,7 @@ "name": "word-wrap", "prevSize": 32, "code": 59805, - "tempChar": "" + "tempChar": "" }, { "order": 708, @@ -307,7 +315,7 @@ "name": "webapp", "prevSize": 32, "code": 59795, - "tempChar": "" + "tempChar": "" }, { "order": 707, @@ -315,7 +323,7 @@ "name": "reload", "prevSize": 32, "code": 59796, - "tempChar": "" + "tempChar": "" }, { "order": 706, @@ -323,7 +331,7 @@ "name": "install", "prevSize": 32, "code": 59801, - "tempChar": "" + "tempChar": "" }, { "order": 705, @@ -331,7 +339,7 @@ "name": "favorite-filled", "prevSize": 32, "code": 59800, - "tempChar": "" + "tempChar": "" }, { "order": 702, @@ -339,7 +347,7 @@ "name": "share-screen", "prevSize": 32, "code": 59770, - "tempChar": "" + "tempChar": "" }, { "order": 701, @@ -347,7 +355,7 @@ "name": "video-outlined", "prevSize": 32, "code": 59799, - "tempChar": "" + "tempChar": "" }, { "order": 700, @@ -355,7 +363,7 @@ "name": "stats", "prevSize": 32, "code": 59798, - "tempChar": "" + "tempChar": "" }, { "order": 699, @@ -363,7 +371,7 @@ "name": "copy-media", "prevSize": 32, "code": 59797, - "tempChar": "" + "tempChar": "" }, { "order": 704, @@ -371,7 +379,7 @@ "name": "sidebar", "prevSize": 32, "code": 59794, - "tempChar": "" + "tempChar": "" }, { "order": 690, @@ -379,7 +387,7 @@ "name": "video-stop", "prevSize": 32, "code": 59787, - "tempChar": "" + "tempChar": "" }, { "order": 678, @@ -387,7 +395,7 @@ "name": "speaker", "prevSize": 32, "code": 59777, - "tempChar": "" + "tempChar": "" }, { "order": 679, @@ -395,7 +403,7 @@ "name": "speaker-outline", "prevSize": 32, "code": 59778, - "tempChar": "" + "tempChar": "" }, { "order": 680, @@ -403,7 +411,7 @@ "name": "phone-discard-outline", "prevSize": 32, "code": 59779, - "tempChar": "" + "tempChar": "" }, { "order": 681, @@ -411,7 +419,7 @@ "name": "allow-speak", "prevSize": 32, "code": 59780, - "tempChar": "" + "tempChar": "" }, { "order": 682, @@ -419,7 +427,7 @@ "name": "stop-raising-hand", "prevSize": 32, "code": 59781, - "tempChar": "" + "tempChar": "" }, { "order": 683, @@ -427,7 +435,7 @@ "name": "share-screen-outlined", "prevSize": 32, "code": 59782, - "tempChar": "" + "tempChar": "" }, { "order": 684, @@ -435,7 +443,7 @@ "name": "voice-chat", "prevSize": 32, "code": 59783, - "tempChar": "" + "tempChar": "" }, { "order": 689, @@ -443,7 +451,7 @@ "name": "video", "prevSize": 32, "code": 59784, - "tempChar": "" + "tempChar": "" }, { "order": 686, @@ -451,7 +459,7 @@ "name": "noise-suppression", "prevSize": 32, "code": 59785, - "tempChar": "" + "tempChar": "" }, { "order": 703, @@ -459,7 +467,7 @@ "name": "phone-discard", "prevSize": 32, "code": 59786, - "tempChar": "" + "tempChar": "" }, { "order": 667, @@ -467,7 +475,7 @@ "name": "bot-commands-filled", "prevSize": 32, "code": 59775, - "tempChar": "" + "tempChar": "" }, { "order": 664, @@ -475,7 +483,7 @@ "name": "reply-filled", "prevSize": 32, "code": 59776, - "tempChar": "" + "tempChar": "" }, { "order": 656, @@ -483,7 +491,7 @@ "name": "bug", "prevSize": 32, "code": 59774, - "tempChar": "" + "tempChar": "" }, { "order": 619, @@ -491,7 +499,7 @@ "name": "data", "prevSize": 32, "code": 59773, - "tempChar": "" + "tempChar": "" }, { "order": 622, @@ -499,7 +507,7 @@ "name": "darkmode", "prevSize": 32, "code": 59769, - "tempChar": "" + "tempChar": "" }, { "order": 711, @@ -507,7 +515,7 @@ "name": "animations", "prevSize": 32, "code": 59804, - "tempChar": "" + "tempChar": "" }, { "order": 626, @@ -515,7 +523,7 @@ "name": "enter", "prevSize": 32, "code": 59771, - "tempChar": "" + "tempChar": "" }, { "order": 627, @@ -523,7 +531,7 @@ "name": "fontsize", "prevSize": 32, "code": 59772, - "tempChar": "" + "tempChar": "" }, { "order": 630, @@ -531,7 +539,7 @@ "name": "permissions", "prevSize": 32, "code": 59766, - "tempChar": "" + "tempChar": "" }, { "order": 631, @@ -539,7 +547,7 @@ "name": "card", "prevSize": 32, "code": 59767, - "tempChar": "" + "tempChar": "" }, { "order": 634, @@ -547,7 +555,7 @@ "name": "truck", "prevSize": 32, "code": 59768, - "tempChar": "" + "tempChar": "" }, { "order": 663, @@ -555,7 +563,7 @@ "name": "share-filled", "prevSize": 32, "code": 59738, - "tempChar": "" + "tempChar": "" }, { "order": 638, @@ -563,7 +571,7 @@ "name": "bold", "prevSize": 32, "code": 59745, - "tempChar": "" + "tempChar": "" }, { "order": 639, @@ -571,7 +579,7 @@ "name": "bot-command", "prevSize": 32, "code": 59746, - "tempChar": "" + "tempChar": "" }, { "order": 642, @@ -579,7 +587,7 @@ "name": "calendar-filter", "prevSize": 32, "code": 59747, - "tempChar": "" + "tempChar": "" }, { "order": 643, @@ -587,7 +595,7 @@ "name": "comments", "prevSize": 32, "code": 59748, - "tempChar": "" + "tempChar": "" }, { "order": 645, @@ -595,7 +603,7 @@ "name": "comments-sticker", "prevSize": 32, "code": 59749, - "tempChar": "" + "tempChar": "" }, { "order": 646, @@ -603,7 +611,7 @@ "name": "arrow-down", "prevSize": 32, "code": 59750, - "tempChar": "" + "tempChar": "" }, { "order": 668, @@ -611,7 +619,7 @@ "name": "email", "prevSize": 32, "code": 59751, - "tempChar": "" + "tempChar": "" }, { "order": 648, @@ -619,7 +627,7 @@ "name": "italic", "prevSize": 32, "code": 59752, - "tempChar": "" + "tempChar": "" }, { "order": 620, @@ -627,7 +635,7 @@ "name": "link", "prevSize": 32, "code": 59753, - "tempChar": "" + "tempChar": "" }, { "order": 621, @@ -635,7 +643,7 @@ "name": "mention", "prevSize": 32, "code": 59754, - "tempChar": "" + "tempChar": "" }, { "order": 624, @@ -643,7 +651,7 @@ "name": "monospace", "prevSize": 32, "code": 59755, - "tempChar": "" + "tempChar": "" }, { "order": 625, @@ -651,7 +659,7 @@ "name": "next", "prevSize": 32, "code": 59756, - "tempChar": "" + "tempChar": "" }, { "order": 628, @@ -659,7 +667,7 @@ "name": "password-off", "prevSize": 32, "code": 59757, - "tempChar": "" + "tempChar": "" }, { "order": 629, @@ -667,7 +675,7 @@ "name": "pin-list", "prevSize": 32, "code": 59758, - "tempChar": "" + "tempChar": "" }, { "order": 632, @@ -675,7 +683,7 @@ "name": "previous", "prevSize": 32, "code": 59759, - "tempChar": "" + "tempChar": "" }, { "order": 633, @@ -683,7 +691,7 @@ "name": "replace", "prevSize": 32, "code": 59760, - "tempChar": "" + "tempChar": "" }, { "order": 636, @@ -691,7 +699,7 @@ "name": "schedule", "prevSize": 32, "code": 59761, - "tempChar": "" + "tempChar": "" }, { "order": 691, @@ -699,7 +707,7 @@ "name": "strikethrough", "prevSize": 32, "code": 59762, - "tempChar": "" + "tempChar": "" }, { "order": 692, @@ -707,7 +715,7 @@ "name": "underlined", "prevSize": 32, "code": 59763, - "tempChar": "" + "tempChar": "" }, { "order": 641, @@ -715,7 +723,7 @@ "name": "zoom-in", "prevSize": 32, "code": 59764, - "tempChar": "" + "tempChar": "" }, { "order": 649, @@ -723,27 +731,41 @@ "name": "zoom-out", "prevSize": 32, "code": 59765, - "tempChar": "" + "tempChar": "" } ], "id": 2, "metadata": { "name": "Untitled Set", "importSize": { - "width": 489, - "height": 489 + "width": 768, + "height": 768 } }, "height": 1024, "prevSize": 32, "icons": [ { - "id": 76, + "id": 77, "paths": [ - "M543.839 668.139c-15.919-14.001-41.812-11.891-55.815 4.028l-147.687 166.483v-665.357c0-21.865-18.029-39.894-39.894-39.894s-39.894 18.029-39.894 39.894v665.357l-147.687-166.483c-15.919-15.919-39.894-18.029-55.815-4.028-15.919 15.919-18.029 39.894-4.028 55.815l217.503 243.396c16.303 20.138 45.074 17.070 57.925 0l219.421-243.396c14.001-15.728 12.084-41.812-4.028-55.815z", - "M970.979 301.033l-215.584-243.396c-19.18-19.371-43.155-20.523-59.841 0l-219.421 243.396c-14.001 15.919-11.891 41.812 4.028 55.815 24.551 19.565 49.293 6.138 55.815-4.028l147.687-166.483v663.439c0 21.865 18.029 39.894 39.894 39.894s39.894-15.919 39.894-37.976v-665.166l147.687 166.483c15.919 15.919 39.894 18.029 55.815 4.028 15.919-16.112 18.029-40.087 4.028-56.006z" + "M226.933 596.267c0.4 0 0.667 0 1.067 0 7.2 0 14.4 0 21.467 0 3.6 0 7.333 0 10.933 0 23.6 0 42.667-19.067 42.667-42.667s-19.067-42.667-42.667-42.667c-3.6 0-7.2 0-10.8 0-7.333 0-14.8 0-22.133 0-0.267 0-0.4 0-0.667 0-28.267 0-48.8-10.8-61.333-32.267-14.4-24.533-14.533-58.933-0.4-83.6 12.4-21.733 33.067-32.8 61.467-32.933h287.733c23.6 0 42.667-19.067 42.667-42.667s-19.067-42.667-42.667-42.667h-287.733c-0.133 0-0.133 0-0.267 0-47.6 0.267-89.467 18.667-118.133 51.867-25.2 29.2-38.933 67.733-38.667 108.8s14.4 79.467 40 108.4c28.667 32.533 70.4 50.4 117.467 50.4z", + "M514.4 951.6c23.6 0 42.667-19.067 42.667-42.667v-112.667c0-23.6-19.067-42.667-42.667-42.667s-42.667 19.067-42.667 42.667v112.667c0 23.467 19.067 42.667 42.667 42.667z", + "M247.733 951.6c0 0 0.133 0 0 0h266.533c23.6 0 42.667-19.067 42.667-42.667s-19.067-42.667-42.667-42.667h-266.4c0 0 0 0 0 0-24.667 0-30.933-9.067-34-29.2v-293.067c0-23.6-19.067-42.667-42.667-42.667s-42.667 19.067-42.667 42.667v296c0 1.867 0.133 3.867 0.4 5.733 8.933 67.2 52.267 105.867 118.8 105.867z", + "M486.8 362.133c4 0 8-0.533 12.133-1.733 10.133-2.933 43.067-16.8 40.667-69.733-1.6-36.4-19.067-82.8-45.6-121.2-24.133-34.8-66.4-79.067-131.2-92.133-74.933-15.2-111.867 7.6-129.733 29.333-23.067 28.133-25.867 69.2-7.6 112.533 27.2 64.667 101.6 134.4 191.067 142.267 14.667 1.333 28.133-4.933 36.8-15.6 8 10.133 20.4 16.267 33.467 16.267zM454.267 291.867c-0.133 0.133-0.267 0.4-0.533 0.533-7.067-8.933-17.6-14.933-29.733-16-49.867-4.4-93.733-43.333-113.467-77.6-12.667-22-12.133-35.2-11.2-38 3.067-2 16.8-5.733 46.667 0.267 42.267 8.533 70.133 44.133 82.933 64.667 17.867 28.667 24.133 54.133 25.333 66.133zM474.8 278.533c0 0 0 0 0 0s0 0 0 0z", + "M799.067 596.267c-0.4 0-0.667 0-1.067 0-7.2 0-14.4 0-21.467 0-3.6 0-7.333 0-10.933 0-23.6 0-42.667-19.067-42.667-42.667s19.067-42.667 42.667-42.667c3.6 0 7.2 0 10.8 0 7.333 0 14.8 0 22.133 0 0.267 0 0.4 0 0.667 0 28.267 0 48.8-10.8 61.333-32.267 14.4-24.533 14.533-58.933 0.4-83.6-12.4-21.733-33.067-32.8-61.467-32.933h-287.733c-23.6 0-42.667-19.067-42.667-42.667s19.067-42.667 42.667-42.667h287.867c0.133 0 0.133 0 0.267 0 47.6 0.267 89.467 18.667 118.133 51.867 25.2 29.2 38.933 67.733 38.667 108.8s-14.4 79.467-40 108.4c-28.667 32.533-70.533 50.4-117.6 50.4z", + "M511.733 951.6c-23.6 0-42.667-19.067-42.667-42.667v-112.667c0-23.6 19.067-42.667 42.667-42.667s42.667 19.067 42.667 42.667v112.667c0 23.467-19.2 42.667-42.667 42.667z", + "M778.267 951.6c0 0 0 0 0 0h-266.533c-23.6 0-42.667-19.067-42.667-42.667s19.067-42.667 42.667-42.667h266.533c0 0 0 0 0 0 24.667 0 30.933-9.067 34-29.2v-293.067c0-23.6 19.067-42.667 42.667-42.667s42.667 19.067 42.667 42.667v296c0 1.867-0.133 3.867-0.4 5.733-9.067 67.2-52.4 105.867-118.933 105.867z", + "M539.2 362.133c-4 0-8-0.533-12.133-1.733-10.133-2.933-43.067-16.8-40.667-69.733 1.6-36.4 19.067-82.8 45.6-121.2 24.133-34.8 66.4-79.067 131.2-92.133 74.933-15.2 111.867 7.6 129.733 29.333 23.067 28.133 25.867 69.2 7.6 112.533-27.2 64.667-101.6 134.4-191.067 142.267-14.667 1.333-28.133-4.933-36.8-15.6-8 10.133-20.4 16.267-33.467 16.267zM571.867 291.867c0.133 0.133 0.267 0.4 0.533 0.533 7.067-8.933 17.6-14.933 29.733-16 49.867-4.4 93.733-43.333 113.467-77.6 12.667-22 12.133-35.2 11.2-38-3.067-2-16.8-5.733-46.667 0.267-42.267 8.533-70.133 44.133-82.933 64.667-18 28.667-24.267 54.133-25.333 66.133zM551.2 278.533c0.133 0 0.133 0 0 0 0.133 0 0.133 0 0 0z", + "M514.267 697.2l-85.733 52.533c-8.933 5.467-20.533 2.667-26-6.267-2.667-4.4-3.467-9.6-2.267-14.533l13.333-52.267c4.8-18.8 17.733-34.667 35.2-43.067l93.467-44.933c4.4-2.133 6.133-7.333 4.133-11.733-1.733-3.467-5.467-5.467-9.333-4.8l-104.133 18c-21.2 3.6-42.8-2.133-59.333-16l-32.933-27.467c-8-6.667-9.067-18.667-2.4-26.667 3.2-3.867 8-6.267 13.067-6.667l100.4-7.867c7.067-0.533 13.333-5.067 16-11.6l38.8-93.6c4-9.6 15.067-14.267 24.667-10.267 4.667 1.867 8.267 5.6 10.267 10.267l38.8 93.6c2.667 6.533 8.933 11.067 16 11.6l101.067 7.867c10.4 0.8 18.267 9.867 17.333 20.4-0.4 5.067-2.8 9.6-6.533 12.933l-77.067 65.733c-5.467 4.667-7.733 11.867-6.133 18.8l23.733 98.4c2.4 10.133-3.867 20.4-14 22.8-4.933 1.2-10 0.4-14.267-2.267l-86.4-52.933c-6.133-3.733-13.733-3.733-19.733 0v0z" ], "attrs": [ + {}, + {}, + {}, + {}, + {}, + {}, + {}, {}, {} ], @@ -751,9 +773,24 @@ "isMulticolor2": false, "grid": 24, "tags": [ - "sort" + "gift" ] }, + { + "id": 76, + "paths": [ + "M128 341.867h768c25.6 0 42.667-17.067 42.667-42.667s-17.067-42.667-42.667-42.667h-768c-25.6 0-42.667 17.067-42.667 42.667s17.067 42.667 42.667 42.667zM130.667 554.667h768c25.6 0 42.667-17.067 42.667-42.667s-17.067-42.667-42.667-42.667h-768c-25.6 0-42.667 17.067-42.667 42.667s17.067 42.667 42.667 42.667zM130.667 768h768c25.6 0 42.667-17.067 42.667-42.667s-17.067-42.667-42.667-42.667h-768c-25.6 0-42.667 17.067-42.667 42.667s17.067 42.667 42.667 42.667z" + ], + "attrs": [ + {} + ], + "grid": 24, + "tags": [ + "sort" + ], + "isMulticolor": false, + "isMulticolor2": false + }, { "id": 75, "paths": [ @@ -3416,7 +3453,7 @@ "name": "select", "prevSize": 32, "code": 59744, - "tempChar": "" + "tempChar": "" }, { "order": 480, @@ -3424,7 +3461,7 @@ "name": "folder", "prevSize": 32, "code": 59667, - "tempChar": "" + "tempChar": "" }, { "order": 481, @@ -3432,7 +3469,7 @@ "name": "bots", "prevSize": 32, "code": 59669, - "tempChar": "" + "tempChar": "" }, { "order": 482, @@ -3440,7 +3477,7 @@ "name": "calendar", "prevSize": 32, "code": 59670, - "tempChar": "" + "tempChar": "" }, { "order": 483, @@ -3448,7 +3485,7 @@ "name": "cloud-download", "prevSize": 32, "code": 59671, - "tempChar": "" + "tempChar": "" }, { "order": 484, @@ -3456,7 +3493,7 @@ "name": "colorize", "prevSize": 32, "code": 59672, - "tempChar": "" + "tempChar": "" }, { "order": 651, @@ -3464,7 +3501,7 @@ "name": "forward", "prevSize": 32, "code": 59687, - "tempChar": "" + "tempChar": "" }, { "order": 650, @@ -3472,7 +3509,7 @@ "name": "reply", "prevSize": 32, "code": 59719, - "tempChar": "" + "tempChar": "" }, { "order": 487, @@ -3480,7 +3517,7 @@ "name": "help", "prevSize": 32, "code": 59690, - "tempChar": "" + "tempChar": "" }, { "order": 488, @@ -3488,7 +3525,7 @@ "name": "info", "prevSize": 32, "code": 59691, - "tempChar": "" + "tempChar": "" }, { "order": 489, @@ -3496,7 +3533,7 @@ "name": "info-filled", "prevSize": 32, "code": 59675, - "tempChar": "" + "tempChar": "" }, { "order": 490, @@ -3504,7 +3541,7 @@ "name": "delete-filled", "prevSize": 32, "code": 59676, - "tempChar": "" + "tempChar": "" }, { "order": 491, @@ -3512,7 +3549,7 @@ "name": "delete", "prevSize": 32, "code": 59677, - "tempChar": "" + "tempChar": "" }, { "order": 492, @@ -3520,7 +3557,7 @@ "name": "edit", "prevSize": 32, "code": 59683, - "tempChar": "" + "tempChar": "" }, { "order": 493, @@ -3528,7 +3565,7 @@ "name": "new-chat-filled", "prevSize": 32, "code": 59705, - "tempChar": "" + "tempChar": "" }, { "order": 494, @@ -3536,7 +3573,7 @@ "name": "send", "prevSize": 32, "code": 59722, - "tempChar": "" + "tempChar": "" }, { "order": 495, @@ -3544,7 +3581,7 @@ "name": "send-outline", "prevSize": 32, "code": 59723, - "tempChar": "" + "tempChar": "" }, { "order": 496, @@ -3552,7 +3589,7 @@ "name": "add-user-filled", "prevSize": 32, "code": 59652, - "tempChar": "" + "tempChar": "" }, { "order": 497, @@ -3560,7 +3597,7 @@ "name": "add-user", "prevSize": 32, "code": 59653, - "tempChar": "" + "tempChar": "" }, { "order": 498, @@ -3568,7 +3605,7 @@ "name": "delete-user", "prevSize": 32, "code": 59678, - "tempChar": "" + "tempChar": "" }, { "order": 499, @@ -3576,7 +3613,7 @@ "name": "microphone", "prevSize": 32, "code": 59701, - "tempChar": "" + "tempChar": "" }, { "order": 500, @@ -3584,7 +3621,7 @@ "name": "microphone-alt", "prevSize": 32, "code": 59707, - "tempChar": "" + "tempChar": "" }, { "order": 501, @@ -3592,7 +3629,7 @@ "name": "poll", "prevSize": 32, "code": 59704, - "tempChar": "" + "tempChar": "" }, { "order": 502, @@ -3600,7 +3637,7 @@ "name": "revote", "prevSize": 32, "code": 59706, - "tempChar": "" + "tempChar": "" }, { "order": 503, @@ -3608,7 +3645,7 @@ "name": "photo", "prevSize": 32, "code": 59712, - "tempChar": "" + "tempChar": "" }, { "order": 504, @@ -3616,7 +3653,7 @@ "name": "document", "prevSize": 32, "code": 59679, - "tempChar": "" + "tempChar": "" }, { "order": 505, @@ -3624,7 +3661,7 @@ "name": "camera", "prevSize": 32, "code": 59662, - "tempChar": "" + "tempChar": "" }, { "order": 506, @@ -3632,7 +3669,7 @@ "name": "camera-add", "prevSize": 32, "code": 59663, - "tempChar": "" + "tempChar": "" }, { "order": 507, @@ -3640,7 +3677,7 @@ "name": "logout", "prevSize": 32, "code": 59698, - "tempChar": "" + "tempChar": "" }, { "order": 508, @@ -3648,7 +3685,7 @@ "name": "saved-messages", "prevSize": 32, "code": 59720, - "tempChar": "" + "tempChar": "" }, { "order": 509, @@ -3656,7 +3693,7 @@ "name": "settings", "prevSize": 32, "code": 59726, - "tempChar": "" + "tempChar": "" }, { "order": 652, @@ -3664,7 +3701,7 @@ "name": "phone", "prevSize": 32, "code": 59711, - "tempChar": "" + "tempChar": "" }, { "order": 653, @@ -3672,7 +3709,7 @@ "name": "attach", "prevSize": 32, "code": 59657, - "tempChar": "" + "tempChar": "" }, { "order": 512, @@ -3680,7 +3717,7 @@ "name": "copy", "prevSize": 32, "code": 59674, - "tempChar": "" + "tempChar": "" }, { "order": 513, @@ -3688,7 +3725,7 @@ "name": "channel", "prevSize": 32, "code": 59665, - "tempChar": "" + "tempChar": "" }, { "order": 514, @@ -3696,7 +3733,7 @@ "name": "group", "prevSize": 32, "code": 59689, - "tempChar": "" + "tempChar": "" }, { "order": 515, @@ -3704,7 +3741,7 @@ "name": "user", "prevSize": 32, "code": 59737, - "tempChar": "" + "tempChar": "" }, { "order": 516, @@ -3712,7 +3749,7 @@ "name": "non-contacts", "prevSize": 32, "code": 59688, - "tempChar": "" + "tempChar": "" }, { "order": 517, @@ -3720,7 +3757,7 @@ "name": "active-sessions", "prevSize": 32, "code": 59650, - "tempChar": "" + "tempChar": "" }, { "order": 518, @@ -3728,7 +3765,7 @@ "name": "admin", "prevSize": 32, "code": 59654, - "tempChar": "" + "tempChar": "" }, { "order": 519, @@ -3736,7 +3773,7 @@ "name": "download", "prevSize": 32, "code": 59681, - "tempChar": "" + "tempChar": "" }, { "order": 520, @@ -3744,7 +3781,7 @@ "name": "location", "prevSize": 32, "code": 59696, - "tempChar": "" + "tempChar": "" }, { "order": 521, @@ -3752,7 +3789,7 @@ "name": "stop", "prevSize": 32, "code": 59730, - "tempChar": "" + "tempChar": "" }, { "order": 523, @@ -3760,7 +3797,7 @@ "name": "archive", "prevSize": 32, "code": 59656, - "tempChar": "" + "tempChar": "" }, { "order": 524, @@ -3768,7 +3805,7 @@ "name": "unarchive", "prevSize": 32, "code": 59731, - "tempChar": "" + "tempChar": "" }, { "order": 525, @@ -3776,7 +3813,7 @@ "name": "readchats", "prevSize": 32, "code": 59699, - "tempChar": "" + "tempChar": "" }, { "order": 526, @@ -3784,7 +3821,7 @@ "name": "unread", "prevSize": 32, "code": 59735, - "tempChar": "" + "tempChar": "" }, { "order": 654, @@ -3792,7 +3829,7 @@ "name": "message", "prevSize": 32, "code": 59700, - "tempChar": "" + "tempChar": "" }, { "order": 659, @@ -3800,7 +3837,7 @@ "name": "lock", "prevSize": 32, "code": 59697, - "tempChar": "" + "tempChar": "" }, { "order": 529, @@ -3808,7 +3845,7 @@ "name": "unlock", "prevSize": 32, "code": 59732, - "tempChar": "" + "tempChar": "" }, { "order": 530, @@ -3816,7 +3853,7 @@ "name": "mute", "prevSize": 32, "code": 59703, - "tempChar": "" + "tempChar": "" }, { "order": 531, @@ -3824,7 +3861,7 @@ "name": "unmute", "prevSize": 32, "code": 59733, - "tempChar": "" + "tempChar": "" }, { "order": 532, @@ -3832,7 +3869,7 @@ "name": "pin", "prevSize": 32, "code": 59713, - "tempChar": "" + "tempChar": "" }, { "order": 533, @@ -3840,7 +3877,7 @@ "name": "unpin", "prevSize": 32, "code": 59734, - "tempChar": "" + "tempChar": "" }, { "order": 534, @@ -3848,7 +3885,7 @@ "name": "smallscreen", "prevSize": 32, "code": 59742, - "tempChar": "" + "tempChar": "" }, { "order": 535, @@ -3856,7 +3893,7 @@ "name": "fullscreen", "prevSize": 32, "code": 59743, - "tempChar": "" + "tempChar": "" }, { "order": 536, @@ -3864,7 +3901,7 @@ "name": "large-pause", "prevSize": 32, "code": 59694, - "tempChar": "" + "tempChar": "" }, { "order": 537, @@ -3872,7 +3909,7 @@ "name": "large-play", "prevSize": 32, "code": 59695, - "tempChar": "" + "tempChar": "" }, { "order": 538, @@ -3880,7 +3917,7 @@ "name": "pause", "prevSize": 32, "code": 59709, - "tempChar": "" + "tempChar": "" }, { "order": 539, @@ -3888,7 +3925,7 @@ "name": "play", "prevSize": 32, "code": 59715, - "tempChar": "" + "tempChar": "" }, { "order": 540, @@ -3896,7 +3933,7 @@ "name": "channelviews", "prevSize": 32, "code": 59666, - "tempChar": "" + "tempChar": "" }, { "order": 541, @@ -3904,7 +3941,7 @@ "name": "message-succeeded", "prevSize": 32, "code": 59648, - "tempChar": "" + "tempChar": "" }, { "order": 657, @@ -3912,7 +3949,7 @@ "name": "message-read", "prevSize": 32, "code": 59649, - "tempChar": "" + "tempChar": "" }, { "order": 543, @@ -3920,7 +3957,7 @@ "name": "message-pending", "prevSize": 32, "code": 59724, - "tempChar": "" + "tempChar": "" }, { "order": 544, @@ -3928,7 +3965,7 @@ "name": "message-failed", "prevSize": 32, "code": 59725, - "tempChar": "" + "tempChar": "" }, { "order": 545, @@ -3936,7 +3973,7 @@ "name": "favorite", "prevSize": 32, "code": 59710, - "tempChar": "" + "tempChar": "" }, { "order": 546, @@ -3944,7 +3981,7 @@ "name": "keyboard", "prevSize": 32, "code": 59716, - "tempChar": "" + "tempChar": "" }, { "order": 547, @@ -3952,7 +3989,7 @@ "name": "delete-left", "prevSize": 32, "code": 59717, - "tempChar": "" + "tempChar": "" }, { "order": 548, @@ -3960,7 +3997,7 @@ "name": "recent", "prevSize": 32, "code": 59718, - "tempChar": "" + "tempChar": "" }, { "order": 549, @@ -3968,7 +4005,7 @@ "name": "gifs", "prevSize": 32, "code": 59727, - "tempChar": "" + "tempChar": "" }, { "order": 550, @@ -3976,7 +4013,7 @@ "name": "stickers", "prevSize": 32, "code": 59739, - "tempChar": "" + "tempChar": "" }, { "order": 551, @@ -3984,7 +4021,7 @@ "name": "smile", "prevSize": 32, "code": 59728, - "tempChar": "" + "tempChar": "" }, { "order": 552, @@ -3992,7 +4029,7 @@ "name": "animals", "prevSize": 32, "code": 59655, - "tempChar": "" + "tempChar": "" }, { "order": 553, @@ -4000,7 +4037,7 @@ "name": "eats", "prevSize": 32, "code": 59682, - "tempChar": "" + "tempChar": "" }, { "order": 554, @@ -4008,7 +4045,7 @@ "name": "sport", "prevSize": 32, "code": 59729, - "tempChar": "" + "tempChar": "" }, { "order": 555, @@ -4016,7 +4053,7 @@ "name": "car", "prevSize": 32, "code": 59664, - "tempChar": "" + "tempChar": "" }, { "order": 556, @@ -4024,7 +4061,7 @@ "name": "lamp", "prevSize": 32, "code": 59692, - "tempChar": "" + "tempChar": "" }, { "order": 557, @@ -4032,7 +4069,7 @@ "name": "language", "prevSize": 32, "code": 59693, - "tempChar": "" + "tempChar": "" }, { "order": 558, @@ -4040,7 +4077,7 @@ "name": "flag", "prevSize": 32, "code": 59686, - "tempChar": "" + "tempChar": "" }, { "order": 559, @@ -4048,7 +4085,7 @@ "name": "more", "prevSize": 32, "code": 59702, - "tempChar": "" + "tempChar": "" }, { "order": 560, @@ -4056,7 +4093,7 @@ "name": "search", "prevSize": 32, "code": 59721, - "tempChar": "" + "tempChar": "" }, { "order": 561, @@ -4064,7 +4101,7 @@ "name": "remove", "prevSize": 32, "code": 59740, - "tempChar": "" + "tempChar": "" }, { "order": 562, @@ -4072,7 +4109,7 @@ "name": "add", "prevSize": 32, "code": 59651, - "tempChar": "" + "tempChar": "" }, { "order": 563, @@ -4080,7 +4117,7 @@ "name": "check", "prevSize": 32, "code": 59668, - "tempChar": "" + "tempChar": "" }, { "order": 564, @@ -4088,7 +4125,7 @@ "name": "close", "prevSize": 32, "code": 59673, - "tempChar": "" + "tempChar": "" }, { "order": 610, @@ -4096,7 +4133,7 @@ "name": "arrow-left", "prevSize": 32, "code": 59661, - "tempChar": "" + "tempChar": "" }, { "order": 566, @@ -4104,7 +4141,7 @@ "name": "arrow-right", "prevSize": 32, "code": 59708, - "tempChar": "" + "tempChar": "" }, { "order": 730, @@ -4112,7 +4149,7 @@ "name": "down", "prevSize": 32, "code": 59680, - "tempChar": "" + "tempChar": "" }, { "order": 568, @@ -4120,7 +4157,7 @@ "name": "up", "prevSize": 32, "code": 59736, - "tempChar": "" + "tempChar": "" }, { "order": 569, @@ -4128,7 +4165,7 @@ "name": "eye-closed", "prevSize": 32, "code": 59685, - "tempChar": "" + "tempChar": "" }, { "order": 570, @@ -4136,7 +4173,7 @@ "name": "eye", "prevSize": 32, "code": 59684, - "tempChar": "" + "tempChar": "" }, { "order": 571, @@ -4144,7 +4181,7 @@ "name": "muted", "prevSize": 32, "code": 59741, - "tempChar": "" + "tempChar": "" }, { "order": 572, @@ -4152,7 +4189,7 @@ "name": "avatar-archived-chats", "prevSize": 32, "code": 59658, - "tempChar": "" + "tempChar": "" }, { "order": 573, @@ -4160,7 +4197,7 @@ "name": "avatar-deleted-account", "prevSize": 32, "code": 59659, - "tempChar": "" + "tempChar": "" }, { "order": 574, @@ -4168,7 +4205,7 @@ "name": "avatar-saved-messages", "prevSize": 32, "code": 59660, - "tempChar": "" + "tempChar": "" }, { "order": 575, @@ -4176,7 +4213,7 @@ "name": "pinned-chat", "prevSize": 32, "code": 59714, - "tempChar": "" + "tempChar": "" } ], "prevSize": 32, diff --git a/src/styles/icons.scss b/src/styles/icons.scss index befb49ead..ff5bd44ef 100644 --- a/src/styles/icons.scss +++ b/src/styles/icons.scss @@ -51,6 +51,9 @@ .icon-volume-3:before { content: "\e991"; } +.icon-gift:before { + content: "\e9ad"; +} .icon-sort:before { content: "\e9ac"; } diff --git a/src/util/langProvider.ts b/src/util/langProvider.ts index 488dce6dd..c1b9da425 100644 --- a/src/util/langProvider.ts +++ b/src/util/langProvider.ts @@ -204,14 +204,14 @@ function processTemplate(template: string, value: any) { const initialValue = translationSlices.shift(); return translationSlices.reduce((result, str, index) => { - return `${result}${String(value[index] || '')}${str}`; + return `${result}${String(value[index] ?? '')}${str}`; }, initialValue || ''); } function processTranslation(langString: ApiLangString | undefined, key: string, value?: any, format?: 'i') { - const preferedPluralOption = typeof value === 'number' ? getPluralOption(value) : 'value'; + const preferredPluralOption = typeof value === 'number' ? getPluralOption(value) : 'value'; const template = langString ? ( - langString[preferedPluralOption] || langString.otherValue || langString.value + langString[preferredPluralOption] || langString.otherValue || langString.value ) : undefined; if (!template || !template.trim()) { const parts = key.split('.');