Global Search: Show sponsored results (#5844)
Co-authored-by: Dmitry Kabanov <dmitrykabanovdev@gmail.com> Co-authored-by: Dmitry Kabanov <153344039+dmitrykabanovdev@users.noreply.github.com>
This commit is contained in:
parent
3087fb85cc
commit
97bd26df00
@ -18,6 +18,7 @@ import type {
|
||||
ApiRestrictionReason,
|
||||
ApiSendAsPeerId,
|
||||
ApiSponsoredMessageReportResult,
|
||||
ApiSponsoredPeer,
|
||||
ApiStarsSubscriptionPricing,
|
||||
ApiTopic,
|
||||
} from '../../types';
|
||||
@ -711,3 +712,16 @@ export function buildApiStarsSubscriptionPricing(
|
||||
amount: pricing.amount.toJSNumber(),
|
||||
};
|
||||
}
|
||||
|
||||
export function buildApiSponsoredPeer(sponsoredPeer: GramJs.SponsoredPeer): ApiSponsoredPeer {
|
||||
const {
|
||||
peer, randomId, additionalInfo, sponsorInfo,
|
||||
} = sponsoredPeer;
|
||||
|
||||
return {
|
||||
peerId: getApiChatIdFromMtpPeer(peer),
|
||||
randomId: serializeBytes(randomId),
|
||||
additionalInfo,
|
||||
sponsorInfo,
|
||||
};
|
||||
}
|
||||
|
||||
@ -45,6 +45,7 @@ import {
|
||||
buildApiChatlistInvite,
|
||||
buildApiChatReactions,
|
||||
buildApiMissingInvitedUser,
|
||||
buildApiSponsoredPeer,
|
||||
buildApiTopic,
|
||||
buildChatMember,
|
||||
buildChatMembers,
|
||||
@ -2020,3 +2021,9 @@ export async function fetchChannelRecommendations({ chat }: { chat?: ApiChat })
|
||||
count: result instanceof GramJs.messages.ChatsSlice ? result.count : similarChannels.length,
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchSponsoredPeer({ query }: { query: string }) {
|
||||
const result = await invokeRequest(new GramJs.contacts.GetSponsoredPeers({ q: query }));
|
||||
if (!result || result instanceof GramJs.contacts.SponsoredPeersEmpty) return undefined;
|
||||
return buildApiSponsoredPeer(result.peers[0]);
|
||||
}
|
||||
|
||||
@ -313,3 +313,10 @@ export type ApiDraft = {
|
||||
effectId?: string;
|
||||
isLocal?: boolean;
|
||||
};
|
||||
|
||||
export type ApiSponsoredPeer = {
|
||||
randomId: string;
|
||||
peerId: string;
|
||||
sponsorInfo?: string;
|
||||
additionalInfo?: string;
|
||||
};
|
||||
|
||||
@ -782,6 +782,7 @@
|
||||
"MessageRecommendedLabel" = "recommended";
|
||||
"SponsoredMessageAd" = "Ad";
|
||||
"SponsoredMessageAdWhatIsThis" = "what's this?";
|
||||
"SponsoredPeerBadge" = "Ad";
|
||||
"PremiumStickerTooltip" = "This set contains premium stickers like this one.";
|
||||
"ViewAction" = "View";
|
||||
"Loading" = "Loading...";
|
||||
@ -1923,4 +1924,4 @@
|
||||
"ApiMessageActionPaidMessagesRefundedOutgoing" = "You refunded **{stars}** to {user}";
|
||||
"ApiMessageActionPaidMessagesRefundedIncoming" = "{user} refunded **{stars}** to you";
|
||||
"NotificationTitleNotSupportedInFrozenAccount" = "Your account is frozen";
|
||||
"NotificationMessageNotSupportedInFrozenAccount" = "This action is not available";
|
||||
"NotificationMessageNotSupportedInFrozenAccount" = "This action is not available";
|
||||
|
||||
@ -58,8 +58,7 @@ export { default as ChatFolderModal } from '../components/left/ChatFolderModal';
|
||||
export { default as MuteChatModal } from '../components/left/MuteChatModal';
|
||||
|
||||
export { default as ContextMenuContainer } from '../components/middle/message/ContextMenuContainer';
|
||||
export { default as SponsoredMessageContextMenuContainer }
|
||||
from '../components/middle/message/SponsoredMessageContextMenuContainer';
|
||||
export { default as SponsoredContextMenuContainer } from '../components/middle/message/SponsoredContextMenuContainer';
|
||||
export { default as StickerSetModal } from '../components/common/StickerSetModal';
|
||||
export { default as CustomEmojiSetsModal } from '../components/common/CustomEmojiSetsModal';
|
||||
export { default as HeaderMenuContainer } from '../components/middle/HeaderMenuContainer';
|
||||
|
||||
@ -8,15 +8,21 @@ type OwnProps = {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
|
||||
onMouseDown?: (e: React.MouseEvent<HTMLDivElement>) => void;
|
||||
};
|
||||
|
||||
const BadgeButton = ({
|
||||
children,
|
||||
className,
|
||||
onClick,
|
||||
onMouseDown,
|
||||
}: OwnProps) => {
|
||||
return (
|
||||
<div className={buildClassName(styles.root, onClick && styles.clickable, className)} onClick={onClick}>
|
||||
<div
|
||||
className={buildClassName(styles.root, onClick && styles.clickable, className)}
|
||||
onClick={onClick}
|
||||
onMouseDown={onMouseDown}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -5,7 +5,7 @@ import React, {
|
||||
} from '../../../lib/teact/teact';
|
||||
import { getActions, getGlobal, withGlobal } from '../../../global';
|
||||
|
||||
import type { ApiMessage, ApiMessageSearchContext } from '../../../api/types';
|
||||
import type { ApiMessage, ApiMessageSearchContext, ApiSponsoredPeer } from '../../../api/types';
|
||||
import { LoadMoreDirection } from '../../../types';
|
||||
|
||||
import { ALL_FOLDER_ID, GLOBAL_SUGGESTED_CHANNELS_ID } from '../../../config';
|
||||
@ -27,6 +27,7 @@ import useAppLayout from '../../../hooks/useAppLayout';
|
||||
import useContextMenuHandlers from '../../../hooks/useContextMenuHandlers';
|
||||
import useEffectOnce from '../../../hooks/useEffectOnce';
|
||||
import useHorizontalScroll from '../../../hooks/useHorizontalScroll';
|
||||
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import useOldLang from '../../../hooks/useOldLang';
|
||||
@ -43,6 +44,7 @@ import Transition from '../../ui/Transition';
|
||||
import ChatMessage from './ChatMessage';
|
||||
import DateSuggest from './DateSuggest';
|
||||
import LeftSearchResultChat from './LeftSearchResultChat';
|
||||
import LeftSearchResultSponsored from './LeftSearchResultSponsored';
|
||||
import RecentContacts from './RecentContacts';
|
||||
|
||||
import './ChatResults.scss';
|
||||
@ -62,6 +64,7 @@ type StateProps = {
|
||||
accountPeerIds?: string[];
|
||||
globalPeerIds?: string[];
|
||||
foundIds?: SearchResultKey[];
|
||||
sponsoredPeer?: ApiSponsoredPeer;
|
||||
globalMessagesByChatId?: Record<string, { byId: Record<number, ApiMessage> }>;
|
||||
fetchingStatus?: { chats?: boolean; messages?: boolean };
|
||||
suggestedChannelIds?: string[];
|
||||
@ -69,6 +72,7 @@ type StateProps = {
|
||||
|
||||
const MIN_QUERY_LENGTH_FOR_GLOBAL_SEARCH = 4;
|
||||
const LESS_LIST_ITEMS_AMOUNT = 5;
|
||||
const INTERSECTION_THROTTLE = 200;
|
||||
|
||||
const runThrottled = throttle((cb) => cb(), 500, false);
|
||||
|
||||
@ -85,6 +89,7 @@ const ChatResults: FC<OwnProps & StateProps> = ({
|
||||
globalMessagesByChatId,
|
||||
fetchingStatus,
|
||||
suggestedChannelIds,
|
||||
sponsoredPeer,
|
||||
onReset,
|
||||
onSearchDateSelect,
|
||||
}) => {
|
||||
@ -93,6 +98,8 @@ const ChatResults: FC<OwnProps & StateProps> = ({
|
||||
setGlobalSearchChatId, loadChannelRecommendations,
|
||||
} = getActions();
|
||||
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const chatSelectionRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@ -335,7 +342,15 @@ const ChatResults: FC<OwnProps & StateProps> = ({
|
||||
&& !localResults.length && !globalResults.length && !actualFoundIds.length;
|
||||
const isMessagesFetching = fetchingStatus?.messages;
|
||||
|
||||
if (!searchQuery && !searchDate && !isChannelList) {
|
||||
const shouldRenderTopPeers = !searchQuery && !searchDate && !isChannelList;
|
||||
|
||||
const { observe } = useIntersectionObserver({
|
||||
rootRef: containerRef,
|
||||
throttleMs: INTERSECTION_THROTTLE,
|
||||
isDisabled: !shouldRenderTopPeers,
|
||||
});
|
||||
|
||||
if (shouldRenderTopPeers) {
|
||||
return <RecentContacts onReset={onReset} />;
|
||||
}
|
||||
|
||||
@ -343,6 +358,7 @@ const ChatResults: FC<OwnProps & StateProps> = ({
|
||||
|
||||
return (
|
||||
<InfiniteScroll
|
||||
ref={containerRef}
|
||||
className="LeftSearch--content custom-scroll"
|
||||
items={actualFoundIds}
|
||||
onLoadMore={handleLoadMore}
|
||||
@ -415,6 +431,9 @@ const ChatResults: FC<OwnProps & StateProps> = ({
|
||||
)}
|
||||
{oldLang('DialogList.SearchSectionGlobal')}
|
||||
</h3>
|
||||
{sponsoredPeer && (
|
||||
<LeftSearchResultSponsored sponsoredPeer={sponsoredPeer} observeIntersection={observe} />
|
||||
)}
|
||||
{globalResults.map((id, index) => {
|
||||
if (!shouldShowMoreGlobal && index >= LESS_LIST_ITEMS_AMOUNT) {
|
||||
return undefined;
|
||||
@ -493,7 +512,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
}
|
||||
|
||||
const {
|
||||
fetchingStatus, globalResults, localResults, resultsByType,
|
||||
fetchingStatus, globalResults, localResults, resultsByType, sponsoredPeer,
|
||||
} = selectTabState(global).globalSearch;
|
||||
const { peerIds: globalPeerIds } = globalResults || {};
|
||||
const { peerIds: accountPeerIds } = localResults || {};
|
||||
@ -509,6 +528,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
foundIds,
|
||||
globalMessagesByChatId,
|
||||
fetchingStatus,
|
||||
sponsoredPeer,
|
||||
suggestedChannelIds: similarChannelIds,
|
||||
};
|
||||
},
|
||||
|
||||
@ -183,6 +183,11 @@
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.search-sponsored-badge {
|
||||
display: flex;
|
||||
align-self: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.search-section {
|
||||
|
||||
116
src/components/left/search/LeftSearchResultSponsored.tsx
Normal file
116
src/components/left/search/LeftSearchResultSponsored.tsx
Normal file
@ -0,0 +1,116 @@
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import React, { memo, useRef } from '../../../lib/teact/teact';
|
||||
import { getActions } from '../../../global';
|
||||
|
||||
import type { ApiSponsoredPeer } from '../../../api/types';
|
||||
import { StoryViewerOrigin } from '../../../types';
|
||||
|
||||
import { isUserId } from '../../../global/helpers';
|
||||
|
||||
import useContextMenuHandlers from '../../../hooks/useContextMenuHandlers';
|
||||
import { useFastClick } from '../../../hooks/useFastClick';
|
||||
import { type ObserveFn, useOnIntersect } from '../../../hooks/useIntersectionObserver';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import useSelectWithEnter from '../../../hooks/useSelectWithEnter';
|
||||
|
||||
import BadgeButton from '../../common/BadgeButton';
|
||||
import GroupChatInfo from '../../common/GroupChatInfo';
|
||||
import Icon from '../../common/icons/Icon';
|
||||
import PrivateChatInfo from '../../common/PrivateChatInfo';
|
||||
import SponsoredMessageContextMenuContainer from '../../middle/message/SponsoredContextMenuContainer';
|
||||
import ListItem from '../../ui/ListItem';
|
||||
|
||||
type OwnProps = {
|
||||
sponsoredPeer: ApiSponsoredPeer;
|
||||
observeIntersection?: ObserveFn;
|
||||
};
|
||||
|
||||
const LeftSearchResultSponsored: FC<OwnProps> = ({
|
||||
sponsoredPeer,
|
||||
observeIntersection,
|
||||
}) => {
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const { clickSponsored, viewSponsored, openChat } = getActions();
|
||||
const lang = useLang();
|
||||
|
||||
const {
|
||||
peerId, randomId, additionalInfo, sponsorInfo,
|
||||
} = sponsoredPeer;
|
||||
|
||||
useOnIntersect(ref, observeIntersection, (entry) => {
|
||||
if (entry.intersectionRatio === 1) {
|
||||
viewSponsored({ randomId });
|
||||
}
|
||||
});
|
||||
|
||||
const handleClick = useLastCallback(() => {
|
||||
clickSponsored({ randomId });
|
||||
openChat({ id: peerId });
|
||||
});
|
||||
|
||||
const {
|
||||
isContextMenuOpen, contextMenuAnchor,
|
||||
handleBeforeContextMenu, handleContextMenu,
|
||||
handleContextMenuClose, handleContextMenuHide,
|
||||
} = useContextMenuHandlers(ref);
|
||||
|
||||
const {
|
||||
handleClick: handleBadgeClick,
|
||||
handleMouseDown: handleBadgeMouseDown,
|
||||
} = useFastClick((e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
handleContextMenu(e);
|
||||
});
|
||||
|
||||
const buttonRef = useSelectWithEnter(handleClick);
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
ref={ref}
|
||||
className="chat-item-clickable search-result"
|
||||
onClick={handleClick}
|
||||
onMouseDown={handleBeforeContextMenu}
|
||||
onContextMenu={handleContextMenu}
|
||||
buttonRef={buttonRef}
|
||||
>
|
||||
{isUserId(peerId) ? (
|
||||
<PrivateChatInfo
|
||||
userId={peerId}
|
||||
withUsername
|
||||
withStory
|
||||
avatarSize="medium"
|
||||
storyViewerOrigin={StoryViewerOrigin.SearchResult}
|
||||
/>
|
||||
) : (
|
||||
<GroupChatInfo
|
||||
chatId={peerId}
|
||||
withUsername
|
||||
avatarSize="medium"
|
||||
withStory
|
||||
storyViewerOrigin={StoryViewerOrigin.SearchResult}
|
||||
/>
|
||||
)}
|
||||
<BadgeButton className="search-sponsored-badge" onMouseDown={handleBadgeMouseDown} onClick={handleBadgeClick}>
|
||||
{lang('SponsoredPeerBadge')}
|
||||
<Icon name="more" />
|
||||
</BadgeButton>
|
||||
{contextMenuAnchor && (
|
||||
<SponsoredMessageContextMenuContainer
|
||||
isOpen={isContextMenuOpen}
|
||||
anchor={contextMenuAnchor}
|
||||
triggerRef={ref}
|
||||
randomId={randomId}
|
||||
additionalInfo={additionalInfo}
|
||||
canReport
|
||||
sponsorInfo={sponsorInfo}
|
||||
onClose={handleContextMenuClose}
|
||||
onCloseAnimationEnd={handleContextMenuHide}
|
||||
/>
|
||||
)}
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(LeftSearchResultSponsored);
|
||||
@ -122,7 +122,7 @@ const MediaViewer = ({
|
||||
toggleChatInfo,
|
||||
searchChatMediaMessages,
|
||||
loadMoreProfilePhotos,
|
||||
clickSponsoredMessage,
|
||||
clickSponsored,
|
||||
openUrl,
|
||||
} = getActions();
|
||||
|
||||
@ -265,7 +265,7 @@ const MediaViewer = ({
|
||||
const handleSponsoredClick = useLastCallback((isFromMedia?: boolean) => {
|
||||
if (!sponsoredMessage || !chatId) return;
|
||||
|
||||
clickSponsoredMessage({ isMedia: isFromMedia, isFullscreen: true, peerId: chatId });
|
||||
clickSponsored({ isMedia: isFromMedia, isFullscreen: true, randomId: sponsoredMessage.randomId });
|
||||
openUrl({ url: sponsoredMessage!.url });
|
||||
closeMediaViewer();
|
||||
});
|
||||
|
||||
@ -3,9 +3,6 @@ import React, {
|
||||
memo, useRef,
|
||||
} from '../../../lib/teact/teact';
|
||||
|
||||
import type {
|
||||
ApiSponsoredMessage,
|
||||
} from '../../../api/types';
|
||||
import type { IAnchorPosition } from '../../../types';
|
||||
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
@ -20,7 +17,8 @@ import './MessageContextMenu.scss';
|
||||
type OwnProps = {
|
||||
isOpen: boolean;
|
||||
anchor: IAnchorPosition;
|
||||
message: ApiSponsoredMessage;
|
||||
sponsorInfo?: string;
|
||||
canReport?: boolean;
|
||||
triggerRef: React.RefObject<HTMLElement>;
|
||||
shouldSkipAbout?: boolean;
|
||||
onClose: NoneToVoidFunction;
|
||||
@ -31,9 +29,10 @@ type OwnProps = {
|
||||
onSponsoredReport?: NoneToVoidFunction;
|
||||
};
|
||||
|
||||
const SponsoredMessageContextMenu: FC<OwnProps> = ({
|
||||
const SponsoredContextMenu: FC<OwnProps> = ({
|
||||
isOpen,
|
||||
message,
|
||||
sponsorInfo,
|
||||
canReport,
|
||||
anchor,
|
||||
triggerRef,
|
||||
shouldSkipAbout,
|
||||
@ -53,7 +52,7 @@ const SponsoredMessageContextMenu: FC<OwnProps> = ({
|
||||
const getMenuElement = useLastCallback(() => menuRef.current);
|
||||
const getRootElement = useLastCallback(() => document.body);
|
||||
|
||||
const isSeparatorNeeded = message.sponsorInfo || !shouldSkipAbout || message.canReport;
|
||||
const isSeparatorNeeded = sponsorInfo || !shouldSkipAbout || canReport;
|
||||
|
||||
return (
|
||||
<Menu
|
||||
@ -69,15 +68,15 @@ const SponsoredMessageContextMenu: FC<OwnProps> = ({
|
||||
onClose={onClose}
|
||||
onCloseAnimationEnd={onCloseAnimationEnd}
|
||||
>
|
||||
{message.sponsorInfo && onSponsorInfo && (
|
||||
{sponsorInfo && onSponsorInfo && (
|
||||
<MenuItem icon="channel" onClick={onSponsorInfo}>{lang('SponsoredMessageSponsor')}</MenuItem>
|
||||
)}
|
||||
{!shouldSkipAbout && (
|
||||
<MenuItem icon="info" onClick={onAboutAdsClick}>
|
||||
{lang(message.canReport ? 'AboutRevenueSharingAds' : 'SponsoredMessageInfo')}
|
||||
{lang(canReport ? 'AboutRevenueSharingAds' : 'SponsoredMessageInfo')}
|
||||
</MenuItem>
|
||||
)}
|
||||
{message.canReport && onSponsoredReport && (
|
||||
{canReport && onSponsoredReport && (
|
||||
<MenuItem icon="hand-stop" onClick={onSponsoredReport}>
|
||||
{lang('ReportAd')}
|
||||
</MenuItem>
|
||||
@ -90,4 +89,4 @@ const SponsoredMessageContextMenu: FC<OwnProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(SponsoredMessageContextMenu);
|
||||
export default memo(SponsoredContextMenu);
|
||||
@ -0,0 +1,20 @@
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import React from '../../../lib/teact/teact';
|
||||
|
||||
import type { OwnProps } from './SponsoredContextMenuContainer';
|
||||
|
||||
import { Bundles } from '../../../util/moduleLoader';
|
||||
|
||||
import useModuleLoader from '../../../hooks/useModuleLoader';
|
||||
|
||||
const SponsoredContextMenuContainerAsync: FC<OwnProps> = (props) => {
|
||||
const { isOpen } = props;
|
||||
const SponsoredContextMenuContainer = useModuleLoader(
|
||||
Bundles.Extra, 'SponsoredContextMenuContainer', !isOpen,
|
||||
);
|
||||
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
return SponsoredContextMenuContainer ? <SponsoredContextMenuContainer {...props} /> : undefined;
|
||||
};
|
||||
|
||||
export default SponsoredContextMenuContainerAsync;
|
||||
@ -2,17 +2,19 @@ import type { FC } from '../../../lib/teact/teact';
|
||||
import React, { memo } from '../../../lib/teact/teact';
|
||||
import { getActions } from '../../../global';
|
||||
|
||||
import type { ApiSponsoredMessage } from '../../../api/types';
|
||||
import type { IAnchorPosition } from '../../../types';
|
||||
|
||||
import useLastCallback from '../../../hooks/useLastCallback';
|
||||
import useShowTransition from '../../../hooks/useShowTransition';
|
||||
|
||||
import SponsoredMessageContextMenu from './SponsoredMessageContextMenu';
|
||||
import SponsoredContextMenu from './SponsoredContextMenu';
|
||||
|
||||
export type OwnProps = {
|
||||
isOpen: boolean;
|
||||
message: ApiSponsoredMessage;
|
||||
randomId: string;
|
||||
sponsorInfo?: string;
|
||||
additionalInfo?: string;
|
||||
canReport?: boolean;
|
||||
anchor: IAnchorPosition;
|
||||
triggerRef: React.RefObject<HTMLElement>;
|
||||
shouldSkipAbout?: boolean;
|
||||
@ -23,7 +25,10 @@ export type OwnProps = {
|
||||
|
||||
const SponsoredMessageContextMenuContainer: FC<OwnProps> = ({
|
||||
isOpen,
|
||||
message,
|
||||
randomId,
|
||||
sponsorInfo,
|
||||
additionalInfo,
|
||||
canReport,
|
||||
anchor,
|
||||
triggerRef,
|
||||
shouldSkipAbout,
|
||||
@ -34,8 +39,8 @@ const SponsoredMessageContextMenuContainer: FC<OwnProps> = ({
|
||||
const {
|
||||
openAboutAdsModal,
|
||||
showDialog,
|
||||
reportSponsoredMessage,
|
||||
hideSponsoredMessages,
|
||||
reportSponsored,
|
||||
hideSponsored,
|
||||
} = getActions();
|
||||
|
||||
const { ref } = useShowTransition({
|
||||
@ -49,26 +54,31 @@ const SponsoredMessageContextMenuContainer: FC<OwnProps> = ({
|
||||
});
|
||||
|
||||
const handleAboutAdsOpen = useLastCallback(() => {
|
||||
openAboutAdsModal({ chatId: message.chatId });
|
||||
openAboutAdsModal({
|
||||
randomId,
|
||||
additionalInfo,
|
||||
canReport,
|
||||
sponsorInfo,
|
||||
});
|
||||
handleItemClick();
|
||||
});
|
||||
|
||||
const handleSponsoredHide = useLastCallback(() => {
|
||||
hideSponsoredMessages();
|
||||
hideSponsored();
|
||||
handleItemClick();
|
||||
});
|
||||
|
||||
const handleSponsorInfo = useLastCallback(() => {
|
||||
showDialog({
|
||||
data: {
|
||||
message: [message.sponsorInfo, message.additionalInfo].join('\n'),
|
||||
message: [sponsorInfo, additionalInfo].filter(Boolean).join('\n'),
|
||||
},
|
||||
});
|
||||
handleItemClick();
|
||||
});
|
||||
|
||||
const handleReportSponsoredMessage = useLastCallback(() => {
|
||||
reportSponsoredMessage({ peerId: message.chatId, randomId: message.randomId });
|
||||
reportSponsored({ randomId });
|
||||
handleItemClick();
|
||||
});
|
||||
|
||||
@ -78,11 +88,12 @@ const SponsoredMessageContextMenuContainer: FC<OwnProps> = ({
|
||||
|
||||
return (
|
||||
<div ref={ref} className="ContextMenuContainer">
|
||||
<SponsoredMessageContextMenu
|
||||
<SponsoredContextMenu
|
||||
isOpen={isOpen}
|
||||
anchor={anchor}
|
||||
triggerRef={triggerRef}
|
||||
message={message}
|
||||
canReport={canReport}
|
||||
sponsorInfo={sponsorInfo}
|
||||
shouldSkipAbout={shouldSkipAbout}
|
||||
onClose={onClose}
|
||||
onCloseAnimationEnd={onClose}
|
||||
@ -38,7 +38,7 @@ import PeerColorWrapper from '../../common/PeerColorWrapper';
|
||||
import Button from '../../ui/Button';
|
||||
import MessageAppendix from './MessageAppendix';
|
||||
import Photo from './Photo';
|
||||
import SponsoredMessageContextMenuContainer from './SponsoredMessageContextMenuContainer.async';
|
||||
import SponsoredContextMenuContainer from './SponsoredContextMenuContainer.async';
|
||||
import Video from './Video';
|
||||
|
||||
import './SponsoredMessage.scss';
|
||||
@ -72,10 +72,10 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
||||
canAutoPlayMedia,
|
||||
}) => {
|
||||
const {
|
||||
viewSponsoredMessage,
|
||||
viewSponsored,
|
||||
openUrl,
|
||||
hideSponsoredMessages,
|
||||
clickSponsoredMessage,
|
||||
hideSponsored,
|
||||
clickSponsored,
|
||||
openMediaViewer,
|
||||
openAboutAdsModal,
|
||||
} = getActions();
|
||||
@ -103,11 +103,11 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
||||
|
||||
useEffect(() => {
|
||||
return shouldObserve ? observeIntersection(contentRef.current!, (target) => {
|
||||
if (target.isIntersecting) {
|
||||
viewSponsoredMessage({ peerId: chatId });
|
||||
if (target.isIntersecting && message?.randomId) {
|
||||
viewSponsored({ randomId: message.randomId });
|
||||
}
|
||||
}) : undefined;
|
||||
}, [chatId, shouldObserve, observeIntersection, viewSponsoredMessage]);
|
||||
}, [message?.randomId, shouldObserve, observeIntersection, viewSponsored]);
|
||||
|
||||
const handleMouseDown = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
||||
preventMessageInputBlur(e);
|
||||
@ -115,7 +115,7 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
||||
};
|
||||
|
||||
const handleHideSponsoredMessage = useLastCallback(() => {
|
||||
hideSponsoredMessages();
|
||||
hideSponsored();
|
||||
});
|
||||
|
||||
const {
|
||||
@ -128,12 +128,13 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
||||
const handleClick = useLastCallback(() => {
|
||||
if (!message) return;
|
||||
|
||||
clickSponsoredMessage({ isMedia: photo || isGif ? true : undefined, peerId: chatId });
|
||||
clickSponsored({ randomId: message.randomId, isMedia: photo || isGif ? true : undefined });
|
||||
openUrl({ url: message.url, shouldSkipModal: true });
|
||||
});
|
||||
|
||||
const handleOpenMedia = useLastCallback(() => {
|
||||
clickSponsoredMessage({ isMedia: true, peerId: chatId });
|
||||
if (!message) return;
|
||||
clickSponsored({ randomId: message.randomId, isMedia: true });
|
||||
openMediaViewer({
|
||||
origin: MediaViewerOrigin.SponsoredMessage,
|
||||
chatId,
|
||||
@ -142,7 +143,13 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
|
||||
const handleOpenAboutAdsModal = useLastCallback(() => {
|
||||
openAboutAdsModal({ chatId });
|
||||
if (!message) return;
|
||||
openAboutAdsModal({
|
||||
randomId: message.randomId,
|
||||
canReport: message.canReport,
|
||||
additionalInfo: message.additionalInfo,
|
||||
sponsorInfo: message.sponsorInfo,
|
||||
});
|
||||
});
|
||||
|
||||
const extraPadding = 0;
|
||||
@ -315,11 +322,14 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
{contextMenuAnchor && (
|
||||
<SponsoredMessageContextMenuContainer
|
||||
<SponsoredContextMenuContainer
|
||||
isOpen={isContextMenuOpen}
|
||||
anchor={contextMenuAnchor}
|
||||
triggerRef={ref}
|
||||
message={message!}
|
||||
randomId={message.randomId}
|
||||
canReport={message.canReport}
|
||||
sponsorInfo={message.sponsorInfo}
|
||||
additionalInfo={message.additionalInfo}
|
||||
onClose={handleContextMenuClose}
|
||||
onCloseAnimationEnd={handleContextMenuHide}
|
||||
/>
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import React from '../../../lib/teact/teact';
|
||||
|
||||
import type { OwnProps } from './SponsoredMessageContextMenuContainer';
|
||||
|
||||
import { Bundles } from '../../../util/moduleLoader';
|
||||
|
||||
import useModuleLoader from '../../../hooks/useModuleLoader';
|
||||
|
||||
const SponsoredMessageContextMenuContainerAsync: FC<OwnProps> = (props) => {
|
||||
const { isOpen } = props;
|
||||
const SponsoredMessageContextMenuContainer = useModuleLoader(
|
||||
Bundles.Extra, 'SponsoredMessageContextMenuContainer', !isOpen,
|
||||
);
|
||||
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
return SponsoredMessageContextMenuContainer ? <SponsoredMessageContextMenuContainer {...props} /> : undefined;
|
||||
};
|
||||
|
||||
export default SponsoredMessageContextMenuContainerAsync;
|
||||
@ -17,7 +17,7 @@ import useHeaderPane, { type PaneState } from '../hooks/useHeaderPane';
|
||||
|
||||
import Avatar from '../../common/Avatar';
|
||||
import BadgeButton from '../../common/BadgeButton';
|
||||
import SponsoredMessageContextMenuContainer from '../message/SponsoredMessageContextMenuContainer';
|
||||
import SponsoredMessageContextMenuContainer from '../message/SponsoredContextMenuContainer';
|
||||
|
||||
import styles from './BotAdPane.module.scss';
|
||||
|
||||
@ -40,9 +40,9 @@ const BotAdPane = ({
|
||||
onPaneStateChange,
|
||||
}: OwnProps & StateProps) => {
|
||||
const {
|
||||
viewSponsoredMessage,
|
||||
viewSponsored,
|
||||
openUrl,
|
||||
clickSponsoredMessage,
|
||||
clickSponsored,
|
||||
openAboutAdsModal,
|
||||
} = getActions();
|
||||
|
||||
@ -67,25 +67,38 @@ const BotAdPane = ({
|
||||
const handleClick = useLastCallback(() => {
|
||||
if (!renderingSponsoredMessage) return;
|
||||
|
||||
clickSponsoredMessage({ peerId: chatId });
|
||||
clickSponsored({ randomId: renderingSponsoredMessage.randomId });
|
||||
openUrl({ url: renderingSponsoredMessage.url, shouldSkipModal: true });
|
||||
});
|
||||
|
||||
const handleAboutClick = useLastCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
||||
if (!renderingSponsoredMessage) return;
|
||||
const {
|
||||
randomId, additionalInfo, canReport, sponsorInfo,
|
||||
} = renderingSponsoredMessage;
|
||||
e.stopPropagation();
|
||||
openAboutAdsModal({ chatId });
|
||||
openAboutAdsModal({
|
||||
randomId,
|
||||
additionalInfo,
|
||||
canReport,
|
||||
sponsorInfo,
|
||||
});
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (shouldRender && sponsoredMessage) {
|
||||
viewSponsoredMessage({ peerId: chatId });
|
||||
if (shouldRender && renderingSponsoredMessage) {
|
||||
viewSponsored({ randomId: renderingSponsoredMessage.randomId });
|
||||
}
|
||||
}, [shouldRender, sponsoredMessage, chatId]);
|
||||
}, [shouldRender, renderingSponsoredMessage, chatId]);
|
||||
|
||||
if (!shouldRender || !renderingSponsoredMessage) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const {
|
||||
randomId, canReport, additionalInfo, sponsorInfo,
|
||||
} = renderingSponsoredMessage;
|
||||
|
||||
const {
|
||||
peerColor,
|
||||
content,
|
||||
@ -132,7 +145,10 @@ const BotAdPane = ({
|
||||
isOpen={isContextMenuOpen}
|
||||
anchor={contextMenuAnchor}
|
||||
triggerRef={ref}
|
||||
message={renderingSponsoredMessage}
|
||||
randomId={randomId}
|
||||
additionalInfo={additionalInfo}
|
||||
canReport={canReport}
|
||||
sponsorInfo={sponsorInfo}
|
||||
onClose={handleContextMenuClose}
|
||||
onCloseAnimationEnd={handleContextMenuHide}
|
||||
/>
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
import React, { memo, useMemo, useRef } from '../../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
import type { ApiSponsoredMessage } from '../../../api/types';
|
||||
import type { TabState } from '../../../global/types';
|
||||
import type { TableAboutData } from '../common/TableAboutModal';
|
||||
|
||||
import { selectSponsoredMessage } from '../../../global/selectors';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import renderText from '../../common/helpers/renderText';
|
||||
|
||||
@ -16,7 +14,7 @@ import useOldLang from '../../../hooks/useOldLang';
|
||||
|
||||
import Icon from '../../common/icons/Icon';
|
||||
import SafeLink from '../../common/SafeLink';
|
||||
import SponsoredMessageContextMenuContainer from '../../middle/message/SponsoredMessageContextMenuContainer';
|
||||
import SponsoredMessageContextMenuContainer from '../../middle/message/SponsoredContextMenuContainer';
|
||||
import Button from '../../ui/Button';
|
||||
import Modal from '../../ui/Modal';
|
||||
import TableAboutModal from '../common/TableAboutModal';
|
||||
@ -29,18 +27,21 @@ export type OwnProps = {
|
||||
};
|
||||
|
||||
type StateProps = {
|
||||
message?: ApiSponsoredMessage;
|
||||
minLevelToRestrictAds?: number;
|
||||
};
|
||||
|
||||
const AboutAdsModal = ({ message, minLevelToRestrictAds }: OwnProps & StateProps) => {
|
||||
const AboutAdsModal = ({ modal, minLevelToRestrictAds }: OwnProps & StateProps) => {
|
||||
const { closeAboutAdsModal } = getActions();
|
||||
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const moreMenuRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const isOpen = Boolean(message);
|
||||
const isMonetizationSharing = message?.canReport;
|
||||
const isOpen = Boolean(modal);
|
||||
const renderingModal = useCurrentOrPrev(modal);
|
||||
const {
|
||||
canReport, randomId, additionalInfo, sponsorInfo,
|
||||
} = renderingModal || {};
|
||||
const isMonetizationSharing = canReport;
|
||||
|
||||
const renderingIsNewDesign = useCurrentOrPrev(isMonetizationSharing);
|
||||
|
||||
@ -139,12 +140,15 @@ const AboutAdsModal = ({ message, minLevelToRestrictAds }: OwnProps & StateProps
|
||||
buttonText={oldLang('RevenueSharingAdsUnderstood')}
|
||||
onClose={handleClose}
|
||||
/>
|
||||
{contextMenuAnchor && message && (
|
||||
{contextMenuAnchor && randomId && (
|
||||
<SponsoredMessageContextMenuContainer
|
||||
isOpen={isContextMenuOpen}
|
||||
anchor={contextMenuAnchor}
|
||||
triggerRef={moreMenuRef}
|
||||
message={message}
|
||||
randomId={randomId}
|
||||
additionalInfo={additionalInfo}
|
||||
canReport={canReport}
|
||||
sponsorInfo={sponsorInfo}
|
||||
shouldSkipAbout
|
||||
onItemClick={handleClose}
|
||||
onClose={handleContextMenuClose}
|
||||
@ -174,12 +178,10 @@ const AboutAdsModal = ({ message, minLevelToRestrictAds }: OwnProps & StateProps
|
||||
};
|
||||
|
||||
export default memo(withGlobal<OwnProps>(
|
||||
(global, { modal }): StateProps => {
|
||||
const message = modal?.chatId ? selectSponsoredMessage(global, modal.chatId) : undefined;
|
||||
(global): StateProps => {
|
||||
const minLevelToRestrictAds = global.appConfig?.channelRestrictAdsLevelMin;
|
||||
|
||||
return {
|
||||
message,
|
||||
minLevelToRestrictAds,
|
||||
};
|
||||
},
|
||||
|
||||
@ -30,7 +30,7 @@ const ReportAdModal = ({
|
||||
modal,
|
||||
}: OwnProps) => {
|
||||
const {
|
||||
reportSponsoredMessage, closeReportAdModal, openPreviousReportAdModal,
|
||||
reportSponsored, closeReportAdModal, openPreviousReportAdModal,
|
||||
} = getActions();
|
||||
const lang = useOldLang();
|
||||
const isOpen = Boolean(modal);
|
||||
@ -40,7 +40,7 @@ const ReportAdModal = ({
|
||||
|
||||
const handleOptionClick = useLastCallback((e, option: string) => {
|
||||
const { chatId, randomId } = modal!;
|
||||
reportSponsoredMessage({ peerId: chatId, randomId, option });
|
||||
reportSponsored({ peerId: chatId, randomId, option });
|
||||
});
|
||||
|
||||
const [renderingSection, renderingDepth] = useMemo(() => {
|
||||
|
||||
@ -33,11 +33,14 @@ addActionHandler('setGlobalSearchQuery', (global, actions, payload): ActionRetur
|
||||
|
||||
if (query && !chatId) {
|
||||
void searchThrottled(async () => {
|
||||
const result = await callApi('searchChats', { query });
|
||||
const [searchResult, sponsoredResult] = await Promise.all([
|
||||
callApi('searchChats', { query }),
|
||||
callApi('fetchSponsoredPeer', { query }),
|
||||
]);
|
||||
|
||||
global = getGlobal();
|
||||
const currentSearchQuery = selectCurrentGlobalSearchQuery(global, tabId);
|
||||
if (!result || !currentSearchQuery || (query !== currentSearchQuery)) {
|
||||
if (!searchResult || !currentSearchQuery || (query !== currentSearchQuery)) {
|
||||
global = updateGlobalSearchFetchingStatus(global, { chats: false }, tabId);
|
||||
setGlobal(global);
|
||||
return;
|
||||
@ -45,7 +48,7 @@ addActionHandler('setGlobalSearchQuery', (global, actions, payload): ActionRetur
|
||||
|
||||
const {
|
||||
accountResultIds, globalResultIds,
|
||||
} = result;
|
||||
} = searchResult;
|
||||
|
||||
global = updateGlobalSearchFetchingStatus(global, { chats: false }, tabId);
|
||||
global = updateGlobalSearch(global, {
|
||||
@ -56,6 +59,7 @@ addActionHandler('setGlobalSearchQuery', (global, actions, payload): ActionRetur
|
||||
...selectTabState(global, tabId).globalSearch.globalResults,
|
||||
peerIds: globalResultIds,
|
||||
},
|
||||
sponsoredPeer: sponsoredResult,
|
||||
}, tabId);
|
||||
|
||||
setGlobal(global);
|
||||
|
||||
@ -84,6 +84,7 @@ import {
|
||||
updateChat,
|
||||
updateChatFullInfo,
|
||||
updateChatMessage,
|
||||
updateGlobalSearch,
|
||||
updateListedIds,
|
||||
updateMessageTranslation,
|
||||
updateOutlyingLists,
|
||||
@ -135,7 +136,6 @@ import {
|
||||
selectReplyCanBeSentToChat,
|
||||
selectScheduledMessage,
|
||||
selectSendAs,
|
||||
selectSponsoredMessage,
|
||||
selectTabState,
|
||||
selectThreadIdFromMessage,
|
||||
selectTopic,
|
||||
@ -1867,38 +1867,24 @@ addActionHandler('loadSponsoredMessages', async (global, actions, payload): Prom
|
||||
setGlobal(global);
|
||||
});
|
||||
|
||||
addActionHandler('viewSponsoredMessage', (global, actions, payload): ActionReturnType => {
|
||||
const { peerId } = payload;
|
||||
const peer = selectPeer(global, peerId);
|
||||
const message = selectSponsoredMessage(global, peerId);
|
||||
if (!peer || !message) {
|
||||
return;
|
||||
}
|
||||
addActionHandler('viewSponsored', (global, actions, payload): ActionReturnType => {
|
||||
const { randomId } = payload;
|
||||
|
||||
void callApi('viewSponsoredMessage', { random: message.randomId });
|
||||
void callApi('viewSponsoredMessage', { random: randomId });
|
||||
});
|
||||
|
||||
addActionHandler('clickSponsoredMessage', (global, actions, payload): ActionReturnType => {
|
||||
const { peerId, isMedia, isFullscreen } = payload;
|
||||
const peer = selectPeer(global, peerId);
|
||||
const message = selectSponsoredMessage(global, peerId);
|
||||
if (!peer || !message) {
|
||||
return;
|
||||
}
|
||||
addActionHandler('clickSponsored', (global, actions, payload): ActionReturnType => {
|
||||
const { randomId, isMedia, isFullscreen } = payload;
|
||||
|
||||
void callApi('clickSponsoredMessage', {
|
||||
random: message.randomId, isMedia, isFullscreen,
|
||||
random: randomId, isMedia, isFullscreen,
|
||||
});
|
||||
});
|
||||
|
||||
addActionHandler('reportSponsoredMessage', async (global, actions, payload): Promise<void> => {
|
||||
addActionHandler('reportSponsored', async (global, actions, payload): Promise<void> => {
|
||||
const {
|
||||
peerId, randomId, option = '', tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
const peer = selectPeer(global, peerId);
|
||||
if (!peer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await callApi('reportSponsoredMessage', { randomId, option });
|
||||
|
||||
@ -1918,7 +1904,13 @@ addActionHandler('reportSponsoredMessage', async (global, actions, payload): Pro
|
||||
actions.closeReportAdModal({ tabId });
|
||||
|
||||
global = getGlobal();
|
||||
global = deleteSponsoredMessage(global, peerId);
|
||||
if (peerId) {
|
||||
global = deleteSponsoredMessage(global, peerId);
|
||||
} else {
|
||||
global = updateGlobalSearch(global, {
|
||||
sponsoredPeer: undefined,
|
||||
}, tabId);
|
||||
}
|
||||
setGlobal(global);
|
||||
return;
|
||||
}
|
||||
@ -1943,7 +1935,7 @@ addActionHandler('reportSponsoredMessage', async (global, actions, payload): Pro
|
||||
}
|
||||
});
|
||||
|
||||
addActionHandler('hideSponsoredMessages', async (global, actions, payload): Promise<void> => {
|
||||
addActionHandler('hideSponsored', async (global, actions, payload): Promise<void> => {
|
||||
const { tabId = getCurrentTabId() } = payload || {};
|
||||
const isCurrentUserPremium = selectIsCurrentUserPremium(global);
|
||||
if (!isCurrentUserPremium) {
|
||||
|
||||
@ -1064,11 +1064,16 @@ addActionHandler('closeDeleteMessageModal', (global, actions, payload): ActionRe
|
||||
});
|
||||
|
||||
addActionHandler('openAboutAdsModal', (global, actions, payload): ActionReturnType => {
|
||||
const { chatId, tabId = getCurrentTabId() } = payload || {};
|
||||
const {
|
||||
randomId, additionalInfo, canReport, sponsorInfo, tabId = getCurrentTabId(),
|
||||
} = payload || {};
|
||||
|
||||
return updateTabState(global, {
|
||||
aboutAdsModal: {
|
||||
chatId,
|
||||
randomId,
|
||||
canReport,
|
||||
additionalInfo,
|
||||
sponsorInfo,
|
||||
},
|
||||
}, tabId);
|
||||
});
|
||||
|
||||
@ -504,21 +504,24 @@ export interface ActionPayloads {
|
||||
loadSponsoredMessages: {
|
||||
peerId: string;
|
||||
};
|
||||
viewSponsoredMessage: {
|
||||
peerId: string;
|
||||
viewSponsored: {
|
||||
randomId: string;
|
||||
};
|
||||
clickSponsoredMessage: {
|
||||
peerId: string;
|
||||
clickSponsored: {
|
||||
randomId: string;
|
||||
isMedia?: boolean;
|
||||
isFullscreen?: boolean;
|
||||
};
|
||||
reportSponsoredMessage: {
|
||||
peerId: string;
|
||||
reportSponsored: {
|
||||
peerId?: string;
|
||||
randomId: string;
|
||||
option?: string;
|
||||
} & WithTabId;
|
||||
openAboutAdsModal: {
|
||||
chatId: string;
|
||||
randomId: string;
|
||||
canReport?: boolean;
|
||||
sponsorInfo?: string;
|
||||
additionalInfo?: string;
|
||||
} & WithTabId;
|
||||
closeAboutAdsModal: WithTabId | undefined;
|
||||
openPreparedInlineMessageModal: {
|
||||
@ -542,7 +545,7 @@ export interface ActionPayloads {
|
||||
openPreviousReportModal: WithTabId | undefined;
|
||||
closeReportAdModal: WithTabId | undefined;
|
||||
closeReportModal: WithTabId | undefined;
|
||||
hideSponsoredMessages: WithTabId | undefined;
|
||||
hideSponsored: WithTabId | undefined;
|
||||
loadSendAs: {
|
||||
chatId: string;
|
||||
};
|
||||
|
||||
@ -35,6 +35,7 @@ import type {
|
||||
ApiReceiptRegular,
|
||||
ApiSavedGifts,
|
||||
ApiSavedStarGift,
|
||||
ApiSponsoredPeer,
|
||||
ApiStarGift,
|
||||
ApiStarGiftAttribute,
|
||||
ApiStarGiveawayOption,
|
||||
@ -186,7 +187,10 @@ export type TabState = {
|
||||
};
|
||||
|
||||
aboutAdsModal?: {
|
||||
chatId: string;
|
||||
randomId: string;
|
||||
canReport?: boolean;
|
||||
sponsorInfo?: string;
|
||||
additionalInfo?: string;
|
||||
};
|
||||
|
||||
reactionPicker?: {
|
||||
@ -220,6 +224,7 @@ export type TabState = {
|
||||
currentContent?: GlobalSearchContent;
|
||||
chatId?: string;
|
||||
foundTopicIds?: number[];
|
||||
sponsoredPeer?: ApiSponsoredPeer;
|
||||
fetchingStatus?: {
|
||||
chats?: boolean;
|
||||
messages?: boolean;
|
||||
@ -440,7 +445,7 @@ export type TabState = {
|
||||
openedCustomEmojiSetIds?: string[];
|
||||
|
||||
reportAdModal?: {
|
||||
chatId: string;
|
||||
chatId?: string;
|
||||
randomId: string;
|
||||
sections: {
|
||||
title: string;
|
||||
|
||||
@ -1498,6 +1498,7 @@ contacts.getTopPeers#973478b6 flags:# correspondents:flags.0?true bots_pm:flags.
|
||||
contacts.addContact#e8f463d0 flags:# add_phone_privacy_exception:flags.0?true id:InputUser first_name:string last_name:string phone:string = Updates;
|
||||
contacts.resolvePhone#8af94344 phone:string = contacts.ResolvedPeer;
|
||||
contacts.editCloseFriends#ba6705f0 id:Vector<long> = Bool;
|
||||
contacts.getSponsoredPeers#b6c8c393 q:string = contacts.SponsoredPeers;
|
||||
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
|
||||
messages.getDialogs#a0f4cb4f flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:long = messages.Dialogs;
|
||||
messages.getHistory#4423e6c5 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
|
||||
|
||||
@ -77,6 +77,7 @@
|
||||
"contacts.addContact",
|
||||
"contacts.resolvePhone",
|
||||
"contacts.editCloseFriends",
|
||||
"contacts.getSponsoredPeers",
|
||||
"messages.getMessages",
|
||||
"messages.getDialogs",
|
||||
"messages.getHistory",
|
||||
|
||||
1
src/types/language.d.ts
vendored
1
src/types/language.d.ts
vendored
@ -685,6 +685,7 @@ export interface LangPair {
|
||||
'MessageRecommendedLabel': undefined;
|
||||
'SponsoredMessageAd': undefined;
|
||||
'SponsoredMessageAdWhatIsThis': undefined;
|
||||
'SponsoredPeerBadge': undefined;
|
||||
'PremiumStickerTooltip': undefined;
|
||||
'ViewAction': undefined;
|
||||
'Loading': undefined;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user