From d5f214fa9a1b3900b9b61c4992df405b660bc515 Mon Sep 17 00:00:00 2001 From: zubiden <19638254+zubiden@users.noreply.github.com> Date: Mon, 27 Jan 2025 23:51:10 +0100 Subject: [PATCH] Unique Gift: Support withdrawal (#5534) --- src/api/gramjs/apiBuilders/bots.ts | 2 +- src/api/gramjs/apiBuilders/chats.ts | 3 +- src/api/gramjs/apiBuilders/gifts.ts | 5 +- src/api/gramjs/apiBuilders/messageContent.ts | 5 +- src/api/gramjs/apiBuilders/messages.ts | 5 +- src/api/gramjs/apiBuilders/misc.ts | 2 +- src/api/gramjs/apiBuilders/payments.ts | 2 +- src/api/gramjs/gramjsBuilders/index.ts | 2 +- .../gramjs/{helpers.ts => helpers/localDb.ts} | 67 +--- src/api/gramjs/helpers/misc.ts | 179 ++++++++++ src/api/gramjs/methods/auth.ts | 45 +-- src/api/gramjs/methods/bots.ts | 4 +- src/api/gramjs/methods/chats.ts | 4 +- src/api/gramjs/methods/client.ts | 13 +- src/api/gramjs/methods/messages.ts | 2 +- src/api/gramjs/methods/payments.ts | 45 ++- src/api/gramjs/methods/settings.ts | 2 +- src/api/gramjs/methods/statistics.ts | 18 +- src/api/gramjs/methods/stories.ts | 3 +- src/api/gramjs/methods/twoFaSettings.ts | 79 +---- src/api/gramjs/methods/users.ts | 2 +- src/api/gramjs/updates/entityProcessor.ts | 2 +- src/api/gramjs/updates/mtpUpdateHandler.ts | 4 +- src/api/gramjs/worker/worker.ts | 2 +- src/api/types/payments.ts | 1 + src/api/types/updates.ts | 9 +- src/assets/font-icons/fragment.svg | 1 + src/assets/localization/fallback.strings | 32 +- src/assets/localization/initialKeys.ts | 2 +- src/assets/localization/initialStrings.ts | 5 +- src/bundles/stars.ts | 1 + .../VerificationMonetizationModal.async.tsx | 4 +- .../common/VerificationMonetizationModal.tsx | 77 +++-- .../left/settings/twoFa/SettingsTwoFa.tsx | 42 +-- src/components/main/Main.tsx | 2 + src/components/modals/ModalContainer.tsx | 8 +- .../gift/fragment/GiftWithdrawModal.async.tsx | 18 + .../fragment/GiftWithdrawModal.module.scss | 39 +++ .../gift/fragment/GiftWithdrawModal.tsx | 157 +++++++++ .../modals/gift/info/GiftInfoModal.tsx | 11 + src/components/payment/PasswordConfirm.tsx | 18 +- src/components/payment/PaymentInfo.tsx | 32 +- src/components/payment/PaymentModal.tsx | 5 +- src/components/payment/ShippingInfo.tsx | 48 +-- .../statistics/MonetizationStatistics.tsx | 32 +- src/components/story/StorySettings.tsx | 15 +- src/global/actions/all.ts | 2 +- src/global/actions/api/payments.ts | 55 ++- src/global/actions/api/statistics.ts | 27 +- src/global/actions/api/twoFaSettings.ts | 10 +- src/global/actions/apiUpdaters/password.ts | 20 -- .../actions/apiUpdaters/twoFaSettings.ts | 2 +- src/global/actions/ui/stars.ts | 34 +- src/global/actions/ui/statistics.ts | 38 +++ src/global/actions/ui/stories.ts | 8 - src/global/helpers/users.ts | 7 +- src/global/initialState.ts | 2 - src/global/reducers/index.ts | 1 - src/global/reducers/password.ts | 14 - src/global/reducers/statistics.ts | 19 +- src/global/types/actions.ts | 18 +- src/global/types/globalState.ts | 7 +- src/global/types/tabState.ts | 17 +- src/hooks/reducers/usePaymentReducer.ts | 3 +- src/lib/gramjs/client/2fa.ts | 48 +-- src/lib/gramjs/client/TelegramClient.ts | 5 +- src/lib/gramjs/errors/RPCErrorList.ts | 4 +- src/lib/gramjs/tl/apiTl.ts | 1 + src/lib/gramjs/tl/static/api.json | 1 + src/styles/icons.scss | 322 +++++++++--------- src/styles/icons.woff | Bin 31588 -> 31700 bytes src/styles/icons.woff2 | Bin 26400 -> 26476 bytes src/types/icons/font.ts | 1 + src/types/language.d.ts | 28 +- src/util/dates/units.ts | 19 ++ src/util/localization/index.ts | 5 +- src/util/localization/types.ts | 9 +- 77 files changed, 1121 insertions(+), 662 deletions(-) rename src/api/gramjs/{helpers.ts => helpers/localDb.ts} (70%) create mode 100644 src/api/gramjs/helpers/misc.ts create mode 100644 src/assets/font-icons/fragment.svg create mode 100644 src/components/modals/gift/fragment/GiftWithdrawModal.async.tsx create mode 100644 src/components/modals/gift/fragment/GiftWithdrawModal.module.scss create mode 100644 src/components/modals/gift/fragment/GiftWithdrawModal.tsx delete mode 100644 src/global/actions/apiUpdaters/password.ts create mode 100644 src/global/actions/ui/statistics.ts delete mode 100644 src/global/reducers/password.ts create mode 100644 src/util/dates/units.ts diff --git a/src/api/gramjs/apiBuilders/bots.ts b/src/api/gramjs/apiBuilders/bots.ts index a6e7270a6..67b183db1 100644 --- a/src/api/gramjs/apiBuilders/bots.ts +++ b/src/api/gramjs/apiBuilders/bots.ts @@ -19,7 +19,7 @@ import type { import { numberToHexColor } from '../../../util/colors'; import { pick } from '../../../util/iteratees'; -import { addDocumentToLocalDb } from '../helpers'; +import { addDocumentToLocalDb } from '../helpers/localDb'; import { buildApiPhoto, buildApiThumbnailFromStripped } from './common'; import { omitVirtualClassFields } from './helpers'; import { buildApiDocument, buildApiWebDocument, buildVideoFromDocument } from './messageContent'; diff --git a/src/api/gramjs/apiBuilders/chats.ts b/src/api/gramjs/apiBuilders/chats.ts index 93be9d8da..971b673ff 100644 --- a/src/api/gramjs/apiBuilders/chats.ts +++ b/src/api/gramjs/apiBuilders/chats.ts @@ -25,7 +25,8 @@ import type { import { pick, pickTruthy } from '../../../util/iteratees'; import { getServerTime, getServerTimeOffset } from '../../../util/serverTime'; -import { addPhotoToLocalDb, addUserToLocalDb, serializeBytes } from '../helpers'; +import { addPhotoToLocalDb, addUserToLocalDb } from '../helpers/localDb'; +import { serializeBytes } from '../helpers/misc'; import { buildApiBotVerification, buildApiFormattedText, buildApiPhoto, buildApiUsernames, buildAvatarPhotoId, } from './common'; diff --git a/src/api/gramjs/apiBuilders/gifts.ts b/src/api/gramjs/apiBuilders/gifts.ts index d5fa6d2d0..cb0597dc2 100644 --- a/src/api/gramjs/apiBuilders/gifts.ts +++ b/src/api/gramjs/apiBuilders/gifts.ts @@ -8,7 +8,7 @@ import type { } from '../../types'; import { numberToHexColor } from '../../../util/colors'; -import { addDocumentToLocalDb } from '../helpers'; +import { addDocumentToLocalDb } from '../helpers/localDb'; import { buildApiFormattedText } from './common'; import { getApiChatIdFromMtpPeer } from './peers'; import { buildStickerFromDocument } from './symbols'; @@ -129,7 +129,7 @@ export function buildApiStarGiftAttribute(attribute: GramJs.TypeStarGiftAttribut export function buildApiSavedStarGift(userStarGift: GramJs.SavedStarGift, peerId: string): ApiSavedStarGift { const { gift, date, convertStars, fromId, message, msgId, nameHidden, unsaved, upgradeStars, transferStars, canUpgrade, - savedId, + savedId, canExportAt, } = userStarGift; const inputGift: ApiInputSavedStarGift | undefined = savedId && peerId @@ -150,5 +150,6 @@ export function buildApiSavedStarGift(userStarGift: GramJs.SavedStarGift, peerId transferStars: transferStars?.toJSNumber(), inputGift, savedId: savedId?.toString(), + canExportAt, }; } diff --git a/src/api/gramjs/apiBuilders/messageContent.ts b/src/api/gramjs/apiBuilders/messageContent.ts index 84b7c4a48..5e1887c5f 100644 --- a/src/api/gramjs/apiBuilders/messageContent.ts +++ b/src/api/gramjs/apiBuilders/messageContent.ts @@ -32,8 +32,9 @@ import { SUPPORTED_PHOTO_CONTENT_TYPES, SUPPORTED_VIDEO_CONTENT_TYPES, VIDEO_WEB import { generateWaveform } from '../../../util/generateWaveform'; import { pick } from '../../../util/iteratees'; import { - addMediaToLocalDb, addStoryToLocalDb, type MediaRepairContext, serializeBytes, -} from '../helpers'; + addMediaToLocalDb, addStoryToLocalDb, type MediaRepairContext, +} from '../helpers/localDb'; +import { serializeBytes } from '../helpers/misc'; import { buildApiFormattedText, buildApiMessageEntity, diff --git a/src/api/gramjs/apiBuilders/messages.ts b/src/api/gramjs/apiBuilders/messages.ts index 4c4d7c838..3a40a81e8 100644 --- a/src/api/gramjs/apiBuilders/messages.ts +++ b/src/api/gramjs/apiBuilders/messages.ts @@ -58,9 +58,8 @@ import { buildPeer } from '../gramjsBuilders'; import { addPhotoToLocalDb, type MediaRepairContext, - resolveMessageApiChatId, - serializeBytes, -} from '../helpers'; +} from '../helpers/localDb'; +import { resolveMessageApiChatId, serializeBytes } from '../helpers/misc'; import { buildApiCallDiscardReason } from './calls'; import { buildApiFormattedText, diff --git a/src/api/gramjs/apiBuilders/misc.ts b/src/api/gramjs/apiBuilders/misc.ts index 16c93c815..686ec064c 100644 --- a/src/api/gramjs/apiBuilders/misc.ts +++ b/src/api/gramjs/apiBuilders/misc.ts @@ -22,7 +22,7 @@ import { buildCollectionByCallback, omit, omitUndefined, pick, } from '../../../util/iteratees'; import { getServerTime } from '../../../util/serverTime'; -import { addUserToLocalDb } from '../helpers'; +import { addUserToLocalDb } from '../helpers/localDb'; import { omitVirtualClassFields } from './helpers'; import { buildApiDocument, buildMessageTextContent } from './messageContent'; import { buildApiPeerId, getApiChatIdFromMtpPeer } from './peers'; diff --git a/src/api/gramjs/apiBuilders/payments.ts b/src/api/gramjs/apiBuilders/payments.ts index 5634e37b3..a1afb5136 100644 --- a/src/api/gramjs/apiBuilders/payments.ts +++ b/src/api/gramjs/apiBuilders/payments.ts @@ -29,7 +29,7 @@ import type { BoughtPaidMedia, } from '../../types'; -import { addWebDocumentToLocalDb } from '../helpers'; +import { addWebDocumentToLocalDb } from '../helpers/localDb'; import { buildApiStarsSubscriptionPricing } from './chats'; import { buildApiMessageEntity } from './common'; import { buildApiStarGift } from './gifts'; diff --git a/src/api/gramjs/gramjsBuilders/index.ts b/src/api/gramjs/gramjsBuilders/index.ts index 241cc026b..f44885f4d 100644 --- a/src/api/gramjs/gramjsBuilders/index.ts +++ b/src/api/gramjs/gramjsBuilders/index.ts @@ -37,7 +37,7 @@ import { import { CHANNEL_ID_LENGTH, DEFAULT_STATUS_ICON_ID } from '../../../config'; import { pick } from '../../../util/iteratees'; -import { deserializeBytes } from '../helpers'; +import { deserializeBytes } from '../helpers/misc'; import localDb from '../localDb'; function checkIfChannelId(id: string) { diff --git a/src/api/gramjs/helpers.ts b/src/api/gramjs/helpers/localDb.ts similarity index 70% rename from src/api/gramjs/helpers.ts rename to src/api/gramjs/helpers/localDb.ts index d72ee3ae5..ed2b68e39 100644 --- a/src/api/gramjs/helpers.ts +++ b/src/api/gramjs/helpers/localDb.ts @@ -1,42 +1,11 @@ -import { Api as GramJs } from '../../lib/gramjs'; +import { Api as GramJs } from '../../../lib/gramjs'; -import type { RepairInfo } from './localDb'; - -import { buildApiPeerId, getApiChatIdFromMtpPeer } from './apiBuilders/peers'; -import localDb from './localDb'; - -const LOG_BACKGROUND = '#111111DD'; -const LOG_PREFIX_COLOR = '#E4D00A'; -const LOG_SUFFIX = { - INVOKE: '#49DBF5', - BEACON: '#F549DB', - RESPONSE: '#6887F7', - CONNECTING: '#E4D00A', - CONNECTED: '#26D907', - 'CONNECTING ERROR': '#D1191C', - 'INVOKE ERROR': '#D1191C', - UPDATE: '#0DD151', - 'UNEXPECTED UPDATE': '#9C9C9C', - 'UNEXPECTED RESPONSE': '#D1191C', -}; +import { buildApiPeerId, getApiChatIdFromMtpPeer } from '../apiBuilders/peers'; +import localDb, { type RepairInfo } from '../localDb'; export type MessageRepairContext = Pick; export type MediaRepairContext = MessageRepairContext; -export function resolveMessageApiChatId(mtpMessage: GramJs.TypeMessage) { - if (!(mtpMessage instanceof GramJs.Message || mtpMessage instanceof GramJs.MessageService)) { - return undefined; - } - - return getApiChatIdFromMtpPeer(mtpMessage.peerId); -} - -export function isChatFolder( - filter?: GramJs.TypeDialogFilter, -): filter is GramJs.DialogFilter | GramJs.DialogFilterChatlist { - return filter instanceof GramJs.DialogFilter || filter instanceof GramJs.DialogFilterChatlist; -} - export function addMessageToLocalDb(message: GramJs.TypeMessage | GramJs.TypeSponsoredMessage) { if (message instanceof GramJs.Message) { if (message.media) addMediaToLocalDb(message.media, message); @@ -204,33 +173,3 @@ export function addUserToLocalDb(user: GramJs.User) { export function addWebDocumentToLocalDb(webDocument: GramJs.TypeWebDocument) { localDb.webDocuments[webDocument.url] = webDocument; } - -export function serializeBytes(value: Buffer) { - return String.fromCharCode(...value); -} - -export function deserializeBytes(value: string) { - return Buffer.from(value, 'binary'); -} - -export function log(suffix: keyof typeof LOG_SUFFIX, ...data: any) { - /* eslint-disable max-len */ - /* eslint-disable no-console */ - const func = suffix === 'UNEXPECTED RESPONSE' ? console.error - : suffix === 'INVOKE ERROR' || suffix === 'UNEXPECTED UPDATE' ? console.warn : console.log; - /* eslint-enable no-console */ - func( - `%cGramJS%c${suffix}`, - `color: ${LOG_PREFIX_COLOR}; background: ${LOG_BACKGROUND}; padding: 0.25rem; border-radius: 0.25rem;`, - `color: ${LOG_SUFFIX[suffix]}; background: ${LOG_BACKGROUND}; padding: 0.25rem; border-radius: 0.25rem; margin-left: 0.25rem;`, - ...data, - ); - /* eslint-enable max-len */ -} - -export function isResponseUpdate(result: T['__response']): result is GramJs.TypeUpdate { - return result instanceof GramJs.UpdatesTooLong || result instanceof GramJs.UpdateShortMessage - || result instanceof GramJs.UpdateShortChatMessage || result instanceof GramJs.UpdateShort - || result instanceof GramJs.UpdatesCombined || result instanceof GramJs.Updates - || result instanceof GramJs.UpdateShortSentMessage; -} diff --git a/src/api/gramjs/helpers/misc.ts b/src/api/gramjs/helpers/misc.ts new file mode 100644 index 000000000..9a9dc50d4 --- /dev/null +++ b/src/api/gramjs/helpers/misc.ts @@ -0,0 +1,179 @@ +import { Api as GramJs, errors } from '../../../lib/gramjs'; + +import type { RegularLangKey } from '../../../types/language'; +import type { RegularLangFnParameters } from '../../../util/localization'; + +import { DEBUG } from '../../../config'; +import { + DAY, getDays, getHours, getMinutes, HOUR, MINUTE, +} from '../../../util/dates/units'; +import { getApiChatIdFromMtpPeer } from '../apiBuilders/peers'; + +const LOG_BACKGROUND = '#111111DD'; +const LOG_PREFIX_COLOR = '#E4D00A'; +const LOG_SUFFIX = { + INVOKE: '#49DBF5', + BEACON: '#F549DB', + RESPONSE: '#6887F7', + CONNECTING: '#E4D00A', + CONNECTED: '#26D907', + 'CONNECTING ERROR': '#D1191C', + 'INVOKE ERROR': '#D1191C', + UPDATE: '#0DD151', + 'UNEXPECTED UPDATE': '#9C9C9C', + 'UNEXPECTED RESPONSE': '#D1191C', +}; + +const ERROR_KEYS: Record = { + PHONE_NUMBER_INVALID: 'ErrorPhoneNumberInvalid', + PHONE_CODE_INVALID: 'ErrorCodeInvalid', + PASSWORD_HASH_INVALID: 'ErrorIncorrectPassword', + PHONE_PASSWORD_FLOOD: 'ErrorPasswordFlood', + PHONE_NUMBER_BANNED: 'ErrorPhoneBanned', + EMAIL_UNCONFIRMED: 'ErrorEmailUnconfirmed', + EMAIL_HASH_EXPIRED: 'ErrorEmailHashExpired', + NEW_SALT_INVALID: 'ErrorNewSaltInvalid', + SRP_PASSWORD_CHANGED: 'ErrorPasswordChanged', + CODE_INVALID: 'ErrorEmailCodeInvalid', + PASSWORD_MISSING: 'ErrorPasswordMissing', +}; + +export type MessageRepairContext = Pick; +export type MediaRepairContext = MessageRepairContext; + +export type WrappedError = { + messageKey: RegularLangFnParameters; + errorMessage?: string; + error: T; +}; + +export function resolveMessageApiChatId(mtpMessage: GramJs.TypeMessage) { + if (!(mtpMessage instanceof GramJs.Message || mtpMessage instanceof GramJs.MessageService)) { + return undefined; + } + + return getApiChatIdFromMtpPeer(mtpMessage.peerId); +} + +export function isChatFolder( + filter?: GramJs.TypeDialogFilter, +): filter is GramJs.DialogFilter | GramJs.DialogFilterChatlist { + return filter instanceof GramJs.DialogFilter || filter instanceof GramJs.DialogFilterChatlist; +} + +export function serializeBytes(value: Buffer) { + return String.fromCharCode(...value); +} + +export function deserializeBytes(value: string) { + return Buffer.from(value, 'binary'); +} + +export function log(suffix: keyof typeof LOG_SUFFIX, ...data: any) { + /* eslint-disable max-len */ + /* eslint-disable no-console */ + const func = suffix === 'UNEXPECTED RESPONSE' ? console.error + : suffix === 'INVOKE ERROR' || suffix === 'UNEXPECTED UPDATE' ? console.warn : console.log; + /* eslint-enable no-console */ + func( + `%cGramJS%c${suffix}`, + `color: ${LOG_PREFIX_COLOR}; background: ${LOG_BACKGROUND}; padding: 0.25rem; border-radius: 0.25rem;`, + `color: ${LOG_SUFFIX[suffix]}; background: ${LOG_BACKGROUND}; padding: 0.25rem; border-radius: 0.25rem; margin-left: 0.25rem;`, + ...data, + ); + /* eslint-enable max-len */ +} + +export function isResponseUpdate(result: T['__response']): result is GramJs.TypeUpdate { + return result instanceof GramJs.UpdatesTooLong || result instanceof GramJs.UpdateShortMessage + || result instanceof GramJs.UpdateShortChatMessage || result instanceof GramJs.UpdateShort + || result instanceof GramJs.UpdatesCombined || result instanceof GramJs.Updates + || result instanceof GramJs.UpdateShortSentMessage; +} + +export function checkErrorType(error: unknown): error is Error { + if (!(error instanceof Error)) { + // eslint-disable-next-line no-console + if (DEBUG) console.warn('Unexpected error type', error); + return false; + } + + return true; +} + +export function wrapError(error: T): WrappedError { + let messageKey: RegularLangFnParameters | undefined; + + const errorMessage = error instanceof errors.RPCError ? error.errorMessage : undefined; + + if (error instanceof errors.FloodWaitError) { + messageKey = { + key: 'ErrorFloodTime', + variables: { time: formatWait(error.seconds) }, + }; + } else if (error instanceof errors.PasswordFreshError) { + messageKey = { + key: 'ErrorPasswordFresh', + variables: { time: formatWait(error.seconds) }, + }; + } else if (error instanceof errors.RPCError) { + messageKey = { + key: ERROR_KEYS[error.errorMessage], + }; + } + + if (!messageKey) { + if (error.message) { + messageKey = { + key: 'ErrorUnexpectedMessage', + variables: { error: error.message }, + }; + } else { + messageKey = { + key: 'ErrorUnexpected', + }; + } + } + + return { + messageKey, + errorMessage, + error, + }; +} + +function formatWait(seconds: number): RegularLangFnParameters { + if (seconds < MINUTE) { + return { + key: 'Seconds', + variables: { count: seconds }, + options: { pluralValue: seconds }, + }; + } + + if (seconds < HOUR) { + const minutes = getMinutes(seconds); + return { + key: 'Minutes', + variables: { count: minutes }, + options: { pluralValue: minutes }, + }; + } + + if (seconds < DAY) { + const hours = getHours(seconds); + return { + key: 'Hours', + variables: { count: hours }, + options: { pluralValue: hours }, + }; + } + + const days = getDays(seconds); + + return { + key: 'Days', + variables: { count: days }, + options: { pluralValue: days }, + }; +} diff --git a/src/api/gramjs/methods/auth.ts b/src/api/gramjs/methods/auth.ts index 923f9e773..ed1a62a7d 100644 --- a/src/api/gramjs/methods/auth.ts +++ b/src/api/gramjs/methods/auth.ts @@ -1,7 +1,3 @@ -import { FloodWaitError, RPCError } from '../../../lib/gramjs/errors'; - -import type { RegularLangKey } from '../../../types/language'; -import type { RegularLangFnParameters } from '../../../util/localization'; import type { ApiUpdateAuthorizationState, ApiUpdateAuthorizationStateType, @@ -9,17 +5,9 @@ import type { ApiUserFullInfo, } from '../../types'; -import { DEBUG } from '../../../config'; +import { wrapError } from '../helpers/misc'; import { sendApiUpdate } from '../updates/apiUpdateEmitter'; -const ApiErrors: Record = { - PHONE_NUMBER_INVALID: 'ErrorPhoneNumberInvalid', - PHONE_CODE_INVALID: 'ErrorCodeInvalid', - PASSWORD_HASH_INVALID: 'ErrorIncorrectPassword', - PHONE_PASSWORD_FLOOD: 'ErrorPasswordFlood', - PHONE_NUMBER_BANNED: 'ErrorPhoneBanned', -}; - const authController: { resolve?: Function; reject?: Function; @@ -87,36 +75,7 @@ export function onRequestQrCode(qrCode: { token: Buffer; expires: number }) { } export function onAuthError(err: Error) { - let messageKey: RegularLangFnParameters | undefined; - - if (err instanceof FloodWaitError) { - const hours = Math.ceil(Number(err.seconds) / 60 / 60); - messageKey = { - key: 'ErrorFlood', - variables: { hour: hours }, - options: { pluralValue: hours }, - }; - } else if (err instanceof RPCError) { - messageKey = { - key: ApiErrors[err.errorMessage], - }; - } else if (err.message) { - messageKey = { - key: 'ErrorUnexpectedMessage', - variables: { error: err.message }, - }; - } - - if (!messageKey) { - messageKey = { - key: 'ErrorUnexpected', - }; - - if (DEBUG) { - // eslint-disable-next-line no-console - console.error(err); - } - } + const { messageKey } = wrapError(err); sendApiUpdate({ '@type': 'updateAuthorizationError', diff --git a/src/api/gramjs/methods/bots.ts b/src/api/gramjs/methods/bots.ts index d348ff957..d44112d16 100644 --- a/src/api/gramjs/methods/bots.ts +++ b/src/api/gramjs/methods/bots.ts @@ -39,8 +39,8 @@ import { addPhotoToLocalDb, addUserToLocalDb, addWebDocumentToLocalDb, - deserializeBytes, -} from '../helpers'; +} from '../helpers/localDb'; +import { deserializeBytes } from '../helpers/misc'; import { sendApiUpdate } from '../updates/apiUpdateEmitter'; import { invokeRequest } from './client'; diff --git a/src/api/gramjs/methods/chats.ts b/src/api/gramjs/methods/chats.ts index 5acc8c53f..fbfe2040b 100644 --- a/src/api/gramjs/methods/chats.ts +++ b/src/api/gramjs/methods/chats.ts @@ -69,8 +69,8 @@ import { } from '../gramjsBuilders'; import { addPhotoToLocalDb, - isChatFolder, -} from '../helpers'; +} from '../helpers/localDb'; +import { isChatFolder } from '../helpers/misc'; import { scheduleMutedChatUpdate } from '../scheduleUnmute'; import { sendApiUpdate } from '../updates/apiUpdateEmitter'; import { diff --git a/src/api/gramjs/methods/client.ts b/src/api/gramjs/methods/client.ts index 8bab90fdb..0610cae3d 100644 --- a/src/api/gramjs/methods/client.ts +++ b/src/api/gramjs/methods/client.ts @@ -3,7 +3,7 @@ import { sessions, type Update, } from '../../../lib/gramjs'; -import type { TwoFaParams, TwoFaPasswordParams } from '../../../lib/gramjs/client/2fa'; +import type { TwoFaParams } from '../../../lib/gramjs/client/2fa'; import TelegramClient from '../../../lib/gramjs/client/TelegramClient'; import { RPCError } from '../../../lib/gramjs/errors'; import { Logger as GramJsLogger } from '../../../lib/gramjs/extensions/index'; @@ -30,8 +30,11 @@ import { buildApiStory } from '../apiBuilders/stories'; import { buildApiUser, buildApiUserFullInfo } from '../apiBuilders/users'; import { buildInputPeerFromLocalDb, getEntityTypeById } from '../gramjsBuilders'; import { - addStoryToLocalDb, addUserToLocalDb, isResponseUpdate, log, -} from '../helpers'; + addStoryToLocalDb, addUserToLocalDb, +} from '../helpers/localDb'; +import { + isResponseUpdate, log, +} from '../helpers/misc'; import localDb, { clearLocalDb, type RepairInfo } from '../localDb'; import { sendApiUpdate } from '../updates/apiUpdateEmitter'; import { processAndUpdateEntities, processMessageAndUpdateThreadInfo } from '../updates/entityProcessor'; @@ -376,8 +379,8 @@ export function getTmpPassword(currentPassword: string, ttl?: number) { return client.getTmpPassword(currentPassword, ttl); } -export function getCurrentPassword(params: TwoFaPasswordParams) { - return client.getCurrentPassword(params); +export function getCurrentPassword(currentPassword?: string) { + return client.getCurrentPassword(currentPassword); } export function abortChatRequests(params: { chatId: string; threadId?: ThreadId }) { diff --git a/src/api/gramjs/methods/messages.ts b/src/api/gramjs/methods/messages.ts index 7b2938583..231d03efc 100644 --- a/src/api/gramjs/methods/messages.ts +++ b/src/api/gramjs/methods/messages.ts @@ -89,7 +89,7 @@ import { import { deserializeBytes, resolveMessageApiChatId, -} from '../helpers'; +} from '../helpers/misc'; import { sendApiUpdate } from '../updates/apiUpdateEmitter'; import { processMessageAndUpdateThreadInfo } from '../updates/entityProcessor'; import { processAffectedHistory, updateChannelState } from '../updates/updateManager'; diff --git a/src/api/gramjs/methods/payments.ts b/src/api/gramjs/methods/payments.ts index 41d2e2980..b265eeb86 100644 --- a/src/api/gramjs/methods/payments.ts +++ b/src/api/gramjs/methods/payments.ts @@ -45,13 +45,15 @@ import { buildShippingInfo, } from '../gramjsBuilders'; import { + checkErrorType, deserializeBytes, serializeBytes, -} from '../helpers'; + wrapError, +} from '../helpers/misc'; import localDb from '../localDb'; import { sendApiUpdate } from '../updates/apiUpdateEmitter'; import { handleGramJsUpdate, invokeRequest } from './client'; -import { getTemporaryPaymentPassword } from './twoFaSettings'; +import { getPassword, getTemporaryPaymentPassword } from './twoFaSettings'; export async function validateRequestedInfo({ inputInvoice, @@ -689,3 +691,42 @@ export function upgradeGift({ shouldReturnTrue: true, }); } + +export async function fetchStarGiftWithdrawalUrl({ + inputGift, + password, +}: { + inputGift: ApiRequestInputSavedStarGift; + password: string; +}) { + try { + const passwordCheck = await getPassword(password); + + if (!passwordCheck) { + return undefined; + } + + if ('error' in passwordCheck) { + return passwordCheck; + } + + const result = await invokeRequest(new GramJs.payments.GetStarGiftWithdrawalUrl({ + stargift: buildInputSavedStarGift(inputGift), + password: passwordCheck, + }), { + shouldThrow: true, + }); + + if (!result) { + return undefined; + } + + return { url: result.url }; + } catch (err: unknown) { + if (!checkErrorType(err)) return undefined; + + return wrapError(err); + } + + return undefined; +} diff --git a/src/api/gramjs/methods/settings.ts b/src/api/gramjs/methods/settings.ts index 22d349806..7d7b99c0e 100644 --- a/src/api/gramjs/methods/settings.ts +++ b/src/api/gramjs/methods/settings.ts @@ -43,7 +43,7 @@ import { buildInputPrivacyKey, buildInputPrivacyRules, } from '../gramjsBuilders'; -import { addPhotoToLocalDb } from '../helpers'; +import { addPhotoToLocalDb } from '../helpers/localDb'; import localDb from '../localDb'; import { getClient, invokeRequest, uploadFile } from './client'; diff --git a/src/api/gramjs/methods/statistics.ts b/src/api/gramjs/methods/statistics.ts index c1f328888..b8f2f51c7 100644 --- a/src/api/gramjs/methods/statistics.ts +++ b/src/api/gramjs/methods/statistics.ts @@ -16,8 +16,9 @@ import { buildStoryPublicForwards, } from '../apiBuilders/statistics'; import { buildInputEntity, buildInputPeer } from '../gramjsBuilders'; +import { checkErrorType, wrapError } from '../helpers/misc'; import { invokeRequest } from './client'; -import { getPassword, onPasswordError } from './twoFaSettings'; +import { getPassword } from './twoFaSettings'; export async function fetchChannelStatistics({ chat, dcId, @@ -216,7 +217,7 @@ export async function fetchStoryPublicForwards({ }; } -export async function loadMonetizationRevenueWithdrawalUrl({ +export async function fetchMonetizationRevenueWithdrawalUrl({ peer, currentPassword, }: { peer: ApiPeer; @@ -225,10 +226,14 @@ export async function loadMonetizationRevenueWithdrawalUrl({ try { const password = await getPassword(currentPassword); - if (!password || 'error' in password) { + if (!password) { return undefined; } + if ('error' in password) { + return password; + } + const result = await invokeRequest(new GramJs.stats.GetBroadcastRevenueWithdrawalUrl({ peer: buildInputPeer(peer.id, peer.accessHash), password, @@ -240,9 +245,10 @@ export async function loadMonetizationRevenueWithdrawalUrl({ return undefined; } - return result; - } catch (err: any) { - onPasswordError(err); + return { url: result.url }; + } catch (err: unknown) { + if (!checkErrorType(err)) return undefined; + return wrapError(err); } return undefined; diff --git a/src/api/gramjs/methods/stories.ts b/src/api/gramjs/methods/stories.ts index 4f9275638..a6ca5d367 100644 --- a/src/api/gramjs/methods/stories.ts +++ b/src/api/gramjs/methods/stories.ts @@ -26,7 +26,8 @@ import { buildInputPrivacyRules, buildInputReaction, } from '../gramjsBuilders'; -import { addStoryToLocalDb, deserializeBytes } from '../helpers'; +import { addStoryToLocalDb } from '../helpers/localDb'; +import { deserializeBytes } from '../helpers/misc'; import { invokeRequest } from './client'; export async function fetchAllStories({ diff --git a/src/api/gramjs/methods/twoFaSettings.ts b/src/api/gramjs/methods/twoFaSettings.ts index 3a6be255e..44e59ba4b 100644 --- a/src/api/gramjs/methods/twoFaSettings.ts +++ b/src/api/gramjs/methods/twoFaSettings.ts @@ -1,21 +1,11 @@ -import { Api as GramJs, errors } from '../../../lib/gramjs'; +import { Api as GramJs } from '../../../lib/gramjs'; -import { DEBUG } from '../../../config'; +import { checkErrorType, wrapError } from '../helpers/misc'; import { sendApiUpdate } from '../updates/apiUpdateEmitter'; import { getCurrentPassword, getTmpPassword, invokeRequest, updateTwoFaSettings, } from './client'; -const ApiErrors: { [k: string]: string } = { - EMAIL_UNCONFIRMED: 'Email unconfirmed', - EMAIL_HASH_EXPIRED: 'Email hash expired', - NEW_SALT_INVALID: 'The new salt is invalid', - NEW_SETTINGS_INVALID: 'The new password settings are invalid', - CODE_INVALID: 'Invalid Code', - PASSWORD_HASH_INVALID: 'Invalid Password', - PASSWORD_MISSING: 'You must enable 2FA before executing this operation', -}; - const emailCodeController: { resolve?: Function; reject?: Function; @@ -45,18 +35,22 @@ function onRequestEmailCode(length: number) { } export function getTemporaryPaymentPassword(password: string, ttl?: number) { - return getTmpPassword(password, ttl); + try { + return getTmpPassword(password, ttl); + } catch (err: unknown) { + if (!checkErrorType(err)) return undefined; + + return Promise.resolve(wrapError(err)); + } } export function getPassword(password: string) { try { - return getCurrentPassword({ - currentPassword: password, - onPasswordCodeError: onPasswordError, - }); - } catch (err: any) { - onPasswordError(err); - return undefined; + return getCurrentPassword(password); + } catch (err: unknown) { + if (!checkErrorType(err)) return undefined; + + return Promise.resolve(wrapError(err)); } } @@ -126,51 +120,10 @@ export function provideRecoveryEmailCode(code: string) { } function onError(err: Error) { - let message: string; - - if (err instanceof errors.FloodWaitError) { - const hours = Math.ceil(Number(err.seconds) / 60 / 60); - message = `Too many attempts. Try again in ${hours > 1 ? `${hours} hours` : 'an hour'}`; - } else { - message = ApiErrors[err.message]; - } - - if (!message) { - message = 'Unexpected Error'; - - if (DEBUG) { - // eslint-disable-next-line no-console - console.error(err); - } - } + const wrappedError = wrapError(err); sendApiUpdate({ '@type': 'updateTwoFaError', - message, - }); -} - -export function onPasswordError(err: Error) { - let message: string; - - if (err instanceof errors.PasswordModifiedError) { - const hours = Math.ceil(Number(err.seconds) / 60 / 60); - message = `Too many attempts. Try again in ${hours > 1 ? `${hours} hours` : 'an hour'}`; - } else { - message = ApiErrors[err.message]; - } - - if (!message) { - message = 'Unexpected Error'; - - if (DEBUG) { - // eslint-disable-next-line no-console - console.error(err); - } - } - - sendApiUpdate({ - '@type': 'updatePasswordError', - error: message, + messageKey: wrappedError.messageKey, }); } diff --git a/src/api/gramjs/methods/users.ts b/src/api/gramjs/methods/users.ts index 57716fa02..2c70e3775 100644 --- a/src/api/gramjs/methods/users.ts +++ b/src/api/gramjs/methods/users.ts @@ -17,7 +17,7 @@ import { buildMtpPeerId, getEntityTypeById, } from '../gramjsBuilders'; -import { addPhotoToLocalDb, addUserToLocalDb } from '../helpers'; +import { addPhotoToLocalDb, addUserToLocalDb } from '../helpers/localDb'; import localDb from '../localDb'; import { sendApiUpdate } from '../updates/apiUpdateEmitter'; import { invokeRequest } from './client'; diff --git a/src/api/gramjs/updates/entityProcessor.ts b/src/api/gramjs/updates/entityProcessor.ts index 55dee5823..fc67ca380 100644 --- a/src/api/gramjs/updates/entityProcessor.ts +++ b/src/api/gramjs/updates/entityProcessor.ts @@ -9,7 +9,7 @@ import { buildApiChatFromPreview } from '../apiBuilders/chats'; import { buildPollFromMedia } from '../apiBuilders/messageContent'; import { buildApiThreadInfoFromMessage } from '../apiBuilders/messages'; import { buildApiUser } from '../apiBuilders/users'; -import { addChatToLocalDb, addMessageToLocalDb, addUserToLocalDb } from '../helpers'; +import { addChatToLocalDb, addMessageToLocalDb, addUserToLocalDb } from '../helpers/localDb'; import { sendImmediateApiUpdate } from './apiUpdateEmitter'; const TYPE_USER = new Set(['User', 'UserEmpty']); diff --git a/src/api/gramjs/updates/mtpUpdateHandler.ts b/src/api/gramjs/updates/mtpUpdateHandler.ts index e659c2496..2dd8f0948 100644 --- a/src/api/gramjs/updates/mtpUpdateHandler.ts +++ b/src/api/gramjs/updates/mtpUpdateHandler.ts @@ -71,11 +71,13 @@ import { import { addPhotoToLocalDb, addStoryToLocalDb, +} from '../helpers/localDb'; +import { isChatFolder, log, resolveMessageApiChatId, serializeBytes, -} from '../helpers'; +} from '../helpers/misc'; import localDb from '../localDb'; import { scheduleMutedChatUpdate, scheduleMutedTopicUpdate } from '../scheduleUnmute'; import { sendApiUpdate } from './apiUpdateEmitter'; diff --git a/src/api/gramjs/worker/worker.ts b/src/api/gramjs/worker/worker.ts index 533274d88..cc440b670 100644 --- a/src/api/gramjs/worker/worker.ts +++ b/src/api/gramjs/worker/worker.ts @@ -7,7 +7,7 @@ import type { OriginMessageEvent, WorkerPayload } from './types'; import { DEBUG } from '../../../config'; import { DEBUG_LEVELS } from '../../../util/debugConsole'; import { throttleWithTickEnd } from '../../../util/schedulers'; -import { log } from '../helpers'; +import { log } from '../helpers/misc'; import { callApi, cancelApiProgress, initApi } from '../methods/init'; declare const self: WorkerGlobalScope; diff --git a/src/api/types/payments.ts b/src/api/types/payments.ts index bf62bb3c2..ef0ae44b5 100644 --- a/src/api/types/payments.ts +++ b/src/api/types/payments.ts @@ -271,6 +271,7 @@ export interface ApiSavedStarGift { canUpgrade?: true; alreadyPaidUpgradeStars?: number; transferStars?: number; + canExportAt?: number; isConverted?: boolean; // Local field, used for Action Message upgradeMsgId?: number; // Local field, used for Action Message } diff --git a/src/api/types/updates.ts b/src/api/types/updates.ts index bba5a039a..656475000 100644 --- a/src/api/types/updates.ts +++ b/src/api/types/updates.ts @@ -491,12 +491,7 @@ export type ApiUpdateSavedGifs = { export type ApiUpdateTwoFaError = { '@type': 'updateTwoFaError'; - message: string; -}; - -export type ApiUpdatePasswordError = { - '@type': 'updatePasswordError'; - error: string; + messageKey: RegularLangFnParameters; }; export type ApiUpdateNotifySettings = { @@ -819,7 +814,7 @@ export type ApiUpdate = ( ApiUpdateRecentStickers | ApiUpdateSavedGifs | ApiUpdateNewScheduledMessage | ApiUpdateMoveStickerSetToTop | ApiUpdateScheduledMessageSendSucceeded | ApiUpdateScheduledMessage | ApiUpdateStarPaymentStateCompleted | ApiUpdateDeleteScheduledMessages | ApiUpdateResetMessages | ApiUpdateMessageTranslations | - ApiUpdateTwoFaError | ApiUpdatePasswordError | ApiUpdateTwoFaStateWaitCode | ApiUpdateWebViewResultSent | + ApiUpdateTwoFaError | ApiUpdateTwoFaStateWaitCode | ApiUpdateWebViewResultSent | ApiUpdateNotifySettings | ApiUpdateNotifyExceptions | ApiUpdatePeerBlocked | ApiUpdatePrivacy | ApiUpdateServerTimeOffset | ApiUpdateMessageReactions | ApiUpdateSavedReactionTags | ApiUpdateGroupCallParticipants | ApiUpdateGroupCallConnection | ApiUpdateGroupCall | ApiUpdateGroupCallStreams | diff --git a/src/assets/font-icons/fragment.svg b/src/assets/font-icons/fragment.svg new file mode 100644 index 000000000..d473ad267 --- /dev/null +++ b/src/assets/font-icons/fragment.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/localization/fallback.strings b/src/assets/localization/fallback.strings index 4a6a7be8e..403dbdfe7 100644 --- a/src/assets/localization/fallback.strings +++ b/src/assets/localization/fallback.strings @@ -668,16 +668,23 @@ "FavoriteStickers" = "Favorites"; "PremiumStickers" = "Premium Stickers"; "GroupStickers" = "Group Stickers"; -"ErrorSendRestrictedStickersAll" = "Sorry, sending stickers is not allowed in this group."; -"ErrorPhoneNumberInvalid" = "Invalid phone number, please try again."; -"ErrorCodeInvalid" = "Invalid code, please try again."; -"ErrorIncorrectPassword" = "Invalid password, please try again."; -"ErrorPasswordFlood" = "Too many attempts, please try again later."; -"ErrorPhoneBanned" = "This phone number is banned."; -"ErrorFlood_one" = "Too many attempts, please try again in {hour} hour"; -"ErrorFlood_other" = "Too many attempts, please try again in {hour} hours"; +"ErrorSendRestrictedStickersAll" = "Sorry, sending stickers is not allowed in this group"; +"ErrorPhoneNumberInvalid" = "Invalid phone number, please try again"; +"ErrorCodeInvalid" = "Invalid code, please try again"; +"ErrorEmailCodeInvalid" = "Invalid code, please try again"; +"ErrorIncorrectPassword" = "Invalid password, please try again"; +"ErrorPasswordFlood" = "Too many attempts, please try again later"; +"ErrorPhoneBanned" = "This phone number is banned"; +"ErrorFloodTime" = "Too many attempts, please try again in {time}"; +"ErrorPasswordFresh" = "The password was modified less than 24 hours ago, try again in {time}"; "ErrorUnexpected" = "Unexpected error"; "ErrorUnexpectedMessage" = "Unexpected error: {error}"; +"ErrorEmailUnconfirmed" = "Email not confirmed"; +"ErrorEmailHashExpired" = "Failed to confirm email, please try again"; +"ErrorNewSaltInvalid" = "Error validating password, please try again"; +"ErrorPasswordChanged" = "Password has been changed, please try again"; +"ErrorPasswordMissing" = "You must set 2FA password to use this feature"; +"ErrorUnspecified" = "Error"; "NoStickers" = "No stickers yet"; "ClearRecentEmoji" = "Clear recent emoji?"; "TextFormatAddLinkTitle" = "Add Link"; @@ -1429,6 +1436,7 @@ "GiftInfoViewUpgraded" = "View Upgraded Gift"; "GiftInfoUpgradeBadge" = "upgrade"; "GiftInfoUpgradeForFree" = "Upgrade For Free"; +"GiftInfoWithdraw" = "Withdraw"; "GiftUpgradeUniqueTitle" = "Unique"; "GiftUpgradeUniqueDescription" = "Turn your gift into a unique collectible that you can transfer or auction."; "GiftUpgradeTransferableTitle" = "Transferable"; @@ -1447,6 +1455,11 @@ "GiftMakeUniqueDescription" = "Enable this to let {user} turn your gift into a unique collectible. {link}"; "GiftMakeUniqueDescriptionChannel" = "Enable this to let admins of {peer} to turn your gift into a unique collectible. {link}"; "GiftMakeUniqueLink" = "Learn More >"; +"GiftWithdrawTitle" = "Manage with Fragment"; +"GiftWithdrawDescription" = "You can use Fragment, a third-party service, to transfer **{gift}** to the TON blockchain. After that, you can manage it as an NFT with any TON wallet application.\n\nYou can also move such NFTs back to your Telegram account via Fragment."; +"GiftWithdrawSubmit" = "Open Fragment"; +"GiftWithdrawWait_one" = "In {days} day, you'll be able to send this collectible to any TON blockchain address outside Telegram for sale or auction."; +"GiftWithdrawWait_other" = "In {days} days, you'll be able to send this collectible to any TON blockchain address outside Telegram for sale or auction."; "StarsAmount" = "⭐️{amount}"; "StarsAmountText_one" = "{amount} Star"; "StarsAmountText_other" = "{amount} Stars"; @@ -1586,3 +1599,6 @@ "ViewButtonGiftUnique" = "VIEW COLLECTIBLE"; "AuthContinueOnThisLanguage" = "Continue in English"; "Share" = "Share"; +"CheckPasswordTitle" = "Enter Password"; +"CheckPasswordPlaceholder" = "Password"; +"CheckPasswordDescription" = "Please enter your password to continue."; diff --git a/src/assets/localization/initialKeys.ts b/src/assets/localization/initialKeys.ts index 9d17a382b..0868f71cd 100644 --- a/src/assets/localization/initialKeys.ts +++ b/src/assets/localization/initialKeys.ts @@ -28,7 +28,7 @@ const INITIAL_KEYS: LangKey[] = [ 'ErrorIncorrectPassword', 'ErrorPasswordFlood', 'ErrorPhoneBanned', - 'ErrorFlood', + 'ErrorFloodTime', 'ErrorUnexpected', 'ErrorUnexpectedMessage', ]; diff --git a/src/assets/localization/initialStrings.ts b/src/assets/localization/initialStrings.ts index 7c42cf753..8ee3c2fbc 100644 --- a/src/assets/localization/initialStrings.ts +++ b/src/assets/localization/initialStrings.ts @@ -31,10 +31,7 @@ export default { "ErrorIncorrectPassword": "Invalid password, please try again.", "ErrorPasswordFlood": "Too many attempts, please try again later.", "ErrorPhoneBanned": "This phone number is banned.", - "ErrorFlood": { - "one": "Too many attempts, please try again in {hour} hour", - "other": "Too many attempts, please try again in {hour} hours" - }, + "ErrorFloodTime": "Too many attempts, please try again in {time}.", "ErrorUnexpected": "Unexpected error", "ErrorUnexpectedMessage": "Unexpected error: {error}" } as Record; diff --git a/src/bundles/stars.ts b/src/bundles/stars.ts index 5a61b1974..c6437704f 100644 --- a/src/bundles/stars.ts +++ b/src/bundles/stars.ts @@ -9,3 +9,4 @@ 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'; +export { default as GiftWithdrawModal } from '../components/modals/gift/fragment/GiftWithdrawModal'; diff --git a/src/components/common/VerificationMonetizationModal.async.tsx b/src/components/common/VerificationMonetizationModal.async.tsx index e037427c2..62fbf73a2 100644 --- a/src/components/common/VerificationMonetizationModal.async.tsx +++ b/src/components/common/VerificationMonetizationModal.async.tsx @@ -8,8 +8,8 @@ import { Bundles } from '../../util/moduleLoader'; import useModuleLoader from '../../hooks/useModuleLoader'; const VerificationMonetizationModalAsync: FC = (props) => { - const { isOpen } = props; - const VerificationMonetizationModal = useModuleLoader(Bundles.Extra, 'VerificationMonetizationModal', !isOpen); + const { modal } = props; + const VerificationMonetizationModal = useModuleLoader(Bundles.Extra, 'VerificationMonetizationModal', !modal); // eslint-disable-next-line react/jsx-props-no-spreading return VerificationMonetizationModal ? : undefined; diff --git a/src/components/common/VerificationMonetizationModal.tsx b/src/components/common/VerificationMonetizationModal.tsx index b90fc92ac..8eac2932f 100644 --- a/src/components/common/VerificationMonetizationModal.tsx +++ b/src/components/common/VerificationMonetizationModal.tsx @@ -1,14 +1,16 @@ -import type { FC } from '../../lib/teact/teact'; import React, { memo, useState, } from '../../lib/teact/teact'; -import { getActions } from '../../global'; +import { getActions, withGlobal } from '../../global'; + +import type { TabState } from '../../global/types'; import buildClassName from '../../util/buildClassName'; +import useCurrentOrPrev from '../../hooks/useCurrentOrPrev'; +import useLang from '../../hooks/useLang'; import useLastCallback from '../../hooks/useLastCallback'; -import useOldLang from '../../hooks/useOldLang'; import Modal from '../ui/Modal'; import PasswordForm from './PasswordForm'; @@ -16,62 +18,63 @@ import PasswordForm from './PasswordForm'; import styles from './VerificationMonetizationModal.module.scss'; export type OwnProps = { - isOpen: boolean; - onClose: NoneToVoidFunction; - chatId: string; - passwordHint?: string; - error?: string; - isLoading?: boolean; + modal: TabState['monetizationVerificationModal']; }; -const VerificationMonetizationModal: FC = ({ - isOpen, - chatId, - onClose, +type StateProps = { + passwordHint?: string; +}; + +const VerificationMonetizationModal = ({ + modal, passwordHint, - error, - isLoading, -}) => { +}: OwnProps & StateProps) => { const { - clearMonetizationInfo, loadMonetizationRevenueWithdrawalUrl, + closeMonetizationVerificationModal, clearMonetizationVerificationError, processMonetizationRevenueWithdrawalUrl, } = getActions(); - const lang = useOldLang(); + const isOpen = Boolean(modal); + + const renderingModal = useCurrentOrPrev(modal); + + const lang = useLang(); const [shouldShowPassword, setShouldShowPassword] = useState(false); const handleSubmit = useLastCallback((password: string) => { - loadMonetizationRevenueWithdrawalUrl({ - peerId: chatId, + if (!renderingModal) return; + processMonetizationRevenueWithdrawalUrl({ + peerId: renderingModal.chatId, currentPassword: password, - onSuccess: () => { - onClose(); - }, }); }); const handleClearError = useLastCallback(() => { - clearMonetizationInfo(); + clearMonetizationVerificationError(); + }); + + const handleClose = useLastCallback(() => { + closeMonetizationVerificationModal(); }); return (
= ({ ); }; -export default memo(VerificationMonetizationModal); +export default memo(withGlobal( + (global): StateProps => { + const { + twoFaSettings: { + hint: passwordHint, + }, + } = global; + + return { + passwordHint, + }; + }, +)(VerificationMonetizationModal)); diff --git a/src/components/left/settings/twoFa/SettingsTwoFa.tsx b/src/components/left/settings/twoFa/SettingsTwoFa.tsx index 0d3502622..cddae79cd 100644 --- a/src/components/left/settings/twoFa/SettingsTwoFa.tsx +++ b/src/components/left/settings/twoFa/SettingsTwoFa.tsx @@ -6,6 +6,7 @@ import type { GlobalState } from '../../../../global/types'; import type { TwoFaDispatch, TwoFaState } from '../../../../hooks/reducers/useTwoFaReducer'; import { SettingsScreens } from '../../../../types'; +import useLang from '../../../../hooks/useLang'; import useOldLang from '../../../../hooks/useOldLang'; import SettingsTwoFaPassword from '../SettingsPasswordForm'; @@ -33,7 +34,7 @@ const SettingsTwoFa: FC = ({ state, hint, isLoading, - error, + errorKey, waitingEmailCodeLength, dispatch, isActive, @@ -49,6 +50,9 @@ const SettingsTwoFa: FC = ({ clearPassword, } = getActions(); + const lang = useLang(); + const oldLang = useOldLang(); + useEffect(() => { if (waitingEmailCodeLength) { if (currentScreen === SettingsScreens.TwoFaNewPasswordEmail) { @@ -153,8 +157,6 @@ const SettingsTwoFa: FC = ({ provideTwoFaEmailCode({ code }); }, [provideTwoFaEmailCode]); - const lang = useOldLang(); - switch (currentScreen) { case SettingsScreens.TwoFaDisabled: return ( @@ -175,8 +177,8 @@ const SettingsTwoFa: FC = ({ case SettingsScreens.TwoFaNewPassword: return ( = ({ return ( = ({ return ( = ({ icon="email" type="email" isLoading={isLoading} - error={error} + error={errorKey && lang.withRegular(errorKey)} clearError={clearTwoFaError} - placeholder={lang('RecoveryEmailTitle')} + placeholder={oldLang('RecoveryEmailTitle')} shouldConfirm onSubmit={handleNewPasswordEmail} isActive={isActive || [ @@ -244,7 +246,7 @@ const SettingsTwoFa: FC = ({ return ( = ({ return ( = ({ case SettingsScreens.TwoFaChangePasswordNew: return ( = ({ return ( = ({ return ( = ({ return ( = ({ return ( = ({ = ({ return ( ; type StateProps = { @@ -109,6 +113,8 @@ const MODALS: ModalRegistry = { locationAccessModal: LocationAccessModal, aboutAdsModal: AboutAdsModal, giftUpgradeModal: GiftUpgradeModal, + monetizationVerificationModal: VerificationMonetizationModal, + giftWithdrawModal: GiftWithdrawModal, }; const MODAL_KEYS = Object.keys(MODALS) as ModalKey[]; const MODAL_ENTRIES = Object.entries(MODALS) as Entries; diff --git a/src/components/modals/gift/fragment/GiftWithdrawModal.async.tsx b/src/components/modals/gift/fragment/GiftWithdrawModal.async.tsx new file mode 100644 index 000000000..c87c42925 --- /dev/null +++ b/src/components/modals/gift/fragment/GiftWithdrawModal.async.tsx @@ -0,0 +1,18 @@ +import type { FC } from '../../../../lib/teact/teact'; +import React from '../../../../lib/teact/teact'; + +import type { OwnProps } from './GiftWithdrawModal'; + +import { Bundles } from '../../../../util/moduleLoader'; + +import useModuleLoader from '../../../../hooks/useModuleLoader'; + +const GiftWithdrawModalAsync: FC = (props) => { + const { modal } = props; + const GiftWithdrawModal = useModuleLoader(Bundles.Stars, 'GiftWithdrawModal', !modal); + + // eslint-disable-next-line react/jsx-props-no-spreading + return GiftWithdrawModal ? : undefined; +}; + +export default GiftWithdrawModalAsync; diff --git a/src/components/modals/gift/fragment/GiftWithdrawModal.module.scss b/src/components/modals/gift/fragment/GiftWithdrawModal.module.scss new file mode 100644 index 000000000..a38df4cf2 --- /dev/null +++ b/src/components/modals/gift/fragment/GiftWithdrawModal.module.scss @@ -0,0 +1,39 @@ +.header { + display: flex; + justify-content: center; + align-items: center; + gap: 0.5rem; + + margin-bottom: 1rem; +} + +.giftPreview { + width: 5.625rem; + height: 5.625rem; + position: relative; + + display: grid; + place-items: center; + + overflow: hidden; + border-radius: 0.625rem; +} + +.backdrop { + position: absolute; + inset: 0; +} + +.description { + text-wrap: pretty; + margin-bottom: 1.5rem; +} + +.arrow { + font-size: 3rem; + color: var(--color-text-secondary); +} + +.noPassword { + font-weight: var(--font-weight-semibold); +} diff --git a/src/components/modals/gift/fragment/GiftWithdrawModal.tsx b/src/components/modals/gift/fragment/GiftWithdrawModal.tsx new file mode 100644 index 000000000..5673083c7 --- /dev/null +++ b/src/components/modals/gift/fragment/GiftWithdrawModal.tsx @@ -0,0 +1,157 @@ +import React, { + memo, + useState, +} from '../../../../lib/teact/teact'; +import { getActions, withGlobal } from '../../../../global'; + +import type { ApiStarGiftUnique } from '../../../../api/types'; +import type { TabState } from '../../../../global/types'; +import type { CustomPeer } from '../../../../types'; + +import { getDays } from '../../../../util/dates/units'; +import { getServerTime } from '../../../../util/serverTime'; +import { getGiftAttributes } from '../../../common/helpers/gifts'; +import { REM } from '../../../common/helpers/mediaDimensions'; + +import useCurrentOrPrev from '../../../../hooks/useCurrentOrPrev'; +import useLang from '../../../../hooks/useLang'; +import useLastCallback from '../../../../hooks/useLastCallback'; + +import AnimatedIconFromSticker from '../../../common/AnimatedIconFromSticker'; +import Avatar from '../../../common/Avatar'; +import Icon from '../../../common/icons/Icon'; +import PasswordForm from '../../../common/PasswordForm'; +import RadialPatternBackground from '../../../common/profile/RadialPatternBackground'; +import Modal from '../../../ui/Modal'; + +import styles from './GiftWithdrawModal.module.scss'; + +export type OwnProps = { + modal: TabState['giftWithdrawModal']; +}; + +type StateProps = { + hasPassword?: boolean; + passwordHint?: string; +}; + +const FRAGMENT_PEER: CustomPeer = { + isCustomPeer: true, + avatarIcon: 'fragment', + title: '', + customPeerAvatarColor: '#000000', +}; +const GIFT_STICKER_SIZE = 4.5 * REM; + +const GiftWithdrawModal = ({ modal, hasPassword, passwordHint }: OwnProps & StateProps) => { + const { closeGiftWithdrawModal, clearGiftWithdrawError, processStarGiftWithdrawal } = getActions(); + const isOpen = Boolean(modal); + + const [shouldShowPassword, setShouldShowPassword] = useState(false); + + const lang = useLang(); + + const renderingModal = useCurrentOrPrev(modal); + const gift = renderingModal?.gift?.gift as ApiStarGiftUnique; + const giftAttributes = gift && getGiftAttributes(gift); + const exportDelay = renderingModal?.gift?.canExportAt + ? Math.max(renderingModal.gift.canExportAt - getServerTime(), 0) : undefined; + + const handleClose = useLastCallback(() => { + closeGiftWithdrawModal(); + }); + + const handleSubmit = useLastCallback((password: string) => { + processStarGiftWithdrawal({ + gift: renderingModal!.gift.inputGift!, + password, + }); + }); + + return ( + + {giftAttributes && ( + <> +
+
+ + +
+ + +
+

+ {lang('GiftWithdrawDescription', { + gift: `${gift.title} #${gift.number}`, + }, { + withNodes: true, + withMarkdown: true, + renderTextFilters: ['br'], + })} +

+ + )} + {Boolean(exportDelay) && ( +

+ {lang('GiftWithdrawWait', { days: getDays(exportDelay) }, { pluralValue: getDays(exportDelay) })} +

+ )} + {!hasPassword && {lang('ErrorPasswordMissing')}} + {hasPassword && !exportDelay && ( + + )} +
+ ); +}; + +export default memo(withGlobal( + (global): StateProps => { + const { + settings: { + byKey: { + hasPassword, + }, + }, + twoFaSettings: { + hint: passwordHint, + }, + } = global; + + return { + hasPassword, + passwordHint, + }; + }, +)(GiftWithdrawModal)); diff --git a/src/components/modals/gift/info/GiftInfoModal.tsx b/src/components/modals/gift/info/GiftInfoModal.tsx index 3e80752a6..f7c131643 100644 --- a/src/components/modals/gift/info/GiftInfoModal.tsx +++ b/src/components/modals/gift/info/GiftInfoModal.tsx @@ -72,6 +72,7 @@ const GiftInfoModal = ({ openGiftUpgradeModal, showNotification, openChatWithDraft, + openGiftWithdrawModal, } = getActions(); const [isConvertConfirmOpen, openConvertConfirm, closeConvertConfirm] = useFlag(); @@ -127,6 +128,11 @@ const GiftInfoModal = ({ handleClose(); }); + const handleWithdraw = useLastCallback(() => { + if (savedGift?.gift.type !== 'starGiftUnique') return; + openGiftWithdrawModal({ gift: savedGift }); + }); + const handleFocusUpgraded = useLastCallback(() => { if (!savedGift?.upgradeMsgId || !renderingTargetPeer) return; const { upgradeMsgId } = savedGift; @@ -291,6 +297,11 @@ const GiftInfoModal = ({ > {lang('Share')} + {canUpdate && isUniqueGift && ( + + {lang('GiftInfoWithdraw')} + + )} ); diff --git a/src/components/payment/PasswordConfirm.tsx b/src/components/payment/PasswordConfirm.tsx index 9b866c7b7..1fbaf7438 100644 --- a/src/components/payment/PasswordConfirm.tsx +++ b/src/components/payment/PasswordConfirm.tsx @@ -4,9 +4,11 @@ import { getActions, withGlobal } from '../../global'; import type { ApiPaymentCredentials } from '../../api/types'; import type { FormState } from '../../hooks/reducers/usePaymentReducer'; +import type { RegularLangFnParameters } from '../../util/localization'; import { selectTabState } from '../../global/selectors'; +import useLang from '../../hooks/useLang'; import useOldLang from '../../hooks/useOldLang'; import PasswordForm from '../common/PasswordForm'; @@ -20,14 +22,14 @@ interface OwnProps { } interface StateProps { - error?: string; + errorKey?: RegularLangFnParameters; passwordHint?: string; savedCredentials?: ApiPaymentCredentials[]; } const PasswordConfirm: FC = ({ isActive, - error, + errorKey, state, savedCredentials, passwordHint, @@ -35,7 +37,9 @@ const PasswordConfirm: FC = ({ }) => { const { clearPaymentError } = getActions(); - const lang = useOldLang(); + const oldLang = useOldLang(); + const lang = useLang(); + const [shouldShowPassword, setShouldShowPassword] = useState(false); const cardName = useMemo(() => { return savedCredentials?.length && state.savedCredentialId @@ -48,10 +52,10 @@ const PasswordConfirm: FC = ({ = ({ export default memo(withGlobal((global): StateProps => { const { payment } = selectTabState(global); return { - error: payment.error?.message, + errorKey: payment.error?.messageKey, passwordHint: global.twoFaSettings.hint, savedCredentials: payment.form?.type === 'regular' ? payment.form.savedCredentials : undefined, }; diff --git a/src/components/payment/PaymentInfo.tsx b/src/components/payment/PaymentInfo.tsx index eab2d40bc..9093aaab0 100644 --- a/src/components/payment/PaymentInfo.tsx +++ b/src/components/payment/PaymentInfo.tsx @@ -7,6 +7,7 @@ import React, { import type { ApiCountry } from '../../api/types'; import type { FormEditDispatch, FormState } from '../../hooks/reducers/usePaymentReducer'; +import useLang from '../../hooks/useLang'; import useOldLang from '../../hooks/useOldLang'; import Checkbox from '../ui/Checkbox'; @@ -75,58 +76,59 @@ const PaymentInfo: FC = ({ dispatch({ type: 'changeSaveCredentials', payload: e.target.value }); }, [dispatch]); - const lang = useOldLang(); + const oldLang = useOldLang(); + const lang = useLang(); const { formErrors = {} } = state; return (
-
{lang('PaymentCardTitle')}
+
{oldLang('PaymentCardTitle')}
{needCardholderName && ( )}
{needCountry || needZip ? ( -
{lang('PaymentBillingAddress')}
+
{oldLang('PaymentBillingAddress')}
) : undefined}
{needCountry && ( @@ -159,52 +161,52 @@ const ShippingInfo: FC = ({
) : undefined} { needName || needEmail || needPhone ? ( -
{lang('PaymentShippingReceiver')}
+
{oldLang('PaymentShippingReceiver')}
) : undefined } { needName && ( ) } { needEmail && ( ) } { needPhone && ( ) } { - const { loadChannelMonetizationStatistics, loadPasswordInfo } = getActions(); + const { loadChannelMonetizationStatistics, openMonetizationVerificationModal, loadPasswordInfo } = getActions(); const oldLang = useOldLang(); const lang = useLang(); @@ -79,9 +72,6 @@ const MonetizationStatistics = ({ const loadedCharts = useRef([]); const forceUpdate = useForceUpdate(); const [isAboutMonetizationModalOpen, openAboutMonetizationModal, closeAboutMonetizationModal] = useFlag(false); - const [ - isVerificationMonetizationModalOpen, openVerificationMonetizationModal, closeVerificationMonetizationModal, - ] = useFlag(false); const [isConfirmPasswordDialogOpen, openConfirmPasswordDialogOpen, closeConfirmPasswordDialogOpen] = useFlag(); const availableBalance = statistics?.balances?.availableBalance; const isWithdrawalEnabled = statistics?.balances?.isWithdrawalEnabled; @@ -206,7 +196,9 @@ const MonetizationStatistics = ({ const verificationMonetizationHandler = useLastCallback(() => { if (hasPassword) { - openVerificationMonetizationModal(); + openMonetizationVerificationModal({ + chatId, + }); } else { openConfirmPasswordDialogOpen(); } @@ -259,14 +251,6 @@ const MonetizationStatistics = ({ isOpen={isAboutMonetizationModalOpen} onClose={closeAboutMonetizationModal} /> - @@ -419,15 +420,3 @@ export default memo(withGlobal((global): StateProps => { currentUserId: global.currentUserId!, }; })(StorySettings)); - -function convertSecondsToHours(seconds: number): number { - const secondsInHour = 3600; - const minutesInHour = 60; - - const hours = Math.floor(seconds / secondsInHour); - const remainingSeconds = seconds % secondsInHour; - const remainingMinutes = Math.floor(remainingSeconds / minutesInHour); - - // If remaining minutes are greater than or equal to 30, round up the hours - return remainingMinutes >= 30 ? hours + 1 : hours; -} diff --git a/src/global/actions/all.ts b/src/global/actions/all.ts index 0146942f3..d192c886e 100644 --- a/src/global/actions/all.ts +++ b/src/global/actions/all.ts @@ -33,6 +33,7 @@ import './ui/passcode'; import './ui/stars'; import './ui/reactions'; import './ui/stories'; +import './ui/statistics'; import './apiUpdaters/initial'; import './apiUpdaters/chats'; import './apiUpdaters/messages'; @@ -41,6 +42,5 @@ import './apiUpdaters/symbols'; import './apiUpdaters/misc'; import './apiUpdaters/settings'; import './apiUpdaters/twoFaSettings'; -import './apiUpdaters/password'; import './apiUpdaters/calls'; import './apiUpdaters/payments'; diff --git a/src/global/actions/api/payments.ts b/src/global/actions/api/payments.ts index aaeccbaf5..ab7f37340 100644 --- a/src/global/actions/api/payments.ts +++ b/src/global/actions/api/payments.ts @@ -2,6 +2,7 @@ import type { ApiInputInvoice, ApiInputInvoiceStarGift, ApiInputInvoiceStarGiftUpgrade, ApiRequestInputInvoice, } from '../../../api/types'; import type { ApiCredentials } from '../../../components/payment/PaymentModal'; +import type { RegularLangFnParameters } from '../../../util/localization'; import type { ActionReturnType, GlobalState, TabArgs, } from '../../types'; @@ -397,7 +398,7 @@ async function sendSmartGlocalCredentials( if (result.status !== 'ok') { // TODO после получения документации сделать аналог getStripeError(result.error); - const error = { description: 'payment error' }; + const error = { descriptionKey: { key: 'ErrorUnexpected' } satisfies RegularLangFnParameters }; global = getGlobal(); global = updateTabState(global, { payment: { @@ -554,9 +555,9 @@ addActionHandler('validatePaymentPassword', async (global, actions, payload): Pr global = getGlobal(); if (!result) { - global = updatePayment(global, { error: { message: 'Unknown Error', field: 'password' } }, tabId); + global = updatePayment(global, { error: { messageKey: { key: 'ErrorUnexpected' }, field: 'password' } }, tabId); } else if ('error' in result) { - global = updatePayment(global, { error: { message: result.error, field: 'password' } }, tabId); + global = updatePayment(global, { error: { messageKey: result.messageKey, field: 'password' } }, tabId); } else { global = updatePayment(global, { temporaryPassword: result, step: PaymentStep.Checkout }, tabId); } @@ -1063,3 +1064,51 @@ addActionHandler('openUniqueGiftBySlug', async (global, actions, payload): Promi actions.openGiftInfoModal({ gift, tabId }); }); + +addActionHandler('processStarGiftWithdrawal', async (global, actions, payload): Promise => { + const { + gift, password, tabId = getCurrentTabId(), + } = payload; + + let giftWithdrawModal = selectTabState(global, tabId).giftWithdrawModal; + if (!giftWithdrawModal) return; + + global = updateTabState(global, { + giftWithdrawModal: { + ...giftWithdrawModal, + isLoading: true, + errorKey: undefined, + }, + }, tabId); + setGlobal(global); + + const inputGift = getRequestInputSavedStarGift(global, gift); + if (!inputGift) { + return; + } + + const result = await callApi('fetchStarGiftWithdrawalUrl', { inputGift, password }); + + if (!result) { + return; + } + + global = getGlobal(); + giftWithdrawModal = selectTabState(global, tabId).giftWithdrawModal; + if (!giftWithdrawModal) return; + + if ('error' in result) { + global = updateTabState(global, { + giftWithdrawModal: { + ...giftWithdrawModal, + isLoading: false, + errorKey: result.messageKey, + }, + }, tabId); + setGlobal(global); + return; + } + + actions.openUrl({ url: result.url, shouldSkipModal: true, tabId }); + actions.closeGiftWithdrawModal({ tabId }); +}); diff --git a/src/global/actions/api/statistics.ts b/src/global/actions/api/statistics.ts index 0545ea9bc..3cb37f910 100644 --- a/src/global/actions/api/statistics.ts +++ b/src/global/actions/api/statistics.ts @@ -1,5 +1,3 @@ -import type { ActionReturnType } from '../../types'; - import { areDeepEqual } from '../../../util/areDeepEqual'; import { getCurrentTabId } from '../../../util/establishMultitabRole'; import { callApi } from '../../../api/gramjs'; @@ -7,10 +5,10 @@ import { addActionHandler, getGlobal, setGlobal } from '../../index'; import { updateChannelMonetizationStatistics, updateMessageStatistics, - updateMonetizationInfo, updateStatistics, updateStatisticsGraph, updateStoryStatistics, + updateVerifyMonetizationModal, } from '../../reducers'; import { selectChat, @@ -229,12 +227,14 @@ addActionHandler('loadStoryPublicForwards', async (global, actions, payload): Pr setGlobal(global); }); -addActionHandler('loadMonetizationRevenueWithdrawalUrl', async (global, actions, payload): Promise => { +addActionHandler('processMonetizationRevenueWithdrawalUrl', async (global, actions, payload): Promise => { const { - peerId, currentPassword, onSuccess, tabId = getCurrentTabId(), + peerId, currentPassword, tabId = getCurrentTabId(), } = payload; - global = updateMonetizationInfo(global, { isLoading: true, error: undefined }); + global = updateVerifyMonetizationModal(global, { + isLoading: true, + }, tabId); setGlobal(global); const peer = selectPeer(global, peerId); @@ -242,27 +242,26 @@ addActionHandler('loadMonetizationRevenueWithdrawalUrl', async (global, actions, return; } - const result = await callApi('loadMonetizationRevenueWithdrawalUrl', { peer, currentPassword }); + const result = await callApi('fetchMonetizationRevenueWithdrawalUrl', { peer, currentPassword }); if (!result) { return; } global = getGlobal(); - global = updateMonetizationInfo(global, { isLoading: false }); + global = updateVerifyMonetizationModal(global, { + isLoading: false, + errorKey: 'error' in result ? result.messageKey : undefined, + }, tabId); setGlobal(global); - if (result) { - onSuccess(); + if ('url' in result) { actions.openUrl({ url: result.url, shouldSkipModal: true, tabId, ignoreDeepLinks: true, }); + actions.closeMonetizationVerificationModal({ tabId }); } }); - -addActionHandler('clearMonetizationInfo', (global): ActionReturnType => { - return updateMonetizationInfo(global, { error: undefined }); -}); diff --git a/src/global/actions/api/twoFaSettings.ts b/src/global/actions/api/twoFaSettings.ts index 59b02fd40..a2ea5dd4f 100644 --- a/src/global/actions/api/twoFaSettings.ts +++ b/src/global/actions/api/twoFaSettings.ts @@ -19,7 +19,7 @@ addActionHandler('loadPasswordInfo', async (global): Promise => { addActionHandler('checkPassword', async (global, actions, payload): Promise => { const { currentPassword, onSuccess } = payload; - global = updateTwoFaSettings(global, { isLoading: true, error: undefined }); + global = updateTwoFaSettings(global, { isLoading: true, errorKey: undefined }); setGlobal(global); const isSuccess = await callApi('checkPassword', currentPassword); @@ -36,7 +36,7 @@ addActionHandler('checkPassword', async (global, actions, payload): Promise => { const { currentPassword, onSuccess } = payload; - global = updateTwoFaSettings(global, { isLoading: true, error: undefined }); + global = updateTwoFaSettings(global, { isLoading: true, errorKey: undefined }); setGlobal(global); const isSuccess = await callApi('clearPassword', currentPassword); @@ -55,7 +55,7 @@ addActionHandler('updatePassword', async (global, actions, payload): Promise { - return updateTwoFaSettings(global, { error: undefined }); + return updateTwoFaSettings(global, { errorKey: undefined }); }); diff --git a/src/global/actions/apiUpdaters/password.ts b/src/global/actions/apiUpdaters/password.ts deleted file mode 100644 index 3601c5d73..000000000 --- a/src/global/actions/apiUpdaters/password.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { ActionReturnType } from '../../types'; - -import { addActionHandler } from '../../index'; - -addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => { - switch (update['@type']) { - case 'updatePasswordError': { - return { - ...global, - monetizationInfo: { - ...global.monetizationInfo, - isLoading: false, - error: update.error, - }, - }; - } - } - - return undefined; -}); diff --git a/src/global/actions/apiUpdaters/twoFaSettings.ts b/src/global/actions/apiUpdaters/twoFaSettings.ts index 5d47ce70c..833f7fba3 100644 --- a/src/global/actions/apiUpdaters/twoFaSettings.ts +++ b/src/global/actions/apiUpdaters/twoFaSettings.ts @@ -20,7 +20,7 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => { ...global, twoFaSettings: { ...global.twoFaSettings, - error: update.message, + errorKey: update.messageKey, }, }; } diff --git a/src/global/actions/ui/stars.ts b/src/global/actions/ui/stars.ts index 83b32aef4..0c992eece 100644 --- a/src/global/actions/ui/stars.ts +++ b/src/global/actions/ui/stars.ts @@ -9,7 +9,7 @@ import { clearStarPayment, openStarsTransactionModal, } from '../../reducers'; import { updateTabState } from '../../reducers/tabs'; -import { selectChatMessage, selectStarsPayment } from '../../selectors'; +import { selectChatMessage, selectStarsPayment, selectTabState } from '../../selectors'; addActionHandler('processOriginStarsPayment', (global, actions, payload): ActionReturnType => { const { originData, status, tabId = getCurrentTabId() } = payload; @@ -302,3 +302,35 @@ addActionHandler('closeGiftUpgradeModal', (global, actions, payload): ActionRetu giftUpgradeModal: undefined, }, tabId); }); + +addActionHandler('openGiftWithdrawModal', (global, actions, payload): ActionReturnType => { + const { gift, tabId = getCurrentTabId() } = payload || {}; + + return updateTabState(global, { + giftWithdrawModal: { + gift, + }, + }, tabId); +}); + +addActionHandler('closeGiftWithdrawModal', (global, actions, payload): ActionReturnType => { + const { tabId = getCurrentTabId() } = payload || {}; + + return updateTabState(global, { + giftWithdrawModal: undefined, + }, tabId); +}); + +addActionHandler('clearGiftWithdrawError', (global, actions, payload): ActionReturnType => { + const { tabId = getCurrentTabId() } = payload || {}; + const tabState = selectTabState(global, tabId); + const giftWithdrawModal = tabState?.giftWithdrawModal; + if (!giftWithdrawModal) return undefined; + + return updateTabState(global, { + giftWithdrawModal: { + ...giftWithdrawModal, + errorKey: undefined, + }, + }, tabId); +}); diff --git a/src/global/actions/ui/statistics.ts b/src/global/actions/ui/statistics.ts new file mode 100644 index 000000000..85d89ce44 --- /dev/null +++ b/src/global/actions/ui/statistics.ts @@ -0,0 +1,38 @@ +import type { ActionReturnType } from '../../types'; + +import { getCurrentTabId } from '../../../util/establishMultitabRole'; +import { addActionHandler } from '../..'; +import { updateVerifyMonetizationModal } from '../../reducers'; +import { updateTabState } from '../../reducers/tabs'; + +addActionHandler('openMonetizationVerificationModal', (global, actions, payload): ActionReturnType => { + const { tabId = getCurrentTabId(), chatId } = payload || {}; + + return updateTabState(global, { + monetizationVerificationModal: { + chatId, + }, + }, tabId); +}); + +addActionHandler('closeMonetizationVerificationModal', (global, actions, payload): ActionReturnType => { + const { tabId = getCurrentTabId() } = payload || {}; + + return updateTabState(global, { + monetizationVerificationModal: undefined, + }, tabId); +}); + +addActionHandler('clearMonetizationVerificationError', (global, actions, payload): ActionReturnType => { + const { tabId = getCurrentTabId() } = payload || {}; + + return updateVerifyMonetizationModal(global, { errorKey: undefined }, tabId); +}); + +addActionHandler('closeMonetizationStatistics', (global, actions, payload): ActionReturnType => { + const { tabId = getCurrentTabId() } = payload || {}; + + return updateTabState(global, { + monetizationStatistics: undefined, + }, tabId); +}); diff --git a/src/global/actions/ui/stories.ts b/src/global/actions/ui/stories.ts index b74c1ce22..df0a35576 100644 --- a/src/global/actions/ui/stories.ts +++ b/src/global/actions/ui/stories.ts @@ -428,11 +428,3 @@ addActionHandler('closeBoostStatistics', (global, actions, payload): ActionRetur boostStatistics: undefined, }, tabId); }); - -addActionHandler('closeMonetizationStatistics', (global, actions, payload): ActionReturnType => { - const { tabId = getCurrentTabId() } = payload || {}; - - return updateTabState(global, { - monetizationStatistics: undefined, - }, tabId); -}); diff --git a/src/global/helpers/users.ts b/src/global/helpers/users.ts index 0ab94b8b5..fadf7c72f 100644 --- a/src/global/helpers/users.ts +++ b/src/global/helpers/users.ts @@ -3,6 +3,7 @@ import type { OldLangFn } from '../../hooks/useOldLang'; import { ANONYMOUS_USER_ID, SERVICE_NOTIFICATIONS_USER_ID } from '../../config'; import { formatFullDate, formatTime } from '../../util/dates/dateFormat'; +import { DAY } from '../../util/dates/units'; import { orderBy } from '../../util/iteratees'; import { formatPhoneNumber } from '../../util/phoneNumber'; import { prepareSearchWordsForNeedle } from '../../util/searchWords'; @@ -227,11 +228,11 @@ export function sortUserIds( switch (userStatus.type) { case 'userStatusRecently': - return now - 60 * 60 * 24; + return now - DAY; case 'userStatusLastWeek': - return now - 60 * 60 * 24 * 7; + return now - DAY * 7; case 'userStatusLastMonth': - return now - 60 * 60 * 24 * 7 * 30; + return now - DAY * 7 * 30; default: return 0; } diff --git a/src/global/initialState.ts b/src/global/initialState.ts index 323e6d19e..6f1219447 100644 --- a/src/global/initialState.ts +++ b/src/global/initialState.ts @@ -313,8 +313,6 @@ export const INITIAL_GLOBAL_STATE: GlobalState = { isMinimized: false, isHidden: false, }, - - monetizationInfo: {}, }; export const INITIAL_TAB_STATE: TabState = { diff --git a/src/global/reducers/index.ts b/src/global/reducers/index.ts index 3ed9c26fe..99507b0fd 100644 --- a/src/global/reducers/index.ts +++ b/src/global/reducers/index.ts @@ -13,5 +13,4 @@ export * from './statistics'; export * from './stories'; export * from './translations'; export * from './peers'; -export * from './password'; export * from './topics'; diff --git a/src/global/reducers/password.ts b/src/global/reducers/password.ts deleted file mode 100644 index 9e9a24d77..000000000 --- a/src/global/reducers/password.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { GlobalState } from '../types'; - -export function updateMonetizationInfo( - global: T, - update: GlobalState['monetizationInfo'], -): T { - return { - ...global, - monetizationInfo: { - ...global.monetizationInfo, - ...update, - }, - }; -} diff --git a/src/global/reducers/statistics.ts b/src/global/reducers/statistics.ts index 7466ef276..cd89d5f20 100644 --- a/src/global/reducers/statistics.ts +++ b/src/global/reducers/statistics.ts @@ -2,7 +2,7 @@ import type { ApiChannelMonetizationStatistics, ApiChannelStatistics, ApiGroupStatistics, ApiPostStatistics, StatisticsGraph, } from '../../api/types'; -import type { GlobalState, TabArgs } from '../types'; +import type { GlobalState, TabArgs, TabState } from '../types'; import { getCurrentTabId } from '../../util/establishMultitabRole'; import { selectTabState } from '../selectors'; @@ -78,3 +78,20 @@ export function updateChannelMonetizationStatistics( }, }, tabId); } + +export function updateVerifyMonetizationModal( + global: T, update: Partial, + ...[tabId = getCurrentTabId()]: TabArgs +): T { + const tabState = selectTabState(global, tabId); + if (!tabState.monetizationVerificationModal) { + return global; + } + + return updateTabState(global, { + monetizationVerificationModal: { + ...tabState.monetizationVerificationModal, + ...update, + }, + }, tabId); +} diff --git a/src/global/types/actions.ts b/src/global/types/actions.ts index 4d7c141b5..61996b911 100644 --- a/src/global/types/actions.ts +++ b/src/global/types/actions.ts @@ -173,7 +173,11 @@ export interface ActionPayloads { updatePerformanceSettings: Partial; loadPasswordInfo: undefined; clearTwoFaError: undefined; - clearMonetizationInfo: undefined; + openMonetizationVerificationModal: { + chatId: string; + } & WithTabId; + clearMonetizationVerificationError: WithTabId | undefined; + closeMonetizationVerificationModal: WithTabId | undefined; updatePassword: { currentPassword: string; password: string; @@ -756,10 +760,9 @@ export interface ActionPayloads { peerId: string; } & WithTabId; - loadMonetizationRevenueWithdrawalUrl: { + processMonetizationRevenueWithdrawalUrl: { peerId: string; currentPassword: string; - onSuccess: VoidFunction; } & WithTabId; // ui @@ -2323,6 +2326,15 @@ export interface ActionPayloads { shouldKeepOriginalDetails?: boolean; upgradeStars?: number; } & WithTabId; + openGiftWithdrawModal: { + gift: ApiSavedStarGift; + } & WithTabId; + clearGiftWithdrawError: WithTabId | undefined; + closeGiftWithdrawModal: WithTabId | undefined; + processStarGiftWithdrawal: { + gift: ApiInputSavedStarGift; + password: string; + } & WithTabId; loadPeerSavedGifts: { peerId: string; shouldRefresh?: boolean; diff --git a/src/global/types/globalState.ts b/src/global/types/globalState.ts index da1446e0c..00651edaf 100644 --- a/src/global/types/globalState.ts +++ b/src/global/types/globalState.ts @@ -109,15 +109,10 @@ export type GlobalState = { twoFaSettings: { hint?: string; isLoading?: boolean; - error?: string; + errorKey?: RegularLangFnParameters; waitingEmailCodeLength?: number; }; - monetizationInfo: { - isLoading?: boolean; - error?: string; - }; - attachmentSettings: { shouldCompress: boolean; shouldSendGrouped: boolean; diff --git a/src/global/types/tabState.ts b/src/global/types/tabState.ts index 4e41c7a78..50830910a 100644 --- a/src/global/types/tabState.ts +++ b/src/global/types/tabState.ts @@ -82,6 +82,7 @@ import type { } from '../../types'; import type { WebApp, WebAppModalStateType } from '../../types/webapp'; import type { SearchResultKey } from '../../util/keys/searchResultKey'; +import type { RegularLangFnParameters } from '../../util/localization'; import type { CallbackAction } from './actions'; export type TabState = { @@ -377,8 +378,8 @@ export type TabState = { receipt?: ApiReceiptRegular; error?: { field?: string; - message?: string; - description?: string; + messageKey?: RegularLangFnParameters; + descriptionKey?: RegularLangFnParameters; }; isPaymentModalOpen?: boolean; isExtendedMedia?: boolean; @@ -720,6 +721,12 @@ export type TabState = { gift?: ApiSavedStarGift; }; + giftWithdrawModal?: { + gift: ApiSavedStarGift; + isLoading?: boolean; + errorKey?: RegularLangFnParameters; + }; + suggestedStatusModal?: { botId: string; webAppKey?: string; @@ -727,5 +734,11 @@ export type TabState = { duration?: number; }; + monetizationVerificationModal?: { + chatId: string; + isLoading?: boolean; + errorKey?: RegularLangFnParameters; + }; + isWaitingForStarGiftUpgrade?: true; }; diff --git a/src/hooks/reducers/usePaymentReducer.ts b/src/hooks/reducers/usePaymentReducer.ts index a0a45ec71..708d2e377 100644 --- a/src/hooks/reducers/usePaymentReducer.ts +++ b/src/hooks/reducers/usePaymentReducer.ts @@ -1,3 +1,4 @@ +import type { RegularLangFnParameters } from '../../util/localization'; import type { Dispatch, StateReducer } from '../useReducer'; import useReducer from '../useReducer'; @@ -21,7 +22,7 @@ export type FormState = { billingZip: string; saveInfo: boolean; saveCredentials: boolean; - formErrors: Record; + formErrors: Partial>; tipAmount: number; savedCredentialId: string; }; diff --git a/src/lib/gramjs/client/2fa.ts b/src/lib/gramjs/client/2fa.ts index 3909335f8..7e9ff22c0 100644 --- a/src/lib/gramjs/client/2fa.ts +++ b/src/lib/gramjs/client/2fa.ts @@ -1,6 +1,7 @@ import type TelegramClient from './TelegramClient'; +import type { WrappedError } from '../../../api/gramjs/helpers/misc'; -import { EmailUnconfirmedError, PasswordModifiedError, RPCError } from '../errors'; +import { EmailUnconfirmedError } from '../errors'; import Api from '../tl/api'; import { generateRandomBytes } from '../Helpers'; @@ -16,13 +17,8 @@ export interface TwoFaParams { onEmailCodeError?: (err: Error) => void; } -export interface TwoFaPasswordParams { - currentPassword?: string; - onPasswordCodeError?: (err: Error) => void; -} - -export type TmpPasswordResult = Api.account.TmpPassword | { error: string } | undefined; -export type PasswordResult = Api.TypeInputCheckPasswordSRP | { error: string } | undefined; +export type TmpPasswordResult = Api.account.TmpPassword | WrappedError | undefined; +export type PasswordResult = Api.TypeInputCheckPasswordSRP | WrappedError | undefined; /** * Changes the 2FA settings of the logged in user. @@ -143,28 +139,17 @@ export async function getTmpPassword(client: TelegramClient, currentPassword: st } const inputPassword = await computeCheck(pwd, currentPassword); - try { - const result = await client.invoke(new Api.account.GetTmpPassword({ - password: inputPassword, - period: ttl, - })); + const result = await client.invoke(new Api.account.GetTmpPassword({ + password: inputPassword, + period: ttl, + })); - return result; - } catch (err: unknown) { - if (err instanceof RPCError && err.errorMessage === 'PASSWORD_HASH_INVALID') { - return { error: err.errorMessage }; - } - - throw err; - } + return result; } export async function getCurrentPassword( client: TelegramClient, - { - currentPassword, - onPasswordCodeError, - }: TwoFaPasswordParams, + currentPassword?: string, ): Promise { const pwd = await client.invoke(new Api.account.GetPassword()); @@ -172,16 +157,5 @@ export async function getCurrentPassword( return undefined; } - try { - return currentPassword ? await computeCheck(pwd, currentPassword!) : new Api.InputCheckPasswordEmpty(); - } catch (err: any) { - if (err instanceof PasswordModifiedError) { - onPasswordCodeError!(err); - return undefined; - } else if (err instanceof RPCError && err.errorMessage ==='PASSWORD_HASH_INVALID') { - return { error: err.errorMessage }; - } else { - throw err; - } - } + return currentPassword ? await computeCheck(pwd, currentPassword!) : new Api.InputCheckPasswordEmpty(); } diff --git a/src/lib/gramjs/client/TelegramClient.ts b/src/lib/gramjs/client/TelegramClient.ts index 42cdb6b85..0ba7bca34 100644 --- a/src/lib/gramjs/client/TelegramClient.ts +++ b/src/lib/gramjs/client/TelegramClient.ts @@ -24,7 +24,6 @@ import { TwoFaParams, TmpPasswordResult, PasswordResult, - TwoFaPasswordParams, } from './2fa'; import RequestState from '../network/RequestState'; import Deferred from '../../../util/Deferred'; @@ -1264,8 +1263,8 @@ class TelegramClient { return getTmpPassword(this, currentPassword, ttl); } - getCurrentPassword(params: TwoFaPasswordParams): Promise { - return getCurrentPassword(this, params); + getCurrentPassword(currentPassword?: string): Promise { + return getCurrentPassword(this, currentPassword); } // event region diff --git a/src/lib/gramjs/errors/RPCErrorList.ts b/src/lib/gramjs/errors/RPCErrorList.ts index 94d2d63f0..8e40d62b9 100644 --- a/src/lib/gramjs/errors/RPCErrorList.ts +++ b/src/lib/gramjs/errors/RPCErrorList.ts @@ -136,7 +136,7 @@ export class EmailUnconfirmedError extends BadRequestError { } } -export class PasswordModifiedError extends BadRequestError { +export class PasswordFreshError extends BadRequestError { public seconds: number; constructor(args: any) { @@ -159,6 +159,6 @@ export const rpcErrorRe = new Map([ [/USER_MIGRATE_(\d+)/, UserMigrateError], [/NETWORK_MIGRATE_(\d+)/, NetworkMigrateError], [/EMAIL_UNCONFIRMED_(\d+)/, EmailUnconfirmedError], - [/PASSWORD_TOO_FRESH_(\d+)/, PasswordModifiedError], + [/PASSWORD_TOO_FRESH_(\d+)/, PasswordFreshError], [/^Timeout$/, TimedOutError], ]); diff --git a/src/lib/gramjs/tl/apiTl.ts b/src/lib/gramjs/tl/apiTl.ts index c42e80eae..bc69afbd8 100644 --- a/src/lib/gramjs/tl/apiTl.ts +++ b/src/lib/gramjs/tl/apiTl.ts @@ -1722,6 +1722,7 @@ payments.upgradeStarGift#aed6e4f5 flags:# keep_original_details:flags.0?true sta payments.transferStarGift#7f18176a stargift:InputSavedStarGift to_id:InputPeer = Updates; payments.getUniqueStarGift#a1974d72 slug:string = payments.UniqueStarGift; payments.getSavedStarGifts#23830de9 flags:# exclude_unsaved:flags.0?true exclude_saved:flags.1?true exclude_unlimited:flags.2?true exclude_limited:flags.3?true exclude_unique:flags.4?true sort_by_value:flags.5?true peer:InputPeer offset:string limit:int = payments.SavedStarGifts; +payments.getStarGiftWithdrawalUrl#d06e93a8 stargift:InputSavedStarGift password:InputCheckPasswordSRP = payments.StarGiftWithdrawalUrl; 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; diff --git a/src/lib/gramjs/tl/static/api.json b/src/lib/gramjs/tl/static/api.json index 43c848019..5d247db2a 100644 --- a/src/lib/gramjs/tl/static/api.json +++ b/src/lib/gramjs/tl/static/api.json @@ -310,6 +310,7 @@ "payments.upgradeStarGift", "payments.transferStarGift", "payments.getUniqueStarGift", + "payments.getStarGiftWithdrawalUrl", "langpack.getLangPack", "langpack.getStrings", "langpack.getLanguages", diff --git a/src/styles/icons.scss b/src/styles/icons.scss index 9b6bfa377..7376f860e 100644 --- a/src/styles/icons.scss +++ b/src/styles/icons.scss @@ -124,165 +124,166 @@ $icons-map: ( "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", + "fragment": "\f15a", + "fullscreen": "\f15b", + "gifs": "\f15c", + "gift": "\f15d", + "group-filled": "\f15e", + "group": "\f15f", + "grouped-disable": "\f160", + "grouped": "\f161", + "hand-stop": "\f162", + "hashtag": "\f163", + "heart-outline": "\f164", + "heart": "\f165", + "help": "\f166", + "info-filled": "\f167", + "info": "\f168", + "install": "\f169", + "italic": "\f16a", + "key": "\f16b", + "keyboard": "\f16c", + "lamp": "\f16d", + "language": "\f16e", + "large-pause": "\f16f", + "large-play": "\f170", + "link-badge": "\f171", + "link-broken": "\f172", + "link": "\f173", + "location": "\f174", + "lock-badge": "\f175", + "lock": "\f176", + "logout": "\f177", + "loop": "\f178", + "mention": "\f179", + "message-failed": "\f17a", + "message-pending": "\f17b", + "message-read": "\f17c", + "message-succeeded": "\f17d", + "message": "\f17e", + "microphone-alt": "\f17f", + "microphone": "\f180", + "monospace": "\f181", + "more-circle": "\f182", + "more": "\f183", + "move-caption-down": "\f184", + "move-caption-up": "\f185", + "mute": "\f186", + "muted": "\f187", + "my-notes": "\f188", + "new-chat-filled": "\f189", + "next": "\f18a", + "nochannel": "\f18b", + "noise-suppression": "\f18c", + "non-contacts": "\f18d", + "one-filled": "\f18e", + "open-in-new-tab": "\f18f", + "password-off": "\f190", + "pause": "\f191", + "permissions": "\f192", + "phone-discard-outline": "\f193", + "phone-discard": "\f194", + "phone": "\f195", + "photo": "\f196", + "pin-badge": "\f197", + "pin-list": "\f198", + "pin": "\f199", + "pinned-chat": "\f19a", + "pinned-message": "\f19b", + "pip": "\f19c", + "play-story": "\f19d", + "play": "\f19e", + "poll": "\f19f", + "previous": "\f1a0", + "privacy-policy": "\f1a1", + "quote-text": "\f1a2", + "quote": "\f1a3", + "readchats": "\f1a4", + "recent": "\f1a5", + "reload": "\f1a6", + "remove-quote": "\f1a7", + "remove": "\f1a8", + "reopen-topic": "\f1a9", + "replace": "\f1aa", + "replies": "\f1ab", + "reply-filled": "\f1ac", + "reply": "\f1ad", + "revenue-split": "\f1ae", + "revote": "\f1af", + "save-story": "\f1b0", + "saved-messages": "\f1b1", + "schedule": "\f1b2", + "search": "\f1b3", + "select": "\f1b4", + "send-outline": "\f1b5", + "send": "\f1b6", + "settings-filled": "\f1b7", + "settings": "\f1b8", + "share-filled": "\f1b9", + "share-screen-outlined": "\f1ba", + "share-screen-stop": "\f1bb", + "share-screen": "\f1bc", + "show-message": "\f1bd", + "sidebar": "\f1be", + "skip-next": "\f1bf", + "skip-previous": "\f1c0", + "smallscreen": "\f1c1", + "smile": "\f1c2", + "sort": "\f1c3", + "speaker-muted-story": "\f1c4", + "speaker-outline": "\f1c5", + "speaker-story": "\f1c6", + "speaker": "\f1c7", + "spoiler-disable": "\f1c8", + "spoiler": "\f1c9", + "sport": "\f1ca", + "star": "\f1cb", + "stars-lock": "\f1cc", + "stats": "\f1cd", + "stealth-future": "\f1ce", + "stealth-past": "\f1cf", + "stickers": "\f1d0", + "stop-raising-hand": "\f1d1", + "stop": "\f1d2", + "story-caption": "\f1d3", + "story-expired": "\f1d4", + "story-priority": "\f1d5", + "story-reply": "\f1d6", + "strikethrough": "\f1d7", + "tag-add": "\f1d8", + "tag-crossed": "\f1d9", + "tag-filter": "\f1da", + "tag-name": "\f1db", + "tag": "\f1dc", + "timer": "\f1dd", + "toncoin": "\f1de", + "trade": "\f1df", + "transcribe": "\f1e0", + "truck": "\f1e1", + "unarchive": "\f1e2", + "underlined": "\f1e3", + "unlock-badge": "\f1e4", + "unlock": "\f1e5", + "unmute": "\f1e6", + "unpin": "\f1e7", + "unread": "\f1e8", + "up": "\f1e9", + "user-filled": "\f1ea", + "user-online": "\f1eb", + "user": "\f1ec", + "video-outlined": "\f1ed", + "video-stop": "\f1ee", + "video": "\f1ef", + "view-once": "\f1f0", + "voice-chat": "\f1f1", + "volume-1": "\f1f2", + "volume-2": "\f1f3", + "volume-3": "\f1f4", + "web": "\f1f5", + "webapp": "\f1f6", + "word-wrap": "\f1f7", + "zoom-in": "\f1f8", + "zoom-out": "\f1f9", ); .icon-active-sessions::before { @@ -552,6 +553,9 @@ $icons-map: ( .icon-forward::before { content: map.get($icons-map, "forward"); } +.icon-fragment::before { + content: map.get($icons-map, "fragment"); +} .icon-fullscreen::before { content: map.get($icons-map, "fullscreen"); } diff --git a/src/styles/icons.woff b/src/styles/icons.woff index 48794b466b624a6761bfc270cf2f1103eb64af22..2a88b40d595f8228a31888dae44d784ba45d3a8f 100644 GIT binary patch delta 31391 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 delta 31293 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ɲSD;H&r=zK(C;oA?&Kjql*Q_#VEGAK-`h5q^xH;HUT*evV(@m-rQa zjo;w6_#J+aKj4q}6aI|9;IH@_{*Hg(pZFL4jsM_0{C8*0xRV=^T4Al!%1&99rCNz} z!Lomqn0r=RVbY~63X#Pf?-A&;tdwfZibC(Dwi0YTWJ;E-uu0gR*EeH^=l%tag59Ik z=rS#tRP#>abl}65(@8^mGrgx$E)6e4vM*_2A(n33KqFT zh1S-kx^{(Bq952etc}TofGvq!%5_;Xl^r|=+cqks%h}$dUd=fxgvwZmw-YArc*0pJ z3`;5Og9i3EGZ8)6m@}KVA)1jNN{OP?J8bEs-8WL~*~I(Wq<0+LZg8LHg0B-^Xuf|= zMJ8Q8zzMBZwCcwVak`ScAMlLUItw`|G|OgO7X_>6OsO+g#2xiO8+k;W;5`?LUTU4> zYwuwzNVu-H6x~d+$itYtUXvCPWfc8slato3amzyfTkNZH(BL8ID7DJsO!L|+pJcjT z6m3mM-q^UaI1&_rDEKR={E9vu7iNDV4p)?)#*0BiP83^;gLgXX5}xdf#vZof9^v_t zZOG%JCdVC5hXdGKjbHU7h0S6Z4qNv7FEp>lao*oaS zvW|LvAZeAnw-(!&o`oj6qJouGTrjn&sWrw0Gb@o+j8c-cxM16a-mq@#u7O6c$q|oZ zDzz{#l2Cq4bUYjsdPT+&CYyaK>CCKc!E{Oa64|_?6?KYKt4YU=VA*a*Y|Xh48TCXf znU#_oUFCk(vBD+$bVRkIZN-1M7?;{~wI6xBTWXqAoK@bAQ1$cUBy|;)wG(~6WO2Do zm3G3;mDmdtri-T%huui&wkvm)mR5whWtu5GQKXAg4bX75iMO!%;aroCsZ^;~=-6UX zF>Cj9dX$*6 z$XScqAkx=W;*;x(%4{PKql%h7CRa96*LGGJxnX>pl2r0-a%N2tNgV~CAK=JmDU6|k z5u6fCoA1ks5h1eS(4ZkC3jql8XJ`byjf=2LVJCjyc5M*Ilxz^HrqI#}uXsbc5Gt(vOP(zw_?S7x_ z9w+s!I5}2Agf6qzqM?ed}-3i2C0oezB?V%|1bAXV!lS>YqGa)~+^U(orf+ z7q>&+?s`X4!=$A!rG5%UUNQ}D@4BaDG;O63*{oqyK7MR&#|>@rYMqg5;c}X4t9(df z%-@S+zf%uen#PI8?G@^wqARmUpzkEzokOP;*HZPJVVOv1RTMk diff --git a/src/styles/icons.woff2 b/src/styles/icons.woff2 index 94e8bf132ef6b165bc9b88d3aedc0af398397b9b..9efed8b4e64f429d0b4830c8b71504e5d1e54af1 100644 GIT binary patch literal 26476 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 X1*~kFxUdmh literal 26400 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 diff --git a/src/types/icons/font.ts b/src/types/icons/font.ts index 46c5150ab..e0ccd605d 100644 --- a/src/types/icons/font.ts +++ b/src/types/icons/font.ts @@ -88,6 +88,7 @@ export type FontIconName = | 'fontsize' | 'forums' | 'forward' + | 'fragment' | 'fullscreen' | 'gifs' | 'gift' diff --git a/src/types/language.d.ts b/src/types/language.d.ts index 522a44ff1..8f3f58d55 100644 --- a/src/types/language.d.ts +++ b/src/types/language.d.ts @@ -590,10 +590,17 @@ export interface LangPair { 'ErrorSendRestrictedStickersAll': undefined; 'ErrorPhoneNumberInvalid': undefined; 'ErrorCodeInvalid': undefined; + 'ErrorEmailCodeInvalid': undefined; 'ErrorIncorrectPassword': undefined; 'ErrorPasswordFlood': undefined; 'ErrorPhoneBanned': undefined; 'ErrorUnexpected': undefined; + 'ErrorEmailUnconfirmed': undefined; + 'ErrorEmailHashExpired': undefined; + 'ErrorNewSaltInvalid': undefined; + 'ErrorPasswordChanged': undefined; + 'ErrorPasswordMissing': undefined; + 'ErrorUnspecified': undefined; 'NoStickers': undefined; 'ClearRecentEmoji': undefined; 'TextFormatAddLinkTitle': undefined; @@ -1190,6 +1197,7 @@ export interface LangPair { 'GiftInfoViewUpgraded': undefined; 'GiftInfoUpgradeBadge': undefined; 'GiftInfoUpgradeForFree': undefined; + 'GiftInfoWithdraw': undefined; 'GiftUpgradeUniqueTitle': undefined; 'GiftUpgradeUniqueDescription': undefined; 'GiftUpgradeTransferableTitle': undefined; @@ -1203,6 +1211,8 @@ export interface LangPair { 'GiftUpgradedDescription': undefined; 'GiftMakeUniqueAcc': undefined; 'GiftMakeUniqueLink': undefined; + 'GiftWithdrawTitle': undefined; + 'GiftWithdrawSubmit': undefined; 'AllGiftsCategory': undefined; 'LimitedGiftsCategory': undefined; 'StockGiftsCategory': undefined; @@ -1296,6 +1306,9 @@ export interface LangPair { 'ViewButtonGiftUnique': undefined; 'AuthContinueOnThisLanguage': undefined; 'Share': undefined; + 'CheckPasswordTitle': undefined; + 'CheckPasswordPlaceholder': undefined; + 'CheckPasswordDescription': undefined; } export interface LangPairWithVariables { @@ -1461,6 +1474,12 @@ export interface LangPairWithVariables { 'SlowModeHint': { 'time': V; }; + 'ErrorFloodTime': { + 'time': V; + }; + 'ErrorPasswordFresh': { + 'time': V; + }; 'ErrorUnexpectedMessage': { 'error': V; }; @@ -1707,6 +1726,9 @@ export interface LangPairWithVariables { 'peer': V; 'link': V; }; + 'GiftWithdrawDescription': { + 'gift': V; + }; 'StarsAmount': { 'amount': V; }; @@ -1829,9 +1851,6 @@ export interface LangPairPluralWithVariables { 'PreviewSenderSendFile': { 'count': V; }; - 'ErrorFlood': { - 'hour': V; - }; 'PinnedMessageTitle': { 'index': V; }; @@ -1958,6 +1977,9 @@ export interface LangPairPluralWithVariables { 'count': V; 'total': V; }; + 'GiftWithdrawWait': { + 'days': V; + }; 'StarsAmountText': { 'amount': V; }; diff --git a/src/util/dates/units.ts b/src/util/dates/units.ts new file mode 100644 index 000000000..cb1bdc1a6 --- /dev/null +++ b/src/util/dates/units.ts @@ -0,0 +1,19 @@ +/// In seconds +export const MINUTE = 60; +export const HOUR = 3600; +export const DAY = 86400; + +export function getMinutes(seconds: number, roundDown?: boolean) { + const roundFunc = roundDown ? Math.floor : Math.ceil; + return roundFunc(seconds / MINUTE); +} + +export function getHours(seconds: number, roundDown?: boolean) { + const roundFunc = roundDown ? Math.floor : Math.ceil; + return roundFunc(seconds / HOUR); +} + +export function getDays(seconds: number, roundDown?: boolean) { + const roundFunc = roundDown ? Math.floor : Math.ceil; + return roundFunc(seconds / DAY); +} diff --git a/src/util/localization/index.ts b/src/util/localization/index.ts index f4243a997..6d794d2ad 100644 --- a/src/util/localization/index.ts +++ b/src/util/localization/index.ts @@ -361,7 +361,7 @@ function getString(langKey: LangKey, count: number) { function processTranslation( langKey: LangKey, - variables?: Record, + variables?: Record, options?: LangFnOptions | LangFnOptionsWithPlural, ): string { const cacheKey = `${langKey}-${JSON.stringify(variables)}-${JSON.stringify(options)}`; @@ -377,6 +377,9 @@ function processTranslation( const variableEntries = variables ? Object.entries(variables) : []; const finalString = variableEntries.reduce((result, [key, value]) => { if (value === undefined) return result; + if (typeof value === 'object') { // Allow recursive variables in basic `lang.with` + value = processTranslation(value.key, value.variables, value.options); + } const valueAsString = Number.isFinite(value) ? formatters!.number.format(value as number) : String(value); return result.replace(`{${key}}`, valueAsString); diff --git a/src/util/localization/types.ts b/src/util/localization/types.ts index 0a1dd412b..b5b3411ac 100644 --- a/src/util/localization/types.ts +++ b/src/util/localization/types.ts @@ -11,6 +11,7 @@ import type { TextFilter } from '../../components/common/helpers/renderText'; import type { LangPairPluralWithVariables, LangPairWithVariables, + LangVariable, PluralLangKey, PluralLangKeyWithVariables, RegularLangKey, @@ -55,7 +56,9 @@ type RegularLangFnParametersWithoutVariables = { type RegularLangFnParametersWithVariables = { [K in keyof T]: { key: K; - variables: T[K]; + variables: { + [key in keyof T[K]]: LangVariable | RegularLangFnParameters; + }; options?: LangFnOptions; } }[keyof T]; @@ -69,7 +72,9 @@ type RegularLangFnPluralParameters = { type RegularLangFnPluralParametersWithVariables = { [K in keyof T]: { key: K; - variables: T[K]; + variables: { + [key in keyof T[K]]: LangVariable | RegularLangFnParameters; + }; options: LangFnOptionsWithPlural; } }[keyof T];