Support layer 201 (#5794)

This commit is contained in:
Alexander Zinchuk 2025-04-23 18:59:21 +02:00
parent 10cfa5f22c
commit 92d9f0736c
73 changed files with 1406 additions and 331 deletions

View File

@ -92,6 +92,9 @@ export interface GramJsAppConfig extends LimitsConfig {
stars_paid_message_commission_permille?: number; stars_paid_message_commission_permille?: number;
stars_paid_message_amount_max?: number; stars_paid_message_amount_max?: number;
stargifts_pinned_to_top_limit?: number; stargifts_pinned_to_top_limit?: number;
freeze_since_date?: number;
freeze_until_date?: number;
freeze_appeal_url?: string;
} }
function buildEmojiSounds(appConfig: GramJsAppConfig) { function buildEmojiSounds(appConfig: GramJsAppConfig) {
@ -185,5 +188,8 @@ export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiApp
starRefStartPrefixes: appConfig.starref_start_param_prefixes, starRefStartPrefixes: appConfig.starref_start_param_prefixes,
tonExplorerUrl: appConfig.ton_blockchain_explorer_url, tonExplorerUrl: appConfig.ton_blockchain_explorer_url,
savedGiftPinLimit: appConfig.stargifts_pinned_to_top_limit, savedGiftPinLimit: appConfig.stargifts_pinned_to_top_limit,
freezeSinceDate: appConfig.freeze_since_date,
freezeUntilDate: appConfig.freeze_until_date,
freezeAppealUrl: appConfig.freeze_appeal_url,
}; };
} }

View File

@ -413,6 +413,27 @@ export function buildApiMessageAction(action: GramJs.TypeMessageAction): ApiMess
savedId: savedId && buildApiPeerId(savedId, 'user'), savedId: savedId && buildApiPeerId(savedId, 'user'),
}; };
} }
if (action instanceof GramJs.MessageActionPaidMessagesPrice) {
const {
stars,
} = action;
return {
mediaType: 'action',
type: 'paidMessagesPrice',
stars: stars.toJSNumber(),
};
}
if (action instanceof GramJs.MessageActionPaidMessagesRefunded) {
const {
stars, count,
} = action;
return {
mediaType: 'action',
type: 'paidMessagesRefunded',
stars: stars.toJSNumber(),
count,
};
}
return UNSUPPORTED_ACTION; return UNSUPPORTED_ACTION;
} }

View File

@ -307,6 +307,12 @@ export async function invokeRequest<T extends GramJs.AnyRequest>(
console.error(err); console.error(err);
} }
const message = err instanceof RPCError ? err.errorMessage : err.message;
if (message.includes('FROZEN_METHOD_INVALID')) {
dispatchNotSupportedInFrozenAccountUpdate(err, request);
}
if (shouldThrow) { if (shouldThrow) {
throw err; throw err;
} }
@ -441,6 +447,27 @@ export function dispatchErrorUpdate<T extends GramJs.AnyRequest>(err: Error, req
}); });
} }
function dispatchNotSupportedInFrozenAccountUpdate<T extends GramJs.AnyRequest>(err: Error, request: T) {
if (!(err instanceof RPCError)) return;
const message = err.errorMessage;
if (
request instanceof GramJs.messages.GetPinnedDialogs
|| request instanceof GramJs.phone.GetGroupParticipants
|| request instanceof GramJs.channels.GetParticipant
|| request instanceof GramJs.channels.GetParticipants
|| request instanceof GramJs.channels.GetForumTopics) {
return;
}
sendApiUpdate({
'@type': 'notSupportedInFrozenAccount',
error: {
message,
},
});
}
async function handleTerminatedSession() { async function handleTerminatedSession() {
try { try {
await invokeRequest(new GramJs.users.GetFullUser({ await invokeRequest(new GramJs.users.GetFullUser({

View File

@ -1775,20 +1775,17 @@ export async function fetchSponsoredMessages({ peer }: { peer: ApiPeer }) {
}; };
} }
export async function viewSponsoredMessage({ peer, random }: { peer: ApiPeer; random: string }) { export async function viewSponsoredMessage({ random }: { random: string }) {
await invokeRequest(new GramJs.messages.ViewSponsoredMessage({ await invokeRequest(new GramJs.messages.ViewSponsoredMessage({
peer: buildInputPeer(peer.id, peer.accessHash),
randomId: deserializeBytes(random), randomId: deserializeBytes(random),
})); }));
} }
export function clickSponsoredMessage({ export function clickSponsoredMessage({
peer,
random, random,
isMedia, isMedia,
isFullscreen, isFullscreen,
}: { }: {
peer: ApiPeer;
random: string; random: string;
isMedia?: boolean; isMedia?: boolean;
isFullscreen?: boolean; isFullscreen?: boolean;
@ -1796,23 +1793,19 @@ export function clickSponsoredMessage({
return invokeRequest(new GramJs.messages.ClickSponsoredMessage({ return invokeRequest(new GramJs.messages.ClickSponsoredMessage({
media: isMedia || undefined, media: isMedia || undefined,
fullscreen: isFullscreen || undefined, fullscreen: isFullscreen || undefined,
peer: buildInputPeer(peer.id, peer.accessHash),
randomId: deserializeBytes(random), randomId: deserializeBytes(random),
})); }));
} }
export async function reportSponsoredMessage({ export async function reportSponsoredMessage({
peer,
randomId, randomId,
option, option,
}: { }: {
peer: ApiPeer;
randomId: string; randomId: string;
option: string; option: string;
}) { }) {
try { try {
const result = await invokeRequest(new GramJs.messages.ReportSponsoredMessage({ const result = await invokeRequest(new GramJs.messages.ReportSponsoredMessage({
peer: buildInputPeer(peer.id, peer.accessHash),
randomId: deserializeBytes(randomId), randomId: deserializeBytes(randomId),
option: deserializeBytes(option), option: deserializeBytes(option),
}), { }), {

View File

@ -268,6 +268,17 @@ export interface ApiMessageActionExpiredContent extends ActionMediaType {
isRoundVideo?: true; isRoundVideo?: true;
} }
export interface ApiMessageActionPaidMessagesRefunded extends ActionMediaType {
type: 'paidMessagesRefunded';
count:number;
stars:number;
}
export interface ApiMessageActionPaidMessagesPrice extends ActionMediaType {
type: 'paidMessagesPrice';
stars:number;
}
export interface ApiMessageActionUnsupported extends ActionMediaType { export interface ApiMessageActionUnsupported extends ActionMediaType {
type: 'unsupported'; type: 'unsupported';
} }
@ -284,4 +295,5 @@ export type ApiMessageAction = ApiMessageActionUnsupported | ApiMessageActionCha
| ApiMessageActionTopicCreate | ApiMessageActionTopicEdit | ApiMessageActionSuggestProfilePhoto | ApiMessageActionTopicCreate | ApiMessageActionTopicEdit | ApiMessageActionSuggestProfilePhoto
| ApiMessageActionChannelJoined | ApiMessageActionGiftCode | ApiMessageActionGiveawayLaunch | ApiMessageActionChannelJoined | ApiMessageActionGiftCode | ApiMessageActionGiveawayLaunch
| ApiMessageActionGiveawayResults | ApiMessageActionPaymentRefunded | ApiMessageActionGiftStars | ApiMessageActionGiveawayResults | ApiMessageActionPaymentRefunded | ApiMessageActionGiftStars
| ApiMessageActionPrizeStars | ApiMessageActionStarGift | ApiMessageActionStarGiftUnique; | ApiMessageActionPrizeStars | ApiMessageActionStarGift | ApiMessageActionStarGiftUnique
| ApiMessageActionPaidMessagesRefunded | ApiMessageActionPaidMessagesPrice;

View File

@ -243,6 +243,9 @@ export interface ApiAppConfig {
starRefStartPrefixes?: string[]; starRefStartPrefixes?: string[];
tonExplorerUrl?: string; tonExplorerUrl?: string;
savedGiftPinLimit?: number; savedGiftPinLimit?: number;
freezeSinceDate?: number;
freezeUntilDate?: number;
freezeAppealUrl?: string;
} }
export interface ApiConfig { export interface ApiConfig {

View File

@ -463,6 +463,11 @@ export type ApiUpdateError = {
error: ApiError; error: ApiError;
}; };
export type ApiUpdateNotSupportedInFrozenAccountError = {
'@type': 'notSupportedInFrozenAccount';
error: ApiError;
};
export type ApiUpdateConfig = { export type ApiUpdateConfig = {
'@type': 'updateConfig'; '@type': 'updateConfig';
}; };
@ -855,7 +860,7 @@ export type ApiUpdate = (
ApiUpdateDeleteSavedHistory | ApiUpdatePremiumFloodWait | ApiUpdateStarsBalance | ApiUpdateDeleteSavedHistory | ApiUpdatePremiumFloodWait | ApiUpdateStarsBalance |
ApiUpdateQuickReplyMessage | ApiUpdateQuickReplies | ApiDeleteQuickReply | ApiUpdateDeleteQuickReplyMessages | ApiUpdateQuickReplyMessage | ApiUpdateQuickReplies | ApiDeleteQuickReply | ApiUpdateDeleteQuickReplyMessages |
ApiUpdateDeleteProfilePhoto | ApiUpdateNewProfilePhoto | ApiUpdateEntities | ApiUpdatePaidReactionPrivacy | ApiUpdateDeleteProfilePhoto | ApiUpdateNewProfilePhoto | ApiUpdateEntities | ApiUpdatePaidReactionPrivacy |
ApiUpdateLangPackTooLong | ApiUpdateLangPack ApiUpdateLangPackTooLong | ApiUpdateLangPack | ApiUpdateNotSupportedInFrozenAccountError
); );
export type OnApiUpdate = (update: ApiUpdate) => void; export type OnApiUpdate = (update: ApiUpdate) => void;

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path fill="#000" d="M19.58 16C23.868 14.353 27 10.153 27 5.294A3.306 3.306 0 0 0 23.703 2H7.297A3.305 3.305 0 0 0 4 5.294C4 10.153 7.05 14.353 11.42 16 7.132 17.647 4 21.847 4 26.706A3.306 3.306 0 0 0 7.297 30h16.406A3.306 3.306 0 0 0 27 26.706c0-4.859-3.133-9.059-7.42-10.706M5.65 5.294c0-.906.742-1.647 1.648-1.647h16.406c.906 0 1.648.741 1.648 1.647 0 5.435-4.451 9.8-9.81 9.8-5.358 0-9.892-4.365-9.892-9.8m18.054 23.059H7.297a1.653 1.653 0 0 1-1.648-1.647c0-5.435 4.451-9.8 9.81-9.8 5.358 0 9.892 4.365 9.892 9.8 0 .906-.742 1.647-1.648 1.647"/><path fill="#000" d="m9.688 24.235.824 1.4 4.947-3.13 5.029 3.13.824-1.4-5.853-3.623zM19.498 9l.99.741.989-1.317-.99-.742c-1.154-.906-2.802-.906-4.039 0-.577.494-1.401.494-2.06 0a3.47 3.47 0 0 0-4.123 0l-.824.742.99 1.317.906-.741a1.62 1.62 0 0 1 2.06 0c1.155.906 2.886.906 4.04 0 .66-.412 1.484-.412 2.061 0"/></svg>

After

Width:  |  Height:  |  Size: 942 B

View File

@ -1902,6 +1902,25 @@
"PaidMessageTransaction_other" = "Fee for {count} Messages"; "PaidMessageTransaction_other" = "Fee for {count} Messages";
"PaidMessageTransactionDescription" = "You receive **{percent}** of the price that you charge for each incoming message."; "PaidMessageTransactionDescription" = "You receive **{percent}** of the price that you charge for each incoming message.";
"PaidMessageTransactionTotal" = "Total"; "PaidMessageTransactionTotal" = "Total";
"TitleFrozenAccount" = "Your account is frozen!";
"SubtitleFrozenAccount" = "Tap to view details and submit an appeal.";
"ComposerTitleFrozenAccount" = "Your account is frozen";
"ComposerSubtitleFrozenAccount" = "Tap to view details";
"DescriptionRestrictedMedia" = "Posting media content is not allowed in this group."; "DescriptionRestrictedMedia" = "Posting media content is not allowed in this group.";
"DescriptionScheduledPaidMediaNotAllowed" = "Posting scheduled paid media content is not allowed"; "DescriptionScheduledPaidMediaNotAllowed" = "Posting scheduled paid media content is not allowed";
"DescriptionScheduledPaidMessagesNotAllowed" = "Scheduled paid messages is not allowed"; "DescriptionScheduledPaidMessagesNotAllowed" = "Scheduled paid messages is not allowed";
"FrozenAccountModalTitle" = "Your Account is Frozen";
"FrozenAccountViolationTitle" = "Violation of Terms";
"FrozenAccountViolationSubtitle" = "Your account was frozen for breaking Telegram's Terms and Conditions";
"FrozenAccountReadOnlyTitle" = "Read-Only Mode";
"FrozenAccountReadOnlySubtitle" = "You can access your account but can't send messages or take actions.";
"FrozenAccountAppealTitle" = "Appeal Before Deactivation";
"FrozenAccountAppealSubtitle" = "Appeal via {botLink} before {date} or your account will be deleted.";
"ButtonAppeal" = "Submit an Appeal";
"ButtonUnderstood" = "Understood";
"ActionPaidMessageGroupPrice" = "Messages now cost **{stars}** in this group";
"ActionPaidMessageGroupPriceFree" = "Messages are now free in this group";
"ApiMessageActionPaidMessagesRefundedOutgoing" = "You refunded **{stars}** to {user}";
"ApiMessageActionPaidMessagesRefundedIncoming" = "{user} refunded **{stars}** to you";
"NotificationTitleNotSupportedInFrozenAccount" = "Your account is frozen";
"NotificationMessageNotSupportedInFrozenAccount" = "This action is not available";

Binary file not shown.

View File

@ -97,3 +97,4 @@ export { default as ReceiptModal } from '../components/payment/ReceiptModal';
export { default as InviteViaLinkModal } from '../components/modals/inviteViaLink/InviteViaLinkModal'; export { default as InviteViaLinkModal } from '../components/modals/inviteViaLink/InviteViaLinkModal';
export { default as OneTimeMediaModal } from '../components/modals/oneTimeMedia/OneTimeMediaModal'; export { default as OneTimeMediaModal } from '../components/modals/oneTimeMedia/OneTimeMediaModal';
export { default as WebAppsCloseConfirmationModal } from '../components/main/WebAppsCloseConfirmationModal'; export { default as WebAppsCloseConfirmationModal } from '../components/main/WebAppsCloseConfirmationModal';
export { default as FrozenAccountModal } from '../components/modals/frozenAccount/FrozenAccountModal';

View File

@ -82,6 +82,7 @@ import {
selectEditingMessage, selectEditingMessage,
selectEditingScheduledDraft, selectEditingScheduledDraft,
selectIsChatWithSelf, selectIsChatWithSelf,
selectIsCurrentUserFrozen,
selectIsCurrentUserPremium, selectIsCurrentUserPremium,
selectIsInSelectMode, selectIsInSelectMode,
selectIsPremiumPurchaseBlocked, selectIsPremiumPurchaseBlocked,
@ -291,6 +292,8 @@ type StateProps =
isPaymentMessageConfirmDialogOpen: boolean; isPaymentMessageConfirmDialogOpen: boolean;
starsBalance: number; starsBalance: number;
isStarsBalanceModalOpen: boolean; isStarsBalanceModalOpen: boolean;
isAccountFrozen?: boolean;
isAppConfigLoaded?: boolean;
}; };
enum MainButtonState { enum MainButtonState {
@ -411,6 +414,8 @@ const Composer: FC<OwnProps & StateProps> = ({
isPaymentMessageConfirmDialogOpen, isPaymentMessageConfirmDialogOpen,
starsBalance, starsBalance,
isStarsBalanceModalOpen, isStarsBalanceModalOpen,
isAccountFrozen,
isAppConfigLoaded,
}) => { }) => {
const { const {
sendMessage, sendMessage,
@ -499,10 +504,10 @@ const Composer: FC<OwnProps & StateProps> = ({
}, [chatId]); }, [chatId]);
useEffect(() => { useEffect(() => {
if (chatId && isReady && !isInStoryViewer) { if (isAppConfigLoaded && chatId && isReady && !isInStoryViewer) {
loadScheduledHistory({ chatId }); loadScheduledHistory({ chatId });
} }
}, [isReady, chatId, threadId, isInStoryViewer]); }, [isReady, chatId, threadId, isInStoryViewer, isAppConfigLoaded]);
useEffect(() => { useEffect(() => {
const isChannelWithProfiles = isChannel && chat?.areProfilesShown; const isChannelWithProfiles = isChannel && chat?.areProfilesShown;
@ -1960,7 +1965,7 @@ const Composer: FC<OwnProps & StateProps> = ({
)} )}
</> </>
)} )}
{((!isComposerBlocked || canSendGifs || canSendStickers) && !isNeedPremium) && ( {((!isComposerBlocked || canSendGifs || canSendStickers) && !isNeedPremium && !isAccountFrozen) && (
<SymbolMenuButton <SymbolMenuButton
chatId={chatId} chatId={chatId}
threadId={threadId} threadId={threadId}
@ -2373,6 +2378,8 @@ export default memo(withGlobal<OwnProps>(
const isForwarding = chatId === tabState.forwardMessages.toChatId; const isForwarding = chatId === tabState.forwardMessages.toChatId;
const starsBalance = global.stars?.balance.amount || 0; const starsBalance = global.stars?.balance.amount || 0;
const isStarsBalanceModalOpen = Boolean(tabState.starsBalanceModal); const isStarsBalanceModalOpen = Boolean(tabState.starsBalanceModal);
const isAccountFrozen = selectIsCurrentUserFrozen(global);
const isAppConfigLoaded = global.isAppConfigLoaded;
return { return {
availableReactions: global.reactions.availableReactions, availableReactions: global.reactions.availableReactions,
@ -2457,6 +2464,8 @@ export default memo(withGlobal<OwnProps>(
isPaymentMessageConfirmDialogOpen: tabState.isPaymentMessageConfirmDialogOpen, isPaymentMessageConfirmDialogOpen: tabState.isPaymentMessageConfirmDialogOpen,
starsBalance, starsBalance,
isStarsBalanceModalOpen, isStarsBalanceModalOpen,
isAccountFrozen,
isAppConfigLoaded,
}; };
}, },
)(Composer)); )(Composer));

View File

@ -1,4 +1,5 @@
import QrPlane from '../../../assets/tgs/auth/QrPlane.tgs'; import QrPlane from '../../../assets/tgs/auth/QrPlane.tgs';
import BannedDuck from '../../../assets/tgs/BannedDuck.tgs';
import CameraFlip from '../../../assets/tgs/calls/CameraFlip.tgs'; import CameraFlip from '../../../assets/tgs/calls/CameraFlip.tgs';
import HandFilled from '../../../assets/tgs/calls/HandFilled.tgs'; import HandFilled from '../../../assets/tgs/calls/HandFilled.tgs';
import HandOutline from '../../../assets/tgs/calls/HandOutline.tgs'; import HandOutline from '../../../assets/tgs/calls/HandOutline.tgs';
@ -66,4 +67,5 @@ export const LOCAL_TGS_URLS = {
StarReaction, StarReaction,
Report, Report,
SearchingDuck, SearchingDuck,
BannedDuck,
}; };

View File

@ -9,7 +9,9 @@ import type { FoldersActions } from '../../hooks/reducers/useFoldersReducer';
import type { ReducerAction } from '../../hooks/useReducer'; import type { ReducerAction } from '../../hooks/useReducer';
import { LeftColumnContent, SettingsScreens } from '../../types'; import { LeftColumnContent, SettingsScreens } from '../../types';
import { selectCurrentChat, selectIsForumPanelOpen, selectTabState } from '../../global/selectors'; import {
selectCurrentChat, selectIsCurrentUserFrozen, selectIsForumPanelOpen, selectTabState,
} from '../../global/selectors';
import { import {
IS_APP, IS_FIREFOX, IS_MAC_OS, IS_TOUCH_ENV, LAYERS_ANIMATION_NAME, IS_APP, IS_FIREFOX, IS_MAC_OS, IS_TOUCH_ENV, LAYERS_ANIMATION_NAME,
} from '../../util/browser/windowEnvironment'; } from '../../util/browser/windowEnvironment';
@ -52,6 +54,7 @@ type StateProps = {
isClosingSearch?: boolean; isClosingSearch?: boolean;
archiveSettings: GlobalState['archiveSettings']; archiveSettings: GlobalState['archiveSettings'];
isArchivedStoryRibbonShown?: boolean; isArchivedStoryRibbonShown?: boolean;
isAccountFrozen?: boolean;
}; };
enum ContentType { enum ContentType {
@ -86,6 +89,7 @@ function LeftColumn({
isClosingSearch, isClosingSearch,
archiveSettings, archiveSettings,
isArchivedStoryRibbonShown, isArchivedStoryRibbonShown,
isAccountFrozen,
}: OwnProps & StateProps) { }: OwnProps & StateProps) {
const { const {
setGlobalSearchQuery, setGlobalSearchQuery,
@ -545,6 +549,7 @@ function LeftColumn({
isElectronUpdateAvailable={isElectronUpdateAvailable} isElectronUpdateAvailable={isElectronUpdateAvailable}
isForumPanelOpen={isForumPanelOpen} isForumPanelOpen={isForumPanelOpen}
onTopicSearch={handleTopicSearch} onTopicSearch={handleTopicSearch}
isAccountFrozen={isAccountFrozen}
/> />
); );
} }
@ -598,6 +603,7 @@ export default memo(withGlobal<OwnProps>(
const isChatOpen = Boolean(currentChat?.id); const isChatOpen = Boolean(currentChat?.id);
const isForumPanelOpen = selectIsForumPanelOpen(global); const isForumPanelOpen = selectIsForumPanelOpen(global);
const forumPanelChatId = tabState.forumPanelChatId; const forumPanelChatId = tabState.forumPanelChatId;
const isAccountFrozen = selectIsCurrentUserFrozen(global);
return { return {
searchQuery: query, searchQuery: query,
@ -616,6 +622,7 @@ export default memo(withGlobal<OwnProps>(
isClosingSearch: tabState.globalSearch.isClosing, isClosingSearch: tabState.globalSearch.isClosing,
archiveSettings, archiveSettings,
isArchivedStoryRibbonShown: isArchivedRibbonShown, isArchivedStoryRibbonShown: isArchivedRibbonShown,
isAccountFrozen,
}; };
}, },
)(LeftColumn)); )(LeftColumn));

View File

@ -2,6 +2,7 @@ import type { FC } from '../../lib/teact/teact';
import React, { import React, {
useCallback, useEffect, useMemo, useState, useCallback, useEffect, useMemo, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { getActions } from '../../global';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
@ -19,6 +20,7 @@ type OwnProps = {
onNewPrivateChat: () => void; onNewPrivateChat: () => void;
onNewChannel: () => void; onNewChannel: () => void;
onNewGroup: () => void; onNewGroup: () => void;
isAccountFrozen?: boolean;
}; };
const NewChatButton: FC<OwnProps> = ({ const NewChatButton: FC<OwnProps> = ({
@ -26,8 +28,10 @@ const NewChatButton: FC<OwnProps> = ({
onNewPrivateChat, onNewPrivateChat,
onNewChannel, onNewChannel,
onNewGroup, onNewGroup,
isAccountFrozen,
}) => { }) => {
const [isMenuOpen, setIsMenuOpen] = useState(false); const [isMenuOpen, setIsMenuOpen] = useState(false);
const { openFrozenAccountModal } = getActions();
useEffect(() => { useEffect(() => {
if (!isShown) { if (!isShown) {
@ -44,8 +48,12 @@ const NewChatButton: FC<OwnProps> = ({
); );
const toggleIsMenuOpen = useCallback(() => { const toggleIsMenuOpen = useCallback(() => {
if (isAccountFrozen) {
openFrozenAccountModal();
return;
}
setIsMenuOpen(!isMenuOpen); setIsMenuOpen(!isMenuOpen);
}, [isMenuOpen]); }, [isMenuOpen, isAccountFrozen]);
const handleClose = useCallback(() => { const handleClose = useCallback(() => {
setIsMenuOpen(false); setIsMenuOpen(false);

View File

@ -33,6 +33,7 @@ import {
selectChatMessage, selectChatMessage,
selectCurrentMessageList, selectCurrentMessageList,
selectDraft, selectDraft,
selectIsCurrentUserFrozen,
selectIsForumPanelClosed, selectIsForumPanelClosed,
selectIsForumPanelOpen, selectIsForumPanelOpen,
selectNotifyDefaults, selectNotifyDefaults,
@ -114,6 +115,7 @@ type StateProps = {
lastMessage?: ApiMessage; lastMessage?: ApiMessage;
currentUserId: string; currentUserId: string;
isSynced?: boolean; isSynced?: boolean;
isAccountFrozen?: boolean;
}; };
const Chat: FC<OwnProps & StateProps> = ({ const Chat: FC<OwnProps & StateProps> = ({
@ -151,6 +153,7 @@ const Chat: FC<OwnProps & StateProps> = ({
className, className,
isSynced, isSynced,
onDragEnter, onDragEnter,
isAccountFrozen,
}) => { }) => {
const { const {
openChat, openChat,
@ -163,6 +166,7 @@ const Chat: FC<OwnProps & StateProps> = ({
closeForumPanel, closeForumPanel,
setShouldCloseRightColumn, setShouldCloseRightColumn,
reportMessages, reportMessages,
openFrozenAccountModal,
} = getActions(); } = getActions();
const { isMobile } = useAppLayout(); const { isMobile } = useAppLayout();
@ -248,11 +252,21 @@ const Chat: FC<OwnProps & StateProps> = ({
}); });
const handleDelete = useLastCallback(() => { const handleDelete = useLastCallback(() => {
if (isAccountFrozen) {
openFrozenAccountModal();
return;
}
markRenderDeleteModal(); markRenderDeleteModal();
openDeleteModal(); openDeleteModal();
}); });
const handleMute = useLastCallback(() => { const handleMute = useLastCallback(() => {
if (isAccountFrozen) {
openFrozenAccountModal();
return;
}
markRenderMuteModal(); markRenderMuteModal();
openMuteModal(); openMuteModal();
}); });
@ -263,6 +277,11 @@ const Chat: FC<OwnProps & StateProps> = ({
}); });
const handleReport = useLastCallback(() => { const handleReport = useLastCallback(() => {
if (isAccountFrozen) {
openFrozenAccountModal();
return;
}
if (!chat) return; if (!chat) return;
reportMessages({ chatId: chat.id, messageIds: [] }); reportMessages({ chatId: chat.id, messageIds: [] });
}); });
@ -468,6 +487,7 @@ export default memo(withGlobal<OwnProps>(
const storyData = lastMessage?.content.storyData; const storyData = lastMessage?.content.storyData;
const lastMessageStory = storyData && selectPeerStory(global, storyData.peerId, storyData.id); const lastMessageStory = storyData && selectPeerStory(global, storyData.peerId, storyData.id);
const isAccountFrozen = selectIsCurrentUserFrozen(global);
return { return {
chat, chat,
@ -494,6 +514,7 @@ export default memo(withGlobal<OwnProps>(
topics: topicsInfo?.topicsById, topics: topicsInfo?.topicsById,
isSynced: global.isSynced, isSynced: global.isSynced,
lastMessageStory, lastMessageStory,
isAccountFrozen,
}; };
}, },
)(Chat)); )(Chat));

View File

@ -13,7 +13,7 @@ import type { TabWithProperties } from '../../ui/TabList';
import { SettingsScreens } from '../../../types'; import { SettingsScreens } from '../../../types';
import { ALL_FOLDER_ID } from '../../../config'; import { ALL_FOLDER_ID } from '../../../config';
import { selectCanShareFolder, selectTabState } from '../../../global/selectors'; import { selectCanShareFolder, selectIsCurrentUserFrozen, selectTabState } from '../../../global/selectors';
import { selectCurrentLimit } from '../../../global/selectors/limits'; import { selectCurrentLimit } from '../../../global/selectors/limits';
import { IS_TOUCH_ENV } from '../../../util/browser/windowEnvironment'; import { IS_TOUCH_ENV } from '../../../util/browser/windowEnvironment';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
@ -60,6 +60,7 @@ type StateProps = {
archiveSettings: GlobalState['archiveSettings']; archiveSettings: GlobalState['archiveSettings'];
isStoryRibbonShown?: boolean; isStoryRibbonShown?: boolean;
sessions?: Record<string, ApiSession>; sessions?: Record<string, ApiSession>;
isAccountFrozen?: boolean;
}; };
const SAVED_MESSAGES_HOTKEY = '0'; const SAVED_MESSAGES_HOTKEY = '0';
@ -85,6 +86,7 @@ const ChatFolders: FC<OwnProps & StateProps> = ({
archiveSettings, archiveSettings,
isStoryRibbonShown, isStoryRibbonShown,
sessions, sessions,
isAccountFrozen,
}) => { }) => {
const { const {
loadChatFolders, loadChatFolders,
@ -368,6 +370,7 @@ const ChatFolders: FC<OwnProps & StateProps> = ({
canDisplayArchive={(hasArchivedChats || hasArchivedStories) && !archiveSettings.isHidden} canDisplayArchive={(hasArchivedChats || hasArchivedStories) && !archiveSettings.isHidden}
archiveSettings={archiveSettings} archiveSettings={archiveSettings}
sessions={sessions} sessions={sessions}
isAccountFrozen={isAccountFrozen}
/> />
); );
} }
@ -432,6 +435,7 @@ export default memo(withGlobal<OwnProps>(
} = global; } = global;
const { shouldSkipHistoryAnimations, activeChatFolder } = selectTabState(global); const { shouldSkipHistoryAnimations, activeChatFolder } = selectTabState(global);
const { storyViewer: { isRibbonShown: isStoryRibbonShown } } = selectTabState(global); const { storyViewer: { isRibbonShown: isStoryRibbonShown } } = selectTabState(global);
const isAccountFrozen = selectIsCurrentUserFrozen(global);
return { return {
chatFoldersById, chatFoldersById,
@ -448,6 +452,7 @@ export default memo(withGlobal<OwnProps>(
archiveSettings, archiveSettings,
isStoryRibbonShown, isStoryRibbonShown,
sessions, sessions,
isAccountFrozen,
}; };
}, },
)(ChatFolders)); )(ChatFolders));

View File

@ -39,6 +39,7 @@ import Loading from '../../ui/Loading';
import Archive from './Archive'; import Archive from './Archive';
import Chat from './Chat'; import Chat from './Chat';
import EmptyFolder from './EmptyFolder'; import EmptyFolder from './EmptyFolder';
import FrozenAccountNotification from './FrozenAccountNotification';
import UnconfirmedSession from './UnconfirmedSession'; import UnconfirmedSession from './UnconfirmedSession';
type OwnProps = { type OwnProps = {
@ -53,6 +54,7 @@ type OwnProps = {
foldersDispatch?: FolderEditDispatch; foldersDispatch?: FolderEditDispatch;
onSettingsScreenSelect?: (screen: SettingsScreens) => void; onSettingsScreenSelect?: (screen: SettingsScreens) => void;
onLeftColumnContentChange?: (content: LeftColumnContent) => void; onLeftColumnContentChange?: (content: LeftColumnContent) => void;
isAccountFrozen?: boolean;
}; };
const INTERSECTION_THROTTLE = 200; const INTERSECTION_THROTTLE = 200;
@ -71,12 +73,14 @@ const ChatList: FC<OwnProps> = ({
foldersDispatch, foldersDispatch,
onSettingsScreenSelect, onSettingsScreenSelect,
onLeftColumnContentChange, onLeftColumnContentChange,
isAccountFrozen,
}) => { }) => {
const { const {
openChat, openChat,
openNextChat, openNextChat,
closeForumPanel, closeForumPanel,
toggleStoryRibbon, toggleStoryRibbon,
openFrozenAccountModal,
} = getActions(); } = getActions();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
@ -91,6 +95,7 @@ const ChatList: FC<OwnProps> = ({
); );
const shouldDisplayArchive = isAllFolder && canDisplayArchive && archiveSettings; const shouldDisplayArchive = isAllFolder && canDisplayArchive && archiveSettings;
const shouldShowFrozenAccountNotification = isAccountFrozen && isAllFolder;
const orderedIds = useFolderManagerForOrderedIds(resolvedFolderId); const orderedIds = useFolderManagerForOrderedIds(resolvedFolderId);
usePeerStoriesPolling(orderedIds); usePeerStoriesPolling(orderedIds);
@ -98,6 +103,7 @@ const ChatList: FC<OwnProps> = ({
const chatsHeight = (orderedIds?.length || 0) * CHAT_HEIGHT_PX; const chatsHeight = (orderedIds?.length || 0) * CHAT_HEIGHT_PX;
const archiveHeight = shouldDisplayArchive const archiveHeight = shouldDisplayArchive
? archiveSettings?.isMinimized ? ARCHIVE_MINIMIZED_HEIGHT : CHAT_HEIGHT_PX : 0; ? archiveSettings?.isMinimized ? ARCHIVE_MINIMIZED_HEIGHT : CHAT_HEIGHT_PX : 0;
const frozenNotificationHeight = shouldShowFrozenAccountNotification ? 68 : 0;
const { orderDiffById, getAnimationType } = useOrderDiff(orderedIds); const { orderDiffById, getAnimationType } = useOrderDiff(orderedIds);
@ -108,8 +114,8 @@ const ChatList: FC<OwnProps> = ({
const current = sessionsArray.find((session) => session.isCurrent); const current = sessionsArray.find((session) => session.isCurrent);
if (!current || getServerTime() - current.dateCreated < FRESH_AUTH_PERIOD) return false; if (!current || getServerTime() - current.dateCreated < FRESH_AUTH_PERIOD) return false;
return isAllFolder && sessionsArray.some((session) => session.isUnconfirmed); return !isAccountFrozen && isAllFolder && sessionsArray.some((session) => session.isUnconfirmed);
}, [isAllFolder, sessions]); }, [isAllFolder, sessions, isAccountFrozen]);
useEffect(() => { useEffect(() => {
if (!shouldShowUnconfirmedSessions) setUnconfirmedSessionHeight(0); if (!shouldShowUnconfirmedSessions) setUnconfirmedSessionHeight(0);
@ -174,6 +180,10 @@ const ChatList: FC<OwnProps> = ({
closeForumPanel(); closeForumPanel();
}); });
const handleFrozenAccountNotificationClick = useLastCallback(() => {
openFrozenAccountModal();
});
const handleArchivedDragEnter = useLastCallback(() => { const handleArchivedDragEnter = useLastCallback(() => {
if (shouldIgnoreDragRef.current) { if (shouldIgnoreDragRef.current) {
shouldIgnoreDragRef.current = false; shouldIgnoreDragRef.current = false;
@ -215,7 +225,8 @@ const ChatList: FC<OwnProps> = ({
return viewportIds!.map((id, i) => { return viewportIds!.map((id, i) => {
const isPinned = viewportOffset + i < pinnedCount; const isPinned = viewportOffset + i < pinnedCount;
const offsetTop = unconfirmedSessionHeight + archiveHeight + (viewportOffset + i) * CHAT_HEIGHT_PX; const offsetTop = unconfirmedSessionHeight + archiveHeight + frozenNotificationHeight
+ (viewportOffset + i) * CHAT_HEIGHT_PX;
return ( return (
<Chat <Chat
@ -244,7 +255,7 @@ const ChatList: FC<OwnProps> = ({
preloadBackwards={CHAT_LIST_SLICE} preloadBackwards={CHAT_LIST_SLICE}
withAbsolutePositioning withAbsolutePositioning
beforeChildren={renderedOverflowTrigger} beforeChildren={renderedOverflowTrigger}
maxHeight={chatsHeight + archiveHeight + unconfirmedSessionHeight} maxHeight={chatsHeight + archiveHeight + frozenNotificationHeight + unconfirmedSessionHeight}
onLoadMore={getMore} onLoadMore={getMore}
onDragLeave={handleDragLeave} onDragLeave={handleDragLeave}
> >
@ -255,6 +266,12 @@ const ChatList: FC<OwnProps> = ({
onHeightChange={setUnconfirmedSessionHeight} onHeightChange={setUnconfirmedSessionHeight}
/> />
)} )}
{shouldShowFrozenAccountNotification && (
<FrozenAccountNotification
key="frozen"
onClick={handleFrozenAccountNotificationClick}
/>
)}
{shouldDisplayArchive && ( {shouldDisplayArchive && (
<Archive <Archive
key="archive" key="archive"

View File

@ -0,0 +1,25 @@
.root {
background-color: var(--color-background-secondary);
margin-inline: -0.5rem;
padding-block: 0.75rem;
padding-inline: 1rem;
cursor: pointer;
&:hover {
opacity: 0.85;
}
}
.title {
color: var(--color-error);
font-weight: var(--font-weight-medium);
font-size: 1rem;
line-height: 1rem;
}
.subtitle {
color: var(--color-text-secondary);
font-size: 0.875rem;
margin-top: 0.25rem;
line-height: 1rem;
}

View File

@ -0,0 +1,25 @@
import React, { memo } from '../../../lib/teact/teact';
import useLang from '../../../hooks/useLang';
import styles from './FrozenAccountNotification.module.scss';
type OwnProps = {
onClick: () => void;
};
const FrozenAccountNotification = ({ onClick }: OwnProps) => {
const lang = useLang();
return (
<div
className={styles.root}
onClick={onClick}
>
<div className={styles.title}>{lang('TitleFrozenAccount')}</div>
<div className={styles.subtitle}>{lang('SubtitleFrozenAccount')}</div>
</div>
);
};
export default memo(FrozenAccountNotification);

View File

@ -43,6 +43,7 @@ type OwnProps = {
onContentChange: (content: LeftColumnContent) => void; onContentChange: (content: LeftColumnContent) => void;
onSettingsScreenSelect: (screen: SettingsScreens) => void; onSettingsScreenSelect: (screen: SettingsScreens) => void;
onTopicSearch: NoneToVoidFunction; onTopicSearch: NoneToVoidFunction;
isAccountFrozen?: boolean;
onReset: () => void; onReset: () => void;
}; };
@ -67,6 +68,7 @@ const LeftMain: FC<OwnProps> = ({
onSettingsScreenSelect, onSettingsScreenSelect,
onReset, onReset,
onTopicSearch, onTopicSearch,
isAccountFrozen,
}) => { }) => {
const { closeForumPanel } = getActions(); const { closeForumPanel } = getActions();
const [isNewChatButtonShown, setIsNewChatButtonShown] = useState(IS_TOUCH_ENV); const [isNewChatButtonShown, setIsNewChatButtonShown] = useState(IS_TOUCH_ENV);
@ -243,6 +245,7 @@ const LeftMain: FC<OwnProps> = ({
onNewPrivateChat={handleSelectContacts} onNewPrivateChat={handleSelectContacts}
onNewChannel={handleSelectNewChannel} onNewChannel={handleSelectNewChannel}
onNewGroup={handleSelectNewGroup} onNewGroup={handleSelectNewGroup}
isAccountFrozen={isAccountFrozen}
/> />
</div> </div>
); );

View File

@ -5,7 +5,7 @@ import { getActions, withGlobal } from '../../../global';
import type { ApiEmojiStatusCollectible, ApiEmojiStatusType, ApiSticker } from '../../../api/types'; import type { ApiEmojiStatusCollectible, ApiEmojiStatusType, ApiSticker } from '../../../api/types';
import { EMOJI_STATUS_LOOP_LIMIT } from '../../../config'; import { EMOJI_STATUS_LOOP_LIMIT } from '../../../config';
import { selectUser } from '../../../global/selectors'; import { selectIsCurrentUserFrozen, selectUser } from '../../../global/selectors';
import { getServerTime } from '../../../util/serverTime'; import { getServerTime } from '../../../util/serverTime';
import useTimeout from '../../../hooks/schedulers/useTimeout'; import useTimeout from '../../../hooks/schedulers/useTimeout';
@ -22,13 +22,14 @@ import StatusPickerMenu from './StatusPickerMenu.async';
interface StateProps { interface StateProps {
emojiStatus?: ApiEmojiStatusType; emojiStatus?: ApiEmojiStatusType;
collectibleStatuses?: ApiEmojiStatusType[]; collectibleStatuses?: ApiEmojiStatusType[];
isAccountFrozen?: boolean;
} }
const EFFECT_DURATION_MS = 1500; const EFFECT_DURATION_MS = 1500;
const EMOJI_STATUS_SIZE = 24; const EMOJI_STATUS_SIZE = 24;
const StatusButton: FC<StateProps> = ({ emojiStatus, collectibleStatuses }) => { const StatusButton: FC<StateProps> = ({ emojiStatus, collectibleStatuses, isAccountFrozen }) => {
const { setEmojiStatus, loadCurrentUser } = getActions(); const { setEmojiStatus, loadCurrentUser, openFrozenAccountModal } = getActions();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const buttonRef = useRef<HTMLButtonElement>(null); const buttonRef = useRef<HTMLButtonElement>(null);
@ -60,8 +61,12 @@ const StatusButton: FC<StateProps> = ({ emojiStatus, collectibleStatuses }) => {
useTimeout(hideEffect, isEffectShown ? EFFECT_DURATION_MS : undefined); useTimeout(hideEffect, isEffectShown ? EFFECT_DURATION_MS : undefined);
const handleEmojiStatusClick = useCallback(() => { const handleEmojiStatusClick = useCallback(() => {
if (isAccountFrozen) {
openFrozenAccountModal();
return;
}
openStatusPicker(); openStatusPicker();
}, [openStatusPicker]); }, [openStatusPicker, isAccountFrozen]);
return ( return (
<div className="StatusButton extra-spacing"> <div className="StatusButton extra-spacing">
@ -105,9 +110,11 @@ export default memo(withGlobal((global): StateProps => {
const { currentUserId } = global; const { currentUserId } = global;
const currentUser = currentUserId ? selectUser(global, currentUserId) : undefined; const currentUser = currentUserId ? selectUser(global, currentUserId) : undefined;
const collectibleStatuses = global.collectibleEmojiStatuses?.statuses; const collectibleStatuses = global.collectibleEmojiStatuses?.statuses;
const isAccountFrozen = selectIsCurrentUserFrozen(global);
return { return {
emojiStatus: currentUser?.emojiStatus, emojiStatus: currentUser?.emojiStatus,
collectibleStatuses, collectibleStatuses,
isAccountFrozen,
}; };
})(StatusButton)); })(StatusButton));

View File

@ -6,7 +6,10 @@ import type { ApiPrivacySettings } from '../../../api/types';
import type { GlobalState } from '../../../global/types'; import type { GlobalState } from '../../../global/types';
import { SettingsScreens } from '../../../types'; import { SettingsScreens } from '../../../types';
import { selectCanSetPasscode, selectIsCurrentUserPremium } from '../../../global/selectors'; import {
selectCanSetPasscode, selectIsCurrentUserFrozen,
selectIsCurrentUserPremium,
} from '../../../global/selectors';
import { selectSharedSettings } from '../../../global/selectors/sharedState'; import { selectSharedSettings } from '../../../global/selectors/sharedState';
import useHistoryBack from '../../../hooks/useHistoryBack'; import useHistoryBack from '../../../hooks/useHistoryBack';
@ -37,6 +40,7 @@ type StateProps = {
shouldNewNonContactPeersRequirePremium?: boolean; shouldNewNonContactPeersRequirePremium?: boolean;
shouldChargeForMessages: boolean; shouldChargeForMessages: boolean;
canDisplayChatInTitle?: boolean; canDisplayChatInTitle?: boolean;
isCurrentUserFrozen?: boolean;
privacy: GlobalState['settings']['privacy']; privacy: GlobalState['settings']['privacy'];
}; };
@ -58,6 +62,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
privacy, privacy,
onScreenSelect, onScreenSelect,
onReset, onReset,
isCurrentUserFrozen,
}) => { }) => {
const { const {
loadPrivacySettings, loadPrivacySettings,
@ -71,17 +76,19 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
} = getActions(); } = getActions();
useEffect(() => { useEffect(() => {
loadBlockedUsers(); if (!isCurrentUserFrozen) {
loadPrivacySettings(); loadBlockedUsers();
loadContentSettings(); loadPrivacySettings();
loadWebAuthorizations(); loadContentSettings();
}, []); loadWebAuthorizations();
}
}, [isCurrentUserFrozen]);
useEffect(() => { useEffect(() => {
if (isActive) { if (isActive && !isCurrentUserFrozen) {
loadGlobalPrivacySettings(); loadGlobalPrivacySettings();
} }
}, [isActive, loadGlobalPrivacySettings]); }, [isActive, isCurrentUserFrozen, loadGlobalPrivacySettings]);
const oldLang = useOldLang(); const oldLang = useOldLang();
const lang = useLang(); const lang = useLang();
@ -419,6 +426,7 @@ export default memo(withGlobal<OwnProps>(
const { canDisplayChatInTitle } = selectSharedSettings(global); const { canDisplayChatInTitle } = selectSharedSettings(global);
const shouldChargeForMessages = Boolean(nonContactPeersPaidStars); const shouldChargeForMessages = Boolean(nonContactPeersPaidStars);
const isCurrentUserFrozen = selectIsCurrentUserFrozen(global);
return { return {
isCurrentUserPremium: selectIsCurrentUserPremium(global), isCurrentUserPremium: selectIsCurrentUserPremium(global),
@ -435,6 +443,7 @@ export default memo(withGlobal<OwnProps>(
privacy, privacy,
canDisplayChatInTitle, canDisplayChatInTitle,
canSetPasscode: selectCanSetPasscode(global), canSetPasscode: selectCanSetPasscode(global),
isCurrentUserFrozen,
}; };
}, },
)(SettingsPrivacy)); )(SettingsPrivacy));

View File

@ -19,6 +19,7 @@ import {
selectChatFolder, selectChatFolder,
selectChatMessage, selectChatMessage,
selectCurrentMessageList, selectCurrentMessageList,
selectIsCurrentUserFrozen,
selectIsCurrentUserPremium, selectIsCurrentUserPremium,
selectIsForwardModalOpen, selectIsForwardModalOpen,
selectIsMediaViewerOpen, selectIsMediaViewerOpen,
@ -141,6 +142,8 @@ type StateProps = {
noRightColumnAnimation?: boolean; noRightColumnAnimation?: boolean;
withInterfaceAnimations?: boolean; withInterfaceAnimations?: boolean;
isSynced?: boolean; isSynced?: boolean;
isAccountFrozen?: boolean;
isAppConfigLoaded?: boolean;
}; };
const APP_OUTDATED_TIMEOUT_MS = 5 * 60 * 1000; // 5 min const APP_OUTDATED_TIMEOUT_MS = 5 * 60 * 1000; // 5 min
@ -194,6 +197,8 @@ const Main = ({
noRightColumnAnimation, noRightColumnAnimation,
isSynced, isSynced,
currentUserId, currentUserId,
isAccountFrozen,
isAppConfigLoaded,
}: OwnProps & StateProps) => { }: OwnProps & StateProps) => {
const { const {
initMain, initMain,
@ -248,6 +253,10 @@ const Main = ({
loadTopBotApps, loadTopBotApps,
loadPaidReactionPrivacy, loadPaidReactionPrivacy,
loadPasswordInfo, loadPasswordInfo,
loadBotFreezeAppeal,
loadAllChats,
loadAllStories,
loadAllHiddenStories,
} = getActions(); } = getActions();
if (DEBUG && !DEBUG_isLogged) { if (DEBUG && !DEBUG_isLogged) {
@ -309,45 +318,54 @@ const Main = ({
loadAppConfig(); loadAppConfig();
loadPeerColors(); loadPeerColors();
initMain(); initMain();
loadAvailableReactions();
loadAnimatedEmojis();
loadNotificationSettings();
loadNotificationExceptions();
loadAttachBots();
loadContactList(); loadContactList();
loadDefaultTopicIcons();
checkAppVersion(); checkAppVersion();
loadTopReactions(); loadAuthorizations();
loadPasswordInfo();
}
}, [isMasterTab, isSynced]);
// Initial API calls
useEffect(() => {
if (isMasterTab && isSynced && isAppConfigLoaded && !isAccountFrozen) {
loadAllChats({ listType: 'saved' });
loadAllStories();
loadAllHiddenStories();
loadRecentReactions(); loadRecentReactions();
loadDefaultTagReactions(); loadDefaultTagReactions();
loadFeaturedEmojiStickers(); loadAttachBots();
loadNotificationSettings();
loadNotificationExceptions();
loadTopInlineBots(); loadTopInlineBots();
loadEmojiKeywords({ language: BASE_EMOJI_KEYWORD_LANG }); loadTopReactions();
loadTimezones();
loadQuickReplies();
loadStarStatus(); loadStarStatus();
loadEmojiKeywords({ language: BASE_EMOJI_KEYWORD_LANG });
loadFeaturedEmojiStickers();
loadSavedReactionTags();
loadTopBotApps();
loadPaidReactionPrivacy();
loadDefaultTopicIcons();
loadAnimatedEmojis();
loadAvailableReactions();
loadUserCollectibleStatuses();
loadGenericEmojiEffects();
loadPremiumGifts(); loadPremiumGifts();
loadStarGifts(); loadStarGifts();
loadAvailableEffects(); loadAvailableEffects();
loadBirthdayNumbersStickers(); loadBirthdayNumbersStickers();
loadRestrictedEmojiStickers(); loadRestrictedEmojiStickers();
loadGenericEmojiEffects(); loadQuickReplies();
loadSavedReactionTags(); loadTimezones();
loadAuthorizations();
loadTopBotApps();
loadPaidReactionPrivacy();
loadPasswordInfo();
loadUserCollectibleStatuses();
} }
}, [isMasterTab, isSynced]); }, [isMasterTab, isSynced, isAppConfigLoaded, isAccountFrozen]);
// Initial Premium API calls // Initial Premium API calls
useEffect(() => { useEffect(() => {
if (isMasterTab && isCurrentUserPremium) { if (isMasterTab && isCurrentUserPremium && isAppConfigLoaded && !isAccountFrozen) {
loadDefaultStatusIcons(); loadDefaultStatusIcons();
loadRecentEmojiStatuses(); loadRecentEmojiStatuses();
} }
}, [isCurrentUserPremium, isMasterTab]); }, [isCurrentUserPremium, isMasterTab, isAppConfigLoaded, isAccountFrozen]);
// Language-based API calls // Language-based API calls
useEffect(() => { useEffect(() => {
@ -357,8 +375,6 @@ const Main = ({
} }
loadCountryList({ langCode: lang.code }); loadCountryList({ langCode: lang.code });
loadAttachBots();
} }
}, [lang, isMasterTab]); }, [lang, isMasterTab]);
@ -374,7 +390,7 @@ const Main = ({
// Sticker sets // Sticker sets
useEffect(() => { useEffect(() => {
if (isMasterTab && isSynced) { if (isMasterTab && isSynced && isAppConfigLoaded && !isAccountFrozen) {
if (!addedSetIds || !addedCustomEmojiIds) { if (!addedSetIds || !addedCustomEmojiIds) {
loadStickerSets(); loadStickerSets();
loadFavoriteStickers(); loadFavoriteStickers();
@ -384,7 +400,11 @@ const Main = ({
loadAddedStickers(); loadAddedStickers();
} }
} }
}, [addedSetIds, addedCustomEmojiIds, isMasterTab, isSynced]); }, [addedSetIds, addedCustomEmojiIds, isMasterTab, isSynced, isAppConfigLoaded, isAccountFrozen]);
useEffect(() => {
loadBotFreezeAppeal();
}, [isAppConfigLoaded]);
// Check version when service chat is ready // Check version when service chat is ready
useEffect(() => { useEffect(() => {
@ -636,6 +656,7 @@ export default memo(withGlobal<OwnProps>(
|| !selectCanAnimateInterface(global); || !selectCanAnimateInterface(global);
const deleteFolderDialog = deleteFolderDialogModal ? selectChatFolder(global, deleteFolderDialogModal) : undefined; const deleteFolderDialog = deleteFolderDialogModal ? selectChatFolder(global, deleteFolderDialogModal) : undefined;
const isAccountFrozen = selectIsCurrentUserFrozen(global);
return { return {
currentUserId, currentUserId,
@ -681,6 +702,8 @@ export default memo(withGlobal<OwnProps>(
requestedDraft, requestedDraft,
noRightColumnAnimation, noRightColumnAnimation,
isSynced: global.isSynced, isSynced: global.isSynced,
isAccountFrozen,
isAppConfigLoaded: global.isAppConfigLoaded,
}; };
}, },
)(Main)); )(Main));

View File

@ -0,0 +1,21 @@
.root {
cursor: pointer;
&:hover {
opacity: 0.85;
}
}
.title {
color: var(--color-error);
font-weight: var(--font-weight-medium);
font-size: 1rem;
line-height: 1rem;
}
.subtitle {
color: var(--color-text-secondary);
font-size: 0.875rem;
margin-top: 0.25rem;
line-height: 1rem;
}

View File

@ -0,0 +1,29 @@
import React, { memo } from '../../lib/teact/teact';
import { getActions } from '../../global';
import useLang from '../../hooks/useLang';
import useLastCallback from '../../hooks/useLastCallback';
import styles from './FrozenAccountPlaceholder.module.scss';
function FrozenAccountPlaceholder() {
const lang = useLang();
const { openFrozenAccountModal } = getActions();
const handleClick = useLastCallback(() => {
openFrozenAccountModal();
});
return (
<div
className={styles.root}
onClick={handleClick}
>
<div className={styles.title}>{lang('ComposerTitleFrozenAccount')}</div>
<div className={styles.subtitle}>{lang('ComposerSubtitleFrozenAccount')}</div>
</div>
);
}
export default memo(FrozenAccountPlaceholder);

View File

@ -23,6 +23,7 @@ import {
selectChatFullInfo, selectChatFullInfo,
selectIsChatBotNotStarted, selectIsChatBotNotStarted,
selectIsChatWithSelf, selectIsChatWithSelf,
selectIsCurrentUserFrozen,
selectIsInSelectMode, selectIsInSelectMode,
selectIsRightColumnShown, selectIsRightColumnShown,
selectIsUserBlocked, selectIsUserBlocked,
@ -82,6 +83,7 @@ interface StateProps {
language: string; language: string;
detectedChatLanguage?: string; detectedChatLanguage?: string;
doNotTranslate: string[]; doNotTranslate: string[];
isAccountFrozen?: boolean;
} }
// Chrome breaks layout when focusing input during transition // Chrome breaks layout when focusing input during transition
@ -121,6 +123,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
detectedChatLanguage, detectedChatLanguage,
doNotTranslate, doNotTranslate,
onTopicSearch, onTopicSearch,
isAccountFrozen,
}) => { }) => {
const { const {
joinChannel, joinChannel,
@ -137,6 +140,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
setSettingOption, setSettingOption,
unblockUser, unblockUser,
setViewForumAsMessages, setViewForumAsMessages,
openFrozenAccountModal,
} = getActions(); } = getActions();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const menuButtonRef = useRef<HTMLButtonElement>(null); const menuButtonRef = useRef<HTMLButtonElement>(null);
@ -219,6 +223,10 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
}); });
const handleRequestCall = useLastCallback(() => { const handleRequestCall = useLastCallback(() => {
if (isAccountFrozen) {
openFrozenAccountModal();
return;
}
requestMasterAndRequestCall({ userId: chatId }); requestMasterAndRequestCall({ userId: chatId });
}); });
@ -513,6 +521,7 @@ export default memo(withGlobal<OwnProps>(
const isTranslating = Boolean(selectRequestedChatTranslationLanguage(global, chatId)); const isTranslating = Boolean(selectRequestedChatTranslationLanguage(global, chatId));
const canTranslate = selectCanTranslateChat(global, chatId) && !fullInfo?.isTranslationDisabled; const canTranslate = selectCanTranslateChat(global, chatId) && !fullInfo?.isTranslationDisabled;
const isAccountFrozen = selectIsCurrentUserFrozen(global);
return { return {
noMenu: false, noMenu: false,
@ -542,6 +551,7 @@ export default memo(withGlobal<OwnProps>(
doNotTranslate, doNotTranslate,
detectedChatLanguage: chat.detectedLanguage, detectedChatLanguage: chat.detectedLanguage,
canUnblock, canUnblock,
isAccountFrozen,
}; };
}, },
)(HeaderActions)); )(HeaderActions));

View File

@ -31,6 +31,7 @@ import {
selectChatFullInfo, selectChatFullInfo,
selectCurrentMessageList, selectCurrentMessageList,
selectIsChatWithSelf, selectIsChatWithSelf,
selectIsCurrentUserFrozen,
selectIsRightColumnShown, selectIsRightColumnShown,
selectNotifyDefaults, selectNotifyDefaults,
selectNotifyException, selectNotifyException,
@ -122,6 +123,7 @@ type StateProps = {
isBot?: boolean; isBot?: boolean;
isChatWithSelf?: boolean; isChatWithSelf?: boolean;
savedDialog?: ApiChat; savedDialog?: ApiChat;
isAccountFrozen?: boolean;
}; };
const CLOSE_MENU_ANIMATION_DURATION = 200; const CLOSE_MENU_ANIMATION_DURATION = 200;
@ -176,6 +178,7 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
onAsMessagesClick, onAsMessagesClick,
onClose, onClose,
onCloseAnimationEnd, onCloseAnimationEnd,
isAccountFrozen,
}) => { }) => {
const { const {
updateChatMutedState, updateChatMutedState,
@ -186,6 +189,7 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
createGroupCall, createGroupCall,
openLinkedChat, openLinkedChat,
openAddContactDialog, openAddContactDialog,
openFrozenAccountModal,
requestMasterAndRequestCall, requestMasterAndRequestCall,
toggleStatistics, toggleStatistics,
openMonetizationStatistics, openMonetizationStatistics,
@ -224,14 +228,23 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
}); });
const handleReport = useLastCallback(() => { const handleReport = useLastCallback(() => {
setIsMenuOpen(false); if (isAccountFrozen) {
reportMessages({ chatId, messageIds: [] }); openFrozenAccountModal();
} else {
setIsMenuOpen(false);
reportMessages({ chatId, messageIds: [] });
}
onClose(); onClose();
}); });
const handleDelete = useLastCallback(() => { const handleDelete = useLastCallback(() => {
if (isAccountFrozen) {
openFrozenAccountModal();
onClose();
} else {
setIsDeleteModalOpen(true);
}
setIsMenuOpen(false); setIsMenuOpen(false);
setIsDeleteModalOpen(true);
}); });
const closeMenu = useLastCallback(() => { const closeMenu = useLastCallback(() => {
@ -251,39 +264,68 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
}); });
const handleStartBot = useLastCallback(() => { const handleStartBot = useLastCallback(() => {
sendBotCommand({ command: '/start' }); if (isAccountFrozen) {
openFrozenAccountModal();
} else {
sendBotCommand({ command: '/start' });
}
}); });
const handleRestartBot = useLastCallback(() => { const handleRestartBot = useLastCallback(() => {
restartBot({ chatId }); if (isAccountFrozen) {
openFrozenAccountModal();
} else {
restartBot({ chatId });
}
}); });
const handleUnmuteClick = useLastCallback(() => { const handleUnmuteClick = useLastCallback(() => {
updateChatMutedState({ chatId, isMuted: false }); if (isAccountFrozen) {
openFrozenAccountModal();
} else {
updateChatMutedState({ chatId, isMuted: false });
}
closeMenu(); closeMenu();
}); });
const handleMuteClick = useLastCallback(() => { const handleMuteClick = useLastCallback(() => {
markRenderMuteModal(); if (isAccountFrozen) {
setIsMuteModalOpen(true); openFrozenAccountModal();
closeMenu();
} else {
markRenderMuteModal();
setIsMuteModalOpen(true);
}
setIsMenuOpen(false); setIsMenuOpen(false);
}); });
const handleCreateTopicClick = useLastCallback(() => { const handleCreateTopicClick = useLastCallback(() => {
openCreateTopicPanel({ chatId }); if (isAccountFrozen) {
setShouldCloseFast(!isRightColumnShown); openFrozenAccountModal();
} else {
openCreateTopicPanel({ chatId });
setShouldCloseFast(!isRightColumnShown);
}
closeMenu(); closeMenu();
}); });
const handleEditClick = useLastCallback(() => { const handleEditClick = useLastCallback(() => {
toggleManagement({ force: true }); if (isAccountFrozen) {
setShouldCloseFast(!isRightColumnShown); openFrozenAccountModal();
} else {
toggleManagement({ force: true });
setShouldCloseFast(!isRightColumnShown);
}
closeMenu(); closeMenu();
}); });
const handleEditTopicClick = useLastCallback(() => { const handleEditTopicClick = useLastCallback(() => {
openEditTopicPanel({ chatId, topicId: Number(threadId) }); if (isAccountFrozen) {
setShouldCloseFast(!isRightColumnShown); openFrozenAccountModal();
} else {
openEditTopicPanel({ chatId, topicId: Number(threadId) });
setShouldCloseFast(!isRightColumnShown);
}
closeMenu(); closeMenu();
}); });
@ -294,7 +336,9 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
}); });
const handleEnterVoiceChatClick = useLastCallback(() => { const handleEnterVoiceChatClick = useLastCallback(() => {
if (canCreateVoiceChat) { if (isAccountFrozen) {
openFrozenAccountModal();
} else if (canCreateVoiceChat) {
// TODO Show popup to schedule // TODO Show popup to schedule
createGroupCall({ createGroupCall({
chatId, chatId,
@ -313,27 +357,47 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
}); });
const handleGiftClick = useLastCallback(() => { const handleGiftClick = useLastCallback(() => {
openGiftModal({ forUserId: chatId }); if (isAccountFrozen) {
openFrozenAccountModal();
} else {
openGiftModal({ forUserId: chatId });
}
closeMenu(); closeMenu();
}); });
const handleAddContactClick = useLastCallback(() => { const handleAddContactClick = useLastCallback(() => {
openAddContactDialog({ userId: chatId }); if (isAccountFrozen) {
openFrozenAccountModal();
} else {
openAddContactDialog({ userId: chatId });
}
closeMenu(); closeMenu();
}); });
const handleSubscribe = useLastCallback(() => { const handleSubscribe = useLastCallback(() => {
onSubscribeChannel(); if (isAccountFrozen) {
openFrozenAccountModal();
} else {
onSubscribeChannel();
}
closeMenu(); closeMenu();
}); });
const handleVideoCall = useLastCallback(() => { const handleVideoCall = useLastCallback(() => {
requestMasterAndRequestCall({ userId: chatId, isVideo: true }); if (isAccountFrozen) {
openFrozenAccountModal();
} else {
requestMasterAndRequestCall({ userId: chatId, isVideo: true });
}
closeMenu(); closeMenu();
}); });
const handleCall = useLastCallback(() => { const handleCall = useLastCallback(() => {
requestMasterAndRequestCall({ userId: chatId }); if (isAccountFrozen) {
openFrozenAccountModal();
} else {
requestMasterAndRequestCall({ userId: chatId });
}
closeMenu(); closeMenu();
}); });
@ -355,7 +419,9 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
}); });
const handleBoostClick = useLastCallback(() => { const handleBoostClick = useLastCallback(() => {
if (canViewBoosts) { if (isAccountFrozen) {
openFrozenAccountModal();
} else if (canViewBoosts) {
openBoostStatistics({ chatId }); openBoostStatistics({ chatId });
setShouldCloseFast(!isRightColumnShown); setShouldCloseFast(!isRightColumnShown);
} else { } else {
@ -370,7 +436,11 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
}); });
const handleSelectMessages = useLastCallback(() => { const handleSelectMessages = useLastCallback(() => {
enterMessageSelectMode(); if (isAccountFrozen) {
openFrozenAccountModal();
} else {
enterMessageSelectMode();
}
closeMenu(); closeMenu();
}); });
@ -380,12 +450,20 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
}); });
const handleBlock = useLastCallback(() => { const handleBlock = useLastCallback(() => {
blockUser({ userId: chatId }); if (isAccountFrozen) {
openFrozenAccountModal();
} else {
blockUser({ userId: chatId });
}
closeMenu(); closeMenu();
}); });
const handleUnblock = useLastCallback(() => { const handleUnblock = useLastCallback(() => {
unblockUser({ userId: chatId }); if (isAccountFrozen) {
openFrozenAccountModal();
} else {
unblockUser({ userId: chatId });
}
closeMenu(); closeMenu();
}); });
@ -756,6 +834,7 @@ export default memo(withGlobal<OwnProps>(
const isSavedDialog = getIsSavedDialog(chatId, threadId, global.currentUserId); const isSavedDialog = getIsSavedDialog(chatId, threadId, global.currentUserId);
const savedDialog = isSavedDialog ? selectChat(global, String(threadId)) : undefined; const savedDialog = isSavedDialog ? selectChat(global, String(threadId)) : undefined;
const isAccountFrozen = selectIsCurrentUserFrozen(global);
return { return {
chat, chat,
@ -782,6 +861,7 @@ export default memo(withGlobal<OwnProps>(
isBot: Boolean(chatBot), isBot: Boolean(chatBot),
isChatWithSelf, isChatWithSelf,
savedDialog, savedDialog,
isAccountFrozen,
}; };
}, },
)(HeaderMenuContainer)); )(HeaderMenuContainer));

View File

@ -43,6 +43,7 @@ import {
selectFocusedMessageId, selectFocusedMessageId,
selectIsChatProtected, selectIsChatProtected,
selectIsChatWithSelf, selectIsChatWithSelf,
selectIsCurrentUserFrozen,
selectIsCurrentUserPremium, selectIsCurrentUserPremium,
selectIsInSelectMode, selectIsInSelectMode,
selectIsViewportNewest, selectIsViewportNewest,
@ -130,10 +131,12 @@ type StateProps = {
isEmptyThread?: boolean; isEmptyThread?: boolean;
isForum?: boolean; isForum?: boolean;
currentUserId: string; currentUserId: string;
isAccountFrozen?: boolean;
areAdsEnabled?: boolean; areAdsEnabled?: boolean;
channelJoinInfo?: ApiChatFullInfo['joinInfo']; channelJoinInfo?: ApiChatFullInfo['joinInfo'];
isChatProtected?: boolean; isChatProtected?: boolean;
hasCustomGreeting?: boolean; hasCustomGreeting?: boolean;
isAppConfigLoaded?: boolean;
}; };
const MESSAGE_REACTIONS_POLLING_INTERVAL = 20 * 1000; const MESSAGE_REACTIONS_POLLING_INTERVAL = 20 * 1000;
@ -196,7 +199,9 @@ const MessageList: FC<OwnProps & StateProps> = ({
onIntersectPinnedMessage, onIntersectPinnedMessage,
onScrollDownToggle, onScrollDownToggle,
onNotchToggle, onNotchToggle,
isAccountFrozen,
hasCustomGreeting, hasCustomGreeting,
isAppConfigLoaded,
}) => { }) => {
const { const {
loadViewportMessages, setScrollOffset, loadSponsoredMessages, loadMessageReactions, copyMessagesByIds, loadViewportMessages, setScrollOffset, loadSponsoredMessages, loadMessageReactions, copyMessagesByIds,
@ -248,10 +253,10 @@ const MessageList: FC<OwnProps & StateProps> = ({
useEffect(() => { useEffect(() => {
const canHaveAds = isChannelChat || isBot; const canHaveAds = isChannelChat || isBot;
if (areAdsEnabled && canHaveAds && isSynced && isReady) { if (areAdsEnabled && canHaveAds && isSynced && isReady && isAppConfigLoaded) {
loadSponsoredMessages({ peerId: chatId }); loadSponsoredMessages({ peerId: chatId });
} }
}, [chatId, isSynced, isReady, isChannelChat, isBot, areAdsEnabled]); }, [chatId, isSynced, isReady, isChannelChat, isBot, areAdsEnabled, isAppConfigLoaded]);
// Updated only once when messages are loaded (as we want the unread divider to keep its position) // Updated only once when messages are loaded (as we want the unread divider to keep its position)
useSyncEffect(() => { useSyncEffect(() => {
@ -344,7 +349,7 @@ const MessageList: FC<OwnProps & StateProps> = ({
threadId, isChatWithSelf, channelJoinInfo]); threadId, isChatWithSelf, channelJoinInfo]);
useInterval(() => { useInterval(() => {
if (!messageIds || !messagesById || type === 'scheduled') return; if (!messageIds || !messagesById || type === 'scheduled' || isAccountFrozen) return;
if (!isChannelChat && !isGroupChat) return; if (!isChannelChat && !isGroupChat) return;
const ids = messageIds.filter((id) => { const ids = messageIds.filter((id) => {
@ -796,8 +801,10 @@ export default memo(withGlobal<OwnProps>(
const isCurrentUserPremium = selectIsCurrentUserPremium(global); const isCurrentUserPremium = selectIsCurrentUserPremium(global);
const areAdsEnabled = !isCurrentUserPremium || selectUserFullInfo(global, currentUserId)?.areAdsEnabled; const areAdsEnabled = !isCurrentUserPremium || selectUserFullInfo(global, currentUserId)?.areAdsEnabled;
const isAccountFrozen = selectIsCurrentUserFrozen(global);
const hasCustomGreeting = Boolean(userFullInfo?.businessIntro); const hasCustomGreeting = Boolean(userFullInfo?.businessIntro);
const isAppConfigLoaded = global.isAppConfigLoaded;
return { return {
areAdsEnabled, areAdsEnabled,
@ -832,7 +839,9 @@ export default memo(withGlobal<OwnProps>(
currentUserId, currentUserId,
isChatProtected: selectIsChatProtected(global, chatId), isChatProtected: selectIsChatProtected(global, chatId),
...(withLastMessageWhenPreloading && { lastMessage }), ...(withLastMessageWhenPreloading && { lastMessage }),
isAccountFrozen,
hasCustomGreeting, hasCustomGreeting,
isAppConfigLoaded,
}; };
}, },
)(MessageList)); )(MessageList));

View File

@ -266,14 +266,19 @@
} }
.MessageSelectToolbar-inner, .MessageSelectToolbar-inner,
.composer-button, .composer-button {
.messaging-disabled {
.mask-image-disabled & { .mask-image-disabled & {
box-shadow: 0 0.25rem 0.5rem 0.125rem var(--color-default-shadow); box-shadow: 0 0.25rem 0.5rem 0.125rem var(--color-default-shadow);
border-radius: var(--border-radius-messages); border-radius: var(--border-radius-messages);
} }
} }
.messaging-disabled {
.mask-image-disabled & {
border-radius: var(--border-radius-messages);
}
}
.middle-column-footer-button-container { .middle-column-footer-button-container {
width: 100%; width: 100%;
display: flex; display: flex;

View File

@ -47,6 +47,7 @@ import {
selectCurrentMiddleSearch, selectCurrentMiddleSearch,
selectDraft, selectDraft,
selectIsChatBotNotStarted, selectIsChatBotNotStarted,
selectIsCurrentUserFrozen,
selectIsInSelectMode, selectIsInSelectMode,
selectIsRightColumnShown, selectIsRightColumnShown,
selectIsUserBlocked, selectIsUserBlocked,
@ -93,6 +94,7 @@ import ChatLanguageModal from './ChatLanguageModal.async';
import { DropAreaState } from './composer/DropArea'; import { DropAreaState } from './composer/DropArea';
import EmojiInteractionAnimation from './EmojiInteractionAnimation.async'; import EmojiInteractionAnimation from './EmojiInteractionAnimation.async';
import FloatingActionButtons from './FloatingActionButtons'; import FloatingActionButtons from './FloatingActionButtons';
import FrozenAccountPlaceholder from './FrozenAccountPlaceholder';
import MessageList from './MessageList'; import MessageList from './MessageList';
import MessageSelectToolbar from './MessageSelectToolbar.async'; import MessageSelectToolbar from './MessageSelectToolbar.async';
import MiddleHeader from './MiddleHeader'; import MiddleHeader from './MiddleHeader';
@ -156,6 +158,8 @@ type StateProps = {
isContactRequirePremium?: boolean; isContactRequirePremium?: boolean;
topics?: Record<number, ApiTopic>; topics?: Record<number, ApiTopic>;
paidMessagesStars?: number; paidMessagesStars?: number;
isAccountFrozen?: boolean;
freezeAppealChat?: ApiChat;
}; };
function isImage(item: DataTransferItem) { function isImage(item: DataTransferItem) {
@ -217,6 +221,8 @@ function MiddleColumn({
isContactRequirePremium, isContactRequirePremium,
topics, topics,
paidMessagesStars, paidMessagesStars,
isAccountFrozen,
freezeAppealChat,
}: OwnProps & StateProps) { }: OwnProps & StateProps) {
const { const {
openChat, openChat,
@ -448,7 +454,8 @@ function MiddleColumn({
const composerRestrictionMessage = messageSendingRestrictionReason const composerRestrictionMessage = messageSendingRestrictionReason
?? forumComposerPlaceholder ?? forumComposerPlaceholder
?? (isContactRequirePremium ? <PremiumRequiredPlaceholder userId={chatId!} /> : undefined); ?? (isContactRequirePremium ? <PremiumRequiredPlaceholder userId={chatId!} /> : undefined)
?? (isAccountFrozen && freezeAppealChat?.id !== chatId ? <FrozenAccountPlaceholder /> : undefined);
// CSS Variables calculation doesn't work properly with transforms, so we calculate transform values in JS // CSS Variables calculation doesn't work properly with transforms, so we calculate transform values in JS
const { const {
@ -477,7 +484,7 @@ function MiddleColumn({
const isMessagingDisabled = Boolean( const isMessagingDisabled = Boolean(
!isPinnedMessageList && !isSavedDialog && !renderingCanPost && !renderingCanRestartBot && !renderingCanStartBot !isPinnedMessageList && !isSavedDialog && !renderingCanPost && !renderingCanRestartBot && !renderingCanStartBot
&& !renderingCanSubscribe && composerRestrictionMessage, && !renderingCanSubscribe && composerRestrictionMessage,
); ) || (isAccountFrozen && freezeAppealChat?.id !== chatId);
const withMessageListBottomShift = Boolean( const withMessageListBottomShift = Boolean(
renderingCanRestartBot || renderingCanSubscribe || renderingShouldSendJoinRequest || renderingCanStartBot renderingCanRestartBot || renderingCanSubscribe || renderingShouldSendJoinRequest || renderingCanStartBot
|| (isPinnedMessageList && canUnpin) || canShowOpenChatButton || renderingCanUnblock, || (isPinnedMessageList && canUnpin) || canShowOpenChatButton || renderingCanUnblock,
@ -809,6 +816,10 @@ export default memo(withGlobal<OwnProps>(
const isContactRequirePremium = userFull?.isContactRequirePremium; const isContactRequirePremium = userFull?.isContactRequirePremium;
const paidMessagesStars = selectPeerPaidMessagesStars(global, chatId); const paidMessagesStars = selectPeerPaidMessagesStars(global, chatId);
const isAccountFrozen = selectIsCurrentUserFrozen(global);
const botFreezeAppealId = global.botFreezeAppealId;
const freezeAppealChat = botFreezeAppealId
? selectChat(global, botFreezeAppealId) : undefined;
return { return {
...state, ...state,
@ -826,7 +837,8 @@ export default memo(withGlobal<OwnProps>(
&& !isBotNotStarted && !isBotNotStarted
&& !(shouldJoinToSend && chat?.isNotJoined) && !(shouldJoinToSend && chat?.isNotJoined)
&& !shouldBlockSendInForum && !shouldBlockSendInForum
&& !isSavedDialog, && !isSavedDialog
&& (!isAccountFrozen || freezeAppealChat?.id === chatId),
isPinnedMessageList, isPinnedMessageList,
currentUserBannedRights: chat?.currentUserBannedRights, currentUserBannedRights: chat?.currentUserBannedRights,
defaultBannedRights: chat?.defaultBannedRights, defaultBannedRights: chat?.defaultBannedRights,
@ -847,6 +859,8 @@ export default memo(withGlobal<OwnProps>(
isContactRequirePremium, isContactRequirePremium,
topics, topics,
paidMessagesStars, paidMessagesStars,
isAccountFrozen,
freezeAppealChat,
}; };
}, },
)(MiddleColumn)); )(MiddleColumn));

View File

@ -19,6 +19,7 @@ import { getMessageReplyInfo } from '../../../global/helpers/replies';
import { import {
selectChat, selectChat,
selectChatMessage, selectChatMessage,
selectIsCurrentUserFrozen,
selectIsCurrentUserPremium, selectIsCurrentUserPremium,
selectIsInSelectMode, selectIsInSelectMode,
selectIsMessageFocused, selectIsMessageFocused,
@ -86,6 +87,7 @@ type StateProps = {
hasUnreadReaction?: boolean; hasUnreadReaction?: boolean;
isResizingContainer?: boolean; isResizingContainer?: boolean;
scrollTargetPosition?: ScrollTargetPosition; scrollTargetPosition?: ScrollTargetPosition;
isAccountFrozen?: boolean;
}; };
const SINGLE_LINE_ACTIONS: Set<ApiMessageAction['type']> = new Set([ const SINGLE_LINE_ACTIONS: Set<ApiMessageAction['type']> = new Set([
@ -121,6 +123,7 @@ const ActionMessage = ({
observeIntersectionForBottom, observeIntersectionForBottom,
observeIntersectionForLoading, observeIntersectionForLoading,
observeIntersectionForPlaying, observeIntersectionForPlaying,
isAccountFrozen,
}: OwnProps & StateProps) => { }: OwnProps & StateProps) => {
const { const {
requestConfetti, requestConfetti,
@ -189,7 +192,7 @@ const ActionMessage = ({
handleContextMenuClose, handleContextMenuHide, handleContextMenuClose, handleContextMenuHide,
} = useContextMenuHandlers( } = useContextMenuHandlers(
ref, ref,
isTouchScreen && isInSelectMode, (isTouchScreen && isInSelectMode) || isAccountFrozen,
!IS_ELECTRON, !IS_ELECTRON,
IS_ANDROID, IS_ANDROID,
getIsMessageListReady, getIsMessageListReady,
@ -448,6 +451,7 @@ const ActionMessage = ({
threadId={threadId} threadId={threadId}
observeIntersection={observeIntersectionForPlaying} observeIntersection={observeIntersectionForPlaying}
isCurrentUserPremium={isCurrentUserPremium} isCurrentUserPremium={isCurrentUserPremium}
isAccountFrozen
/> />
)} )}
</div> </div>
@ -479,6 +483,7 @@ export default memo(withGlobal<OwnProps>(
const isCurrentUserPremium = selectIsCurrentUserPremium(global); const isCurrentUserPremium = selectIsCurrentUserPremium(global);
const hasUnreadReaction = chat?.unreadReactions?.includes(message.id); const hasUnreadReaction = chat?.unreadReactions?.includes(message.id);
const isAccountFrozen = selectIsCurrentUserFrozen(global);
return { return {
sender, sender,
@ -494,6 +499,7 @@ export default memo(withGlobal<OwnProps>(
hasUnreadReaction, hasUnreadReaction,
isResizingContainer, isResizingContainer,
scrollTargetPosition, scrollTargetPosition,
isAccountFrozen,
}; };
}, },
)(ActionMessage)); )(ActionMessage));

View File

@ -699,6 +699,31 @@ const ActionMessageText = ({
case 'customAction': case 'customAction':
return action.message; return action.message;
case 'paidMessagesPrice': {
const { stars } = action;
if (stars === 0) {
return lang('ActionPaidMessageGroupPriceFree');
}
return lang('ActionPaidMessageGroupPrice', {
stars: formatStarsAsText(lang, stars),
}, { withNodes: true, withMarkdown: true });
}
case 'paidMessagesRefunded': {
const { stars } = action;
const user = selectPeer(global, chatId);
const userTitle = (user && getPeerTitle(lang, user)) || userFallbackText;
const key = isOutgoing
? 'ApiMessageActionPaidMessagesRefundedOutgoing'
: 'ApiMessageActionPaidMessagesRefundedIncoming';
return lang(key, {
stars: formatStarsAsText(lang, stars),
user: renderPeerLink(user?.id, userTitle),
}, { withNodes: true, withMarkdown: true });
}
case 'phoneCall': // Rendered as a regular message, but considered an action for the summary case 'phoneCall': // Rendered as a regular message, but considered an action for the summary
return lang(getCallMessageKey(action, isOutgoing)); return lang(getCallMessageKey(action, isOutgoing));
default: default:

View File

@ -4,7 +4,7 @@ import { getActions, getGlobal } from '../../../global';
import type { ApiCommentsInfo } from '../../../api/types'; import type { ApiCommentsInfo } from '../../../api/types';
import { selectPeer } from '../../../global/selectors'; import { selectIsCurrentUserFrozen, selectPeer } from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { formatIntegerCompact } from '../../../util/textFormat'; import { formatIntegerCompact } from '../../../util/textFormat';
@ -36,7 +36,7 @@ const CommentButton: FC<OwnProps> = ({
isLoading, isLoading,
asActionButton, asActionButton,
}) => { }) => {
const { openThread } = getActions(); const { openThread, openFrozenAccountModal } = getActions();
const shouldRenderLoading = useAsyncRendering([isLoading], SHOW_LOADER_DELAY); const shouldRenderLoading = useAsyncRendering([isLoading], SHOW_LOADER_DELAY);
@ -46,6 +46,11 @@ const CommentButton: FC<OwnProps> = ({
} = threadInfo; } = threadInfo;
const handleClick = useLastCallback(() => { const handleClick = useLastCallback(() => {
const global = getGlobal();
if (selectIsCurrentUserFrozen(global)) {
openFrozenAccountModal();
return;
}
openThread({ openThread({
isComments: true, chatId, originMessageId, originChannelId, isComments: true, chatId, originMessageId, originChannelId,
}); });

View File

@ -85,6 +85,7 @@ import {
selectForwardedSender, selectForwardedSender,
selectIsChatProtected, selectIsChatProtected,
selectIsChatWithSelf, selectIsChatWithSelf,
selectIsCurrentUserFrozen,
selectIsCurrentUserPremium, selectIsCurrentUserPremium,
selectIsDocumentGroupSelected, selectIsDocumentGroupSelected,
selectIsInSelectMode, selectIsInSelectMode,
@ -305,6 +306,7 @@ type StateProps = {
lastPlaybackTimestamp?: number; lastPlaybackTimestamp?: number;
paidMessageStars?: number; paidMessageStars?: number;
isChatWithUser?: boolean; isChatWithUser?: boolean;
isAccountFrozen?: boolean;
}; };
type MetaPosition = type MetaPosition =
@ -428,6 +430,7 @@ const Message: FC<OwnProps & StateProps> = ({
onIntersectPinnedMessage, onIntersectPinnedMessage,
paidMessageStars, paidMessageStars,
isChatWithUser, isChatWithUser,
isAccountFrozen,
}) => { }) => {
const { const {
toggleMessageSelection, toggleMessageSelection,
@ -465,7 +468,7 @@ const Message: FC<OwnProps & StateProps> = ({
handleContextMenuHide, handleContextMenuHide,
} = useContextMenuHandlers( } = useContextMenuHandlers(
ref, ref,
isTouchScreen && isInSelectMode, (isTouchScreen && isInSelectMode) || isAccountFrozen,
!IS_ELECTRON, !IS_ELECTRON,
IS_ANDROID, IS_ANDROID,
getIsMessageListReady, getIsMessageListReady,
@ -570,6 +573,7 @@ const Message: FC<OwnProps & StateProps> = ({
const hasSubheader = hasTopicChip || hasMessageReply || hasStoryReply || hasForwardedCustomShape; const hasSubheader = hasTopicChip || hasMessageReply || hasStoryReply || hasForwardedCustomShape;
const selectMessage = useLastCallback((e?: React.MouseEvent<HTMLDivElement, MouseEvent>, groupedId?: string) => { const selectMessage = useLastCallback((e?: React.MouseEvent<HTMLDivElement, MouseEvent>, groupedId?: string) => {
if (isAccountFrozen) return;
toggleMessageSelection({ toggleMessageSelection({
messageId, messageId,
groupedId, groupedId,
@ -768,7 +772,7 @@ const Message: FC<OwnProps & StateProps> = ({
&& !isInDocumentGroupNotLast && messageListType === 'thread' && !isInDocumentGroupNotLast && messageListType === 'thread'
&& !noComments; && !noComments;
const withQuickReactionButton = !isTouchScreen && !phoneCall && !isInSelectMode && defaultReaction const withQuickReactionButton = !isTouchScreen && !phoneCall && !isInSelectMode && defaultReaction
&& !isInDocumentGroupNotLast && !isStoryMention && !hasTtl; && !isInDocumentGroupNotLast && !isStoryMention && !hasTtl && !isAccountFrozen;
const hasOutsideReactions = !withVoiceTranscription && hasReactions const hasOutsideReactions = !withVoiceTranscription && hasReactions
&& (isCustomShape || ((photo || video || storyData || (location?.mediaType === 'geo')) && !hasText)); && (isCustomShape || ((photo || video || storyData || (location?.mediaType === 'geo')) && !hasText));
@ -1048,6 +1052,7 @@ const Message: FC<OwnProps & StateProps> = ({
noRecentReactors={isChannel} noRecentReactors={isChannel}
tags={tags} tags={tags}
isCurrentUserPremium={isPremium} isCurrentUserPremium={isPremium}
isAccountFrozen
/> />
); );
} }
@ -1699,6 +1704,7 @@ const Message: FC<OwnProps & StateProps> = ({
observeIntersection={observeIntersectionForPlaying} observeIntersection={observeIntersectionForPlaying}
noRecentReactors={isChannel} noRecentReactors={isChannel}
tags={tags} tags={tags}
isAccountFrozen
/> />
)} )}
</div> </div>
@ -1858,6 +1864,7 @@ export default memo(withGlobal<OwnProps>(
const maxTimestamp = selectMessageTimestampableDuration(global, message); const maxTimestamp = selectMessageTimestampableDuration(global, message);
const lastPlaybackTimestamp = selectMessageLastPlaybackTimestamp(global, chatId, message.id); const lastPlaybackTimestamp = selectMessageLastPlaybackTimestamp(global, chatId, message.id);
const isAccountFrozen = selectIsCurrentUserFrozen(global);
return { return {
theme: selectTheme(global), theme: selectTheme(global),
@ -1951,6 +1958,7 @@ export default memo(withGlobal<OwnProps>(
lastPlaybackTimestamp, lastPlaybackTimestamp,
paidMessageStars, paidMessageStars,
isChatWithUser, isChatWithUser,
isAccountFrozen,
}; };
}, },
)(Message)); )(Message));

View File

@ -36,6 +36,7 @@ type OwnProps = {
isCurrentUserPremium?: boolean; isCurrentUserPremium?: boolean;
observeIntersection?: ObserveFn; observeIntersection?: ObserveFn;
noRecentReactors?: boolean; noRecentReactors?: boolean;
isAccountFrozen?: boolean;
}; };
const MAX_RECENT_AVATARS = 3; const MAX_RECENT_AVATARS = 3;
@ -51,6 +52,7 @@ const Reactions: FC<OwnProps> = ({
noRecentReactors, noRecentReactors,
isCurrentUserPremium, isCurrentUserPremium,
tags, tags,
isAccountFrozen,
}) => { }) => {
const { const {
toggleReaction, toggleReaction,
@ -60,6 +62,7 @@ const Reactions: FC<OwnProps> = ({
openPremiumModal, openPremiumModal,
resetLocalPaidReactions, resetLocalPaidReactions,
showNotification, showNotification,
openFrozenAccountModal,
} = getActions(); } = getActions();
const lang = useOldLang(); const lang = useOldLang();
@ -107,6 +110,10 @@ const Reactions: FC<OwnProps> = ({
}, [message, noRecentReactors, recentReactorsByReactionKey, results, areTags, tags, totalCount]); }, [message, noRecentReactors, recentReactorsByReactionKey, results, areTags, tags, totalCount]);
const handleClick = useLastCallback((reaction: ApiReaction) => { const handleClick = useLastCallback((reaction: ApiReaction) => {
if (isAccountFrozen) {
openFrozenAccountModal();
return;
}
if (areTags) { if (areTags) {
if (!isCurrentUserPremium) { if (!isCurrentUserPremium) {
openPremiumModal({ openPremiumModal({
@ -130,6 +137,11 @@ const Reactions: FC<OwnProps> = ({
const paidLocalCount = useMemo(() => results.find((r) => r.reaction.type === 'paid')?.localAmount || 0, [results]); const paidLocalCount = useMemo(() => results.find((r) => r.reaction.type === 'paid')?.localAmount || 0, [results]);
const handlePaidClick = useLastCallback((count: number) => { const handlePaidClick = useLastCallback((count: number) => {
if (isAccountFrozen) {
openFrozenAccountModal();
return;
}
addLocalPaidReaction({ addLocalPaidReaction({
chatId: message.chatId, chatId: message.chatId,
messageId: message.id, messageId: message.id,
@ -162,6 +174,11 @@ const Reactions: FC<OwnProps> = ({
}, [lang, message, paidLocalCount]); }, [lang, message, paidLocalCount]);
const handleRemoveReaction = useLastCallback((reaction: ApiReaction) => { const handleRemoveReaction = useLastCallback((reaction: ApiReaction) => {
if (isAccountFrozen) {
openFrozenAccountModal();
return;
}
toggleReaction({ toggleReaction({
chatId: message.chatId, chatId: message.chatId,
messageId: message.id, messageId: message.id,

View File

@ -15,6 +15,7 @@ import ChatInviteModal from './chatInvite/ChatInviteModal.async';
import ChatlistModal from './chatlist/ChatlistModal.async'; import ChatlistModal from './chatlist/ChatlistModal.async';
import CollectibleInfoModal from './collectible/CollectibleInfoModal.async'; import CollectibleInfoModal from './collectible/CollectibleInfoModal.async';
import EmojiStatusAccessModal from './emojiStatusAccess/EmojiStatusAccessModal.async'; import EmojiStatusAccessModal from './emojiStatusAccess/EmojiStatusAccessModal.async';
import FrozenAccountModal from './frozenAccount/FrozenAccountModal.async';
import PremiumGiftModal from './gift/GiftModal.async'; import PremiumGiftModal from './gift/GiftModal.async';
import GiftInfoModal from './gift/info/GiftInfoModal.async'; import GiftInfoModal from './gift/info/GiftInfoModal.async';
import GiftRecipientPicker from './gift/recipient/GiftRecipientPicker.async'; import GiftRecipientPicker from './gift/recipient/GiftRecipientPicker.async';
@ -79,7 +80,8 @@ type ModalKey = keyof Pick<TabState,
'sharePreparedMessageModal' | 'sharePreparedMessageModal' |
'giftStatusInfoModal' | 'giftStatusInfoModal' |
'giftTransferModal' | 'giftTransferModal' |
'chatRefundModal' 'chatRefundModal' |
'isFrozenAccountModalOpen'
>; >;
type StateProps = { type StateProps = {
@ -130,6 +132,7 @@ const MODALS: ModalRegistry = {
sharePreparedMessageModal: SharePreparedMessageModal, sharePreparedMessageModal: SharePreparedMessageModal,
giftTransferModal: GiftTransferModal, giftTransferModal: GiftTransferModal,
chatRefundModal: ChatRefundModal, chatRefundModal: ChatRefundModal,
isFrozenAccountModalOpen: FrozenAccountModal,
}; };
const MODAL_KEYS = Object.keys(MODALS) as ModalKey[]; const MODAL_KEYS = Object.keys(MODALS) as ModalKey[];
const MODAL_ENTRIES = Object.entries(MODALS) as Entries<ModalRegistry>; const MODAL_ENTRIES = Object.entries(MODALS) as Entries<ModalRegistry>;

View File

@ -9,7 +9,9 @@ import type { ApiStickerSet, ApiUser } from '../../../api/types';
import type { TabState } from '../../../global/types'; import type { TabState } from '../../../global/types';
import { getUserFullName } from '../../../global/helpers'; import { getUserFullName } from '../../../global/helpers';
import { selectIsCurrentUserPremium, selectStickerSet, selectUser } from '../../../global/selectors'; import {
selectIsCurrentUserFrozen, selectIsCurrentUserPremium, selectStickerSet, selectUser,
} from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import useInterval from '../../../hooks/schedulers/useInterval'; import useInterval from '../../../hooks/schedulers/useInterval';
@ -31,6 +33,7 @@ export type StateProps = {
currentUser?: ApiUser; currentUser?: ApiUser;
stickerSet?: ApiStickerSet; stickerSet?: ApiStickerSet;
isPremium?: boolean; isPremium?: boolean;
isAccountFrozen?: boolean;
}; };
const INTERVAL = 3200; const INTERVAL = 3200;
@ -40,6 +43,7 @@ const EmojiStatusAccessModal: FC<OwnProps & StateProps> = ({
currentUser, currentUser,
stickerSet, stickerSet,
isPremium, isPremium,
isAccountFrozen,
}) => { }) => {
const { const {
closeEmojiStatusAccessModal, closeEmojiStatusAccessModal,
@ -60,10 +64,10 @@ const EmojiStatusAccessModal: FC<OwnProps & StateProps> = ({
const [currentStatusIndex, setCurrentStatusIndex] = useState<number>(0); const [currentStatusIndex, setCurrentStatusIndex] = useState<number>(0);
useEffect(() => { useEffect(() => {
if (isOpen && !stickerSet?.stickers) { if (isOpen && !stickerSet?.stickers && !isAccountFrozen) {
loadDefaultStatusIcons(); loadDefaultStatusIcons();
} }
}, [isOpen, stickerSet]); }, [isOpen, stickerSet, isAccountFrozen]);
const mockPeerWithStatus = useMemo(() => { const mockPeerWithStatus = useMemo(() => {
if (!currentUser || !stickerSet?.stickers) return undefined; if (!currentUser || !stickerSet?.stickers) return undefined;
@ -195,11 +199,13 @@ export default memo(withGlobal<OwnProps>(
const currentUser = selectUser(global, global.currentUserId!); const currentUser = selectUser(global, global.currentUserId!);
const isPremium = selectIsCurrentUserPremium(global); const isPremium = selectIsCurrentUserPremium(global);
const stickerSet = global.defaultStatusIconsId ? selectStickerSet(global, global.defaultStatusIconsId) : undefined; const stickerSet = global.defaultStatusIconsId ? selectStickerSet(global, global.defaultStatusIconsId) : undefined;
const isAccountFrozen = selectIsCurrentUserFrozen(global);
return { return {
currentUser, currentUser,
stickerSet, stickerSet,
isPremium, isPremium,
isAccountFrozen,
}; };
}, },
)(EmojiStatusAccessModal)); )(EmojiStatusAccessModal));

View File

@ -0,0 +1,18 @@
import type { FC } from '../../../lib/teact/teact';
import React from '../../../lib/teact/teact';
import type { OwnProps } from './FrozenAccountModal';
import { Bundles } from '../../../util/moduleLoader';
import useModuleLoader from '../../../hooks/useModuleLoader';
const FrozenAccountModalAsync: FC<OwnProps> = (props) => {
const { modal } = props;
const FrozenAccountModal = useModuleLoader(Bundles.Extra, 'FrozenAccountModal', modal);
// eslint-disable-next-line react/jsx-props-no-spreading
return FrozenAccountModal ? <FrozenAccountModal {...props} /> : undefined;
};
export default FrozenAccountModalAsync;

View File

@ -0,0 +1,26 @@
.header {
margin-top: 0.5rem;
margin-bottom: 0.75rem;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.title {
font-weight: var(--font-weight-medium);
font-size: 1.25rem;
text-align: center;
padding-top: 0.5rem;
}
.footer {
margin-top: 0.5rem;
display: flex;
align-self: stretch;
flex-direction: column;
}
.buttonAppeal {
margin-bottom: 0.5rem;
}

View File

@ -0,0 +1,143 @@
import React, { memo, useMemo } from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
import type { TabState } from '../../../global/types';
import { selectUser } from '../../../global/selectors';
import { formatDateToString } from '../../../util/dates/dateFormat';
import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets';
import formatUsername from '../../common/helpers/formatUsername';
import useLang from '../../../hooks/useLang';
import useLastCallback from '../../../hooks/useLastCallback';
import AnimatedIconWithPreview from '../../common/AnimatedIconWithPreview';
import Button from '../../ui/Button';
import Link from '../../ui/Link';
import TableAboutModal, { type TableAboutData } from '../common/TableAboutModal';
import styles from './FrozenAccountModal.module.scss';
export type OwnProps = {
modal: TabState['isFrozenAccountModalOpen'];
};
type StateProps = {
freezeAppealUrl?: string;
botFreezeAppealUsername?: string;
freezeUntilDate?: number;
};
const FrozenAccountModal = ({
modal,
freezeUntilDate,
freezeAppealUrl,
botFreezeAppealUsername,
}: OwnProps & StateProps) => {
const {
closeFrozenAccountModal,
openUrl,
} = getActions();
const lang = useLang();
const isOpen = Boolean(modal);
const handleClose = useLastCallback(() => {
closeFrozenAccountModal();
});
const handleAppeal = useLastCallback(() => {
closeFrozenAccountModal();
if (freezeAppealUrl) {
openUrl({ url: freezeAppealUrl });
}
});
const header = useMemo(() => {
return (
<div className={styles.header}>
<AnimatedIconWithPreview
size={160}
tgsUrl={LOCAL_TGS_URLS.BannedDuck}
noLoop
/>
<div className={styles.title}>
{lang('FrozenAccountModalTitle')}
</div>
</div>
);
}, [lang]);
const footer = useMemo(() => {
if (!isOpen) return undefined;
return (
<div className={styles.footer}>
<Button
className={styles.buttonAppeal}
size="smaller"
onClick={handleAppeal}
noForcedUpperCase
>
{lang('ButtonAppeal')}
</Button>
<Button
isText
size="smaller"
onClick={handleClose}
noForcedUpperCase
>
{lang('ButtonUnderstood')}
</Button>
</div>
);
}, [lang, isOpen]);
if (!freezeUntilDate || !botFreezeAppealUsername) return undefined;
const date = new Date(freezeUntilDate * 1000);
const botLink = (
<Link onClick={handleAppeal} isPrimary>
{formatUsername(botFreezeAppealUsername)}
</Link>
);
const listItemData = [
['hand-stop', lang('FrozenAccountViolationTitle'), lang('FrozenAccountViolationSubtitle')],
['lock', lang('FrozenAccountReadOnlyTitle'), lang('FrozenAccountReadOnlySubtitle')],
['frozen-time', lang('FrozenAccountAppealTitle'),
lang('FrozenAccountAppealSubtitle', {
botLink,
date: formatDateToString(date, lang.code),
}, {
withNodes: true,
})],
] satisfies TableAboutData;
return (
<TableAboutModal
isOpen={isOpen}
header={header}
listItemData={listItemData}
footer={footer}
hasBackdrop
onClose={handleClose}
/>
);
};
export default memo(withGlobal<OwnProps>(
(global): StateProps => {
const freezeUntilDate = global.appConfig?.freezeUntilDate;
const freezeAppealUrl = global.appConfig?.freezeAppealUrl;
const botFreezeAppealId = global.botFreezeAppealId;
const botFreezeAppealUsername = botFreezeAppealId
? selectUser(global, botFreezeAppealId)?.usernames?.[0]?.username : undefined;
return {
freezeUntilDate,
freezeAppealUrl,
botFreezeAppealUsername,
};
},
)(FrozenAccountModal));

View File

@ -19,6 +19,7 @@ import { isChatChannel, isUserId } from '../../global/helpers';
import { getPeerTitle } from '../../global/helpers/peers'; import { getPeerTitle } from '../../global/helpers/peers';
import { import {
selectChat, selectChat,
selectIsCurrentUserFrozen,
selectIsCurrentUserPremium, selectIsCurrentUserPremium,
selectPeer, selectPeer,
selectPeerPaidMessagesStars, selectPeerPaidMessagesStars,
@ -104,6 +105,7 @@ interface StateProps {
stealthMode: ApiStealthMode; stealthMode: ApiStealthMode;
withHeaderAnimation?: boolean; withHeaderAnimation?: boolean;
paidMessagesStars?: number; paidMessagesStars?: number;
isAccountFrozen?: boolean;
} }
const VIDEO_MIN_READY_STATE = IS_SAFARI ? 4 : 3; const VIDEO_MIN_READY_STATE = IS_SAFARI ? 4 : 3;
@ -137,6 +139,7 @@ function Story({
onClose, onClose,
onReport, onReport,
paidMessagesStars, paidMessagesStars,
isAccountFrozen,
}: OwnProps & StateProps) { }: OwnProps & StateProps) {
const { const {
viewStory, viewStory,
@ -233,7 +236,7 @@ function Story({
? story.content.video.duration ? story.content.video.duration
: undefined; : undefined;
const shouldShowComposer = !(isOut && isUserStory) && !isChangelog && !isChannelStory; const shouldShowComposer = !(isOut && isUserStory) && !isChangelog && !isChannelStory && !isAccountFrozen;
const shouldShowFooter = isLoadedStory && !shouldShowComposer && (isOut || isChannelStory); const shouldShowFooter = isLoadedStory && !shouldShowComposer && (isOut || isChannelStory);
const headerAnimation = isMobile && withHeaderAnimation ? 'slideFade' : 'none'; const headerAnimation = isMobile && withHeaderAnimation ? 'slideFade' : 'none';
@ -965,6 +968,7 @@ export default memo(withGlobal<OwnProps>((global, {
const fromPeer = isLoadedStory && story.fromId ? selectPeer(global, story.fromId) : undefined; const fromPeer = isLoadedStory && story.fromId ? selectPeer(global, story.fromId) : undefined;
const paidMessagesStars = selectPeerPaidMessagesStars(global, peerId); const paidMessagesStars = selectPeerPaidMessagesStars(global, peerId);
const isAccountFrozen = selectIsCurrentUserFrozen(global);
return { return {
peer: (user || chat)!, peer: (user || chat)!,
@ -982,5 +986,6 @@ export default memo(withGlobal<OwnProps>((global, {
stealthMode: global.stories.stealthMode, stealthMode: global.stories.stealthMode,
withHeaderAnimation, withHeaderAnimation,
paidMessagesStars, paidMessagesStars,
isAccountFrozen,
}; };
})(Story)); })(Story));

View File

@ -23,6 +23,7 @@ import './ui/messages';
import './ui/globalSearch'; import './ui/globalSearch';
import './ui/middleSearch'; import './ui/middleSearch';
import './ui/stickerSearch'; import './ui/stickerSearch';
import './ui/account';
import './ui/users'; import './ui/users';
import './ui/settings'; import './ui/settings';
import './ui/misc'; import './ui/misc';

View File

@ -16,6 +16,7 @@ import { ManagementProgress } from '../../../types';
import { BOT_FATHER_USERNAME, GENERAL_REFETCH_INTERVAL, PAID_SEND_DELAY } from '../../../config'; import { BOT_FATHER_USERNAME, GENERAL_REFETCH_INTERVAL, PAID_SEND_DELAY } from '../../../config';
import { copyTextToClipboard } from '../../../util/clipboard'; import { copyTextToClipboard } from '../../../util/clipboard';
import { getUsernameFromDeepLink } from '../../../util/deepLinkParser';
import { getCurrentTabId } from '../../../util/establishMultitabRole'; import { getCurrentTabId } from '../../../util/establishMultitabRole';
import { getTranslationFn } from '../../../util/localization'; import { getTranslationFn } from '../../../util/localization';
import { formatStarsAsText } from '../../../util/localization/format'; import { formatStarsAsText } from '../../../util/localization/format';
@ -55,6 +56,7 @@ import {
selectCurrentChat, selectCurrentChat,
selectCurrentMessageList, selectCurrentMessageList,
selectDraft, selectDraft,
selectIsCurrentUserFrozen,
selectIsTrustedBot, selectIsTrustedBot,
selectMessageReplyInfo, selectMessageReplyInfo,
selectPeer, selectPeer,
@ -681,6 +683,11 @@ addActionHandler('requestMainWebView', async (global, actions, payload): Promise
tabId = getCurrentTabId(), tabId = getCurrentTabId(),
} = payload; } = payload;
if (selectIsCurrentUserFrozen(global)) {
actions.openFrozenAccountModal({ tabId });
return;
}
if (checkIfOpenOrActivate(global, botId, tabId)) return; if (checkIfOpenOrActivate(global, botId, tabId)) return;
const bot = selectUser(global, botId); const bot = selectUser(global, botId);
@ -1423,3 +1430,17 @@ addActionHandler('startBotFatherConversation', async (global, actions, payload):
actions.openChat({ id: botFatherId, tabId }); actions.openChat({ id: botFatherId, tabId });
}); });
addActionHandler('loadBotFreezeAppeal', async (global): Promise<void> => {
const botUrl = global.appConfig?.freezeAppealUrl;
if (!botUrl) return;
const botAppealUsername = botUrl ? getUsernameFromDeepLink(botUrl) : undefined;
if (!botAppealUsername) return;
const chat = await fetchChatByUsername(global, botAppealUsername);
global = getGlobal();
global = {
...global,
botFreezeAppealId: chat?.id,
};
setGlobal(global);
});

View File

@ -113,6 +113,7 @@ import {
selectDraft, selectDraft,
selectIsChatPinned, selectIsChatPinned,
selectIsChatWithSelf, selectIsChatWithSelf,
selectIsCurrentUserFrozen,
selectLastServiceNotification, selectLastServiceNotification,
selectPeer, selectPeer,
selectSimilarChannelIds, selectSimilarChannelIds,
@ -366,10 +367,11 @@ addActionHandler('openThread', async (global, actions, payload): Promise<void> =
}); });
} }
const result = await callApi('fetchDiscussionMessage', { const result = selectIsCurrentUserFrozen(global) ? undefined
chat: selectChat(global, loadingChatId)!, : await callApi('fetchDiscussionMessage', {
messageId: Number(loadingThreadId), chat: selectChat(global, loadingChatId)!,
}); messageId: Number(loadingThreadId),
});
global = getGlobal(); global = getGlobal();
loadingThread = selectTabState(global, tabId).loadingThread; loadingThread = selectTabState(global, tabId).loadingThread;
@ -630,6 +632,11 @@ addActionHandler('updateChatMutedState', (global, actions, payload): ActionRetur
const { chatId, isMuted } = payload; const { chatId, isMuted } = payload;
let { mutedUntil } = payload; let { mutedUntil } = payload;
if (selectIsCurrentUserFrozen(global)) {
actions.openFrozenAccountModal({ tabId: getCurrentTabId() });
return;
}
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) { if (!chat) {
return; return;
@ -911,6 +918,11 @@ addActionHandler('createGroupChat', async (global, actions, payload): Promise<vo
addActionHandler('toggleChatPinned', (global, actions, payload): ActionReturnType => { addActionHandler('toggleChatPinned', (global, actions, payload): ActionReturnType => {
const { id, folderId, tabId = getCurrentTabId() } = payload; const { id, folderId, tabId = getCurrentTabId() } = payload;
if (selectIsCurrentUserFrozen(global)) {
actions.openFrozenAccountModal({ tabId });
return;
}
const chat = selectChat(global, id); const chat = selectChat(global, id);
if (!chat) { if (!chat) {
return; return;
@ -958,6 +970,12 @@ addActionHandler('toggleChatPinned', (global, actions, payload): ActionReturnTyp
addActionHandler('toggleChatArchived', (global, actions, payload): ActionReturnType => { addActionHandler('toggleChatArchived', (global, actions, payload): ActionReturnType => {
const { id } = payload; const { id } = payload;
if (selectIsCurrentUserFrozen(global)) {
actions.openFrozenAccountModal({ tabId: getCurrentTabId() });
return;
}
const chat = selectChat(global, id); const chat = selectChat(global, id);
if (chat) { if (chat) {
void callApi('toggleChatArchived', { void callApi('toggleChatArchived', {
@ -969,6 +987,12 @@ addActionHandler('toggleChatArchived', (global, actions, payload): ActionReturnT
addActionHandler('toggleSavedDialogPinned', (global, actions, payload): ActionReturnType => { addActionHandler('toggleSavedDialogPinned', (global, actions, payload): ActionReturnType => {
const { id, tabId = getCurrentTabId() } = payload; const { id, tabId = getCurrentTabId() } = payload;
if (selectIsCurrentUserFrozen(global)) {
actions.openFrozenAccountModal({ tabId });
return;
}
const chat = selectChat(global, id); const chat = selectChat(global, id);
if (!chat) { if (!chat) {
return; return;
@ -1171,6 +1195,11 @@ addActionHandler('deleteChatFolder', async (global, actions, payload): Promise<v
addActionHandler('markChatUnread', (global, actions, payload): ActionReturnType => { addActionHandler('markChatUnread', (global, actions, payload): ActionReturnType => {
const { id } = payload; const { id } = payload;
if (selectIsCurrentUserFrozen(global)) {
actions.openFrozenAccountModal({ tabId: getCurrentTabId() });
return;
}
const chat = selectChat(global, id); const chat = selectChat(global, id);
if (!chat) return; if (!chat) return;
void callApi('toggleDialogUnread', { void callApi('toggleDialogUnread', {
@ -1180,7 +1209,14 @@ addActionHandler('markChatUnread', (global, actions, payload): ActionReturnType
}); });
addActionHandler('markChatMessagesRead', async (global, actions, payload): Promise<void> => { addActionHandler('markChatMessagesRead', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { id } = payload; const { id } = payload;
if (selectIsCurrentUserFrozen(global)) {
actions.openFrozenAccountModal({ tabId: getCurrentTabId() });
return;
}
const chat = selectChat(global, id); const chat = selectChat(global, id);
if (!chat) return; if (!chat) return;
if (!chat.isForum) { if (!chat.isForum) {
@ -1229,6 +1265,7 @@ addActionHandler('markChatRead', (global, actions, payload): ActionReturnType =>
}); });
addActionHandler('markTopicRead', (global, actions, payload): ActionReturnType => { addActionHandler('markTopicRead', (global, actions, payload): ActionReturnType => {
if (selectIsCurrentUserFrozen(global)) return;
const { chatId, topicId } = payload; const { chatId, topicId } = payload;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) return; if (!chat) return;
@ -1784,6 +1821,8 @@ addActionHandler('updateChatMemberBannedRights', async (global, actions, payload
}); });
addActionHandler('updateChatAdmin', async (global, actions, payload): Promise<void> => { addActionHandler('updateChatAdmin', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { const {
chatId, userId, adminRights, customTitle, chatId, userId, adminRights, customTitle,
tabId = getCurrentTabId(), tabId = getCurrentTabId(),
@ -1942,6 +1981,7 @@ addActionHandler('loadGroupsForDiscussion', async (global): Promise<void> => {
}); });
addActionHandler('linkDiscussionGroup', async (global, actions, payload): Promise<void> => { addActionHandler('linkDiscussionGroup', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { channelId, chatId, tabId = getCurrentTabId() } = payload || {}; const { channelId, chatId, tabId = getCurrentTabId() } = payload || {};
const channel = selectChat(global, channelId); const channel = selectChat(global, channelId);
@ -2023,6 +2063,7 @@ addActionHandler('resetOpenChatWithDraft', (global, actions, payload): ActionRet
}); });
addActionHandler('loadMoreMembers', async (global, actions, payload): Promise<void> => { addActionHandler('loadMoreMembers', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { tabId = getCurrentTabId() } = payload || {}; const { tabId = getCurrentTabId() } = payload || {};
const { chatId } = selectCurrentMessageList(global, tabId) || {}; const { chatId } = selectCurrentMessageList(global, tabId) || {};
const chat = chatId ? selectChat(global, chatId) : undefined; const chat = chatId ? selectChat(global, chatId) : undefined;
@ -2211,7 +2252,11 @@ addActionHandler('processAttachBotParameters', async (global, actions, payload):
}); });
addActionHandler('loadTopics', async (global, actions, payload): Promise<void> => { addActionHandler('loadTopics', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { chatId, force } = payload; const { chatId, force } = payload;
if (selectIsCurrentUserFrozen(global)) {
return;
}
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) return; if (!chat) return;
@ -2780,6 +2825,8 @@ addActionHandler('setViewForumAsMessages', (global, actions, payload): ActionRet
}); });
addActionHandler('loadChannelRecommendations', async (global, actions, payload): Promise<void> => { addActionHandler('loadChannelRecommendations', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { chatId } = payload; const { chatId } = payload;
const chat = chatId ? selectChat(global, chatId) : undefined; const chat = chatId ? selectChat(global, chatId) : undefined;
@ -2810,6 +2857,8 @@ addActionHandler('loadChannelRecommendations', async (global, actions, payload):
}); });
addActionHandler('loadBotRecommendations', async (global, actions, payload): Promise<void> => { addActionHandler('loadBotRecommendations', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { userId } = payload; const { userId } = payload;
const user = selectChat(global, userId); const user = selectChat(global, userId);
@ -2915,20 +2964,21 @@ async function loadChats(
const isFirstBatch = !shouldIgnorePagination && !offsetPeer && !offsetDate && !offsetId; const isFirstBatch = !shouldIgnorePagination && !offsetPeer && !offsetDate && !offsetId;
const shouldReplaceStaleState = listType === 'active' && isFirstBatch; const shouldReplaceStaleState = listType === 'active' && isFirstBatch;
const isAccountFreeze = selectIsCurrentUserFrozen(global);
const result = listType === 'saved' ? await callApi('fetchSavedChats', { const result = listType === 'saved' ? await callApi('fetchSavedChats', {
limit: CHAT_LIST_LOAD_SLICE, limit: CHAT_LIST_LOAD_SLICE,
offsetDate, offsetDate,
offsetId, offsetId,
offsetPeer, offsetPeer,
withPinned: isFirstBatch, withPinned: isFirstBatch && !isAccountFreeze,
}) : await callApi('fetchChats', { }) : await callApi('fetchChats', {
limit: CHAT_LIST_LOAD_SLICE, limit: CHAT_LIST_LOAD_SLICE,
offsetDate, offsetDate,
offsetId, offsetId,
offsetPeer, offsetPeer,
archived: listType === 'archived', archived: listType === 'archived',
withPinned: isFirstBatch, withPinned: isFirstBatch && !isAccountFreeze,
lastLocalServiceMessageId, lastLocalServiceMessageId,
}); });
@ -3002,6 +3052,7 @@ async function loadChats(
export async function loadFullChat<T extends GlobalState>( export async function loadFullChat<T extends GlobalState>(
global: T, actions: RequiredGlobalActions, chat: ApiChat, global: T, actions: RequiredGlobalActions, chat: ApiChat,
) { ) {
if (selectIsCurrentUserFrozen(global)) return undefined;
const result = await callApi('fetchFullChat', chat); const result = await callApi('fetchFullChat', chat);
if (!result) { if (!result) {
return undefined; return undefined;

View File

@ -10,7 +10,8 @@ import {
updateChat, updateChatFullInfo, updateManagement, updateManagementProgress, updateUserFullInfo, updateChat, updateChatFullInfo, updateManagement, updateManagementProgress, updateUserFullInfo,
} from '../../reducers'; } from '../../reducers';
import { import {
selectChat, selectCurrentMessageList, selectTabState, selectUser, selectChat, selectCurrentMessageList, selectIsCurrentUserFrozen,
selectTabState, selectUser,
} from '../../selectors'; } from '../../selectors';
import { ensureIsSuperGroup } from './chats'; import { ensureIsSuperGroup } from './chats';
@ -109,6 +110,8 @@ addActionHandler('setOpenedInviteInfo', (global, actions, payload): ActionReturn
}); });
addActionHandler('loadExportedChatInvites', async (global, actions, payload): Promise<void> => { addActionHandler('loadExportedChatInvites', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { const {
chatId, adminId, isRevoked, limit, tabId = getCurrentTabId(), chatId, adminId, isRevoked, limit, tabId = getCurrentTabId(),
} = payload!; } = payload!;

View File

@ -120,6 +120,7 @@ import {
selectForwardsContainVoiceMessages, selectForwardsContainVoiceMessages,
selectIsChatBotNotStarted, selectIsChatBotNotStarted,
selectIsChatWithSelf, selectIsChatWithSelf,
selectIsCurrentUserFrozen,
selectIsCurrentUserPremium, selectIsCurrentUserPremium,
selectLanguageCode, selectLanguageCode,
selectListedIds, selectListedIds,
@ -994,6 +995,7 @@ addActionHandler('reportChannelSpam', (global, actions, payload): ActionReturnTy
}); });
addActionHandler('markMessageListRead', (global, actions, payload): ActionReturnType => { addActionHandler('markMessageListRead', (global, actions, payload): ActionReturnType => {
if (selectIsCurrentUserFrozen(global)) return undefined;
const { maxId, tabId = getCurrentTabId() } = payload!; const { maxId, tabId = getCurrentTabId() } = payload!;
const currentMessageList = selectCurrentMessageList(global, tabId); const currentMessageList = selectCurrentMessageList(global, tabId);
@ -1177,6 +1179,8 @@ addActionHandler('loadExtendedMedia', (global, actions, payload): ActionReturnTy
}); });
addActionHandler('loadScheduledHistory', async (global, actions, payload): Promise<void> => { addActionHandler('loadScheduledHistory', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { chatId } = payload; const { chatId } = payload;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) { if (!chat) {
@ -1852,6 +1856,8 @@ addActionHandler('loadSendPaidReactionsAs', async (global, actions, payload): Pr
}); });
addActionHandler('loadSponsoredMessages', async (global, actions, payload): Promise<void> => { addActionHandler('loadSponsoredMessages', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { peerId } = payload; const { peerId } = payload;
const peer = selectPeer(global, peerId); const peer = selectPeer(global, peerId);
if (!peer) { if (!peer) {
@ -1880,7 +1886,7 @@ addActionHandler('viewSponsoredMessage', (global, actions, payload): ActionRetur
return; return;
} }
void callApi('viewSponsoredMessage', { peer, random: message.randomId }); void callApi('viewSponsoredMessage', { random: message.randomId });
}); });
addActionHandler('clickSponsoredMessage', (global, actions, payload): ActionReturnType => { addActionHandler('clickSponsoredMessage', (global, actions, payload): ActionReturnType => {
@ -1892,7 +1898,7 @@ addActionHandler('clickSponsoredMessage', (global, actions, payload): ActionRetu
} }
void callApi('clickSponsoredMessage', { void callApi('clickSponsoredMessage', {
peer, random: message.randomId, isMedia, isFullscreen, random: message.randomId, isMedia, isFullscreen,
}); });
}); });
@ -1905,7 +1911,7 @@ addActionHandler('reportSponsoredMessage', async (global, actions, payload): Pro
return; return;
} }
const result = await callApi('reportSponsoredMessage', { peer, randomId, option }); const result = await callApi('reportSponsoredMessage', { randomId, option });
if (!result) return; if (!result) return;
@ -2352,6 +2358,8 @@ addActionHandler('scheduleForViewsIncrement', (global, actions, payload): Action
addActionHandler('loadMessageViews', async (global, actions, payload): Promise<void> => { addActionHandler('loadMessageViews', async (global, actions, payload): Promise<void> => {
const { chatId, ids, shouldIncrement } = payload; const { chatId, ids, shouldIncrement } = payload;
if (selectIsCurrentUserFrozen(global)) return;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) return; if (!chat) return;

View File

@ -40,6 +40,7 @@ import { updateTabState } from '../../reducers/tabs';
import { import {
selectChat, selectChat,
selectChatFullInfo, selectChatFullInfo,
selectIsCurrentUserFrozen,
selectPaymentInputInvoice, selectPaymentInputInvoice,
selectPaymentRequestId, selectPaymentRequestId,
selectProviderPublicToken, selectProviderPublicToken,
@ -530,6 +531,11 @@ addActionHandler('openGiftModal', async (global, actions, payload): Promise<void
forUserId, tabId = getCurrentTabId(), forUserId, tabId = getCurrentTabId(),
} = payload; } = payload;
if (selectIsCurrentUserFrozen(global)) {
actions.openFrozenAccountModal({ tabId });
return;
}
const gifts = await callApi('getPremiumGiftCodeOptions', {}); const gifts = await callApi('getPremiumGiftCodeOptions', {});
if (!gifts) return; if (!gifts) return;
@ -549,6 +555,11 @@ addActionHandler('openStarsGiftModal', async (global, actions, payload): Promise
tabId = getCurrentTabId(), tabId = getCurrentTabId(),
} = payload || {}; } = payload || {};
if (selectIsCurrentUserFrozen(global)) {
actions.openFrozenAccountModal({ tabId });
return;
}
const starsGiftOptions = await callApi('getStarsGiftOptions', {}); const starsGiftOptions = await callApi('getStarsGiftOptions', {});
global = getGlobal(); global = getGlobal();

View File

@ -31,6 +31,7 @@ import {
selectCurrentChat, selectCurrentChat,
selectDefaultReaction, selectDefaultReaction,
selectIsChatWithSelf, selectIsChatWithSelf,
selectIsCurrentUserFrozen,
selectMaxUserReactions, selectMaxUserReactions,
selectMessageIdsByGroupId, selectMessageIdsByGroupId,
selectPerformanceSettingsValue, selectPerformanceSettingsValue,
@ -391,6 +392,8 @@ addActionHandler('stopActiveEmojiInteraction', (global, actions, payload): Actio
}); });
addActionHandler('loadReactors', async (global, actions, payload): Promise<void> => { addActionHandler('loadReactors', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { chatId, messageId, reaction } = payload; const { chatId, messageId, reaction } = payload;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
const message = selectChatMessage(global, chatId, messageId); const message = selectChatMessage(global, chatId, messageId);
@ -418,6 +421,8 @@ addActionHandler('loadReactors', async (global, actions, payload): Promise<void>
}); });
addActionHandler('loadMessageReactions', (global, actions, payload): ActionReturnType => { addActionHandler('loadMessageReactions', (global, actions, payload): ActionReturnType => {
if (selectIsCurrentUserFrozen(global)) return;
const { ids, chatId } = payload; const { ids, chatId } = payload;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);

View File

@ -22,7 +22,8 @@ import {
} from '../../reducers'; } from '../../reducers';
import { updateTabState } from '../../reducers/tabs'; import { updateTabState } from '../../reducers/tabs';
import { import {
selectChat, selectTabState, selectUser, selectChat, selectIsCurrentUserFrozen,
selectTabState, selectUser,
} from '../../selectors'; } from '../../selectors';
import { selectSharedSettings } from '../../selectors/sharedState'; import { selectSharedSettings } from '../../selectors/sharedState';
@ -390,6 +391,8 @@ addActionHandler('loadLanguages', async (global): Promise<void> => {
}); });
addActionHandler('loadPrivacySettings', async (global): Promise<void> => { addActionHandler('loadPrivacySettings', async (global): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const result = await Promise.all([ const result = await Promise.all([
callApi('fetchPrivacySettings', 'phoneNumber'), callApi('fetchPrivacySettings', 'phoneNumber'),
callApi('fetchPrivacySettings', 'addByPhone'), callApi('fetchPrivacySettings', 'addByPhone'),
@ -574,6 +577,8 @@ addActionHandler('updateIsOnline', (global, actions, payload): ActionReturnType
}); });
addActionHandler('loadContentSettings', async (global): Promise<void> => { addActionHandler('loadContentSettings', async (global): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const result = await callApi('fetchContentSettings'); const result = await callApi('fetchContentSettings');
if (!result) return; if (!result) return;
@ -644,6 +649,7 @@ addActionHandler('loadAppConfig', async (global, actions, payload): Promise<void
global = { global = {
...global, ...global,
appConfig, appConfig,
isAppConfigLoaded: true,
}; };
setGlobal(global); setGlobal(global);
}); });

View File

@ -27,6 +27,7 @@ import {
} from '../../reducers'; } from '../../reducers';
import { updateTabState } from '../../reducers/tabs'; import { updateTabState } from '../../reducers/tabs';
import { import {
selectIsCurrentUserFrozen,
selectPeer, selectPeerStories, selectPeerStory, selectPeer, selectPeerStories, selectPeerStory,
selectPinnedStories, selectTabState, selectPinnedStories, selectTabState,
} from '../../selectors'; } from '../../selectors';
@ -278,6 +279,8 @@ addActionHandler('toggleStoryPinnedToTop', async (global, actions, payload): Pro
}); });
addActionHandler('loadPeerStories', async (global, actions, payload): Promise<void> => { addActionHandler('loadPeerStories', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { peerId } = payload; const { peerId } = payload;
const peer = selectPeer(global, peerId); const peer = selectPeer(global, peerId);
if (!peer) return; if (!peer) return;
@ -296,6 +299,8 @@ addActionHandler('loadPeerStories', async (global, actions, payload): Promise<vo
}); });
addActionHandler('loadPeerProfileStories', async (global, actions, payload): Promise<void> => { addActionHandler('loadPeerProfileStories', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { peerId, offsetId } = payload; const { peerId, offsetId } = payload;
const peer = selectPeer(global, peerId); const peer = selectPeer(global, peerId);
let peerStories = selectPeerStories(global, peerId); let peerStories = selectPeerStories(global, peerId);
@ -320,6 +325,8 @@ addActionHandler('loadPeerProfileStories', async (global, actions, payload): Pro
}); });
addActionHandler('loadStoriesArchive', async (global, actions, payload): Promise<void> => { addActionHandler('loadStoriesArchive', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { peerId, offsetId } = payload; const { peerId, offsetId } = payload;
const peer = selectPeer(global, peerId); const peer = selectPeer(global, peerId);
let peerStories = selectPeerStories(global, peerId); let peerStories = selectPeerStories(global, peerId);

View File

@ -29,7 +29,9 @@ import {
updateStickersForEmoji, updateStickersForEmoji,
} from '../../reducers'; } from '../../reducers';
import { updateTabState } from '../../reducers/tabs'; import { updateTabState } from '../../reducers/tabs';
import { selectIsCurrentUserPremium, selectStickerSet, selectTabState } from '../../selectors'; import {
selectIsCurrentUserFrozen, selectIsCurrentUserPremium, selectStickerSet, selectTabState,
} from '../../selectors';
import { selectCurrentLimit, selectPremiumLimit } from '../../selectors/limits'; import { selectCurrentLimit, selectPremiumLimit } from '../../selectors/limits';
const ADDED_SETS_THROTTLE = 200; const ADDED_SETS_THROTTLE = 200;
@ -128,6 +130,10 @@ addActionHandler('loadFavoriteStickers', async (global): Promise<void> => {
addActionHandler('loadPremiumStickers', async (global): Promise<void> => { addActionHandler('loadPremiumStickers', async (global): Promise<void> => {
const { hash } = global.stickers.premium || {}; const { hash } = global.stickers.premium || {};
if (selectIsCurrentUserFrozen(global)) {
return;
}
const result = await callApi('fetchStickersForEmoji', { emoji: '⭐️⭐️', hash }); const result = await callApi('fetchStickersForEmoji', { emoji: '⭐️⭐️', hash });
if (!result) { if (!result) {
return; return;
@ -151,6 +157,10 @@ addActionHandler('loadPremiumStickers', async (global): Promise<void> => {
addActionHandler('loadGreetingStickers', async (global): Promise<void> => { addActionHandler('loadGreetingStickers', async (global): Promise<void> => {
const { hash } = global.stickers.greeting || {}; const { hash } = global.stickers.greeting || {};
if (selectIsCurrentUserFrozen(global)) {
return;
}
const greeting = await callApi('fetchStickersForEmoji', { emoji: '👋⭐️', hash }); const greeting = await callApi('fetchStickersForEmoji', { emoji: '👋⭐️', hash });
if (!greeting) { if (!greeting) {
return; return;

View File

@ -66,7 +66,7 @@ addActionHandler('sync', (global, actions): ActionReturnType => {
}, RELEASE_STATUS_TIMEOUT); }, RELEASE_STATUS_TIMEOUT);
const { const {
loadAllChats, preloadTopChatMessages, loadAllStories, loadAllHiddenStories, loadAllChats, preloadTopChatMessages,
} = actions; } = actions;
initFolderManager(); initFolderManager();
@ -91,10 +91,7 @@ addActionHandler('sync', (global, actions): ActionReturnType => {
} }
loadAllChats({ listType: 'archived' }); loadAllChats({ listType: 'archived' });
loadAllChats({ listType: 'saved' });
preloadTopChatMessages(); preloadTopChatMessages();
loadAllStories();
loadAllHiddenStories();
}, },
}); });
}); });

View File

@ -30,6 +30,7 @@ import { updateTabState } from '../../reducers/tabs';
import { import {
selectChat, selectChat,
selectChatFullInfo, selectChatFullInfo,
selectIsCurrentUserFrozen,
selectIsCurrentUserPremium, selectIsCurrentUserPremium,
selectPeer, selectPeer,
selectPeerPhotos, selectPeerPhotos,
@ -159,6 +160,11 @@ addActionHandler('loadCurrentUser', (): ActionReturnType => {
addActionHandler('loadCommonChats', async (global, actions, payload): Promise<void> => { addActionHandler('loadCommonChats', async (global, actions, payload): Promise<void> => {
const { userId } = payload; const { userId } = payload;
if (selectIsCurrentUserFrozen(global)) {
return;
}
const user = selectUser(global, userId); const user = selectUser(global, userId);
const commonChats = selectUserCommonChats(global, userId); const commonChats = selectUserCommonChats(global, userId);
if (!user || isUserBot(user) || commonChats?.isFullyLoaded) { if (!user || isUserBot(user) || commonChats?.isFullyLoaded) {
@ -294,6 +300,8 @@ addActionHandler('deleteContact', async (global, actions, payload): Promise<void
}); });
addActionHandler('loadMoreProfilePhotos', async (global, actions, payload): Promise<void> => { addActionHandler('loadMoreProfilePhotos', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { peerId, shouldInvalidateCache, isPreload } = payload; const { peerId, shouldInvalidateCache, isPreload } = payload;
const isPrivate = isUserId(peerId); const isPrivate = isUserId(peerId);
@ -550,6 +558,8 @@ addActionHandler('openSuggestedStatusModal', async (global, actions, payload): P
addActionHandler('loadPeerSettings', async (global, actions, payload): Promise<void> => { addActionHandler('loadPeerSettings', async (global, actions, payload): Promise<void> => {
const { peerId } = payload; const { peerId } = payload;
if (selectIsCurrentUserFrozen(global)) return;
const userFullInfo = selectUserFullInfo(global, peerId); const userFullInfo = selectUserFullInfo(global, peerId);
if (!userFullInfo) { if (!userFullInfo) {
actions.loadFullUser({ userId: peerId }); actions.loadFullUser({ userId: peerId });

View File

@ -95,6 +95,19 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
break; break;
} }
case 'notSupportedInFrozenAccount': {
actions.showNotification({
title: {
key: 'NotificationTitleNotSupportedInFrozenAccount',
},
message: {
key: 'NotificationMessageNotSupportedInFrozenAccount',
},
tabId: getCurrentTabId(),
});
break;
}
} }
}); });

View File

@ -0,0 +1,21 @@
import type { ActionReturnType } from '../../types';
import { getCurrentTabId } from '../../../util/establishMultitabRole';
import { addActionHandler } from '../..';
import { updateTabState } from '../../reducers/tabs';
addActionHandler('openFrozenAccountModal', (global, actions, payload): ActionReturnType => {
const { tabId = getCurrentTabId() } = payload || {};
return updateTabState(global, {
isFrozenAccountModalOpen: true,
}, tabId);
});
addActionHandler('closeFrozenAccountModal', (global, actions, payload): ActionReturnType => {
const { tabId = getCurrentTabId() } = payload || {};
return updateTabState(global, {
isFrozenAccountModalOpen: false,
}, tabId);
});

View File

@ -21,7 +21,8 @@ import {
import { updateGroupCall } from '../../reducers/calls'; import { updateGroupCall } from '../../reducers/calls';
import { updateTabState } from '../../reducers/tabs'; import { updateTabState } from '../../reducers/tabs';
import { import {
selectChat, selectChatFullInfo, selectTabState, selectUser, selectChat, selectChatFullInfo, selectIsCurrentUserFrozen,
selectTabState, selectUser,
} from '../../selectors'; } from '../../selectors';
import { selectActiveGroupCall, selectChatGroupCall, selectGroupCall } from '../../selectors/calls'; import { selectActiveGroupCall, selectChatGroupCall, selectGroupCall } from '../../selectors/calls';
import { fetchChatByUsername, loadFullChat } from '../api/chats'; import { fetchChatByUsername, loadFullChat } from '../api/chats';
@ -90,6 +91,7 @@ export function initializeSounds() {
} }
async function fetchGroupCall<T extends GlobalState>(global: T, groupCall: Partial<ApiGroupCall>) { async function fetchGroupCall<T extends GlobalState>(global: T, groupCall: Partial<ApiGroupCall>) {
if (selectIsCurrentUserFrozen(global)) return undefined;
const result = await callApi('getGroupCall', { const result = await callApi('getGroupCall', {
call: groupCall, call: groupCall,
}); });
@ -130,6 +132,8 @@ addActionHandler('toggleGroupCallPanel', (global, actions, payload): ActionRetur
}); });
addActionHandler('subscribeToGroupCallUpdates', async (global, actions, payload): Promise<void> => { addActionHandler('subscribeToGroupCallUpdates', async (global, actions, payload): Promise<void> => {
if (selectIsCurrentUserFrozen(global)) return;
const { subscribed, id } = payload!; const { subscribed, id } = payload!;
const groupCall = selectGroupCall(global, id); const groupCall = selectGroupCall(global, id);

View File

@ -10,7 +10,9 @@ import {
clearStarPayment, openStarsTransactionModal, clearStarPayment, openStarsTransactionModal,
} from '../../reducers'; } from '../../reducers';
import { updateTabState } from '../../reducers/tabs'; import { updateTabState } from '../../reducers/tabs';
import { selectChatMessage, selectStarsPayment, selectTabState } from '../../selectors'; import {
selectChatMessage, selectIsCurrentUserFrozen, selectStarsPayment, selectTabState,
} from '../../selectors';
addActionHandler('processOriginStarsPayment', (global, actions, payload): ActionReturnType => { addActionHandler('processOriginStarsPayment', (global, actions, payload): ActionReturnType => {
const { originData, status, tabId = getCurrentTabId() } = payload; const { originData, status, tabId = getCurrentTabId() } = payload;
@ -59,6 +61,11 @@ addActionHandler('openGiftRecipientPicker', (global, actions, payload): ActionRe
tabId = getCurrentTabId(), tabId = getCurrentTabId(),
} = payload || {}; } = payload || {};
if (selectIsCurrentUserFrozen(global)) {
actions.openFrozenAccountModal({ tabId });
return global;
}
return updateTabState(global, { return updateTabState(global, {
isGiftRecipientPickerOpen: true, isGiftRecipientPickerOpen: true,
}, tabId); }, tabId);

View File

@ -5,6 +5,7 @@ import { addTabStateResetterAction } from '../../helpers/meta';
import { addActionHandler } from '../../index'; import { addActionHandler } from '../../index';
import { closeNewContactDialog, updateUserSearch } from '../../reducers'; import { closeNewContactDialog, updateUserSearch } from '../../reducers';
import { updateTabState } from '../../reducers/tabs'; import { updateTabState } from '../../reducers/tabs';
import { selectIsCurrentUserFrozen } from '../../selectors';
addActionHandler('setUserSearchQuery', (global, actions, payload): ActionReturnType => { addActionHandler('setUserSearchQuery', (global, actions, payload): ActionReturnType => {
const { const {
@ -23,6 +24,11 @@ addActionHandler('setUserSearchQuery', (global, actions, payload): ActionReturnT
addActionHandler('openAddContactDialog', (global, actions, payload): ActionReturnType => { addActionHandler('openAddContactDialog', (global, actions, payload): ActionReturnType => {
const { userId, tabId = getCurrentTabId() } = payload; const { userId, tabId = getCurrentTabId() } = payload;
if (selectIsCurrentUserFrozen(global)) {
actions.openFrozenAccountModal({ tabId });
return global;
}
return updateTabState(global, { return updateTabState(global, {
newContact: { userId }, newContact: { userId },
}, tabId); }, tabId);
@ -31,6 +37,11 @@ addActionHandler('openAddContactDialog', (global, actions, payload): ActionRetur
addActionHandler('openNewContactDialog', (global, actions, payload): ActionReturnType => { addActionHandler('openNewContactDialog', (global, actions, payload): ActionReturnType => {
const { tabId = getCurrentTabId() } = payload || {}; const { tabId = getCurrentTabId() } = payload || {};
if (selectIsCurrentUserFrozen(global)) {
actions.openFrozenAccountModal({ tabId });
return global;
}
return updateTabState(global, { return updateTabState(global, {
newContact: { newContact: {
isByPhoneNumber: true, isByPhoneNumber: true,

View File

@ -35,6 +35,10 @@ export function selectIsCurrentUserPremium<T extends GlobalState>(global: T) {
return Boolean(global.users.byId[global.currentUserId].isPremium); return Boolean(global.users.byId[global.currentUserId].isPremium);
} }
export function selectIsCurrentUserFrozen<T extends GlobalState>(global: T) {
return Boolean(global.appConfig?.freezeUntilDate);
}
export function selectIsPremiumPurchaseBlocked<T extends GlobalState>(global: T) { export function selectIsPremiumPurchaseBlocked<T extends GlobalState>(global: T) {
return global.appConfig?.isPremiumPurchaseBlocked ?? true; return global.appConfig?.isPremiumPurchaseBlocked ?? true;
} }

View File

@ -1026,6 +1026,8 @@ export interface ActionPayloads {
changeSessionTtl: { changeSessionTtl: {
days: number; days: number;
}; };
openFrozenAccountModal: WithTabId | undefined;
closeFrozenAccountModal: WithTabId | undefined;
// Chats // Chats
loadPeerSettings: { loadPeerSettings: {
@ -1713,6 +1715,7 @@ export interface ActionPayloads {
startBotFatherConversation: { startBotFatherConversation: {
param: string; param: string;
} & WithTabId; } & WithTabId;
loadBotFreezeAppeal: undefined;
checkUsername: { checkUsername: {
username: string; username: string;
} & WithTabId; } & WithTabId;

View File

@ -84,6 +84,7 @@ export type GlobalState = {
connectionState?: ApiUpdateConnectionStateType; connectionState?: ApiUpdateConnectionStateType;
currentUserId?: string; currentUserId?: string;
isSyncing?: boolean; isSyncing?: boolean;
isAppConfigLoaded?: boolean;
isAppUpdateAvailable?: boolean; isAppUpdateAvailable?: boolean;
isElectronUpdateAvailable?: boolean; isElectronUpdateAvailable?: boolean;
isSynced?: boolean; isSynced?: boolean;
@ -92,6 +93,7 @@ export type GlobalState = {
lastIsChatInfoShown?: boolean; lastIsChatInfoShown?: boolean;
initialUnreadNotifications?: number; initialUnreadNotifications?: number;
shouldShowContextMenuHint?: boolean; shouldShowContextMenuHint?: boolean;
botFreezeAppealId?: string;
audioPlayer: { audioPlayer: {
lastPlaybackRate: number; lastPlaybackRate: number;

View File

@ -618,6 +618,8 @@ export type TabState = {
isGiftRecipientPickerOpen?: boolean; isGiftRecipientPickerOpen?: boolean;
isFrozenAccountModalOpen?: boolean;
starsGiftingPickerModal?: { starsGiftingPickerModal?: {
isOpen?: boolean; isOpen?: boolean;
}; };

View File

@ -12,5 +12,5 @@ for (const tl of Object.values(Api)) {
} }
} }
export const LAYER = 200; export const LAYER = 201;
export { tlobjects }; export { tlobjects };

File diff suppressed because one or more lines are too long

View File

@ -159,6 +159,8 @@ messageActionGiftStars#45d5b021 flags:# currency:string amount:long stars:long c
messageActionPrizeStars#b00c47a2 flags:# unclaimed:flags.0?true stars:long transaction_id:string boost_peer:Peer giveaway_msg_id:int = MessageAction; messageActionPrizeStars#b00c47a2 flags:# unclaimed:flags.0?true stars:long transaction_id:string boost_peer:Peer giveaway_msg_id:int = MessageAction;
messageActionStarGift#4717e8a4 flags:# name_hidden:flags.0?true saved:flags.2?true converted:flags.3?true upgraded:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true gift:StarGift message:flags.1?TextWithEntities convert_stars:flags.4?long upgrade_msg_id:flags.5?int upgrade_stars:flags.8?long from_id:flags.11?Peer peer:flags.12?Peer saved_id:flags.12?long = MessageAction; messageActionStarGift#4717e8a4 flags:# name_hidden:flags.0?true saved:flags.2?true converted:flags.3?true upgraded:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true gift:StarGift message:flags.1?TextWithEntities convert_stars:flags.4?long upgrade_msg_id:flags.5?int upgrade_stars:flags.8?long from_id:flags.11?Peer peer:flags.12?Peer saved_id:flags.12?long = MessageAction;
messageActionStarGiftUnique#acdfcb81 flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long from_id:flags.6?Peer peer:flags.7?Peer saved_id:flags.7?long = MessageAction; messageActionStarGiftUnique#acdfcb81 flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long from_id:flags.6?Peer peer:flags.7?Peer saved_id:flags.7?long = MessageAction;
messageActionPaidMessagesRefunded#ac1f1fcd count:int stars:long = MessageAction;
messageActionPaidMessagesPrice#bcd71419 stars:long = MessageAction;
dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true view_forum_as_messages:flags.6?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog; dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true view_forum_as_messages:flags.6?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog;
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog; dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
photoEmpty#2331b22d id:long = Photo; photoEmpty#2331b22d id:long = Photo;
@ -173,6 +175,7 @@ geoPointEmpty#1117dd5f = GeoPoint;
geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radius:flags.0?int = GeoPoint; geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radius:flags.0?int = GeoPoint;
auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode; auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode;
auth.sentCodeSuccess#2390fe44 authorization:auth.Authorization = auth.SentCode; auth.sentCodeSuccess#2390fe44 authorization:auth.Authorization = auth.SentCode;
auth.sentCodePaymentRequired#d7cef980 store_product:string phone_code_hash:string = auth.SentCode;
auth.authorization#2ea2c0d4 flags:# setup_password_required:flags.1?true otherwise_relogin_days:flags.1?int tmp_sessions:flags.0?int future_auth_token:flags.2?bytes user:User = auth.Authorization; auth.authorization#2ea2c0d4 flags:# setup_password_required:flags.1?true otherwise_relogin_days:flags.1?int tmp_sessions:flags.0?int future_auth_token:flags.2?bytes user:User = auth.Authorization;
auth.authorizationSignUpRequired#44747e9a flags:# terms_of_service:flags.0?help.TermsOfService = auth.Authorization; auth.authorizationSignUpRequired#44747e9a flags:# terms_of_service:flags.0?help.TermsOfService = auth.Authorization;
auth.exportedAuthorization#b434e2b8 id:long bytes:bytes = auth.ExportedAuthorization; auth.exportedAuthorization#b434e2b8 id:long bytes:bytes = auth.ExportedAuthorization;
@ -196,7 +199,7 @@ inputReportReasonGeoIrrelevant#dbd4feed = ReportReason;
inputReportReasonFake#f5ddd6e7 = ReportReason; inputReportReasonFake#f5ddd6e7 = ReportReason;
inputReportReasonIllegalDrugs#a8eb2be = ReportReason; inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
inputReportReasonPersonalDetails#9ec7863d = ReportReason; inputReportReasonPersonalDetails#9ec7863d = ReportReason;
userFull#d2234ea0 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long = UserFull; userFull#99e78045 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true display_gifts_button:flags2.16?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long disallowed_gifts:flags2.15?DisallowedGiftsSettings = UserFull;
contact#145ade0b user_id:long mutual:Bool = Contact; contact#145ade0b user_id:long mutual:Bool = Contact;
importedContact#c13e3c50 user_id:long client_id:long = ImportedContact; importedContact#c13e3c50 user_id:long client_id:long = ImportedContact;
contactStatus#16d9703b user_id:long status:UserStatus = ContactStatus; contactStatus#16d9703b user_id:long status:UserStatus = ContactStatus;
@ -374,6 +377,7 @@ updateBusinessBotCallbackQuery#1ea2fda7 flags:# query_id:long user_id:long conne
updateStarsRevenueStatus#a584b019 peer:Peer status:StarsRevenueStatus = Update; updateStarsRevenueStatus#a584b019 peer:Peer status:StarsRevenueStatus = Update;
updateBotPurchasedPaidMedia#283bd312 user_id:long payload:string qts:int = Update; updateBotPurchasedPaidMedia#283bd312 user_id:long payload:string qts:int = Update;
updatePaidReactionPrivacy#8b725fce private:PaidReactionPrivacy = Update; updatePaidReactionPrivacy#8b725fce private:PaidReactionPrivacy = Update;
updateSentPhoneCode#504aa18f sent_code:auth.SentCode = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference; updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference;
updates.difference#f49ca0 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> state:updates.State = updates.Difference; updates.difference#f49ca0 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> state:updates.State = updates.Difference;
@ -746,7 +750,6 @@ phoneCallDiscardReasonMissed#85e42301 = PhoneCallDiscardReason;
phoneCallDiscardReasonDisconnect#e095c1a0 = PhoneCallDiscardReason; phoneCallDiscardReasonDisconnect#e095c1a0 = PhoneCallDiscardReason;
phoneCallDiscardReasonHangup#57adc690 = PhoneCallDiscardReason; phoneCallDiscardReasonHangup#57adc690 = PhoneCallDiscardReason;
phoneCallDiscardReasonBusy#faf7e8c9 = PhoneCallDiscardReason; phoneCallDiscardReasonBusy#faf7e8c9 = PhoneCallDiscardReason;
phoneCallDiscardReasonAllowGroupCall#afe2b839 encrypted_key:bytes = PhoneCallDiscardReason;
dataJSON#7d748d04 data:string = DataJSON; dataJSON#7d748d04 data:string = DataJSON;
labeledPrice#cb296bf8 label:string amount:long = LabeledPrice; labeledPrice#cb296bf8 label:string amount:long = LabeledPrice;
invoice#49ee584 flags:# test:flags.0?true name_requested:flags.1?true phone_requested:flags.2?true email_requested:flags.3?true shipping_address_requested:flags.4?true flexible:flags.5?true phone_to_provider:flags.6?true email_to_provider:flags.7?true recurring:flags.9?true currency:string prices:Vector<LabeledPrice> max_tip_amount:flags.8?long suggested_tip_amounts:flags.8?Vector<long> terms_url:flags.10?string subscription_period:flags.11?int = Invoice; invoice#49ee584 flags:# test:flags.0?true name_requested:flags.1?true phone_requested:flags.2?true email_requested:flags.3?true shipping_address_requested:flags.4?true flexible:flags.5?true phone_to_provider:flags.6?true email_to_provider:flags.7?true recurring:flags.9?true currency:string prices:Vector<LabeledPrice> max_tip_amount:flags.8?long suggested_tip_amounts:flags.8?Vector<long> terms_url:flags.10?string subscription_period:flags.11?int = Invoice;
@ -1025,7 +1028,7 @@ statsGroupTopPoster#9d04af9b user_id:long messages:int avg_chars:int = StatsGrou
statsGroupTopAdmin#d7584c87 user_id:long deleted:int kicked:int banned:int = StatsGroupTopAdmin; statsGroupTopAdmin#d7584c87 user_id:long deleted:int kicked:int banned:int = StatsGroupTopAdmin;
statsGroupTopInviter#535f779d user_id:long invitations:int = StatsGroupTopInviter; statsGroupTopInviter#535f779d user_id:long invitations:int = StatsGroupTopInviter;
stats.megagroupStats#ef7ff916 period:StatsDateRangeDays members:StatsAbsValueAndPrev messages:StatsAbsValueAndPrev viewers:StatsAbsValueAndPrev posters:StatsAbsValueAndPrev growth_graph:StatsGraph members_graph:StatsGraph new_members_by_source_graph:StatsGraph languages_graph:StatsGraph messages_graph:StatsGraph actions_graph:StatsGraph top_hours_graph:StatsGraph weekdays_graph:StatsGraph top_posters:Vector<StatsGroupTopPoster> top_admins:Vector<StatsGroupTopAdmin> top_inviters:Vector<StatsGroupTopInviter> users:Vector<User> = stats.MegagroupStats; stats.megagroupStats#ef7ff916 period:StatsDateRangeDays members:StatsAbsValueAndPrev messages:StatsAbsValueAndPrev viewers:StatsAbsValueAndPrev posters:StatsAbsValueAndPrev growth_graph:StatsGraph members_graph:StatsGraph new_members_by_source_graph:StatsGraph languages_graph:StatsGraph messages_graph:StatsGraph actions_graph:StatsGraph top_hours_graph:StatsGraph weekdays_graph:StatsGraph top_posters:Vector<StatsGroupTopPoster> top_admins:Vector<StatsGroupTopAdmin> top_inviters:Vector<StatsGroupTopInviter> users:Vector<User> = stats.MegagroupStats;
globalPrivacySettings#c9d8df1c flags:# archive_and_mute_new_noncontact_peers:flags.0?true keep_archived_unmuted:flags.1?true keep_archived_folders:flags.2?true hide_read_marks:flags.3?true new_noncontact_peers_require_premium:flags.4?true noncontact_peers_paid_stars:flags.5?long = GlobalPrivacySettings; globalPrivacySettings#fe41b34f flags:# archive_and_mute_new_noncontact_peers:flags.0?true keep_archived_unmuted:flags.1?true keep_archived_folders:flags.2?true hide_read_marks:flags.3?true new_noncontact_peers_require_premium:flags.4?true display_gifts_button:flags.7?true noncontact_peers_paid_stars:flags.5?long disallowed_gifts:flags.6?DisallowedGiftsSettings = GlobalPrivacySettings;
help.countryCode#4203c5ef flags:# country_code:string prefixes:flags.0?Vector<string> patterns:flags.1?Vector<string> = help.CountryCode; help.countryCode#4203c5ef flags:# country_code:string prefixes:flags.0?Vector<string> patterns:flags.1?Vector<string> = help.CountryCode;
help.country#c3878e23 flags:# hidden:flags.0?true iso2:string default_name:string name:flags.1?string country_codes:Vector<help.CountryCode> = help.Country; help.country#c3878e23 flags:# hidden:flags.0?true iso2:string default_name:string name:flags.1?string country_codes:Vector<help.CountryCode> = help.Country;
help.countriesListNotModified#93cc1f32 = help.CountriesList; help.countriesListNotModified#93cc1f32 = help.CountriesList;
@ -1130,6 +1133,7 @@ inputInvoiceStarGift#e8625e92 flags:# hide_name:flags.0?true include_upgrade:fla
inputInvoiceStarGiftUpgrade#4d818d5d flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = InputInvoice; inputInvoiceStarGiftUpgrade#4d818d5d flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = InputInvoice;
inputInvoiceStarGiftTransfer#4a5f5bd9 stargift:InputSavedStarGift to_id:InputPeer = InputInvoice; inputInvoiceStarGiftTransfer#4a5f5bd9 stargift:InputSavedStarGift to_id:InputPeer = InputInvoice;
inputInvoicePremiumGiftStars#dabab2ef flags:# user_id:InputUser months:int message:flags.0?TextWithEntities = InputInvoice; inputInvoicePremiumGiftStars#dabab2ef flags:# user_id:InputUser months:int message:flags.0?TextWithEntities = InputInvoice;
inputInvoiceBusinessBotTransferStars#f4997e42 bot:InputUser stars:long = InputInvoice;
payments.exportedInvoice#aed0cbd9 url:string = payments.ExportedInvoice; payments.exportedInvoice#aed0cbd9 url:string = payments.ExportedInvoice;
messages.transcribedAudio#cfb9d957 flags:# pending:flags.0?true transcription_id:long text:string trial_remains_num:flags.1?int trial_remains_until_date:flags.1?int = messages.TranscribedAudio; messages.transcribedAudio#cfb9d957 flags:# pending:flags.0?true transcription_id:long text:string trial_remains_num:flags.1?int trial_remains_until_date:flags.1?int = messages.TranscribedAudio;
help.premiumPromo#5334759c status_text:string status_entities:Vector<MessageEntity> video_sections:Vector<string> videos:Vector<Document> period_options:Vector<PremiumSubscriptionOption> users:Vector<User> = help.PremiumPromo; help.premiumPromo#5334759c status_text:string status_entities:Vector<MessageEntity> video_sections:Vector<string> videos:Vector<Document> period_options:Vector<PremiumSubscriptionOption> users:Vector<User> = help.PremiumPromo;
@ -1140,6 +1144,7 @@ inputStorePaymentPremiumGiveaway#160544ca flags:# only_new_subscribers:flags.0?t
inputStorePaymentStarsTopup#dddd0f56 stars:long currency:string amount:long = InputStorePaymentPurpose; inputStorePaymentStarsTopup#dddd0f56 stars:long currency:string amount:long = InputStorePaymentPurpose;
inputStorePaymentStarsGift#1d741ef7 user_id:InputUser stars:long currency:string amount:long = InputStorePaymentPurpose; inputStorePaymentStarsGift#1d741ef7 user_id:InputUser stars:long currency:string amount:long = InputStorePaymentPurpose;
inputStorePaymentStarsGiveaway#751f08fa flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.3?true stars:long boost_peer:InputPeer additional_peers:flags.1?Vector<InputPeer> countries_iso2:flags.2?Vector<string> prize_description:flags.4?string random_id:long until_date:int currency:string amount:long users:int = InputStorePaymentPurpose; inputStorePaymentStarsGiveaway#751f08fa flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.3?true stars:long boost_peer:InputPeer additional_peers:flags.1?Vector<InputPeer> countries_iso2:flags.2?Vector<string> prize_description:flags.4?string random_id:long until_date:int currency:string amount:long users:int = InputStorePaymentPurpose;
inputStorePaymentAuthCode#9bb2636d flags:# restore:flags.0?true phone_number:string phone_code_hash:string currency:string amount:long = InputStorePaymentPurpose;
paymentFormMethod#88f8f21b url:string title:string = PaymentFormMethod; paymentFormMethod#88f8f21b url:string title:string = PaymentFormMethod;
emojiStatusEmpty#2de11aae = EmojiStatus; emojiStatusEmpty#2de11aae = EmojiStatus;
emojiStatus#e7ff068a flags:# document_id:long until:flags.0?int = EmojiStatus; emojiStatus#e7ff068a flags:# document_id:long until:flags.0?int = EmojiStatus;
@ -1298,11 +1303,11 @@ inputQuickReplyShortcut#24596d41 shortcut:string = InputQuickReplyShortcut;
inputQuickReplyShortcutId#1190cf1 shortcut_id:int = InputQuickReplyShortcut; inputQuickReplyShortcutId#1190cf1 shortcut_id:int = InputQuickReplyShortcut;
messages.quickReplies#c68d6695 quick_replies:Vector<QuickReply> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.QuickReplies; messages.quickReplies#c68d6695 quick_replies:Vector<QuickReply> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.QuickReplies;
messages.quickRepliesNotModified#5f91eb5b = messages.QuickReplies; messages.quickRepliesNotModified#5f91eb5b = messages.QuickReplies;
connectedBot#bd068601 flags:# can_reply:flags.0?true bot_id:long recipients:BusinessBotRecipients = ConnectedBot; connectedBot#cd64636c flags:# bot_id:long recipients:BusinessBotRecipients rights:BusinessBotRights = ConnectedBot;
account.connectedBots#17d7f87b connected_bots:Vector<ConnectedBot> users:Vector<User> = account.ConnectedBots; account.connectedBots#17d7f87b connected_bots:Vector<ConnectedBot> users:Vector<User> = account.ConnectedBots;
messages.dialogFilters#2ad93719 flags:# tags_enabled:flags.0?true filters:Vector<DialogFilter> = messages.DialogFilters; messages.dialogFilters#2ad93719 flags:# tags_enabled:flags.0?true filters:Vector<DialogFilter> = messages.DialogFilters;
birthday#6c8e1e06 flags:# day:int month:int year:flags.0?int = Birthday; birthday#6c8e1e06 flags:# day:int month:int year:flags.0?int = Birthday;
botBusinessConnection#896433b4 flags:# can_reply:flags.0?true disabled:flags.1?true connection_id:string user_id:long dc_id:int date:int = BotBusinessConnection; botBusinessConnection#8f34b2f5 flags:# disabled:flags.1?true connection_id:string user_id:long dc_id:int date:int rights:flags.2?BusinessBotRights = BotBusinessConnection;
inputBusinessIntro#9c469cd flags:# title:string description:string sticker:flags.0?InputDocument = InputBusinessIntro; inputBusinessIntro#9c469cd flags:# title:string description:string sticker:flags.0?InputDocument = InputBusinessIntro;
businessIntro#5a0a066d flags:# title:string description:string sticker:flags.0?Document = BusinessIntro; businessIntro#5a0a066d flags:# title:string description:string sticker:flags.0?Document = BusinessIntro;
messages.myStickers#faff629d count:int sets:Vector<StickerSetCovered> = messages.MyStickers; messages.myStickers#faff629d count:int sets:Vector<StickerSetCovered> = messages.MyStickers;
@ -1409,6 +1414,11 @@ account.paidMessagesRevenue#1e109708 stars_amount:long = account.PaidMessagesRev
requirementToContactEmpty#50a9839 = RequirementToContact; requirementToContactEmpty#50a9839 = RequirementToContact;
requirementToContactPremium#e581e4e9 = RequirementToContact; requirementToContactPremium#e581e4e9 = RequirementToContact;
requirementToContactPaidMessages#b4f67e93 stars_amount:long = RequirementToContact; requirementToContactPaidMessages#b4f67e93 stars_amount:long = RequirementToContact;
businessBotRights#a0624cf7 flags:# reply:flags.0?true read_messages:flags.1?true delete_sent_messages:flags.2?true delete_received_messages:flags.3?true edit_name:flags.4?true edit_bio:flags.5?true edit_profile_photo:flags.6?true edit_username:flags.7?true view_gifts:flags.8?true sell_gifts:flags.9?true change_gift_settings:flags.10?true transfer_and_upgrade_gifts:flags.11?true transfer_stars:flags.12?true manage_stories:flags.13?true = BusinessBotRights;
disallowedGiftsSettings#71f276c4 flags:# disallow_unlimited_stargifts:flags.0?true disallow_limited_stargifts:flags.1?true disallow_unique_stargifts:flags.2?true disallow_premium_gifts:flags.3?true = DisallowedGiftsSettings;
sponsoredPeer#c69708d3 flags:# random_id:bytes peer:Peer sponsor_info:flags.0?string additional_info:flags.1?string = SponsoredPeer;
contacts.sponsoredPeersEmpty#ea32b4b1 = contacts.SponsoredPeers;
contacts.sponsoredPeers#eb032884 peers:Vector<SponsoredPeer> chats:Vector<Chat> users:Vector<User> = contacts.SponsoredPeers;
---functions--- ---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
initConnection#c1cd5ea9 {X:Type} flags:# api_id:int device_model:string system_version:string app_version:string system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy params:flags.1?JSONValue query:!X = X; initConnection#c1cd5ea9 {X:Type} flags:# api_id:int device_model:string system_version:string app_version:string system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy params:flags.1?JSONValue query:!X = X;
@ -1476,7 +1486,6 @@ account.addNoPaidMessagesException#6f688aa7 flags:# refund_charged:flags.0?true
account.getPaidMessagesRevenue#f1266f38 user_id:InputUser = account.PaidMessagesRevenue; account.getPaidMessagesRevenue#f1266f38 user_id:InputUser = account.PaidMessagesRevenue;
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>; users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
users.getFullUser#b60f5918 id:InputUser = users.UserFull; users.getFullUser#b60f5918 id:InputUser = users.UserFull;
users.getRequirementsToContact#d89a83a3 id:Vector<InputUser> = Vector<RequirementToContact>;
contacts.getContacts#5dd69e12 hash:long = contacts.Contacts; contacts.getContacts#5dd69e12 hash:long = contacts.Contacts;
contacts.importContacts#2c800be5 contacts:Vector<InputContact> = contacts.ImportedContacts; contacts.importContacts#2c800be5 contacts:Vector<InputContact> = contacts.ImportedContacts;
contacts.deleteContacts#96a0e00 id:Vector<InputUser> = Updates; contacts.deleteContacts#96a0e00 id:Vector<InputUser> = Updates;
@ -1629,9 +1638,9 @@ messages.getFactCheck#b9cdc5ee peer:InputPeer msg_id:Vector<int> = Vector<FactCh
messages.requestMainWebView#c9e01e7b flags:# compact:flags.7?true fullscreen:flags.8?true peer:InputPeer bot:InputUser start_param:flags.1?string theme_params:flags.0?DataJSON platform:string = WebViewResult; messages.requestMainWebView#c9e01e7b flags:# compact:flags.7?true fullscreen:flags.8?true peer:InputPeer bot:InputUser start_param:flags.1?string theme_params:flags.0?DataJSON platform:string = WebViewResult;
messages.sendPaidReaction#58bbcb50 flags:# peer:InputPeer msg_id:int count:int random_id:long private:flags.0?PaidReactionPrivacy = Updates; messages.sendPaidReaction#58bbcb50 flags:# peer:InputPeer msg_id:int count:int random_id:long private:flags.0?PaidReactionPrivacy = Updates;
messages.getPaidReactionPrivacy#472455aa = Updates; messages.getPaidReactionPrivacy#472455aa = Updates;
messages.viewSponsoredMessage#673ad8f1 peer:InputPeer random_id:bytes = Bool; messages.viewSponsoredMessage#269e3643 random_id:bytes = Bool;
messages.clickSponsoredMessage#f093465 flags:# media:flags.0?true fullscreen:flags.1?true peer:InputPeer random_id:bytes = Bool; messages.clickSponsoredMessage#8235057e flags:# media:flags.0?true fullscreen:flags.1?true random_id:bytes = Bool;
messages.reportSponsoredMessage#1af3dbb8 peer:InputPeer random_id:bytes option:bytes = channels.SponsoredMessageReportResult; messages.reportSponsoredMessage#12cbf0c4 random_id:bytes option:bytes = channels.SponsoredMessageReportResult;
messages.getSponsoredMessages#9bd2f439 peer:InputPeer = messages.SponsoredMessages; messages.getSponsoredMessages#9bd2f439 peer:InputPeer = messages.SponsoredMessages;
messages.getPreparedInlineMessage#857ebdb8 bot:InputUser id:string = messages.PreparedInlineMessage; messages.getPreparedInlineMessage#857ebdb8 bot:InputUser id:string = messages.PreparedInlineMessage;
messages.reportMessagesDelivery#5a6d7395 flags:# push:flags.0?true peer:InputPeer id:Vector<int> = Bool; messages.reportMessagesDelivery#5a6d7395 flags:# push:flags.0?true peer:InputPeer id:Vector<int> = Bool;

View File

@ -185,6 +185,8 @@ messageActionGiftStars#45d5b021 flags:# currency:string amount:long stars:long c
messageActionPrizeStars#b00c47a2 flags:# unclaimed:flags.0?true stars:long transaction_id:string boost_peer:Peer giveaway_msg_id:int = MessageAction; messageActionPrizeStars#b00c47a2 flags:# unclaimed:flags.0?true stars:long transaction_id:string boost_peer:Peer giveaway_msg_id:int = MessageAction;
messageActionStarGift#4717e8a4 flags:# name_hidden:flags.0?true saved:flags.2?true converted:flags.3?true upgraded:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true gift:StarGift message:flags.1?TextWithEntities convert_stars:flags.4?long upgrade_msg_id:flags.5?int upgrade_stars:flags.8?long from_id:flags.11?Peer peer:flags.12?Peer saved_id:flags.12?long = MessageAction; messageActionStarGift#4717e8a4 flags:# name_hidden:flags.0?true saved:flags.2?true converted:flags.3?true upgraded:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true gift:StarGift message:flags.1?TextWithEntities convert_stars:flags.4?long upgrade_msg_id:flags.5?int upgrade_stars:flags.8?long from_id:flags.11?Peer peer:flags.12?Peer saved_id:flags.12?long = MessageAction;
messageActionStarGiftUnique#acdfcb81 flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long from_id:flags.6?Peer peer:flags.7?Peer saved_id:flags.7?long = MessageAction; messageActionStarGiftUnique#acdfcb81 flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long from_id:flags.6?Peer peer:flags.7?Peer saved_id:flags.7?long = MessageAction;
messageActionPaidMessagesRefunded#ac1f1fcd count:int stars:long = MessageAction;
messageActionPaidMessagesPrice#bcd71419 stars:long = MessageAction;
dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true view_forum_as_messages:flags.6?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog; dialog#d58a08c6 flags:# pinned:flags.2?true unread_mark:flags.3?true view_forum_as_messages:flags.6?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog;
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog; dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
@ -204,6 +206,7 @@ geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radiu
auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode; auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode;
auth.sentCodeSuccess#2390fe44 authorization:auth.Authorization = auth.SentCode; auth.sentCodeSuccess#2390fe44 authorization:auth.Authorization = auth.SentCode;
auth.sentCodePaymentRequired#d7cef980 store_product:string phone_code_hash:string = auth.SentCode;
auth.authorization#2ea2c0d4 flags:# setup_password_required:flags.1?true otherwise_relogin_days:flags.1?int tmp_sessions:flags.0?int future_auth_token:flags.2?bytes user:User = auth.Authorization; auth.authorization#2ea2c0d4 flags:# setup_password_required:flags.1?true otherwise_relogin_days:flags.1?int tmp_sessions:flags.0?int future_auth_token:flags.2?bytes user:User = auth.Authorization;
auth.authorizationSignUpRequired#44747e9a flags:# terms_of_service:flags.0?help.TermsOfService = auth.Authorization; auth.authorizationSignUpRequired#44747e9a flags:# terms_of_service:flags.0?help.TermsOfService = auth.Authorization;
@ -236,7 +239,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason;
inputReportReasonIllegalDrugs#a8eb2be = ReportReason; inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
inputReportReasonPersonalDetails#9ec7863d = ReportReason; inputReportReasonPersonalDetails#9ec7863d = ReportReason;
userFull#d2234ea0 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long = UserFull; userFull#99e78045 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true display_gifts_button:flags2.16?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long disallowed_gifts:flags2.15?DisallowedGiftsSettings = UserFull;
contact#145ade0b user_id:long mutual:Bool = Contact; contact#145ade0b user_id:long mutual:Bool = Contact;
@ -427,6 +430,7 @@ updateBusinessBotCallbackQuery#1ea2fda7 flags:# query_id:long user_id:long conne
updateStarsRevenueStatus#a584b019 peer:Peer status:StarsRevenueStatus = Update; updateStarsRevenueStatus#a584b019 peer:Peer status:StarsRevenueStatus = Update;
updateBotPurchasedPaidMedia#283bd312 user_id:long payload:string qts:int = Update; updateBotPurchasedPaidMedia#283bd312 user_id:long payload:string qts:int = Update;
updatePaidReactionPrivacy#8b725fce private:PaidReactionPrivacy = Update; updatePaidReactionPrivacy#8b725fce private:PaidReactionPrivacy = Update;
updateSentPhoneCode#504aa18f sent_code:auth.SentCode = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@ -897,7 +901,6 @@ phoneCallDiscardReasonMissed#85e42301 = PhoneCallDiscardReason;
phoneCallDiscardReasonDisconnect#e095c1a0 = PhoneCallDiscardReason; phoneCallDiscardReasonDisconnect#e095c1a0 = PhoneCallDiscardReason;
phoneCallDiscardReasonHangup#57adc690 = PhoneCallDiscardReason; phoneCallDiscardReasonHangup#57adc690 = PhoneCallDiscardReason;
phoneCallDiscardReasonBusy#faf7e8c9 = PhoneCallDiscardReason; phoneCallDiscardReasonBusy#faf7e8c9 = PhoneCallDiscardReason;
phoneCallDiscardReasonAllowGroupCall#afe2b839 encrypted_key:bytes = PhoneCallDiscardReason;
dataJSON#7d748d04 data:string = DataJSON; dataJSON#7d748d04 data:string = DataJSON;
@ -1311,7 +1314,7 @@ statsGroupTopInviter#535f779d user_id:long invitations:int = StatsGroupTopInvite
stats.megagroupStats#ef7ff916 period:StatsDateRangeDays members:StatsAbsValueAndPrev messages:StatsAbsValueAndPrev viewers:StatsAbsValueAndPrev posters:StatsAbsValueAndPrev growth_graph:StatsGraph members_graph:StatsGraph new_members_by_source_graph:StatsGraph languages_graph:StatsGraph messages_graph:StatsGraph actions_graph:StatsGraph top_hours_graph:StatsGraph weekdays_graph:StatsGraph top_posters:Vector<StatsGroupTopPoster> top_admins:Vector<StatsGroupTopAdmin> top_inviters:Vector<StatsGroupTopInviter> users:Vector<User> = stats.MegagroupStats; stats.megagroupStats#ef7ff916 period:StatsDateRangeDays members:StatsAbsValueAndPrev messages:StatsAbsValueAndPrev viewers:StatsAbsValueAndPrev posters:StatsAbsValueAndPrev growth_graph:StatsGraph members_graph:StatsGraph new_members_by_source_graph:StatsGraph languages_graph:StatsGraph messages_graph:StatsGraph actions_graph:StatsGraph top_hours_graph:StatsGraph weekdays_graph:StatsGraph top_posters:Vector<StatsGroupTopPoster> top_admins:Vector<StatsGroupTopAdmin> top_inviters:Vector<StatsGroupTopInviter> users:Vector<User> = stats.MegagroupStats;
globalPrivacySettings#c9d8df1c flags:# archive_and_mute_new_noncontact_peers:flags.0?true keep_archived_unmuted:flags.1?true keep_archived_folders:flags.2?true hide_read_marks:flags.3?true new_noncontact_peers_require_premium:flags.4?true noncontact_peers_paid_stars:flags.5?long = GlobalPrivacySettings; globalPrivacySettings#fe41b34f flags:# archive_and_mute_new_noncontact_peers:flags.0?true keep_archived_unmuted:flags.1?true keep_archived_folders:flags.2?true hide_read_marks:flags.3?true new_noncontact_peers_require_premium:flags.4?true display_gifts_button:flags.7?true noncontact_peers_paid_stars:flags.5?long disallowed_gifts:flags.6?DisallowedGiftsSettings = GlobalPrivacySettings;
help.countryCode#4203c5ef flags:# country_code:string prefixes:flags.0?Vector<string> patterns:flags.1?Vector<string> = help.CountryCode; help.countryCode#4203c5ef flags:# country_code:string prefixes:flags.0?Vector<string> patterns:flags.1?Vector<string> = help.CountryCode;
@ -1481,6 +1484,7 @@ inputInvoiceStarGift#e8625e92 flags:# hide_name:flags.0?true include_upgrade:fla
inputInvoiceStarGiftUpgrade#4d818d5d flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = InputInvoice; inputInvoiceStarGiftUpgrade#4d818d5d flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = InputInvoice;
inputInvoiceStarGiftTransfer#4a5f5bd9 stargift:InputSavedStarGift to_id:InputPeer = InputInvoice; inputInvoiceStarGiftTransfer#4a5f5bd9 stargift:InputSavedStarGift to_id:InputPeer = InputInvoice;
inputInvoicePremiumGiftStars#dabab2ef flags:# user_id:InputUser months:int message:flags.0?TextWithEntities = InputInvoice; inputInvoicePremiumGiftStars#dabab2ef flags:# user_id:InputUser months:int message:flags.0?TextWithEntities = InputInvoice;
inputInvoiceBusinessBotTransferStars#f4997e42 bot:InputUser stars:long = InputInvoice;
payments.exportedInvoice#aed0cbd9 url:string = payments.ExportedInvoice; payments.exportedInvoice#aed0cbd9 url:string = payments.ExportedInvoice;
@ -1495,6 +1499,7 @@ inputStorePaymentPremiumGiveaway#160544ca flags:# only_new_subscribers:flags.0?t
inputStorePaymentStarsTopup#dddd0f56 stars:long currency:string amount:long = InputStorePaymentPurpose; inputStorePaymentStarsTopup#dddd0f56 stars:long currency:string amount:long = InputStorePaymentPurpose;
inputStorePaymentStarsGift#1d741ef7 user_id:InputUser stars:long currency:string amount:long = InputStorePaymentPurpose; inputStorePaymentStarsGift#1d741ef7 user_id:InputUser stars:long currency:string amount:long = InputStorePaymentPurpose;
inputStorePaymentStarsGiveaway#751f08fa flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.3?true stars:long boost_peer:InputPeer additional_peers:flags.1?Vector<InputPeer> countries_iso2:flags.2?Vector<string> prize_description:flags.4?string random_id:long until_date:int currency:string amount:long users:int = InputStorePaymentPurpose; inputStorePaymentStarsGiveaway#751f08fa flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.3?true stars:long boost_peer:InputPeer additional_peers:flags.1?Vector<InputPeer> countries_iso2:flags.2?Vector<string> prize_description:flags.4?string random_id:long until_date:int currency:string amount:long users:int = InputStorePaymentPurpose;
inputStorePaymentAuthCode#9bb2636d flags:# restore:flags.0?true phone_number:string phone_code_hash:string currency:string amount:long = InputStorePaymentPurpose;
paymentFormMethod#88f8f21b url:string title:string = PaymentFormMethod; paymentFormMethod#88f8f21b url:string title:string = PaymentFormMethod;
@ -1753,7 +1758,7 @@ inputQuickReplyShortcutId#1190cf1 shortcut_id:int = InputQuickReplyShortcut;
messages.quickReplies#c68d6695 quick_replies:Vector<QuickReply> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.QuickReplies; messages.quickReplies#c68d6695 quick_replies:Vector<QuickReply> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.QuickReplies;
messages.quickRepliesNotModified#5f91eb5b = messages.QuickReplies; messages.quickRepliesNotModified#5f91eb5b = messages.QuickReplies;
connectedBot#bd068601 flags:# can_reply:flags.0?true bot_id:long recipients:BusinessBotRecipients = ConnectedBot; connectedBot#cd64636c flags:# bot_id:long recipients:BusinessBotRecipients rights:BusinessBotRights = ConnectedBot;
account.connectedBots#17d7f87b connected_bots:Vector<ConnectedBot> users:Vector<User> = account.ConnectedBots; account.connectedBots#17d7f87b connected_bots:Vector<ConnectedBot> users:Vector<User> = account.ConnectedBots;
@ -1761,7 +1766,7 @@ messages.dialogFilters#2ad93719 flags:# tags_enabled:flags.0?true filters:Vector
birthday#6c8e1e06 flags:# day:int month:int year:flags.0?int = Birthday; birthday#6c8e1e06 flags:# day:int month:int year:flags.0?int = Birthday;
botBusinessConnection#896433b4 flags:# can_reply:flags.0?true disabled:flags.1?true connection_id:string user_id:long dc_id:int date:int = BotBusinessConnection; botBusinessConnection#8f34b2f5 flags:# disabled:flags.1?true connection_id:string user_id:long dc_id:int date:int rights:flags.2?BusinessBotRights = BotBusinessConnection;
inputBusinessIntro#9c469cd flags:# title:string description:string sticker:flags.0?InputDocument = InputBusinessIntro; inputBusinessIntro#9c469cd flags:# title:string description:string sticker:flags.0?InputDocument = InputBusinessIntro;
@ -1945,6 +1950,15 @@ requirementToContactEmpty#50a9839 = RequirementToContact;
requirementToContactPremium#e581e4e9 = RequirementToContact; requirementToContactPremium#e581e4e9 = RequirementToContact;
requirementToContactPaidMessages#b4f67e93 stars_amount:long = RequirementToContact; requirementToContactPaidMessages#b4f67e93 stars_amount:long = RequirementToContact;
businessBotRights#a0624cf7 flags:# reply:flags.0?true read_messages:flags.1?true delete_sent_messages:flags.2?true delete_received_messages:flags.3?true edit_name:flags.4?true edit_bio:flags.5?true edit_profile_photo:flags.6?true edit_username:flags.7?true view_gifts:flags.8?true sell_gifts:flags.9?true change_gift_settings:flags.10?true transfer_and_upgrade_gifts:flags.11?true transfer_stars:flags.12?true manage_stories:flags.13?true = BusinessBotRights;
disallowedGiftsSettings#71f276c4 flags:# disallow_unlimited_stargifts:flags.0?true disallow_limited_stargifts:flags.1?true disallow_unique_stargifts:flags.2?true disallow_premium_gifts:flags.3?true = DisallowedGiftsSettings;
sponsoredPeer#c69708d3 flags:# random_id:bytes peer:Peer sponsor_info:flags.0?string additional_info:flags.1?string = SponsoredPeer;
contacts.sponsoredPeersEmpty#ea32b4b1 = contacts.SponsoredPeers;
contacts.sponsoredPeers#eb032884 peers:Vector<SponsoredPeer> chats:Vector<Chat> users:Vector<User> = contacts.SponsoredPeers;
---functions--- ---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -1956,7 +1970,7 @@ invokeWithMessagesRange#365275f2 {X:Type} range:MessageRange query:!X = X;
invokeWithTakeout#aca9fd2e {X:Type} takeout_id:long query:!X = X; invokeWithTakeout#aca9fd2e {X:Type} takeout_id:long query:!X = X;
invokeWithBusinessConnection#dd289f8e {X:Type} connection_id:string query:!X = X; invokeWithBusinessConnection#dd289f8e {X:Type} connection_id:string query:!X = X;
invokeWithGooglePlayIntegrity#1df92984 {X:Type} nonce:string token:string query:!X = X; invokeWithGooglePlayIntegrity#1df92984 {X:Type} nonce:string token:string query:!X = X;
invokeWithApnsSecret#dae54f8 {X:Type} nonce:string secret:string query:!X = X; invokeWithApnsSecret#0dae54f8 {X:Type} nonce:string secret:string query:!X = X;
invokeWithReCaptcha#adbb0f94 {X:Type} token:string query:!X = X; invokeWithReCaptcha#adbb0f94 {X:Type} token:string query:!X = X;
auth.sendCode#a677244f phone_number:string api_id:int api_hash:string settings:CodeSettings = auth.SentCode; auth.sendCode#a677244f phone_number:string api_id:int api_hash:string settings:CodeSettings = auth.SentCode;
@ -2079,7 +2093,7 @@ account.updateBusinessWorkHours#4b00e066 flags:# business_work_hours:flags.0?Bus
account.updateBusinessLocation#9e6b131a flags:# geo_point:flags.1?InputGeoPoint address:flags.0?string = Bool; account.updateBusinessLocation#9e6b131a flags:# geo_point:flags.1?InputGeoPoint address:flags.0?string = Bool;
account.updateBusinessGreetingMessage#66cdafc4 flags:# message:flags.0?InputBusinessGreetingMessage = Bool; account.updateBusinessGreetingMessage#66cdafc4 flags:# message:flags.0?InputBusinessGreetingMessage = Bool;
account.updateBusinessAwayMessage#a26a7fa5 flags:# message:flags.0?InputBusinessAwayMessage = Bool; account.updateBusinessAwayMessage#a26a7fa5 flags:# message:flags.0?InputBusinessAwayMessage = Bool;
account.updateConnectedBot#43d8521d flags:# can_reply:flags.0?true deleted:flags.1?true bot:InputUser recipients:InputBusinessBotRecipients = Updates; account.updateConnectedBot#66a08c7e flags:# deleted:flags.1?true rights:flags.0?BusinessBotRights bot:InputUser recipients:InputBusinessBotRecipients = Updates;
account.getConnectedBots#4ea4c80f = account.ConnectedBots; account.getConnectedBots#4ea4c80f = account.ConnectedBots;
account.getBotBusinessConnection#76a86270 connection_id:string = Updates; account.getBotBusinessConnection#76a86270 connection_id:string = Updates;
account.updateBusinessIntro#a614d034 flags:# intro:flags.0?InputBusinessIntro = Bool; account.updateBusinessIntro#a614d034 flags:# intro:flags.0?InputBusinessIntro = Bool;
@ -2130,6 +2144,7 @@ contacts.importContactToken#13005788 token:string = User;
contacts.editCloseFriends#ba6705f0 id:Vector<long> = Bool; contacts.editCloseFriends#ba6705f0 id:Vector<long> = Bool;
contacts.setBlocked#94c65c76 flags:# my_stories_from:flags.0?true id:Vector<InputPeer> limit:int = Bool; contacts.setBlocked#94c65c76 flags:# my_stories_from:flags.0?true id:Vector<InputPeer> limit:int = Bool;
contacts.getBirthdays#daeda864 = contacts.ContactBirthdays; contacts.getBirthdays#daeda864 = contacts.ContactBirthdays;
contacts.getSponsoredPeers#b6c8c393 q:string = contacts.SponsoredPeers;
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages; messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
messages.getDialogs#a0f4cb4f flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:long = messages.Dialogs; messages.getDialogs#a0f4cb4f flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:long = messages.Dialogs;
@ -2348,9 +2363,9 @@ messages.requestMainWebView#c9e01e7b flags:# compact:flags.7?true fullscreen:fla
messages.sendPaidReaction#58bbcb50 flags:# peer:InputPeer msg_id:int count:int random_id:long private:flags.0?PaidReactionPrivacy = Updates; messages.sendPaidReaction#58bbcb50 flags:# peer:InputPeer msg_id:int count:int random_id:long private:flags.0?PaidReactionPrivacy = Updates;
messages.togglePaidReactionPrivacy#435885b5 peer:InputPeer msg_id:int private:PaidReactionPrivacy = Bool; messages.togglePaidReactionPrivacy#435885b5 peer:InputPeer msg_id:int private:PaidReactionPrivacy = Bool;
messages.getPaidReactionPrivacy#472455aa = Updates; messages.getPaidReactionPrivacy#472455aa = Updates;
messages.viewSponsoredMessage#673ad8f1 peer:InputPeer random_id:bytes = Bool; messages.viewSponsoredMessage#269e3643 random_id:bytes = Bool;
messages.clickSponsoredMessage#f093465 flags:# media:flags.0?true fullscreen:flags.1?true peer:InputPeer random_id:bytes = Bool; messages.clickSponsoredMessage#8235057e flags:# media:flags.0?true fullscreen:flags.1?true random_id:bytes = Bool;
messages.reportSponsoredMessage#1af3dbb8 peer:InputPeer random_id:bytes option:bytes = channels.SponsoredMessageReportResult; messages.reportSponsoredMessage#12cbf0c4 random_id:bytes option:bytes = channels.SponsoredMessageReportResult;
messages.getSponsoredMessages#9bd2f439 peer:InputPeer = messages.SponsoredMessages; messages.getSponsoredMessages#9bd2f439 peer:InputPeer = messages.SponsoredMessages;
messages.savePreparedInlineMessage#f21f7f2f flags:# result:InputBotInlineResult user_id:InputUser peer_types:flags.0?Vector<InlineQueryPeerType> = messages.BotPreparedInlineMessage; messages.savePreparedInlineMessage#f21f7f2f flags:# result:InputBotInlineResult user_id:InputUser peer_types:flags.0?Vector<InlineQueryPeerType> = messages.BotPreparedInlineMessage;
messages.getPreparedInlineMessage#857ebdb8 bot:InputUser id:string = messages.PreparedInlineMessage; messages.getPreparedInlineMessage#857ebdb8 bot:InputUser id:string = messages.PreparedInlineMessage;
@ -2506,7 +2521,6 @@ payments.getBankCardData#2e79d779 number:string = payments.BankCardData;
payments.exportInvoice#f91b065 invoice_media:InputMedia = payments.ExportedInvoice; payments.exportInvoice#f91b065 invoice_media:InputMedia = payments.ExportedInvoice;
payments.assignAppStoreTransaction#80ed747d receipt:bytes purpose:InputStorePaymentPurpose = Updates; payments.assignAppStoreTransaction#80ed747d receipt:bytes purpose:InputStorePaymentPurpose = Updates;
payments.assignPlayMarketTransaction#dffd50d3 receipt:DataJSON purpose:InputStorePaymentPurpose = Updates; payments.assignPlayMarketTransaction#dffd50d3 receipt:DataJSON purpose:InputStorePaymentPurpose = Updates;
payments.canPurchasePremium#9fc19eb6 purpose:InputStorePaymentPurpose = Bool;
payments.getPremiumGiftCodeOptions#2757ba54 flags:# boost_peer:flags.0?InputPeer = Vector<PremiumGiftCodeOption>; payments.getPremiumGiftCodeOptions#2757ba54 flags:# boost_peer:flags.0?InputPeer = Vector<PremiumGiftCodeOption>;
payments.checkGiftCode#8e51b4c1 slug:string = payments.CheckedGiftCode; payments.checkGiftCode#8e51b4c1 slug:string = payments.CheckedGiftCode;
payments.applyGiftCode#f6e26854 slug:string = Updates; payments.applyGiftCode#f6e26854 slug:string = Updates;
@ -2544,6 +2558,7 @@ payments.getSavedStarGift#b455a106 stargift:Vector<InputSavedStarGift> = payment
payments.getStarGiftWithdrawalUrl#d06e93a8 stargift:InputSavedStarGift password:InputCheckPasswordSRP = payments.StarGiftWithdrawalUrl; payments.getStarGiftWithdrawalUrl#d06e93a8 stargift:InputSavedStarGift password:InputCheckPasswordSRP = payments.StarGiftWithdrawalUrl;
payments.toggleChatStarGiftNotifications#60eaefa1 flags:# enabled:flags.0?true peer:InputPeer = Bool; payments.toggleChatStarGiftNotifications#60eaefa1 flags:# enabled:flags.0?true peer:InputPeer = Bool;
payments.toggleStarGiftsPinnedToTop#1513e7b0 peer:InputPeer stargift:Vector<InputSavedStarGift> = Bool; payments.toggleStarGiftsPinnedToTop#1513e7b0 peer:InputPeer stargift:Vector<InputSavedStarGift> = Bool;
payments.canPurchaseStore#4fdc5ea7 purpose:InputStorePaymentPurpose = Bool;
stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true emojis:flags.5?true text_color:flags.6?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector<InputStickerSetItem> software:flags.3?string = messages.StickerSet; stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true emojis:flags.5?true text_color:flags.6?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector<InputStickerSetItem> software:flags.3?string = messages.StickerSet;
stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet; stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;

View File

@ -127,168 +127,169 @@ $icons-map: (
"forums": "\f15a", "forums": "\f15a",
"forward": "\f15b", "forward": "\f15b",
"fragment": "\f15c", "fragment": "\f15c",
"fullscreen": "\f15d", "frozen-time": "\f15d",
"gifs": "\f15e", "fullscreen": "\f15e",
"gift": "\f15f", "gifs": "\f15f",
"group-filled": "\f160", "gift": "\f160",
"group": "\f161", "group-filled": "\f161",
"grouped-disable": "\f162", "group": "\f162",
"grouped": "\f163", "grouped-disable": "\f163",
"hand-stop": "\f164", "grouped": "\f164",
"hashtag": "\f165", "hand-stop": "\f165",
"heart-outline": "\f166", "hashtag": "\f166",
"heart": "\f167", "heart-outline": "\f167",
"help": "\f168", "heart": "\f168",
"info-filled": "\f169", "help": "\f169",
"info": "\f16a", "info-filled": "\f16a",
"install": "\f16b", "info": "\f16b",
"italic": "\f16c", "install": "\f16c",
"key": "\f16d", "italic": "\f16d",
"keyboard": "\f16e", "key": "\f16e",
"lamp": "\f16f", "keyboard": "\f16f",
"language": "\f170", "lamp": "\f170",
"large-pause": "\f171", "language": "\f171",
"large-play": "\f172", "large-pause": "\f172",
"link-badge": "\f173", "large-play": "\f173",
"link-broken": "\f174", "link-badge": "\f174",
"link": "\f175", "link-broken": "\f175",
"location": "\f176", "link": "\f176",
"lock-badge": "\f177", "location": "\f177",
"lock": "\f178", "lock-badge": "\f178",
"logout": "\f179", "lock": "\f179",
"loop": "\f17a", "logout": "\f17a",
"mention": "\f17b", "loop": "\f17b",
"message-failed": "\f17c", "mention": "\f17c",
"message-pending": "\f17d", "message-failed": "\f17d",
"message-read": "\f17e", "message-pending": "\f17e",
"message-succeeded": "\f17f", "message-read": "\f17f",
"message": "\f180", "message-succeeded": "\f180",
"microphone-alt": "\f181", "message": "\f181",
"microphone": "\f182", "microphone-alt": "\f182",
"monospace": "\f183", "microphone": "\f183",
"more-circle": "\f184", "monospace": "\f184",
"more": "\f185", "more-circle": "\f185",
"move-caption-down": "\f186", "more": "\f186",
"move-caption-up": "\f187", "move-caption-down": "\f187",
"mute": "\f188", "move-caption-up": "\f188",
"muted": "\f189", "mute": "\f189",
"my-notes": "\f18a", "muted": "\f18a",
"new-chat-filled": "\f18b", "my-notes": "\f18b",
"next": "\f18c", "new-chat-filled": "\f18c",
"nochannel": "\f18d", "next": "\f18d",
"noise-suppression": "\f18e", "nochannel": "\f18e",
"non-contacts": "\f18f", "noise-suppression": "\f18f",
"one-filled": "\f190", "non-contacts": "\f190",
"open-in-new-tab": "\f191", "one-filled": "\f191",
"password-off": "\f192", "open-in-new-tab": "\f192",
"pause": "\f193", "password-off": "\f193",
"permissions": "\f194", "pause": "\f194",
"phone-discard-outline": "\f195", "permissions": "\f195",
"phone-discard": "\f196", "phone-discard-outline": "\f196",
"phone": "\f197", "phone-discard": "\f197",
"photo": "\f198", "phone": "\f198",
"pin-badge": "\f199", "photo": "\f199",
"pin-list": "\f19a", "pin-badge": "\f19a",
"pin": "\f19b", "pin-list": "\f19b",
"pinned-chat": "\f19c", "pin": "\f19c",
"pinned-message": "\f19d", "pinned-chat": "\f19d",
"pip": "\f19e", "pinned-message": "\f19e",
"play-story": "\f19f", "pip": "\f19f",
"play": "\f1a0", "play-story": "\f1a0",
"poll": "\f1a1", "play": "\f1a1",
"previous": "\f1a2", "poll": "\f1a2",
"privacy-policy": "\f1a3", "previous": "\f1a3",
"proof-of-ownership": "\f1a4", "privacy-policy": "\f1a4",
"quote-text": "\f1a5", "proof-of-ownership": "\f1a5",
"quote": "\f1a6", "quote-text": "\f1a6",
"radial-badge": "\f1a7", "quote": "\f1a7",
"readchats": "\f1a8", "radial-badge": "\f1a8",
"recent": "\f1a9", "readchats": "\f1a9",
"reload": "\f1aa", "recent": "\f1aa",
"remove-quote": "\f1ab", "reload": "\f1ab",
"remove": "\f1ac", "remove-quote": "\f1ac",
"reopen-topic": "\f1ad", "remove": "\f1ad",
"replace": "\f1ae", "reopen-topic": "\f1ae",
"replies": "\f1af", "replace": "\f1af",
"reply-filled": "\f1b0", "replies": "\f1b0",
"reply": "\f1b1", "reply-filled": "\f1b1",
"revenue-split": "\f1b2", "reply": "\f1b2",
"revote": "\f1b3", "revenue-split": "\f1b3",
"save-story": "\f1b4", "revote": "\f1b4",
"saved-messages": "\f1b5", "save-story": "\f1b5",
"schedule": "\f1b6", "saved-messages": "\f1b6",
"search": "\f1b7", "schedule": "\f1b7",
"select": "\f1b8", "search": "\f1b8",
"send-outline": "\f1b9", "select": "\f1b9",
"send": "\f1ba", "send-outline": "\f1ba",
"settings-filled": "\f1bb", "send": "\f1bb",
"settings": "\f1bc", "settings-filled": "\f1bc",
"share-filled": "\f1bd", "settings": "\f1bd",
"share-screen-outlined": "\f1be", "share-filled": "\f1be",
"share-screen-stop": "\f1bf", "share-screen-outlined": "\f1bf",
"share-screen": "\f1c0", "share-screen-stop": "\f1c0",
"show-message": "\f1c1", "share-screen": "\f1c1",
"sidebar": "\f1c2", "show-message": "\f1c2",
"skip-next": "\f1c3", "sidebar": "\f1c3",
"skip-previous": "\f1c4", "skip-next": "\f1c4",
"smallscreen": "\f1c5", "skip-previous": "\f1c5",
"smile": "\f1c6", "smallscreen": "\f1c6",
"sort": "\f1c7", "smile": "\f1c7",
"speaker-muted-story": "\f1c8", "sort": "\f1c8",
"speaker-outline": "\f1c9", "speaker-muted-story": "\f1c9",
"speaker-story": "\f1ca", "speaker-outline": "\f1ca",
"speaker": "\f1cb", "speaker-story": "\f1cb",
"spoiler-disable": "\f1cc", "speaker": "\f1cc",
"spoiler": "\f1cd", "spoiler-disable": "\f1cd",
"sport": "\f1ce", "spoiler": "\f1ce",
"star": "\f1cf", "sport": "\f1cf",
"stars-lock": "\f1d0", "star": "\f1d0",
"stats": "\f1d1", "stars-lock": "\f1d1",
"stealth-future": "\f1d2", "stats": "\f1d2",
"stealth-past": "\f1d3", "stealth-future": "\f1d3",
"stickers": "\f1d4", "stealth-past": "\f1d4",
"stop-raising-hand": "\f1d5", "stickers": "\f1d5",
"stop": "\f1d6", "stop-raising-hand": "\f1d6",
"story-caption": "\f1d7", "stop": "\f1d7",
"story-expired": "\f1d8", "story-caption": "\f1d8",
"story-priority": "\f1d9", "story-expired": "\f1d9",
"story-reply": "\f1da", "story-priority": "\f1da",
"strikethrough": "\f1db", "story-reply": "\f1db",
"tag-add": "\f1dc", "strikethrough": "\f1dc",
"tag-crossed": "\f1dd", "tag-add": "\f1dd",
"tag-filter": "\f1de", "tag-crossed": "\f1de",
"tag-name": "\f1df", "tag-filter": "\f1df",
"tag": "\f1e0", "tag-name": "\f1e0",
"timer": "\f1e1", "tag": "\f1e1",
"toncoin": "\f1e2", "timer": "\f1e2",
"trade": "\f1e3", "toncoin": "\f1e3",
"transcribe": "\f1e4", "trade": "\f1e4",
"truck": "\f1e5", "transcribe": "\f1e5",
"unarchive": "\f1e6", "truck": "\f1e6",
"underlined": "\f1e7", "unarchive": "\f1e7",
"unique-profile": "\f1e8", "underlined": "\f1e8",
"unlock-badge": "\f1e9", "unique-profile": "\f1e9",
"unlock": "\f1ea", "unlock-badge": "\f1ea",
"unmute": "\f1eb", "unlock": "\f1eb",
"unpin": "\f1ec", "unmute": "\f1ec",
"unread": "\f1ed", "unpin": "\f1ed",
"up": "\f1ee", "unread": "\f1ee",
"user-filled": "\f1ef", "up": "\f1ef",
"user-online": "\f1f0", "user-filled": "\f1f0",
"user": "\f1f1", "user-online": "\f1f1",
"video-outlined": "\f1f2", "user": "\f1f2",
"video-stop": "\f1f3", "video-outlined": "\f1f3",
"video": "\f1f4", "video-stop": "\f1f4",
"view-once": "\f1f5", "video": "\f1f5",
"voice-chat": "\f1f6", "view-once": "\f1f6",
"volume-1": "\f1f7", "voice-chat": "\f1f7",
"volume-2": "\f1f8", "volume-1": "\f1f8",
"volume-3": "\f1f9", "volume-2": "\f1f9",
"web": "\f1fa", "volume-3": "\f1fa",
"webapp": "\f1fb", "web": "\f1fb",
"word-wrap": "\f1fc", "webapp": "\f1fc",
"zoom-in": "\f1fd", "word-wrap": "\f1fd",
"zoom-out": "\f1fe", "zoom-in": "\f1fe",
"zoom-out": "\f1ff",
); );
.icon-active-sessions::before { .icon-active-sessions::before {
@ -567,6 +568,9 @@ $icons-map: (
.icon-fragment::before { .icon-fragment::before {
content: map.get($icons-map, "fragment"); content: map.get($icons-map, "fragment");
} }
.icon-frozen-time::before {
content: map.get($icons-map, "frozen-time");
}
.icon-fullscreen::before { .icon-fullscreen::before {
content: map.get($icons-map, "fullscreen"); content: map.get($icons-map, "fullscreen");
} }

Binary file not shown.

Binary file not shown.

View File

@ -91,6 +91,7 @@ export type FontIconName =
| 'forums' | 'forums'
| 'forward' | 'forward'
| 'fragment' | 'fragment'
| 'frozen-time'
| 'fullscreen' | 'fullscreen'
| 'gifs' | 'gifs'
| 'gift' | 'gift'

View File

@ -1458,9 +1458,24 @@ export interface LangPair {
'StoryTooltipReactionSent': undefined; 'StoryTooltipReactionSent': undefined;
'StarsNeededTextSendPaidMessages': undefined; 'StarsNeededTextSendPaidMessages': undefined;
'PaidMessageTransactionTotal': undefined; 'PaidMessageTransactionTotal': undefined;
'TitleFrozenAccount': undefined;
'SubtitleFrozenAccount': undefined;
'ComposerTitleFrozenAccount': undefined;
'ComposerSubtitleFrozenAccount': undefined;
'DescriptionRestrictedMedia': undefined; 'DescriptionRestrictedMedia': undefined;
'DescriptionScheduledPaidMediaNotAllowed': undefined; 'DescriptionScheduledPaidMediaNotAllowed': undefined;
'DescriptionScheduledPaidMessagesNotAllowed': undefined; 'DescriptionScheduledPaidMessagesNotAllowed': undefined;
'FrozenAccountModalTitle': undefined;
'FrozenAccountViolationTitle': undefined;
'FrozenAccountViolationSubtitle': undefined;
'FrozenAccountReadOnlyTitle': undefined;
'FrozenAccountReadOnlySubtitle': undefined;
'FrozenAccountAppealTitle': undefined;
'ButtonAppeal': undefined;
'ButtonUnderstood': undefined;
'ActionPaidMessageGroupPriceFree': undefined;
'NotificationTitleNotSupportedInFrozenAccount': undefined;
'NotificationMessageNotSupportedInFrozenAccount': undefined;
} }
export interface LangPairWithVariables<V extends unknown = LangVariable> { export interface LangPairWithVariables<V extends unknown = LangVariable> {
@ -2346,6 +2361,21 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
'PaidMessageTransactionDescription': { 'PaidMessageTransactionDescription': {
'percent': V; 'percent': V;
}; };
'FrozenAccountAppealSubtitle': {
'botLink': V;
'date': V;
};
'ActionPaidMessageGroupPrice': {
'stars': V;
};
'ApiMessageActionPaidMessagesRefundedOutgoing': {
'stars': V;
'user': V;
};
'ApiMessageActionPaidMessagesRefundedIncoming': {
'user': V;
'stars': V;
};
} }
export interface LangPairPlural { export interface LangPairPlural {

View File

@ -147,6 +147,14 @@ export function tryParseDeepLink(link: string): DeepLink | undefined {
} }
} }
export function getUsernameFromDeepLink(url: string) {
const deepLink = tryParseDeepLink(url);
if (deepLink?.type === 'publicUsernameOrBotLink') {
return deepLink.username;
}
return undefined;
}
function parseDeepLink(url: string) { function parseDeepLink(url: string) {
const correctUrl = ensureProtocol(url); const correctUrl = ensureProtocol(url);
if (!correctUrl) { if (!correctUrl) {