import type { FC } from '../../../lib/teact/teact'; import React, { useMemo } from '../../../lib/teact/teact'; import { getActions, getGlobal, withGlobal } from '../../../global'; import type { ApiMessage } from '../../../api/types'; import type { GlobalState, TabState } from '../../../global/types'; import type { ObserveFn } from '../../../hooks/useIntersectionObserver'; import type { IAlbum, ISettings } from '../../../types'; import type { IAlbumLayout } from './helpers/calculateAlbumLayout'; import { getIsDownloading, getMessageContent, getMessageHtmlId, getMessagePhoto, } from '../../../global/helpers'; import { selectActiveDownloads, selectCanAutoLoadMedia, selectCanAutoPlayMedia, selectTheme, } from '../../../global/selectors'; import { getMessageKey } from '../../../util/keys/messageKey'; import { AlbumRectPart } from './helpers/calculateAlbumLayout'; import withSelectControl from './hocs/withSelectControl'; import useLastCallback from '../../../hooks/useLastCallback'; import Photo from './Photo'; import Video from './Video'; import './Album.scss'; const PhotoWithSelect = withSelectControl(Photo); const VideoWithSelect = withSelectControl(Video); type OwnProps = { album: IAlbum; observeIntersection: ObserveFn; hasCustomAppendix?: boolean; isOwn: boolean; isProtected?: boolean; albumLayout: IAlbumLayout; onMediaClick: (messageId: number, index?: number) => void; }; type StateProps = { theme: ISettings['theme']; uploadsByKey: GlobalState['fileUploads']['byMessageKey']; activeDownloads: TabState['activeDownloads']; }; const Album: FC = ({ album, observeIntersection, hasCustomAppendix, isOwn, isProtected, albumLayout, onMediaClick, uploadsByKey, activeDownloads, theme, }) => { const { cancelUploadMedia } = getActions(); const { content: { paidMedia } } = album.mainMessage; const mediaCount = album.isPaidMedia ? paidMedia!.extendedMedia.length : album.messages.length; const handlePaidMediaClick = useLastCallback((index: number) => { onMediaClick(album.mainMessage.id, index); }); const handleAlbumMessageClick = useLastCallback((messageId: number) => { onMediaClick(messageId); }); const handleCancelUpload = useLastCallback((messageId: number) => { cancelUploadMedia({ chatId: album.mainMessage.chatId, messageId }); }); const messages = useMemo(() => { if (album.isPaidMedia) { return album.mainMessage.content.paidMedia!.extendedMedia.map(() => album.mainMessage); } return album.messages; }, [album]); function renderAlbumMessage(message: ApiMessage, index: number) { const renderingPaidMedia = album.isPaidMedia ? message.content.paidMedia?.extendedMedia[index] : undefined; const paidPhotoOrPreview = renderingPaidMedia && 'mediaType' in renderingPaidMedia ? renderingPaidMedia : renderingPaidMedia?.photo; const paidVideoOrPreview = renderingPaidMedia && 'mediaType' in renderingPaidMedia ? renderingPaidMedia : renderingPaidMedia?.video; const photo = paidPhotoOrPreview || getMessagePhoto(message); const video = paidVideoOrPreview || getMessageContent(message).video; const fileUpload = uploadsByKey[getMessageKey(message)]; const uploadProgress = fileUpload?.progress; const { dimensions, sides } = albumLayout.layout[index]; // Ignoring global updates is a known drawback here const canAutoLoad = selectCanAutoLoadMedia(getGlobal(), message); const canAutoPlay = selectCanAutoPlayMedia(getGlobal(), message); if (photo) { const shouldAffectAppendix = hasCustomAppendix && ( // eslint-disable-next-line no-bitwise (isOwn ? index === mediaCount - 1 : Boolean(sides & AlbumRectPart.Left && sides & AlbumRectPart.Bottom)) ); return ( ); } else if (video) { return ( ); } return undefined; } const { width: containerWidth, height: containerHeight } = albumLayout.containerStyle; return (
{messages.map(renderAlbumMessage)}
); }; export default withGlobal( (global): StateProps => { const theme = selectTheme(global); const activeDownloads = selectActiveDownloads(global); return { theme, uploadsByKey: global.fileUploads.byMessageKey, activeDownloads, }; }, )(Album);