[Refactoring] Unify AppConfig and limits (#6139)

This commit is contained in:
zubiden 2025-08-29 08:57:45 +02:00 committed by Alexander Zinchuk
parent 66fa05a002
commit 428d7bb36c
70 changed files with 375 additions and 293 deletions

View File

@ -3,20 +3,11 @@ import { Api as GramJs } from '../../../lib/gramjs';
import type { ApiAppConfig, ApiLimitType, ApiPremiumSection } from '../../types';
import { omitUndefined } from '../../../util/iteratees';
import {
DEFAULT_APP_CONFIG,
DEFAULT_LIMITS,
MAX_UNIQUE_REACTIONS,
SERVICE_NOTIFICATIONS_USER_ID,
STORY_EXPIRE_PERIOD,
STORY_VIEWERS_EXPIRE_PERIOD,
TODO_ITEM_LENGTH_LIMIT,
TODO_ITEMS_LIMIT,
TODO_TITLE_LENGTH_LIMIT,
TON_SUGGESTED_POST_AMOUNT_MAX,
TON_SUGGESTED_POST_AMOUNT_MIN,
TON_TOPUP_URL_DEFAULT,
TON_USD_RATE_DEFAULT,
} from '../../../config';
} from '../../../limits';
import localDb from '../localDb';
import { buildJson } from './misc';
@ -36,7 +27,8 @@ type Limit =
| 'chatlist_invites_limit'
| 'chatlist_joined_limit'
| 'recommended_channels_limit'
| 'saved_dialogs_pinned_limit';
| 'saved_dialogs_pinned_limit'
| 'reactions_user_max';
type LimitKey = `${Limit}_${LimitType}`;
type LimitsConfig = Record<LimitKey, number>;
@ -57,6 +49,7 @@ export interface GramJsAppConfig extends LimitsConfig {
autologin_domains: string[];
autologin_token: string;
url_auth_domains: string[];
whitelisted_domains: string[];
premium_purchase_blocked: boolean;
giveaway_gifts_purchase_available: boolean;
giveaway_add_peers_max: number;
@ -74,11 +67,9 @@ export interface GramJsAppConfig extends LimitsConfig {
// Forums
topics_pinned_limit: number;
// Stories
stories_all_hidden?: boolean;
story_expire_period: number;
story_viewers_expire_period: number;
stories_changelog_user_id?: number;
stories_pinned_to_top_count_max?: number;
stories_changelog_user_id: number;
stories_pinned_to_top_count_max: number;
// Boosts
group_transcribe_level_min?: number;
new_noncontact_peers_require_premium_without_ownpremium?: boolean;
@ -157,14 +148,15 @@ function getLimit(appConfig: GramJsAppConfig, key: Limit, fallbackKey: ApiLimitT
export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiAppConfig {
const appConfig = buildJson(json) as GramJsAppConfig;
return {
const config: Partial<ApiAppConfig> = {
emojiSounds: buildEmojiSounds(appConfig),
seenByMaxChatMembers: appConfig.chat_read_mark_size_threshold,
seenByExpiresAt: appConfig.chat_read_mark_expire_period,
readDateExpiresAt: appConfig.pm_read_date_expire_period,
autologinDomains: appConfig.autologin_domains || [],
urlAuthDomains: appConfig.url_auth_domains || [],
maxUniqueReactions: appConfig.reactions_uniq_max ?? MAX_UNIQUE_REACTIONS,
whitelistedDomains: appConfig.whitelisted_domains || [],
maxUniqueReactions: appConfig.reactions_uniq_max,
premiumBotUsername: appConfig.premium_bot_username,
premiumInvoiceSlug: appConfig.premium_invoice_slug,
premiumPromoOrder: appConfig.premium_promo_order as ApiPremiumSection[],
@ -172,8 +164,6 @@ export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiApp
isGiveawayGiftsPurchaseAvailable: appConfig.giveaway_gifts_purchase_available,
defaultEmojiStatusesStickerSetId: appConfig.default_emoji_statuses_stickerset_id,
topicsPinnedLimit: appConfig.topics_pinned_limit,
maxUserReactionsDefault: appConfig.reactions_user_max_default,
maxUserReactionsPremium: appConfig.reactions_user_max_premium,
hiddenMembersMinCount: appConfig.hidden_members_group_size_min,
giveawayAddPeersMax: appConfig.giveaway_add_peers_max,
giveawayBoostsPerPremium: appConfig.giveaway_boosts_per_premium,
@ -195,13 +185,12 @@ export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiApp
chatlistJoined: getLimit(appConfig, 'chatlist_joined_limit', 'chatlistJoined'),
recommendedChannels: getLimit(appConfig, 'recommended_channels_limit', 'recommendedChannels'),
savedDialogsPinned: getLimit(appConfig, 'saved_dialogs_pinned_limit', 'savedDialogsPinned'),
maxReactions: getLimit(appConfig, 'reactions_user_max', 'maxReactions'),
moreAccounts: DEFAULT_LIMITS.moreAccounts,
},
hash,
areStoriesHidden: appConfig.stories_all_hidden,
storyExpirePeriod: appConfig.story_expire_period ?? STORY_EXPIRE_PERIOD,
storyViewersExpirePeriod: appConfig.story_viewers_expire_period ?? STORY_VIEWERS_EXPIRE_PERIOD,
storyChangelogUserId: appConfig.stories_changelog_user_id?.toString() ?? SERVICE_NOTIFICATIONS_USER_ID,
storyViewersExpirePeriod: appConfig.story_viewers_expire_period,
storyChangelogUserId: appConfig.stories_changelog_user_id?.toString(),
maxPinnedStoriesCount: appConfig.stories_pinned_to_top_count_max,
groupTranscribeLevelMin: appConfig.group_transcribe_level_min,
canLimitNewMessagesWithoutPremium: appConfig.new_noncontact_peers_require_premium_without_ownpremium,
@ -238,18 +227,23 @@ export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiApp
starsSuggestedPostFutureMax: appConfig.stars_suggested_post_future_max,
starsSuggestedPostFutureMin: appConfig.stars_suggested_post_future_min,
tonSuggestedPostCommissionPermille: appConfig.ton_suggested_post_commission_permille,
tonSuggestedPostAmountMax: appConfig.ton_suggested_post_amount_max ?? TON_SUGGESTED_POST_AMOUNT_MAX,
tonSuggestedPostAmountMin: appConfig.ton_suggested_post_amount_min ?? TON_SUGGESTED_POST_AMOUNT_MIN,
tonUsdRate: appConfig.ton_usd_rate ?? TON_USD_RATE_DEFAULT,
tonTopupUrl: appConfig.ton_topup_url ?? TON_TOPUP_URL_DEFAULT,
tonSuggestedPostAmountMax: appConfig.ton_suggested_post_amount_max,
tonSuggestedPostAmountMin: appConfig.ton_suggested_post_amount_min,
tonUsdRate: appConfig.ton_usd_rate,
tonTopupUrl: appConfig.ton_topup_url,
pollMaxAnswers: appConfig.poll_answers_max,
todoItemsMax: appConfig.todo_items_max ?? TODO_ITEMS_LIMIT,
todoTitleLengthMax: appConfig.todo_title_length_max ?? TODO_TITLE_LENGTH_LIMIT,
todoItemLengthMax: appConfig.todo_item_length_max ?? TODO_ITEM_LENGTH_LIMIT,
todoItemsMax: appConfig.todo_items_max,
todoTitleLengthMax: appConfig.todo_title_length_max,
todoItemLengthMax: appConfig.todo_item_length_max,
ignoreRestrictionReasons: appConfig.ignore_restriction_reasons,
needAgeVideoVerification: appConfig.need_age_video_verification,
verifyAgeBotUsername: appConfig.verify_age_bot_username,
verifyAgeCountry: appConfig.verify_age_country,
verifyAgeMin: appConfig.verify_age_min,
};
return {
...DEFAULT_APP_CONFIG,
...omitUndefined(config),
};
}

View File

@ -6,7 +6,7 @@ import type {
ApiChat, ApiGroupCall, ApiPhoneCall, ApiUser,
} from '../../types';
import { GROUP_CALL_PARTICIPANTS_LIMIT } from '../../../config';
import { GROUP_CALL_PARTICIPANTS_LIMIT } from '../../../limits';
import {
buildApiGroupCall,
buildApiGroupCallParticipant, buildCallProtocol,

View File

@ -27,13 +27,13 @@ import {
ARCHIVED_FOLDER_ID,
DEBUG,
GENERAL_TOPIC_ID,
GLOBAL_SEARCH_CONTACTS_LIMIT,
MAX_INT_32,
MEMBERS_LOAD_SLICE,
SERVICE_NOTIFICATIONS_USER_ID,
TOPICS_SLICE,
} from '../../../config';
import { buildCollectionByKey, omitUndefined } from '../../../util/iteratees';
import { GLOBAL_SEARCH_CONTACTS_LIMIT } from '../../../limits';
import {
buildApiChatBotCommands,
buildApiChatFolder,

View File

@ -38,13 +38,11 @@ import {
} from '../../types';
import {
API_GENERAL_ID_LIMIT,
DEBUG,
GIF_MIME_TYPE,
MAX_INT_32,
MENTION_UNREAD_SLICE,
MESSAGE_ID_REQUIRED_ERROR,
PINNED_MESSAGES_LIMIT,
REACTION_UNREAD_SLICE,
SUPPORTED_PHOTO_CONTENT_TYPES,
SUPPORTED_VIDEO_CONTENT_TYPES,
@ -54,6 +52,7 @@ import { compact, split } from '../../../util/iteratees';
import { getMessageKey } from '../../../util/keys/messageKey';
import { getServerTime } from '../../../util/serverTime';
import { interpolateArray } from '../../../util/waveform';
import { API_GENERAL_ID_LIMIT, PINNED_MESSAGES_LIMIT } from '../../../limits';
import {
buildApiChatFromPreview,
buildApiSendAsPeerId,

View File

@ -5,13 +5,13 @@ import type {
ApiChat, ApiReaction, ApiSticker,
} from '../../types';
import { split } from '../../../util/iteratees';
import {
API_GENERAL_ID_LIMIT,
REACTION_LIST_LIMIT,
RECENT_REACTIONS_LIMIT,
TOP_REACTIONS_LIMIT,
} from '../../../config';
import { split } from '../../../util/iteratees';
} from '../../../limits';
import {
buildApiAvailableEffect,
buildApiAvailableReaction,

View File

@ -18,11 +18,11 @@ import type {
import {
ACCEPTABLE_USERNAME_ERRORS,
BLOCKED_LIST_LIMIT,
LANG_PACK,
MAX_INT_32,
} from '../../../config';
import { buildCollectionByKey } from '../../../util/iteratees';
import { BLOCKED_LIST_LIMIT } from '../../../limits';
import { buildAppConfig } from '../apiBuilders/appConfig';
import { buildApiPhoto, buildPrivacyRules } from '../apiBuilders/common';
import { buildApiDisallowedGiftsSettings } from '../apiBuilders/gifts';

View File

@ -10,8 +10,9 @@ import type {
ApiTypeStory,
} from '../../types';
import { MESSAGE_ID_REQUIRED_ERROR, STORY_LIST_LIMIT } from '../../../config';
import { MESSAGE_ID_REQUIRED_ERROR } from '../../../config';
import { buildCollectionByCallback } from '../../../util/iteratees';
import { STORY_LIST_LIMIT } from '../../../limits';
import { buildApiReportResult } from '../apiBuilders/messages';
import { getApiChatIdFromMtpPeer } from '../apiBuilders/peers';
import {

View File

@ -205,6 +205,7 @@ export interface ApiAppConfig {
readDateExpiresAt: number;
autologinDomains: string[];
urlAuthDomains: string[];
whitelistedDomains: string[];
premiumInvoiceSlug: string;
premiumBotUsername: string;
isPremiumPurchaseBlocked: boolean;
@ -217,27 +218,24 @@ export interface ApiAppConfig {
defaultEmojiStatusesStickerSetId: string;
maxUniqueReactions: number;
topicsPinnedLimit: number;
maxUserReactionsDefault: number;
maxUserReactionsPremium: number;
hiddenMembersMinCount: number;
limits: Record<ApiLimitType, readonly [number, number]>;
canDisplayAutoarchiveSetting: boolean;
areStoriesHidden?: boolean;
storyExpirePeriod: number;
storyViewersExpirePeriod: number;
storyChangelogUserId: string;
maxPinnedStoriesCount?: number;
groupTranscribeLevelMin?: number;
canLimitNewMessagesWithoutPremium?: boolean;
maxPinnedStoriesCount: number;
groupTranscribeLevelMin: number;
canLimitNewMessagesWithoutPremium: boolean;
starsPaidMessagesAvailable?: boolean;
starsPaidMessageCommissionPermille?: number;
starsPaidMessageAmountMax?: number;
starsUsdWithdrawRateX1000?: number;
starsUsdWithdrawRateX1000: number;
bandwidthPremiumNotifyPeriod?: number;
bandwidthPremiumUploadSpeedup?: number;
bandwidthPremiumDownloadSpeedup?: number;
channelRestrictAdsLevelMin?: number;
channelAutoTranslationLevelMin?: number;
channelLevelMax: number;
paidReactionMaxAmount?: number;
isChannelRevenueWithdrawalEnabled?: boolean;
isStarsGiftEnabled?: boolean;
@ -252,24 +250,24 @@ export interface ApiAppConfig {
starsStargiftResaleAmountMin?: number;
starsStargiftResaleAmountMax?: number;
starsStargiftResaleCommissionPermille?: number;
starsSuggestedPostAmountMax?: number;
starsSuggestedPostAmountMin?: number;
starsSuggestedPostCommissionPermille?: number;
starsSuggestedPostAgeMin?: number;
starsSuggestedPostFutureMax?: number;
starsSuggestedPostFutureMin?: number;
tonSuggestedPostCommissionPermille?: number;
tonSuggestedPostAmountMax?: number;
tonSuggestedPostAmountMin?: number;
starsSuggestedPostAmountMax: number;
starsSuggestedPostAmountMin: number;
starsSuggestedPostCommissionPermille: number;
starsSuggestedPostAgeMin: number;
starsSuggestedPostFutureMax: number;
starsSuggestedPostFutureMin: number;
tonSuggestedPostCommissionPermille: number;
tonSuggestedPostAmountMax: number;
tonSuggestedPostAmountMin: number;
tonStargiftResaleAmountMax?: number;
tonStargiftResaleAmountMin?: number;
tonStargiftResaleCommissionPermille?: number;
tonUsdRate?: number;
tonTopupUrl?: string;
tonTopupUrl: string;
pollMaxAnswers?: number;
todoItemsMax?: number;
todoTitleLengthMax?: number;
todoItemLengthMax?: number;
todoItemsMax: number;
todoTitleLengthMax: number;
todoItemLengthMax: number;
ignoreRestrictionReasons?: string[];
needAgeVideoVerification?: boolean;
verifyAgeBotUsername?: string;
@ -375,14 +373,16 @@ export type ApiLimitType =
| 'chatlistJoined'
| 'recommendedChannels'
| 'savedDialogsPinned'
| 'maxReactions'
| 'moreAccounts';
export type ApiLimitTypeWithModal = Exclude<ApiLimitType, (
'captionLength' | 'aboutLength' | 'stickersFaved' | 'savedGifs' | 'recommendedChannels' | 'moreAccounts'
| 'maxReactions'
)>;
export type ApiLimitTypeForPromo = Exclude<ApiLimitType,
'uploadMaxFileparts' | 'chatlistInvites' | 'chatlistJoined' | 'savedDialogsPinned'
'uploadMaxFileparts' | 'chatlistInvites' | 'chatlistJoined' | 'savedDialogsPinned' | 'maxReactions'
>;
export type ApiPeerNotifySettings = {

View File

@ -47,7 +47,6 @@ import { MAIN_THREAD_ID } from '../../api/types';
import {
BASE_EMOJI_KEYWORD_LANG,
DEFAULT_MAX_MESSAGE_LENGTH,
EDITABLE_INPUT_MODAL_ID,
HEART_REACTION,
MAX_UPLOAD_FILEPART_SIZE,
@ -126,6 +125,7 @@ import parseHtmlAsFormattedText from '../../util/parseHtmlAsFormattedText';
import { insertHtmlInSelection } from '../../util/selection';
import { getServerTime } from '../../util/serverTime';
import windowSize from '../../util/windowSize';
import { DEFAULT_MAX_MESSAGE_LENGTH } from '../../limits';
import applyIosAutoCapitalizationFix from '../middle/composer/helpers/applyIosAutoCapitalizationFix';
import buildAttachment, { prepareAttachmentsToSend } from '../middle/composer/helpers/buildAttachment';
import { buildCustomEmojiHtml } from '../middle/composer/helpers/customEmoji';
@ -2622,7 +2622,7 @@ export default memo(withGlobal<OwnProps>(
isAccountFrozen,
isAppConfigLoaded,
insertingPeerIdMention,
pollMaxAnswers: appConfig?.pollMaxAnswers,
pollMaxAnswers: appConfig.pollMaxAnswers,
};
},
)(Composer));

View File

@ -53,7 +53,7 @@ const SensitiveContentConfirmModal = ({
export default memo(withGlobal<OwnProps>((global): StateProps => {
const appConfig = global.appConfig;
const verifyAgeMin = appConfig?.verifyAgeMin;
const verifyAgeMin = appConfig.verifyAgeMin;
return {
verifyAgeMin: verifyAgeMin || VERIFY_AGE_MIN_DEFAULT,

View File

@ -100,16 +100,16 @@ function PaidMessagePrice({
export default memo(withGlobal<OwnProps>(
(global): StateProps => {
const starsUsdWithdrawRateX1000 = global.appConfig?.starsUsdWithdrawRateX1000;
const starsUsdWithdrawRateX1000 = global.appConfig.starsUsdWithdrawRateX1000;
const starsUsdWithdrawRate = starsUsdWithdrawRateX1000 ? starsUsdWithdrawRateX1000 / 1000 : 1;
const configStarsPaidMessageCommissionPermille = global.appConfig?.starsPaidMessageCommissionPermille;
const configStarsPaidMessageCommissionPermille = global.appConfig.starsPaidMessageCommissionPermille;
const starsPaidMessageCommissionPermille = configStarsPaidMessageCommissionPermille
? configStarsPaidMessageCommissionPermille / 1000 : 100;
return {
starsPaidMessageCommissionPermille,
starsUsdWithdrawRate,
starsPaidMessageAmountMax: global.appConfig?.starsPaidMessageAmountMax || DEFAULT_MAXIMUM_CHARGE_FOR_MESSAGES,
starsPaidMessageAmountMax: global.appConfig.starsPaidMessageAmountMax || DEFAULT_MAXIMUM_CHARGE_FOR_MESSAGES,
};
},
)(PaidMessagePrice));

View File

@ -252,10 +252,12 @@
overflow: hidden;
display: flex;
&-summary {
text-overflow: ellipsis;
overflow: hidden;
flex: unset;
max-width: none;
text-overflow: ellipsis;
white-space: nowrap;
}
.draft {
@ -280,6 +282,8 @@
}
.media-preview--image {
flex-shrink: 0;
width: 1.25rem;
height: 1.25rem;
margin-inline-start: 0.125rem;
@ -289,7 +293,6 @@
vertical-align: -0.25rem;
object-fit: cover;
flex-shrink: 0;
body.is-ios & {
width: 1.125rem;

View File

@ -241,8 +241,8 @@ export default memo(withGlobal<OwnProps>((global): StateProps => {
shouldChargeForMessages: Boolean(nonContactPeersPaidStars),
nonContactPeersPaidStars: nonContactPeersPaidStars || DEFAULT_CHARGE_FOR_MESSAGES,
isCurrentUserPremium: selectIsCurrentUserPremium(global),
canLimitNewMessagesWithoutPremium: global.appConfig?.canLimitNewMessagesWithoutPremium,
canChargeForMessages: global.appConfig?.starsPaidMessagesAvailable,
canLimitNewMessagesWithoutPremium: global.appConfig.canLimitNewMessagesWithoutPremium,
canChargeForMessages: global.appConfig.starsPaidMessagesAvailable,
noPaidReactionsForUsersCount,
privacy,
};

View File

@ -490,12 +490,12 @@ export default memo(withGlobal<OwnProps>(
blockedCount: blocked.totalCount,
webAuthCount: global.activeWebSessions.orderedHashes.length,
isSensitiveEnabled,
canDisplayAutoarchiveSetting: Boolean(appConfig?.canDisplayAutoarchiveSetting),
canDisplayAutoarchiveSetting: Boolean(appConfig.canDisplayAutoarchiveSetting),
shouldArchiveAndMuteNewNonContact,
canChangeSensitive,
shouldNewNonContactPeersRequirePremium,
shouldChargeForMessages,
needAgeVideoVerification: Boolean(appConfig?.needAgeVideoVerification),
needAgeVideoVerification: Boolean(appConfig.needAgeVideoVerification),
privacy,
canDisplayChatInTitle,
canSetPasscode: selectCanSetPasscode(global),

View File

@ -919,10 +919,10 @@ export default memo(withGlobal<OwnProps>((global): StateProps => {
gifts: giveawayModal?.gifts,
selectedMemberList: giveawayModal?.selectedMemberIds,
selectedChannelList: giveawayModal?.selectedChannelIds,
giveawayBoostPerPremiumLimit: global.appConfig?.giveawayBoostsPerPremium,
isStarsGiftEnabled: global.appConfig?.isStarsGiftEnabled,
userSelectionLimit: global.appConfig?.giveawayAddPeersMax,
countrySelectionLimit: global.appConfig?.giveawayCountriesMax,
giveawayBoostPerPremiumLimit: global.appConfig.giveawayBoostsPerPremium,
isStarsGiftEnabled: global.appConfig.isStarsGiftEnabled,
userSelectionLimit: global.appConfig.giveawayAddPeersMax,
countrySelectionLimit: global.appConfig.giveawayCountriesMax,
countryList: global.countryList.general,
prepaidGiveaway: giveawayModal?.prepaidGiveaway,
isChannel,

View File

@ -530,9 +530,9 @@ export default memo(withGlobal<OwnProps>((global): StateProps => {
limitFolders: selectPremiumLimit(global, 'dialogFilters'),
limitPins: selectPremiumLimit(global, 'dialogFolderPinned'),
limitLinks: selectPremiumLimit(global, 'channelsPublic'),
limits: global.appConfig?.limits,
premiumSlug: global.appConfig?.premiumInvoiceSlug,
premiumBotUsername: global.appConfig?.premiumBotUsername,
premiumPromoOrder: global.appConfig?.premiumPromoOrder,
limits: global.appConfig.limits,
premiumSlug: global.appConfig.premiumInvoiceSlug,
premiumBotUsername: global.appConfig.premiumBotUsername,
premiumPromoOrder: global.appConfig.premiumPromoOrder,
};
})(PremiumMainModal));

View File

@ -219,7 +219,7 @@ const PremiumLimitReachedModal: FC<OwnProps & StateProps> = ({
export default memo(withGlobal<OwnProps>(
(global, { limit }): StateProps => {
const { limits } = global.appConfig || {};
const { limits } = global.appConfig;
const isPremium = selectIsCurrentUserPremium(global);
return {

View File

@ -9,11 +9,6 @@ import type { ApiNewMediaTodo } from '../../../api/types';
import type { ApiMessage } from '../../../api/types';
import type { TabState } from '../../../global/types/tabState';
import {
TODO_ITEM_LENGTH_LIMIT,
TODO_ITEMS_LIMIT,
TODO_TITLE_LENGTH_LIMIT,
} from '../../../config';
import { requestMeasure, requestNextMutation } from '../../../lib/fasterdom/fasterdom';
import { selectChatMessage } from '../../../global/selectors';
import captureEscKeyListener from '../../../util/captureEscKeyListener';
@ -40,9 +35,9 @@ export type OwnProps = {
export type StateProps = {
editingMessage?: ApiMessage;
maxItemsCount?: number;
maxTitleLength?: number;
maxItemLength?: number;
maxItemsCount: number;
maxTitleLength: number;
maxItemLength: number;
};
type Item = {
@ -56,9 +51,9 @@ const MAX_OPTION_LENGTH = 100;
const ToDoListModal = ({
modal,
maxItemsCount = TODO_ITEMS_LIMIT,
maxTitleLength = TODO_TITLE_LENGTH_LIMIT,
maxItemLength = TODO_ITEM_LENGTH_LIMIT,
maxItemsCount,
maxTitleLength,
maxItemLength,
editingMessage,
onSend,
onClear,
@ -407,9 +402,9 @@ export default memo(withGlobal<OwnProps>(
const editingMessage = modal?.messageId ? selectChatMessage(global, modal.chatId, modal.messageId) : undefined;
return {
editingMessage,
maxItemsCount: appConfig?.todoItemsMax,
maxTitleLength: appConfig?.todoTitleLengthMax,
maxItemLength: appConfig?.todoItemLengthMax,
maxItemsCount: appConfig.todoItemsMax,
maxTitleLength: appConfig.todoTitleLengthMax,
maxItemLength: appConfig.todoItemLengthMax,
};
},
)(ToDoListModal));

View File

@ -26,9 +26,6 @@ import type {
} from '../../../types';
import { MAIN_THREAD_ID } from '../../../api/types';
import {
TODO_ITEMS_LIMIT,
} from '../../../config';
import { PREVIEW_AVATAR_COUNT, SERVICE_NOTIFICATIONS_USER_ID } from '../../../config';
import {
areReactionsEmpty,
@ -802,7 +799,7 @@ export default memo(withGlobal<OwnProps>(
const {
seenByExpiresAt, seenByMaxChatMembers, maxUniqueReactions, readDateExpiresAt,
} = global.appConfig || {};
} = global.appConfig;
const reactionsLimit = chatFullInfo?.reactionsLimit || maxUniqueReactions;
@ -899,7 +896,7 @@ export default memo(withGlobal<OwnProps>(
const canGift = selectCanGift(global, message.chatId);
const savedDialogId = selectSavedDialogIdFromMessage(global, message);
const todoItemsMax = global.appConfig?.todoItemsMax || TODO_ITEMS_LIMIT;
const todoItemsMax = global.appConfig.todoItemsMax;
const canAppendTodoList = message.content.todo?.todo.othersCanAppend
&& message.content.todo?.todo.items?.length < todoItemsMax;

View File

@ -46,7 +46,7 @@ import type { OnIntersectPinnedMessage } from '../hooks/usePinnedMessage';
import { MAIN_THREAD_ID } from '../../../api/types';
import { AudioOrigin } from '../../../types';
import { EMOJI_STATUS_LOOP_LIMIT, MESSAGE_APPEARANCE_DELAY, STARS_SUGGESTED_POST_FUTURE_MIN } from '../../../config';
import { EMOJI_STATUS_LOOP_LIMIT, MESSAGE_APPEARANCE_DELAY } from '../../../config';
import {
areReactionsEmpty,
getIsDownloading,
@ -1995,7 +1995,7 @@ export default memo(withGlobal<OwnProps>(
? (chatFullInfo?.boostsApplied ?? message.senderBoosts) : message.senderBoosts;
const chatLevel = chat?.boostLevel || 0;
const transcribeMinLevel = global.appConfig?.groupTranscribeLevelMin;
const transcribeMinLevel = global.appConfig.groupTranscribeLevelMin;
const canTranscribeVoice = isPremium || Boolean(transcribeMinLevel && chatLevel >= transcribeMinLevel);
const viaBusinessBot = viaBusinessBotId ? selectUser(global, viaBusinessBotId) : undefined;
@ -2009,7 +2009,7 @@ export default memo(withGlobal<OwnProps>(
const lastPlaybackTimestamp = selectMessageLastPlaybackTimestamp(global, chatId, message.id);
const isAccountFrozen = selectIsCurrentUserFrozen(global);
const minFutureTime = global.appConfig?.starsSuggestedPostFutureMin || STARS_SUGGESTED_POST_FUTURE_MIN;
const minFutureTime = global.appConfig.starsSuggestedPostFutureMin;
const isMediaNsfw = selectIsMediaNsfw(global, message);
const isReplyMediaNsfw = replyMessage && selectIsMediaNsfw(global, replyMessage);

View File

@ -310,7 +310,7 @@ const Photo = <T,>({
export default memo(withGlobal((global): StateProps => {
const appConfig = global.appConfig;
const needsAgeVerification = appConfig?.needAgeVideoVerification;
const needsAgeVerification = appConfig.needAgeVideoVerification;
return {
needsAgeVerification,

View File

@ -232,7 +232,7 @@ const Sticker: FC<OwnProps & StateProps> = ({
export default memo(withGlobal<OwnProps>((global): StateProps => {
const appConfig = global.appConfig;
const needsAgeVerification = appConfig?.needAgeVideoVerification;
const needsAgeVerification = appConfig.needAgeVideoVerification;
return {
needsAgeVerification,

View File

@ -353,7 +353,7 @@ const Video = <T,>({
export default memo(withGlobal((global): StateProps => {
const appConfig = global.appConfig;
const needsAgeVerification = appConfig?.needAgeVideoVerification;
const needsAgeVerification = appConfig.needAgeVideoVerification;
return {
needsAgeVerification,

View File

@ -194,7 +194,7 @@ export default memo(withGlobal<OwnProps>(
canPlayAnimatedEmojis,
sender: giftSender || messageSender,
recipient: giftRecipient || messageRecipient,
starGiftMaxConvertPeriod: global.appConfig?.starGiftMaxConvertPeriod,
starGiftMaxConvertPeriod: global.appConfig.starGiftMaxConvertPeriod,
};
},
)(StarGiftAction));

View File

@ -4,7 +4,7 @@ import { withGlobal } from '../../../../global';
import type { ApiMessage, ApiPeer } from '../../../../api/types';
import type { ApiMessageActionSuggestedPostApproval } from '../../../../api/types/messageActions';
import { STARS_SUGGESTED_POST_AGE_MIN, TON_CURRENCY_CODE } from '../../../../config';
import { TON_CURRENCY_CODE } from '../../../../config';
import { getPeerFullTitle } from '../../../../global/helpers/peers';
import { getMessageReplyInfo } from '../../../../global/helpers/replies';
import { selectIsMonoforumAdmin, selectMonoforumChannel,
@ -146,7 +146,7 @@ export default memo(withGlobal<OwnProps>(
}
const { appConfig } = global;
const ageMinSeconds = appConfig?.starsSuggestedPostAgeMin || STARS_SUGGESTED_POST_AGE_MIN;
const ageMinSeconds = appConfig.starsSuggestedPostAgeMin;
const isAdmin = chat ? Boolean(selectIsMonoforumAdmin(global, message.chatId)) : false;
return {

View File

@ -304,7 +304,7 @@ export default memo(withGlobal<OwnProps>((global): StateProps => {
const message = chatId && messageId ? selectChatMessage(global, chatId, messageId) : undefined;
const isPrivateChat = isUserId(chatId || storyPeerId || '');
const areSomeReactionsAllowed = chatFullInfo?.enabledReactions?.type === 'some';
const { maxUniqueReactions } = global.appConfig || {};
const { maxUniqueReactions } = global.appConfig;
const areAllReactionsAllowed = chatFullInfo?.enabledReactions?.type === 'all'
&& chatFullInfo?.enabledReactions?.areCustomAllowed;

View File

@ -153,7 +153,7 @@ export default memo(withGlobal<OwnProps>(
(global, { chatId }): StateProps => {
const { availableReactions, topReactions } = global.reactions;
const { maxUniqueReactions } = global.appConfig || {};
const { maxUniqueReactions } = global.appConfig;
const { enabledReactions, isPaidReactionAvailable } = selectChatFullInfo(global, chatId) || {};
return {

View File

@ -178,7 +178,7 @@ const AboutAdsModal = ({ modal, minLevelToRestrictAds }: OwnProps & StateProps)
export default memo(withGlobal<OwnProps>(
(global): StateProps => {
const minLevelToRestrictAds = global.appConfig?.channelRestrictAdsLevelMin;
const minLevelToRestrictAds = global.appConfig.channelRestrictAdsLevelMin;
return {
minLevelToRestrictAds,

View File

@ -86,8 +86,8 @@ const AgeVerificationModal: FC<OwnProps & StateProps> = ({
export default memo(withGlobal((global): StateProps => {
const appConfig = global.appConfig;
const verifyAgeBotUsername = appConfig?.verifyAgeBotUsername;
const verifyAgeMin = appConfig?.verifyAgeMin || VERIFY_AGE_MIN_DEFAULT;
const verifyAgeBotUsername = appConfig.verifyAgeBotUsername;
const verifyAgeMin = appConfig.verifyAgeMin || VERIFY_AGE_MIN_DEFAULT;
return {
verifyAgeBotUsername,

View File

@ -63,7 +63,6 @@ const CollectibleInfoModal: FC<OwnProps & StateProps> = ({
const handleOpenUrl = useLastCallback(() => {
openUrl({
url: modal!.url,
shouldSkipModal: true,
});
handleClose();
});

View File

@ -129,8 +129,8 @@ const FrozenAccountModal = ({
export default memo(withGlobal<OwnProps>(
(global): StateProps => {
const freezeUntilDate = global.appConfig?.freezeUntilDate;
const freezeAppealUrl = global.appConfig?.freezeAppealUrl;
const freezeUntilDate = global.appConfig.freezeUntilDate;
const freezeAppealUrl = global.appConfig.freezeAppealUrl;
const botFreezeAppeal = global.botFreezeAppealId ? selectUser(global, global.botFreezeAppealId) : undefined;
const botFreezeAppealUsername = botFreezeAppeal && getMainUsername(botFreezeAppeal);

View File

@ -428,7 +428,7 @@ export default memo(withGlobal<OwnProps>(
patternColor,
customBackground,
backgroundColor,
captionLimit: global.appConfig?.starGiftMaxMessageLength,
captionLimit: global.appConfig.starGiftMaxMessageLength,
currentUserId: global.currentUserId,
isPaymentFormLoading: tabState.isPaymentFormLoading,
paidMessagesStars,

View File

@ -528,7 +528,7 @@ export default memo(withGlobal<OwnProps>((global, { modal }): StateProps => {
const areResaleGiftsLoading = resaleGifts.isLoading !== false;
return {
boostPerSentGift: global.appConfig?.boostsPerSentGift,
boostPerSentGift: global.appConfig.boostsPerSentGift,
starGiftsById: starGifts?.byId,
starGiftIdsByCategory: starGifts?.idsByCategory,
starBalance: stars?.balance,

View File

@ -10,10 +10,10 @@ import type {
} from '../../../api/types';
import type { ResaleGiftsFilterOptions } from '../../../types';
import { RESALE_GIFTS_LIMIT } from '../../../config';
import { selectTabState,
} from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import { RESALE_GIFTS_LIMIT } from '../../../limits';
import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets';
import useInfiniteScroll from '../../../hooks/useInfiniteScroll';

View File

@ -906,8 +906,8 @@ export default memo(withGlobal<OwnProps>(
targetPeer,
releasedByPeer,
currentUserId,
starGiftMaxConvertPeriod: global.appConfig?.starGiftMaxConvertPeriod,
tonExplorerUrl: global.appConfig?.tonExplorerUrl,
starGiftMaxConvertPeriod: global.appConfig.starGiftMaxConvertPeriod,
tonExplorerUrl: global.appConfig.tonExplorerUrl,
hasAdminRights,
currentUserEmojiStatus,
collectibleEmojiStatuses,

View File

@ -176,21 +176,21 @@ const GiftResalePriceComposerModal = ({
export default memo(withGlobal<OwnProps>(
(global): StateProps => {
const configPermille = global.appConfig?.starsStargiftResaleCommissionPermille;
const configPermille = global.appConfig.starsStargiftResaleCommissionPermille;
const starsStargiftResaleCommissionPermille = configPermille ? (configPermille / 1000) : undefined;
const starsStargiftResaleAmountMin = global.appConfig?.starsStargiftResaleAmountMin || 0;
const starsStargiftResaleAmountMax = global.appConfig?.starsStargiftResaleAmountMax;
const starsStargiftResaleAmountMin = global.appConfig.starsStargiftResaleAmountMin || 0;
const starsStargiftResaleAmountMax = global.appConfig.starsStargiftResaleAmountMax;
const starsUsdWithdrawRateX1000 = global.appConfig?.starsUsdWithdrawRateX1000;
const starsUsdWithdrawRateX1000 = global.appConfig.starsUsdWithdrawRateX1000;
const starsUsdWithdrawRate = starsUsdWithdrawRateX1000 ? starsUsdWithdrawRateX1000 / 1000 : 1;
const tonConfigPermille = global.appConfig?.tonStargiftResaleCommissionPermille;
const tonConfigPermille = global.appConfig.tonStargiftResaleCommissionPermille;
const tonStargiftResaleCommissionPermille = tonConfigPermille ? (tonConfigPermille / 1000) : 0;
const tonStargiftResaleAmountMin = convertTonFromNanos(global.appConfig?.tonStargiftResaleAmountMin || 0);
const maxTonFromConfig = global.appConfig?.tonStargiftResaleAmountMax;
const tonStargiftResaleAmountMin = convertTonFromNanos(global.appConfig.tonStargiftResaleAmountMin || 0);
const maxTonFromConfig = global.appConfig.tonStargiftResaleAmountMax;
const tonStargiftResaleAmountMax = maxTonFromConfig && convertTonFromNanos(maxTonFromConfig);
const tonUsdRate = global.appConfig?.tonUsdRate;
const tonUsdRate = global.appConfig.tonUsdRate;
return {
starsStargiftResaleCommissionPermille,

View File

@ -377,7 +377,7 @@ export default memo(withGlobal<OwnProps>(
const chat = modal && selectChat(global, modal.chatId);
const message = modal && selectChatMessage(global, modal.chatId, modal.messageId);
const starBalance = global.stars?.balance;
const maxAmount = global.appConfig?.paidReactionMaxAmount || MAX_REACTION_AMOUNT;
const maxAmount = global.appConfig.paidReactionMaxAmount || MAX_REACTION_AMOUNT;
const defaultPrivacy = global.settings.paidReactionPrivacy;
const sendPaidReactionsAsPeerIds = chat?.sendPaidReactionsAsPeerIds;
const currentUserId = global.currentUserId!;

View File

@ -10,8 +10,6 @@ import {
PAID_MESSAGES_PURPOSE,
STARS_CURRENCY_CODE,
TON_CURRENCY_CODE,
TON_TOPUP_URL_DEFAULT,
TON_USD_RATE_DEFAULT,
} from '../../../config';
import { getChatTitle, getUserFullName } from '../../../global/helpers';
import { getPeerTitle } from '../../../global/helpers/peers';
@ -298,7 +296,7 @@ const StarsBalanceModal = ({
});
const handleTonTopUp = useLastCallback(() => {
openUrl({ url: tonTopupUrl, shouldSkipModal: true });
openUrl({ url: tonTopupUrl });
});
return (
@ -419,8 +417,8 @@ export default memo(withGlobal<OwnProps>(
starsBalanceState: global.stars,
tonBalanceState: global.ton,
canBuyPremium: !selectIsPremiumPurchaseBlocked(global),
tonUsdRate: global.appConfig?.tonUsdRate || TON_USD_RATE_DEFAULT,
tonTopupUrl: global.appConfig?.tonTopupUrl || TON_TOPUP_URL_DEFAULT,
tonUsdRate: global.appConfig.tonUsdRate,
tonTopupUrl: global.appConfig.tonTopupUrl,
animationLevel: selectSharedSettings(global).animationLevel,
};
},

View File

@ -345,7 +345,7 @@ export default memo(withGlobal<OwnProps>(
(global, { modal }): StateProps => {
const peerId = modal?.transaction?.peer?.type === 'peer' && modal.transaction.peer.id;
const peer = peerId ? selectPeer(global, peerId) : undefined;
const paidMessageCommission = global.appConfig?.starsPaidMessageCommissionPermille;
const paidMessageCommission = global.appConfig.starsPaidMessageCommissionPermille;
const currencyAmount = modal?.transaction.amount;
const starsGiftSticker = modal?.transaction.isGift

View File

@ -11,14 +11,8 @@ import { MAIN_THREAD_ID } from '../../../api/types';
import {
STARS_CURRENCY_CODE,
STARS_SUGGESTED_POST_AGE_MIN,
STARS_SUGGESTED_POST_AMOUNT_MAX,
STARS_SUGGESTED_POST_AMOUNT_MIN,
STARS_SUGGESTED_POST_FUTURE_MAX,
STARS_SUGGESTED_POST_FUTURE_MIN,
TON_CURRENCY_CODE,
TON_SUGGESTED_POST_AMOUNT_MAX,
TON_SUGGESTED_POST_AMOUNT_MIN } from '../../../config';
} from '../../../config';
import { selectIsMonoforumAdmin, selectPeer } from '../../../global/selectors';
import { selectDraft } from '../../../global/selectors/messages';
import buildClassName from '../../../util/buildClassName';
@ -29,7 +23,9 @@ import {
formatStarsAsText,
formatTonAsIcon,
formatTonAsText } from '../../../util/localization/format';
import { getServerTime } from '../../../util/serverTime';
import useFlag from '../../../hooks/useFlag';
import useLang from '../../../hooks/useLang';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
@ -46,8 +42,6 @@ export type OwnProps = {
modal: TabState['suggestMessageModal'];
};
import useFlag from '../../../hooks/useFlag';
type StateProps = {
starBalance?: ApiStarsAmount;
tonBalance?: number;
@ -63,6 +57,9 @@ type StateProps = {
isMonoforumAdmin?: boolean;
};
// Add 1 minute if time is less than server min, to allow user to send the message
const FUTURE_TIME_ADJUSTMENT = 1 * 60;
const SuggestMessageModal = ({
modal,
starBalance,
@ -174,7 +171,9 @@ const SuggestMessageModal = ({
updateDraftSuggestedPostInfo({
price: { currency: selectedCurrency, amount: neededAmount, nanos: 0 },
scheduleDate: scheduleDate ? scheduleDate / 1000 : undefined,
scheduleDate: scheduleDate
? Math.max(scheduleDate / 1000, getServerTime() + futureMin + FUTURE_TIME_ADJUSTMENT)
: undefined,
});
closeSuggestMessageModal();
@ -308,14 +307,14 @@ export default memo(withGlobal<OwnProps>(
const currentDraft = modal ? selectDraft(global, modal.chatId, MAIN_THREAD_ID) : undefined;
const { appConfig } = global;
const maxStarsAmount = appConfig?.starsSuggestedPostAmountMax || STARS_SUGGESTED_POST_AMOUNT_MAX;
const minStarsAmount = appConfig?.starsSuggestedPostAmountMin || STARS_SUGGESTED_POST_AMOUNT_MIN;
const ageMinSeconds = appConfig?.starsSuggestedPostAgeMin || STARS_SUGGESTED_POST_AGE_MIN;
const futureMin = appConfig?.starsSuggestedPostFutureMin || STARS_SUGGESTED_POST_FUTURE_MIN;
const futureMax = appConfig?.starsSuggestedPostFutureMax || STARS_SUGGESTED_POST_FUTURE_MAX;
const maxStarsAmount = appConfig.starsSuggestedPostAmountMax;
const minStarsAmount = appConfig.starsSuggestedPostAmountMin;
const ageMinSeconds = appConfig.starsSuggestedPostAgeMin;
const futureMin = appConfig.starsSuggestedPostFutureMin;
const futureMax = appConfig.starsSuggestedPostFutureMax;
const tonMaxAmount = appConfig?.tonSuggestedPostAmountMax || TON_SUGGESTED_POST_AMOUNT_MAX;
const tonMinAmount = appConfig?.tonSuggestedPostAmountMin || TON_SUGGESTED_POST_AMOUNT_MIN;
const tonMaxAmount = appConfig.tonSuggestedPostAmountMax;
const tonMinAmount = appConfig.tonSuggestedPostAmountMin;
const isMonoforumAdmin = modal ? selectIsMonoforumAdmin(global, modal.chatId) : false;

View File

@ -4,12 +4,9 @@ import { getActions, withGlobal } from '../../../global';
import type { ApiMessage, ApiPeer } from '../../../api/types';
import type { TabState } from '../../../global/types';
import { STARS_CURRENCY_CODE, STARS_SUGGESTED_POST_AGE_MIN,
STARS_SUGGESTED_POST_COMMISSION_PERMILLE,
STARS_SUGGESTED_POST_FUTURE_MAX,
STARS_SUGGESTED_POST_FUTURE_MIN,
import {
STARS_CURRENCY_CODE,
TON_CURRENCY_CODE,
TON_SUGGESTED_POST_COMMISSION_PERMILLE,
} from '../../../config';
import { getPeerFullTitle } from '../../../global/helpers/peers';
import { selectChatMessage, selectIsMonoforumAdmin, selectSender } from '../../../global/selectors';
@ -224,13 +221,11 @@ export default memo(withGlobal<OwnProps>(
const sender = message ? selectSender(global, message) : undefined;
const isAdmin = modal && selectIsMonoforumAdmin(global, modal.chatId);
const { appConfig } = global;
const commissionPermille = appConfig?.starsSuggestedPostCommissionPermille
|| STARS_SUGGESTED_POST_COMMISSION_PERMILLE;
const tonCommissionPermille = appConfig?.tonSuggestedPostCommissionPermille
|| TON_SUGGESTED_POST_COMMISSION_PERMILLE;
const minAge = appConfig?.starsSuggestedPostAgeMin || STARS_SUGGESTED_POST_AGE_MIN;
const futureMin = (appConfig?.starsSuggestedPostFutureMin || STARS_SUGGESTED_POST_FUTURE_MIN) * 2;
const futureMax = appConfig?.starsSuggestedPostFutureMax || STARS_SUGGESTED_POST_FUTURE_MAX;
const commissionPermille = appConfig.starsSuggestedPostCommissionPermille;
const tonCommissionPermille = appConfig.tonSuggestedPostCommissionPermille;
const minAge = appConfig.starsSuggestedPostAgeMin;
const futureMin = appConfig.starsSuggestedPostFutureMin;
const futureMax = appConfig.starsSuggestedPostFutureMax;
const scheduleDate = message?.suggestedPostInfo?.scheduleDate;
return {

View File

@ -386,7 +386,7 @@ const useWebAppFrame = (
if (eventType === 'web_app_verify_age') {
const { passed } = eventData;
const minAge = getGlobal().appConfig?.verifyAgeMin || VERIFY_AGE_MIN_DEFAULT;
const minAge = getGlobal().appConfig.verifyAgeMin || VERIFY_AGE_MIN_DEFAULT;
const ageFromParam = eventData.age || 0;
if (passed && ageFromParam >= minAge) {

View File

@ -383,7 +383,7 @@ export default memo(withGlobal<OwnProps>(
const { management } = selectTabState(global);
const { progress } = management;
const { invites } = management.byChatId[chatId] || {};
const minLevelToToggleAutoTranslation = global.appConfig?.channelAutoTranslationLevelMin;
const minLevelToToggleAutoTranslation = global.appConfig.channelAutoTranslationLevelMin;
const hasAutoTranslation = chat?.hasAutoTranslation;
const chatBoostLevel = chat?.level;
const canToggleAutoTranslation = chatBoostLevel && minLevelToToggleAutoTranslation

View File

@ -280,7 +280,7 @@ export default memo(withGlobal<OwnProps>(
const { members, adminMembersById, areParticipantsHidden } = selectChatFullInfo(global, chatId) || {};
const isChannel = chat && isChatChannel(chat);
const { userIds: localContactIds } = global.contactList || {};
const hiddenMembersMinCount = global.appConfig?.hiddenMembersMinCount;
const hiddenMembersMinCount = global.appConfig.hiddenMembersMinCount;
const canDeleteMembers = chat && (chat.isCreator || getHasAdminRight(chat, 'banUsers'));

View File

@ -358,7 +358,7 @@ export default memo(withGlobal<OwnProps>(
const { progress } = selectTabState(global).management;
const paidMessagesStars = chat?.paidMessagesStars;
const configStarsPaidMessageCommissionPermille = global.appConfig?.starsPaidMessageCommissionPermille;
const configStarsPaidMessageCommissionPermille = global.appConfig.starsPaidMessageCommissionPermille;
return {
chat,

View File

@ -10,9 +10,6 @@ import type {
ApiAvailableReaction, ApiChat, ApiChatReactions, ApiReaction,
} from '../../../api/types';
import {
MAX_UNIQUE_REACTIONS,
} from '../../../config';
import { isChatChannel, isSameReaction } from '../../../global/helpers';
import { selectChat, selectChatFullInfo } from '../../../global/selectors';
@ -271,7 +268,7 @@ const ManageReactions: FC<OwnProps & StateProps> = ({
export default memo(withGlobal<OwnProps>(
(global, { chatId }): StateProps => {
const chat = selectChat(global, chatId)!;
const { maxUniqueReactions = MAX_UNIQUE_REACTIONS } = global.appConfig || {};
const { maxUniqueReactions } = global.appConfig;
const chatFullInfo = selectChatFullInfo(global, chatId);
const reactionsLimit = chatFullInfo?.reactionsLimit || maxUniqueReactions;

View File

@ -429,7 +429,7 @@ export default memo(withGlobal(
const chatId = boostStatistics && boostStatistics.chatId;
const chat = chatId ? selectChat(global, chatId) : undefined;
const isChannel = chat && isChatChannel(chat);
const giveawayBoostsPerPremium = global.appConfig?.giveawayBoostsPerPremium;
const giveawayBoostsPerPremium = global.appConfig.giveawayBoostsPerPremium;
const { animationLevel } = selectSharedSettings(global);
return {

View File

@ -301,7 +301,7 @@ export default memo(withGlobal(
const statistics = tabState.statistics.monetization;
const isChannelRevenueWithdrawalEnabled = global.appConfig?.isChannelRevenueWithdrawalEnabled;
const isChannelRevenueWithdrawalEnabled = global.appConfig.isChannelRevenueWithdrawalEnabled;
return {
chatId: chatId!,

View File

@ -190,7 +190,7 @@ export default memo(withGlobal<OwnProps>((global, { story }): StateProps => {
const chat = selectChat(global, story.peerId);
const isProtected = chat?.isProtected;
const { maxPinnedStoriesCount } = global.appConfig || {};
const { maxPinnedStoriesCount } = global.appConfig;
const isOwn = 'isOut' in story && story.isOut;
const pinnedStories = selectPinnedStories(global, story.peerId);
const isPinned = pinnedStories?.some((pinnedStory) => pinnedStory.id === story.id);

View File

@ -981,8 +981,8 @@ export default memo(withGlobal<OwnProps>((global, {
isMuted,
isCurrentUserPremium: selectIsCurrentUserPremium(global),
shouldForcePause,
storyChangelogUserId: appConfig!.storyChangelogUserId,
viewersExpirePeriod: appConfig!.storyExpirePeriod + appConfig!.storyViewersExpirePeriod,
storyChangelogUserId: appConfig.storyChangelogUserId,
viewersExpirePeriod: appConfig.storyViewersExpirePeriod,
isChatExist: Boolean(chat),
arePeerSettingsLoaded: Boolean(userFullInfo?.settings),
stealthMode: global.stories.stealthMode,

View File

@ -44,7 +44,7 @@ interface StateProps {
isLoading?: boolean;
views?: ApiTypeStoryView[];
nextOffset?: string;
viewersExpirePeriod: number;
viewersExpireDate?: number;
isCurrentUserPremium?: boolean;
}
@ -52,7 +52,7 @@ const REFETCH_DEBOUNCE = 250;
function StoryViewModal({
story,
viewersExpirePeriod,
viewersExpireDate,
views,
nextOffset,
isLoading,
@ -69,7 +69,7 @@ function StoryViewModal({
const lang = useOldLang();
const isOpen = Boolean(story);
const isExpired = Boolean(story?.date) && (story.date + viewersExpirePeriod) < getServerTime();
const isExpired = Boolean(viewersExpireDate) && viewersExpireDate < getServerTime();
const { viewsCount = 0, reactionsCount = 0 } = story?.views || {};
const shouldShowJustContacts = story?.isPublic && viewsCount > STORY_VIEWS_MIN_CONTACTS_FILTER;
@ -275,11 +275,12 @@ export default memo(withGlobal((global) => {
storyId, views, nextOffset, isLoading,
} = viewModal || {};
const story = storyId ? selectPeerStory(global, global.currentUserId!, storyId) : undefined;
const storyExpireDate = story?.['@type'] === 'story' ? story.expireDate : undefined;
return {
storyId,
views,
viewersExpirePeriod: appConfig!.storyExpirePeriod + appConfig!.storyViewersExpirePeriod,
viewersExpireDate: storyExpireDate ? (storyExpireDate + appConfig.storyViewersExpirePeriod) : undefined,
story: story && 'content' in story ? story : undefined,
nextOffset,
isLoading,

View File

@ -5,9 +5,6 @@ import { getActions, withGlobal } from '../../global';
import type { ApiStarsAmount, ApiTonAmount } from '../../api/types';
import {
TON_USD_RATE_DEFAULT,
} from '../../config';
import { formatStarsAmount } from '../../global/helpers/payments';
import buildClassName from '../../util/buildClassName';
import { convertTonFromNanos, convertTonToUsd, formatCurrencyAsString } from '../../util/formatCurrency';
@ -30,7 +27,7 @@ export type OwnProps = {
export type StateProps = {
starBalance?: ApiStarsAmount;
tonBalance?: ApiTonAmount;
tonUsdRate: number;
tonUsdRate?: number;
};
function ModalStarBalanceBar({
@ -38,8 +35,8 @@ function ModalStarBalanceBar({
tonBalance,
tonUsdRate,
isModalOpen,
onCloseAnimationEnd,
currency,
onCloseAnimationEnd,
}: StateProps & OwnProps) {
const {
openStarsBalanceModal,
@ -94,7 +91,7 @@ function ModalStarBalanceBar({
)}
</div>
<div>
{isTonMode && (
{isTonMode && Boolean(tonUsdRate) && (
<div className={styles.tonInUsdDescription} style="color: var(--color-text-secondary)">
{`${formatCurrencyAsString(
convertTonToUsd((currentBalance as ApiTonAmount).amount, tonUsdRate, true),
@ -123,7 +120,7 @@ export default memo(withGlobal(
return {
starBalance: stars?.balance,
tonBalance: ton?.balance,
tonUsdRate: global.appConfig?.tonUsdRate || TON_USD_RATE_DEFAULT,
tonUsdRate: global.appConfig.tonUsdRate,
};
},
)(ModalStarBalanceBar));

View File

@ -1,5 +1,5 @@
import type {
ApiLimitType, ApiLimitTypeForPromo, ApiPremiumSection, ApiReactionEmoji,
ApiLimitTypeForPromo, ApiPremiumSection, ApiReactionEmoji,
} from './api/types';
import type {
GiftProfileFilterOptions,
@ -94,39 +94,18 @@ export const CHAT_MEDIA_SLICE = 42;
export const MESSAGE_SEARCH_SLICE = 42;
export const GLOBAL_SEARCH_SLICE = 20;
export const GLOBAL_TOPIC_SEARCH_SLICE = 5;
export const GLOBAL_SEARCH_CONTACTS_LIMIT = 20;
export const MEMBERS_SLICE = 30;
export const MEMBERS_LOAD_SLICE = 200;
export const PINNED_MESSAGES_LIMIT = 50;
export const BLOCKED_LIST_LIMIT = 100;
export const PROFILE_SENSITIVE_AREA = 500;
export const TOPIC_LIST_SENSITIVE_AREA = 600;
export const GROUP_CALL_PARTICIPANTS_LIMIT = 100;
export const STORY_LIST_LIMIT = 100;
export const API_GENERAL_ID_LIMIT = 100;
export const RESALE_GIFTS_LIMIT = 50;
export const TODO_ITEMS_LIMIT = 30;
export const TODO_TITLE_LENGTH_LIMIT = 32;
export const TODO_ITEM_LENGTH_LIMIT = 64;
// Public Posts Search defaults
export const PUBLIC_POSTS_SEARCH_DEFAULT_STARS_AMOUNT = 10;
export const PUBLIC_POSTS_SEARCH_DEFAULT_TOTAL_DAILY = 2;
// Suggested Posts defaults
export const STARS_SUGGESTED_POST_AMOUNT_MAX = 100000;
export const STARS_SUGGESTED_POST_AMOUNT_MIN = 5;
export const STARS_SUGGESTED_POST_COMMISSION_PERMILLE = 850;
export const STARS_SUGGESTED_POST_AGE_MIN = 86400; // 24 hours in seconds
export const STARS_SUGGESTED_POST_FUTURE_MAX = 2678400; // 31 days in seconds
export const STARS_SUGGESTED_POST_FUTURE_MIN = 300; // 5 minutes in seconds
export const TON_CURRENCY_CODE = 'TON';
export const TON_SUGGESTED_POST_COMMISSION_PERMILLE = 850;
export const TON_USD_RATE_DEFAULT = 3;
export const VERIFY_AGE_MIN_DEFAULT = 18;
export const TON_TOPUP_URL_DEFAULT = 'https://fragment.com/ads/topup';
export const TON_SUGGESTED_POST_AMOUNT_MIN = 10000000; // 0.01 TON in nanos
export const TON_SUGGESTED_POST_AMOUNT_MAX = 10000000000000; // 10 000 TON in nanos
export const STORY_VIEWS_MIN_SEARCH = 15;
export const STORY_MIN_REACTIONS_SORT = 10;
@ -136,14 +115,8 @@ export const MEDIA_TIMESTAMP_SAVE_MINIMUM_DURATION = 30; // 30s
export const GLOBAL_SUGGESTED_CHANNELS_ID = 'global';
// As in Telegram for Android
// https://github.com/DrKLO/Telegram/blob/51e9947527/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java#L7799
export const TOP_REACTIONS_LIMIT = 100;
// As in Telegram for Android
// https://github.com/DrKLO/Telegram/blob/51e9947527/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java#L7781
export const RECENT_REACTIONS_LIMIT = 50;
export const REACTION_LIST_LIMIT = 100;
export const REACTION_UNREAD_SLICE = 100;
export const MENTION_UNREAD_SLICE = 100;
export const TOPICS_SLICE = 20;
@ -401,7 +374,6 @@ export const PEER_COLOR_BG_OPACITY = '1a';
export const PEER_COLOR_BG_ACTIVE_OPACITY = '2b';
export const PEER_COLOR_GRADIENT_STEP = 5; // px
export const MAX_UPLOAD_FILEPART_SIZE = 524288;
export const MAX_UNIQUE_REACTIONS = 11;
export const IGNORE_UNHANDLED_ERRORS = new Set([
'USER_CANCELED',
@ -411,25 +383,6 @@ export const IGNORE_UNHANDLED_ERRORS = new Set([
export const GROUP_CALL_VOLUME_MULTIPLIER = 100;
export const GROUP_CALL_DEFAULT_VOLUME = 100 * GROUP_CALL_VOLUME_MULTIPLIER;
export const DEFAULT_LIMITS: Record<ApiLimitType, readonly [number, number]> = {
uploadMaxFileparts: [4000, 8000],
stickersFaved: [5, 10],
savedGifs: [200, 400],
dialogFiltersChats: [100, 200],
dialogFilters: [10, 20],
dialogFolderPinned: [5, 10],
captionLength: [1024, 4096],
channels: [500, 1000],
channelsPublic: [10, 20],
aboutLength: [70, 140],
chatlistInvites: [3, 100],
chatlistJoined: [2, 20],
recommendedChannels: [10, 100],
savedDialogsPinned: [5, 100],
moreAccounts: [3, MULTIACCOUNT_MAX_SLOTS],
};
export const DEFAULT_MAX_MESSAGE_LENGTH = 4096;
export const ONE_TIME_MEDIA_TTL_SECONDS = 2147483647;
// Premium

View File

@ -1444,7 +1444,7 @@ addActionHandler('startBotFatherConversation', async (global, actions, payload):
});
addActionHandler('loadBotFreezeAppeal', async (global): Promise<void> => {
const botUrl = global.appConfig?.freezeAppealUrl;
const botUrl = global.appConfig.freezeAppealUrl;
if (!botUrl) return;
const botAppealUsername = botUrl ? getUsernameFromDeepLink(botUrl) : undefined;
if (!botAppealUsername) return;

View File

@ -2517,7 +2517,7 @@ addActionHandler('toggleTopicPinned', (global, actions, payload): ActionReturnTy
chatId, topicId, isPinned, tabId = getCurrentTabId(),
} = payload;
const { topicsPinnedLimit } = global.appConfig || {};
const { topicsPinnedLimit } = global.appConfig;
const chat = selectChat(global, chatId);
const topics = selectTopics(global, chatId);
if (!chat || !topics || !topicsPinnedLimit) return;
@ -3375,7 +3375,7 @@ async function openChatByUsername<T extends GlobalState>(
actions.openChat({ id: TMP_CHAT_ID, tabId });
}
const starRefStartPrefixes = global.appConfig?.starRefStartPrefixes;
const starRefStartPrefixes = global.appConfig.starRefStartPrefixes;
let referrer = ref;
if (startParam && starRefStartPrefixes?.length) {
const prefix = starRefStartPrefixes.find((p) => startParam.startsWith(p));

View File

@ -34,7 +34,6 @@ import {
RE_TELEGRAM_LINK,
SERVICE_NOTIFICATIONS_USER_ID,
STARS_CURRENCY_CODE,
STARS_SUGGESTED_POST_FUTURE_MIN,
SUPPORTED_AUDIO_CONTENT_TYPES,
SUPPORTED_PHOTO_CONTENT_TYPES,
SUPPORTED_VIDEO_CONTENT_TYPES,
@ -834,7 +833,7 @@ addActionHandler('initDraftFromSuggestedMessage', (global, actions, payload): Ac
if (message.suggestedPostInfo) {
const { scheduleDate, ...messageSuggestedPost } = message.suggestedPostInfo;
const now = getServerTime();
const futureMin = global.appConfig?.starsSuggestedPostFutureMin || STARS_SUGGESTED_POST_FUTURE_MIN;
const futureMin = global.appConfig.starsSuggestedPostFutureMin;
const validScheduleDate = scheduleDate && scheduleDate > now + futureMin ? scheduleDate : undefined;
@ -2388,22 +2387,22 @@ addActionHandler('openUrl', (global, actions, payload): ActionReturnType => {
}
const { appConfig, config } = global;
if (appConfig) {
if (config?.autologinToken && appConfig.autologinDomains.includes(parsedUrl.hostname)) {
parsedUrl.searchParams.set(AUTOLOGIN_TOKEN_KEY, config.autologinToken);
window.open(parsedUrl.href, '_blank', 'noopener');
return;
}
if (appConfig.urlAuthDomains.includes(parsedUrl.hostname)) {
actions.closeStoryViewer({ tabId });
actions.requestLinkUrlAuth({ url, tabId });
return;
}
if (config?.autologinToken && appConfig.autologinDomains.includes(parsedUrl.hostname)) {
parsedUrl.searchParams.set(AUTOLOGIN_TOKEN_KEY, config.autologinToken);
window.open(parsedUrl.href, '_blank', 'noopener');
return;
}
const shouldDisplayModal = !urlWithProtocol.match(RE_TELEGRAM_LINK) && !shouldSkipModal;
if (appConfig.urlAuthDomains.includes(parsedUrl.hostname)) {
actions.closeStoryViewer({ tabId });
actions.requestLinkUrlAuth({ url, tabId });
return;
}
const isWhitelisted = appConfig.whitelistedDomains.includes(parsedUrl.hostname);
const shouldDisplayModal = !urlWithProtocol.match(RE_TELEGRAM_LINK) && !shouldSkipModal && !isWhitelisted;
if (shouldDisplayModal) {
actions.toggleSafeLinkModal({ url: isMixedScript ? parsedUrl.toString() : urlWithProtocol, tabId });

View File

@ -1213,7 +1213,7 @@ addActionHandler('processStarGiftWithdrawal', async (global, actions, payload):
return;
}
actions.openUrl({ url: result.url, shouldSkipModal: true, tabId });
actions.openUrl({ url: result.url, tabId });
actions.closeGiftWithdrawModal({ tabId });
});

View File

@ -4,13 +4,13 @@ import type { ActionReturnType } from '../../types';
import {
DEFAULT_RESALE_GIFTS_FILTER_OPTIONS,
RESALE_GIFTS_LIMIT,
STARS_CURRENCY_CODE,
TON_CURRENCY_CODE,
} from '../../../config';
import { getCurrentTabId } from '../../../util/establishMultitabRole';
import { buildCollectionByKey } from '../../../util/iteratees';
import { callApi } from '../../../api/gramjs';
import { RESALE_GIFTS_LIMIT } from '../../../limits';
import { areInputSavedGiftsEqual, getRequestInputSavedStarGift } from '../../helpers/payments';
import { addActionHandler, getGlobal, setGlobal } from '../../index';
import {
@ -485,7 +485,7 @@ addActionHandler('toggleSavedGiftPinned', async (global, actions, payload): Prom
const savedGifts = selectPeerSavedGifts(global, peerId, tabId);
if (!savedGifts) return;
const pinLimit = global.appConfig?.savedGiftPinLimit;
const pinLimit = global.appConfig.savedGiftPinLimit;
const currentPinnedGifts = savedGifts.gifts.filter((g) => g.isPinned);
const newPinnedGifts = gift.isPinned
? currentPinnedGifts.filter((g) => (g.gift as ApiStarGiftUnique).slug !== (gift.gift as ApiStarGiftUnique).slug)

View File

@ -270,7 +270,6 @@ addActionHandler('processMonetizationRevenueWithdrawalUrl', async (global, actio
if ('url' in result) {
actions.openUrl({
url: result.url,
shouldSkipModal: true,
tabId,
ignoreDeepLinks: true,
});

View File

@ -877,7 +877,7 @@ addActionHandler('processPremiumFloodWait', (global, actions, payload): ActionRe
bandwidthPremiumDownloadSpeedup,
bandwidthPremiumUploadSpeedup,
bandwidthPremiumNotifyPeriod,
} = global.appConfig || {};
} = global.appConfig;
const { lastPremiumBandwithNotificationDate: lastNotifiedAt } = global.settings;
if (!bandwidthPremiumDownloadSpeedup || !bandwidthPremiumUploadSpeedup || !bandwidthPremiumNotifyPeriod) {

View File

@ -13,7 +13,6 @@ import {
ALL_FOLDER_ID, ANIMATION_LEVEL_DEFAULT,
ARCHIVED_FOLDER_ID,
DEBUG,
DEFAULT_LIMITS,
GLOBAL_STATE_CACHE_ARCHIVED_CHAT_LIST_LIMIT,
GLOBAL_STATE_CACHE_CHAT_LIST_LIMIT,
GLOBAL_STATE_CACHE_CUSTOM_EMOJI_LIMIT,
@ -213,10 +212,6 @@ function unsafeMigrateCache(cached: GlobalState, initialState: GlobalState) {
...cached.chatFolders,
};
if (cached.appConfig && !cached.appConfig.limits) {
cached.appConfig.limits = DEFAULT_LIMITS;
}
if (!cached.chats.similarChannelsById) {
cached.chats.similarChannelsById = initialState.chats.similarChannelsById;
}
@ -230,7 +225,7 @@ function unsafeMigrateCache(cached: GlobalState, initialState: GlobalState) {
}
// Clear old color storage to optimize cache size
if (untypedCached?.appConfig?.peerColors) {
if (untypedCached?.appConfig.peerColors) {
untypedCached.appConfig.peerColors = undefined;
untypedCached.appConfig.darkPeerColors = undefined;
}
@ -309,9 +304,6 @@ function unsafeMigrateCache(cached: GlobalState, initialState: GlobalState) {
cached.cacheVersion = 2;
}
if (cached.appConfig?.limits && !cached.appConfig.limits.moreAccounts) {
cached.appConfig.limits.moreAccounts = DEFAULT_LIMITS.moreAccounts;
}
if (!cached.chats.notifyExceptionById) {
cached.chats.notifyExceptionById = initialState.chats.notifyExceptionById;
}
@ -355,6 +347,10 @@ function unsafeMigrateCache(cached: GlobalState, initialState: GlobalState) {
cachedSharedSettings.animationLevel = ANIMATION_LEVEL_DEFAULT;
cachedSharedSettings.performance = INITIAL_PERFORMANCE_STATE_MED;
}
if (!cached.appConfig) {
cached.appConfig = initialState.appConfig;
}
}
function updateCache(force?: boolean) {

View File

@ -5,11 +5,11 @@ import type {
} from '../../api/types';
import type { GlobalState } from '../types';
import { DEFAULT_LIMITS } from '../../config';
import { isUserId } from '../../util/entities/ids';
import { partition } from '../../util/iteratees';
import { clamp } from '../../util/math';
import { getAccountsInfo } from '../../util/multiaccount';
import { DEFAULT_LIMITS } from '../../limits';
import { getGlobal } from '..';
export function buildApiInputPrivacyRules(global: GlobalState, {
@ -51,7 +51,7 @@ export function buildApiInputPrivacyRules(global: GlobalState, {
export function getCurrentMaxAccountCount() {
const global = getGlobal();
const limit = global.appConfig?.limits?.moreAccounts || DEFAULT_LIMITS.moreAccounts;
const limit = global.appConfig.limits?.moreAccounts || DEFAULT_LIMITS.moreAccounts;
const accounts = getAccountsInfo();
const premiumCount = Object.values(accounts).filter((account) => account.isPremium).length;
// Each premium account increases the base limit by 1, up to the maximum limit.

View File

@ -15,6 +15,7 @@ import {
MACOS_DEFAULT_MESSAGE_TEXT_SIZE_PX,
} from '../config';
import { IS_IOS, IS_MAC_OS } from '../util/browser/windowEnvironment';
import { DEFAULT_APP_CONFIG } from '../limits';
export const INITIAL_PERFORMANCE_STATE_MAX: PerformanceType = {
animatedEmoji: true,
@ -101,6 +102,7 @@ export const INITIAL_GLOBAL_STATE: GlobalState = {
isAppUpdateAvailable: false,
isElectronUpdateAvailable: false,
shouldShowContextMenuHint: true,
appConfig: DEFAULT_APP_CONFIG,
audioPlayer: {
lastPlaybackRate: DEFAULT_PLAYBACK_RATE,

View File

@ -107,7 +107,7 @@ export function addStoriesForPeer<T extends GlobalState>(
if (selectIsChatWithSelf(global, peerId)
|| selectUser(global, peerId)?.isContact
|| peerId === global.appConfig?.storyChangelogUserId) {
|| peerId === global.appConfig.storyChangelogUserId) {
global = updatePeerLastUpdatedAt(global, peerId);
global = updateOrderedStoriesPeerIds(global, [peerId]);
}

View File

@ -1,17 +1,14 @@
import type { ApiLimitType } from '../../api/types';
import type { GlobalState } from '../types';
import { DEFAULT_LIMITS } from '../../config';
import { DEFAULT_LIMITS } from '../../limits';
import { selectIsCurrentUserPremium } from './users';
export function selectCurrentLimit<T extends GlobalState>(global: T, limit: ApiLimitType) {
const { appConfig } = global;
if (!appConfig) {
return DEFAULT_LIMITS[limit][0];
}
const { limits } = appConfig;
const isPremium = selectIsCurrentUserPremium(global);
const { limits } = appConfig;
// When there are new limits when updating a layer, until we get a new configuration, we must use the default values
const value = limits[limit]?.[isPremium ? 1 : 0] ?? DEFAULT_LIMITS[limit][isPremium ? 1 : 0];

View File

@ -23,7 +23,7 @@ import type {
import { ApiMessageEntityTypes, MAIN_THREAD_ID } from '../../api/types';
import {
ANONYMOUS_USER_ID, API_GENERAL_ID_LIMIT, GENERAL_TOPIC_ID, SERVICE_NOTIFICATIONS_USER_ID,
ANONYMOUS_USER_ID, GENERAL_TOPIC_ID, SERVICE_NOTIFICATIONS_USER_ID,
SVG_EXTENSIONS, WEB_APP_PLATFORM,
} from '../../config';
import { IS_TRANSLATION_SUPPORTED } from '../../util/browser/windowEnvironment';
@ -34,6 +34,7 @@ import { getMessageKey, isLocalMessageId } from '../../util/keys/messageKey';
import { MEMO_EMPTY_ARRAY } from '../../util/memo';
import { getServerTime } from '../../util/serverTime';
import { getDocumentExtension } from '../../components/common/helpers/documentInfo';
import { API_GENERAL_ID_LIMIT } from '../../limits';
import {
canSendReaction,
getAllowedAttachmentOptions,
@ -77,13 +78,14 @@ import {
selectIsChatWithSelf,
selectRequestedChatTranslationLanguage,
} from './chats';
import { selectCurrentLimit } from './limits';
import { selectPeer, selectPeerPaidMessagesStars } from './peers';
import { selectPeerStory } from './stories';
import { selectIsStickerFavorite } from './symbols';
import { selectTabState } from './tabs';
import { selectTopic } from './topics';
import {
selectBot, selectIsCurrentUserPremium, selectUser, selectUserStatus,
selectBot, selectUser, selectUserStatus,
} from './users';
export function selectCurrentMessageList<T extends GlobalState>(
@ -1349,9 +1351,7 @@ export function selectDefaultReaction<T extends GlobalState>(global: T, chatId:
}
export function selectMaxUserReactions<T extends GlobalState>(global: T): number {
const isPremium = selectIsCurrentUserPremium(global);
const { maxUserReactionsPremium = 3, maxUserReactionsDefault = 1 } = global.appConfig || {};
return isPremium ? maxUserReactionsPremium : maxUserReactionsDefault;
return selectCurrentLimit(global, 'maxReactions');
}
// Slow, not to be used in `withGlobal`
@ -1580,7 +1580,7 @@ export function selectActiveRestrictionReasons<T extends GlobalState>(
): ApiRestrictionReason[] {
if (!restrictionReasons) return [];
const { ignoreRestrictionReasons } = global.appConfig || {};
const { ignoreRestrictionReasons } = global.appConfig;
return restrictionReasons.filter((reason) => {
const isForCurrentPlatform = reason.platform === 'all' || reason.platform === WEB_APP_PLATFORM;

View File

@ -167,14 +167,14 @@ export function selectAnimatedEmojiEffect<T extends GlobalState>(global: T, emoj
}
export function selectAnimatedEmojiSound<T extends GlobalState>(global: T, emoji: string) {
return global?.appConfig?.emojiSounds[cleanEmoji(emoji)];
return global?.appConfig.emojiSounds[cleanEmoji(emoji)];
}
export function selectIsAlwaysHighPriorityEmoji<T extends GlobalState>(
global: T, stickerSet: ApiStickerSetInfo | ApiStickerSet,
) {
if (!('id' in stickerSet)) return false;
return stickerSet.id === global.appConfig?.defaultEmojiStatusesStickerSetId
return stickerSet.id === global.appConfig.defaultEmojiStatusesStickerSetId
|| stickerSet.id === RESTRICTED_EMOJI_SET_ID;
}

View File

@ -36,15 +36,15 @@ export function selectIsCurrentUserPremium<T extends GlobalState>(global: T) {
}
export function selectIsCurrentUserFrozen<T extends GlobalState>(global: T) {
return Boolean(global.appConfig?.freezeUntilDate);
return Boolean(global.appConfig.freezeUntilDate);
}
export function selectIsPremiumPurchaseBlocked<T extends GlobalState>(global: T) {
return global.appConfig?.isPremiumPurchaseBlocked ?? true;
return global.appConfig.isPremiumPurchaseBlocked ?? true;
}
export function selectIsGiveawayGiftsPurchaseAvailable<T extends GlobalState>(global: T) {
return global.appConfig?.isGiveawayGiftsPurchaseAvailable ?? true;
return global.appConfig.isGiveawayGiftsPurchaseAvailable ?? true;
}
/**

View File

@ -76,7 +76,7 @@ export type GlobalState = {
cacheVersion: number;
isInited: boolean;
config?: ApiConfig;
appConfig?: ApiAppConfig;
appConfig: ApiAppConfig;
peerColors?: ApiPeerColors;
timezones?: {
byId: Record<string, ApiTimezone>;

161
src/limits.ts Normal file
View File

@ -0,0 +1,161 @@
import type { ApiAppConfig, ApiLimitType } from './api/types';
import { MULTIACCOUNT_MAX_SLOTS } from './config';
export const MAX_UNIQUE_REACTIONS = 11;
export const GROUP_CALL_PARTICIPANTS_LIMIT = 100;
export const STORY_LIST_LIMIT = 100;
export const API_GENERAL_ID_LIMIT = 100;
export const RESALE_GIFTS_LIMIT = 50;
export const PINNED_MESSAGES_LIMIT = 50;
export const BLOCKED_LIST_LIMIT = 100;
export const GLOBAL_SEARCH_CONTACTS_LIMIT = 20;
// As in Telegram for Android
// https://github.com/DrKLO/Telegram/blob/51e9947527/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java#L7799
export const TOP_REACTIONS_LIMIT = 100;
export const RECENT_REACTIONS_LIMIT = 50;
export const REACTION_LIST_LIMIT = 100;
export const DEFAULT_LIMITS: Record<ApiLimitType, readonly [number, number]> = {
uploadMaxFileparts: [4000, 8000],
stickersFaved: [5, 10],
savedGifs: [200, 400],
dialogFiltersChats: [100, 200],
dialogFilters: [10, 20],
dialogFolderPinned: [5, 10],
captionLength: [1024, 4096],
channels: [500, 1000],
channelsPublic: [10, 20],
aboutLength: [70, 140],
chatlistInvites: [3, 100],
chatlistJoined: [2, 20],
recommendedChannels: [10, 100],
savedDialogsPinned: [5, 100],
maxReactions: [1, 3],
moreAccounts: [3, MULTIACCOUNT_MAX_SLOTS],
};
export const DEFAULT_MAX_MESSAGE_LENGTH = 4096;
export const DEFAULT_APP_CONFIG: ApiAppConfig = {
hash: 0,
limits: {
uploadMaxFileparts: DEFAULT_LIMITS.uploadMaxFileparts,
stickersFaved: DEFAULT_LIMITS.stickersFaved,
savedGifs: DEFAULT_LIMITS.savedGifs,
dialogFiltersChats: DEFAULT_LIMITS.dialogFiltersChats,
dialogFilters: DEFAULT_LIMITS.dialogFilters,
dialogFolderPinned: DEFAULT_LIMITS.dialogFolderPinned,
captionLength: DEFAULT_LIMITS.captionLength,
channels: DEFAULT_LIMITS.channels,
channelsPublic: DEFAULT_LIMITS.channelsPublic,
aboutLength: DEFAULT_LIMITS.aboutLength,
chatlistInvites: DEFAULT_LIMITS.chatlistInvites,
chatlistJoined: DEFAULT_LIMITS.chatlistJoined,
recommendedChannels: DEFAULT_LIMITS.recommendedChannels,
savedDialogsPinned: DEFAULT_LIMITS.savedDialogsPinned,
moreAccounts: DEFAULT_LIMITS.moreAccounts,
maxReactions: DEFAULT_LIMITS.maxReactions,
},
canDisplayAutoarchiveSetting: true,
autologinDomains: [
'instantview.telegram.org',
'translations.telegram.org',
'contest.dev',
'contest.com',
'bugs.telegram.org',
'suggestions.telegram.org',
'themes.telegram.org',
'promote.telegram.org',
'ads.telegram.org',
],
channelLevelMax: 100,
boostsPerSentGift: 3,
channelRestrictAdsLevelMin: 50,
seenByExpiresAt: 604800,
seenByMaxChatMembers: 100,
defaultEmojiStatusesStickerSetId: '773947703670341676',
emojiSounds: {},
giveawayAddPeersMax: 10,
giveawayBoostsPerPremium: 4,
giveawayCountriesMax: 10,
isGiveawayGiftsPurchaseAvailable: false,
groupTranscribeLevelMin: 6,
hiddenMembersMinCount: 100,
ignoreRestrictionReasons: [],
canLimitNewMessagesWithoutPremium: false,
readDateExpiresAt: 604800,
premiumBotUsername: 'PremiumBot',
premiumInvoiceSlug: 'abc',
premiumPromoOrder: [
'stories',
'more_upload',
'double_limits',
// 'business',
'last_seen',
'voice_to_text',
'faster_download',
'translations',
'animated_emoji',
'emoji_status',
'saved_tags',
// 'peer_colors',
// 'wallpapers',
'profile_badge',
'message_privacy',
'advanced_chat_management',
'no_ads',
// 'app_icons',
'infinite_reactions',
'animated_userpics',
'premium_stickers',
'effects',
],
isPremiumPurchaseBlocked: false,
maxUniqueReactions: 11,
starGiftMaxConvertPeriod: 7776000,
starGiftMaxMessageLength: 255,
starRefStartPrefixes: [
'_tgr_',
],
isStarsGiftEnabled: true,
paidReactionMaxAmount: 2500,
starsUsdWithdrawRateX1000: 1300,
storyChangelogUserId: '777000',
maxPinnedStoriesCount: 3,
starsSuggestedPostAmountMax: 100000,
starsSuggestedPostAmountMin: 5,
starsSuggestedPostAgeMin: 86400,
starsSuggestedPostFutureMin: 300,
starsSuggestedPostFutureMax: 2678400,
starsSuggestedPostCommissionPermille: 850,
tonSuggestedPostCommissionPermille: 850,
todoItemLengthMax: 64,
todoItemsMax: 30,
todoTitleLengthMax: 32,
tonSuggestedPostAmountMax: 10000000000000,
tonSuggestedPostAmountMin: 10000000,
tonTopupUrl: 'https://fragment.com/ads/topup',
storyViewersExpirePeriod: 86400,
topicsPinnedLimit: 5,
bandwidthPremiumDownloadSpeedup: 10,
bandwidthPremiumNotifyPeriod: 3600,
bandwidthPremiumUploadSpeedup: 10,
urlAuthDomains: [
'web.telegram.org',
'web.t.me',
'k.t.me',
'z.t.me',
'a.t.me',
],
whitelistedDomains: [
'telegram.dog',
'telegram.me',
'telegram.org',
't.me',
'telesco.pe',
'fragment.com',
'translations.telegram.org',
],
};