Chat: Fix restriction validation (#6078)
Co-authored-by: Dmitry Kabanov <dmitrykabanovdev@gmail.com>
This commit is contained in:
parent
6e69765a51
commit
9857dc0ec7
@ -120,6 +120,11 @@ export interface GramJsAppConfig extends LimitsConfig {
|
|||||||
todo_items_max?: number;
|
todo_items_max?: number;
|
||||||
todo_title_length_max?: number;
|
todo_title_length_max?: number;
|
||||||
todo_item_length_max?: number;
|
todo_item_length_max?: number;
|
||||||
|
ignore_restriction_reasons?: string[];
|
||||||
|
need_age_video_verification?: boolean;
|
||||||
|
verify_age_bot_username?: string;
|
||||||
|
verify_age_country?: string;
|
||||||
|
verify_age_min?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildEmojiSounds(appConfig: GramJsAppConfig) {
|
function buildEmojiSounds(appConfig: GramJsAppConfig) {
|
||||||
@ -235,5 +240,10 @@ export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiApp
|
|||||||
todoItemsMax: appConfig.todo_items_max ?? TODO_ITEMS_LIMIT,
|
todoItemsMax: appConfig.todo_items_max ?? TODO_ITEMS_LIMIT,
|
||||||
todoTitleLengthMax: appConfig.todo_title_length_max ?? TODO_TITLE_LENGTH_LIMIT,
|
todoTitleLengthMax: appConfig.todo_title_length_max ?? TODO_TITLE_LENGTH_LIMIT,
|
||||||
todoItemLengthMax: appConfig.todo_item_length_max ?? TODO_ITEM_LENGTH_LIMIT,
|
todoItemLengthMax: appConfig.todo_item_length_max ?? TODO_ITEM_LENGTH_LIMIT,
|
||||||
|
ignoreRestrictionReasons: appConfig.ignore_restriction_reasons,
|
||||||
|
needAgeVideoVerification: appConfig.need_age_video_verification,
|
||||||
|
verifyAgeBotUsername: appConfig.verify_age_bot_username,
|
||||||
|
verifyAgeCountry: appConfig.verify_age_country,
|
||||||
|
verifyAgeMin: appConfig.verify_age_min,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import type {
|
|||||||
ApiTopic,
|
ApiTopic,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
|
||||||
import { pick, pickTruthy } from '../../../util/iteratees';
|
import { pickTruthy } from '../../../util/iteratees';
|
||||||
import { getServerTimeOffset } from '../../../util/serverTime';
|
import { getServerTimeOffset } from '../../../util/serverTime';
|
||||||
import { addPhotoToLocalDb, addUserToLocalDb } from '../helpers/localDb';
|
import { addPhotoToLocalDb, addUserToLocalDb } from '../helpers/localDb';
|
||||||
import { serializeBytes } from '../helpers/misc';
|
import { serializeBytes } from '../helpers/misc';
|
||||||
@ -31,7 +31,7 @@ import {
|
|||||||
buildApiBotVerification, buildApiFormattedText, buildApiPhoto, buildApiUsernames, buildAvatarPhotoId,
|
buildApiBotVerification, buildApiFormattedText, buildApiPhoto, buildApiUsernames, buildAvatarPhotoId,
|
||||||
} from './common';
|
} from './common';
|
||||||
import { omitVirtualClassFields } from './helpers';
|
import { omitVirtualClassFields } from './helpers';
|
||||||
import { buildApiPeerNotifySettings } from './misc';
|
import { buildApiPeerNotifySettings, buildApiRestrictionReasons } from './misc';
|
||||||
import {
|
import {
|
||||||
buildApiEmojiStatus,
|
buildApiEmojiStatus,
|
||||||
buildApiPeerColor,
|
buildApiPeerColor,
|
||||||
@ -196,7 +196,7 @@ function buildApiChatRestrictions(peerEntity: Entity): {
|
|||||||
isNotJoined?: boolean;
|
isNotJoined?: boolean;
|
||||||
isForbidden?: boolean;
|
isForbidden?: boolean;
|
||||||
isRestricted?: boolean;
|
isRestricted?: boolean;
|
||||||
restrictionReason?: ApiRestrictionReason;
|
restrictionReasons?: ApiRestrictionReason[];
|
||||||
} {
|
} {
|
||||||
if (peerEntity instanceof GramJs.ChatForbidden) {
|
if (peerEntity instanceof GramJs.ChatForbidden) {
|
||||||
return {
|
return {
|
||||||
@ -213,11 +213,10 @@ function buildApiChatRestrictions(peerEntity: Entity): {
|
|||||||
const restrictions = {};
|
const restrictions = {};
|
||||||
|
|
||||||
if ('restricted' in peerEntity && !peerEntity.min) {
|
if ('restricted' in peerEntity && !peerEntity.min) {
|
||||||
const restrictionReason = buildApiChatRestrictionReason(peerEntity.restrictionReason);
|
const restrictionReasons = buildApiRestrictionReasons(peerEntity.restrictionReason);
|
||||||
|
|
||||||
Object.assign(restrictions, {
|
Object.assign(restrictions, {
|
||||||
isRestricted: peerEntity.restricted,
|
restrictionReasons,
|
||||||
restrictionReason,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,17 +260,6 @@ function buildApiChatMigrationInfo(peerEntity: Entity): {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildApiChatRestrictionReason(
|
|
||||||
restrictionReasons?: GramJs.RestrictionReason[],
|
|
||||||
): ApiRestrictionReason | undefined {
|
|
||||||
if (!restrictionReasons) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const targetReason = restrictionReasons.find(({ platform }) => platform === 'all');
|
|
||||||
return targetReason ? pick(targetReason, ['reason', 'text']) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function buildApiChatFromPreview(
|
export function buildApiChatFromPreview(
|
||||||
preview: GramJs.TypeChat | GramJs.TypeUser,
|
preview: GramJs.TypeChat | GramJs.TypeUser,
|
||||||
isSupport = false,
|
isSupport = false,
|
||||||
|
|||||||
@ -70,6 +70,7 @@ import {
|
|||||||
import { type OmitVirtualFields } from './helpers';
|
import { type OmitVirtualFields } from './helpers';
|
||||||
import { buildApiMessageAction } from './messageActions';
|
import { buildApiMessageAction } from './messageActions';
|
||||||
import { buildMessageContent, buildMessageMediaContent, buildMessageTextContent } from './messageContent';
|
import { buildMessageContent, buildMessageMediaContent, buildMessageTextContent } from './messageContent';
|
||||||
|
import { buildApiRestrictionReasons } from './misc';
|
||||||
import { buildApiPeerColor, buildApiPeerId, getApiChatIdFromMtpPeer } from './peers';
|
import { buildApiPeerColor, buildApiPeerId, getApiChatIdFromMtpPeer } from './peers';
|
||||||
import { buildMessageReactions } from './reactions';
|
import { buildMessageReactions } from './reactions';
|
||||||
|
|
||||||
@ -230,6 +231,8 @@ export function buildApiMessageWithChatId(
|
|||||||
|
|
||||||
const savedPeerId = mtpMessage.savedPeerId && getApiChatIdFromMtpPeer(mtpMessage.savedPeerId);
|
const savedPeerId = mtpMessage.savedPeerId && getApiChatIdFromMtpPeer(mtpMessage.savedPeerId);
|
||||||
|
|
||||||
|
const restrictionReasons = buildApiRestrictionReasons(mtpMessage.restrictionReason);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: mtpMessage.id,
|
id: mtpMessage.id,
|
||||||
chatId,
|
chatId,
|
||||||
@ -277,6 +280,7 @@ export function buildApiMessageWithChatId(
|
|||||||
isVideoProcessingPending,
|
isVideoProcessingPending,
|
||||||
reportDeliveryUntilDate: mtpMessage.reportDeliveryUntilDate,
|
reportDeliveryUntilDate: mtpMessage.reportDeliveryUntilDate,
|
||||||
paidMessageStars: mtpMessage.paidMessageStars?.toJSNumber(),
|
paidMessageStars: mtpMessage.paidMessageStars?.toJSNumber(),
|
||||||
|
restrictionReasons,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import type {
|
|||||||
ApiPeerColors,
|
ApiPeerColors,
|
||||||
ApiPeerNotifySettings,
|
ApiPeerNotifySettings,
|
||||||
ApiPrivacyKey,
|
ApiPrivacyKey,
|
||||||
|
ApiRestrictionReason,
|
||||||
ApiSession,
|
ApiSession,
|
||||||
ApiTimezone,
|
ApiTimezone,
|
||||||
ApiUrlAuthResult,
|
ApiUrlAuthResult,
|
||||||
@ -347,3 +348,15 @@ export function buildApiCollectibleInfo(info: GramJs.fragment.TypeCollectibleInf
|
|||||||
url,
|
url,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildApiRestrictionReasons(
|
||||||
|
restrictionReasons?: GramJs.RestrictionReason[],
|
||||||
|
): ApiRestrictionReason[] | undefined {
|
||||||
|
if (!restrictionReasons) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return restrictionReasons.map((
|
||||||
|
{ reason, text, platform }) =>
|
||||||
|
({ reason, text, platform }));
|
||||||
|
}
|
||||||
|
|||||||
@ -314,8 +314,6 @@ export async function fetchProfilePhotos({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chat?.isRestricted) return undefined;
|
|
||||||
|
|
||||||
const result = await searchMessagesInChat({
|
const result = await searchMessagesInChat({
|
||||||
peer,
|
peer,
|
||||||
type: 'profilePhoto',
|
type: 'profilePhoto',
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import type { ApiBotCommand } from './bots';
|
|||||||
import type {
|
import type {
|
||||||
ApiChatReactions, ApiFormattedText, ApiInputMessageReplyInfo, ApiInputSuggestedPostInfo, ApiPhoto, ApiStickerSet,
|
ApiChatReactions, ApiFormattedText, ApiInputMessageReplyInfo, ApiInputSuggestedPostInfo, ApiPhoto, ApiStickerSet,
|
||||||
} from './messages';
|
} from './messages';
|
||||||
import type { ApiBotVerification, ApiChatInviteImporter, ApiPeerNotifySettings } from './misc';
|
import type { ApiBotVerification, ApiChatInviteImporter, ApiPeerNotifySettings, ApiRestrictionReason } from './misc';
|
||||||
import type {
|
import type {
|
||||||
ApiEmojiStatusType, ApiFakeType, ApiUser, ApiUsername,
|
ApiEmojiStatusType, ApiFakeType, ApiUser, ApiUsername,
|
||||||
} from './users';
|
} from './users';
|
||||||
@ -66,7 +66,7 @@ export interface ApiChat {
|
|||||||
isCreator?: boolean;
|
isCreator?: boolean;
|
||||||
isForbidden?: boolean; // Forbidden - can't send messages (user was kicked, for example)
|
isForbidden?: boolean; // Forbidden - can't send messages (user was kicked, for example)
|
||||||
isRestricted?: boolean; // Restricted - can't access the chat (user was banned or chat is violating rules)
|
isRestricted?: boolean; // Restricted - can't access the chat (user was banned or chat is violating rules)
|
||||||
restrictionReason?: ApiRestrictionReason;
|
restrictionReasons?: ApiRestrictionReason[];
|
||||||
adminRights?: ApiChatAdminRights;
|
adminRights?: ApiChatAdminRights;
|
||||||
currentUserBannedRights?: ApiChatBannedRights;
|
currentUserBannedRights?: ApiChatBannedRights;
|
||||||
defaultBannedRights?: ApiChatBannedRights;
|
defaultBannedRights?: ApiChatBannedRights;
|
||||||
@ -212,11 +212,6 @@ export interface ApiChatBannedRights {
|
|||||||
untilDate?: number;
|
untilDate?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApiRestrictionReason {
|
|
||||||
reason: string;
|
|
||||||
text: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ApiChatFolder {
|
export interface ApiChatFolder {
|
||||||
id: number;
|
id: number;
|
||||||
title: ApiFormattedText;
|
title: ApiFormattedText;
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import type {
|
|||||||
} from './bots';
|
} from './bots';
|
||||||
import type { ApiPeerColor } from './chats';
|
import type { ApiPeerColor } from './chats';
|
||||||
import type { ApiMessageAction } from './messageActions';
|
import type { ApiMessageAction } from './messageActions';
|
||||||
|
import type { ApiRestrictionReason } from './misc';
|
||||||
import type {
|
import type {
|
||||||
ApiLabeledPrice,
|
ApiLabeledPrice,
|
||||||
} from './payments';
|
} from './payments';
|
||||||
@ -642,6 +643,7 @@ export interface ApiMessage {
|
|||||||
areReactionsPossible?: true;
|
areReactionsPossible?: true;
|
||||||
reportDeliveryUntilDate?: number;
|
reportDeliveryUntilDate?: number;
|
||||||
paidMessageStars?: number;
|
paidMessageStars?: number;
|
||||||
|
restrictionReasons?: ApiRestrictionReason[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApiReactions {
|
export interface ApiReactions {
|
||||||
|
|||||||
@ -267,6 +267,11 @@ export interface ApiAppConfig {
|
|||||||
todoItemsMax?: number;
|
todoItemsMax?: number;
|
||||||
todoTitleLengthMax?: number;
|
todoTitleLengthMax?: number;
|
||||||
todoItemLengthMax?: number;
|
todoItemLengthMax?: number;
|
||||||
|
ignoreRestrictionReasons?: string[];
|
||||||
|
needAgeVideoVerification?: boolean;
|
||||||
|
verifyAgeBotUsername?: string;
|
||||||
|
verifyAgeCountry?: string;
|
||||||
|
verifyAgeMin?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ApiConfig {
|
export interface ApiConfig {
|
||||||
@ -385,3 +390,9 @@ export type ApiPeerNotifySettings = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type ApiNotifyPeerType = 'users' | 'groups' | 'channels';
|
export type ApiNotifyPeerType = 'users' | 'groups' | 'channels';
|
||||||
|
|
||||||
|
export interface ApiRestrictionReason {
|
||||||
|
reason: string;
|
||||||
|
text: string;
|
||||||
|
platform: string;
|
||||||
|
}
|
||||||
|
|||||||
@ -2141,3 +2141,15 @@
|
|||||||
"ButtonTopUpViaFragment" = "Top-Up Via Fragment";
|
"ButtonTopUpViaFragment" = "Top-Up Via Fragment";
|
||||||
"TonModalHint" = "You can top-up your TON using Fragment.";
|
"TonModalHint" = "You can top-up your TON using Fragment.";
|
||||||
"TonGiftReceived" = "TON Top-Up";
|
"TonGiftReceived" = "TON Top-Up";
|
||||||
|
"MediaSpoilerSensitive" = "18+";
|
||||||
|
"TitleSensitiveModal" = "18+ content";
|
||||||
|
"TextSensitiveModal" = "This media may contain sensitive content suitable only for adults. Do you still want to view it?";
|
||||||
|
"ButtonSensitiveAlways" = "Always show 18+ media";
|
||||||
|
"ButtonSensitiveView" = "View Anyway";
|
||||||
|
"TitleAgeVerificationModal" = "Age Verification";
|
||||||
|
"TextAgeVerificationModal_one" = "To access such content, you must confirm that you are at least **{count}** year old as required by UK law.";
|
||||||
|
"TextAgeVerificationModal_other" = "To access such content, you must confirm that you are at least **{count}** years old as required by UK law.";
|
||||||
|
"DescriptionAgeVerificationModal" = "This is a one-time process using your phone's camera. Your selfie will not be stored by Telegram.";
|
||||||
|
"TitleAgeCheckFailed" = "Age Check Failed";
|
||||||
|
"TitleAgeCheckSuccess" = "Age Check Success";
|
||||||
|
"ButtonAgeVerification" = "Verify My Age";
|
||||||
@ -24,6 +24,7 @@ export { default as SuggestedStatusModal } from '../components/modals/suggestedS
|
|||||||
export { default as BoostModal } from '../components/modals/boost/BoostModal';
|
export { default as BoostModal } from '../components/modals/boost/BoostModal';
|
||||||
export { default as GiftCodeModal } from '../components/modals/giftcode/GiftCodeModal';
|
export { default as GiftCodeModal } from '../components/modals/giftcode/GiftCodeModal';
|
||||||
export { default as DeleteAccountModal } from '../components/modals/deleteAccount/DeleteAccountModal';
|
export { default as DeleteAccountModal } from '../components/modals/deleteAccount/DeleteAccountModal';
|
||||||
|
export { default as AgeVerificationModal } from '../components/modals/ageVerification/AgeVerificationModal';
|
||||||
export { default as ChatlistModal } from '../components/modals/chatlist/ChatlistModal';
|
export { default as ChatlistModal } from '../components/modals/chatlist/ChatlistModal';
|
||||||
export { default as ChatInviteModal } from '../components/modals/chatInvite/ChatInviteModal';
|
export { default as ChatInviteModal } from '../components/modals/chatInvite/ChatInviteModal';
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import type { FC } from '../../lib/teact/teact';
|
import type { FC } from '../../lib/teact/teact';
|
||||||
import type React from '../../lib/teact/teact';
|
import type React from '../../lib/teact/teact';
|
||||||
import { memo, useEffect, useMemo } from '../../lib/teact/teact';
|
import { memo, useEffect, useMemo } from '../../lib/teact/teact';
|
||||||
import { getActions, withGlobal } from '../../global';
|
import { getActions, getGlobal, withGlobal } from '../../global';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ApiChat, ApiThreadInfo, ApiTopic, ApiTypingStatus, ApiUser,
|
ApiChat, ApiThreadInfo, ApiTopic, ApiTypingStatus, ApiUser,
|
||||||
@ -19,6 +19,7 @@ import {
|
|||||||
selectChat,
|
selectChat,
|
||||||
selectChatMessages,
|
selectChatMessages,
|
||||||
selectChatOnlineCount,
|
selectChatOnlineCount,
|
||||||
|
selectIsChatRestricted,
|
||||||
selectMonoforumChannel,
|
selectMonoforumChannel,
|
||||||
selectThreadInfo,
|
selectThreadInfo,
|
||||||
selectThreadMessagesCount,
|
selectThreadMessagesCount,
|
||||||
@ -126,7 +127,8 @@ const GroupChatInfo: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
const isSuperGroup = chat && isChatSuperGroup(chat);
|
const isSuperGroup = chat && isChatSuperGroup(chat);
|
||||||
const isTopic = Boolean(chat?.isForum && threadInfo && topic);
|
const isTopic = Boolean(chat?.isForum && threadInfo && topic);
|
||||||
const { id: chatId, isMin, isRestricted } = chat || {};
|
const { id: chatId, isMin } = chat || {};
|
||||||
|
const isRestricted = selectIsChatRestricted(getGlobal(), chatId!);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (chatId && !isMin) {
|
if (chatId && !isMin) {
|
||||||
|
|||||||
@ -1,11 +1,14 @@
|
|||||||
.root {
|
.root {
|
||||||
|
|
||||||
--click-shift-x: 0px;
|
--click-shift-x: 0px;
|
||||||
--click-shift-y: 0px;
|
--click-shift-y: 0px;
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
background-color: var(--color-text-secondary); // Fallback before canvas is prepared
|
background-color: var(--color-text-secondary); // Fallback before canvas is prepared
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +36,28 @@
|
|||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nsfw {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
gap: 0.25rem;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
padding: 0.125rem 0.5rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
background-color: rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nsfwIcon {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.dots {
|
.dots {
|
||||||
--x-direction: var(--background-size);
|
--x-direction: var(--background-size);
|
||||||
--y-direction: 0;
|
--y-direction: 0;
|
||||||
|
|||||||
@ -6,15 +6,19 @@ import { requestMutation } from '../../lib/fasterdom/fasterdom';
|
|||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
|
|
||||||
import useCanvasBlur from '../../hooks/useCanvasBlur';
|
import useCanvasBlur from '../../hooks/useCanvasBlur';
|
||||||
|
import useLang from '../../hooks/useLang';
|
||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
|
import useShowTransitionDeprecated from '../../hooks/useShowTransitionDeprecated';
|
||||||
|
|
||||||
|
import Icon from './icons/Icon';
|
||||||
|
|
||||||
import styles from './MediaSpoiler.module.scss';
|
import styles from './MediaSpoiler.module.scss';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
withAnimation?: boolean;
|
withAnimation?: boolean;
|
||||||
thumbDataUri?: string;
|
thumbDataUri?: string;
|
||||||
|
isNsfw?: boolean;
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -27,12 +31,15 @@ const MediaSpoiler: FC<OwnProps> = ({
|
|||||||
isVisible,
|
isVisible,
|
||||||
withAnimation,
|
withAnimation,
|
||||||
thumbDataUri,
|
thumbDataUri,
|
||||||
|
isNsfw,
|
||||||
className,
|
className,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
}) => {
|
}) => {
|
||||||
const ref = useRef<HTMLDivElement>();
|
const ref = useRef<HTMLDivElement>();
|
||||||
|
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(
|
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(
|
||||||
isVisible, undefined, true, withAnimation ? false : undefined, undefined, ANIMATION_DURATION,
|
isVisible, undefined, true, withAnimation ? false : undefined, undefined, ANIMATION_DURATION,
|
||||||
);
|
);
|
||||||
@ -68,6 +75,12 @@ const MediaSpoiler: FC<OwnProps> = ({
|
|||||||
height={height}
|
height={height}
|
||||||
/>
|
/>
|
||||||
<div className={styles.dots} />
|
<div className={styles.dots} />
|
||||||
|
{isNsfw && (
|
||||||
|
<span className={styles.nsfw}>
|
||||||
|
<Icon name="eye-crossed-outline" className={styles.nsfwIcon} />
|
||||||
|
{lang('MediaSpoilerSensitive')}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
.checkBox {
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-inline: -1.125rem;
|
||||||
|
}
|
||||||
47
src/components/common/SensitiveContentConfirmModal.tsx
Normal file
47
src/components/common/SensitiveContentConfirmModal.tsx
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import type { FC } from '../../lib/teact/teact';
|
||||||
|
import { memo } from '../../lib/teact/teact';
|
||||||
|
|
||||||
|
import useLang from '../../hooks/useLang';
|
||||||
|
|
||||||
|
import Checkbox from '../ui/Checkbox';
|
||||||
|
import ConfirmDialog from '../ui/ConfirmDialog';
|
||||||
|
|
||||||
|
import styles from './SensitiveContentConfirmModal.module.scss';
|
||||||
|
|
||||||
|
type OwnProps = {
|
||||||
|
isOpen: boolean;
|
||||||
|
onClose: NoneToVoidFunction;
|
||||||
|
shouldAlwaysShow: boolean;
|
||||||
|
onAlwaysShowChanged: (value: boolean) => void;
|
||||||
|
confirmHandler: NoneToVoidFunction;
|
||||||
|
};
|
||||||
|
|
||||||
|
const SensitiveContentConfirmModal: FC<OwnProps> = ({
|
||||||
|
isOpen,
|
||||||
|
onClose,
|
||||||
|
shouldAlwaysShow,
|
||||||
|
onAlwaysShowChanged,
|
||||||
|
confirmHandler,
|
||||||
|
}) => {
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfirmDialog
|
||||||
|
title={lang('TitleSensitiveModal')}
|
||||||
|
confirmLabel={lang('ButtonSensitiveView')}
|
||||||
|
isOpen={isOpen}
|
||||||
|
onClose={onClose}
|
||||||
|
confirmHandler={confirmHandler}
|
||||||
|
>
|
||||||
|
{lang('TextSensitiveModal')}
|
||||||
|
<Checkbox
|
||||||
|
className={styles.checkBox}
|
||||||
|
label={lang('ButtonSensitiveAlways')}
|
||||||
|
checked={shouldAlwaysShow}
|
||||||
|
onCheck={onAlwaysShowChanged}
|
||||||
|
/>
|
||||||
|
</ConfirmDialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(SensitiveContentConfirmModal);
|
||||||
@ -64,6 +64,7 @@ type OwnProps = {
|
|||||||
chatTranslations?: ChatTranslatedMessages;
|
chatTranslations?: ChatTranslatedMessages;
|
||||||
requestedChatTranslationLanguage?: string;
|
requestedChatTranslationLanguage?: string;
|
||||||
isOpen?: boolean;
|
isOpen?: boolean;
|
||||||
|
isMediaNsfw?: boolean;
|
||||||
observeIntersectionForLoading?: ObserveFn;
|
observeIntersectionForLoading?: ObserveFn;
|
||||||
observeIntersectionForPlaying?: ObserveFn;
|
observeIntersectionForPlaying?: ObserveFn;
|
||||||
onClick: ((e: React.MouseEvent) => void);
|
onClick: ((e: React.MouseEvent) => void);
|
||||||
@ -88,6 +89,7 @@ const EmbeddedMessage: FC<OwnProps> = ({
|
|||||||
noUserColors,
|
noUserColors,
|
||||||
chatTranslations,
|
chatTranslations,
|
||||||
requestedChatTranslationLanguage,
|
requestedChatTranslationLanguage,
|
||||||
|
isMediaNsfw,
|
||||||
observeIntersectionForLoading,
|
observeIntersectionForLoading,
|
||||||
observeIntersectionForPlaying,
|
observeIntersectionForPlaying,
|
||||||
onClick,
|
onClick,
|
||||||
@ -114,7 +116,7 @@ const EmbeddedMessage: FC<OwnProps> = ({
|
|||||||
const mediaThumbnail = useThumbnail(containedMedia);
|
const mediaThumbnail = useThumbnail(containedMedia);
|
||||||
|
|
||||||
const isRoundVideo = Boolean(containedMedia && getMessageRoundVideo(containedMedia));
|
const isRoundVideo = Boolean(containedMedia && getMessageRoundVideo(containedMedia));
|
||||||
const isSpoiler = Boolean(containedMedia && getMessageIsSpoiler(containedMedia));
|
const isSpoiler = Boolean(containedMedia && getMessageIsSpoiler(containedMedia)) || isMediaNsfw;
|
||||||
const isQuote = Boolean(replyInfo?.type === 'message' && replyInfo.isQuote);
|
const isQuote = Boolean(replyInfo?.type === 'message' && replyInfo.isQuote);
|
||||||
const replyForwardInfo = replyInfo?.type === 'message' ? replyInfo.replyFrom : undefined;
|
const replyForwardInfo = replyInfo?.type === 'message' ? replyInfo.replyFrom : undefined;
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import type { FC } from '../../../lib/teact/teact';
|
|||||||
import {
|
import {
|
||||||
memo, useMemo,
|
memo, useMemo,
|
||||||
} from '../../../lib/teact/teact';
|
} from '../../../lib/teact/teact';
|
||||||
import { getActions, withGlobal } from '../../../global';
|
import { getActions, getGlobal, withGlobal } from '../../../global';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ApiBotVerification,
|
ApiBotVerification,
|
||||||
@ -29,6 +29,7 @@ import {
|
|||||||
selectChat,
|
selectChat,
|
||||||
selectChatFullInfo,
|
selectChatFullInfo,
|
||||||
selectCurrentMessageList,
|
selectCurrentMessageList,
|
||||||
|
selectIsChatRestricted,
|
||||||
selectNotifyDefaults,
|
selectNotifyDefaults,
|
||||||
selectNotifyException,
|
selectNotifyException,
|
||||||
selectTopicLink,
|
selectTopicLink,
|
||||||
@ -273,7 +274,8 @@ const ChatExtra: FC<OwnProps & StateProps> = ({
|
|||||||
),
|
),
|
||||||
}, { withNodes: true });
|
}, { withNodes: true });
|
||||||
|
|
||||||
if (chat?.isRestricted || (isSelf && !isInSettings)) {
|
const isRestricted = chatId ? selectIsChatRestricted(getGlobal(), chatId) : false;
|
||||||
|
if (isRestricted || (isSelf && !isInSettings)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import useLastCallback from '../../../hooks/useLastCallback.ts';
|
|||||||
import useOldLang from '../../../hooks/useOldLang';
|
import useOldLang from '../../../hooks/useOldLang';
|
||||||
|
|
||||||
import StarIcon from '../../common/icons/StarIcon';
|
import StarIcon from '../../common/icons/StarIcon';
|
||||||
|
import Button from '../../ui/Button';
|
||||||
import Checkbox from '../../ui/Checkbox';
|
import Checkbox from '../../ui/Checkbox';
|
||||||
import ListItem from '../../ui/ListItem';
|
import ListItem from '../../ui/ListItem';
|
||||||
|
|
||||||
@ -43,6 +44,7 @@ type StateProps = {
|
|||||||
shouldChargeForMessages: boolean;
|
shouldChargeForMessages: boolean;
|
||||||
canDisplayChatInTitle?: boolean;
|
canDisplayChatInTitle?: boolean;
|
||||||
isCurrentUserFrozen?: boolean;
|
isCurrentUserFrozen?: boolean;
|
||||||
|
needAgeVideoVerification?: boolean;
|
||||||
privacy: GlobalState['settings']['privacy'];
|
privacy: GlobalState['settings']['privacy'];
|
||||||
accountDaysTtl?: number;
|
accountDaysTtl?: number;
|
||||||
};
|
};
|
||||||
@ -64,6 +66,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
|||||||
shouldChargeForMessages,
|
shouldChargeForMessages,
|
||||||
canDisplayChatInTitle,
|
canDisplayChatInTitle,
|
||||||
canSetPasscode,
|
canSetPasscode,
|
||||||
|
needAgeVideoVerification,
|
||||||
privacy,
|
privacy,
|
||||||
onReset,
|
onReset,
|
||||||
isCurrentUserFrozen,
|
isCurrentUserFrozen,
|
||||||
@ -73,7 +76,6 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
|||||||
openDeleteAccountModal,
|
openDeleteAccountModal,
|
||||||
loadPrivacySettings,
|
loadPrivacySettings,
|
||||||
loadBlockedUsers,
|
loadBlockedUsers,
|
||||||
loadContentSettings,
|
|
||||||
updateContentSettings,
|
updateContentSettings,
|
||||||
loadGlobalPrivacySettings,
|
loadGlobalPrivacySettings,
|
||||||
updateGlobalPrivacySettings,
|
updateGlobalPrivacySettings,
|
||||||
@ -81,13 +83,13 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
|||||||
setSharedSettingOption,
|
setSharedSettingOption,
|
||||||
openSettingsScreen,
|
openSettingsScreen,
|
||||||
loadAccountDaysTtl,
|
loadAccountDaysTtl,
|
||||||
|
openAgeVerificationModal,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isCurrentUserFrozen) {
|
if (!isCurrentUserFrozen) {
|
||||||
loadBlockedUsers();
|
loadBlockedUsers();
|
||||||
loadPrivacySettings();
|
loadPrivacySettings();
|
||||||
loadContentSettings();
|
|
||||||
loadWebAuthorizations();
|
loadWebAuthorizations();
|
||||||
}
|
}
|
||||||
}, [isCurrentUserFrozen]);
|
}, [isCurrentUserFrozen]);
|
||||||
@ -123,6 +125,10 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
|||||||
updateContentSettings({ isSensitiveEnabled: isChecked });
|
updateContentSettings({ isSensitiveEnabled: isChecked });
|
||||||
}, [updateContentSettings]);
|
}, [updateContentSettings]);
|
||||||
|
|
||||||
|
const handleAgeVerification = useCallback(() => {
|
||||||
|
openAgeVerificationModal();
|
||||||
|
}, [openAgeVerificationModal]);
|
||||||
|
|
||||||
const handleOpenDeleteAccountModal = useLastCallback(() => {
|
const handleOpenDeleteAccountModal = useLastCallback(() => {
|
||||||
if (!accountDaysTtl) return;
|
if (!accountDaysTtl) return;
|
||||||
openDeleteAccountModal({ days: accountDaysTtl });
|
openDeleteAccountModal({ days: accountDaysTtl });
|
||||||
@ -384,7 +390,7 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{canChangeSensitive && (
|
{canChangeSensitive && (
|
||||||
<div className="settings-item">
|
<div className="settings-item fluid-container">
|
||||||
<h4 className="settings-item-header" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
<h4 className="settings-item-header" dir={oldLang.isRtl ? 'rtl' : undefined}>
|
||||||
{oldLang('lng_settings_sensitive_title')}
|
{oldLang('lng_settings_sensitive_title')}
|
||||||
</h4>
|
</h4>
|
||||||
@ -392,9 +398,23 @@ const SettingsPrivacy: FC<OwnProps & StateProps> = ({
|
|||||||
label={oldLang('lng_settings_sensitive_disable_filtering')}
|
label={oldLang('lng_settings_sensitive_disable_filtering')}
|
||||||
subLabel={oldLang('lng_settings_sensitive_about')}
|
subLabel={oldLang('lng_settings_sensitive_about')}
|
||||||
checked={Boolean(isSensitiveEnabled)}
|
checked={Boolean(isSensitiveEnabled)}
|
||||||
disabled={!canChangeSensitive}
|
disabled={!canChangeSensitive || (!isSensitiveEnabled && needAgeVideoVerification)}
|
||||||
onCheck={handleUpdateContentSettings}
|
onCheck={handleUpdateContentSettings}
|
||||||
/>
|
/>
|
||||||
|
{!isSensitiveEnabled && needAgeVideoVerification && (
|
||||||
|
<Button
|
||||||
|
color="primary"
|
||||||
|
fluid
|
||||||
|
size="smaller"
|
||||||
|
noForcedUpperCase
|
||||||
|
className="settings-unlock-button"
|
||||||
|
onClick={handleAgeVerification}
|
||||||
|
>
|
||||||
|
<span className="settings-unlock-button-title">
|
||||||
|
{lang('ButtonAgeVerification')}
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -475,6 +495,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
canChangeSensitive,
|
canChangeSensitive,
|
||||||
shouldNewNonContactPeersRequirePremium,
|
shouldNewNonContactPeersRequirePremium,
|
||||||
shouldChargeForMessages,
|
shouldChargeForMessages,
|
||||||
|
needAgeVideoVerification: Boolean(appConfig?.needAgeVideoVerification),
|
||||||
privacy,
|
privacy,
|
||||||
canDisplayChatInTitle,
|
canDisplayChatInTitle,
|
||||||
canSetPasscode: selectCanSetPasscode(global),
|
canSetPasscode: selectCanSetPasscode(global),
|
||||||
|
|||||||
@ -257,6 +257,7 @@ const Main = ({
|
|||||||
loadAllChats,
|
loadAllChats,
|
||||||
loadAllStories,
|
loadAllStories,
|
||||||
loadAllHiddenStories,
|
loadAllHiddenStories,
|
||||||
|
loadContentSettings,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
if (DEBUG && !DEBUG_isLogged) {
|
if (DEBUG && !DEBUG_isLogged) {
|
||||||
@ -329,6 +330,7 @@ const Main = ({
|
|||||||
loadAllChats({ listType: 'saved' });
|
loadAllChats({ listType: 'saved' });
|
||||||
loadAllStories();
|
loadAllStories();
|
||||||
loadAllHiddenStories();
|
loadAllHiddenStories();
|
||||||
|
loadContentSettings();
|
||||||
loadRecentReactions();
|
loadRecentReactions();
|
||||||
loadDefaultTagReactions();
|
loadDefaultTagReactions();
|
||||||
loadAttachBots();
|
loadAttachBots();
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import {
|
|||||||
selectChat,
|
selectChat,
|
||||||
selectChatFullInfo,
|
selectChatFullInfo,
|
||||||
selectIsChatBotNotStarted,
|
selectIsChatBotNotStarted,
|
||||||
|
selectIsChatRestricted,
|
||||||
selectIsChatWithSelf,
|
selectIsChatWithSelf,
|
||||||
selectIsCurrentUserFrozen,
|
selectIsCurrentUserFrozen,
|
||||||
selectIsInSelectMode,
|
selectIsInSelectMode,
|
||||||
@ -477,7 +478,8 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const isPrivate = isUserId(chatId);
|
const isPrivate = isUserId(chatId);
|
||||||
const { doNotTranslate } = global.settings.byKey;
|
const { doNotTranslate } = global.settings.byKey;
|
||||||
|
|
||||||
if (!chat || chat.isRestricted || selectIsInSelectMode(global)) {
|
const isRestricted = selectIsChatRestricted(global, chatId);
|
||||||
|
if (!chat || isRestricted || selectIsInSelectMode(global)) {
|
||||||
return {
|
return {
|
||||||
noMenu: true,
|
noMenu: true,
|
||||||
language,
|
language,
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import {
|
|||||||
selectChat,
|
selectChat,
|
||||||
selectChatFullInfo,
|
selectChatFullInfo,
|
||||||
selectCurrentMessageList,
|
selectCurrentMessageList,
|
||||||
|
selectIsChatRestricted,
|
||||||
selectIsChatWithSelf,
|
selectIsChatWithSelf,
|
||||||
selectIsCurrentUserFrozen,
|
selectIsCurrentUserFrozen,
|
||||||
selectIsRightColumnShown,
|
selectIsRightColumnShown,
|
||||||
@ -842,7 +843,8 @@ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
|
|||||||
export default memo(withGlobal<OwnProps>(
|
export default memo(withGlobal<OwnProps>(
|
||||||
(global, { chatId, threadId }): StateProps => {
|
(global, { chatId, threadId }): StateProps => {
|
||||||
const chat = selectChat(global, chatId);
|
const chat = selectChat(global, chatId);
|
||||||
if (!chat || chat.isRestricted) {
|
const isRestricted = selectIsChatRestricted(global, chatId);
|
||||||
|
if (!chat || isRestricted) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const isPrivate = isUserId(chat.id);
|
const isPrivate = isUserId(chat.id);
|
||||||
|
|||||||
@ -58,6 +58,8 @@ import {
|
|||||||
selectTranslationLanguage,
|
selectTranslationLanguage,
|
||||||
selectUserFullInfo,
|
selectUserFullInfo,
|
||||||
} from '../../global/selectors';
|
} from '../../global/selectors';
|
||||||
|
import { selectIsChatRestricted } from '../../global/selectors/chats';
|
||||||
|
import { selectActiveRestrictionReasons } from '../../global/selectors/messages';
|
||||||
import animateScroll, { isAnimatingScroll, restartCurrentScrollAnimation } from '../../util/animateScroll';
|
import animateScroll, { isAnimatingScroll, restartCurrentScrollAnimation } from '../../util/animateScroll';
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
import { isUserId } from '../../util/entities/ids';
|
import { isUserId } from '../../util/entities/ids';
|
||||||
@ -125,7 +127,7 @@ type StateProps = {
|
|||||||
firstUnreadId?: number;
|
firstUnreadId?: number;
|
||||||
isViewportNewest?: boolean;
|
isViewportNewest?: boolean;
|
||||||
isRestricted?: boolean;
|
isRestricted?: boolean;
|
||||||
restrictionReason?: ApiRestrictionReason;
|
restrictionReasons?: ApiRestrictionReason[];
|
||||||
focusingId?: number;
|
focusingId?: number;
|
||||||
isSelectModeActive?: boolean;
|
isSelectModeActive?: boolean;
|
||||||
lastMessage?: ApiMessage;
|
lastMessage?: ApiMessage;
|
||||||
@ -189,7 +191,7 @@ const MessageList: FC<OwnProps & StateProps> = ({
|
|||||||
isComments,
|
isComments,
|
||||||
isViewportNewest,
|
isViewportNewest,
|
||||||
isRestricted,
|
isRestricted,
|
||||||
restrictionReason,
|
restrictionReasons,
|
||||||
isEmptyThread,
|
isEmptyThread,
|
||||||
focusingId,
|
focusingId,
|
||||||
isSelectModeActive,
|
isSelectModeActive,
|
||||||
@ -719,7 +721,7 @@ const MessageList: FC<OwnProps & StateProps> = ({
|
|||||||
{isRestricted ? (
|
{isRestricted ? (
|
||||||
<div className="empty">
|
<div className="empty">
|
||||||
<span>
|
<span>
|
||||||
{restrictionReason ? restrictionReason.text : `This is a private ${isChannelChat ? 'channel' : 'chat'}`}
|
{restrictionReasons?.[0]?.text || `This is a private ${isChannelChat ? 'channel' : 'chat'}`}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : paidMessagesStars && !hasMessages && !hasCustomGreeting ? (
|
) : paidMessagesStars && !hasMessages && !hasCustomGreeting ? (
|
||||||
@ -802,7 +804,8 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
return { currentUserId };
|
return { currentUserId };
|
||||||
}
|
}
|
||||||
|
|
||||||
const { isRestricted, restrictionReason } = chat;
|
const isRestricted = selectIsChatRestricted(global, chatId);
|
||||||
|
const restrictionReasons = selectActiveRestrictionReasons(global, chat?.restrictionReasons);
|
||||||
const lastMessage = selectChatLastMessage(global, chatId, isSavedDialog ? 'saved' : 'all');
|
const lastMessage = selectChatLastMessage(global, chatId, isSavedDialog ? 'saved' : 'all');
|
||||||
const focusingId = selectFocusedMessageId(global, chatId);
|
const focusingId = selectFocusedMessageId(global, chatId);
|
||||||
|
|
||||||
@ -836,7 +839,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
areAdsEnabled,
|
areAdsEnabled,
|
||||||
isChatLoaded: true,
|
isChatLoaded: true,
|
||||||
isRestricted,
|
isRestricted,
|
||||||
restrictionReason,
|
restrictionReasons,
|
||||||
isChannelChat: isChatChannel(chat),
|
isChannelChat: isChatChannel(chat),
|
||||||
isChatMonoforum: isChatMonoforum(chat),
|
isChatMonoforum: isChatMonoforum(chat),
|
||||||
isGroupChat: isChatGroup(chat),
|
isGroupChat: isChatGroup(chat),
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import {
|
|||||||
selectForwardedSender,
|
selectForwardedSender,
|
||||||
selectIsChatWithSelf,
|
selectIsChatWithSelf,
|
||||||
selectIsCurrentUserPremium,
|
selectIsCurrentUserPremium,
|
||||||
|
selectIsMediaNsfw,
|
||||||
selectSender,
|
selectSender,
|
||||||
selectTabState,
|
selectTabState,
|
||||||
} from '../../../global/selectors';
|
} from '../../../global/selectors';
|
||||||
@ -67,14 +68,15 @@ type StateProps = {
|
|||||||
currentUserId?: string;
|
currentUserId?: string;
|
||||||
forwardMessageIds?: number[];
|
forwardMessageIds?: number[];
|
||||||
fromChatId?: string;
|
fromChatId?: string;
|
||||||
|
isMediaNsfw?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
onClear?: () => void;
|
|
||||||
shouldForceShowEditing?: boolean;
|
shouldForceShowEditing?: boolean;
|
||||||
chatId: string;
|
chatId: string;
|
||||||
threadId: ThreadId;
|
threadId: ThreadId;
|
||||||
messageListType: MessageListType;
|
messageListType: MessageListType;
|
||||||
|
onClear?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const CLOSE_DURATION = 350;
|
const CLOSE_DURATION = 350;
|
||||||
@ -94,7 +96,6 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
|
|||||||
isCurrentUserPremium,
|
isCurrentUserPremium,
|
||||||
isContextMenuDisabled,
|
isContextMenuDisabled,
|
||||||
isReplyToDiscussion,
|
isReplyToDiscussion,
|
||||||
onClear,
|
|
||||||
isInChangingRecipientMode,
|
isInChangingRecipientMode,
|
||||||
shouldPreventComposerAnimation,
|
shouldPreventComposerAnimation,
|
||||||
senderChat,
|
senderChat,
|
||||||
@ -103,6 +104,8 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
|
|||||||
isSenderChannel,
|
isSenderChannel,
|
||||||
forwardMessageIds,
|
forwardMessageIds,
|
||||||
fromChatId,
|
fromChatId,
|
||||||
|
isMediaNsfw,
|
||||||
|
onClear,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
resetDraftReplyInfo,
|
resetDraftReplyInfo,
|
||||||
@ -301,6 +304,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
|
|||||||
className="inside-input"
|
className="inside-input"
|
||||||
replyInfo={replyInfo}
|
replyInfo={replyInfo}
|
||||||
suggestedPostInfo={suggestedPostInfo}
|
suggestedPostInfo={suggestedPostInfo}
|
||||||
|
isMediaNsfw={isMediaNsfw}
|
||||||
isInComposer
|
isInComposer
|
||||||
message={strippedMessage}
|
message={strippedMessage}
|
||||||
sender={!noAuthors ? sender : undefined}
|
sender={!noAuthors ? sender : undefined}
|
||||||
@ -495,6 +499,8 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
|
|
||||||
const isReplyToDiscussion = replyInfo?.replyToMsgId === threadId && !replyInfo.replyToPeerId;
|
const isReplyToDiscussion = replyInfo?.replyToMsgId === threadId && !replyInfo.replyToPeerId;
|
||||||
|
|
||||||
|
const isMediaNsfw = message && selectIsMediaNsfw(global, message);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
replyInfo,
|
replyInfo,
|
||||||
suggestedPostInfo,
|
suggestedPostInfo,
|
||||||
@ -516,6 +522,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
isSenderChannel,
|
isSenderChannel,
|
||||||
forwardMessageIds,
|
forwardMessageIds,
|
||||||
fromChatId,
|
fromChatId,
|
||||||
|
isMediaNsfw,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(ComposerEmbeddedMessage));
|
)(ComposerEmbeddedMessage));
|
||||||
|
|||||||
@ -86,11 +86,13 @@ import {
|
|||||||
selectDefaultReaction,
|
selectDefaultReaction,
|
||||||
selectForwardedSender,
|
selectForwardedSender,
|
||||||
selectIsChatProtected,
|
selectIsChatProtected,
|
||||||
|
selectIsChatRestricted,
|
||||||
selectIsChatWithSelf,
|
selectIsChatWithSelf,
|
||||||
selectIsCurrentUserFrozen,
|
selectIsCurrentUserFrozen,
|
||||||
selectIsCurrentUserPremium,
|
selectIsCurrentUserPremium,
|
||||||
selectIsDocumentGroupSelected,
|
selectIsDocumentGroupSelected,
|
||||||
selectIsInSelectMode,
|
selectIsInSelectMode,
|
||||||
|
selectIsMediaNsfw,
|
||||||
selectIsMessageFocused,
|
selectIsMessageFocused,
|
||||||
selectIsMessageProtected,
|
selectIsMessageProtected,
|
||||||
selectIsMessageSelected,
|
selectIsMessageSelected,
|
||||||
@ -211,9 +213,6 @@ type MessagePositionProperties = {
|
|||||||
type OwnProps =
|
type OwnProps =
|
||||||
{
|
{
|
||||||
message: ApiMessage;
|
message: ApiMessage;
|
||||||
observeIntersectionForBottom?: ObserveFn;
|
|
||||||
observeIntersectionForLoading?: ObserveFn;
|
|
||||||
observeIntersectionForPlaying?: ObserveFn;
|
|
||||||
album?: IAlbum;
|
album?: IAlbum;
|
||||||
noAvatars?: boolean;
|
noAvatars?: boolean;
|
||||||
withAvatar?: boolean;
|
withAvatar?: boolean;
|
||||||
@ -226,6 +225,9 @@ type OwnProps =
|
|||||||
isJustAdded: boolean;
|
isJustAdded: boolean;
|
||||||
memoFirstUnreadIdRef?: { current: number | undefined };
|
memoFirstUnreadIdRef?: { current: number | undefined };
|
||||||
getIsMessageListReady?: Signal<boolean>;
|
getIsMessageListReady?: Signal<boolean>;
|
||||||
|
observeIntersectionForBottom?: ObserveFn;
|
||||||
|
observeIntersectionForLoading?: ObserveFn;
|
||||||
|
observeIntersectionForPlaying?: ObserveFn;
|
||||||
onIntersectPinnedMessage?: OnIntersectPinnedMessage;
|
onIntersectPinnedMessage?: OnIntersectPinnedMessage;
|
||||||
}
|
}
|
||||||
& MessagePositionProperties;
|
& MessagePositionProperties;
|
||||||
@ -316,6 +318,8 @@ type StateProps = {
|
|||||||
isChatWithUser?: boolean;
|
isChatWithUser?: boolean;
|
||||||
isAccountFrozen?: boolean;
|
isAccountFrozen?: boolean;
|
||||||
minFutureTime?: number;
|
minFutureTime?: number;
|
||||||
|
isMediaNsfw?: boolean;
|
||||||
|
isReplyMediaNsfw?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type MetaPosition =
|
type MetaPosition =
|
||||||
@ -437,11 +441,13 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
poll,
|
poll,
|
||||||
maxTimestamp,
|
maxTimestamp,
|
||||||
lastPlaybackTimestamp,
|
lastPlaybackTimestamp,
|
||||||
onIntersectPinnedMessage,
|
isMediaNsfw,
|
||||||
|
isReplyMediaNsfw,
|
||||||
paidMessageStars,
|
paidMessageStars,
|
||||||
isChatWithUser,
|
isChatWithUser,
|
||||||
isAccountFrozen,
|
isAccountFrozen,
|
||||||
minFutureTime,
|
minFutureTime,
|
||||||
|
onIntersectPinnedMessage,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
toggleMessageSelection,
|
toggleMessageSelection,
|
||||||
@ -1119,6 +1125,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
senderChat={replyMessageChat}
|
senderChat={replyMessageChat}
|
||||||
forwardSender={replyMessageForwardSender}
|
forwardSender={replyMessageForwardSender}
|
||||||
chatTranslations={chatTranslations}
|
chatTranslations={chatTranslations}
|
||||||
|
isMediaNsfw={isReplyMediaNsfw}
|
||||||
requestedChatTranslationLanguage={requestedChatTranslationLanguage}
|
requestedChatTranslationLanguage={requestedChatTranslationLanguage}
|
||||||
observeIntersectionForLoading={observeIntersectionForLoading}
|
observeIntersectionForLoading={observeIntersectionForLoading}
|
||||||
observeIntersectionForPlaying={observeIntersectionForPlaying}
|
observeIntersectionForPlaying={observeIntersectionForPlaying}
|
||||||
@ -1145,6 +1152,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
shouldLoop={shouldLoopStickers}
|
shouldLoop={shouldLoopStickers}
|
||||||
shouldPlayEffect={shouldPlayEffect}
|
shouldPlayEffect={shouldPlayEffect}
|
||||||
withEffect={withAnimatedEffects}
|
withEffect={withAnimatedEffects}
|
||||||
|
isMediaNsfw={isMediaNsfw}
|
||||||
onStopEffect={hideEffect}
|
onStopEffect={hideEffect}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -1443,6 +1451,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
isProtected={isProtected}
|
isProtected={isProtected}
|
||||||
asForwarded={asForwarded}
|
asForwarded={asForwarded}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
|
isMediaNsfw={isMediaNsfw}
|
||||||
forcedWidth={contentWidth}
|
forcedWidth={contentWidth}
|
||||||
onClick={handlePhotoMediaClick}
|
onClick={handlePhotoMediaClick}
|
||||||
onCancelUpload={handleCancelUpload}
|
onCancelUpload={handleCancelUpload}
|
||||||
@ -1462,6 +1471,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
isDownloading={isDownloading}
|
isDownloading={isDownloading}
|
||||||
isProtected={isProtected}
|
isProtected={isProtected}
|
||||||
asForwarded={asForwarded}
|
asForwarded={asForwarded}
|
||||||
|
isMediaNsfw={isMediaNsfw}
|
||||||
lastPlaybackTimestamp={lastPlaybackTimestamp}
|
lastPlaybackTimestamp={lastPlaybackTimestamp}
|
||||||
onClick={handleVideoMediaClick}
|
onClick={handleVideoMediaClick}
|
||||||
onCancelUpload={handleCancelUpload}
|
onCancelUpload={handleCancelUpload}
|
||||||
@ -1895,7 +1905,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const replyMessageChat = replyToPeerId ? selectChat(global, replyToPeerId) : undefined;
|
const replyMessageChat = replyToPeerId ? selectChat(global, replyToPeerId) : undefined;
|
||||||
const isReplyPrivate = !isSystemBotChat && !isAnonymousForwards && replyMessageChat
|
const isReplyPrivate = !isSystemBotChat && !isAnonymousForwards && replyMessageChat
|
||||||
&& !isChatPublic(replyMessageChat)
|
&& !isChatPublic(replyMessageChat)
|
||||||
&& (replyMessageChat.isNotJoined || replyMessageChat.isRestricted);
|
&& (replyMessageChat.isNotJoined || selectIsChatRestricted(global, replyMessageChat.id));
|
||||||
const isReplyToTopicStart = replyMessage?.content.action?.type === 'topicCreate';
|
const isReplyToTopicStart = replyMessage?.content.action?.type === 'topicCreate';
|
||||||
const replyStory = storyReplyId && storyReplyPeerId
|
const replyStory = storyReplyId && storyReplyPeerId
|
||||||
? selectPeerStory(global, storyReplyPeerId, storyReplyId)
|
? selectPeerStory(global, storyReplyPeerId, storyReplyId)
|
||||||
@ -1982,6 +1992,9 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
|
|
||||||
const minFutureTime = global.appConfig?.starsSuggestedPostFutureMin || STARS_SUGGESTED_POST_FUTURE_MIN;
|
const minFutureTime = global.appConfig?.starsSuggestedPostFutureMin || STARS_SUGGESTED_POST_FUTURE_MIN;
|
||||||
|
|
||||||
|
const isMediaNsfw = selectIsMediaNsfw(global, message);
|
||||||
|
const isReplyMediaNsfw = replyMessage && selectIsMediaNsfw(global, replyMessage);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
theme: selectTheme(global),
|
theme: selectTheme(global),
|
||||||
forceSenderName,
|
forceSenderName,
|
||||||
@ -2076,6 +2089,8 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
paidMessageStars,
|
paidMessageStars,
|
||||||
isChatWithUser,
|
isChatWithUser,
|
||||||
isAccountFrozen,
|
isAccountFrozen,
|
||||||
|
isMediaNsfw,
|
||||||
|
isReplyMediaNsfw,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(Message));
|
)(Message));
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import type React from '../../../lib/teact/teact';
|
import type React from '../../../lib/teact/teact';
|
||||||
import { useEffect, useRef, useState } from '../../../lib/teact/teact';
|
import { memo, useEffect, useRef, useState } from '../../../lib/teact/teact';
|
||||||
|
import { getActions, withGlobal } from '../../../global';
|
||||||
|
|
||||||
import type { ApiMediaExtendedPreview, ApiPhoto } from '../../../api/types';
|
import type { ApiMediaExtendedPreview, ApiPhoto } from '../../../api/types';
|
||||||
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||||
@ -28,6 +29,7 @@ import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
|||||||
|
|
||||||
import Icon from '../../common/icons/Icon';
|
import Icon from '../../common/icons/Icon';
|
||||||
import MediaSpoiler from '../../common/MediaSpoiler';
|
import MediaSpoiler from '../../common/MediaSpoiler';
|
||||||
|
import SensitiveContentConfirmModal from '../../common/SensitiveContentConfirmModal';
|
||||||
import ProgressSpinner from '../../ui/ProgressSpinner';
|
import ProgressSpinner from '../../ui/ProgressSpinner';
|
||||||
|
|
||||||
export type OwnProps<T> = {
|
export type OwnProps<T> = {
|
||||||
@ -36,7 +38,6 @@ export type OwnProps<T> = {
|
|||||||
isInWebPage?: boolean;
|
isInWebPage?: boolean;
|
||||||
messageText?: string;
|
messageText?: string;
|
||||||
isOwn?: boolean;
|
isOwn?: boolean;
|
||||||
observeIntersection?: ObserveFn;
|
|
||||||
noAvatars?: boolean;
|
noAvatars?: boolean;
|
||||||
canAutoLoad?: boolean;
|
canAutoLoad?: boolean;
|
||||||
isInSelectMode?: boolean;
|
isInSelectMode?: boolean;
|
||||||
@ -53,16 +54,21 @@ export type OwnProps<T> = {
|
|||||||
theme: ThemeKey;
|
theme: ThemeKey;
|
||||||
className?: string;
|
className?: string;
|
||||||
clickArg?: T;
|
clickArg?: T;
|
||||||
|
isMediaNsfw?: boolean;
|
||||||
|
observeIntersection?: ObserveFn;
|
||||||
onClick?: (arg: T, e: React.MouseEvent<HTMLElement>) => void;
|
onClick?: (arg: T, e: React.MouseEvent<HTMLElement>) => void;
|
||||||
onCancelUpload?: (arg: T) => void;
|
onCancelUpload?: (arg: T) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type StateProps = {
|
||||||
|
needsAgeVerification?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
const Photo = <T,>({
|
const Photo = <T,>({
|
||||||
id,
|
id,
|
||||||
photo,
|
photo,
|
||||||
messageText,
|
messageText,
|
||||||
isOwn,
|
isOwn,
|
||||||
observeIntersection,
|
|
||||||
noAvatars,
|
noAvatars,
|
||||||
canAutoLoad,
|
canAutoLoad,
|
||||||
isInSelectMode,
|
isInSelectMode,
|
||||||
@ -80,9 +86,12 @@ const Photo = <T,>({
|
|||||||
isInWebPage,
|
isInWebPage,
|
||||||
clickArg,
|
clickArg,
|
||||||
className,
|
className,
|
||||||
|
isMediaNsfw,
|
||||||
|
observeIntersection,
|
||||||
onClick,
|
onClick,
|
||||||
onCancelUpload,
|
onCancelUpload,
|
||||||
}: OwnProps<T>) => {
|
needsAgeVerification,
|
||||||
|
}: OwnProps<T> & StateProps) => {
|
||||||
const ref = useRef<HTMLDivElement>();
|
const ref = useRef<HTMLDivElement>();
|
||||||
const isPaidPreview = photo.mediaType === 'extendedMediaPreview';
|
const isPaidPreview = photo.mediaType === 'extendedMediaPreview';
|
||||||
|
|
||||||
@ -106,15 +115,29 @@ const Photo = <T,>({
|
|||||||
const blurredBackgroundRef = useBlurredMediaThumbRef(photo, !withBlurredBackground);
|
const blurredBackgroundRef = useBlurredMediaThumbRef(photo, !withBlurredBackground);
|
||||||
const thumbDataUri = getMediaThumbUri(photo);
|
const thumbDataUri = getMediaThumbUri(photo);
|
||||||
|
|
||||||
const [isSpoilerShown, showSpoiler, hideSpoiler] = useFlag(isPaidPreview || photo.isSpoiler);
|
const { updateContentSettings, openAgeVerificationModal } = getActions();
|
||||||
|
const [isNsfwModalOpen, openNsfwModal, closeNsfwModal] = useFlag();
|
||||||
|
const [shouldAlwaysShowNsfw, setShouldAlwaysShowNsfw] = useState(false);
|
||||||
|
|
||||||
|
const shouldShowSpoiler = isPaidPreview || photo.isSpoiler || isMediaNsfw;
|
||||||
|
const [isSpoilerShown, showSpoiler, hideSpoiler] = useFlag(shouldShowSpoiler);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isPaidPreview || photo.isSpoiler) {
|
if (shouldShowSpoiler) {
|
||||||
showSpoiler();
|
showSpoiler();
|
||||||
} else {
|
} else {
|
||||||
hideSpoiler();
|
hideSpoiler();
|
||||||
}
|
}
|
||||||
}, [isPaidPreview, photo]);
|
}, [shouldShowSpoiler]);
|
||||||
|
|
||||||
|
const handleNsfwConfirm = useLastCallback(() => {
|
||||||
|
closeNsfwModal();
|
||||||
|
hideSpoiler();
|
||||||
|
|
||||||
|
if (shouldAlwaysShowNsfw) {
|
||||||
|
updateContentSettings({ isSensitiveEnabled: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
loadProgress: downloadProgress,
|
loadProgress: downloadProgress,
|
||||||
@ -162,6 +185,14 @@ const Photo = <T,>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isSpoilerShown) {
|
if (isSpoilerShown) {
|
||||||
|
if (isMediaNsfw) {
|
||||||
|
if (needsAgeVerification) {
|
||||||
|
openAgeVerificationModal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
openNsfwModal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
hideSpoiler();
|
hideSpoiler();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -250,6 +281,7 @@ const Photo = <T,>({
|
|||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
className="media-spoiler"
|
className="media-spoiler"
|
||||||
|
isNsfw={isMediaNsfw}
|
||||||
/>
|
/>
|
||||||
{isTransferring && (
|
{isTransferring && (
|
||||||
<span className="message-transfer-progress">
|
<span className="message-transfer-progress">
|
||||||
@ -257,8 +289,22 @@ const Photo = <T,>({
|
|||||||
%
|
%
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
<SensitiveContentConfirmModal
|
||||||
|
isOpen={isNsfwModalOpen}
|
||||||
|
onClose={closeNsfwModal}
|
||||||
|
shouldAlwaysShow={shouldAlwaysShowNsfw}
|
||||||
|
onAlwaysShowChanged={setShouldAlwaysShowNsfw}
|
||||||
|
confirmHandler={handleNsfwConfirm}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Photo;
|
export default memo(withGlobal((global): StateProps => {
|
||||||
|
const appConfig = global.appConfig;
|
||||||
|
const needsAgeVerification = appConfig?.needAgeVideoVerification;
|
||||||
|
|
||||||
|
return {
|
||||||
|
needsAgeVerification,
|
||||||
|
};
|
||||||
|
})(Photo));
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import type { FC } from '../../../lib/teact/teact';
|
import type { FC } from '../../../lib/teact/teact';
|
||||||
import { useEffect, useRef } from '../../../lib/teact/teact';
|
import { memo, useEffect, useRef, useState } from '../../../lib/teact/teact';
|
||||||
import { getActions } from '../../../global';
|
import { getActions, withGlobal } from '../../../global';
|
||||||
|
|
||||||
import type { ApiMessage } from '../../../api/types';
|
import type { ApiMessage } from '../../../api/types';
|
||||||
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||||
import { ApiMediaFormat } from '../../../api/types';
|
import { ApiMediaFormat } from '../../../api/types';
|
||||||
|
|
||||||
import { getStickerMediaHash } from '../../../global/helpers';
|
import { getMediaThumbUri, getStickerMediaHash } from '../../../global/helpers';
|
||||||
import { IS_WEBM_SUPPORTED } from '../../../util/browser/windowEnvironment';
|
import { IS_WEBM_SUPPORTED } from '../../../util/browser/windowEnvironment';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import { getStickerDimensions } from '../../common/helpers/mediaDimensions';
|
import { getStickerDimensions } from '../../common/helpers/mediaDimensions';
|
||||||
@ -20,6 +20,8 @@ import useOldLang from '../../../hooks/useOldLang';
|
|||||||
import useOverlayPosition from './hooks/useOverlayPosition';
|
import useOverlayPosition from './hooks/useOverlayPosition';
|
||||||
|
|
||||||
import AnimatedSticker from '../../common/AnimatedSticker';
|
import AnimatedSticker from '../../common/AnimatedSticker';
|
||||||
|
import MediaSpoiler from '../../common/MediaSpoiler';
|
||||||
|
import SensitiveContentConfirmModal from '../../common/SensitiveContentConfirmModal';
|
||||||
import StickerView from '../../common/StickerView';
|
import StickerView from '../../common/StickerView';
|
||||||
import Portal from '../../ui/Portal';
|
import Portal from '../../ui/Portal';
|
||||||
|
|
||||||
@ -30,19 +32,31 @@ const EFFECT_SIZE_MULTIPLIER = 1 + 0.245 * 2;
|
|||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
message: ApiMessage;
|
message: ApiMessage;
|
||||||
observeIntersection: ObserveFn;
|
|
||||||
observeIntersectionForPlaying: ObserveFn;
|
|
||||||
shouldLoop?: boolean;
|
shouldLoop?: boolean;
|
||||||
shouldPlayEffect?: boolean;
|
shouldPlayEffect?: boolean;
|
||||||
withEffect?: boolean;
|
withEffect?: boolean;
|
||||||
|
isMediaNsfw?: boolean;
|
||||||
|
observeIntersection: ObserveFn;
|
||||||
|
observeIntersectionForPlaying: ObserveFn;
|
||||||
onStopEffect?: VoidFunction;
|
onStopEffect?: VoidFunction;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Sticker: FC<OwnProps> = ({
|
type StateProps = {
|
||||||
message, observeIntersection, observeIntersectionForPlaying, shouldLoop,
|
needsAgeVerification?: boolean;
|
||||||
shouldPlayEffect, withEffect, onStopEffect,
|
};
|
||||||
|
|
||||||
|
const Sticker: FC<OwnProps & StateProps> = ({
|
||||||
|
message,
|
||||||
|
shouldLoop,
|
||||||
|
shouldPlayEffect,
|
||||||
|
withEffect,
|
||||||
|
isMediaNsfw,
|
||||||
|
onStopEffect,
|
||||||
|
observeIntersection,
|
||||||
|
observeIntersectionForPlaying,
|
||||||
|
needsAgeVerification,
|
||||||
}) => {
|
}) => {
|
||||||
const { showNotification, openStickerSet } = getActions();
|
const { showNotification, openStickerSet, updateContentSettings, openAgeVerificationModal } = getActions();
|
||||||
|
|
||||||
const lang = useOldLang();
|
const lang = useOldLang();
|
||||||
const { isMobile } = useAppLayout();
|
const { isMobile } = useAppLayout();
|
||||||
@ -55,6 +69,29 @@ const Sticker: FC<OwnProps> = ({
|
|||||||
const { stickerSetInfo, isVideo, hasEffect } = sticker;
|
const { stickerSetInfo, isVideo, hasEffect } = sticker;
|
||||||
const isMirrored = !message.isOutgoing;
|
const isMirrored = !message.isOutgoing;
|
||||||
|
|
||||||
|
const [isNsfwModalOpen, openNsfwModal, closeNsfwModal] = useFlag();
|
||||||
|
const [shouldAlwaysShowNsfw, setShouldAlwaysShowNsfw] = useState(false);
|
||||||
|
|
||||||
|
const shouldShowSpoiler = isMediaNsfw;
|
||||||
|
const [isSpoilerShown, showSpoiler, hideSpoiler] = useFlag(shouldShowSpoiler);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (shouldShowSpoiler) {
|
||||||
|
showSpoiler();
|
||||||
|
} else {
|
||||||
|
hideSpoiler();
|
||||||
|
}
|
||||||
|
}, [shouldShowSpoiler]);
|
||||||
|
|
||||||
|
const handleNsfwConfirm = useLastCallback(() => {
|
||||||
|
closeNsfwModal();
|
||||||
|
hideSpoiler();
|
||||||
|
|
||||||
|
if (shouldAlwaysShowNsfw) {
|
||||||
|
updateContentSettings({ isSensitiveEnabled: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const mediaHash = sticker.isPreloadedGlobally ? undefined : (
|
const mediaHash = sticker.isPreloadedGlobally ? undefined : (
|
||||||
getStickerMediaHash(sticker, isVideo && !IS_WEBM_SUPPORTED ? 'pictogram' : 'inline')
|
getStickerMediaHash(sticker, isVideo && !IS_WEBM_SUPPORTED ? 'pictogram' : 'inline')
|
||||||
);
|
);
|
||||||
@ -69,6 +106,8 @@ const Sticker: FC<OwnProps> = ({
|
|||||||
);
|
);
|
||||||
const [isPlayingEffect, startPlayingEffect, stopPlayingEffect] = useFlag();
|
const [isPlayingEffect, startPlayingEffect, stopPlayingEffect] = useFlag();
|
||||||
|
|
||||||
|
const thumbDataUri = getMediaThumbUri(sticker);
|
||||||
|
|
||||||
const handleEffectEnded = useLastCallback(() => {
|
const handleEffectEnded = useLastCallback(() => {
|
||||||
stopPlayingEffect();
|
stopPlayingEffect();
|
||||||
onStopEffect?.();
|
onStopEffect?.();
|
||||||
@ -95,6 +134,19 @@ const Sticker: FC<OwnProps> = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleClick = useLastCallback(() => {
|
const handleClick = useLastCallback(() => {
|
||||||
|
if (isSpoilerShown) {
|
||||||
|
if (isMediaNsfw) {
|
||||||
|
if (needsAgeVerification) {
|
||||||
|
openAgeVerificationModal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
openNsfwModal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hideSpoiler();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (hasEffect) {
|
if (hasEffect) {
|
||||||
if (isPlayingEffect || !withEffect) {
|
if (isPlayingEffect || !withEffect) {
|
||||||
showNotification({
|
showNotification({
|
||||||
@ -143,6 +195,15 @@ const Sticker: FC<OwnProps> = ({
|
|||||||
noPlay={!canPlay}
|
noPlay={!canPlay}
|
||||||
withSharedAnimation
|
withSharedAnimation
|
||||||
/>
|
/>
|
||||||
|
<MediaSpoiler
|
||||||
|
isVisible={isSpoilerShown}
|
||||||
|
withAnimation
|
||||||
|
thumbDataUri={thumbDataUri}
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
className="media-spoiler"
|
||||||
|
isNsfw={isMediaNsfw}
|
||||||
|
/>
|
||||||
{shouldRenderEffect && (
|
{shouldRenderEffect && (
|
||||||
<Portal>
|
<Portal>
|
||||||
<AnimatedSticker
|
<AnimatedSticker
|
||||||
@ -158,8 +219,22 @@ const Sticker: FC<OwnProps> = ({
|
|||||||
/>
|
/>
|
||||||
</Portal>
|
</Portal>
|
||||||
)}
|
)}
|
||||||
|
<SensitiveContentConfirmModal
|
||||||
|
isOpen={isNsfwModalOpen}
|
||||||
|
onClose={closeNsfwModal}
|
||||||
|
shouldAlwaysShow={shouldAlwaysShowNsfw}
|
||||||
|
onAlwaysShowChanged={setShouldAlwaysShowNsfw}
|
||||||
|
confirmHandler={handleNsfwConfirm}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Sticker;
|
export default memo(withGlobal<OwnProps>((global): StateProps => {
|
||||||
|
const appConfig = global.appConfig;
|
||||||
|
const needsAgeVerification = appConfig?.needAgeVideoVerification;
|
||||||
|
|
||||||
|
return {
|
||||||
|
needsAgeVerification,
|
||||||
|
};
|
||||||
|
})(Sticker));
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import type React from '../../../lib/teact/teact';
|
import type React from '../../../lib/teact/teact';
|
||||||
import { useEffect, useRef, useState } from '../../../lib/teact/teact';
|
import { memo, useEffect, useRef, useState } from '../../../lib/teact/teact';
|
||||||
import { getActions } from '../../../global';
|
import { getActions, withGlobal } from '../../../global';
|
||||||
|
|
||||||
import type { ApiMediaExtendedPreview, ApiVideo } from '../../../api/types';
|
import type { ApiMediaExtendedPreview, ApiVideo } from '../../../api/types';
|
||||||
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||||
@ -29,6 +29,7 @@ import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
|||||||
|
|
||||||
import Icon from '../../common/icons/Icon';
|
import Icon from '../../common/icons/Icon';
|
||||||
import MediaSpoiler from '../../common/MediaSpoiler';
|
import MediaSpoiler from '../../common/MediaSpoiler';
|
||||||
|
import SensitiveContentConfirmModal from '../../common/SensitiveContentConfirmModal';
|
||||||
import OptimizedVideo from '../../ui/OptimizedVideo';
|
import OptimizedVideo from '../../ui/OptimizedVideo';
|
||||||
import ProgressSpinner from '../../ui/ProgressSpinner';
|
import ProgressSpinner from '../../ui/ProgressSpinner';
|
||||||
|
|
||||||
@ -38,8 +39,6 @@ export type OwnProps<T> = {
|
|||||||
lastPlaybackTimestamp?: number;
|
lastPlaybackTimestamp?: number;
|
||||||
isOwn?: boolean;
|
isOwn?: boolean;
|
||||||
isInWebPage?: boolean;
|
isInWebPage?: boolean;
|
||||||
observeIntersectionForLoading?: ObserveFn;
|
|
||||||
observeIntersectionForPlaying?: ObserveFn;
|
|
||||||
noAvatars?: boolean;
|
noAvatars?: boolean;
|
||||||
canAutoLoad?: boolean;
|
canAutoLoad?: boolean;
|
||||||
canAutoPlay?: boolean;
|
canAutoPlay?: boolean;
|
||||||
@ -51,17 +50,22 @@ export type OwnProps<T> = {
|
|||||||
isProtected?: boolean;
|
isProtected?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
clickArg?: T;
|
clickArg?: T;
|
||||||
|
isMediaNsfw?: boolean;
|
||||||
|
observeIntersectionForLoading?: ObserveFn;
|
||||||
|
observeIntersectionForPlaying?: ObserveFn;
|
||||||
onClick?: (arg: T, e: React.MouseEvent<HTMLElement>) => void;
|
onClick?: (arg: T, e: React.MouseEvent<HTMLElement>) => void;
|
||||||
onCancelUpload?: (arg: T) => void;
|
onCancelUpload?: (arg: T) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type StateProps = {
|
||||||
|
needsAgeVerification?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
const Video = <T,>({
|
const Video = <T,>({
|
||||||
id,
|
id,
|
||||||
video,
|
video,
|
||||||
isOwn,
|
isOwn,
|
||||||
isInWebPage,
|
isInWebPage,
|
||||||
observeIntersectionForLoading,
|
|
||||||
observeIntersectionForPlaying,
|
|
||||||
noAvatars,
|
noAvatars,
|
||||||
canAutoLoad,
|
canAutoLoad,
|
||||||
canAutoPlay,
|
canAutoPlay,
|
||||||
@ -74,26 +78,42 @@ const Video = <T,>({
|
|||||||
className,
|
className,
|
||||||
lastPlaybackTimestamp,
|
lastPlaybackTimestamp,
|
||||||
clickArg,
|
clickArg,
|
||||||
|
isMediaNsfw,
|
||||||
|
observeIntersectionForLoading,
|
||||||
|
observeIntersectionForPlaying,
|
||||||
onClick,
|
onClick,
|
||||||
onCancelUpload,
|
onCancelUpload,
|
||||||
}: OwnProps<T>) => {
|
needsAgeVerification,
|
||||||
const { cancelMediaDownload } = getActions();
|
}: OwnProps<T> & StateProps) => {
|
||||||
|
const { cancelMediaDownload, updateContentSettings, openAgeVerificationModal } = getActions();
|
||||||
const ref = useRef<HTMLDivElement>();
|
const ref = useRef<HTMLDivElement>();
|
||||||
const videoRef = useRef<HTMLVideoElement>();
|
const videoRef = useRef<HTMLVideoElement>();
|
||||||
|
const [isNsfwModalOpen, openNsfwModal, closeNsfwModal] = useFlag();
|
||||||
|
const [shouldAlwaysShowNsfw, setShouldAlwaysShowNsfw] = useState(false);
|
||||||
|
|
||||||
const isPaidPreview = video.mediaType === 'extendedMediaPreview';
|
const isPaidPreview = video.mediaType === 'extendedMediaPreview';
|
||||||
|
|
||||||
const localBlobUrl = !isPaidPreview ? video.blobUrl : undefined;
|
const localBlobUrl = !isPaidPreview ? video.blobUrl : undefined;
|
||||||
|
|
||||||
const [isSpoilerShown, showSpoiler, hideSpoiler] = useFlag(isPaidPreview || video.isSpoiler);
|
const shouldShowSpoiler = isPaidPreview || video.isSpoiler || isMediaNsfw;
|
||||||
|
const [isSpoilerShown, showSpoiler, hideSpoiler] = useFlag(shouldShowSpoiler);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isPaidPreview || video.isSpoiler) {
|
if (shouldShowSpoiler) {
|
||||||
showSpoiler();
|
showSpoiler();
|
||||||
} else {
|
} else {
|
||||||
hideSpoiler();
|
hideSpoiler();
|
||||||
}
|
}
|
||||||
}, [isPaidPreview, video]);
|
}, [shouldShowSpoiler]);
|
||||||
|
|
||||||
|
const handleNsfwConfirm = useLastCallback(() => {
|
||||||
|
closeNsfwModal();
|
||||||
|
hideSpoiler();
|
||||||
|
|
||||||
|
if (shouldAlwaysShowNsfw) {
|
||||||
|
updateContentSettings({ isSensitiveEnabled: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const isIntersectingForLoading = useIsIntersecting(ref, observeIntersectionForLoading);
|
const isIntersectingForLoading = useIsIntersecting(ref, observeIntersectionForLoading);
|
||||||
const isIntersectingForPlaying = (
|
const isIntersectingForPlaying = (
|
||||||
@ -204,6 +224,14 @@ const Video = <T,>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isSpoilerShown) {
|
if (isSpoilerShown) {
|
||||||
|
if (isMediaNsfw) {
|
||||||
|
if (needsAgeVerification) {
|
||||||
|
openAgeVerificationModal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
openNsfwModal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
hideSpoiler();
|
hideSpoiler();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -278,6 +306,7 @@ const Video = <T,>({
|
|||||||
isVisible={isSpoilerShown}
|
isVisible={isSpoilerShown}
|
||||||
withAnimation
|
withAnimation
|
||||||
thumbDataUri={thumbDataUri}
|
thumbDataUri={thumbDataUri}
|
||||||
|
isNsfw={isMediaNsfw}
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
className="media-spoiler"
|
className="media-spoiler"
|
||||||
@ -309,8 +338,22 @@ const Video = <T,>({
|
|||||||
style={`--_progress: ${Math.floor((lastPlaybackTimestamp / duration) * 100)}%`}
|
style={`--_progress: ${Math.floor((lastPlaybackTimestamp / duration) * 100)}%`}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<SensitiveContentConfirmModal
|
||||||
|
isOpen={isNsfwModalOpen}
|
||||||
|
onClose={closeNsfwModal}
|
||||||
|
shouldAlwaysShow={shouldAlwaysShowNsfw}
|
||||||
|
onAlwaysShowChanged={setShouldAlwaysShowNsfw}
|
||||||
|
confirmHandler={handleNsfwConfirm}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Video;
|
export default memo(withGlobal((global): StateProps => {
|
||||||
|
const appConfig = global.appConfig;
|
||||||
|
const needsAgeVerification = appConfig?.needAgeVideoVerification;
|
||||||
|
|
||||||
|
return {
|
||||||
|
needsAgeVerification,
|
||||||
|
};
|
||||||
|
})(Video));
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { pick } from '../../util/iteratees';
|
|||||||
import VerificationMonetizationModal from '../common/VerificationMonetizationModal.async';
|
import VerificationMonetizationModal from '../common/VerificationMonetizationModal.async';
|
||||||
import WebAppsCloseConfirmationModal from '../main/WebAppsCloseConfirmationModal.async';
|
import WebAppsCloseConfirmationModal from '../main/WebAppsCloseConfirmationModal.async';
|
||||||
import AboutAdsModal from './aboutAds/AboutAdsModal.async';
|
import AboutAdsModal from './aboutAds/AboutAdsModal.async';
|
||||||
|
import AgeVerificationModal from './ageVerification/AgeVerificationModal.async';
|
||||||
import AttachBotInstallModal from './attachBotInstall/AttachBotInstallModal.async';
|
import AttachBotInstallModal from './attachBotInstall/AttachBotInstallModal.async';
|
||||||
import BoostModal from './boost/BoostModal.async';
|
import BoostModal from './boost/BoostModal.async';
|
||||||
import ChatInviteModal from './chatInvite/ChatInviteModal.async';
|
import ChatInviteModal from './chatInvite/ChatInviteModal.async';
|
||||||
@ -89,7 +90,8 @@ type ModalKey = keyof Pick<TabState,
|
|||||||
'giftTransferModal' |
|
'giftTransferModal' |
|
||||||
'chatRefundModal' |
|
'chatRefundModal' |
|
||||||
'isFrozenAccountModalOpen' |
|
'isFrozenAccountModalOpen' |
|
||||||
'deleteAccountModal'
|
'deleteAccountModal' |
|
||||||
|
'isAgeVerificationModalOpen'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type StateProps = {
|
type StateProps = {
|
||||||
@ -145,6 +147,7 @@ const MODALS: ModalRegistry = {
|
|||||||
chatRefundModal: ChatRefundModal,
|
chatRefundModal: ChatRefundModal,
|
||||||
isFrozenAccountModalOpen: FrozenAccountModal,
|
isFrozenAccountModalOpen: FrozenAccountModal,
|
||||||
deleteAccountModal: DeleteAccountModal,
|
deleteAccountModal: DeleteAccountModal,
|
||||||
|
isAgeVerificationModalOpen: AgeVerificationModal,
|
||||||
};
|
};
|
||||||
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>;
|
||||||
|
|||||||
@ -0,0 +1,18 @@
|
|||||||
|
import type { FC } from '../../../lib/teact/teact';
|
||||||
|
import { memo } from '../../../lib/teact/teact';
|
||||||
|
|
||||||
|
import type { OwnProps } from './AgeVerificationModal';
|
||||||
|
|
||||||
|
import { Bundles } from '../../../util/moduleLoader';
|
||||||
|
|
||||||
|
import useModuleLoader from '../../../hooks/useModuleLoader';
|
||||||
|
|
||||||
|
const AgeVerificationModalAsync: FC<OwnProps> = memo((props) => {
|
||||||
|
const { modal } = props;
|
||||||
|
|
||||||
|
const AgeVerificationModal = useModuleLoader(Bundles.Extra, 'AgeVerificationModal', !modal);
|
||||||
|
|
||||||
|
return AgeVerificationModal ? <AgeVerificationModal {...props} /> : undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
export default AgeVerificationModalAsync;
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
.root {
|
||||||
|
:global(.modal-dialog) {
|
||||||
|
max-width: 25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 1rem 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconWrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
width: 4rem;
|
||||||
|
height: 4rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
font-size: 2rem;
|
||||||
|
color: var(--color-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainText,
|
||||||
|
.description {
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
import type { FC } from '../../../lib/teact/teact';
|
||||||
|
import { memo } from '../../../lib/teact/teact';
|
||||||
|
import { getActions, withGlobal } from '../../../global';
|
||||||
|
|
||||||
|
import type { TabState } from '../../../global/types';
|
||||||
|
|
||||||
|
import useLang from '../../../hooks/useLang';
|
||||||
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
|
|
||||||
|
import Icon from '../../common/icons/Icon';
|
||||||
|
import Button from '../../ui/Button';
|
||||||
|
import Modal from '../../ui/Modal';
|
||||||
|
|
||||||
|
import styles from './AgeVerificationModal.module.scss';
|
||||||
|
|
||||||
|
export type OwnProps = {
|
||||||
|
modal: TabState['isAgeVerificationModalOpen'];
|
||||||
|
};
|
||||||
|
|
||||||
|
type StateProps = {
|
||||||
|
verifyAgeBotUsername?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const AGE_REQUIRED = 18;
|
||||||
|
|
||||||
|
const AgeVerificationModal: FC<OwnProps & StateProps> = ({
|
||||||
|
modal,
|
||||||
|
verifyAgeBotUsername,
|
||||||
|
}) => {
|
||||||
|
const { closeAgeVerificationModal, openChatByUsername } = getActions();
|
||||||
|
const lang = useLang();
|
||||||
|
const isOpen = Boolean(modal);
|
||||||
|
const ageRequired = AGE_REQUIRED;
|
||||||
|
|
||||||
|
const handleVerifyAge = useLastCallback(() => {
|
||||||
|
if (verifyAgeBotUsername) {
|
||||||
|
openChatByUsername({
|
||||||
|
shouldStartMainApp: true,
|
||||||
|
username: verifyAgeBotUsername,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
closeAgeVerificationModal();
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleClose = useLastCallback(() => {
|
||||||
|
closeAgeVerificationModal();
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
isOpen={isOpen}
|
||||||
|
onClose={handleClose}
|
||||||
|
className={styles.root}
|
||||||
|
>
|
||||||
|
<div className={styles.content}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<div className={styles.iconWrapper}>
|
||||||
|
<Icon name="user" className={styles.icon} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2 className={styles.title}>
|
||||||
|
{lang('TitleAgeVerificationModal')}
|
||||||
|
</h2>
|
||||||
|
<p className={styles.mainText}>
|
||||||
|
{lang('TextAgeVerificationModal', { count: ageRequired }, {
|
||||||
|
withMarkdown: true,
|
||||||
|
withNodes: true,
|
||||||
|
pluralValue: ageRequired,
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
<p className={styles.description}>
|
||||||
|
{lang('DescriptionAgeVerificationModal')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="dialog-buttons mt-2">
|
||||||
|
<Button
|
||||||
|
onClick={handleVerifyAge}
|
||||||
|
>
|
||||||
|
{lang('ButtonAgeVerification')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(withGlobal((global): StateProps => {
|
||||||
|
const appConfig = global.appConfig;
|
||||||
|
const verifyAgeBotUsername = appConfig?.verifyAgeBotUsername;
|
||||||
|
|
||||||
|
return {
|
||||||
|
verifyAgeBotUsername,
|
||||||
|
};
|
||||||
|
})(AgeVerificationModal));
|
||||||
@ -50,6 +50,7 @@ const useWebAppFrame = (
|
|||||||
closeWebApp,
|
closeWebApp,
|
||||||
openSuggestedStatusModal,
|
openSuggestedStatusModal,
|
||||||
updateWebApp,
|
updateWebApp,
|
||||||
|
updateContentSettings,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
const isReloadSupported = useRef<boolean>(false);
|
const isReloadSupported = useRef<boolean>(false);
|
||||||
@ -382,6 +383,25 @@ const useWebAppFrame = (
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (eventType === 'web_app_verify_age') {
|
||||||
|
const { passed } = eventData;
|
||||||
|
|
||||||
|
if (passed) {
|
||||||
|
showNotification({
|
||||||
|
message: {
|
||||||
|
key: 'TitleAgeCheckSuccess',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
updateContentSettings({ isSensitiveEnabled: true });
|
||||||
|
} else {
|
||||||
|
showNotification({
|
||||||
|
message: {
|
||||||
|
key: 'TitleAgeCheckFailed',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onEvent(data);
|
onEvent(data);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Ignore other messages
|
// Ignore other messages
|
||||||
|
|||||||
@ -48,6 +48,7 @@ import {
|
|||||||
selectChatFullInfo,
|
selectChatFullInfo,
|
||||||
selectChatMessages,
|
selectChatMessages,
|
||||||
selectCurrentSharedMediaSearch,
|
selectCurrentSharedMediaSearch,
|
||||||
|
selectIsChatRestricted,
|
||||||
selectIsCurrentUserPremium,
|
selectIsCurrentUserPremium,
|
||||||
selectIsRightColumnShown,
|
selectIsRightColumnShown,
|
||||||
selectMonoforumChannel,
|
selectMonoforumChannel,
|
||||||
@ -995,6 +996,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const peerGifts = selectTabState(global).savedGifts.giftsByPeerId[chatId];
|
const peerGifts = selectTabState(global).savedGifts.giftsByPeerId[chatId];
|
||||||
|
|
||||||
const monoforumChannel = selectMonoforumChannel(global, chatId);
|
const monoforumChannel = selectMonoforumChannel(global, chatId);
|
||||||
|
const isRestricted = chat && selectIsChatRestricted(global, chat.id);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
theme: selectTheme(global),
|
theme: selectTheme(global),
|
||||||
@ -1012,7 +1014,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
canDeleteMembers,
|
canDeleteMembers,
|
||||||
currentUserId: global.currentUserId,
|
currentUserId: global.currentUserId,
|
||||||
isRightColumnShown: selectIsRightColumnShown(global, isMobile),
|
isRightColumnShown: selectIsRightColumnShown(global, isMobile),
|
||||||
isRestricted: chat?.isRestricted,
|
isRestricted,
|
||||||
activeDownloads,
|
activeDownloads,
|
||||||
usersById,
|
usersById,
|
||||||
userStatusesById,
|
userStatusesById,
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import type { FC } from '../../../lib/teact/teact';
|
|||||||
import {
|
import {
|
||||||
memo, useEffect, useMemo, useState,
|
memo, useEffect, useMemo, useState,
|
||||||
} from '../../../lib/teact/teact';
|
} from '../../../lib/teact/teact';
|
||||||
import { getActions, withGlobal } from '../../../global';
|
import { getActions, getGlobal, withGlobal } from '../../../global';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ApiAvailableReaction, ApiChat, ApiChatFullInfo, ApiExportedInvite,
|
ApiAvailableReaction, ApiChat, ApiChatFullInfo, ApiExportedInvite,
|
||||||
@ -12,7 +12,7 @@ import { ApiMediaFormat } from '../../../api/types';
|
|||||||
import { ManagementProgress, ManagementScreens } from '../../../types';
|
import { ManagementProgress, ManagementScreens } from '../../../types';
|
||||||
|
|
||||||
import { getChatAvatarHash, getHasAdminRight, isChatChannel, isChatPublic } from '../../../global/helpers';
|
import { getChatAvatarHash, getHasAdminRight, isChatChannel, isChatPublic } from '../../../global/helpers';
|
||||||
import { selectChat, selectChatFullInfo, selectTabState } from '../../../global/selectors';
|
import { selectChat, selectChatFullInfo, selectIsChatRestricted, selectTabState } from '../../../global/selectors';
|
||||||
import { formatInteger } from '../../../util/textFormat';
|
import { formatInteger } from '../../../util/textFormat';
|
||||||
|
|
||||||
import useFlag from '../../../hooks/useFlag';
|
import useFlag from '../../../hooks/useFlag';
|
||||||
@ -217,7 +217,8 @@ const ManageChannel: FC<OwnProps & StateProps> = ({
|
|||||||
}, [availableReactions, chatFullInfo?.enabledReactions, lang]);
|
}, [availableReactions, chatFullInfo?.enabledReactions, lang]);
|
||||||
const isChannelPublic = useMemo(() => isChatPublic(chat), [chat]);
|
const isChannelPublic = useMemo(() => isChatPublic(chat), [chat]);
|
||||||
|
|
||||||
if (chat.isRestricted || chat.isForbidden) {
|
const isRestricted = selectIsChatRestricted(getGlobal(), chatId);
|
||||||
|
if (isRestricted || chat.isForbidden) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import type { FC } from '../../../lib/teact/teact';
|
|||||||
import {
|
import {
|
||||||
memo, useEffect, useMemo, useRef, useState,
|
memo, useEffect, useMemo, useRef, useState,
|
||||||
} from '../../../lib/teact/teact';
|
} from '../../../lib/teact/teact';
|
||||||
import { getActions, withGlobal } from '../../../global';
|
import { getActions, getGlobal, withGlobal } from '../../../global';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ApiAvailableReaction, ApiChat, ApiChatBannedRights, ApiChatFullInfo, ApiExportedInvite,
|
ApiAvailableReaction, ApiChat, ApiChatBannedRights, ApiChatFullInfo, ApiExportedInvite,
|
||||||
@ -17,7 +17,7 @@ import {
|
|||||||
isChatBasicGroup,
|
isChatBasicGroup,
|
||||||
isChatPublic,
|
isChatPublic,
|
||||||
} from '../../../global/helpers';
|
} from '../../../global/helpers';
|
||||||
import { selectChat, selectChatFullInfo, selectTabState } from '../../../global/selectors';
|
import { selectChat, selectChatFullInfo, selectIsChatRestricted, selectTabState } from '../../../global/selectors';
|
||||||
import { debounce } from '../../../util/schedulers';
|
import { debounce } from '../../../util/schedulers';
|
||||||
import { formatInteger } from '../../../util/textFormat';
|
import { formatInteger } from '../../../util/textFormat';
|
||||||
import renderText from '../../common/helpers/renderText';
|
import renderText from '../../common/helpers/renderText';
|
||||||
@ -312,7 +312,8 @@ const ManageGroup: FC<OwnProps & StateProps> = ({
|
|||||||
openChat({ id: undefined });
|
openChat({ id: undefined });
|
||||||
});
|
});
|
||||||
|
|
||||||
if (chat.isRestricted || chat.isForbidden) {
|
const isRestricted = selectIsChatRestricted(getGlobal(), chatId);
|
||||||
|
if (isRestricted || chat.isForbidden) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -344,6 +344,8 @@ export const TME_WEB_DOMAINS = new Set(['t.me', 'web.t.me', 'a.t.me', 'k.t.me',
|
|||||||
export const WEB_APP_PLATFORM = 'weba';
|
export const WEB_APP_PLATFORM = 'weba';
|
||||||
export const LANG_PACK = 'weba';
|
export const LANG_PACK = 'weba';
|
||||||
|
|
||||||
|
export const NSFW_RESTRICTION_REASON = 'sensitive';
|
||||||
|
|
||||||
// eslint-disable-next-line @stylistic/max-len
|
// eslint-disable-next-line @stylistic/max-len
|
||||||
export const COUNTRIES_WITH_12H_TIME_FORMAT = new Set(['AU', 'BD', 'CA', 'CO', 'EG', 'HN', 'IE', 'IN', 'JO', 'MX', 'MY', 'NI', 'NZ', 'PH', 'PK', 'SA', 'SV', 'US']);
|
export const COUNTRIES_WITH_12H_TIME_FORMAT = new Set(['AU', 'BD', 'CA', 'CO', 'EG', 'HN', 'IE', 'IN', 'JO', 'MX', 'MY', 'NI', 'NZ', 'PH', 'PK', 'SA', 'SV', 'US']);
|
||||||
|
|
||||||
|
|||||||
@ -1633,7 +1633,8 @@ addActionHandler('acceptChatInvite', async (global, actions, payload): Promise<v
|
|||||||
|
|
||||||
addActionHandler('openChatByUsername', async (global, actions, payload): Promise<void> => {
|
addActionHandler('openChatByUsername', async (global, actions, payload): Promise<void> => {
|
||||||
const {
|
const {
|
||||||
username, messageId, commentId, startParam, startAttach, attach, threadId, originalParts, startApp, mode,
|
username, messageId, commentId, startParam, startAttach, attach, threadId, originalParts,
|
||||||
|
startApp, shouldStartMainApp, mode,
|
||||||
text, onChatChanged, choose, ref, timestamp,
|
text, onChatChanged, choose, ref, timestamp,
|
||||||
tabId = getCurrentTabId(),
|
tabId = getCurrentTabId(),
|
||||||
} = payload;
|
} = payload;
|
||||||
@ -1661,7 +1662,7 @@ addActionHandler('openChatByUsername', async (global, actions, payload): Promise
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startApp !== undefined && !webAppName) {
|
if ((startApp !== undefined && !webAppName) || shouldStartMainApp) {
|
||||||
const theme = extractCurrentThemeParams();
|
const theme = extractCurrentThemeParams();
|
||||||
const chatByUsername = await fetchChatByUsername(global, username);
|
const chatByUsername = await fetchChatByUsername(global, username);
|
||||||
global = getGlobal();
|
global = getGlobal();
|
||||||
|
|||||||
@ -126,6 +126,7 @@ import {
|
|||||||
selectForwardsCanBeSentToChat,
|
selectForwardsCanBeSentToChat,
|
||||||
selectForwardsContainVoiceMessages,
|
selectForwardsContainVoiceMessages,
|
||||||
selectIsChatBotNotStarted,
|
selectIsChatBotNotStarted,
|
||||||
|
selectIsChatRestricted,
|
||||||
selectIsChatWithSelf,
|
selectIsChatWithSelf,
|
||||||
selectIsCurrentUserFrozen,
|
selectIsCurrentUserFrozen,
|
||||||
selectIsCurrentUserPremium,
|
selectIsCurrentUserPremium,
|
||||||
@ -187,8 +188,9 @@ addActionHandler('loadViewportMessages', (global, actions, payload): ActionRetur
|
|||||||
}
|
}
|
||||||
|
|
||||||
const chat = selectChat(global, chatId);
|
const chat = selectChat(global, chatId);
|
||||||
// TODO Revise if `chat.isRestricted` check is needed
|
const isRestricted = selectIsChatRestricted(global, chatId);
|
||||||
if (!chat || chat.isRestricted) {
|
// TODO Revise if `isRestricted` check is needed
|
||||||
|
if (!chat || isRestricted) {
|
||||||
onError?.();
|
onError?.();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import { updateTabState } from '../../reducers/tabs';
|
|||||||
import {
|
import {
|
||||||
selectChat,
|
selectChat,
|
||||||
selectChatFullInfo,
|
selectChatFullInfo,
|
||||||
|
selectIsChatRestricted,
|
||||||
selectIsCurrentUserFrozen,
|
selectIsCurrentUserFrozen,
|
||||||
selectIsCurrentUserPremium,
|
selectIsCurrentUserPremium,
|
||||||
selectPeer,
|
selectPeer,
|
||||||
@ -309,6 +310,10 @@ addActionHandler('loadMoreProfilePhotos', async (global, actions, payload): Prom
|
|||||||
const user = isPrivate ? selectUser(global, peerId) : undefined;
|
const user = isPrivate ? selectUser(global, peerId) : undefined;
|
||||||
const chat = !isPrivate ? selectChat(global, peerId) : undefined;
|
const chat = !isPrivate ? selectChat(global, peerId) : undefined;
|
||||||
const peer = user || chat;
|
const peer = user || chat;
|
||||||
|
|
||||||
|
if (chat && selectIsChatRestricted(global, peerId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const profilePhotos = selectPeerPhotos(global, peerId);
|
const profilePhotos = selectPeerPhotos(global, peerId);
|
||||||
if (!peer?.avatarPhotoId) {
|
if (!peer?.avatarPhotoId) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -44,7 +44,7 @@ import {
|
|||||||
|
|
||||||
const TYPING_STATUS_CLEAR_DELAY = 6000; // 6 seconds
|
const TYPING_STATUS_CLEAR_DELAY = 6000; // 6 seconds
|
||||||
const INVALIDATE_FULL_CHAT_FIELDS = new Set<keyof ApiChat>([
|
const INVALIDATE_FULL_CHAT_FIELDS = new Set<keyof ApiChat>([
|
||||||
'boostLevel', 'isForum', 'isLinkedInDiscussion', 'fakeType', 'restrictionReason', 'isJoinToSend', 'isJoinRequest',
|
'boostLevel', 'isForum', 'isLinkedInDiscussion', 'fakeType', 'restrictionReasons', 'isJoinToSend', 'isJoinRequest',
|
||||||
'type',
|
'type',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@ -41,3 +41,19 @@ addActionHandler('closeDeleteAccountModal', (global, actions, payload): ActionRe
|
|||||||
deleteAccountModal: undefined,
|
deleteAccountModal: undefined,
|
||||||
}, tabId);
|
}, tabId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addActionHandler('openAgeVerificationModal', (global, actions, payload): ActionReturnType => {
|
||||||
|
const { tabId = getCurrentTabId() } = payload || {};
|
||||||
|
|
||||||
|
return updateTabState(global, {
|
||||||
|
isAgeVerificationModalOpen: true,
|
||||||
|
}, tabId);
|
||||||
|
});
|
||||||
|
|
||||||
|
addActionHandler('closeAgeVerificationModal', (global, actions, payload): ActionReturnType => {
|
||||||
|
const { tabId = getCurrentTabId() } = payload || {};
|
||||||
|
|
||||||
|
return updateTabState(global, {
|
||||||
|
isAgeVerificationModalOpen: false,
|
||||||
|
}, tabId);
|
||||||
|
});
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import {
|
|||||||
import { formatDateToString, formatTime } from '../../util/dates/dateFormat';
|
import { formatDateToString, formatTime } from '../../util/dates/dateFormat';
|
||||||
import { getPeerIdDividend, isUserId } from '../../util/entities/ids';
|
import { getPeerIdDividend, isUserId } from '../../util/entities/ids';
|
||||||
import { getServerTime } from '../../util/serverTime';
|
import { getServerTime } from '../../util/serverTime';
|
||||||
|
import { selectIsChatRestricted } from '../selectors';
|
||||||
import { getGlobal } from '..';
|
import { getGlobal } from '..';
|
||||||
import { isSystemBot } from './bots';
|
import { isSystemBot } from './bots';
|
||||||
import { getMainUsername } from './users';
|
import { getMainUsername } from './users';
|
||||||
@ -155,7 +156,9 @@ export function getCanPostInChat(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chat.isRestricted || chat.isForbidden || chat.migratedTo
|
const global = getGlobal();
|
||||||
|
const isRestricted = selectIsChatRestricted(global, chat.id);
|
||||||
|
if (isRestricted || chat.isForbidden || chat.migratedTo
|
||||||
|| (chat.isNotJoined && !isChatMonoforum(chat) && !isMessageThread)
|
|| (chat.isNotJoined && !isChatMonoforum(chat) && !isMessageThread)
|
||||||
|| isSystemBot(chat.id) || isAnonymousForwardsChat(chat.id)) {
|
|| isSystemBot(chat.id) || isAnonymousForwardsChat(chat.id)) {
|
||||||
return false;
|
return false;
|
||||||
@ -380,7 +383,9 @@ export function getGroupStatus(lang: OldLangFn, chat: ApiChat) {
|
|||||||
const chatTypeString = lang(getChatTypeString(chat));
|
const chatTypeString = lang(getChatTypeString(chat));
|
||||||
const { membersCount } = chat;
|
const { membersCount } = chat;
|
||||||
|
|
||||||
if (chat.isRestricted) {
|
const global = getGlobal();
|
||||||
|
const isRestricted = selectIsChatRestricted(global, chat.id);
|
||||||
|
if (isRestricted) {
|
||||||
return chatTypeString === 'Channel' ? 'channel is inaccessible' : 'group is inaccessible';
|
return chatTypeString === 'Channel' ? 'channel is inaccessible' : 'group is inaccessible';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import {
|
|||||||
isUserBot,
|
isUserBot,
|
||||||
isUserOnline,
|
isUserOnline,
|
||||||
} from '../helpers';
|
} from '../helpers';
|
||||||
|
import { selectActiveRestrictionReasons } from './messages';
|
||||||
import { selectTabState } from './tabs';
|
import { selectTabState } from './tabs';
|
||||||
import {
|
import {
|
||||||
selectBot, selectIsCurrentUserPremium, selectUser, selectUserFullInfo,
|
selectBot, selectIsCurrentUserPremium, selectUser, selectUserFullInfo,
|
||||||
@ -374,3 +375,11 @@ export function selectMonoforumChannel<T extends GlobalState>(
|
|||||||
|
|
||||||
return chat.isMonoforum ? selectChat(global, chat.linkedMonoforumId!) : undefined;
|
return chat.isMonoforum ? selectChat(global, chat.linkedMonoforumId!) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectIsChatRestricted<T extends GlobalState>(global: T, chatId: string): boolean {
|
||||||
|
const chat = selectChat(global, chatId);
|
||||||
|
if (!chat) return false;
|
||||||
|
|
||||||
|
const activeRestrictions = selectActiveRestrictionReasons(global, chat.restrictionReasons);
|
||||||
|
return activeRestrictions.length > 0;
|
||||||
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import {
|
|||||||
isAnonymousForwardsChat,
|
isAnonymousForwardsChat,
|
||||||
isChatAdmin, isChatGroup, isUserBot,
|
isChatAdmin, isChatGroup, isUserBot,
|
||||||
} from '../helpers';
|
} from '../helpers';
|
||||||
import { selectChat, selectIsChatWithSelf } from './chats';
|
import { selectChat, selectIsChatRestricted, selectIsChatWithSelf } from './chats';
|
||||||
import { selectCurrentMessageList } from './messages';
|
import { selectCurrentMessageList } from './messages';
|
||||||
import { selectTabState } from './tabs';
|
import { selectTabState } from './tabs';
|
||||||
import { selectBot, selectUser } from './users';
|
import { selectBot, selectUser } from './users';
|
||||||
@ -72,7 +72,8 @@ export function selectCanManage<T extends GlobalState>(
|
|||||||
chatId: string,
|
chatId: string,
|
||||||
) {
|
) {
|
||||||
const chat = selectChat(global, chatId);
|
const chat = selectChat(global, chatId);
|
||||||
if (!chat || chat.isRestricted || chat.isMonoforum) return false;
|
const isRestricted = selectIsChatRestricted(global, chatId);
|
||||||
|
if (!chat || isRestricted || chat.isMonoforum) return false;
|
||||||
|
|
||||||
const isPrivate = isUserId(chat.id);
|
const isPrivate = isUserId(chat.id);
|
||||||
const user = isPrivate ? selectUser(global, chatId) : undefined;
|
const user = isPrivate ? selectUser(global, chatId) : undefined;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import type {
|
|||||||
ApiMessageEntityCustomEmoji,
|
ApiMessageEntityCustomEmoji,
|
||||||
ApiMessageForwardInfo,
|
ApiMessageForwardInfo,
|
||||||
ApiMessageOutgoingStatus,
|
ApiMessageOutgoingStatus,
|
||||||
ApiPeer, ApiSponsoredMessage,
|
ApiPeer, ApiRestrictionReason, ApiSponsoredMessage,
|
||||||
ApiStickerSetInfo,
|
ApiStickerSetInfo,
|
||||||
} from '../../api/types';
|
} from '../../api/types';
|
||||||
import type {
|
import type {
|
||||||
@ -22,8 +22,8 @@ import type {
|
|||||||
import { ApiMessageEntityTypes, MAIN_THREAD_ID } from '../../api/types';
|
import { ApiMessageEntityTypes, MAIN_THREAD_ID } from '../../api/types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ANONYMOUS_USER_ID, API_GENERAL_ID_LIMIT, GENERAL_TOPIC_ID, SERVICE_NOTIFICATIONS_USER_ID,
|
ANONYMOUS_USER_ID, API_GENERAL_ID_LIMIT, GENERAL_TOPIC_ID, NSFW_RESTRICTION_REASON, SERVICE_NOTIFICATIONS_USER_ID,
|
||||||
SVG_EXTENSIONS,
|
SVG_EXTENSIONS, WEB_APP_PLATFORM,
|
||||||
} from '../../config';
|
} from '../../config';
|
||||||
import { IS_TRANSLATION_SUPPORTED } from '../../util/browser/windowEnvironment';
|
import { IS_TRANSLATION_SUPPORTED } from '../../util/browser/windowEnvironment';
|
||||||
import { isUserId } from '../../util/entities/ids';
|
import { isUserId } from '../../util/entities/ids';
|
||||||
@ -72,11 +72,13 @@ import {
|
|||||||
selectChat,
|
selectChat,
|
||||||
selectChatFullInfo,
|
selectChatFullInfo,
|
||||||
selectChatLastMessageId,
|
selectChatLastMessageId,
|
||||||
|
selectIsChatRestricted,
|
||||||
selectIsChatWithBot,
|
selectIsChatWithBot,
|
||||||
selectIsChatWithSelf,
|
selectIsChatWithSelf,
|
||||||
selectRequestedChatTranslationLanguage,
|
selectRequestedChatTranslationLanguage,
|
||||||
} from './chats';
|
} from './chats';
|
||||||
import { selectPeer, selectPeerPaidMessagesStars } from './peers';
|
import { selectPeer, selectPeerPaidMessagesStars } from './peers';
|
||||||
|
import { selectSettingsKeys } from './settings';
|
||||||
import { selectPeerStory } from './stories';
|
import { selectPeerStory } from './stories';
|
||||||
import { selectIsStickerFavorite } from './symbols';
|
import { selectIsStickerFavorite } from './symbols';
|
||||||
import { selectTabState } from './tabs';
|
import { selectTabState } from './tabs';
|
||||||
@ -587,7 +589,8 @@ export function selectThreadIdFromMessage<T extends GlobalState>(global: T, mess
|
|||||||
|
|
||||||
export function selectCanReplyToMessage<T extends GlobalState>(global: T, message: ApiMessage, threadId: ThreadId) {
|
export function selectCanReplyToMessage<T extends GlobalState>(global: T, message: ApiMessage, threadId: ThreadId) {
|
||||||
const chat = selectChat(global, message.chatId);
|
const chat = selectChat(global, message.chatId);
|
||||||
if (!chat || chat.isRestricted || chat.isForbidden) return false;
|
const isRestricted = selectIsChatRestricted(global, message.chatId);
|
||||||
|
if (!chat || isRestricted || chat.isForbidden) return false;
|
||||||
|
|
||||||
const isLocal = isMessageLocal(message);
|
const isLocal = isMessageLocal(message);
|
||||||
const isServiceNotification = isServiceNotificationMessage(message);
|
const isServiceNotification = isServiceNotificationMessage(message);
|
||||||
@ -632,7 +635,8 @@ export function selectAllowedMessageActionsSlow<T extends GlobalState>(
|
|||||||
global: T, message: ApiMessage, threadId: ThreadId,
|
global: T, message: ApiMessage, threadId: ThreadId,
|
||||||
) {
|
) {
|
||||||
const chat = selectChat(global, message.chatId);
|
const chat = selectChat(global, message.chatId);
|
||||||
if (!chat || chat.isRestricted) {
|
const isRestricted = selectIsChatRestricted(global, message.chatId);
|
||||||
|
if (!chat || isRestricted) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1563,3 +1567,31 @@ export function selectMessageLastPlaybackTimestamp<T extends GlobalState>(
|
|||||||
) {
|
) {
|
||||||
return global.messages.playbackByChatId[chatId]?.byId[messageId];
|
return global.messages.playbackByChatId[chatId]?.byId[messageId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectActiveRestrictionReasons<T extends GlobalState>(
|
||||||
|
global: T, restrictionReasons?: ApiRestrictionReason[],
|
||||||
|
): ApiRestrictionReason[] {
|
||||||
|
if (!restrictionReasons) return [];
|
||||||
|
|
||||||
|
const { ignoreRestrictionReasons } = global.appConfig || {};
|
||||||
|
|
||||||
|
return restrictionReasons.filter((reason) => {
|
||||||
|
const isForCurrentPlatform = reason.platform === 'all' || reason.platform === WEB_APP_PLATFORM;
|
||||||
|
if (!isForCurrentPlatform) return false;
|
||||||
|
|
||||||
|
const shouldIgnore = ignoreRestrictionReasons?.includes(reason.reason);
|
||||||
|
return !shouldIgnore;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsMediaNsfw<T extends GlobalState>(global: T, message: ApiMessage) {
|
||||||
|
const { isSensitiveEnabled } = selectSettingsKeys(global);
|
||||||
|
const chat = selectChat(global, message.chatId);
|
||||||
|
if (isSensitiveEnabled) return false;
|
||||||
|
|
||||||
|
const chatActiveRestrictions = selectActiveRestrictionReasons(global, chat?.restrictionReasons);
|
||||||
|
const messageActiveRestrictions = selectActiveRestrictionReasons(global, message.restrictionReasons);
|
||||||
|
|
||||||
|
return chatActiveRestrictions.some((reason) => reason.reason === NSFW_RESTRICTION_REASON)
|
||||||
|
|| messageActiveRestrictions.some((reason) => reason.reason === NSFW_RESTRICTION_REASON);
|
||||||
|
}
|
||||||
|
|||||||
@ -656,6 +656,7 @@ export interface ActionPayloads {
|
|||||||
startAttach?: string;
|
startAttach?: string;
|
||||||
attach?: string;
|
attach?: string;
|
||||||
startApp?: string;
|
startApp?: string;
|
||||||
|
shouldStartMainApp?: boolean;
|
||||||
mode?: string;
|
mode?: string;
|
||||||
choose?: ApiChatType[];
|
choose?: ApiChatType[];
|
||||||
text?: string;
|
text?: string;
|
||||||
@ -1081,6 +1082,8 @@ export interface ActionPayloads {
|
|||||||
days: number;
|
days: number;
|
||||||
} & WithTabId | undefined;
|
} & WithTabId | undefined;
|
||||||
closeDeleteAccountModal: WithTabId | undefined;
|
closeDeleteAccountModal: WithTabId | undefined;
|
||||||
|
openAgeVerificationModal: WithTabId | undefined;
|
||||||
|
closeAgeVerificationModal: WithTabId | undefined;
|
||||||
setAccountTTL: {
|
setAccountTTL: {
|
||||||
days: number;
|
days: number;
|
||||||
} & WithTabId | undefined;
|
} & WithTabId | undefined;
|
||||||
|
|||||||
@ -754,6 +754,8 @@ export type TabState = {
|
|||||||
selfDestructAccountDays: number;
|
selfDestructAccountDays: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
isAgeVerificationModalOpen?: boolean;
|
||||||
|
|
||||||
paidReactionModal?: {
|
paidReactionModal?: {
|
||||||
chatId: string;
|
chatId: string;
|
||||||
messageId: number;
|
messageId: number;
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { getActions, getGlobal } from '../../global';
|
|||||||
import type { ApiChat, ApiUser } from '../../api/types';
|
import type { ApiChat, ApiUser } from '../../api/types';
|
||||||
|
|
||||||
import { isChatChannel, isUserBot } from '../../global/helpers';
|
import { isChatChannel, isUserBot } from '../../global/helpers';
|
||||||
import { selectPeer, selectUserStatus } from '../../global/selectors';
|
import { selectIsChatRestricted, selectPeer, selectUserStatus } from '../../global/selectors';
|
||||||
import { isUserId } from '../../util/entities/ids';
|
import { isUserId } from '../../util/entities/ids';
|
||||||
import { throttle } from '../../util/schedulers';
|
import { throttle } from '../../util/schedulers';
|
||||||
|
|
||||||
@ -54,7 +54,8 @@ export default function usePeerStoriesPolling(ids?: string[]) {
|
|||||||
return !user.isContact && !user.isSelf && !isUserBot(user) && !peer.isSupport && isStatusAvailable;
|
return !user.isContact && !user.isSelf && !isUserBot(user) && !peer.isSupport && isStatusAvailable;
|
||||||
} else {
|
} else {
|
||||||
const chat = peer as ApiChat;
|
const chat = peer as ApiChat;
|
||||||
return isChatChannel(chat) && !chat.isRestricted;
|
const isRestricted = selectIsChatRestricted(global, chat.id);
|
||||||
|
return isChatChannel(chat) && !isRestricted;
|
||||||
}
|
}
|
||||||
}).map((user) => user.id);
|
}).map((user) => user.id);
|
||||||
}, [peers]);
|
}, [peers]);
|
||||||
|
|||||||
@ -12,6 +12,6 @@ for (const tl of Object.values(Api)) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LAYER = 207;
|
export const LAYER = 210;
|
||||||
|
|
||||||
export { tlobjects };
|
export { tlobjects };
|
||||||
|
|||||||
137
src/lib/gramjs/tl/api.d.ts
vendored
137
src/lib/gramjs/tl/api.d.ts
vendored
@ -397,6 +397,8 @@ namespace Api {
|
|||||||
export type TypeTodoList = TodoList;
|
export type TypeTodoList = TodoList;
|
||||||
export type TypeTodoCompletion = TodoCompletion;
|
export type TypeTodoCompletion = TodoCompletion;
|
||||||
export type TypeSuggestedPost = SuggestedPost;
|
export type TypeSuggestedPost = SuggestedPost;
|
||||||
|
export type TypeStarsRating = StarsRating;
|
||||||
|
export type TypeStarGiftCollection = StarGiftCollection;
|
||||||
export type TypeResPQ = ResPQ;
|
export type TypeResPQ = ResPQ;
|
||||||
export type TypeP_Q_inner_data = PQInnerData | PQInnerDataDc | PQInnerDataTemp | PQInnerDataTempDc;
|
export type TypeP_Q_inner_data = PQInnerData | PQInnerDataDc | PQInnerDataTemp | PQInnerDataTempDc;
|
||||||
export type TypeServer_DH_Params = ServerDHParamsFail | ServerDHParamsOk;
|
export type TypeServer_DH_Params = ServerDHParamsFail | ServerDHParamsOk;
|
||||||
@ -612,6 +614,7 @@ namespace Api {
|
|||||||
export type TypeSavedStarGifts = payments.SavedStarGifts;
|
export type TypeSavedStarGifts = payments.SavedStarGifts;
|
||||||
export type TypeStarGiftWithdrawalUrl = payments.StarGiftWithdrawalUrl;
|
export type TypeStarGiftWithdrawalUrl = payments.StarGiftWithdrawalUrl;
|
||||||
export type TypeResaleStarGifts = payments.ResaleStarGifts;
|
export type TypeResaleStarGifts = payments.ResaleStarGifts;
|
||||||
|
export type TypeStarGiftCollections = payments.StarGiftCollectionsNotModified | payments.StarGiftCollections;
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace phone {
|
export namespace phone {
|
||||||
@ -3918,6 +3921,7 @@ namespace Api {
|
|||||||
botVerification?: Api.TypeBotVerification;
|
botVerification?: Api.TypeBotVerification;
|
||||||
sendPaidMessagesStars?: long;
|
sendPaidMessagesStars?: long;
|
||||||
disallowedGifts?: Api.TypeDisallowedGiftsSettings;
|
disallowedGifts?: Api.TypeDisallowedGiftsSettings;
|
||||||
|
starsRating?: Api.TypeStarsRating;
|
||||||
}> {
|
}> {
|
||||||
// flags: Api.Type;
|
// flags: Api.Type;
|
||||||
blocked?: true;
|
blocked?: true;
|
||||||
@ -3969,7 +3973,8 @@ namespace Api {
|
|||||||
botVerification?: Api.TypeBotVerification;
|
botVerification?: Api.TypeBotVerification;
|
||||||
sendPaidMessagesStars?: long;
|
sendPaidMessagesStars?: long;
|
||||||
disallowedGifts?: Api.TypeDisallowedGiftsSettings;
|
disallowedGifts?: Api.TypeDisallowedGiftsSettings;
|
||||||
CONSTRUCTOR_ID: 2582085701;
|
starsRating?: Api.TypeStarsRating;
|
||||||
|
CONSTRUCTOR_ID: 702447806;
|
||||||
SUBCLASS_OF_ID: 524706233;
|
SUBCLASS_OF_ID: 524706233;
|
||||||
className: 'UserFull';
|
className: 'UserFull';
|
||||||
|
|
||||||
@ -13347,6 +13352,7 @@ namespace Api {
|
|||||||
quoteText?: string;
|
quoteText?: string;
|
||||||
quoteEntities?: Api.TypeMessageEntity[];
|
quoteEntities?: Api.TypeMessageEntity[];
|
||||||
quoteOffset?: int;
|
quoteOffset?: int;
|
||||||
|
todoItemId?: int;
|
||||||
} | void> {
|
} | void> {
|
||||||
// flags: Api.Type;
|
// flags: Api.Type;
|
||||||
replyToScheduled?: true;
|
replyToScheduled?: true;
|
||||||
@ -13360,7 +13366,8 @@ namespace Api {
|
|||||||
quoteText?: string;
|
quoteText?: string;
|
||||||
quoteEntities?: Api.TypeMessageEntity[];
|
quoteEntities?: Api.TypeMessageEntity[];
|
||||||
quoteOffset?: int;
|
quoteOffset?: int;
|
||||||
CONSTRUCTOR_ID: 2948336091;
|
todoItemId?: int;
|
||||||
|
CONSTRUCTOR_ID: 1763137035;
|
||||||
SUBCLASS_OF_ID: 1531810151;
|
SUBCLASS_OF_ID: 1531810151;
|
||||||
className: 'MessageReplyHeader';
|
className: 'MessageReplyHeader';
|
||||||
|
|
||||||
@ -15261,6 +15268,7 @@ namespace Api {
|
|||||||
quoteEntities?: Api.TypeMessageEntity[];
|
quoteEntities?: Api.TypeMessageEntity[];
|
||||||
quoteOffset?: int;
|
quoteOffset?: int;
|
||||||
monoforumPeerId?: Api.TypeInputPeer;
|
monoforumPeerId?: Api.TypeInputPeer;
|
||||||
|
todoItemId?: int;
|
||||||
}> {
|
}> {
|
||||||
// flags: Api.Type;
|
// flags: Api.Type;
|
||||||
replyToMsgId: int;
|
replyToMsgId: int;
|
||||||
@ -15270,7 +15278,8 @@ namespace Api {
|
|||||||
quoteEntities?: Api.TypeMessageEntity[];
|
quoteEntities?: Api.TypeMessageEntity[];
|
||||||
quoteOffset?: int;
|
quoteOffset?: int;
|
||||||
monoforumPeerId?: Api.TypeInputPeer;
|
monoforumPeerId?: Api.TypeInputPeer;
|
||||||
CONSTRUCTOR_ID: 2960144560;
|
todoItemId?: int;
|
||||||
|
CONSTRUCTOR_ID: 2258615824;
|
||||||
SUBCLASS_OF_ID: 2356220701;
|
SUBCLASS_OF_ID: 2356220701;
|
||||||
className: 'InputReplyToMessage';
|
className: 'InputReplyToMessage';
|
||||||
|
|
||||||
@ -16754,6 +16763,8 @@ namespace Api {
|
|||||||
limited?: true;
|
limited?: true;
|
||||||
soldOut?: true;
|
soldOut?: true;
|
||||||
birthday?: true;
|
birthday?: true;
|
||||||
|
requirePremium?: true;
|
||||||
|
limitedPerUser?: true;
|
||||||
id: long;
|
id: long;
|
||||||
sticker: Api.TypeDocument;
|
sticker: Api.TypeDocument;
|
||||||
stars: long;
|
stars: long;
|
||||||
@ -16767,11 +16778,15 @@ namespace Api {
|
|||||||
resellMinStars?: long;
|
resellMinStars?: long;
|
||||||
title?: string;
|
title?: string;
|
||||||
releasedBy?: Api.TypePeer;
|
releasedBy?: Api.TypePeer;
|
||||||
|
perUserTotal?: int;
|
||||||
|
perUserRemains?: int;
|
||||||
}> {
|
}> {
|
||||||
// flags: Api.Type;
|
// flags: Api.Type;
|
||||||
limited?: true;
|
limited?: true;
|
||||||
soldOut?: true;
|
soldOut?: true;
|
||||||
birthday?: true;
|
birthday?: true;
|
||||||
|
requirePremium?: true;
|
||||||
|
limitedPerUser?: true;
|
||||||
id: long;
|
id: long;
|
||||||
sticker: Api.TypeDocument;
|
sticker: Api.TypeDocument;
|
||||||
stars: long;
|
stars: long;
|
||||||
@ -16785,7 +16800,9 @@ namespace Api {
|
|||||||
resellMinStars?: long;
|
resellMinStars?: long;
|
||||||
title?: string;
|
title?: string;
|
||||||
releasedBy?: Api.TypePeer;
|
releasedBy?: Api.TypePeer;
|
||||||
CONSTRUCTOR_ID: 2139438098;
|
perUserTotal?: int;
|
||||||
|
perUserRemains?: int;
|
||||||
|
CONSTRUCTOR_ID: 12386139;
|
||||||
SUBCLASS_OF_ID: 3273414923;
|
SUBCLASS_OF_ID: 3273414923;
|
||||||
className: 'StarGift';
|
className: 'StarGift';
|
||||||
|
|
||||||
@ -16793,6 +16810,7 @@ namespace Api {
|
|||||||
}
|
}
|
||||||
export class StarGiftUnique extends VirtualClass<{
|
export class StarGiftUnique extends VirtualClass<{
|
||||||
// flags: Api.Type;
|
// flags: Api.Type;
|
||||||
|
requirePremium?: true;
|
||||||
id: long;
|
id: long;
|
||||||
title: string;
|
title: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
@ -16808,6 +16826,7 @@ namespace Api {
|
|||||||
releasedBy?: Api.TypePeer;
|
releasedBy?: Api.TypePeer;
|
||||||
}> {
|
}> {
|
||||||
// flags: Api.Type;
|
// flags: Api.Type;
|
||||||
|
requirePremium?: true;
|
||||||
id: long;
|
id: long;
|
||||||
title: string;
|
title: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
@ -17079,6 +17098,7 @@ namespace Api {
|
|||||||
transferStars?: long;
|
transferStars?: long;
|
||||||
canTransferAt?: int;
|
canTransferAt?: int;
|
||||||
canResellAt?: int;
|
canResellAt?: int;
|
||||||
|
collectionId?: int[];
|
||||||
}> {
|
}> {
|
||||||
// flags: Api.Type;
|
// flags: Api.Type;
|
||||||
nameHidden?: true;
|
nameHidden?: true;
|
||||||
@ -17098,7 +17118,8 @@ namespace Api {
|
|||||||
transferStars?: long;
|
transferStars?: long;
|
||||||
canTransferAt?: int;
|
canTransferAt?: int;
|
||||||
canResellAt?: int;
|
canResellAt?: int;
|
||||||
CONSTRUCTOR_ID: 3755607193;
|
collectionId?: int[];
|
||||||
|
CONSTRUCTOR_ID: 514213599;
|
||||||
SUBCLASS_OF_ID: 2385198100;
|
SUBCLASS_OF_ID: 2385198100;
|
||||||
className: 'SavedStarGift';
|
className: 'SavedStarGift';
|
||||||
|
|
||||||
@ -17378,6 +17399,44 @@ namespace Api {
|
|||||||
|
|
||||||
static fromReader(reader: Reader): SuggestedPost;
|
static fromReader(reader: Reader): SuggestedPost;
|
||||||
}
|
}
|
||||||
|
export class StarsRating extends VirtualClass<{
|
||||||
|
// flags: Api.Type;
|
||||||
|
level: int;
|
||||||
|
currentLevelStars: long;
|
||||||
|
stars: long;
|
||||||
|
nextLevelStars?: long;
|
||||||
|
}> {
|
||||||
|
// flags: Api.Type;
|
||||||
|
level: int;
|
||||||
|
currentLevelStars: long;
|
||||||
|
stars: long;
|
||||||
|
nextLevelStars?: long;
|
||||||
|
CONSTRUCTOR_ID: 453922567;
|
||||||
|
SUBCLASS_OF_ID: 1668506656;
|
||||||
|
className: 'StarsRating';
|
||||||
|
|
||||||
|
static fromReader(reader: Reader): StarsRating;
|
||||||
|
}
|
||||||
|
export class StarGiftCollection extends VirtualClass<{
|
||||||
|
// flags: Api.Type;
|
||||||
|
collectionId: int;
|
||||||
|
title: string;
|
||||||
|
icon?: Api.TypeDocument;
|
||||||
|
giftsCount: int;
|
||||||
|
hash: long;
|
||||||
|
}> {
|
||||||
|
// flags: Api.Type;
|
||||||
|
collectionId: int;
|
||||||
|
title: string;
|
||||||
|
icon?: Api.TypeDocument;
|
||||||
|
giftsCount: int;
|
||||||
|
hash: long;
|
||||||
|
CONSTRUCTOR_ID: 2641040304;
|
||||||
|
SUBCLASS_OF_ID: 1138805578;
|
||||||
|
className: 'StarGiftCollection';
|
||||||
|
|
||||||
|
static fromReader(reader: Reader): StarGiftCollection;
|
||||||
|
}
|
||||||
export class ResPQ extends VirtualClass<{
|
export class ResPQ extends VirtualClass<{
|
||||||
nonce: int128;
|
nonce: int128;
|
||||||
serverNonce: int128;
|
serverNonce: int128;
|
||||||
@ -21385,6 +21444,23 @@ namespace Api {
|
|||||||
|
|
||||||
static fromReader(reader: Reader): ResaleStarGifts;
|
static fromReader(reader: Reader): ResaleStarGifts;
|
||||||
}
|
}
|
||||||
|
export class StarGiftCollectionsNotModified extends VirtualClass<void> {
|
||||||
|
CONSTRUCTOR_ID: 2696564503;
|
||||||
|
SUBCLASS_OF_ID: 4028047852;
|
||||||
|
className: 'StarGiftCollectionsNotModified';
|
||||||
|
|
||||||
|
static fromReader(reader: Reader): StarGiftCollectionsNotModified;
|
||||||
|
}
|
||||||
|
export class StarGiftCollections extends VirtualClass<{
|
||||||
|
collections: Api.TypeStarGiftCollection[];
|
||||||
|
}> {
|
||||||
|
collections: Api.TypeStarGiftCollection[];
|
||||||
|
CONSTRUCTOR_ID: 2317955827;
|
||||||
|
SUBCLASS_OF_ID: 4028047852;
|
||||||
|
className: 'StarGiftCollections';
|
||||||
|
|
||||||
|
static fromReader(reader: Reader): StarGiftCollections;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace phone {
|
export namespace phone {
|
||||||
@ -27128,6 +27204,7 @@ namespace Api {
|
|||||||
excludeUnique?: true;
|
excludeUnique?: true;
|
||||||
sortByValue?: true;
|
sortByValue?: true;
|
||||||
peer: Api.TypeInputPeer;
|
peer: Api.TypeInputPeer;
|
||||||
|
collectionId?: int;
|
||||||
offset: string;
|
offset: string;
|
||||||
limit: int;
|
limit: int;
|
||||||
}, payments.TypeSavedStarGifts> {
|
}, payments.TypeSavedStarGifts> {
|
||||||
@ -27139,6 +27216,7 @@ namespace Api {
|
|||||||
excludeUnique?: true;
|
excludeUnique?: true;
|
||||||
sortByValue?: true;
|
sortByValue?: true;
|
||||||
peer: Api.TypeInputPeer;
|
peer: Api.TypeInputPeer;
|
||||||
|
collectionId?: int;
|
||||||
offset: string;
|
offset: string;
|
||||||
limit: int;
|
limit: int;
|
||||||
}
|
}
|
||||||
@ -27201,6 +27279,53 @@ namespace Api {
|
|||||||
stargift: Api.TypeInputSavedStarGift;
|
stargift: Api.TypeInputSavedStarGift;
|
||||||
resellStars: long;
|
resellStars: long;
|
||||||
}
|
}
|
||||||
|
export class CreateStarGiftCollection extends Request<{
|
||||||
|
peer: Api.TypeInputPeer;
|
||||||
|
title: string;
|
||||||
|
stargift: Api.TypeInputSavedStarGift[];
|
||||||
|
}, Api.TypeStarGiftCollection> {
|
||||||
|
peer: Api.TypeInputPeer;
|
||||||
|
title: string;
|
||||||
|
stargift: Api.TypeInputSavedStarGift[];
|
||||||
|
}
|
||||||
|
export class UpdateStarGiftCollection extends Request<{
|
||||||
|
// flags: Api.Type;
|
||||||
|
peer: Api.TypeInputPeer;
|
||||||
|
collectionId: int;
|
||||||
|
title?: string;
|
||||||
|
deleteStargift?: Api.TypeInputSavedStarGift[];
|
||||||
|
addStargift?: Api.TypeInputSavedStarGift[];
|
||||||
|
order?: Api.TypeInputSavedStarGift[];
|
||||||
|
}, Api.TypeStarGiftCollection> {
|
||||||
|
// flags: Api.Type;
|
||||||
|
peer: Api.TypeInputPeer;
|
||||||
|
collectionId: int;
|
||||||
|
title?: string;
|
||||||
|
deleteStargift?: Api.TypeInputSavedStarGift[];
|
||||||
|
addStargift?: Api.TypeInputSavedStarGift[];
|
||||||
|
order?: Api.TypeInputSavedStarGift[];
|
||||||
|
}
|
||||||
|
export class ReorderStarGiftCollections extends Request<{
|
||||||
|
peer: Api.TypeInputPeer;
|
||||||
|
order: int[];
|
||||||
|
}, Bool> {
|
||||||
|
peer: Api.TypeInputPeer;
|
||||||
|
order: int[];
|
||||||
|
}
|
||||||
|
export class DeleteStarGiftCollection extends Request<{
|
||||||
|
peer: Api.TypeInputPeer;
|
||||||
|
collectionId: int;
|
||||||
|
}, Bool> {
|
||||||
|
peer: Api.TypeInputPeer;
|
||||||
|
collectionId: int;
|
||||||
|
}
|
||||||
|
export class GetStarGiftCollections extends Request<{
|
||||||
|
peer: Api.TypeInputPeer;
|
||||||
|
hash: long;
|
||||||
|
}, payments.TypeStarGiftCollections> {
|
||||||
|
peer: Api.TypeInputPeer;
|
||||||
|
hash: long;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace stickers {
|
export namespace stickers {
|
||||||
@ -28196,7 +28321,7 @@ namespace Api {
|
|||||||
| help.GetConfig | help.GetNearestDc | help.GetAppUpdate | help.GetInviteText | help.GetSupport | help.SetBotUpdatesStatus | help.GetCdnConfig | help.GetRecentMeUrls | help.GetTermsOfServiceUpdate | help.AcceptTermsOfService | help.GetDeepLinkInfo | help.GetAppConfig | help.SaveAppLog | help.GetPassportConfig | help.GetSupportName | help.GetUserInfo | help.EditUserInfo | help.GetPromoData | help.HidePromoData | help.DismissSuggestion | help.GetCountriesList | help.GetPremiumPromo | help.GetPeerColors | help.GetPeerProfileColors | help.GetTimezonesList
|
| help.GetConfig | help.GetNearestDc | help.GetAppUpdate | help.GetInviteText | help.GetSupport | help.SetBotUpdatesStatus | help.GetCdnConfig | help.GetRecentMeUrls | help.GetTermsOfServiceUpdate | help.AcceptTermsOfService | help.GetDeepLinkInfo | help.GetAppConfig | help.SaveAppLog | help.GetPassportConfig | help.GetSupportName | help.GetUserInfo | help.EditUserInfo | help.GetPromoData | help.HidePromoData | help.DismissSuggestion | help.GetCountriesList | help.GetPremiumPromo | help.GetPeerColors | help.GetPeerProfileColors | help.GetTimezonesList
|
||||||
| channels.ReadHistory | channels.DeleteMessages | channels.ReportSpam | channels.GetMessages | channels.GetParticipants | channels.GetParticipant | channels.GetChannels | channels.GetFullChannel | channels.CreateChannel | channels.EditAdmin | channels.EditTitle | channels.EditPhoto | channels.CheckUsername | channels.UpdateUsername | channels.JoinChannel | channels.LeaveChannel | channels.InviteToChannel | channels.DeleteChannel | channels.ExportMessageLink | channels.ToggleSignatures | channels.GetAdminedPublicChannels | channels.EditBanned | channels.GetAdminLog | channels.SetStickers | channels.ReadMessageContents | channels.DeleteHistory | channels.TogglePreHistoryHidden | channels.GetLeftChannels | channels.GetGroupsForDiscussion | channels.SetDiscussionGroup | channels.EditCreator | channels.EditLocation | channels.ToggleSlowMode | channels.GetInactiveChannels | channels.ConvertToGigagroup | channels.GetSendAs | channels.DeleteParticipantHistory | channels.ToggleJoinToSend | channels.ToggleJoinRequest | channels.ReorderUsernames | channels.ToggleUsername | channels.DeactivateAllUsernames | channels.ToggleForum | channels.CreateForumTopic | channels.GetForumTopics | channels.GetForumTopicsByID | channels.EditForumTopic | channels.UpdatePinnedForumTopic | channels.DeleteTopicHistory | channels.ReorderPinnedForumTopics | channels.ToggleAntiSpam | channels.ReportAntiSpamFalsePositive | channels.ToggleParticipantsHidden | channels.UpdateColor | channels.ToggleViewForumAsMessages | channels.GetChannelRecommendations | channels.UpdateEmojiStatus | channels.SetBoostsToUnblockRestrictions | channels.SetEmojiStickers | channels.RestrictSponsoredMessages | channels.SearchPosts | channels.UpdatePaidMessagesPrice | channels.ToggleAutotranslation | channels.GetMessageAuthor
|
| channels.ReadHistory | channels.DeleteMessages | channels.ReportSpam | channels.GetMessages | channels.GetParticipants | channels.GetParticipant | channels.GetChannels | channels.GetFullChannel | channels.CreateChannel | channels.EditAdmin | channels.EditTitle | channels.EditPhoto | channels.CheckUsername | channels.UpdateUsername | channels.JoinChannel | channels.LeaveChannel | channels.InviteToChannel | channels.DeleteChannel | channels.ExportMessageLink | channels.ToggleSignatures | channels.GetAdminedPublicChannels | channels.EditBanned | channels.GetAdminLog | channels.SetStickers | channels.ReadMessageContents | channels.DeleteHistory | channels.TogglePreHistoryHidden | channels.GetLeftChannels | channels.GetGroupsForDiscussion | channels.SetDiscussionGroup | channels.EditCreator | channels.EditLocation | channels.ToggleSlowMode | channels.GetInactiveChannels | channels.ConvertToGigagroup | channels.GetSendAs | channels.DeleteParticipantHistory | channels.ToggleJoinToSend | channels.ToggleJoinRequest | channels.ReorderUsernames | channels.ToggleUsername | channels.DeactivateAllUsernames | channels.ToggleForum | channels.CreateForumTopic | channels.GetForumTopics | channels.GetForumTopicsByID | channels.EditForumTopic | channels.UpdatePinnedForumTopic | channels.DeleteTopicHistory | channels.ReorderPinnedForumTopics | channels.ToggleAntiSpam | channels.ReportAntiSpamFalsePositive | channels.ToggleParticipantsHidden | channels.UpdateColor | channels.ToggleViewForumAsMessages | channels.GetChannelRecommendations | channels.UpdateEmojiStatus | channels.SetBoostsToUnblockRestrictions | channels.SetEmojiStickers | channels.RestrictSponsoredMessages | channels.SearchPosts | channels.UpdatePaidMessagesPrice | channels.ToggleAutotranslation | channels.GetMessageAuthor
|
||||||
| bots.SendCustomRequest | bots.AnswerWebhookJSONQuery | bots.SetBotCommands | bots.ResetBotCommands | bots.GetBotCommands | bots.SetBotMenuButton | bots.GetBotMenuButton | bots.SetBotBroadcastDefaultAdminRights | bots.SetBotGroupDefaultAdminRights | bots.SetBotInfo | bots.GetBotInfo | bots.ReorderUsernames | bots.ToggleUsername | bots.CanSendMessage | bots.AllowSendMessage | bots.InvokeWebViewCustomMethod | bots.GetPopularAppBots | bots.AddPreviewMedia | bots.EditPreviewMedia | bots.DeletePreviewMedia | bots.ReorderPreviewMedias | bots.GetPreviewInfo | bots.GetPreviewMedias | bots.UpdateUserEmojiStatus | bots.ToggleUserEmojiStatusPermission | bots.CheckDownloadFileParams | bots.GetAdminedBots | bots.UpdateStarRefProgram | bots.SetCustomVerification | bots.GetBotRecommendations
|
| bots.SendCustomRequest | bots.AnswerWebhookJSONQuery | bots.SetBotCommands | bots.ResetBotCommands | bots.GetBotCommands | bots.SetBotMenuButton | bots.GetBotMenuButton | bots.SetBotBroadcastDefaultAdminRights | bots.SetBotGroupDefaultAdminRights | bots.SetBotInfo | bots.GetBotInfo | bots.ReorderUsernames | bots.ToggleUsername | bots.CanSendMessage | bots.AllowSendMessage | bots.InvokeWebViewCustomMethod | bots.GetPopularAppBots | bots.AddPreviewMedia | bots.EditPreviewMedia | bots.DeletePreviewMedia | bots.ReorderPreviewMedias | bots.GetPreviewInfo | bots.GetPreviewMedias | bots.UpdateUserEmojiStatus | bots.ToggleUserEmojiStatusPermission | bots.CheckDownloadFileParams | bots.GetAdminedBots | bots.UpdateStarRefProgram | bots.SetCustomVerification | bots.GetBotRecommendations
|
||||||
| payments.GetPaymentForm | payments.GetPaymentReceipt | payments.ValidateRequestedInfo | payments.SendPaymentForm | payments.GetSavedInfo | payments.ClearSavedInfo | payments.GetBankCardData | payments.ExportInvoice | payments.AssignAppStoreTransaction | payments.AssignPlayMarketTransaction | payments.GetPremiumGiftCodeOptions | payments.CheckGiftCode | payments.ApplyGiftCode | payments.GetGiveawayInfo | payments.LaunchPrepaidGiveaway | payments.GetStarsTopupOptions | payments.GetStarsStatus | payments.GetStarsTransactions | payments.SendStarsForm | payments.RefundStarsCharge | payments.GetStarsRevenueStats | payments.GetStarsRevenueWithdrawalUrl | payments.GetStarsRevenueAdsAccountUrl | payments.GetStarsTransactionsByID | payments.GetStarsGiftOptions | payments.GetStarsSubscriptions | payments.ChangeStarsSubscription | payments.FulfillStarsSubscription | payments.GetStarsGiveawayOptions | payments.GetStarGifts | payments.SaveStarGift | payments.ConvertStarGift | payments.BotCancelStarsSubscription | payments.GetConnectedStarRefBots | payments.GetConnectedStarRefBot | payments.GetSuggestedStarRefBots | payments.ConnectStarRefBot | payments.EditConnectedStarRefBot | payments.GetStarGiftUpgradePreview | payments.UpgradeStarGift | payments.TransferStarGift | payments.GetUniqueStarGift | payments.GetSavedStarGifts | payments.GetSavedStarGift | payments.GetStarGiftWithdrawalUrl | payments.ToggleChatStarGiftNotifications | payments.ToggleStarGiftsPinnedToTop | payments.CanPurchaseStore | payments.GetResaleStarGifts | payments.UpdateStarGiftPrice
|
| payments.GetPaymentForm | payments.GetPaymentReceipt | payments.ValidateRequestedInfo | payments.SendPaymentForm | payments.GetSavedInfo | payments.ClearSavedInfo | payments.GetBankCardData | payments.ExportInvoice | payments.AssignAppStoreTransaction | payments.AssignPlayMarketTransaction | payments.GetPremiumGiftCodeOptions | payments.CheckGiftCode | payments.ApplyGiftCode | payments.GetGiveawayInfo | payments.LaunchPrepaidGiveaway | payments.GetStarsTopupOptions | payments.GetStarsStatus | payments.GetStarsTransactions | payments.SendStarsForm | payments.RefundStarsCharge | payments.GetStarsRevenueStats | payments.GetStarsRevenueWithdrawalUrl | payments.GetStarsRevenueAdsAccountUrl | payments.GetStarsTransactionsByID | payments.GetStarsGiftOptions | payments.GetStarsSubscriptions | payments.ChangeStarsSubscription | payments.FulfillStarsSubscription | payments.GetStarsGiveawayOptions | payments.GetStarGifts | payments.SaveStarGift | payments.ConvertStarGift | payments.BotCancelStarsSubscription | payments.GetConnectedStarRefBots | payments.GetConnectedStarRefBot | payments.GetSuggestedStarRefBots | payments.ConnectStarRefBot | payments.EditConnectedStarRefBot | payments.GetStarGiftUpgradePreview | payments.UpgradeStarGift | payments.TransferStarGift | payments.GetUniqueStarGift | payments.GetSavedStarGifts | payments.GetSavedStarGift | payments.GetStarGiftWithdrawalUrl | payments.ToggleChatStarGiftNotifications | payments.ToggleStarGiftsPinnedToTop | payments.CanPurchaseStore | payments.GetResaleStarGifts | payments.UpdateStarGiftPrice | payments.CreateStarGiftCollection | payments.UpdateStarGiftCollection | payments.ReorderStarGiftCollections | payments.DeleteStarGiftCollection | payments.GetStarGiftCollections
|
||||||
| stickers.CreateStickerSet | stickers.RemoveStickerFromSet | stickers.ChangeStickerPosition | stickers.AddStickerToSet | stickers.SetStickerSetThumb | stickers.CheckShortName | stickers.SuggestShortName | stickers.ChangeSticker | stickers.RenameStickerSet | stickers.DeleteStickerSet | stickers.ReplaceSticker
|
| stickers.CreateStickerSet | stickers.RemoveStickerFromSet | stickers.ChangeStickerPosition | stickers.AddStickerToSet | stickers.SetStickerSetThumb | stickers.CheckShortName | stickers.SuggestShortName | stickers.ChangeSticker | stickers.RenameStickerSet | stickers.DeleteStickerSet | stickers.ReplaceSticker
|
||||||
| phone.GetCallConfig | phone.RequestCall | phone.AcceptCall | phone.ConfirmCall | phone.ReceivedCall | phone.DiscardCall | phone.SetCallRating | phone.SaveCallDebug | phone.SendSignalingData | phone.CreateGroupCall | phone.JoinGroupCall | phone.LeaveGroupCall | phone.InviteToGroupCall | phone.DiscardGroupCall | phone.ToggleGroupCallSettings | phone.GetGroupCall | phone.GetGroupParticipants | phone.CheckGroupCall | phone.ToggleGroupCallRecord | phone.EditGroupCallParticipant | phone.EditGroupCallTitle | phone.GetGroupCallJoinAs | phone.ExportGroupCallInvite | phone.ToggleGroupCallStartSubscription | phone.StartScheduledGroupCall | phone.SaveDefaultGroupCallJoinAs | phone.JoinGroupCallPresentation | phone.LeaveGroupCallPresentation | phone.GetGroupCallStreamChannels | phone.GetGroupCallStreamRtmpUrl | phone.SaveCallLog | phone.CreateConferenceCall | phone.DeleteConferenceCallParticipants | phone.SendConferenceCallBroadcast | phone.InviteConferenceCallParticipant | phone.DeclineConferenceCallInvite | phone.GetGroupCallChainBlocks
|
| phone.GetCallConfig | phone.RequestCall | phone.AcceptCall | phone.ConfirmCall | phone.ReceivedCall | phone.DiscardCall | phone.SetCallRating | phone.SaveCallDebug | phone.SendSignalingData | phone.CreateGroupCall | phone.JoinGroupCall | phone.LeaveGroupCall | phone.InviteToGroupCall | phone.DiscardGroupCall | phone.ToggleGroupCallSettings | phone.GetGroupCall | phone.GetGroupParticipants | phone.CheckGroupCall | phone.ToggleGroupCallRecord | phone.EditGroupCallParticipant | phone.EditGroupCallTitle | phone.GetGroupCallJoinAs | phone.ExportGroupCallInvite | phone.ToggleGroupCallStartSubscription | phone.StartScheduledGroupCall | phone.SaveDefaultGroupCallJoinAs | phone.JoinGroupCallPresentation | phone.LeaveGroupCallPresentation | phone.GetGroupCallStreamChannels | phone.GetGroupCallStreamRtmpUrl | phone.SaveCallLog | phone.CreateConferenceCall | phone.DeleteConferenceCallParticipants | phone.SendConferenceCallBroadcast | phone.InviteConferenceCallParticipant | phone.DeclineConferenceCallInvite | phone.GetGroupCallChainBlocks
|
||||||
| langpack.GetLangPack | langpack.GetStrings | langpack.GetDifference | langpack.GetLanguages | langpack.GetLanguage
|
| langpack.GetLangPack | langpack.GetStrings | langpack.GetDifference | langpack.GetLanguages | langpack.GetLanguage
|
||||||
|
|||||||
@ -208,7 +208,7 @@ inputReportReasonGeoIrrelevant#dbd4feed = ReportReason;
|
|||||||
inputReportReasonFake#f5ddd6e7 = ReportReason;
|
inputReportReasonFake#f5ddd6e7 = ReportReason;
|
||||||
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
|
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
|
||||||
inputReportReasonPersonalDetails#9ec7863d = ReportReason;
|
inputReportReasonPersonalDetails#9ec7863d = ReportReason;
|
||||||
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;
|
userFull#29de80be 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 stars_rating:flags2.17?StarsRating = 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;
|
||||||
@ -1051,7 +1051,7 @@ help.countriesList#87d0759e countries:Vector<help.Country> hash:int = help.Count
|
|||||||
messageViews#455b853d flags:# views:flags.0?int forwards:flags.1?int replies:flags.2?MessageReplies = MessageViews;
|
messageViews#455b853d flags:# views:flags.0?int forwards:flags.1?int replies:flags.2?MessageReplies = MessageViews;
|
||||||
messages.messageViews#b6c4f543 views:Vector<MessageViews> chats:Vector<Chat> users:Vector<User> = messages.MessageViews;
|
messages.messageViews#b6c4f543 views:Vector<MessageViews> chats:Vector<Chat> users:Vector<User> = messages.MessageViews;
|
||||||
messages.discussionMessage#a6341782 flags:# messages:Vector<Message> max_id:flags.0?int read_inbox_max_id:flags.1?int read_outbox_max_id:flags.2?int unread_count:int chats:Vector<Chat> users:Vector<User> = messages.DiscussionMessage;
|
messages.discussionMessage#a6341782 flags:# messages:Vector<Message> max_id:flags.0?int read_inbox_max_id:flags.1?int read_outbox_max_id:flags.2?int unread_count:int chats:Vector<Chat> users:Vector<User> = messages.DiscussionMessage;
|
||||||
messageReplyHeader#afbc09db flags:# reply_to_scheduled:flags.2?true forum_topic:flags.3?true quote:flags.9?true reply_to_msg_id:flags.4?int reply_to_peer_id:flags.0?Peer reply_from:flags.5?MessageFwdHeader reply_media:flags.8?MessageMedia reply_to_top_id:flags.1?int quote_text:flags.6?string quote_entities:flags.7?Vector<MessageEntity> quote_offset:flags.10?int = MessageReplyHeader;
|
messageReplyHeader#6917560b flags:# reply_to_scheduled:flags.2?true forum_topic:flags.3?true quote:flags.9?true reply_to_msg_id:flags.4?int reply_to_peer_id:flags.0?Peer reply_from:flags.5?MessageFwdHeader reply_media:flags.8?MessageMedia reply_to_top_id:flags.1?int quote_text:flags.6?string quote_entities:flags.7?Vector<MessageEntity> quote_offset:flags.10?int todo_item_id:flags.11?int = MessageReplyHeader;
|
||||||
messageReplyStoryHeader#e5af939 peer:Peer story_id:int = MessageReplyHeader;
|
messageReplyStoryHeader#e5af939 peer:Peer story_id:int = MessageReplyHeader;
|
||||||
messageReplies#83d60fc2 flags:# comments:flags.0?true replies:int replies_pts:int recent_repliers:flags.1?Vector<Peer> channel_id:flags.0?long max_id:flags.2?int read_max_id:flags.3?int = MessageReplies;
|
messageReplies#83d60fc2 flags:# comments:flags.0?true replies:int replies_pts:int recent_repliers:flags.1?Vector<Peer> channel_id:flags.0?long max_id:flags.2?int read_max_id:flags.3?int = MessageReplies;
|
||||||
peerBlocked#e8fd8014 peer_id:Peer date:int = PeerBlocked;
|
peerBlocked#e8fd8014 peer_id:Peer date:int = PeerBlocked;
|
||||||
@ -1245,7 +1245,7 @@ storyViewPublicForward#9083670b flags:# blocked:flags.0?true blocked_my_stories_
|
|||||||
storyViewPublicRepost#bd74cf49 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true peer_id:Peer story:StoryItem = StoryView;
|
storyViewPublicRepost#bd74cf49 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true peer_id:Peer story:StoryItem = StoryView;
|
||||||
stories.storyViewsList#59d78fc5 flags:# count:int views_count:int forwards_count:int reactions_count:int views:Vector<StoryView> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = stories.StoryViewsList;
|
stories.storyViewsList#59d78fc5 flags:# count:int views_count:int forwards_count:int reactions_count:int views:Vector<StoryView> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = stories.StoryViewsList;
|
||||||
stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews;
|
stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews;
|
||||||
inputReplyToMessage#b07038b0 flags:# reply_to_msg_id:int top_msg_id:flags.0?int reply_to_peer_id:flags.1?InputPeer quote_text:flags.2?string quote_entities:flags.3?Vector<MessageEntity> quote_offset:flags.4?int monoforum_peer_id:flags.5?InputPeer = InputReplyTo;
|
inputReplyToMessage#869fbe10 flags:# reply_to_msg_id:int top_msg_id:flags.0?int reply_to_peer_id:flags.1?InputPeer quote_text:flags.2?string quote_entities:flags.3?Vector<MessageEntity> quote_offset:flags.4?int monoforum_peer_id:flags.5?InputPeer todo_item_id:flags.6?int = InputReplyTo;
|
||||||
inputReplyToStory#5881323a peer:InputPeer story_id:int = InputReplyTo;
|
inputReplyToStory#5881323a peer:InputPeer story_id:int = InputReplyTo;
|
||||||
inputReplyToMonoForum#69d66c45 monoforum_peer_id:InputPeer = InputReplyTo;
|
inputReplyToMonoForum#69d66c45 monoforum_peer_id:InputPeer = InputReplyTo;
|
||||||
exportedStoryLink#3fc9053b link:string = ExportedStoryLink;
|
exportedStoryLink#3fc9053b link:string = ExportedStoryLink;
|
||||||
@ -1386,8 +1386,8 @@ starsSubscription#2e6eab1a flags:# canceled:flags.0?true can_refulfill:flags.1?t
|
|||||||
messageReactor#4ba3a95a flags:# top:flags.0?true my:flags.1?true anonymous:flags.2?true peer_id:flags.3?Peer count:int = MessageReactor;
|
messageReactor#4ba3a95a flags:# top:flags.0?true my:flags.1?true anonymous:flags.2?true peer_id:flags.3?Peer count:int = MessageReactor;
|
||||||
starsGiveawayOption#94ce852a flags:# extended:flags.0?true default:flags.1?true stars:long yearly_boosts:int store_product:flags.2?string currency:string amount:long winners:Vector<StarsGiveawayWinnersOption> = StarsGiveawayOption;
|
starsGiveawayOption#94ce852a flags:# extended:flags.0?true default:flags.1?true stars:long yearly_boosts:int store_product:flags.2?string currency:string amount:long winners:Vector<StarsGiveawayWinnersOption> = StarsGiveawayOption;
|
||||||
starsGiveawayWinnersOption#54236209 flags:# default:flags.0?true users:int per_user_stars:long = StarsGiveawayWinnersOption;
|
starsGiveawayWinnersOption#54236209 flags:# default:flags.0?true users:int per_user_stars:long = StarsGiveawayWinnersOption;
|
||||||
starGift#7f853c12 flags:# limited:flags.0?true sold_out:flags.1?true birthday:flags.2?true id:long sticker:Document stars:long availability_remains:flags.0?int availability_total:flags.0?int availability_resale:flags.4?long convert_stars:long first_sale_date:flags.1?int last_sale_date:flags.1?int upgrade_stars:flags.3?long resell_min_stars:flags.4?long title:flags.5?string released_by:flags.6?Peer = StarGift;
|
starGift#bcff5b flags:# limited:flags.0?true sold_out:flags.1?true birthday:flags.2?true require_premium:flags.7?true limited_per_user:flags.8?true id:long sticker:Document stars:long availability_remains:flags.0?int availability_total:flags.0?int availability_resale:flags.4?long convert_stars:long first_sale_date:flags.1?int last_sale_date:flags.1?int upgrade_stars:flags.3?long resell_min_stars:flags.4?long title:flags.5?string released_by:flags.6?Peer per_user_total:flags.8?int per_user_remains:flags.8?int = StarGift;
|
||||||
starGiftUnique#f63778ae flags:# id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector<StarGiftAttribute> availability_issued:int availability_total:int gift_address:flags.3?string resell_stars:flags.4?long released_by:flags.5?Peer = StarGift;
|
starGiftUnique#f63778ae flags:# require_premium:flags.6?true id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector<StarGiftAttribute> availability_issued:int availability_total:int gift_address:flags.3?string resell_stars:flags.4?long released_by:flags.5?Peer = StarGift;
|
||||||
payments.starGiftsNotModified#a388a368 = payments.StarGifts;
|
payments.starGiftsNotModified#a388a368 = payments.StarGifts;
|
||||||
payments.starGifts#2ed82995 hash:int gifts:Vector<StarGift> chats:Vector<Chat> users:Vector<User> = payments.StarGifts;
|
payments.starGifts#2ed82995 hash:int gifts:Vector<StarGift> chats:Vector<Chat> users:Vector<User> = payments.StarGifts;
|
||||||
messageReportOption#7903e3d9 text:string option:bytes = MessageReportOption;
|
messageReportOption#7903e3d9 text:string option:bytes = MessageReportOption;
|
||||||
@ -1416,7 +1416,7 @@ users.users#62d706b8 users:Vector<User> = users.Users;
|
|||||||
users.usersSlice#315a4974 count:int users:Vector<User> = users.Users;
|
users.usersSlice#315a4974 count:int users:Vector<User> = users.Users;
|
||||||
payments.uniqueStarGift#caa2f60b gift:StarGift users:Vector<User> = payments.UniqueStarGift;
|
payments.uniqueStarGift#caa2f60b gift:StarGift users:Vector<User> = payments.UniqueStarGift;
|
||||||
messages.webPagePreview#b53e8b21 media:MessageMedia users:Vector<User> = messages.WebPagePreview;
|
messages.webPagePreview#b53e8b21 media:MessageMedia users:Vector<User> = messages.WebPagePreview;
|
||||||
savedStarGift#dfda0499 flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true pinned_to_top:flags.12?true from_id:flags.1?Peer date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int saved_id:flags.11?long convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long can_transfer_at:flags.13?int can_resell_at:flags.14?int = SavedStarGift;
|
savedStarGift#1ea646df flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true pinned_to_top:flags.12?true from_id:flags.1?Peer date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int saved_id:flags.11?long convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long can_transfer_at:flags.13?int can_resell_at:flags.14?int collection_id:flags.15?Vector<int> = SavedStarGift;
|
||||||
payments.savedStarGifts#95f389b1 flags:# count:int chat_notifications_enabled:flags.1?Bool gifts:Vector<SavedStarGift> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.SavedStarGifts;
|
payments.savedStarGifts#95f389b1 flags:# count:int chat_notifications_enabled:flags.1?Bool gifts:Vector<SavedStarGift> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.SavedStarGifts;
|
||||||
inputSavedStarGiftUser#69279795 msg_id:int = InputSavedStarGift;
|
inputSavedStarGiftUser#69279795 msg_id:int = InputSavedStarGift;
|
||||||
inputSavedStarGiftChat#f101aa7f peer:InputPeer saved_id:long = InputSavedStarGift;
|
inputSavedStarGiftChat#f101aa7f peer:InputPeer saved_id:long = InputSavedStarGift;
|
||||||
@ -1445,6 +1445,10 @@ todoItem#cba9a52f id:int title:TextWithEntities = TodoItem;
|
|||||||
todoList#49b92a26 flags:# others_can_append:flags.0?true others_can_complete:flags.1?true title:TextWithEntities list:Vector<TodoItem> = TodoList;
|
todoList#49b92a26 flags:# others_can_append:flags.0?true others_can_complete:flags.1?true title:TextWithEntities list:Vector<TodoItem> = TodoList;
|
||||||
todoCompletion#4cc120b7 id:int completed_by:long date:int = TodoCompletion;
|
todoCompletion#4cc120b7 id:int completed_by:long date:int = TodoCompletion;
|
||||||
suggestedPost#e8e37e5 flags:# accepted:flags.1?true rejected:flags.2?true price:flags.3?StarsAmount schedule_date:flags.0?int = SuggestedPost;
|
suggestedPost#e8e37e5 flags:# accepted:flags.1?true rejected:flags.2?true price:flags.3?StarsAmount schedule_date:flags.0?int = SuggestedPost;
|
||||||
|
starsRating#1b0e4f07 flags:# level:int current_level_stars:long stars:long next_level_stars:flags.0?long = StarsRating;
|
||||||
|
starGiftCollection#9d6b13b0 flags:# collection_id:int title:string icon:flags.0?Document gifts_count:int hash:long = StarGiftCollection;
|
||||||
|
payments.starGiftCollectionsNotModified#a0ba4f17 = payments.StarGiftCollections;
|
||||||
|
payments.starGiftCollections#8a2932f3 collections:Vector<StarGiftCollection> = payments.StarGiftCollections;
|
||||||
---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;
|
||||||
@ -1779,7 +1783,7 @@ payments.getStarGiftUpgradePreview#9c9abcb1 gift_id:long = payments.StarGiftUpgr
|
|||||||
payments.upgradeStarGift#aed6e4f5 flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = Updates;
|
payments.upgradeStarGift#aed6e4f5 flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = Updates;
|
||||||
payments.transferStarGift#7f18176a stargift:InputSavedStarGift to_id:InputPeer = Updates;
|
payments.transferStarGift#7f18176a stargift:InputSavedStarGift to_id:InputPeer = Updates;
|
||||||
payments.getUniqueStarGift#a1974d72 slug:string = payments.UniqueStarGift;
|
payments.getUniqueStarGift#a1974d72 slug:string = payments.UniqueStarGift;
|
||||||
payments.getSavedStarGifts#23830de9 flags:# exclude_unsaved:flags.0?true exclude_saved:flags.1?true exclude_unlimited:flags.2?true exclude_limited:flags.3?true exclude_unique:flags.4?true sort_by_value:flags.5?true peer:InputPeer offset:string limit:int = payments.SavedStarGifts;
|
payments.getSavedStarGifts#a319e569 flags:# exclude_unsaved:flags.0?true exclude_saved:flags.1?true exclude_unlimited:flags.2?true exclude_limited:flags.3?true exclude_unique:flags.4?true sort_by_value:flags.5?true peer:InputPeer collection_id:flags.6?int offset:string limit:int = payments.SavedStarGifts;
|
||||||
payments.getStarGiftWithdrawalUrl#d06e93a8 stargift:InputSavedStarGift password:InputCheckPasswordSRP = payments.StarGiftWithdrawalUrl;
|
payments.getStarGiftWithdrawalUrl#d06e93a8 stargift:InputSavedStarGift password:InputCheckPasswordSRP = payments.StarGiftWithdrawalUrl;
|
||||||
payments.toggleStarGiftsPinnedToTop#1513e7b0 peer:InputPeer stargift:Vector<InputSavedStarGift> = Bool;
|
payments.toggleStarGiftsPinnedToTop#1513e7b0 peer:InputPeer stargift:Vector<InputSavedStarGift> = Bool;
|
||||||
payments.getResaleStarGifts#7a5fa236 flags:# sort_by_price:flags.1?true sort_by_num:flags.2?true attributes_hash:flags.0?long gift_id:long attributes:flags.3?Vector<StarGiftAttributeId> offset:string limit:int = payments.ResaleStarGifts;
|
payments.getResaleStarGifts#7a5fa236 flags:# sort_by_price:flags.1?true sort_by_num:flags.2?true attributes_hash:flags.0?long gift_id:long attributes:flags.3?Vector<StarGiftAttributeId> offset:string limit:int = payments.ResaleStarGifts;
|
||||||
|
|||||||
@ -248,7 +248,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason;
|
|||||||
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
|
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
|
||||||
inputReportReasonPersonalDetails#9ec7863d = ReportReason;
|
inputReportReasonPersonalDetails#9ec7863d = ReportReason;
|
||||||
|
|
||||||
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;
|
userFull#29de80be 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 stars_rating:flags2.17?StarsRating = UserFull;
|
||||||
|
|
||||||
contact#145ade0b user_id:long mutual:Bool = Contact;
|
contact#145ade0b user_id:long mutual:Bool = Contact;
|
||||||
|
|
||||||
@ -1344,7 +1344,7 @@ messages.messageViews#b6c4f543 views:Vector<MessageViews> chats:Vector<Chat> use
|
|||||||
|
|
||||||
messages.discussionMessage#a6341782 flags:# messages:Vector<Message> max_id:flags.0?int read_inbox_max_id:flags.1?int read_outbox_max_id:flags.2?int unread_count:int chats:Vector<Chat> users:Vector<User> = messages.DiscussionMessage;
|
messages.discussionMessage#a6341782 flags:# messages:Vector<Message> max_id:flags.0?int read_inbox_max_id:flags.1?int read_outbox_max_id:flags.2?int unread_count:int chats:Vector<Chat> users:Vector<User> = messages.DiscussionMessage;
|
||||||
|
|
||||||
messageReplyHeader#afbc09db flags:# reply_to_scheduled:flags.2?true forum_topic:flags.3?true quote:flags.9?true reply_to_msg_id:flags.4?int reply_to_peer_id:flags.0?Peer reply_from:flags.5?MessageFwdHeader reply_media:flags.8?MessageMedia reply_to_top_id:flags.1?int quote_text:flags.6?string quote_entities:flags.7?Vector<MessageEntity> quote_offset:flags.10?int = MessageReplyHeader;
|
messageReplyHeader#6917560b flags:# reply_to_scheduled:flags.2?true forum_topic:flags.3?true quote:flags.9?true reply_to_msg_id:flags.4?int reply_to_peer_id:flags.0?Peer reply_from:flags.5?MessageFwdHeader reply_media:flags.8?MessageMedia reply_to_top_id:flags.1?int quote_text:flags.6?string quote_entities:flags.7?Vector<MessageEntity> quote_offset:flags.10?int todo_item_id:flags.11?int = MessageReplyHeader;
|
||||||
messageReplyStoryHeader#e5af939 peer:Peer story_id:int = MessageReplyHeader;
|
messageReplyStoryHeader#e5af939 peer:Peer story_id:int = MessageReplyHeader;
|
||||||
|
|
||||||
messageReplies#83d60fc2 flags:# comments:flags.0?true replies:int replies_pts:int recent_repliers:flags.1?Vector<Peer> channel_id:flags.0?long max_id:flags.2?int read_max_id:flags.3?int = MessageReplies;
|
messageReplies#83d60fc2 flags:# comments:flags.0?true replies:int replies_pts:int recent_repliers:flags.1?Vector<Peer> channel_id:flags.0?long max_id:flags.2?int read_max_id:flags.3?int = MessageReplies;
|
||||||
@ -1649,7 +1649,7 @@ stories.storyViewsList#59d78fc5 flags:# count:int views_count:int forwards_count
|
|||||||
|
|
||||||
stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews;
|
stories.storyViews#de9eed1d views:Vector<StoryViews> users:Vector<User> = stories.StoryViews;
|
||||||
|
|
||||||
inputReplyToMessage#b07038b0 flags:# reply_to_msg_id:int top_msg_id:flags.0?int reply_to_peer_id:flags.1?InputPeer quote_text:flags.2?string quote_entities:flags.3?Vector<MessageEntity> quote_offset:flags.4?int monoforum_peer_id:flags.5?InputPeer = InputReplyTo;
|
inputReplyToMessage#869fbe10 flags:# reply_to_msg_id:int top_msg_id:flags.0?int reply_to_peer_id:flags.1?InputPeer quote_text:flags.2?string quote_entities:flags.3?Vector<MessageEntity> quote_offset:flags.4?int monoforum_peer_id:flags.5?InputPeer todo_item_id:flags.6?int = InputReplyTo;
|
||||||
inputReplyToStory#5881323a peer:InputPeer story_id:int = InputReplyTo;
|
inputReplyToStory#5881323a peer:InputPeer story_id:int = InputReplyTo;
|
||||||
inputReplyToMonoForum#69d66c45 monoforum_peer_id:InputPeer = InputReplyTo;
|
inputReplyToMonoForum#69d66c45 monoforum_peer_id:InputPeer = InputReplyTo;
|
||||||
|
|
||||||
@ -1890,8 +1890,8 @@ starsGiveawayOption#94ce852a flags:# extended:flags.0?true default:flags.1?true
|
|||||||
|
|
||||||
starsGiveawayWinnersOption#54236209 flags:# default:flags.0?true users:int per_user_stars:long = StarsGiveawayWinnersOption;
|
starsGiveawayWinnersOption#54236209 flags:# default:flags.0?true users:int per_user_stars:long = StarsGiveawayWinnersOption;
|
||||||
|
|
||||||
starGift#7f853c12 flags:# limited:flags.0?true sold_out:flags.1?true birthday:flags.2?true id:long sticker:Document stars:long availability_remains:flags.0?int availability_total:flags.0?int availability_resale:flags.4?long convert_stars:long first_sale_date:flags.1?int last_sale_date:flags.1?int upgrade_stars:flags.3?long resell_min_stars:flags.4?long title:flags.5?string released_by:flags.6?Peer = StarGift;
|
starGift#bcff5b flags:# limited:flags.0?true sold_out:flags.1?true birthday:flags.2?true require_premium:flags.7?true limited_per_user:flags.8?true id:long sticker:Document stars:long availability_remains:flags.0?int availability_total:flags.0?int availability_resale:flags.4?long convert_stars:long first_sale_date:flags.1?int last_sale_date:flags.1?int upgrade_stars:flags.3?long resell_min_stars:flags.4?long title:flags.5?string released_by:flags.6?Peer per_user_total:flags.8?int per_user_remains:flags.8?int = StarGift;
|
||||||
starGiftUnique#f63778ae flags:# id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector<StarGiftAttribute> availability_issued:int availability_total:int gift_address:flags.3?string resell_stars:flags.4?long released_by:flags.5?Peer = StarGift;
|
starGiftUnique#f63778ae flags:# require_premium:flags.6?true id:long title:string slug:string num:int owner_id:flags.0?Peer owner_name:flags.1?string owner_address:flags.2?string attributes:Vector<StarGiftAttribute> availability_issued:int availability_total:int gift_address:flags.3?string resell_stars:flags.4?long released_by:flags.5?Peer = StarGift;
|
||||||
|
|
||||||
payments.starGiftsNotModified#a388a368 = payments.StarGifts;
|
payments.starGiftsNotModified#a388a368 = payments.StarGifts;
|
||||||
payments.starGifts#2ed82995 hash:int gifts:Vector<StarGift> chats:Vector<Chat> users:Vector<User> = payments.StarGifts;
|
payments.starGifts#2ed82995 hash:int gifts:Vector<StarGift> chats:Vector<Chat> users:Vector<User> = payments.StarGifts;
|
||||||
@ -1940,7 +1940,7 @@ payments.uniqueStarGift#caa2f60b gift:StarGift users:Vector<User> = payments.Uni
|
|||||||
|
|
||||||
messages.webPagePreview#b53e8b21 media:MessageMedia users:Vector<User> = messages.WebPagePreview;
|
messages.webPagePreview#b53e8b21 media:MessageMedia users:Vector<User> = messages.WebPagePreview;
|
||||||
|
|
||||||
savedStarGift#dfda0499 flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true pinned_to_top:flags.12?true from_id:flags.1?Peer date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int saved_id:flags.11?long convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long can_transfer_at:flags.13?int can_resell_at:flags.14?int = SavedStarGift;
|
savedStarGift#1ea646df flags:# name_hidden:flags.0?true unsaved:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true pinned_to_top:flags.12?true from_id:flags.1?Peer date:int gift:StarGift message:flags.2?TextWithEntities msg_id:flags.3?int saved_id:flags.11?long convert_stars:flags.4?long upgrade_stars:flags.6?long can_export_at:flags.7?int transfer_stars:flags.8?long can_transfer_at:flags.13?int can_resell_at:flags.14?int collection_id:flags.15?Vector<int> = SavedStarGift;
|
||||||
|
|
||||||
payments.savedStarGifts#95f389b1 flags:# count:int chat_notifications_enabled:flags.1?Bool gifts:Vector<SavedStarGift> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.SavedStarGifts;
|
payments.savedStarGifts#95f389b1 flags:# count:int chat_notifications_enabled:flags.1?Bool gifts:Vector<SavedStarGift> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.SavedStarGifts;
|
||||||
|
|
||||||
@ -1989,6 +1989,13 @@ todoCompletion#4cc120b7 id:int completed_by:long date:int = TodoCompletion;
|
|||||||
|
|
||||||
suggestedPost#e8e37e5 flags:# accepted:flags.1?true rejected:flags.2?true price:flags.3?StarsAmount schedule_date:flags.0?int = SuggestedPost;
|
suggestedPost#e8e37e5 flags:# accepted:flags.1?true rejected:flags.2?true price:flags.3?StarsAmount schedule_date:flags.0?int = SuggestedPost;
|
||||||
|
|
||||||
|
starsRating#1b0e4f07 flags:# level:int current_level_stars:long stars:long next_level_stars:flags.0?long = StarsRating;
|
||||||
|
|
||||||
|
starGiftCollection#9d6b13b0 flags:# collection_id:int title:string icon:flags.0?Document gifts_count:int hash:long = StarGiftCollection;
|
||||||
|
|
||||||
|
payments.starGiftCollectionsNotModified#a0ba4f17 = payments.StarGiftCollections;
|
||||||
|
payments.starGiftCollections#8a2932f3 collections:Vector<StarGiftCollection> = payments.StarGiftCollections;
|
||||||
|
|
||||||
---functions---
|
---functions---
|
||||||
|
|
||||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||||
@ -2000,7 +2007,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;
|
||||||
@ -2590,7 +2597,7 @@ payments.getStarGiftUpgradePreview#9c9abcb1 gift_id:long = payments.StarGiftUpgr
|
|||||||
payments.upgradeStarGift#aed6e4f5 flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = Updates;
|
payments.upgradeStarGift#aed6e4f5 flags:# keep_original_details:flags.0?true stargift:InputSavedStarGift = Updates;
|
||||||
payments.transferStarGift#7f18176a stargift:InputSavedStarGift to_id:InputPeer = Updates;
|
payments.transferStarGift#7f18176a stargift:InputSavedStarGift to_id:InputPeer = Updates;
|
||||||
payments.getUniqueStarGift#a1974d72 slug:string = payments.UniqueStarGift;
|
payments.getUniqueStarGift#a1974d72 slug:string = payments.UniqueStarGift;
|
||||||
payments.getSavedStarGifts#23830de9 flags:# exclude_unsaved:flags.0?true exclude_saved:flags.1?true exclude_unlimited:flags.2?true exclude_limited:flags.3?true exclude_unique:flags.4?true sort_by_value:flags.5?true peer:InputPeer offset:string limit:int = payments.SavedStarGifts;
|
payments.getSavedStarGifts#a319e569 flags:# exclude_unsaved:flags.0?true exclude_saved:flags.1?true exclude_unlimited:flags.2?true exclude_limited:flags.3?true exclude_unique:flags.4?true sort_by_value:flags.5?true peer:InputPeer collection_id:flags.6?int offset:string limit:int = payments.SavedStarGifts;
|
||||||
payments.getSavedStarGift#b455a106 stargift:Vector<InputSavedStarGift> = payments.SavedStarGifts;
|
payments.getSavedStarGift#b455a106 stargift:Vector<InputSavedStarGift> = payments.SavedStarGifts;
|
||||||
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;
|
||||||
@ -2598,6 +2605,11 @@ payments.toggleStarGiftsPinnedToTop#1513e7b0 peer:InputPeer stargift:Vector<Inpu
|
|||||||
payments.canPurchaseStore#4fdc5ea7 purpose:InputStorePaymentPurpose = Bool;
|
payments.canPurchaseStore#4fdc5ea7 purpose:InputStorePaymentPurpose = Bool;
|
||||||
payments.getResaleStarGifts#7a5fa236 flags:# sort_by_price:flags.1?true sort_by_num:flags.2?true attributes_hash:flags.0?long gift_id:long attributes:flags.3?Vector<StarGiftAttributeId> offset:string limit:int = payments.ResaleStarGifts;
|
payments.getResaleStarGifts#7a5fa236 flags:# sort_by_price:flags.1?true sort_by_num:flags.2?true attributes_hash:flags.0?long gift_id:long attributes:flags.3?Vector<StarGiftAttributeId> offset:string limit:int = payments.ResaleStarGifts;
|
||||||
payments.updateStarGiftPrice#3baea4e1 stargift:InputSavedStarGift resell_stars:long = Updates;
|
payments.updateStarGiftPrice#3baea4e1 stargift:InputSavedStarGift resell_stars:long = Updates;
|
||||||
|
payments.createStarGiftCollection#1f4a0e87 peer:InputPeer title:string stargift:Vector<InputSavedStarGift> = StarGiftCollection;
|
||||||
|
payments.updateStarGiftCollection#4fddbee7 flags:# peer:InputPeer collection_id:int title:flags.0?string delete_stargift:flags.1?Vector<InputSavedStarGift> add_stargift:flags.2?Vector<InputSavedStarGift> order:flags.3?Vector<InputSavedStarGift> = StarGiftCollection;
|
||||||
|
payments.reorderStarGiftCollections#c32af4cc peer:InputPeer order:Vector<int> = Bool;
|
||||||
|
payments.deleteStarGiftCollection#ad5648e8 peer:InputPeer collection_id:int = Bool;
|
||||||
|
payments.getStarGiftCollections#981b91dd peer:InputPeer hash:long = payments.StarGiftCollections;
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
13
src/types/language.d.ts
vendored
13
src/types/language.d.ts
vendored
@ -1600,6 +1600,16 @@ export interface LangPair {
|
|||||||
'ButtonTopUpViaFragment': undefined;
|
'ButtonTopUpViaFragment': undefined;
|
||||||
'TonModalHint': undefined;
|
'TonModalHint': undefined;
|
||||||
'TonGiftReceived': undefined;
|
'TonGiftReceived': undefined;
|
||||||
|
'MediaSpoilerSensitive': undefined;
|
||||||
|
'TitleSensitiveModal': undefined;
|
||||||
|
'TextSensitiveModal': undefined;
|
||||||
|
'ButtonSensitiveAlways': undefined;
|
||||||
|
'ButtonSensitiveView': undefined;
|
||||||
|
'TitleAgeVerificationModal': undefined;
|
||||||
|
'DescriptionAgeVerificationModal': undefined;
|
||||||
|
'TitleAgeCheckFailed': undefined;
|
||||||
|
'TitleAgeCheckSuccess': undefined;
|
||||||
|
'ButtonAgeVerification': undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LangPairWithVariables<V = LangVariable> {
|
export interface LangPairWithVariables<V = LangVariable> {
|
||||||
@ -3089,6 +3099,9 @@ export interface LangPairPluralWithVariables<V = LangVariable> {
|
|||||||
'MessageActionTodoTaskCount': {
|
'MessageActionTodoTaskCount': {
|
||||||
'count': V;
|
'count': V;
|
||||||
};
|
};
|
||||||
|
'TextAgeVerificationModal': {
|
||||||
|
'count': V;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
export type RegularLangKey = keyof LangPair;
|
export type RegularLangKey = keyof LangPair;
|
||||||
export type RegularLangKeyWithVariables = keyof LangPairWithVariables;
|
export type RegularLangKeyWithVariables = keyof LangPairWithVariables;
|
||||||
|
|||||||
@ -91,6 +91,7 @@ interface WebAppInboundEventMap {
|
|||||||
web_app_biometry_request_auth: { reason: string };
|
web_app_biometry_request_auth: { reason: string };
|
||||||
web_app_biometry_update_token: { token: string };
|
web_app_biometry_update_token: { token: string };
|
||||||
web_app_set_emoji_status: { custom_emoji_id: string; duration?: number };
|
web_app_set_emoji_status: { custom_emoji_id: string; duration?: number };
|
||||||
|
web_app_verify_age: { passed: boolean; age?: number };
|
||||||
web_app_request_file_download: { url: string; file_name: string };
|
web_app_request_file_download: { url: string; file_name: string };
|
||||||
web_app_send_prepared_message: { id: string };
|
web_app_send_prepared_message: { id: string };
|
||||||
web_app_device_storage_save_key: {
|
web_app_device_storage_save_key: {
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import {
|
|||||||
import { getIsChatMuted } from '../global/helpers/notifications';
|
import { getIsChatMuted } from '../global/helpers/notifications';
|
||||||
import {
|
import {
|
||||||
selectChatLastMessage,
|
selectChatLastMessage,
|
||||||
|
selectIsChatRestricted,
|
||||||
selectNotifyDefaults,
|
selectNotifyDefaults,
|
||||||
selectTabState,
|
selectTabState,
|
||||||
selectTopics,
|
selectTopics,
|
||||||
@ -527,10 +528,11 @@ function buildChatSummary<T extends GlobalState>(
|
|||||||
isRemovedFromSaved?: boolean,
|
isRemovedFromSaved?: boolean,
|
||||||
): ChatSummary {
|
): ChatSummary {
|
||||||
const {
|
const {
|
||||||
id, type, isRestricted, isNotJoined, migratedTo, folderId,
|
id, type, isNotJoined, migratedTo, folderId,
|
||||||
unreadCount: chatUnreadCount, unreadMentionsCount: chatUnreadMentionsCount, hasUnreadMark,
|
unreadCount: chatUnreadCount, unreadMentionsCount: chatUnreadMentionsCount, hasUnreadMark,
|
||||||
isForum,
|
isForum,
|
||||||
} = chat;
|
} = chat;
|
||||||
|
const isRestricted = selectIsChatRestricted(global, id);
|
||||||
const topics = selectTopics(global, chat.id);
|
const topics = selectTopics(global, chat.id);
|
||||||
|
|
||||||
const { unreadCount, unreadMentionsCount } = isForum
|
const { unreadCount, unreadMentionsCount } = isForum
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user