import type { RefObject } from 'react'; import type { FC } from '../../../lib/teact/teact'; import React, { memo, useEffect, useMemo, useRef, } from '../../../lib/teact/teact'; import { getActions, withGlobal } from '../../../global'; import type { ApiSponsoredMessage } from '../../../api/types'; import type { ISettings } from '../../../types'; import { MediaViewerOrigin } from '../../../types'; import { getIsDownloading, getMessageContent, getMessageDownloadableMedia, } from '../../../global/helpers'; import { selectActiveDownloads, selectCanAutoLoadMedia, selectCanAutoPlayMedia, selectSponsoredMessage, selectTheme, } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; import { IS_ANDROID } from '../../../util/windowEnvironment'; import { renderTextWithEntities } from '../../common/helpers/renderTextWithEntities'; import { preventMessageInputBlur } from '../helpers/preventMessageInputBlur'; import { calculateMediaDimensions, getMinMediaWidth, MIN_MEDIA_WIDTH_WITH_TEXT } from './helpers/mediaDimensions'; import useAppLayout from '../../../hooks/useAppLayout'; import useContextMenuHandlers from '../../../hooks/useContextMenuHandlers'; import useFlag from '../../../hooks/useFlag'; import { type ObserveFn, useIntersectionObserver } from '../../../hooks/useIntersectionObserver'; import useLastCallback from '../../../hooks/useLastCallback'; import useOldLang from '../../../hooks/useOldLang'; import AboutAdsModal from '../../common/AboutAdsModal.async'; import Avatar from '../../common/Avatar'; import Icon from '../../common/icons/Icon'; import PeerColorWrapper from '../../common/PeerColorWrapper'; import Button from '../../ui/Button'; import MessageAppendix from './MessageAppendix'; import Photo from './Photo'; import SponsoredMessageContextMenuContainer from './SponsoredMessageContextMenuContainer.async'; import Video from './Video'; import './SponsoredMessage.scss'; type OwnProps = { chatId: string; containerRef: RefObject; observeIntersectionForLoading: ObserveFn; observeIntersectionForPlaying: ObserveFn; }; type StateProps = { message?: ApiSponsoredMessage; theme: ISettings['theme']; isDownloading?: boolean; canAutoLoadMedia?: boolean; canAutoPlayMedia?: boolean; }; const INTERSECTION_DEBOUNCE_MS = 200; const SponsoredMessage: FC = ({ chatId, message, containerRef, theme, observeIntersectionForLoading, observeIntersectionForPlaying, isDownloading, canAutoLoadMedia, canAutoPlayMedia, }) => { const { viewSponsoredMessage, openUrl, hideSponsoredMessages, clickSponsoredMessage, reportSponsoredMessage, openMediaViewer, } = getActions(); const lang = useOldLang(); // eslint-disable-next-line no-null/no-null const ref = useRef(null); // eslint-disable-next-line no-null/no-null const contentRef = useRef(null); const shouldObserve = Boolean(message); const { isMobile } = useAppLayout(); const { observe: observeIntersection, } = useIntersectionObserver({ rootRef: containerRef, debounceMs: INTERSECTION_DEBOUNCE_MS, threshold: 1, }); const { isContextMenuOpen, contextMenuAnchor, handleBeforeContextMenu, handleContextMenu, handleContextMenuClose, handleContextMenuHide, } = useContextMenuHandlers(ref, undefined, true, IS_ANDROID); const [isAboutAdsModalOpen, openAboutAdsModal, closeAboutAdsModal] = useFlag(false); useEffect(() => { return shouldObserve ? observeIntersection(contentRef.current!, (target) => { if (target.isIntersecting) { viewSponsoredMessage({ chatId }); } }) : undefined; }, [chatId, shouldObserve, observeIntersection, viewSponsoredMessage]); const handleMouseDown = (e: React.MouseEvent) => { preventMessageInputBlur(e); handleBeforeContextMenu(e); }; const handleReportSponsoredMessage = useLastCallback(() => { reportSponsoredMessage({ chatId, randomId: message!.randomId }); }); const handleHideSponsoredMessage = useLastCallback(() => { hideSponsoredMessages(); }); const handleClick = useLastCallback(() => { if (!message) return; clickSponsoredMessage({ chatId }); openUrl({ url: message!.url, shouldSkipModal: true }); }); const handleOpenMedia = useLastCallback(() => { openMediaViewer({ origin: MediaViewerOrigin.SponsoredMessage, chatId, isSponsoredMessage: true, }); }); const { photo, video, } = message ? getMessageContent(message) : { photo: undefined, video: undefined }; const hasMedia = Boolean(photo || video); const extraPadding = 0; const sizeCalculations = useMemo(() => { let calculatedWidth; let contentWidth: number | undefined; const noMediaCorners = false; let style = ''; if (photo || video) { let width: number | undefined; if (photo) { width = calculateMediaDimensions({ media: photo, isMobile, }).width; } else if (video) { width = calculateMediaDimensions({ media: video, isMobile, }).width; } if (width) { if (width < MIN_MEDIA_WIDTH_WITH_TEXT) { contentWidth = width; } calculatedWidth = Math.max(getMinMediaWidth(), width); } } if (calculatedWidth) { style = `width: ${calculatedWidth + extraPadding}px`; } return { contentWidth, noMediaCorners, style, }; }, [photo, video, isMobile]); const { contentWidth, style, } = sizeCalculations; if (!message || !message.content) { return undefined; } function renderContent() { if (!message) return undefined; return ( <>
{message.title}
{Boolean(message.content?.text) && (
{renderTextWithEntities({ text: message.content.text.text, entities: message.content.text.entities, })}
)} ); } function renderMediaContent() { if (!message) return undefined; if (photo) { return ( ); } if (video) { return (