Sponsored Message: Implement reporting (#4487)
This commit is contained in:
parent
19e90c8fbb
commit
37ad59d937
@ -74,6 +74,7 @@ export interface GramJsAppConfig extends LimitsConfig {
|
||||
// Boosts
|
||||
group_transcribe_level_min?: number;
|
||||
new_noncontact_peers_require_premium_without_ownpremium?: boolean;
|
||||
channel_restrict_sponsored_level_min?: number;
|
||||
// Upload premium notifications
|
||||
upload_premium_speedup_notify_period?: number;
|
||||
upload_premium_speedup_download?: number;
|
||||
@ -156,5 +157,6 @@ export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiApp
|
||||
bandwidthPremiumNotifyPeriod: appConfig.upload_premium_speedup_notify_period,
|
||||
bandwidthPremiumUploadSpeedup: appConfig.upload_premium_speedup_upload,
|
||||
bandwidthPremiumDownloadSpeedup: appConfig.upload_premium_speedup_download,
|
||||
channelRestrictAdsLevelMin: appConfig.channel_restrict_sponsored_level_min,
|
||||
};
|
||||
}
|
||||
|
||||
@ -17,11 +17,13 @@ import type {
|
||||
ApiMissingInvitedUser,
|
||||
ApiRestrictionReason,
|
||||
ApiSendAsPeerId,
|
||||
ApiSponsoredMessageReportResult,
|
||||
ApiTopic,
|
||||
} from '../../types';
|
||||
|
||||
import { omitUndefined, pick, pickTruthy } from '../../../util/iteratees';
|
||||
import { getServerTime, getServerTimeOffset } from '../../../util/serverTime';
|
||||
import { serializeBytes } from '../helpers';
|
||||
import { buildApiUsernames } from './common';
|
||||
import { omitVirtualClassFields } from './helpers';
|
||||
import {
|
||||
@ -645,3 +647,31 @@ export function buildApiMissingInvitedUser(
|
||||
isRequiringPremiumToInvite: user.premiumWouldAllowInvite,
|
||||
};
|
||||
}
|
||||
|
||||
export function buildApiSponsoredMessageReportResult(
|
||||
result: GramJs.channels.TypeSponsoredMessageReportResult,
|
||||
): ApiSponsoredMessageReportResult {
|
||||
if (result instanceof GramJs.channels.SponsoredMessageReportResultReported) {
|
||||
return {
|
||||
type: 'reported',
|
||||
};
|
||||
}
|
||||
|
||||
if (result instanceof GramJs.channels.SponsoredMessageReportResultAdsHidden) {
|
||||
return {
|
||||
type: 'hidden',
|
||||
};
|
||||
}
|
||||
|
||||
const title = result.title;
|
||||
const options = result.options.map((option) => ({
|
||||
text: option.text,
|
||||
option: serializeBytes(option.option),
|
||||
}));
|
||||
|
||||
return {
|
||||
type: 'selectOption',
|
||||
title,
|
||||
options,
|
||||
};
|
||||
}
|
||||
|
||||
@ -20,7 +20,6 @@ import type {
|
||||
ApiReplyInfo,
|
||||
ApiReplyKeyboard,
|
||||
ApiSponsoredMessage,
|
||||
ApiSponsoredWebPage,
|
||||
ApiSticker,
|
||||
ApiStory,
|
||||
ApiStorySkipped,
|
||||
@ -51,13 +50,12 @@ import {
|
||||
resolveMessageApiChatId,
|
||||
serializeBytes,
|
||||
} from '../helpers';
|
||||
import { buildApiBotApp } from './bots';
|
||||
import { buildApiCallDiscardReason } from './calls';
|
||||
import {
|
||||
buildApiPhoto,
|
||||
} from './common';
|
||||
import { buildMessageContent, buildMessageMediaContent, buildMessageTextContent } from './messageContent';
|
||||
import { buildApiPeerId, getApiChatIdFromMtpPeer, isPeerUser } from './peers';
|
||||
import { buildApiPeerColor, buildApiPeerId, getApiChatIdFromMtpPeer } from './peers';
|
||||
import { buildMessageReactions } from './reactions';
|
||||
|
||||
const LOCAL_MESSAGES_LIMIT = 1e6; // 1M
|
||||
@ -79,33 +77,28 @@ export function setMessageBuilderCurrentUserId(_currentUserId: string) {
|
||||
|
||||
export function buildApiSponsoredMessage(mtpMessage: GramJs.SponsoredMessage): ApiSponsoredMessage | undefined {
|
||||
const {
|
||||
fromId, message, entities, startParam, channelPost, chatInvite, chatInviteHash, randomId, recommended, sponsorInfo,
|
||||
additionalInfo, showPeerPhoto, webpage, buttonText, app,
|
||||
message, entities, randomId, recommended, sponsorInfo, additionalInfo, buttonText, canReport, title, url, color,
|
||||
} = mtpMessage;
|
||||
const chatId = fromId ? getApiChatIdFromMtpPeer(fromId) : undefined;
|
||||
const chatInviteTitle = chatInvite
|
||||
? (chatInvite instanceof GramJs.ChatInvite
|
||||
? chatInvite.title
|
||||
: !(chatInvite.chat instanceof GramJs.ChatEmpty) ? chatInvite.chat.title : undefined)
|
||||
: undefined;
|
||||
|
||||
let photo: ApiPhoto | undefined;
|
||||
if (mtpMessage.photo instanceof GramJs.Photo) {
|
||||
addPhotoToLocalDb(mtpMessage.photo);
|
||||
photo = buildApiPhoto(mtpMessage.photo);
|
||||
}
|
||||
|
||||
return {
|
||||
randomId: serializeBytes(randomId),
|
||||
isBot: fromId ? isPeerUser(fromId) : false,
|
||||
text: buildMessageTextContent(message, entities),
|
||||
expiresAt: Math.round(Date.now() / 1000) + SPONSORED_MESSAGE_CACHE_MS,
|
||||
isRecommended: Boolean(recommended),
|
||||
...(webpage && { webPage: buildSponsoredWebPage(webpage) }),
|
||||
...(showPeerPhoto && { isAvatarShown: true }),
|
||||
...(chatId && { chatId }),
|
||||
...(chatInviteHash && { chatInviteHash }),
|
||||
...(chatInvite && { chatInviteTitle }),
|
||||
...(startParam && { startParam }),
|
||||
...(channelPost && { channelPostId: channelPost }),
|
||||
...(sponsorInfo && { sponsorInfo }),
|
||||
...(additionalInfo && { additionalInfo }),
|
||||
...(buttonText && { buttonText }),
|
||||
...(app && { botApp: buildApiBotApp(app) }),
|
||||
isRecommended: recommended,
|
||||
sponsorInfo,
|
||||
additionalInfo,
|
||||
buttonText,
|
||||
canReport,
|
||||
title,
|
||||
url,
|
||||
peerColor: color && buildApiPeerColor(color),
|
||||
photo,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1094,19 +1087,3 @@ export function buildApiQuickReply(reply: GramJs.TypeQuickReply): ApiQuickReply
|
||||
topMessageId: topMessage,
|
||||
};
|
||||
}
|
||||
|
||||
function buildSponsoredWebPage(webPage: GramJs.TypeSponsoredWebPage): ApiSponsoredWebPage {
|
||||
let photo: ApiPhoto | undefined;
|
||||
if (webPage.photo instanceof GramJs.Photo) {
|
||||
addPhotoToLocalDb(webPage.photo);
|
||||
photo = buildApiPhoto(webPage.photo);
|
||||
}
|
||||
|
||||
return {
|
||||
...pick(webPage, [
|
||||
'url',
|
||||
'siteName',
|
||||
]),
|
||||
photo,
|
||||
};
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ export function buildApiUserFullInfo(mtpUserFull: GramJs.users.UserFull): ApiUse
|
||||
profilePhoto, voiceMessagesForbidden, premiumGifts,
|
||||
fallbackPhoto, personalPhoto, translationsDisabled, storiesPinnedAvailable,
|
||||
contactRequirePremium, businessWorkHours, businessLocation, businessIntro,
|
||||
birthday, personalChannelId, personalChannelMessage,
|
||||
birthday, personalChannelId, personalChannelMessage, sponsoredEnabled,
|
||||
},
|
||||
users,
|
||||
} = mtpUserFull;
|
||||
@ -49,6 +49,7 @@ export function buildApiUserFullInfo(mtpUserFull: GramJs.users.UserFull): ApiUse
|
||||
businessIntro: businessIntro && buildApiBusinessIntro(businessIntro),
|
||||
personalChannelId: personalChannelId && buildApiPeerId(personalChannelId, 'channel'),
|
||||
personalChannelMessageId: personalChannelMessage,
|
||||
areAdsEnabled: sponsoredEnabled,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -94,3 +94,15 @@ export async function resolveBusinessChatLink({ slug } : { slug: string }) {
|
||||
chatLink,
|
||||
};
|
||||
}
|
||||
|
||||
export function toggleSponsoredMessages({
|
||||
enabled,
|
||||
}: {
|
||||
enabled: boolean;
|
||||
}) {
|
||||
return invokeRequest(new GramJs.account.ToggleSponsoredMessages({
|
||||
enabled,
|
||||
}), {
|
||||
shouldReturnTrue: true,
|
||||
});
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ import {
|
||||
buildApiChatReactions,
|
||||
buildApiChatSettings,
|
||||
buildApiMissingInvitedUser,
|
||||
buildApiSponsoredMessageReportResult,
|
||||
buildApiTopic,
|
||||
buildChatMembers,
|
||||
getPeerKey,
|
||||
@ -70,6 +71,7 @@ import {
|
||||
addEntitiesToLocalDb,
|
||||
addMessageToLocalDb,
|
||||
addPhotoToLocalDb,
|
||||
deserializeBytes,
|
||||
isChatFolder,
|
||||
} from '../helpers';
|
||||
import localDb from '../localDb';
|
||||
@ -2017,3 +2019,39 @@ export async function fetchChannelRecommendations({ chat }: { chat: ApiChat }) {
|
||||
result instanceof GramJs.messages.ChatsSlice ? result.count : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export async function reportSponsoredMessage({
|
||||
chat,
|
||||
randomId,
|
||||
option,
|
||||
}: {
|
||||
chat: ApiChat;
|
||||
randomId: string;
|
||||
option: string;
|
||||
}) {
|
||||
const { id, accessHash } = chat;
|
||||
const channel = buildInputEntity(id, accessHash);
|
||||
|
||||
try {
|
||||
const result = await invokeRequest(new GramJs.channels.ReportSponsoredMessage({
|
||||
channel: channel as GramJs.InputChannel,
|
||||
randomId: deserializeBytes(randomId),
|
||||
option: deserializeBytes(option),
|
||||
}), {
|
||||
shouldThrow: true,
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return buildApiSponsoredMessageReportResult(result);
|
||||
} catch (err) {
|
||||
if (err instanceof Error && err.message === 'PREMIUM_ACCOUNT_REQUIRED') {
|
||||
return {
|
||||
type: 'premiumRequired' as const,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ export {
|
||||
editTopic, toggleForum, fetchTopicById, createTopic, toggleParticipantsHidden, checkChatlistInvite,
|
||||
joinChatlistInvite, createChalistInvite, editChatlistInvite, deleteChatlistInvite, fetchChatlistInvites,
|
||||
fetchLeaveChatlistSuggestions, leaveChatlist, togglePeerTranslations, setViewForumAsMessages,
|
||||
fetchChannelRecommendations, fetchSavedChats, toggleSavedDialogPinned,
|
||||
fetchChannelRecommendations, fetchSavedChats, toggleSavedDialogPinned, reportSponsoredMessage,
|
||||
} from './chats';
|
||||
|
||||
export {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { ThreadId } from '../../types';
|
||||
import type { ApiWebDocument } from './bots';
|
||||
import type { ApiGroupCall, PhoneCallAction } from './calls';
|
||||
import type { ApiChat } from './chats';
|
||||
import type { ApiChat, ApiPeerColor } from './chats';
|
||||
import type { ApiInputStorePaymentPurpose, ApiPremiumGiftCodeOption } from './payments';
|
||||
import type { ApiMessageStoryData, ApiWebPageStoryData } from './stories';
|
||||
|
||||
@ -382,12 +382,6 @@ export interface ApiWebPage {
|
||||
story?: ApiWebPageStoryData;
|
||||
}
|
||||
|
||||
export interface ApiSponsoredWebPage {
|
||||
url: string;
|
||||
siteName: string;
|
||||
photo?: ApiPhoto;
|
||||
}
|
||||
|
||||
export type ApiReplyInfo = ApiMessageReplyInfo | ApiStoryReplyInfo;
|
||||
|
||||
export interface ApiMessageReplyInfo {
|
||||
@ -685,22 +679,18 @@ export type ApiThreadInfo = ApiCommentsInfo | ApiMessageThreadInfo;
|
||||
export type ApiMessageOutgoingStatus = 'read' | 'succeeded' | 'pending' | 'failed';
|
||||
|
||||
export type ApiSponsoredMessage = {
|
||||
chatId?: string;
|
||||
randomId: string;
|
||||
isRecommended?: boolean;
|
||||
isAvatarShown?: boolean;
|
||||
isBot?: boolean;
|
||||
channelPostId?: number;
|
||||
startParam?: string;
|
||||
chatInviteHash?: string;
|
||||
chatInviteTitle?: string;
|
||||
isRecommended?: true;
|
||||
text: ApiFormattedText;
|
||||
webPage?: ApiSponsoredWebPage;
|
||||
expiresAt: number;
|
||||
sponsorInfo?: string;
|
||||
additionalInfo?: string;
|
||||
buttonText?: string;
|
||||
botApp?: ApiBotApp;
|
||||
canReport?: true;
|
||||
title: string;
|
||||
url: string;
|
||||
photo?: ApiPhoto;
|
||||
peerColor?: ApiPeerColor;
|
||||
};
|
||||
|
||||
// KeyboardButtons
|
||||
@ -841,6 +831,17 @@ export type ApiQuickReply = {
|
||||
topMessageId: number;
|
||||
};
|
||||
|
||||
export type ApiSponsoredMessageReportResult = {
|
||||
type: 'reported' | 'hidden' | 'premiumRequired';
|
||||
} | {
|
||||
type: 'selectOption';
|
||||
title: string;
|
||||
options: {
|
||||
text: string;
|
||||
option: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
export const MAIN_THREAD_ID = -1;
|
||||
|
||||
// `Symbol` can not be transferred from worker
|
||||
|
||||
@ -208,6 +208,7 @@ export interface ApiAppConfig {
|
||||
bandwidthPremiumNotifyPeriod?: number;
|
||||
bandwidthPremiumUploadSpeedup?: number;
|
||||
bandwidthPremiumDownloadSpeedup?: number;
|
||||
channelRestrictAdsLevelMin?: number;
|
||||
}
|
||||
|
||||
export interface ApiConfig {
|
||||
|
||||
@ -53,6 +53,7 @@ export interface ApiUserFullInfo {
|
||||
noVoiceMessages?: boolean;
|
||||
premiumGifts?: ApiPremiumGiftOption[];
|
||||
isTranslationDisabled?: true;
|
||||
areAdsEnabled?: boolean;
|
||||
hasPinnedStories?: boolean;
|
||||
isContactRequirePremium?: boolean;
|
||||
birthday?: ApiBirthday;
|
||||
|
||||
1
src/assets/font-icons/nochannel.svg
Normal file
1
src/assets/font-icons/nochannel.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><g clip-path="url(#clip0_427_83808)" transform="matrix(1.66667 0 0 1.66667 -5.667 -4)"><path fill="#000" d="M9.414 7h2.24l4.14-3.253C17.5 2.407 20 3.622 20 5.792v10.916c0 .272-.04.528-.111.767l1.818 1.818a1 1 0 0 1-1.414 1.414l-16-16a1 1 0 0 1 1.414-1.414zm2 2L18 15.586V5.792a.6.6 0 0 0-.97-.472l-4.383 3.443a1.107 1.107 0 0 1-.684.237zM4 11.25c0-1.573.855-2.947 2.125-3.682l1.516 1.515A2.251 2.251 0 0 0 8.25 13.5h3.713c.033 0 .066.002.099.004l5.77 5.77a2.554 2.554 0 0 1-2.038-.522L13 16.558V17a3 3 0 0 1-6 0v-1.687a4.252 4.252 0 0 1-3-4.063zm7 4.25H9V17a1 1 0 0 0 2 0Z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 660 B |
1
src/assets/font-icons/revenue-split.svg
Normal file
1
src/assets/font-icons/revenue-split.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path fill="#000" d="M20.313 5.268a1.67 1.67 0 0 1 2.06-1.158 12.455 12.455 0 0 1 2.72 1.13 1.675 1.675 0 0 1 .64 2.278 1.668 1.668 0 0 1-2.273.64 9.117 9.117 0 0 0-1.992-.826 1.674 1.674 0 0 1-1.155-2.064Zm7.223 4.059a1.668 1.668 0 0 1 2.274.64c.482.86.86 1.776 1.127 2.726a1.67 1.67 0 1 1-3.215.905 9.109 9.109 0 0 0-.825-1.993 1.675 1.675 0 0 1 .639-2.278zm2.246 7.987a1.674 1.674 0 0 1 1.155 2.064 12.482 12.482 0 0 1-1.127 2.726 1.668 1.668 0 0 1-2.273.641 1.675 1.675 0 0 1-.64-2.278 9.192 9.192 0 0 0 .825-1.996 1.67 1.67 0 0 1 2.06-1.157zm-4.05 7.238a1.675 1.675 0 0 1-.639 2.278c-.859.483-1.773.863-2.72 1.13a1.674 1.674 0 0 1-.903-3.222 9.065 9.065 0 0 0 1.988-.826 1.668 1.668 0 0 1 2.274.64z" style="stroke-width:1.67169"/><path fill="#000" d="M14.531 1.05C6.936 1.806 1 8.247 1 16.036c0 7.79 5.936 14.23 13.531 14.985 1.73.171 3.172-1.292 3.172-2.936V3.986c0-1.643-1.441-3.107-3.172-2.935zm-.172 3.475v23.02c-5.649-.826-10.015-5.6-10.015-11.51S8.71 5.351 14.359 4.525z" style="stroke-linecap:round;-inkscape-stroke:none"/><path fill="#000" d="M15.361 3.318a1.672 1.672 0 0 0-1.181.49L1.822 16.194a1.672 1.672 0 0 0 .002 2.364 1.672 1.672 0 0 0 2.365-.002L16.547 6.172a1.672 1.672 0 0 0-.004-2.365 1.672 1.672 0 0 0-1.182-.489zm1.849 8.186a1.672 1.672 0 0 0-2.362.004L4.1 22.278a1.672 1.672 0 0 0 .004 2.363 1.672 1.672 0 0 0 2.363-.002l10.748-10.77a1.672 1.672 0 0 0-.004-2.365zm-1.18 7.879a1.672 1.672 0 0 0-1.182.492L8.475 26.26a1.672 1.672 0 0 0 .004 2.365 1.672 1.672 0 0 0 2.363-.002l6.373-6.387a1.672 1.672 0 0 0-.004-2.363 1.672 1.672 0 0 0-1.182-.49z" style="stroke-linecap:round;-inkscape-stroke:none"/></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@ -27,6 +27,7 @@ export { default as GiftCodeModal } from '../components/modals/giftcode/GiftCode
|
||||
export { default as ChatlistModal } from '../components/modals/chatlist/ChatlistModal';
|
||||
|
||||
export { default as AboutAdsModal } from '../components/common/AboutAdsModal';
|
||||
export { default as ReportAdModal } from '../components/modals/reportAd/ReportAdModal';
|
||||
export { default as CalendarModal } from '../components/common/CalendarModal';
|
||||
export { default as DeleteMessageModal } from '../components/common/DeleteMessageModal';
|
||||
export { default as PinMessageModal } from '../components/common/PinMessageModal';
|
||||
|
||||
35
src/components/common/AboutAdsModal.module.scss
Normal file
35
src/components/common/AboutAdsModal.module.scss
Normal file
@ -0,0 +1,35 @@
|
||||
.title, .description {
|
||||
text-align: center !important;
|
||||
text-wrap: pretty;
|
||||
padding-inline: 1.5rem;
|
||||
}
|
||||
|
||||
.secondary {
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.separator {
|
||||
margin-block: 1rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.topIcon {
|
||||
--premium-gradient: linear-gradient(88.39deg, #6C93FF -2.56%, #976FFF 51.27%, #DF69D1 107.39%);
|
||||
display: grid;
|
||||
place-items: center;
|
||||
flex-shrink: 0;
|
||||
border-radius: 50%;
|
||||
background: var(--premium-gradient);
|
||||
|
||||
font-size: 4rem;
|
||||
color: white;
|
||||
width: 6rem;
|
||||
height: 6rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
@ -1,45 +1,120 @@
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import React, { memo } from '../../lib/teact/teact';
|
||||
import React, { memo, useMemo } from '../../lib/teact/teact';
|
||||
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
import renderText from './helpers/renderText';
|
||||
|
||||
import useDerivedState from '../../hooks/useDerivedState';
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useSelectorSignal from '../../hooks/useSelectorSignal';
|
||||
|
||||
import Button from '../ui/Button';
|
||||
import ListItem from '../ui/ListItem';
|
||||
import Modal from '../ui/Modal';
|
||||
import Separator from '../ui/Separator';
|
||||
import Icon from './Icon';
|
||||
import SafeLink from './SafeLink';
|
||||
|
||||
import styles from './AboutAdsModal.module.scss';
|
||||
|
||||
export type OwnProps = {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
isRevenueSharing?: boolean;
|
||||
onClose: NoneToVoidFunction;
|
||||
};
|
||||
|
||||
const AboutAdsModal: FC<OwnProps> = ({
|
||||
isOpen,
|
||||
isRevenueSharing,
|
||||
onClose,
|
||||
}) => {
|
||||
const lang = useLang();
|
||||
|
||||
const minLevelSignal = useSelectorSignal((global) => global.appConfig?.channelRestrictAdsLevelMin);
|
||||
const minLevelToRestrictAds = useDerivedState(minLevelSignal);
|
||||
|
||||
const regularAdContent = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<h3>{lang('SponsoredMessageInfoScreen.Title')}</h3>
|
||||
<p>{renderText(lang('SponsoredMessageInfoDescription1'), ['br'])}</p>
|
||||
<p>{renderText(lang('SponsoredMessageInfoDescription2'), ['br'])}</p>
|
||||
<p>{renderText(lang('SponsoredMessageInfoDescription3'), ['br'])}</p>
|
||||
<p>
|
||||
<SafeLink
|
||||
url={lang('SponsoredMessageAlertLearnMoreUrl')}
|
||||
text={lang('SponsoredMessageAlertLearnMoreUrl')}
|
||||
/>
|
||||
</p>
|
||||
<p>{renderText(lang('SponsoredMessageInfoDescription4'), ['br'])}</p>
|
||||
</>
|
||||
);
|
||||
}, [lang]);
|
||||
|
||||
const revenueSharingAdContent = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<div className={styles.topIcon}><Icon name="channel" /></div>
|
||||
<h3 className={styles.title}>{lang('AboutRevenueSharingAds')}</h3>
|
||||
<p className={buildClassName(styles.description, styles.secondary)}>
|
||||
{lang('RevenueSharingAdsAlertSubtitle')}
|
||||
</p>
|
||||
<ListItem
|
||||
isStatic
|
||||
multiline
|
||||
icon="lock"
|
||||
>
|
||||
<span className="title">{lang('RevenueSharingAdsInfo1Title')}</span>
|
||||
<span className="subtitle">
|
||||
{renderText(lang('RevenueSharingAdsInfo1Subtitle'), ['simple_markdown'])}
|
||||
</span>
|
||||
</ListItem>
|
||||
<ListItem
|
||||
isStatic
|
||||
multiline
|
||||
icon="revenue-split"
|
||||
>
|
||||
<span className="title">{lang('RevenueSharingAdsInfo2Title')}</span>
|
||||
<span className="subtitle">
|
||||
{renderText(lang('RevenueSharingAdsInfo2Subtitle'), ['simple_markdown'])}
|
||||
</span>
|
||||
</ListItem>
|
||||
<ListItem
|
||||
isStatic
|
||||
multiline
|
||||
icon="nochannel"
|
||||
>
|
||||
<span className="title">{lang('RevenueSharingAdsInfo3Title')}</span>
|
||||
<span className="subtitle">
|
||||
{renderText(lang('RevenueSharingAdsInfo3Subtitle', minLevelToRestrictAds), ['simple_markdown'])}
|
||||
</span>
|
||||
</ListItem>
|
||||
<Separator className={styles.separator} />
|
||||
<h3 className={styles.title}>{renderText(lang('RevenueSharingAdsInfo4Title'), ['simple_markdown'])}</h3>
|
||||
<p className={styles.description}>
|
||||
{renderText(lang('RevenueSharingAdsInfo4Subtitle2', ''), ['simple_markdown'])}
|
||||
<SafeLink
|
||||
url={lang('PromoteUrl')}
|
||||
text={lang('LearnMoreArrow')}
|
||||
/>
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
}, [lang, minLevelToRestrictAds]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
contentClassName={styles.content}
|
||||
onClose={onClose}
|
||||
hasCloseButton
|
||||
title={lang('SponsoredMessageInfo')}
|
||||
>
|
||||
<p>{renderText(lang('SponsoredMessageInfoDescription1'), ['br'])}</p>
|
||||
<p>{renderText(lang('SponsoredMessageInfoDescription2'), ['br'])}</p>
|
||||
<p>{renderText(lang('SponsoredMessageInfoDescription3'), ['br'])}</p>
|
||||
<p>
|
||||
<SafeLink
|
||||
url={lang('SponsoredMessageAlertLearnMoreUrl')}
|
||||
text={lang('SponsoredMessageAlertLearnMoreUrl')}
|
||||
/>
|
||||
</p>
|
||||
<p>{renderText(lang('SponsoredMessageInfoDescription4'), ['br'])}</p>
|
||||
<div className="dialog-buttons mt-2">
|
||||
<Button className="confirm-dialog-button" isText onClick={onClose}>{lang('Close')}</Button>
|
||||
</div>
|
||||
{isRevenueSharing ? revenueSharingAdContent : regularAdContent}
|
||||
<Button
|
||||
size="smaller"
|
||||
onClick={onClose}
|
||||
>
|
||||
{lang('RevenueSharingAdsUnderstood')}
|
||||
</Button>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
3
src/components/common/PeerColorWrapper.module.scss
Normal file
3
src/components/common/PeerColorWrapper.module.scss
Normal file
@ -0,0 +1,3 @@
|
||||
.root {
|
||||
position: relative;
|
||||
}
|
||||
@ -1,30 +1,44 @@
|
||||
import React, { memo } from '../../lib/teact/teact';
|
||||
|
||||
import type { ApiPeer } from '../../api/types';
|
||||
import type { ApiPeer, ApiPeerColor } from '../../api/types';
|
||||
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
import { getPeerColorClass } from './helpers/peerColor';
|
||||
import { getApiPeerColorClass, getPeerColorClass } from './helpers/peerColor';
|
||||
|
||||
import EmojiIconBackground from './embedded/EmojiIconBackground';
|
||||
|
||||
type OwnProps = {
|
||||
import styles from './PeerColorWrapper.module.scss';
|
||||
|
||||
interface OwnProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
peer?: ApiPeer;
|
||||
peerColor?: ApiPeerColor;
|
||||
noUserColors?: boolean;
|
||||
shoudReset?: boolean;
|
||||
className?: string;
|
||||
emojiIconClassName?: string;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
}
|
||||
|
||||
function PeerColorWrapper({
|
||||
peer, noUserColors, shoudReset, className, emojiIconClassName, children,
|
||||
peer, peerColor, noUserColors, shoudReset, className, emojiIconClassName, children, ...otherProps
|
||||
}: OwnProps) {
|
||||
const color = peerColor || peer?.color;
|
||||
|
||||
return (
|
||||
<div className={buildClassName(getPeerColorClass(peer, noUserColors, shoudReset), className)}>
|
||||
{peer?.color?.backgroundEmojiId && (
|
||||
<div
|
||||
className={buildClassName(
|
||||
styles.root,
|
||||
peer && getPeerColorClass(peer, noUserColors, shoudReset),
|
||||
peerColor && getApiPeerColorClass(peerColor),
|
||||
className,
|
||||
)}
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...otherProps}
|
||||
>
|
||||
{color?.backgroundEmojiId && (
|
||||
<EmojiIconBackground
|
||||
className={emojiIconClassName}
|
||||
emojiDocumentId={peer.color.backgroundEmojiId}
|
||||
emojiDocumentId={color.backgroundEmojiId}
|
||||
/>
|
||||
)}
|
||||
{children}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { ApiPeer } from '../../../api/types';
|
||||
import type { ApiPeer, ApiPeerColor } from '../../../api/types';
|
||||
|
||||
import { getPeerColorCount, getPeerColorKey } from '../../../global/helpers';
|
||||
|
||||
@ -9,3 +9,7 @@ export function getPeerColorClass(peer?: ApiPeer, noUserColors?: boolean, should
|
||||
}
|
||||
return noUserColors ? `peer-color-count-${getPeerColorCount(peer)}` : `peer-color-${getPeerColorKey(peer)}`;
|
||||
}
|
||||
|
||||
export function getApiPeerColorClass(color: ApiPeerColor) {
|
||||
return `peer-color-${color.color}`;
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ const BusinessHours = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (!isExpanded) return;
|
||||
const slide = document.querySelector<HTMLElement>(`.${ACTIVE_SLIDE_CLASS_NAME} .${styles.timetable}`);
|
||||
const slide = document.querySelector<HTMLElement>(`.${ACTIVE_SLIDE_CLASS_NAME} > .${styles.timetable}`);
|
||||
if (!slide) return;
|
||||
|
||||
const height = slide.offsetHeight;
|
||||
@ -124,7 +124,7 @@ const BusinessHours = ({
|
||||
}, [isExpanded]);
|
||||
|
||||
const handleAnimationStart = useLastCallback(() => {
|
||||
const slide = document.querySelector<HTMLElement>(`.${TO_SLIDE_CLASS_NAME} .${styles.timetable}`)!;
|
||||
const slide = document.querySelector<HTMLElement>(`.${TO_SLIDE_CLASS_NAME} > .${styles.timetable}`)!;
|
||||
|
||||
requestMeasure(() => {
|
||||
const height = slide.offsetHeight;
|
||||
|
||||
@ -52,6 +52,7 @@ import {
|
||||
selectScrollOffset,
|
||||
selectTabState,
|
||||
selectThreadInfo,
|
||||
selectUserFullInfo,
|
||||
} from '../../global/selectors';
|
||||
import animateScroll, { isAnimatingScroll, restartCurrentScrollAnimation } from '../../util/animateScroll';
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
@ -101,7 +102,6 @@ type OwnProps = {
|
||||
};
|
||||
|
||||
type StateProps = {
|
||||
isCurrentUserPremium?: boolean;
|
||||
isChatLoaded?: boolean;
|
||||
isChannelChat?: boolean;
|
||||
isGroupChat?: boolean;
|
||||
@ -127,6 +127,7 @@ type StateProps = {
|
||||
isEmptyThread?: boolean;
|
||||
isForum?: boolean;
|
||||
currentUserId: string;
|
||||
areAdsEnabled?: boolean;
|
||||
};
|
||||
|
||||
const MESSAGE_REACTIONS_POLLING_INTERVAL = 20 * 1000;
|
||||
@ -150,7 +151,6 @@ const MessageList: FC<OwnProps & StateProps> = ({
|
||||
hasTools,
|
||||
onScrollDownToggle,
|
||||
onNotchToggle,
|
||||
isCurrentUserPremium,
|
||||
isChatLoaded,
|
||||
isForum,
|
||||
isChannelChat,
|
||||
@ -184,6 +184,7 @@ const MessageList: FC<OwnProps & StateProps> = ({
|
||||
getForceNextPinnedInHeader,
|
||||
onPinnedIntersectionChange,
|
||||
isContactRequirePremium,
|
||||
areAdsEnabled,
|
||||
}) => {
|
||||
const {
|
||||
loadViewportMessages, setScrollOffset, loadSponsoredMessages, loadMessageReactions, copyMessagesByIds,
|
||||
@ -230,10 +231,10 @@ const MessageList: FC<OwnProps & StateProps> = ({
|
||||
}, [firstUnreadId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isCurrentUserPremium && isChannelChat && isSynced && isReady) {
|
||||
if (areAdsEnabled && isChannelChat && isSynced && isReady) {
|
||||
loadSponsoredMessages({ chatId });
|
||||
}
|
||||
}, [isCurrentUserPremium, chatId, isSynced, isReady, isChannelChat]);
|
||||
}, [chatId, isSynced, isReady, isChannelChat, areAdsEnabled]);
|
||||
|
||||
// Updated only once when messages are loaded (as we want the unread divider to keep its position)
|
||||
useSyncEffect(() => {
|
||||
@ -633,7 +634,7 @@ const MessageList: FC<OwnProps & StateProps> = ({
|
||||
/>
|
||||
) : hasMessages ? (
|
||||
<MessageListContent
|
||||
isCurrentUserPremium={isCurrentUserPremium}
|
||||
areAdsEnabled={areAdsEnabled}
|
||||
chatId={chatId}
|
||||
isComments={isComments}
|
||||
isChannelChat={isChannelChat}
|
||||
@ -705,8 +706,11 @@ export default memo(withGlobal<OwnProps>(
|
||||
const chatFullInfo = !isUserId(chatId) ? selectChatFullInfo(global, chatId) : undefined;
|
||||
const isEmptyThread = !selectThreadInfo(global, chatId, threadId)?.messagesCount;
|
||||
|
||||
const isCurrentUserPremium = selectIsCurrentUserPremium(global);
|
||||
const areAdsEnabled = !isCurrentUserPremium || selectUserFullInfo(global, currentUserId)?.areAdsEnabled;
|
||||
|
||||
return {
|
||||
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
||||
areAdsEnabled,
|
||||
isChatLoaded: true,
|
||||
isRestricted,
|
||||
restrictionReason,
|
||||
|
||||
@ -32,7 +32,7 @@ import SponsoredMessage from './message/SponsoredMessage';
|
||||
import MessageListBotInfo from './MessageListBotInfo';
|
||||
|
||||
interface OwnProps {
|
||||
isCurrentUserPremium?: boolean;
|
||||
areAdsEnabled?: boolean;
|
||||
chatId: string;
|
||||
threadId: ThreadId;
|
||||
messageIds: number[];
|
||||
@ -64,7 +64,7 @@ interface OwnProps {
|
||||
const UNREAD_DIVIDER_CLASS = 'unread-divider';
|
||||
|
||||
const MessageListContent: FC<OwnProps> = ({
|
||||
isCurrentUserPremium,
|
||||
areAdsEnabled,
|
||||
chatId,
|
||||
threadId,
|
||||
messageIds,
|
||||
@ -290,7 +290,7 @@ const MessageListContent: FC<OwnProps> = ({
|
||||
{withHistoryTriggers && <div ref={backwardsTriggerRef} key="backwards-trigger" className="backwards-trigger" />}
|
||||
{shouldRenderBotInfo && <MessageListBotInfo isInMessageList key={`bot_info_${chatId}`} chatId={chatId} />}
|
||||
{dateGroups.flat()}
|
||||
{!isCurrentUserPremium && isViewportNewest && (
|
||||
{areAdsEnabled && isViewportNewest && (
|
||||
<SponsoredMessage key={chatId} chatId={chatId} containerRef={containerRef} />
|
||||
)}
|
||||
{withHistoryTriggers && (
|
||||
|
||||
@ -674,47 +674,43 @@
|
||||
}
|
||||
}
|
||||
|
||||
.message-action-button {
|
||||
.message-action-buttons {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
color: white;
|
||||
background-color: var(--pattern-color);
|
||||
border-radius: 1rem;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
opacity: 0;
|
||||
transition: opacity 150ms, backdrop-filter 150ms, filter 150ms;
|
||||
transition: opacity 150ms;
|
||||
|
||||
@media (pointer: coarse) {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
background-color: var(--pattern-color) !important;
|
||||
backdrop-filter: brightness(115%);
|
||||
|
||||
@supports not (backdrop-filter: brightness(115%)) {
|
||||
filter: brightness(115%);
|
||||
}
|
||||
}
|
||||
.message-action-button {
|
||||
color: white;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&[data-is-document-group-hover] {
|
||||
.message-action-button {
|
||||
.message-action-buttons {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.message-action-button-shown {
|
||||
.message-action-buttons-shown {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.own .message-action-button {
|
||||
&.own .message-action-buttons {
|
||||
left: -3rem;
|
||||
}
|
||||
|
||||
&:not(.own) .message-action-button {
|
||||
&:not(.own) .message-action-buttons {
|
||||
right: -3rem;
|
||||
}
|
||||
|
||||
|
||||
@ -1389,7 +1389,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
/>
|
||||
{!isInDocumentGroup && (
|
||||
<div className="message-select-control">
|
||||
{isSelected && <i className="icon icon-select" />}
|
||||
{isSelected && <Icon name="select" />}
|
||||
</div>
|
||||
)}
|
||||
{isLastInDocumentGroup && (
|
||||
@ -1398,7 +1398,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
onClick={handleDocumentGroupSelectAll}
|
||||
>
|
||||
{isGroupSelected && (
|
||||
<i className="icon icon-select" />
|
||||
<Icon name="select" />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
@ -1419,33 +1419,38 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
)}
|
||||
{renderContent()}
|
||||
{!isInDocumentGroupNotLast && metaPosition === 'standalone' && !isStoryMention && renderReactionsAndMeta()}
|
||||
{canShowActionButton && canForward ? (
|
||||
<Button
|
||||
className={buildClassName(
|
||||
'message-action-button', isLoadingComments && 'message-action-button-shown',
|
||||
)}
|
||||
color="translucent-white"
|
||||
round
|
||||
size="tiny"
|
||||
ariaLabel={lang('lng_context_forward_msg')}
|
||||
onClick={isLastInDocumentGroup ? handleGroupForward : handleForward}
|
||||
{canShowActionButton && (
|
||||
<div className={buildClassName(
|
||||
'message-action-buttons',
|
||||
isLoadingComments && 'message-action-buttons-shown',
|
||||
)}
|
||||
>
|
||||
<i className="icon icon-share-filled" />
|
||||
</Button>
|
||||
) : canShowActionButton && canFocus ? (
|
||||
<Button
|
||||
className={buildClassName(
|
||||
'message-action-button', isLoadingComments && 'message-action-button-shown',
|
||||
{canForward && (
|
||||
<Button
|
||||
className="message-action-button"
|
||||
color="translucent-white"
|
||||
round
|
||||
size="tiny"
|
||||
ariaLabel={lang('lng_context_forward_msg')}
|
||||
onClick={isLastInDocumentGroup ? handleGroupForward : handleForward}
|
||||
>
|
||||
<Icon name="share-filled" />
|
||||
</Button>
|
||||
)}
|
||||
color="translucent-white"
|
||||
round
|
||||
size="tiny"
|
||||
ariaLabel="Focus message"
|
||||
onClick={isPinnedList ? handleFocus : handleFocusForwarded}
|
||||
>
|
||||
<i className="icon icon-arrow-right" />
|
||||
</Button>
|
||||
) : undefined}
|
||||
{canFocus && (
|
||||
<Button
|
||||
className="message-action-button"
|
||||
color="translucent-white"
|
||||
round
|
||||
size="tiny"
|
||||
ariaLabel="Focus message"
|
||||
onClick={isPinnedList ? handleFocus : handleFocusForwarded}
|
||||
>
|
||||
<Icon name="arrow-right" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{withCommentButton && (
|
||||
<CommentButton
|
||||
threadInfo={repliesThreadInfo}
|
||||
|
||||
@ -118,6 +118,7 @@ type OwnProps = {
|
||||
onAboutAds?: NoneToVoidFunction;
|
||||
onSponsoredHide?: NoneToVoidFunction;
|
||||
onSponsorInfo?: NoneToVoidFunction;
|
||||
onSponsoredReport?: NoneToVoidFunction;
|
||||
onTranslate?: NoneToVoidFunction;
|
||||
onShowOriginal?: NoneToVoidFunction;
|
||||
onSelectLanguage?: NoneToVoidFunction;
|
||||
@ -207,6 +208,7 @@ const MessageContextMenu: FC<OwnProps> = ({
|
||||
onAboutAds,
|
||||
onSponsoredHide,
|
||||
onSponsorInfo,
|
||||
onSponsoredReport,
|
||||
onReactionPickerOpen,
|
||||
onTranslate,
|
||||
onShowOriginal,
|
||||
@ -443,9 +445,21 @@ const MessageContextMenu: FC<OwnProps> = ({
|
||||
{isSponsoredMessage && message.sponsorInfo && (
|
||||
<MenuItem icon="channel" onClick={onSponsorInfo}>{lang('SponsoredMessageSponsor')}</MenuItem>
|
||||
)}
|
||||
{isSponsoredMessage && <MenuItem icon="help" onClick={onAboutAds}>{lang('SponsoredMessageInfo')}</MenuItem>}
|
||||
{isSponsoredMessage && (
|
||||
<MenuItem icon="info" onClick={onAboutAds}>
|
||||
{lang(message.canReport ? 'AboutRevenueSharingAds' : 'SponsoredMessageInfo')}
|
||||
</MenuItem>
|
||||
)}
|
||||
{isSponsoredMessage && message.canReport && (
|
||||
<MenuItem icon="hand-stop" onClick={onSponsoredReport}>
|
||||
{lang('ReportAd')}
|
||||
</MenuItem>
|
||||
)}
|
||||
{isSponsoredMessage && onSponsoredHide && (
|
||||
<MenuItem icon="stop" onClick={onSponsoredHide}>{lang('HideAd')}</MenuItem>
|
||||
<>
|
||||
<MenuSeparator />
|
||||
<MenuItem icon="close-circle" onClick={onSponsoredHide}>{lang('HideAd')}</MenuItem>
|
||||
</>
|
||||
)}
|
||||
{(canShowSeenBy || canShowReactionsCount) && !isSponsoredMessage && (
|
||||
<>
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
margin-top: -0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
z-index: calc(var(--z-sticky-date) + 1);
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
@ -36,26 +37,9 @@
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
&.with-avatar {
|
||||
padding-left: 2.5rem !important;
|
||||
|
||||
& > .Avatar {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 600px) {
|
||||
padding-left: 2.875rem !important;
|
||||
|
||||
.message-content {
|
||||
max-width: min(29rem, calc(100vw - 7.0625rem)) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.message-action-button {
|
||||
.message-action-buttons {
|
||||
bottom: auto !important;
|
||||
top: 0.5rem;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
@ -67,7 +51,7 @@
|
||||
}
|
||||
|
||||
.channel-avatar {
|
||||
--radius: 0.125rem;
|
||||
--radius: 0.25rem;
|
||||
|
||||
float: right;
|
||||
margin: 0 0 0.5rem 0.5rem;
|
||||
@ -86,7 +70,6 @@
|
||||
font-size: calc(var(--message-text-size, 1rem) - 0.125rem);
|
||||
background-color: var(--accent-background-color);
|
||||
border-radius: 0.375rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::before {
|
||||
@ -131,4 +114,19 @@
|
||||
.svg-appendix {
|
||||
transform: translate(0.01875rem, -0.00625rem);
|
||||
}
|
||||
|
||||
.ad-about {
|
||||
font-size: 0.6875rem;
|
||||
margin-inline-start: 0.25rem;
|
||||
border-radius: 1rem;
|
||||
padding-inline: 0.375rem;
|
||||
transition: 150ms filter ease-in;
|
||||
background: var(--accent-background-active-color);
|
||||
cursor: var(--custom-cursor, pointer);
|
||||
filter: opacity(0.8);
|
||||
|
||||
&:hover {
|
||||
filter: opacity(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,23 +1,16 @@
|
||||
import type { MouseEvent as ReactMouseEvent, RefObject } from 'react';
|
||||
import type { RefObject } from 'react';
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import React, { memo, useEffect, useRef } from '../../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
import type {
|
||||
ApiChat, ApiSponsoredMessage, ApiUser,
|
||||
} from '../../../api/types';
|
||||
import type { ApiSponsoredMessage } from '../../../api/types';
|
||||
|
||||
import { getChatTitle, getUserFullName } from '../../../global/helpers';
|
||||
import { selectChat, selectSponsoredMessage, selectUser } from '../../../global/selectors';
|
||||
import { selectSponsoredMessage } from '../../../global/selectors';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import { extractCurrentThemeParams } from '../../../util/themeStyle';
|
||||
import { IS_ANDROID, IS_TOUCH_ENV } from '../../../util/windowEnvironment';
|
||||
import { getPeerColorClass } from '../../common/helpers/peerColor';
|
||||
import renderText from '../../common/helpers/renderText';
|
||||
import { IS_ANDROID } from '../../../util/windowEnvironment';
|
||||
import { renderTextWithEntities } from '../../common/helpers/renderTextWithEntities';
|
||||
import { preventMessageInputBlur } from '../helpers/preventMessageInputBlur';
|
||||
|
||||
import useAppLayout from '../../../hooks/useAppLayout';
|
||||
import useContextMenuHandlers from '../../../hooks/useContextMenuHandlers';
|
||||
import useFlag from '../../../hooks/useFlag';
|
||||
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
|
||||
@ -26,6 +19,8 @@ import useLastCallback from '../../../hooks/useLastCallback';
|
||||
|
||||
import AboutAdsModal from '../../common/AboutAdsModal.async';
|
||||
import Avatar from '../../common/Avatar';
|
||||
import Icon from '../../common/Icon';
|
||||
import PeerColorWrapper from '../../common/PeerColorWrapper';
|
||||
import Button from '../../ui/Button';
|
||||
import MessageAppendix from './MessageAppendix';
|
||||
import SponsoredMessageContextMenuContainer from './SponsoredMessageContextMenuContainer.async';
|
||||
@ -39,31 +34,21 @@ type OwnProps = {
|
||||
|
||||
type StateProps = {
|
||||
message?: ApiSponsoredMessage;
|
||||
peer?: ApiChat;
|
||||
bot?: ApiUser;
|
||||
channel?: ApiChat;
|
||||
};
|
||||
|
||||
const INTERSECTION_DEBOUNCE_MS = 200;
|
||||
|
||||
const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
||||
chatId,
|
||||
peer,
|
||||
message,
|
||||
containerRef,
|
||||
bot,
|
||||
channel,
|
||||
}) => {
|
||||
const {
|
||||
viewSponsoredMessage,
|
||||
openChat,
|
||||
openChatByInvite,
|
||||
requestAppWebView,
|
||||
startBot,
|
||||
focusMessage,
|
||||
openUrl,
|
||||
openPremiumModal,
|
||||
hideSponsoredMessages,
|
||||
clickSponsoredMessage,
|
||||
reportSponsoredMessage,
|
||||
} = getActions();
|
||||
|
||||
const lang = useLang();
|
||||
@ -83,11 +68,8 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
||||
isContextMenuOpen, contextMenuPosition,
|
||||
handleBeforeContextMenu, handleContextMenu,
|
||||
handleContextMenuClose, handleContextMenuHide,
|
||||
} = useContextMenuHandlers(ref, IS_TOUCH_ENV, true, IS_ANDROID);
|
||||
} = useContextMenuHandlers(ref, undefined, true, IS_ANDROID);
|
||||
const [isAboutAdsModalOpen, openAboutAdsModal, closeAboutAdsModal] = useFlag(false);
|
||||
const { isMobile } = useAppLayout();
|
||||
const withAvatar = Boolean(message?.isAvatarShown && peer);
|
||||
const isBotApp = Boolean(message?.botApp);
|
||||
|
||||
useEffect(() => {
|
||||
return shouldObserve ? observeIntersection(contentRef.current!, (target) => {
|
||||
@ -102,146 +84,30 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
||||
handleBeforeContextMenu(e);
|
||||
};
|
||||
|
||||
const handleAvatarClick = useLastCallback(() => {
|
||||
if (!peer) {
|
||||
return;
|
||||
}
|
||||
|
||||
openChat({ id: peer.id });
|
||||
const handleReportSponsoredMessage = useLastCallback(() => {
|
||||
reportSponsoredMessage({ chatId, randomId: message!.randomId });
|
||||
});
|
||||
|
||||
const handleLinkClick = useLastCallback((e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||
e.preventDefault();
|
||||
|
||||
clickSponsoredMessage({ chatId });
|
||||
openUrl({ url: message!.webPage!.url, shouldSkipModal: true });
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
const handleCloseSponsoredMessage = useLastCallback(() => {
|
||||
openPremiumModal();
|
||||
const handleHideSponsoredMessage = useLastCallback(() => {
|
||||
hideSponsoredMessages();
|
||||
});
|
||||
|
||||
const handleClick = useLastCallback(() => {
|
||||
if (!message) return;
|
||||
|
||||
clickSponsoredMessage({ chatId });
|
||||
|
||||
if (isBotApp) {
|
||||
const { shortName } = message.botApp!;
|
||||
const theme = extractCurrentThemeParams();
|
||||
|
||||
requestAppWebView({
|
||||
botId: message.chatId!,
|
||||
appName: shortName,
|
||||
startApp: message.startParam,
|
||||
theme,
|
||||
});
|
||||
} else if (message.chatInviteHash) {
|
||||
openChatByInvite({ hash: message.chatInviteHash });
|
||||
} else if (message.channelPostId) {
|
||||
focusMessage({ chatId: message.chatId!, messageId: message.channelPostId });
|
||||
} else {
|
||||
openChat({ id: message.chatId });
|
||||
|
||||
if (message.startParam) {
|
||||
startBot({
|
||||
botId: message.chatId!,
|
||||
param: message.startParam,
|
||||
});
|
||||
}
|
||||
}
|
||||
openUrl({ url: message!.url, shouldSkipModal: true });
|
||||
});
|
||||
|
||||
if (!message) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function renderAvatar() {
|
||||
return (
|
||||
<Avatar
|
||||
size={isMobile ? 'small-mobile' : 'small'}
|
||||
peer={peer}
|
||||
onClick={peer ? handleAvatarClick : undefined}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function renderPhoto() {
|
||||
if (message?.botApp) {
|
||||
if (!message.botApp.photo) return undefined;
|
||||
|
||||
return (
|
||||
<Avatar
|
||||
size="large"
|
||||
peer={bot}
|
||||
photo={message.botApp.photo}
|
||||
className={buildClassName('channel-avatar', lang.isRtl && 'is-rtl')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (channel) {
|
||||
return (
|
||||
<Avatar
|
||||
size="large"
|
||||
peer={channel}
|
||||
className={buildClassName('channel-avatar', lang.isRtl && 'is-rtl')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function renderContent() {
|
||||
if (message?.webPage) {
|
||||
return (
|
||||
<>
|
||||
<div className="text-content with-meta" dir="auto" ref={contentRef}>
|
||||
<div className="message-title message-peer" dir="ltr">
|
||||
{renderText(message.webPage.siteName)}
|
||||
</div>
|
||||
<span className="text-content-inner" dir="auto">
|
||||
{renderTextWithEntities({
|
||||
text: message!.text.text,
|
||||
entities: message!.text.entities,
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className="SponsoredMessage__button"
|
||||
size="tiny"
|
||||
color="translucent"
|
||||
isRectangular
|
||||
onClick={handleLinkClick}
|
||||
>
|
||||
<i className="icon icon-arrow-right" aria-hidden />
|
||||
{lang('OpenLink')}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const buttonText = message?.buttonText ?? (
|
||||
isBotApp
|
||||
? lang('BotWebAppInstantViewOpen')
|
||||
: (message!.isBot
|
||||
? lang('Conversation.ViewBot')
|
||||
: lang(message!.channelPostId ? 'Conversation.ViewPost' : 'Conversation.ViewChannel')
|
||||
));
|
||||
const title = isBotApp
|
||||
? message!.botApp!.title
|
||||
: (bot
|
||||
? renderText(getUserFullName(bot) || '')
|
||||
: (channel ? renderText(message!.chatInviteTitle || getChatTitle(lang, channel) || '') : '')
|
||||
);
|
||||
|
||||
if (!message) return undefined;
|
||||
return (
|
||||
<>
|
||||
<div className="message-title message-peer" dir="auto">{title}</div>
|
||||
<div className="message-title message-peer" dir="auto">{message.title}</div>
|
||||
<div className="text-content with-meta" dir="auto" ref={contentRef}>
|
||||
<span className="text-content-inner" dir="auto">
|
||||
{renderTextWithEntities({
|
||||
@ -258,48 +124,64 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
||||
isRectangular
|
||||
onClick={handleClick}
|
||||
>
|
||||
{buttonText}
|
||||
{message.buttonText}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const contentClassName = buildClassName(
|
||||
'message-content has-shadow has-solid-background has-appendix',
|
||||
getPeerColorClass(bot || peer || channel),
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
key="sponsored-message"
|
||||
className={buildClassName('SponsoredMessage Message open', withAvatar && 'with-avatar')}
|
||||
className="SponsoredMessage Message open"
|
||||
>
|
||||
{withAvatar && renderAvatar()}
|
||||
<div
|
||||
className={contentClassName}
|
||||
className="message-content has-shadow has-solid-background has-appendix"
|
||||
dir="auto"
|
||||
onMouseDown={handleMouseDown}
|
||||
onContextMenu={handleContextMenu}
|
||||
>
|
||||
<div className="content-inner" dir="auto">
|
||||
{renderPhoto()}
|
||||
<PeerColorWrapper peerColor={message.peerColor} className="content-inner" dir="auto">
|
||||
{message.photo && (
|
||||
<Avatar
|
||||
size="large"
|
||||
photo={message.photo}
|
||||
className={buildClassName('channel-avatar', lang.isRtl && 'is-rtl')}
|
||||
/>
|
||||
)}
|
||||
<span className="message-title message-type">
|
||||
{message!.isRecommended ? lang('Message.RecommendedLabel') : lang('SponsoredMessage')}
|
||||
<span onClick={openAboutAdsModal} className="ad-about">{lang('SponsoredMessageAdWhatIsThis')}</span>
|
||||
</span>
|
||||
{renderContent()}
|
||||
</div>
|
||||
</PeerColorWrapper>
|
||||
<MessageAppendix />
|
||||
<Button
|
||||
className="message-action-button"
|
||||
color="translucent-white"
|
||||
round
|
||||
size="tiny"
|
||||
ariaLabel={lang('Close')}
|
||||
onClick={handleCloseSponsoredMessage}
|
||||
>
|
||||
<i className="icon icon-close" aria-hidden />
|
||||
</Button>
|
||||
<div className="message-action-buttons">
|
||||
<Button
|
||||
className="message-action-button"
|
||||
color="translucent-white"
|
||||
round
|
||||
size="tiny"
|
||||
ariaLabel={lang('Close')}
|
||||
onClick={handleHideSponsoredMessage}
|
||||
>
|
||||
<Icon name="close" />
|
||||
</Button>
|
||||
{message.canReport && (
|
||||
<Button
|
||||
className="message-action-button"
|
||||
color="translucent-white"
|
||||
round
|
||||
size="tiny"
|
||||
ariaLabel={lang('More')}
|
||||
onClick={handleContextMenu}
|
||||
onContextMenu={handleContextMenu}
|
||||
>
|
||||
<Icon name="more" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{contextMenuPosition && (
|
||||
<SponsoredMessageContextMenuContainer
|
||||
@ -307,12 +189,14 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
||||
anchor={contextMenuPosition}
|
||||
message={message!}
|
||||
onAboutAds={openAboutAdsModal}
|
||||
onReportAd={handleReportSponsoredMessage}
|
||||
onClose={handleContextMenuClose}
|
||||
onCloseAnimationEnd={handleContextMenuHide}
|
||||
/>
|
||||
)}
|
||||
<AboutAdsModal
|
||||
isOpen={isAboutAdsModalOpen}
|
||||
isRevenueSharing={message.canReport}
|
||||
onClose={closeAboutAdsModal}
|
||||
/>
|
||||
</div>
|
||||
@ -322,14 +206,9 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
||||
export default memo(withGlobal<OwnProps>(
|
||||
(global, { chatId }): StateProps => {
|
||||
const message = selectSponsoredMessage(global, chatId);
|
||||
const peer = message?.chatId ? selectChat(global, message?.chatId) : undefined;
|
||||
const { chatId: fromChatId, isBot } = message || {};
|
||||
|
||||
return {
|
||||
message,
|
||||
peer,
|
||||
bot: fromChatId && isBot ? selectUser(global, fromChatId) : undefined,
|
||||
channel: !isBot && fromChatId ? selectChat(global, fromChatId) : undefined,
|
||||
};
|
||||
},
|
||||
)(SponsoredMessage));
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import React, { memo } from '../../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
import { getActions } from '../../../global';
|
||||
|
||||
import type { ApiSponsoredMessage } from '../../../api/types';
|
||||
import type { IAnchorPosition } from '../../../types';
|
||||
|
||||
import { selectIsCurrentUserPremium, selectIsPremiumPurchaseBlocked } from '../../../global/selectors';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
|
||||
import useFlag from '../../../hooks/useFlag';
|
||||
@ -18,22 +17,19 @@ export type OwnProps = {
|
||||
isOpen: boolean;
|
||||
message: ApiSponsoredMessage;
|
||||
anchor: IAnchorPosition;
|
||||
onAboutAds: () => void;
|
||||
onClose: () => void;
|
||||
onCloseAnimationEnd: () => void;
|
||||
onAboutAds: NoneToVoidFunction;
|
||||
onReportAd: NoneToVoidFunction;
|
||||
onClose: NoneToVoidFunction;
|
||||
onCloseAnimationEnd: NoneToVoidFunction;
|
||||
};
|
||||
|
||||
type StateProps = {
|
||||
canBuyPremium?: boolean;
|
||||
};
|
||||
|
||||
const SponsoredMessageContextMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
const SponsoredMessageContextMenuContainer: FC<OwnProps> = ({
|
||||
message,
|
||||
anchor,
|
||||
onAboutAds,
|
||||
onReportAd,
|
||||
onClose,
|
||||
onCloseAnimationEnd,
|
||||
canBuyPremium,
|
||||
}) => {
|
||||
const { openPremiumModal, showDialog } = getActions();
|
||||
|
||||
@ -60,6 +56,11 @@ const SponsoredMessageContextMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
});
|
||||
|
||||
const handleReportSponsoredMessage = useLastCallback(() => {
|
||||
closeMenu();
|
||||
onReportAd();
|
||||
});
|
||||
|
||||
if (!anchor) {
|
||||
return undefined;
|
||||
}
|
||||
@ -73,17 +74,12 @@ const SponsoredMessageContextMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
onClose={closeMenu}
|
||||
onCloseAnimationEnd={closeMenu}
|
||||
onAboutAds={handleAboutAdsOpen}
|
||||
onSponsoredHide={canBuyPremium ? handleSponsoredHide : undefined}
|
||||
onSponsoredHide={handleSponsoredHide}
|
||||
onSponsorInfo={handleSponsorInfo}
|
||||
onSponsoredReport={handleReportSponsoredMessage}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(withGlobal<OwnProps>(
|
||||
(global): StateProps => {
|
||||
return {
|
||||
canBuyPremium: !selectIsCurrentUserPremium(global) && !selectIsPremiumPurchaseBlocked(global),
|
||||
};
|
||||
},
|
||||
)(SponsoredMessageContextMenuContainer));
|
||||
export default memo(SponsoredMessageContextMenuContainer);
|
||||
|
||||
@ -12,6 +12,7 @@ import ChatlistModal from './chatlist/ChatlistModal.async';
|
||||
import GiftCodeModal from './giftcode/GiftCodeModal.async';
|
||||
import InviteViaLinkModal from './inviteViaLink/InviteViaLinkModal.async';
|
||||
import OneTimeMediaModal from './oneTimeMedia/OneTimeMediaModal.async';
|
||||
import ReportAdModal from './reportAd/ReportAdModal.async';
|
||||
import UrlAuthModal from './urlAuth/UrlAuthModal.async';
|
||||
import WebAppModal from './webApp/WebAppModal.async';
|
||||
|
||||
@ -24,6 +25,7 @@ type ModalKey = keyof Pick<TabState,
|
||||
'oneTimeMediaModal' |
|
||||
'inviteViaLinkModal' |
|
||||
'requestedAttachBotInstall' |
|
||||
'reportAdModal' |
|
||||
'webApp'
|
||||
>;
|
||||
|
||||
@ -47,6 +49,7 @@ const MODALS: ModalRegistry = {
|
||||
oneTimeMediaModal: OneTimeMediaModal,
|
||||
inviteViaLinkModal: InviteViaLinkModal,
|
||||
requestedAttachBotInstall: AttachBotInstallModal,
|
||||
reportAdModal: ReportAdModal,
|
||||
webApp: WebAppModal,
|
||||
};
|
||||
const MODAL_KEYS = Object.keys(MODALS) as ModalKey[];
|
||||
|
||||
18
src/components/modals/reportAd/ReportAdModal.async.tsx
Normal file
18
src/components/modals/reportAd/ReportAdModal.async.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import React from '../../../lib/teact/teact';
|
||||
|
||||
import type { OwnProps } from './ReportAdModal';
|
||||
|
||||
import { Bundles } from '../../../util/moduleLoader';
|
||||
|
||||
import useModuleLoader from '../../../hooks/useModuleLoader';
|
||||
|
||||
const ReportAdModalAsync: FC<OwnProps> = (props) => {
|
||||
const { modal } = props;
|
||||
const ReportAdModal = useModuleLoader(Bundles.Extra, 'ReportAdModal', !modal);
|
||||
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
return ReportAdModal ? <ReportAdModal {...props} /> : undefined;
|
||||
};
|
||||
|
||||
export default ReportAdModalAsync;
|
||||
54
src/components/modals/reportAd/ReportAdModal.module.scss
Normal file
54
src/components/modals/reportAd/ReportAdModal.module.scss
Normal file
@ -0,0 +1,54 @@
|
||||
.slide { // Do not remove .slide, identifier used in JS
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.modalTitle {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.optionText {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.option {
|
||||
margin-bottom: 0.25rem !important;
|
||||
}
|
||||
|
||||
.optionButton {
|
||||
padding-block: 0 !important;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
color: var(--color-primary);
|
||||
padding-inline: 1rem;
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-top: 0.75rem;
|
||||
margin-bottom: 0;
|
||||
color: var(--color-text-secondary);
|
||||
padding-inline: 1rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.titleMultiline > .title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.transition {
|
||||
/* stylelint-disable-next-line plugin/no-low-performance-animation-properties */
|
||||
transition: height 0.25s ease-in-out;
|
||||
overflow: hidden;
|
||||
}
|
||||
157
src/components/modals/reportAd/ReportAdModal.tsx
Normal file
157
src/components/modals/reportAd/ReportAdModal.tsx
Normal file
@ -0,0 +1,157 @@
|
||||
import React, {
|
||||
memo, useEffect, useMemo, useRef,
|
||||
} from '../../../lib/teact/teact';
|
||||
import { getActions } from '../../../global';
|
||||
|
||||
import type { TabState } from '../../../global/types';
|
||||
|
||||
import { requestMeasure, requestMutation } from '../../../lib/fasterdom/fasterdom';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
|
||||
import Icon from '../../common/Icon';
|
||||
import SafeLink from '../../common/SafeLink';
|
||||
import Button from '../../ui/Button';
|
||||
import ListItem from '../../ui/ListItem';
|
||||
import Modal from '../../ui/Modal';
|
||||
import Transition, { ACTIVE_SLIDE_CLASS_NAME, TO_SLIDE_CLASS_NAME } from '../../ui/Transition';
|
||||
|
||||
import styles from './ReportAdModal.module.scss';
|
||||
|
||||
const ADDED_PADDING = 40;
|
||||
|
||||
export type OwnProps = {
|
||||
modal: TabState['reportAdModal'];
|
||||
};
|
||||
|
||||
const ReportAdModal = ({
|
||||
modal,
|
||||
}: OwnProps) => {
|
||||
const {
|
||||
reportSponsoredMessage, closeReportAdModal, openPreviousReportAdModal,
|
||||
} = getActions();
|
||||
const lang = useLang();
|
||||
const isOpen = Boolean(modal);
|
||||
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const transitionRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const handleOptionClick = useLastCallback((e, option: string) => {
|
||||
const { chatId, randomId } = modal!;
|
||||
reportSponsoredMessage({ chatId, randomId, option });
|
||||
});
|
||||
|
||||
const [renderingSection, renderingDepth] = useMemo(() => {
|
||||
if (!modal) return [undefined, 0];
|
||||
const sectionDepth = modal.sections.length - 1;
|
||||
return [modal.sections[sectionDepth], sectionDepth];
|
||||
}, [modal]);
|
||||
|
||||
const handleBackClick = useLastCallback(() => {
|
||||
if (!renderingDepth) {
|
||||
closeReportAdModal();
|
||||
return;
|
||||
}
|
||||
|
||||
openPreviousReportAdModal();
|
||||
});
|
||||
|
||||
const bottomText = useMemo(() => {
|
||||
if (!modal) return undefined;
|
||||
const template = lang('lng_report_sponsored_reported_learn');
|
||||
const parts = template.split('{link}');
|
||||
return [
|
||||
parts[0],
|
||||
<SafeLink text={lang('lng_report_sponsored_reported_link')} url={lang('ReportAd.Help_URL')} />,
|
||||
parts[1],
|
||||
];
|
||||
}, [lang, modal]);
|
||||
|
||||
const header = useMemo(() => {
|
||||
if (!modal) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const hasSubtitle = Boolean(renderingSection?.subtitle);
|
||||
|
||||
return (
|
||||
<div className="modal-header-condensed">
|
||||
<Button
|
||||
round
|
||||
color="translucent"
|
||||
size="smaller"
|
||||
ariaLabel={lang(renderingDepth ? 'Back' : 'Close')}
|
||||
onClick={handleBackClick}
|
||||
>
|
||||
<Icon name={renderingDepth ? 'arrow-left' : 'close'} />
|
||||
</Button>
|
||||
<div className={buildClassName('modal-title', styles.modalTitle, hasSubtitle && styles.titleMultiline)}>
|
||||
<h3 className={styles.title}>{lang('ReportAd')}</h3>
|
||||
{hasSubtitle && (
|
||||
<span className={styles.subtitle}>{renderingSection.subtitle}</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}, [lang, modal, renderingDepth, renderingSection?.subtitle]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!modal) return;
|
||||
const slide = document.querySelector<HTMLElement>(`.${ACTIVE_SLIDE_CLASS_NAME} > .${styles.slide}`);
|
||||
if (!slide) return;
|
||||
|
||||
const height = slide.scrollHeight;
|
||||
requestMutation(() => {
|
||||
transitionRef.current!.style.height = `${height + ADDED_PADDING}px`;
|
||||
});
|
||||
}, [modal]);
|
||||
|
||||
const handleAnimationStart = useLastCallback(() => {
|
||||
const slide = document.querySelector<HTMLElement>(`.${TO_SLIDE_CLASS_NAME} > .${styles.slide}`)!;
|
||||
|
||||
requestMeasure(() => {
|
||||
const height = slide.scrollHeight;
|
||||
requestMutation(() => {
|
||||
transitionRef.current!.style.height = `${height + ADDED_PADDING}px`;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
hasCloseButton
|
||||
header={header}
|
||||
onClose={closeReportAdModal}
|
||||
>
|
||||
<Transition
|
||||
name="slide"
|
||||
className={styles.transition}
|
||||
ref={transitionRef}
|
||||
activeKey={renderingDepth}
|
||||
onStart={handleAnimationStart}
|
||||
>
|
||||
<div className={styles.slide}>
|
||||
<h3 className={styles.sectionTitle}>{renderingSection?.title}</h3>
|
||||
{renderingSection?.options.map((option) => (
|
||||
<ListItem
|
||||
narrow
|
||||
secondaryIcon="next"
|
||||
className={styles.option}
|
||||
buttonClassName={styles.optionButton}
|
||||
clickArg={option.option}
|
||||
onClick={handleOptionClick}
|
||||
>
|
||||
<div className={styles.optionText}>{option.text}</div>
|
||||
</ListItem>
|
||||
))}
|
||||
</div>
|
||||
<p className={styles.description}>{bottomText}</p>
|
||||
</Transition>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(ReportAdModal);
|
||||
@ -7,7 +7,7 @@ import useLang from '../../hooks/useLang';
|
||||
import styles from './Separator.module.scss';
|
||||
|
||||
type OwnProps = {
|
||||
children: React.ReactNode;
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ export const MEDIA_PROGRESSIVE_CACHE_DISABLED = false;
|
||||
export const MEDIA_PROGRESSIVE_CACHE_NAME = 'tt-media-progressive';
|
||||
export const MEDIA_CACHE_MAX_BYTES = 512 * 1024; // 512 KB
|
||||
export const CUSTOM_BG_CACHE_NAME = 'tt-custom-bg';
|
||||
export const LANG_CACHE_NAME = 'tt-lang-packs-v34';
|
||||
export const LANG_CACHE_NAME = 'tt-lang-packs-v35';
|
||||
export const ASSET_CACHE_NAME = 'tt-assets';
|
||||
export const AUTODOWNLOAD_FILESIZE_MB_LIMITS = [1, 5, 10, 50, 100, 500];
|
||||
export const DATA_BROADCAST_CHANNEL_NAME = 'tt-global';
|
||||
|
||||
@ -67,6 +67,7 @@ import {
|
||||
addChatMessagesById,
|
||||
addChats,
|
||||
addUsers,
|
||||
deleteSponsoredMessage,
|
||||
removeOutlyingList,
|
||||
removeRequestedMessageTranslation,
|
||||
replaceSettings,
|
||||
@ -90,6 +91,7 @@ import {
|
||||
updateThreadUnreadFromForwardedMessage,
|
||||
updateTopic,
|
||||
updateUploadByMessageKey,
|
||||
updateUserFullInfo,
|
||||
updateUsers,
|
||||
} from '../../reducers';
|
||||
import { updateTabState } from '../../reducers/tabs';
|
||||
@ -1548,6 +1550,79 @@ addActionHandler('clickSponsoredMessage', (global, actions, payload): ActionRetu
|
||||
void callApi('clickSponsoredMessage', { chat, random: message.randomId });
|
||||
});
|
||||
|
||||
addActionHandler('reportSponsoredMessage', async (global, actions, payload): Promise<void> => {
|
||||
const {
|
||||
chatId, randomId, option = '', tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
const chat = selectChat(global, chatId);
|
||||
if (!chat) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await callApi('reportSponsoredMessage', { chat, randomId, option });
|
||||
|
||||
if (!result) return;
|
||||
|
||||
if (result.type === 'premiumRequired') {
|
||||
actions.openPremiumModal({ initialSection: 'no_ads', tabId });
|
||||
actions.closeReportAdModal({ tabId });
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.type === 'reported' || result.type === 'hidden') {
|
||||
actions.showNotification({
|
||||
message: translate(result.type === 'reported' ? 'AdReported' : 'AdHidden'),
|
||||
tabId,
|
||||
});
|
||||
actions.closeReportAdModal({ tabId });
|
||||
|
||||
global = getGlobal();
|
||||
global = deleteSponsoredMessage(global, chatId);
|
||||
setGlobal(global);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.type === 'selectOption') {
|
||||
global = getGlobal();
|
||||
const oldSections = selectTabState(global, tabId).reportAdModal?.sections;
|
||||
const selectedOption = oldSections?.[oldSections.length - 1]?.options.find((o) => o.option === option);
|
||||
const newSection = {
|
||||
title: result.title,
|
||||
options: result.options,
|
||||
subtitle: selectedOption?.text,
|
||||
};
|
||||
global = updateTabState(global, {
|
||||
reportAdModal: {
|
||||
chatId,
|
||||
randomId,
|
||||
sections: oldSections ? [...oldSections, newSection] : [newSection],
|
||||
},
|
||||
}, tabId);
|
||||
setGlobal(global);
|
||||
}
|
||||
});
|
||||
|
||||
addActionHandler('hideSponsoredMessages', async (global, actions, payload): Promise<void> => {
|
||||
const { tabId = getCurrentTabId() } = payload || {};
|
||||
const isCurrentUserPremium = selectIsCurrentUserPremium(global);
|
||||
if (!isCurrentUserPremium) {
|
||||
actions.openPremiumModal({ initialSection: 'no_ads', tabId });
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await callApi('toggleSponsoredMessages', { enabled: false });
|
||||
if (!result) return;
|
||||
global = getGlobal();
|
||||
global = updateUserFullInfo(global, global.currentUserId!, {
|
||||
areAdsEnabled: false,
|
||||
});
|
||||
setGlobal(global);
|
||||
actions.showNotification({
|
||||
message: translate('AdHidden'),
|
||||
tabId,
|
||||
});
|
||||
});
|
||||
|
||||
addActionHandler('fetchUnreadMentions', async (global, actions, payload): Promise<void> => {
|
||||
const { chatId, offsetId } = payload;
|
||||
await fetchUnreadMentions(global, chatId, offsetId);
|
||||
|
||||
@ -863,6 +863,33 @@ addActionHandler('closeOneTimeMediaModal', (global, actions, payload): ActionRet
|
||||
setGlobal(global);
|
||||
});
|
||||
|
||||
addActionHandler('closeReportAdModal', (global, actions, payload): ActionReturnType => {
|
||||
const { tabId = getCurrentTabId() } = payload || {};
|
||||
return updateTabState(global, {
|
||||
reportAdModal: undefined,
|
||||
}, tabId);
|
||||
});
|
||||
|
||||
addActionHandler('openPreviousReportAdModal', (global, actions, payload): ActionReturnType => {
|
||||
const { tabId = getCurrentTabId() } = payload || {};
|
||||
const reportAdModal = selectTabState(global, tabId).reportAdModal;
|
||||
if (!reportAdModal) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (reportAdModal.sections.length === 1) {
|
||||
actions.closeReportAdModal({ tabId });
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return updateTabState(global, {
|
||||
reportAdModal: {
|
||||
...reportAdModal,
|
||||
sections: reportAdModal.sections.slice(0, -1),
|
||||
},
|
||||
}, tabId);
|
||||
});
|
||||
|
||||
function copyTextForMessages(global: GlobalState, chatId: string, messageIds: number[]) {
|
||||
const { type: messageListType, threadId } = selectCurrentMessageList(global) || {};
|
||||
const lang = langProvider.translate;
|
||||
|
||||
@ -671,6 +671,23 @@ export function updateSponsoredMessage<T extends GlobalState>(
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteSponsoredMessage<T extends GlobalState>(
|
||||
global: T, chatId: string,
|
||||
): T {
|
||||
const byChatId = global.messages.sponsoredByChatId;
|
||||
if (!byChatId[chatId]) {
|
||||
return global;
|
||||
}
|
||||
|
||||
return {
|
||||
...global,
|
||||
messages: {
|
||||
...global.messages,
|
||||
sponsoredByChatId: omit(byChatId, [chatId]),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function updateFocusDirection<T extends GlobalState>(
|
||||
global: T, direction?: FocusDirection,
|
||||
...[tabId = getCurrentTabId()]: TabArgs<T>
|
||||
|
||||
@ -533,6 +533,19 @@ export type TabState = {
|
||||
openedStickerSetShortName?: string;
|
||||
openedCustomEmojiSetIds?: string[];
|
||||
|
||||
reportAdModal?: {
|
||||
chatId: string;
|
||||
randomId: string;
|
||||
sections: {
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
options: {
|
||||
text: string;
|
||||
option: string;
|
||||
}[];
|
||||
}[];
|
||||
};
|
||||
|
||||
activeDownloads: {
|
||||
byChatId: {
|
||||
[chatId: string]: {
|
||||
@ -1465,6 +1478,14 @@ export interface ActionPayloads {
|
||||
clickSponsoredMessage: {
|
||||
chatId: string;
|
||||
};
|
||||
reportSponsoredMessage: {
|
||||
chatId: string;
|
||||
randomId: string;
|
||||
option?: string;
|
||||
} & WithTabId;
|
||||
openPreviousReportAdModal: WithTabId | undefined;
|
||||
closeReportAdModal: WithTabId | undefined;
|
||||
hideSponsoredMessages: WithTabId | undefined;
|
||||
loadSendAs: {
|
||||
chatId: string;
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
const api = require('./api');
|
||||
|
||||
const LAYER = 177;
|
||||
const LAYER = 178;
|
||||
const tlobjects = {};
|
||||
|
||||
for (const tl of Object.values(api)) {
|
||||
|
||||
129
src/lib/gramjs/tl/api.d.ts
vendored
129
src/lib/gramjs/tl/api.d.ts
vendored
File diff suppressed because one or more lines are too long
@ -80,8 +80,8 @@ chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5
|
||||
chatForbidden#6592a1a7 id:long title:string = Chat;
|
||||
channel#aadfc8f flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int = Chat;
|
||||
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
|
||||
chatFull#c9d31138 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions = ChatFull;
|
||||
channelFull#44c054a7 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet = ChatFull;
|
||||
chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull;
|
||||
channelFull#bbab348d flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet = ChatFull;
|
||||
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
|
||||
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
|
||||
chatParticipantAdmin#a0933f5b user_id:long inviter_id:long date:int = ChatParticipant;
|
||||
@ -188,7 +188,7 @@ inputReportReasonGeoIrrelevant#dbd4feed = ReportReason;
|
||||
inputReportReasonFake#f5ddd6e7 = ReportReason;
|
||||
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
|
||||
inputReportReasonPersonalDetails#9ec7863d = ReportReason;
|
||||
userFull#cc997720 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:# 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 premium_gifts:flags.19?Vector<PremiumGiftOption> 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 = UserFull;
|
||||
userFull#cc997720 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 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 premium_gifts:flags.19?Vector<PremiumGiftOption> 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 = UserFull;
|
||||
contact#145ade0b user_id:long mutual:Bool = Contact;
|
||||
importedContact#c13e3c50 user_id:long client_id:long = ImportedContact;
|
||||
contactStatus#16d9703b user_id:long status:UserStatus = ContactStatus;
|
||||
@ -359,6 +359,7 @@ updateBotBusinessConnect#8ae5c97a connection:BotBusinessConnection qts:int = Upd
|
||||
updateBotNewBusinessMessage#9ddb347c flags:# connection_id:string message:Message reply_to_message:flags.0?Message qts:int = Update;
|
||||
updateBotEditBusinessMessage#7df587c flags:# connection_id:string message:Message reply_to_message:flags.0?Message qts:int = Update;
|
||||
updateBotDeleteBusinessMessage#a02a982e connection_id:string peer:Peer messages:Vector<int> qts:int = Update;
|
||||
updateNewStoryReaction#1824e40b story_id:int peer:Peer reaction:Reaction = Update;
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference;
|
||||
updates.difference#f49ca0 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> state:updates.State = updates.Difference;
|
||||
@ -927,7 +928,7 @@ inputWallPaperSlug#72091c80 slug:string = InputWallPaper;
|
||||
inputWallPaperNoFile#967a462e id:long = InputWallPaper;
|
||||
account.wallPapersNotModified#1c199183 = account.WallPapers;
|
||||
account.wallPapers#cdc3858c hash:long wallpapers:Vector<WallPaper> = account.WallPapers;
|
||||
codeSettings#ad253d78 flags:# allow_flashcall:flags.0?true current_number:flags.1?true allow_app_hash:flags.4?true allow_missed_call:flags.5?true allow_firebase:flags.7?true logout_tokens:flags.6?Vector<bytes> token:flags.8?string app_sandbox:flags.8?Bool = CodeSettings;
|
||||
codeSettings#ad253d78 flags:# allow_flashcall:flags.0?true current_number:flags.1?true allow_app_hash:flags.4?true allow_missed_call:flags.5?true allow_firebase:flags.7?true unknown_number:flags.9?true logout_tokens:flags.6?Vector<bytes> token:flags.8?string app_sandbox:flags.8?Bool = CodeSettings;
|
||||
wallPaperSettings#372efcd0 flags:# blur:flags.1?true motion:flags.2?true background_color:flags.0?int second_background_color:flags.4?int third_background_color:flags.5?int fourth_background_color:flags.6?int intensity:flags.3?int rotation:flags.4?int emoticon:flags.7?string = WallPaperSettings;
|
||||
autoDownloadSettings#baa57628 flags:# disabled:flags.0?true video_preload_large:flags.1?true audio_preload_next:flags.2?true phonecalls_less_data:flags.3?true stories_preload:flags.4?true photo_size_max:int video_size_max:long file_size_max:long video_upload_maxbitrate:int small_queue_active_operations_max:int large_queue_active_operations_max:int = AutoDownloadSettings;
|
||||
account.autoDownloadSettings#63cacf26 low:AutoDownloadSettings medium:AutoDownloadSettings high:AutoDownloadSettings = account.AutoDownloadSettings;
|
||||
@ -967,6 +968,7 @@ inputThemeSettings#8fde504f flags:# message_colors_animated:flags.2?true base_th
|
||||
themeSettings#fa58b6d4 flags:# message_colors_animated:flags.2?true base_theme:BaseTheme accent_color:int outbox_accent_color:flags.3?int message_colors:flags.0?Vector<int> wallpaper:flags.1?WallPaper = ThemeSettings;
|
||||
webPageAttributeTheme#54b56617 flags:# documents:flags.0?Vector<Document> settings:flags.1?ThemeSettings = WebPageAttribute;
|
||||
webPageAttributeStory#2e94c3e7 flags:# peer:Peer id:int story:flags.0?StoryItem = WebPageAttribute;
|
||||
webPageAttributeStickerSet#50cc03d3 flags:# emojis:flags.0?true text_color:flags.1?true stickers:Vector<Document> = WebPageAttribute;
|
||||
messages.votesList#4899484e flags:# count:int votes:Vector<MessagePeerVote> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = messages.VotesList;
|
||||
bankCardOpenUrl#f568028a url:string name:string = BankCardOpenUrl;
|
||||
payments.bankCardData#3e24e573 title:string open_urls:Vector<BankCardOpenUrl> = payments.BankCardData;
|
||||
@ -1041,7 +1043,7 @@ botCommandScopePeerUser#a1321f3 peer:InputPeer user_id:InputUser = BotCommandSco
|
||||
account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordResult;
|
||||
account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult;
|
||||
account.resetPasswordOk#e926d63e = account.ResetPasswordResult;
|
||||
sponsoredMessage#ed5383f7 flags:# recommended:flags.5?true show_peer_photo:flags.6?true can_report:flags.12?true random_id:bytes from_id:flags.3?Peer chat_invite:flags.4?ChatInvite chat_invite_hash:flags.4?string channel_post:flags.2?int start_param:flags.0?string webpage:flags.9?SponsoredWebPage app:flags.10?BotApp message:string entities:flags.1?Vector<MessageEntity> button_text:flags.11?string sponsor_info:flags.7?string additional_info:flags.8?string = SponsoredMessage;
|
||||
sponsoredMessage#bdedf566 flags:# recommended:flags.5?true can_report:flags.12?true random_id:bytes url:string title:string message:string entities:flags.1?Vector<MessageEntity> photo:flags.6?Photo color:flags.13?PeerColor button_text:string sponsor_info:flags.7?string additional_info:flags.8?string = SponsoredMessage;
|
||||
messages.sponsoredMessages#c9ee1d87 flags:# posts_between:flags.0?int messages:Vector<SponsoredMessage> chats:Vector<Chat> users:Vector<User> = messages.SponsoredMessages;
|
||||
messages.sponsoredMessagesEmpty#1839490f = messages.SponsoredMessages;
|
||||
searchResultsCalendarPeriod#c9b0539f date:int min_msg_id:int max_msg_id:int count:int = SearchResultsCalendarPeriod;
|
||||
@ -1165,14 +1167,13 @@ bots.botInfo#e8a775b0 name:string about:string description:string = bots.BotInfo
|
||||
messagePeerVote#b6cc2d5c peer:Peer option:bytes date:int = MessagePeerVote;
|
||||
messagePeerVoteInputOption#74cda504 peer:Peer date:int = MessagePeerVote;
|
||||
messagePeerVoteMultiple#4628f6e6 peer:Peer options:Vector<bytes> date:int = MessagePeerVote;
|
||||
sponsoredWebPage#3db8ec63 flags:# url:string site_name:string photo:flags.0?Photo = SponsoredWebPage;
|
||||
storyViews#8d595cd6 flags:# has_viewers:flags.1?true views_count:int forwards_count:flags.2?int reactions:flags.3?Vector<ReactionCount> reactions_count:flags.4?int recent_viewers:flags.0?Vector<long> = StoryViews;
|
||||
storyItemDeleted#51e6ee4f id:int = StoryItem;
|
||||
storyItemSkipped#ffadc913 flags:# close_friends:flags.8?true id:int date:int expire_date:int = StoryItem;
|
||||
storyItem#79b26a24 flags:# pinned:flags.5?true public:flags.7?true close_friends:flags.8?true min:flags.9?true noforwards:flags.10?true edited:flags.11?true contacts:flags.12?true selected_contacts:flags.13?true out:flags.16?true id:int date:int from_id:flags.18?Peer fwd_from:flags.17?StoryFwdHeader expire_date:int caption:flags.0?string entities:flags.1?Vector<MessageEntity> media:MessageMedia media_areas:flags.14?Vector<MediaArea> privacy:flags.2?Vector<PrivacyRule> views:flags.3?StoryViews sent_reaction:flags.15?Reaction = StoryItem;
|
||||
stories.allStoriesNotModified#1158fe3e flags:# state:string stealth_mode:StoriesStealthMode = stories.AllStories;
|
||||
stories.allStories#6efc5e81 flags:# has_more:flags.0?true count:int state:string peer_stories:Vector<PeerStories> chats:Vector<Chat> users:Vector<User> stealth_mode:StoriesStealthMode = stories.AllStories;
|
||||
stories.stories#5dd8c3c8 count:int stories:Vector<StoryItem> chats:Vector<Chat> users:Vector<User> = stories.Stories;
|
||||
stories.stories#63c3dd0a flags:# count:int stories:Vector<StoryItem> pinned_to_top:flags.0?Vector<int> chats:Vector<Chat> users:Vector<User> = stories.Stories;
|
||||
storyView#b0bdeac5 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true user_id:long date:int reaction:flags.2?Reaction = StoryView;
|
||||
storyViewPublicForward#9083670b flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true message:Message = StoryView;
|
||||
storyViewPublicRepost#bd74cf49 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true peer_id:Peer story:StoryItem = StoryView;
|
||||
@ -1284,6 +1285,9 @@ broadcastRevenueTransactionProceeds#557e2cc4 amount:long from_date:int to_date:i
|
||||
broadcastRevenueTransactionWithdrawal#5a590978 flags:# pending:flags.0?true failed:flags.2?true amount:long date:int provider:string transaction_date:flags.1?int transaction_url:flags.1?string = BroadcastRevenueTransaction;
|
||||
broadcastRevenueTransactionRefund#42d30d2e amount:long date:int provider:string = BroadcastRevenueTransaction;
|
||||
stats.broadcastRevenueTransactions#87158466 count:int transactions:Vector<BroadcastRevenueTransaction> = stats.BroadcastRevenueTransactions;
|
||||
reactionNotificationsFromContacts#bac3a61a = ReactionNotificationsFrom;
|
||||
reactionNotificationsFromAll#4b9e22a0 = ReactionNotificationsFrom;
|
||||
reactionsNotifySettings#56e34970 flags:# messages_notify_from:flags.0?ReactionNotificationsFrom stories_notify_from:flags.1?ReactionNotificationsFrom sound:NotificationSound show_previews:Bool = ReactionsNotifySettings;
|
||||
---functions---
|
||||
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;
|
||||
@ -1345,6 +1349,7 @@ account.getRecentEmojiStatuses#f578105 hash:long = account.EmojiStatuses;
|
||||
account.reorderUsernames#ef500eab order:Vector<string> = Bool;
|
||||
account.toggleUsername#58d6b376 username:string active:Bool = Bool;
|
||||
account.resolveBusinessChatLink#5492e5ee slug:string = account.ResolvedBusinessChatLinks;
|
||||
account.toggleSponsoredMessages#b9d9a38d enabled:Bool = Bool;
|
||||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
|
||||
contacts.getContacts#5dd69e12 hash:long = contacts.Contacts;
|
||||
@ -1395,7 +1400,7 @@ messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
|
||||
messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_param:string = Updates;
|
||||
messages.getMessagesViews#5784d3e1 peer:InputPeer id:Vector<int> increment:Bool = messages.MessageViews;
|
||||
messages.migrateChat#a2875319 chat_id:long = Updates;
|
||||
messages.searchGlobal#4bc6589a flags:# folder_id:flags.0?int q:string filter:MessagesFilter min_date:int max_date:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||
messages.searchGlobal#4bc6589a flags:# broadcasts_only:flags.1?true folder_id:flags.0?int q:string filter:MessagesFilter min_date:int max_date:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||
messages.getDocumentByHash#b1f2061f sha256:bytes size:long mime_type:string = Document;
|
||||
messages.getSavedGifs#5cf09635 hash:long = messages.SavedGifs;
|
||||
messages.saveGif#327a30cb id:InputDocument unsave:Bool = Bool;
|
||||
@ -1457,7 +1462,7 @@ messages.saveDefaultSendAs#ccfddf96 peer:InputPeer send_as:InputPeer = Bool;
|
||||
messages.sendReaction#d30d78d4 flags:# big:flags.1?true add_to_recent:flags.2?true peer:InputPeer msg_id:int reaction:flags.0?Vector<Reaction> = Updates;
|
||||
messages.getMessagesReactions#8bba90e6 peer:InputPeer id:Vector<int> = Updates;
|
||||
messages.getMessageReactionsList#461b3f48 flags:# peer:InputPeer id:int reaction:flags.0?Reaction offset:flags.1?string limit:int = messages.MessageReactionsList;
|
||||
messages.setChatAvailableReactions#feb16771 peer:InputPeer available_reactions:ChatReactions = Updates;
|
||||
messages.setChatAvailableReactions#5a150bd4 flags:# peer:InputPeer available_reactions:ChatReactions reactions_limit:flags.0?int = Updates;
|
||||
messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions;
|
||||
messages.setDefaultReaction#4f47a016 reaction:Reaction = Bool;
|
||||
messages.translateText#63183030 flags:# peer:flags.0?InputPeer id:flags.0?Vector<int> text:flags.1?Vector<TextWithEntities> to_lang:string = messages.TranslatedText;
|
||||
@ -1557,7 +1562,8 @@ channels.deleteTopicHistory#34435f2d channel:InputChannel top_msg_id:int = messa
|
||||
channels.toggleParticipantsHidden#6a6e7854 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.clickSponsoredMessage#18afbc93 channel:InputChannel random_id:bytes = Bool;
|
||||
channels.toggleViewForumAsMessages#9738bb15 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.getChannelRecommendations#83b70d97 channel:InputChannel = messages.Chats;
|
||||
channels.getChannelRecommendations#25a71742 flags:# channel:flags.0?InputChannel = messages.Chats;
|
||||
channels.reportSponsoredMessage#af8ff6b9 channel:InputChannel random_id:bytes option:bytes = channels.SponsoredMessageReportResult;
|
||||
bots.setBotInfo#10cf3123 flags:# bot:flags.2?InputUser lang_code:string name:flags.3?string about:flags.0?string description:flags.1?string = Bool;
|
||||
bots.canSendMessage#1359f4e6 bot:InputUser = Bool;
|
||||
bots.allowSendMessage#f132e3ef bot:InputUser = Updates;
|
||||
|
||||
@ -59,6 +59,7 @@
|
||||
"account.reorderUsernames",
|
||||
"account.toggleUsername",
|
||||
"account.resolveBusinessChatLink",
|
||||
"account.toggleSponsoredMessages",
|
||||
"users.getUsers",
|
||||
"users.getFullUser",
|
||||
"contacts.getContacts",
|
||||
@ -221,6 +222,7 @@
|
||||
"channels.viewSponsoredMessage",
|
||||
"channels.getSponsoredMessages",
|
||||
"channels.getChannelRecommendations",
|
||||
"channels.reportSponsoredMessage",
|
||||
"bots.canSendMessage",
|
||||
"bots.allowSendMessage",
|
||||
"bots.invokeWebViewCustomMethod",
|
||||
|
||||
@ -100,8 +100,8 @@ chatForbidden#6592a1a7 id:long title:string = Chat;
|
||||
channel#aadfc8f flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int = Chat;
|
||||
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
|
||||
|
||||
chatFull#c9d31138 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions = ChatFull;
|
||||
channelFull#44c054a7 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet = ChatFull;
|
||||
chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull;
|
||||
channelFull#bbab348d flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet = ChatFull;
|
||||
|
||||
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
|
||||
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
|
||||
@ -228,7 +228,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason;
|
||||
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
|
||||
inputReportReasonPersonalDetails#9ec7863d = ReportReason;
|
||||
|
||||
userFull#cc997720 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:# 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 premium_gifts:flags.19?Vector<PremiumGiftOption> 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 = UserFull;
|
||||
userFull#cc997720 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 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 premium_gifts:flags.19?Vector<PremiumGiftOption> 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 = UserFull;
|
||||
|
||||
contact#145ade0b user_id:long mutual:Bool = Contact;
|
||||
|
||||
@ -412,6 +412,7 @@ updateBotBusinessConnect#8ae5c97a connection:BotBusinessConnection qts:int = Upd
|
||||
updateBotNewBusinessMessage#9ddb347c flags:# connection_id:string message:Message reply_to_message:flags.0?Message qts:int = Update;
|
||||
updateBotEditBusinessMessage#7df587c flags:# connection_id:string message:Message reply_to_message:flags.0?Message qts:int = Update;
|
||||
updateBotDeleteBusinessMessage#a02a982e connection_id:string peer:Peer messages:Vector<int> qts:int = Update;
|
||||
updateNewStoryReaction#1824e40b story_id:int peer:Peer reaction:Reaction = Update;
|
||||
|
||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||
|
||||
@ -1171,7 +1172,7 @@ inputWallPaperNoFile#967a462e id:long = InputWallPaper;
|
||||
account.wallPapersNotModified#1c199183 = account.WallPapers;
|
||||
account.wallPapers#cdc3858c hash:long wallpapers:Vector<WallPaper> = account.WallPapers;
|
||||
|
||||
codeSettings#ad253d78 flags:# allow_flashcall:flags.0?true current_number:flags.1?true allow_app_hash:flags.4?true allow_missed_call:flags.5?true allow_firebase:flags.7?true logout_tokens:flags.6?Vector<bytes> token:flags.8?string app_sandbox:flags.8?Bool = CodeSettings;
|
||||
codeSettings#ad253d78 flags:# allow_flashcall:flags.0?true current_number:flags.1?true allow_app_hash:flags.4?true allow_missed_call:flags.5?true allow_firebase:flags.7?true unknown_number:flags.9?true logout_tokens:flags.6?Vector<bytes> token:flags.8?string app_sandbox:flags.8?Bool = CodeSettings;
|
||||
|
||||
wallPaperSettings#372efcd0 flags:# blur:flags.1?true motion:flags.2?true background_color:flags.0?int second_background_color:flags.4?int third_background_color:flags.5?int fourth_background_color:flags.6?int intensity:flags.3?int rotation:flags.4?int emoticon:flags.7?string = WallPaperSettings;
|
||||
|
||||
@ -1236,6 +1237,7 @@ themeSettings#fa58b6d4 flags:# message_colors_animated:flags.2?true base_theme:B
|
||||
|
||||
webPageAttributeTheme#54b56617 flags:# documents:flags.0?Vector<Document> settings:flags.1?ThemeSettings = WebPageAttribute;
|
||||
webPageAttributeStory#2e94c3e7 flags:# peer:Peer id:int story:flags.0?StoryItem = WebPageAttribute;
|
||||
webPageAttributeStickerSet#50cc03d3 flags:# emojis:flags.0?true text_color:flags.1?true stickers:Vector<Document> = WebPageAttribute;
|
||||
|
||||
messages.votesList#4899484e flags:# count:int votes:Vector<MessagePeerVote> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = messages.VotesList;
|
||||
|
||||
@ -1361,7 +1363,7 @@ account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordR
|
||||
account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult;
|
||||
account.resetPasswordOk#e926d63e = account.ResetPasswordResult;
|
||||
|
||||
sponsoredMessage#ed5383f7 flags:# recommended:flags.5?true show_peer_photo:flags.6?true can_report:flags.12?true random_id:bytes from_id:flags.3?Peer chat_invite:flags.4?ChatInvite chat_invite_hash:flags.4?string channel_post:flags.2?int start_param:flags.0?string webpage:flags.9?SponsoredWebPage app:flags.10?BotApp message:string entities:flags.1?Vector<MessageEntity> button_text:flags.11?string sponsor_info:flags.7?string additional_info:flags.8?string = SponsoredMessage;
|
||||
sponsoredMessage#bdedf566 flags:# recommended:flags.5?true can_report:flags.12?true random_id:bytes url:string title:string message:string entities:flags.1?Vector<MessageEntity> photo:flags.6?Photo color:flags.13?PeerColor button_text:string sponsor_info:flags.7?string additional_info:flags.8?string = SponsoredMessage;
|
||||
|
||||
messages.sponsoredMessages#c9ee1d87 flags:# posts_between:flags.0?int messages:Vector<SponsoredMessage> chats:Vector<Chat> users:Vector<User> = messages.SponsoredMessages;
|
||||
messages.sponsoredMessagesEmpty#1839490f = messages.SponsoredMessages;
|
||||
@ -1565,8 +1567,6 @@ messagePeerVote#b6cc2d5c peer:Peer option:bytes date:int = MessagePeerVote;
|
||||
messagePeerVoteInputOption#74cda504 peer:Peer date:int = MessagePeerVote;
|
||||
messagePeerVoteMultiple#4628f6e6 peer:Peer options:Vector<bytes> date:int = MessagePeerVote;
|
||||
|
||||
sponsoredWebPage#3db8ec63 flags:# url:string site_name:string photo:flags.0?Photo = SponsoredWebPage;
|
||||
|
||||
storyViews#8d595cd6 flags:# has_viewers:flags.1?true views_count:int forwards_count:flags.2?int reactions:flags.3?Vector<ReactionCount> reactions_count:flags.4?int recent_viewers:flags.0?Vector<long> = StoryViews;
|
||||
|
||||
storyItemDeleted#51e6ee4f id:int = StoryItem;
|
||||
@ -1576,7 +1576,7 @@ storyItem#79b26a24 flags:# pinned:flags.5?true public:flags.7?true close_friends
|
||||
stories.allStoriesNotModified#1158fe3e flags:# state:string stealth_mode:StoriesStealthMode = stories.AllStories;
|
||||
stories.allStories#6efc5e81 flags:# has_more:flags.0?true count:int state:string peer_stories:Vector<PeerStories> chats:Vector<Chat> users:Vector<User> stealth_mode:StoriesStealthMode = stories.AllStories;
|
||||
|
||||
stories.stories#5dd8c3c8 count:int stories:Vector<StoryItem> chats:Vector<Chat> users:Vector<User> = stories.Stories;
|
||||
stories.stories#63c3dd0a flags:# count:int stories:Vector<StoryItem> pinned_to_top:flags.0?Vector<int> chats:Vector<Chat> users:Vector<User> = stories.Stories;
|
||||
|
||||
storyView#b0bdeac5 flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true user_id:long date:int reaction:flags.2?Reaction = StoryView;
|
||||
storyViewPublicForward#9083670b flags:# blocked:flags.0?true blocked_my_stories_from:flags.1?true message:Message = StoryView;
|
||||
@ -1770,6 +1770,11 @@ broadcastRevenueTransactionRefund#42d30d2e amount:long date:int provider:string
|
||||
|
||||
stats.broadcastRevenueTransactions#87158466 count:int transactions:Vector<BroadcastRevenueTransaction> = stats.BroadcastRevenueTransactions;
|
||||
|
||||
reactionNotificationsFromContacts#bac3a61a = ReactionNotificationsFrom;
|
||||
reactionNotificationsFromAll#4b9e22a0 = ReactionNotificationsFrom;
|
||||
|
||||
reactionsNotifySettings#56e34970 flags:# messages_notify_from:flags.0?ReactionNotificationsFrom stories_notify_from:flags.1?ReactionNotificationsFrom sound:NotificationSound show_previews:Bool = ReactionsNotifySettings;
|
||||
|
||||
---functions---
|
||||
|
||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||
@ -1913,6 +1918,9 @@ account.deleteBusinessChatLink#60073674 slug:string = Bool;
|
||||
account.getBusinessChatLinks#6f70dde1 = account.BusinessChatLinks;
|
||||
account.resolveBusinessChatLink#5492e5ee slug:string = account.ResolvedBusinessChatLinks;
|
||||
account.updatePersonalChannel#d94305e0 channel:InputChannel = Bool;
|
||||
account.toggleSponsoredMessages#b9d9a38d enabled:Bool = Bool;
|
||||
account.getReactionsNotifySettings#6dd654c = ReactionsNotifySettings;
|
||||
account.setReactionsNotifySettings#316ce548 settings:ReactionsNotifySettings = ReactionsNotifySettings;
|
||||
|
||||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
|
||||
@ -1993,7 +2001,7 @@ messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_par
|
||||
messages.getMessagesViews#5784d3e1 peer:InputPeer id:Vector<int> increment:Bool = messages.MessageViews;
|
||||
messages.editChatAdmin#a85bd1c2 chat_id:long user_id:InputUser is_admin:Bool = Bool;
|
||||
messages.migrateChat#a2875319 chat_id:long = Updates;
|
||||
messages.searchGlobal#4bc6589a flags:# folder_id:flags.0?int q:string filter:MessagesFilter min_date:int max_date:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||
messages.searchGlobal#4bc6589a flags:# broadcasts_only:flags.1?true folder_id:flags.0?int q:string filter:MessagesFilter min_date:int max_date:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||
messages.reorderStickerSets#78337739 flags:# masks:flags.0?true emojis:flags.1?true order:Vector<long> = Bool;
|
||||
messages.getDocumentByHash#b1f2061f sha256:bytes size:long mime_type:string = Document;
|
||||
messages.getSavedGifs#5cf09635 hash:long = messages.SavedGifs;
|
||||
@ -2097,7 +2105,7 @@ messages.saveDefaultSendAs#ccfddf96 peer:InputPeer send_as:InputPeer = Bool;
|
||||
messages.sendReaction#d30d78d4 flags:# big:flags.1?true add_to_recent:flags.2?true peer:InputPeer msg_id:int reaction:flags.0?Vector<Reaction> = Updates;
|
||||
messages.getMessagesReactions#8bba90e6 peer:InputPeer id:Vector<int> = Updates;
|
||||
messages.getMessageReactionsList#461b3f48 flags:# peer:InputPeer id:int reaction:flags.0?Reaction offset:flags.1?string limit:int = messages.MessageReactionsList;
|
||||
messages.setChatAvailableReactions#feb16771 peer:InputPeer available_reactions:ChatReactions = Updates;
|
||||
messages.setChatAvailableReactions#5a150bd4 flags:# peer:InputPeer available_reactions:ChatReactions reactions_limit:flags.0?int = Updates;
|
||||
messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions;
|
||||
messages.setDefaultReaction#4f47a016 reaction:Reaction = Bool;
|
||||
messages.translateText#63183030 flags:# peer:flags.0?InputPeer id:flags.0?Vector<int> text:flags.1?Vector<TextWithEntities> to_lang:string = messages.TranslatedText;
|
||||
@ -2258,7 +2266,7 @@ channels.toggleParticipantsHidden#6a6e7854 channel:InputChannel enabled:Bool = U
|
||||
channels.clickSponsoredMessage#18afbc93 channel:InputChannel random_id:bytes = Bool;
|
||||
channels.updateColor#d8aa3671 flags:# for_profile:flags.1?true channel:InputChannel color:flags.2?int background_emoji_id:flags.0?long = Updates;
|
||||
channels.toggleViewForumAsMessages#9738bb15 channel:InputChannel enabled:Bool = Updates;
|
||||
channels.getChannelRecommendations#83b70d97 channel:InputChannel = messages.Chats;
|
||||
channels.getChannelRecommendations#25a71742 flags:# channel:flags.0?InputChannel = messages.Chats;
|
||||
channels.updateEmojiStatus#f0d3e6a8 channel:InputChannel emoji_status:EmojiStatus = Updates;
|
||||
channels.setBoostsToUnblockRestrictions#ad399cee channel:InputChannel boosts:int = Updates;
|
||||
channels.setEmojiStickers#3cd930b7 channel:InputChannel stickerset:InputStickerSet = Bool;
|
||||
@ -2398,6 +2406,7 @@ stories.getPeerMaxIDs#535983c3 id:Vector<InputPeer> = Vector<int>;
|
||||
stories.getChatsToSend#a56a8b60 = messages.Chats;
|
||||
stories.togglePeerStoriesHidden#bd0415c4 peer:InputPeer hidden:Bool = Bool;
|
||||
stories.getStoryReactionsList#b9b2881f flags:# forwards_first:flags.2?true peer:InputPeer id:int reaction:flags.0?Reaction offset:flags.1?string limit:int = stories.StoryReactionsList;
|
||||
stories.togglePinnedToTop#b297e9b peer:InputPeer id:Vector<int> = Bool;
|
||||
|
||||
premium.getBoostsList#60f67660 flags:# gifts:flags.0?true peer:InputPeer offset:string limit:int = premium.BoostsList;
|
||||
premium.getMyBoosts#be77b4a = premium.MyBoosts;
|
||||
|
||||
@ -158,110 +158,112 @@ $icons-map: (
|
||||
"my-notes": "\f17f",
|
||||
"new-chat-filled": "\f180",
|
||||
"next": "\f181",
|
||||
"noise-suppression": "\f182",
|
||||
"non-contacts": "\f183",
|
||||
"one-filled": "\f184",
|
||||
"open-in-new-tab": "\f185",
|
||||
"password-off": "\f186",
|
||||
"pause": "\f187",
|
||||
"permissions": "\f188",
|
||||
"phone-discard-outline": "\f189",
|
||||
"phone-discard": "\f18a",
|
||||
"phone": "\f18b",
|
||||
"photo": "\f18c",
|
||||
"pin-badge": "\f18d",
|
||||
"pin-list": "\f18e",
|
||||
"pin": "\f18f",
|
||||
"pinned-chat": "\f190",
|
||||
"pinned-message": "\f191",
|
||||
"pip": "\f192",
|
||||
"play-story": "\f193",
|
||||
"play": "\f194",
|
||||
"poll": "\f195",
|
||||
"premium": "\f196",
|
||||
"previous": "\f197",
|
||||
"privacy-policy": "\f198",
|
||||
"quote-text": "\f199",
|
||||
"quote": "\f19a",
|
||||
"readchats": "\f19b",
|
||||
"recent": "\f19c",
|
||||
"reload": "\f19d",
|
||||
"remove": "\f19e",
|
||||
"reopen-topic": "\f19f",
|
||||
"replace": "\f1a0",
|
||||
"replies": "\f1a1",
|
||||
"reply-filled": "\f1a2",
|
||||
"reply": "\f1a3",
|
||||
"revote": "\f1a4",
|
||||
"save-story": "\f1a5",
|
||||
"saved-messages": "\f1a6",
|
||||
"schedule": "\f1a7",
|
||||
"search": "\f1a8",
|
||||
"select": "\f1a9",
|
||||
"send-outline": "\f1aa",
|
||||
"send": "\f1ab",
|
||||
"settings-filled": "\f1ac",
|
||||
"settings": "\f1ad",
|
||||
"share-filled": "\f1ae",
|
||||
"share-screen-outlined": "\f1af",
|
||||
"share-screen-stop": "\f1b0",
|
||||
"share-screen": "\f1b1",
|
||||
"sidebar": "\f1b2",
|
||||
"skip-next": "\f1b3",
|
||||
"skip-previous": "\f1b4",
|
||||
"smallscreen": "\f1b5",
|
||||
"smile": "\f1b6",
|
||||
"sort": "\f1b7",
|
||||
"speaker-muted-story": "\f1b8",
|
||||
"speaker-outline": "\f1b9",
|
||||
"speaker-story": "\f1ba",
|
||||
"speaker": "\f1bb",
|
||||
"spoiler-disable": "\f1bc",
|
||||
"spoiler": "\f1bd",
|
||||
"sport": "\f1be",
|
||||
"stats": "\f1bf",
|
||||
"stealth-future": "\f1c0",
|
||||
"stealth-past": "\f1c1",
|
||||
"stickers": "\f1c2",
|
||||
"stop-raising-hand": "\f1c3",
|
||||
"stop": "\f1c4",
|
||||
"story-caption": "\f1c5",
|
||||
"story-expired": "\f1c6",
|
||||
"story-priority": "\f1c7",
|
||||
"story-reply": "\f1c8",
|
||||
"strikethrough": "\f1c9",
|
||||
"tag-add": "\f1ca",
|
||||
"tag-crossed": "\f1cb",
|
||||
"tag-filter": "\f1cc",
|
||||
"tag-name": "\f1cd",
|
||||
"tag": "\f1ce",
|
||||
"timer": "\f1cf",
|
||||
"transcribe": "\f1d0",
|
||||
"truck": "\f1d1",
|
||||
"unarchive": "\f1d2",
|
||||
"underlined": "\f1d3",
|
||||
"unlock-badge": "\f1d4",
|
||||
"unlock": "\f1d5",
|
||||
"unmute": "\f1d6",
|
||||
"unpin": "\f1d7",
|
||||
"unread": "\f1d8",
|
||||
"up": "\f1d9",
|
||||
"user-filled": "\f1da",
|
||||
"user-online": "\f1db",
|
||||
"user": "\f1dc",
|
||||
"video-outlined": "\f1dd",
|
||||
"video-stop": "\f1de",
|
||||
"video": "\f1df",
|
||||
"view-once": "\f1e0",
|
||||
"voice-chat": "\f1e1",
|
||||
"volume-1": "\f1e2",
|
||||
"volume-2": "\f1e3",
|
||||
"volume-3": "\f1e4",
|
||||
"web": "\f1e5",
|
||||
"webapp": "\f1e6",
|
||||
"word-wrap": "\f1e7",
|
||||
"zoom-in": "\f1e8",
|
||||
"zoom-out": "\f1e9",
|
||||
"nochannel": "\f182",
|
||||
"noise-suppression": "\f183",
|
||||
"non-contacts": "\f184",
|
||||
"one-filled": "\f185",
|
||||
"open-in-new-tab": "\f186",
|
||||
"password-off": "\f187",
|
||||
"pause": "\f188",
|
||||
"permissions": "\f189",
|
||||
"phone-discard-outline": "\f18a",
|
||||
"phone-discard": "\f18b",
|
||||
"phone": "\f18c",
|
||||
"photo": "\f18d",
|
||||
"pin-badge": "\f18e",
|
||||
"pin-list": "\f18f",
|
||||
"pin": "\f190",
|
||||
"pinned-chat": "\f191",
|
||||
"pinned-message": "\f192",
|
||||
"pip": "\f193",
|
||||
"play-story": "\f194",
|
||||
"play": "\f195",
|
||||
"poll": "\f196",
|
||||
"premium": "\f197",
|
||||
"previous": "\f198",
|
||||
"privacy-policy": "\f199",
|
||||
"quote-text": "\f19a",
|
||||
"quote": "\f19b",
|
||||
"readchats": "\f19c",
|
||||
"recent": "\f19d",
|
||||
"reload": "\f19e",
|
||||
"remove": "\f19f",
|
||||
"reopen-topic": "\f1a0",
|
||||
"replace": "\f1a1",
|
||||
"replies": "\f1a2",
|
||||
"reply-filled": "\f1a3",
|
||||
"reply": "\f1a4",
|
||||
"revenue-split": "\f1a5",
|
||||
"revote": "\f1a6",
|
||||
"save-story": "\f1a7",
|
||||
"saved-messages": "\f1a8",
|
||||
"schedule": "\f1a9",
|
||||
"search": "\f1aa",
|
||||
"select": "\f1ab",
|
||||
"send-outline": "\f1ac",
|
||||
"send": "\f1ad",
|
||||
"settings-filled": "\f1ae",
|
||||
"settings": "\f1af",
|
||||
"share-filled": "\f1b0",
|
||||
"share-screen-outlined": "\f1b1",
|
||||
"share-screen-stop": "\f1b2",
|
||||
"share-screen": "\f1b3",
|
||||
"sidebar": "\f1b4",
|
||||
"skip-next": "\f1b5",
|
||||
"skip-previous": "\f1b6",
|
||||
"smallscreen": "\f1b7",
|
||||
"smile": "\f1b8",
|
||||
"sort": "\f1b9",
|
||||
"speaker-muted-story": "\f1ba",
|
||||
"speaker-outline": "\f1bb",
|
||||
"speaker-story": "\f1bc",
|
||||
"speaker": "\f1bd",
|
||||
"spoiler-disable": "\f1be",
|
||||
"spoiler": "\f1bf",
|
||||
"sport": "\f1c0",
|
||||
"stats": "\f1c1",
|
||||
"stealth-future": "\f1c2",
|
||||
"stealth-past": "\f1c3",
|
||||
"stickers": "\f1c4",
|
||||
"stop-raising-hand": "\f1c5",
|
||||
"stop": "\f1c6",
|
||||
"story-caption": "\f1c7",
|
||||
"story-expired": "\f1c8",
|
||||
"story-priority": "\f1c9",
|
||||
"story-reply": "\f1ca",
|
||||
"strikethrough": "\f1cb",
|
||||
"tag-add": "\f1cc",
|
||||
"tag-crossed": "\f1cd",
|
||||
"tag-filter": "\f1ce",
|
||||
"tag-name": "\f1cf",
|
||||
"tag": "\f1d0",
|
||||
"timer": "\f1d1",
|
||||
"transcribe": "\f1d2",
|
||||
"truck": "\f1d3",
|
||||
"unarchive": "\f1d4",
|
||||
"underlined": "\f1d5",
|
||||
"unlock-badge": "\f1d6",
|
||||
"unlock": "\f1d7",
|
||||
"unmute": "\f1d8",
|
||||
"unpin": "\f1d9",
|
||||
"unread": "\f1da",
|
||||
"up": "\f1db",
|
||||
"user-filled": "\f1dc",
|
||||
"user-online": "\f1dd",
|
||||
"user": "\f1de",
|
||||
"video-outlined": "\f1df",
|
||||
"video-stop": "\f1e0",
|
||||
"video": "\f1e1",
|
||||
"view-once": "\f1e2",
|
||||
"voice-chat": "\f1e3",
|
||||
"volume-1": "\f1e4",
|
||||
"volume-2": "\f1e5",
|
||||
"volume-3": "\f1e6",
|
||||
"web": "\f1e7",
|
||||
"webapp": "\f1e8",
|
||||
"word-wrap": "\f1e9",
|
||||
"zoom-in": "\f1ea",
|
||||
"zoom-out": "\f1eb",
|
||||
);
|
||||
|
||||
.icon-active-sessions::before {
|
||||
@ -651,6 +653,9 @@ $icons-map: (
|
||||
.icon-next::before {
|
||||
content: map.get($icons-map, "next");
|
||||
}
|
||||
.icon-nochannel::before {
|
||||
content: map.get($icons-map, "nochannel");
|
||||
}
|
||||
.icon-noise-suppression::before {
|
||||
content: map.get($icons-map, "noise-suppression");
|
||||
}
|
||||
@ -753,6 +758,9 @@ $icons-map: (
|
||||
.icon-reply::before {
|
||||
content: map.get($icons-map, "reply");
|
||||
}
|
||||
.icon-revenue-split::before {
|
||||
content: map.get($icons-map, "revenue-split");
|
||||
}
|
||||
.icon-revote::before {
|
||||
content: map.get($icons-map, "revote");
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -128,6 +128,7 @@ export type FontIconName =
|
||||
| 'my-notes'
|
||||
| 'new-chat-filled'
|
||||
| 'next'
|
||||
| 'nochannel'
|
||||
| 'noise-suppression'
|
||||
| 'non-contacts'
|
||||
| 'one-filled'
|
||||
@ -162,6 +163,7 @@ export type FontIconName =
|
||||
| 'replies'
|
||||
| 'reply-filled'
|
||||
| 'reply'
|
||||
| 'revenue-split'
|
||||
| 'revote'
|
||||
| 'save-story'
|
||||
| 'saved-messages'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user