mirror of
https://github.com/danog/telegram-tt.git
synced 2024-12-11 16:49:44 +01:00
Message: Support web page videos; Always play videos inline (#1233)
This commit is contained in:
parent
f15d616e20
commit
5facc1e705
@ -27,7 +27,7 @@ import { DELETED_COMMENTS_CHANNEL_ID, LOCAL_MESSAGE_ID_BASE, SERVICE_NOTIFICATIO
|
||||
import { pick } from '../../../util/iteratees';
|
||||
import { getApiChatIdFromMtpPeer } from './chats';
|
||||
import { buildStickerFromDocument } from './symbols';
|
||||
import { buildApiPhoto, buildApiThumbnailFromStripped, buildApiPhotoSize } from './common';
|
||||
import { buildApiPhoto, buildApiThumbnailFromStripped } from './common';
|
||||
import { interpolateArray } from '../../../util/waveform';
|
||||
import { getCurrencySign } from '../../../components/middle/helpers/getCurrencySign';
|
||||
import { buildPeer } from '../gramjsBuilders';
|
||||
@ -511,26 +511,25 @@ export function buildWebPage(media: GramJs.TypeMessageMedia): ApiWebPage | undef
|
||||
|
||||
const { id, photo, document } = media.webpage;
|
||||
|
||||
let video;
|
||||
if (document instanceof GramJs.Document && document.mimeType.startsWith('video')) {
|
||||
video = buildVideoFromDocument(document);
|
||||
}
|
||||
|
||||
return {
|
||||
id: Number(id),
|
||||
...pick(media.webpage, [
|
||||
'url',
|
||||
'displayUrl',
|
||||
'type',
|
||||
'siteName',
|
||||
'title',
|
||||
'description',
|
||||
'duration',
|
||||
]),
|
||||
photo: photo && photo instanceof GramJs.Photo
|
||||
? {
|
||||
id: String(photo.id),
|
||||
thumbnail: buildApiThumbnailFromStripped(photo.sizes),
|
||||
sizes: photo.sizes
|
||||
.filter((s: any): s is GramJs.PhotoSize => s instanceof GramJs.PhotoSize)
|
||||
.map(buildApiPhotoSize),
|
||||
}
|
||||
: undefined,
|
||||
// TODO support video and embed
|
||||
...(document && { hasDocument: true }),
|
||||
photo: photo instanceof GramJs.Photo ? buildApiPhoto(photo) : undefined,
|
||||
document: !video && document ? buildApiDocument(document) : undefined,
|
||||
video,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -292,7 +292,12 @@ export function isMessageWithMedia(message: GramJs.Message | GramJs.UpdateServic
|
||||
|| (
|
||||
media instanceof GramJs.MessageMediaWebPage
|
||||
&& media.webpage instanceof GramJs.WebPage
|
||||
&& media.webpage.photo instanceof GramJs.Photo
|
||||
&& (
|
||||
media.webpage.photo instanceof GramJs.Photo || (
|
||||
media.webpage.document instanceof GramJs.Document
|
||||
&& media.webpage.document.mimeType.startsWith('video')
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -22,6 +22,15 @@ export function addMessageToLocalDb(message: GramJs.Message | GramJs.MessageServ
|
||||
localDb.documents[String(message.media.document.id)] = message.media.document;
|
||||
}
|
||||
|
||||
if (
|
||||
message instanceof GramJs.Message
|
||||
&& message.media instanceof GramJs.MessageMediaWebPage
|
||||
&& message.media.webpage instanceof GramJs.WebPage
|
||||
&& message.media.webpage.document instanceof GramJs.Document
|
||||
) {
|
||||
localDb.documents[String(message.media.webpage.document.id)] = message.media.webpage.document;
|
||||
}
|
||||
|
||||
if (message instanceof GramJs.MessageService && 'photo' in message.action) {
|
||||
addPhotoToLocalDb(message.action.photo);
|
||||
}
|
||||
|
@ -145,6 +145,11 @@ async function download(
|
||||
if (entity.media instanceof GramJs.MessageMediaDocument && entity.media.document instanceof GramJs.Document) {
|
||||
fullSize = entity.media.document.size;
|
||||
}
|
||||
if (entity.media instanceof GramJs.MessageMediaWebPage
|
||||
&& entity.media.webpage instanceof GramJs.WebPage
|
||||
&& entity.media.webpage.document instanceof GramJs.Document) {
|
||||
fullSize = entity.media.webpage.document.size;
|
||||
}
|
||||
} else if (entity instanceof GramJs.Photo) {
|
||||
mimeType = 'image/jpeg';
|
||||
} else if (entityType === 'sticker' && sizeType) {
|
||||
@ -187,6 +192,12 @@ function getMessageMediaMimeType(message: GramJs.Message, sizeType?: string) {
|
||||
return message.media.document!.mimeType;
|
||||
}
|
||||
|
||||
if (message.media instanceof GramJs.MessageMediaWebPage
|
||||
&& message.media.webpage instanceof GramJs.WebPage
|
||||
&& message.media.webpage.document instanceof GramJs.Document) {
|
||||
return message.media.webpage.document.mimeType;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
@ -152,11 +152,14 @@ export interface ApiWebPage {
|
||||
id: number;
|
||||
url: string;
|
||||
displayUrl: string;
|
||||
type?: string;
|
||||
siteName?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
photo?: ApiPhoto;
|
||||
hasDocument?: true;
|
||||
duration?: number;
|
||||
document?: ApiDocument;
|
||||
video?: ApiVideo;
|
||||
}
|
||||
|
||||
export interface ApiMessageForwardInfo {
|
||||
|
@ -9,7 +9,7 @@
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
&.without-photo::before {
|
||||
&.without-media::before {
|
||||
content: attr(data-initial);
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
@ -86,7 +86,7 @@
|
||||
padding: .25rem 3.75rem 0 0;
|
||||
|
||||
.Media,
|
||||
&.without-photo::before {
|
||||
&.without-media::before {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
|
@ -57,13 +57,14 @@ const WebLink: FC<OwnProps> = ({ message, senderTitle, onMessageClick }) => {
|
||||
title,
|
||||
description,
|
||||
photo,
|
||||
video,
|
||||
} = linkData;
|
||||
|
||||
const truncatedDescription = !senderTitle && trimText(description, MAX_TEXT_LENGTH);
|
||||
|
||||
const className = buildClassName(
|
||||
'WebLink scroll-item',
|
||||
!photo && 'without-photo',
|
||||
(!photo && !video) && 'without-media',
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -37,6 +37,7 @@ import {
|
||||
getMessagePhoto,
|
||||
getMessageVideo,
|
||||
getMessageWebPagePhoto,
|
||||
getMessageWebPageVideo,
|
||||
getPhotoFullDimensions,
|
||||
getVideoDimensions,
|
||||
IDimensions,
|
||||
@ -107,12 +108,15 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
|
||||
const animationKey = useRef<number>(null);
|
||||
const isOpen = Boolean(avatarOwner || messageId);
|
||||
const webPagePhoto = message ? getMessageWebPagePhoto(message) : undefined;
|
||||
const webPageVideo = message ? getMessageWebPageVideo(message) : undefined;
|
||||
const photo = message ? getMessagePhoto(message) : undefined;
|
||||
const video = message ? getMessageVideo(message) : undefined;
|
||||
const isWebPagePhoto = Boolean(webPagePhoto);
|
||||
const isPhoto = Boolean(photo || webPagePhoto);
|
||||
const isVideo = Boolean(video);
|
||||
const isGif = video ? video.isGif : undefined;
|
||||
const isWebPageVideo = Boolean(webPageVideo);
|
||||
const messageVideo = video || webPageVideo;
|
||||
const isVideo = Boolean(messageVideo);
|
||||
const isPhoto = Boolean(!isVideo && (photo || webPagePhoto));
|
||||
const isGif = (messageVideo) ? messageVideo.isGif : undefined;
|
||||
const isFromSharedMedia = origin === MediaViewerOrigin.SharedMedia;
|
||||
const isFromSearch = origin === MediaViewerOrigin.SearchResult;
|
||||
const slideAnimation = animationLevel >= 1 ? 'mv-slide' : 'none';
|
||||
@ -129,10 +133,10 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
|
||||
const [isFooterHidden, setIsFooterHidden] = useState<boolean>(false);
|
||||
|
||||
const messageIds = useMemo(() => {
|
||||
return isWebPagePhoto && messageId
|
||||
return (isWebPagePhoto || isWebPageVideo) && messageId
|
||||
? [messageId]
|
||||
: getChatMediaMessageIds(chatMessages || {}, collectionIds || [], isFromSharedMedia);
|
||||
}, [isWebPagePhoto, messageId, chatMessages, collectionIds, isFromSharedMedia]);
|
||||
}, [isWebPagePhoto, isWebPageVideo, messageId, chatMessages, collectionIds, isFromSharedMedia]);
|
||||
|
||||
const selectedMediaMessageIndex = messageId ? messageIds.indexOf(messageId) : -1;
|
||||
const isFirst = selectedMediaMessageIndex === 0 || selectedMediaMessageIndex === -1;
|
||||
@ -185,9 +189,11 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
|
||||
}
|
||||
|
||||
const photoDimensions = isPhoto ? getPhotoFullDimensions((
|
||||
isWebPagePhoto ? getMessageWebPagePhoto(message!) : getMessagePhoto(message!)
|
||||
isWebPagePhoto ? webPagePhoto : photo
|
||||
)!) : undefined;
|
||||
const videoDimensions = isVideo ? getVideoDimensions((
|
||||
isWebPageVideo ? webPageVideo : video
|
||||
)!) : undefined;
|
||||
const videoDimensions = isVideo ? getVideoDimensions(getMessageVideo(message!)!) : undefined;
|
||||
|
||||
useEffect(() => {
|
||||
if (!IS_SINGLE_COLUMN_LAYOUT) {
|
||||
@ -436,7 +442,7 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
|
||||
posterData={bestImageData}
|
||||
posterSize={message && calculateMediaViewerDimensions(videoDimensions!, hasFooter, true)}
|
||||
downloadProgress={downloadProgress}
|
||||
fileSize={video!.size}
|
||||
fileSize={messageVideo!.size}
|
||||
isMediaViewerOpen={isOpen}
|
||||
noPlay={!isActive}
|
||||
onClose={close}
|
||||
|
@ -2,7 +2,13 @@ import { ApiMessage } from '../../../api/types';
|
||||
import { MediaViewerOrigin } from '../../../types';
|
||||
|
||||
import { ANIMATION_END_DELAY } from '../../../config';
|
||||
import { getMessageContent, getPhotoFullDimensions, getVideoDimensions } from '../../../modules/helpers';
|
||||
import {
|
||||
getMessageContent,
|
||||
getMessageWebPagePhoto,
|
||||
getMessageWebPageVideo,
|
||||
getPhotoFullDimensions,
|
||||
getVideoDimensions,
|
||||
} from '../../../modules/helpers';
|
||||
import {
|
||||
AVATAR_FULL_DIMENSIONS,
|
||||
calculateDimensions,
|
||||
@ -28,9 +34,13 @@ export function animateOpening(
|
||||
let isVideo = false;
|
||||
let mediaSize;
|
||||
if (message) {
|
||||
const { photo, video, webPage } = getMessageContent(message);
|
||||
isVideo = Boolean(video);
|
||||
mediaSize = video ? getVideoDimensions(video)! : getPhotoFullDimensions((photo || webPage!.photo)!)!;
|
||||
const { photo, video } = getMessageContent(message);
|
||||
const webPagePhoto = getMessageWebPagePhoto(message);
|
||||
const webPageVideo = getMessageWebPageVideo(message);
|
||||
isVideo = Boolean(video || webPageVideo);
|
||||
mediaSize = isVideo
|
||||
? getVideoDimensions((video || webPageVideo)!)!
|
||||
: getPhotoFullDimensions((photo || webPagePhoto)!)!;
|
||||
} else {
|
||||
mediaSize = AVATAR_FULL_DIMENSIONS;
|
||||
}
|
||||
|
@ -39,6 +39,10 @@
|
||||
bottom: .05rem;
|
||||
}
|
||||
|
||||
&.with-video .media-inner { // TODO add support for video in previews in composer
|
||||
display: none;
|
||||
}
|
||||
|
||||
.site-title,
|
||||
.site-description {
|
||||
flex: 1;
|
||||
|
@ -667,6 +667,8 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
observeIntersection={observeIntersectionForMedia}
|
||||
noAvatars={noAvatars}
|
||||
shouldAutoLoad={shouldAutoLoadMedia}
|
||||
shouldAutoPlay={shouldAutoPlayMedia}
|
||||
lastSyncTime={lastSyncTime}
|
||||
onMediaClick={handleMediaClick}
|
||||
onCancelMediaTransfer={handleCancelUpload}
|
||||
/>
|
||||
|
@ -9,10 +9,11 @@ import { formatMediaDuration } from '../../../util/dateFormat';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import { calculateVideoDimensions } from '../../common/helpers/mediaDimensions';
|
||||
import {
|
||||
canMessagePlayVideoInline,
|
||||
getMediaTransferState,
|
||||
getMessageMediaFormat,
|
||||
getMessageMediaHash,
|
||||
getMessageVideo,
|
||||
getMessageWebPageVideo,
|
||||
isForwardedMessage,
|
||||
isOwnMessage,
|
||||
} from '../../../modules/helpers';
|
||||
@ -62,9 +63,8 @@ const Video: FC<OwnProps> = ({
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
|
||||
const video = message.content.video!;
|
||||
const video = (getMessageVideo(message) || getMessageWebPageVideo(message))!;
|
||||
const localBlobUrl = video.blobUrl;
|
||||
const canPlayInline = Boolean(localBlobUrl) || canMessagePlayVideoInline(video);
|
||||
|
||||
const isIntersecting = useIsIntersecting(ref, observeIntersection);
|
||||
|
||||
@ -87,13 +87,13 @@ const Video: FC<OwnProps> = ({
|
||||
);
|
||||
|
||||
const fullMediaData = localBlobUrl || mediaData;
|
||||
const isInline = Boolean(canPlayInline && isIntersecting && fullMediaData);
|
||||
const isInline = Boolean(isIntersecting && fullMediaData);
|
||||
|
||||
const { isBuffered, bufferingHandlers } = useBuffering(!shouldAutoLoad);
|
||||
const { isUploading, isTransferring, transferProgress } = getMediaTransferState(
|
||||
message,
|
||||
uploadProgress || downloadProgress,
|
||||
shouldDownload && (canPlayInline && !isBuffered),
|
||||
shouldDownload && !isBuffered,
|
||||
);
|
||||
const wasDownloadDisabled = usePrevious(isDownloadAllowed) === false;
|
||||
const {
|
||||
@ -107,6 +107,8 @@ const Video: FC<OwnProps> = ({
|
||||
setPlayProgress(Math.max(0, e.currentTarget.currentTime - 1));
|
||||
}, []);
|
||||
|
||||
const duration = video.duration || (videoRef.current && videoRef.current.duration) || 0;
|
||||
|
||||
const isOwn = isOwnMessage(message);
|
||||
const isForwarded = isForwardedMessage(message);
|
||||
const { width, height } = dimensions || calculateVideoDimensions(video, isOwn, isForwarded, noAvatars);
|
||||
@ -122,15 +124,15 @@ const Video: FC<OwnProps> = ({
|
||||
if (onCancelUpload) {
|
||||
onCancelUpload(message);
|
||||
}
|
||||
} else if (canPlayInline && !fullMediaData) {
|
||||
} else if (!fullMediaData) {
|
||||
setIsDownloadAllowed((isAllowed) => !isAllowed);
|
||||
} else if (canPlayInline && fullMediaData && !isPlayAllowed) {
|
||||
} else if (fullMediaData && !isPlayAllowed) {
|
||||
setIsPlayAllowed(true);
|
||||
videoRef.current!.play();
|
||||
} else if (onClick) {
|
||||
onClick(message.id);
|
||||
}
|
||||
}, [isUploading, canPlayInline, fullMediaData, isPlayAllowed, onClick, onCancelUpload, message]);
|
||||
}, [isUploading, fullMediaData, isPlayAllowed, onClick, onCancelUpload, message]);
|
||||
|
||||
const className = buildClassName('media-inner dark', !isUploading && 'interactive');
|
||||
const videoClassName = buildClassName('full-media', transitionClassNames);
|
||||
@ -140,9 +142,8 @@ const Video: FC<OwnProps> = ({
|
||||
: '';
|
||||
|
||||
const shouldRenderInlineVideo = isInline;
|
||||
const shouldRenderHqPreview = !canPlayInline && mediaData;
|
||||
const shouldRenderPlayButton = !canPlayInline || (isDownloadAllowed && !isPlayAllowed && !shouldRenderSpinner);
|
||||
const shouldRenderDownloadButton = canPlayInline && !isDownloadAllowed;
|
||||
const shouldRenderPlayButton = (isDownloadAllowed && !isPlayAllowed && !shouldRenderSpinner);
|
||||
const shouldRenderDownloadButton = !isDownloadAllowed;
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -189,15 +190,6 @@ const Video: FC<OwnProps> = ({
|
||||
<source src={fullMediaData} />
|
||||
</video>
|
||||
)}
|
||||
{shouldRenderHqPreview && (
|
||||
<img
|
||||
src={mediaData}
|
||||
className={`full-media ${transitionClassNames}`}
|
||||
width={width}
|
||||
height={height}
|
||||
alt=""
|
||||
/>
|
||||
)}
|
||||
{shouldRenderPlayButton && (
|
||||
<i className="icon-large-play" />
|
||||
)}
|
||||
@ -209,13 +201,11 @@ const Video: FC<OwnProps> = ({
|
||||
{shouldRenderDownloadButton && (
|
||||
<i className="icon-download" />
|
||||
)}
|
||||
{isTransferring && !canPlayInline ? (
|
||||
<span className="message-upload-progress">{Math.round(transferProgress * 100)}%</span>
|
||||
) : isTransferring && canPlayInline ? (
|
||||
{isTransferring ? (
|
||||
<span className="message-upload-progress">...</span>
|
||||
) : (
|
||||
<div className="message-media-duration">
|
||||
{video.isGif ? 'GIF' : formatMediaDuration(video.duration - playProgress)}
|
||||
{video.isGif ? 'GIF' : formatMediaDuration(Math.max(duration - playProgress, 0))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -46,6 +46,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.with-video .media-inner{
|
||||
margin-top: 0.5rem !important;
|
||||
margin-bottom: 1rem !important;
|
||||
}
|
||||
|
||||
&.with-square-photo {
|
||||
display: flex;
|
||||
margin-bottom: 1rem;
|
||||
|
@ -11,6 +11,7 @@ import buildClassName from '../../../util/buildClassName';
|
||||
|
||||
import SafeLink from '../../common/SafeLink';
|
||||
import Photo from './Photo';
|
||||
import Video from './Video';
|
||||
|
||||
import './WebPage.scss';
|
||||
|
||||
@ -21,7 +22,9 @@ type OwnProps = {
|
||||
observeIntersection?: ObserveFn;
|
||||
noAvatars?: boolean;
|
||||
shouldAutoLoad?: boolean;
|
||||
shouldAutoPlay?: boolean;
|
||||
inPreview?: boolean;
|
||||
lastSyncTime?: number;
|
||||
onMediaClick?: () => void;
|
||||
onCancelMediaTransfer?: () => void;
|
||||
};
|
||||
@ -31,7 +34,9 @@ const WebPage: FC<OwnProps> = ({
|
||||
observeIntersection,
|
||||
noAvatars,
|
||||
shouldAutoLoad,
|
||||
shouldAutoPlay,
|
||||
inPreview,
|
||||
lastSyncTime,
|
||||
onMediaClick,
|
||||
onCancelMediaTransfer,
|
||||
}) => {
|
||||
@ -58,16 +63,16 @@ const WebPage: FC<OwnProps> = ({
|
||||
title,
|
||||
description,
|
||||
photo,
|
||||
video,
|
||||
} = webPage;
|
||||
|
||||
const isMediaInteractive = photo && onMediaClick && !isSquarePhoto && !webPage.hasDocument;
|
||||
const isMediaInteractive = (photo || video) && onMediaClick && !isSquarePhoto;
|
||||
const truncatedDescription = trimText(description, MAX_TEXT_LENGTH);
|
||||
|
||||
const className = buildClassName(
|
||||
'WebPage',
|
||||
photo
|
||||
? (isSquarePhoto && 'with-square-photo')
|
||||
: (!inPreview && 'without-photo'),
|
||||
isSquarePhoto && 'with-square-photo',
|
||||
!photo && !video && !inPreview && 'without-media',
|
||||
video && 'with-video',
|
||||
);
|
||||
|
||||
return (
|
||||
@ -76,7 +81,7 @@ const WebPage: FC<OwnProps> = ({
|
||||
data-initial={(siteName || displayUrl)[0]}
|
||||
dir="auto"
|
||||
>
|
||||
{photo && (
|
||||
{photo && !video && (
|
||||
<Photo
|
||||
message={message}
|
||||
observeIntersection={observeIntersection}
|
||||
@ -97,6 +102,18 @@ const WebPage: FC<OwnProps> = ({
|
||||
<p className="site-description">{renderText(truncatedDescription, ['emoji', 'br'])}</p>
|
||||
)}
|
||||
</div>
|
||||
{!inPreview && video && (
|
||||
<Video
|
||||
message={message}
|
||||
observeIntersection={observeIntersection!}
|
||||
noAvatars={noAvatars}
|
||||
shouldAutoLoad={shouldAutoLoad}
|
||||
shouldAutoPlay={shouldAutoPlay}
|
||||
lastSyncTime={lastSyncTime}
|
||||
onClick={isMediaInteractive ? handleMediaClick : undefined}
|
||||
onCancelUpload={onCancelMediaTransfer}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -313,7 +313,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.message-content.media {
|
||||
.message-content.media, .WebPage {
|
||||
.media-inner {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -65,7 +65,7 @@ export function buildContentClassName(
|
||||
} else if (webPage) {
|
||||
classNames.push('web-page');
|
||||
|
||||
if (webPage.photo) {
|
||||
if (webPage.photo || webPage.video) {
|
||||
classNames.push('media');
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ export type IDimensions = {
|
||||
|
||||
type Target = 'micro' | 'pictogram' | 'inline' | 'viewerPreview' | 'viewerFull' | 'download';
|
||||
|
||||
const MAX_INLINE_VIDEO_SIZE = 10 * 1024 ** 2; // 10 MB
|
||||
|
||||
export function getMessageContent(message: ApiMessage) {
|
||||
return message.content;
|
||||
@ -88,12 +87,24 @@ export function getMessageWebPagePhoto(message: ApiMessage) {
|
||||
return webPage ? webPage.photo : undefined;
|
||||
}
|
||||
|
||||
export function getMessageWebPageDocument(message: ApiMessage) {
|
||||
const webPage = getMessageWebPage(message);
|
||||
return webPage ? webPage.document : undefined;
|
||||
}
|
||||
|
||||
export function getMessageWebPageVideo(message: ApiMessage): ApiVideo | undefined {
|
||||
const webPage = getMessageWebPage(message);
|
||||
if (!webPage) return undefined;
|
||||
return webPage.video;
|
||||
}
|
||||
|
||||
export function getMessageMediaThumbnail(message: ApiMessage) {
|
||||
const media = getMessagePhoto(message)
|
||||
|| getMessageVideo(message)
|
||||
|| getMessageDocument(message)
|
||||
|| getMessageSticker(message)
|
||||
|| getMessageWebPagePhoto(message);
|
||||
|| getMessageWebPagePhoto(message)
|
||||
|| getMessageWebPageVideo(message);
|
||||
|
||||
if (!media) {
|
||||
return undefined;
|
||||
@ -116,32 +127,34 @@ export function getMessageMediaHash(
|
||||
photo, video, sticker, audio, voice, document,
|
||||
} = message.content;
|
||||
const webPagePhoto = getMessageWebPagePhoto(message);
|
||||
const webPageVideo = getMessageWebPageVideo(message);
|
||||
|
||||
if (!(photo || video || sticker || webPagePhoto || audio || voice || document)) {
|
||||
const messageVideo = video || webPageVideo;
|
||||
const messagePhoto = photo || webPagePhoto;
|
||||
|
||||
if (!(messagePhoto || messageVideo || sticker || audio || voice || document)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const base = getMessageKey(message);
|
||||
|
||||
if (photo || webPagePhoto) {
|
||||
if (messageVideo) {
|
||||
switch (target) {
|
||||
case 'micro':
|
||||
case 'pictogram':
|
||||
return `${base}?size=m`;
|
||||
case 'inline':
|
||||
if (hasMessageLocalBlobUrl(message)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return `${base}?size=x`;
|
||||
return !hasMessageLocalBlobUrl(message) ? getVideoOrAudioBaseHash(messageVideo, base) : undefined;
|
||||
case 'viewerPreview':
|
||||
return `${base}?size=x`;
|
||||
return `${base}?size=m`;
|
||||
case 'viewerFull':
|
||||
return `${base}?size=z`;
|
||||
return getVideoOrAudioBaseHash(messageVideo, base);
|
||||
case 'download':
|
||||
return `${base}?download`;
|
||||
}
|
||||
}
|
||||
|
||||
if (video) {
|
||||
if (messagePhoto) {
|
||||
switch (target) {
|
||||
case 'micro':
|
||||
case 'pictogram':
|
||||
@ -151,17 +164,11 @@ export function getMessageMediaHash(
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (canMessagePlayVideoInline(video)) {
|
||||
return getVideoOrAudioBaseHash(video, base);
|
||||
}
|
||||
|
||||
return `${base}?size=z`;
|
||||
return `${base}?size=x`;
|
||||
case 'viewerPreview':
|
||||
return `${base}?size=m`;
|
||||
return `${base}?size=x`;
|
||||
case 'viewerFull':
|
||||
return getVideoOrAudioBaseHash(video, base);
|
||||
case 'download':
|
||||
return `${base}?download`;
|
||||
return `${base}?size=z`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,10 +242,12 @@ export function getMessageMediaFormat(
|
||||
sticker, video, audio, voice,
|
||||
} = message.content;
|
||||
|
||||
const fullVideo = video || getMessageWebPageVideo(message);
|
||||
|
||||
if (sticker && target === 'inline' && sticker.isAnimated) {
|
||||
return ApiMediaFormat.Lottie;
|
||||
} else if (video && IS_PROGRESSIVE_SUPPORTED && (
|
||||
(target === 'viewerFull') || (target === 'inline' && canMessagePlayVideoInline(video))
|
||||
} else if (fullVideo && IS_PROGRESSIVE_SUPPORTED && (
|
||||
target === 'viewerFull' || target === 'inline'
|
||||
)) {
|
||||
return ApiMediaFormat.Progressive;
|
||||
} else if (audio || voice) {
|
||||
@ -254,12 +263,18 @@ export function getMessageMediaFormat(
|
||||
}
|
||||
|
||||
export function getMessageMediaFilename(message: ApiMessage) {
|
||||
const { photo, video, webPage } = message.content;
|
||||
const { photo, video } = message.content;
|
||||
const webPagePhoto = getMessageWebPagePhoto(message);
|
||||
const webPageVideo = getMessageWebPageVideo(message);
|
||||
|
||||
if (photo || (webPage && webPage.photo)) {
|
||||
if (photo || webPagePhoto) {
|
||||
return `photo${message.date}.jpeg`;
|
||||
}
|
||||
|
||||
if (webPageVideo) {
|
||||
return webPageVideo.fileName;
|
||||
}
|
||||
|
||||
if (video) {
|
||||
return video.fileName;
|
||||
}
|
||||
@ -273,10 +288,6 @@ export function hasMessageLocalBlobUrl(message: ApiMessage) {
|
||||
return (photo && photo.blobUrl) || (video && video.blobUrl) || (document && document.previewBlobUrl);
|
||||
}
|
||||
|
||||
export function canMessagePlayVideoInline(video: ApiVideo): boolean {
|
||||
return video.isGif || video.isRound || video.size <= MAX_INLINE_VIDEO_SIZE;
|
||||
}
|
||||
|
||||
export function getChatMediaMessageIds(
|
||||
messages: Record<number, ApiMessage>, listedIds: number[], reverseOrder = false,
|
||||
) {
|
||||
@ -360,7 +371,7 @@ export function getMessageContentIds(
|
||||
|
||||
export function getMediaDuration(message: ApiMessage) {
|
||||
const { audio, voice, video } = getMessageContent(message);
|
||||
const media = audio || voice || video;
|
||||
const media = audio || voice || video || getMessageWebPageVideo(message);
|
||||
if (!media) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import {
|
||||
isChatGroup,
|
||||
isChatSuperGroup,
|
||||
getMessageVideo,
|
||||
getMessageWebPageVideo,
|
||||
} from '../helpers';
|
||||
import { findLast } from '../../util/iteratees';
|
||||
import { selectIsStickerFavorite } from './symbols';
|
||||
@ -679,7 +680,7 @@ export function selectShouldAutoLoadMedia(
|
||||
}
|
||||
|
||||
export function selectShouldAutoPlayMedia(global: GlobalState, message: ApiMessage) {
|
||||
const video = getMessageVideo(message);
|
||||
const video = getMessageVideo(message) || getMessageWebPageVideo(message);
|
||||
if (!video) {
|
||||
return undefined;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user