WebPage: Render preview and audio document (#4345)
This commit is contained in:
parent
70dfa2e160
commit
f8bcd32865
@ -216,6 +216,39 @@ export function buildVideoFromDocument(document: GramJs.Document, isSpoiler?: bo
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildAudioFromDocument(document: GramJs.Document): ApiAudio | undefined {
|
||||||
|
if (document instanceof GramJs.DocumentEmpty) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
id, mimeType, size, attributes,
|
||||||
|
} = document;
|
||||||
|
|
||||||
|
const audioAttributes = attributes
|
||||||
|
.find((a: any): a is GramJs.DocumentAttributeAudio => a instanceof GramJs.DocumentAttributeAudio);
|
||||||
|
|
||||||
|
if (!audioAttributes) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
duration,
|
||||||
|
title,
|
||||||
|
performer,
|
||||||
|
} = audioAttributes;
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: String(id),
|
||||||
|
mimeType,
|
||||||
|
duration,
|
||||||
|
fileName: getFilenameFromDocument(document, 'audio'),
|
||||||
|
title,
|
||||||
|
performer,
|
||||||
|
size: size.toJSNumber(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function buildVideo(media: GramJs.TypeMessageMedia): ApiVideo | undefined {
|
function buildVideo(media: GramJs.TypeMessageMedia): ApiVideo | undefined {
|
||||||
if (
|
if (
|
||||||
!(media instanceof GramJs.MessageMediaDocument)
|
!(media instanceof GramJs.MessageMediaDocument)
|
||||||
@ -653,9 +686,13 @@ export function buildWebPage(media: GramJs.TypeMessageMedia): ApiWebPage | undef
|
|||||||
} = media.webpage;
|
} = media.webpage;
|
||||||
|
|
||||||
let video;
|
let video;
|
||||||
|
let audio;
|
||||||
if (document instanceof GramJs.Document && document.mimeType.startsWith('video/')) {
|
if (document instanceof GramJs.Document && document.mimeType.startsWith('video/')) {
|
||||||
video = buildVideoFromDocument(document);
|
video = buildVideoFromDocument(document);
|
||||||
}
|
}
|
||||||
|
if (document instanceof GramJs.Document && document.mimeType.startsWith('audio/')) {
|
||||||
|
audio = buildAudioFromDocument(document);
|
||||||
|
}
|
||||||
let story: ApiWebPageStoryData | undefined;
|
let story: ApiWebPageStoryData | undefined;
|
||||||
const attributeStory = attributes
|
const attributeStory = attributes
|
||||||
?.find((a: any): a is GramJs.WebPageAttributeStory => a instanceof GramJs.WebPageAttributeStory);
|
?.find((a: any): a is GramJs.WebPageAttributeStory => a instanceof GramJs.WebPageAttributeStory);
|
||||||
@ -683,8 +720,9 @@ export function buildWebPage(media: GramJs.TypeMessageMedia): ApiWebPage | undef
|
|||||||
'duration',
|
'duration',
|
||||||
]),
|
]),
|
||||||
photo: photo instanceof GramJs.Photo ? buildApiPhoto(photo) : undefined,
|
photo: photo instanceof GramJs.Photo ? buildApiPhoto(photo) : undefined,
|
||||||
document: !video && document ? buildApiDocument(document) : undefined,
|
document: !video && !audio && document ? buildApiDocument(document) : undefined,
|
||||||
video,
|
video,
|
||||||
|
audio,
|
||||||
story,
|
story,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -329,6 +329,7 @@ export interface ApiWebPage {
|
|||||||
title?: string;
|
title?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
photo?: ApiPhoto;
|
photo?: ApiPhoto;
|
||||||
|
audio?: ApiAudio;
|
||||||
duration?: number;
|
duration?: number;
|
||||||
document?: ApiDocument;
|
document?: ApiDocument;
|
||||||
video?: ApiVideo;
|
video?: ApiVideo;
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import {
|
|||||||
getMediaTransferState,
|
getMediaTransferState,
|
||||||
getMessageMediaFormat,
|
getMessageMediaFormat,
|
||||||
getMessageMediaHash,
|
getMessageMediaHash,
|
||||||
|
getMessageWebPageAudio,
|
||||||
hasMessageTtl,
|
hasMessageTtl,
|
||||||
isMessageLocal,
|
isMessageLocal,
|
||||||
isOwnMessage,
|
isOwnMessage,
|
||||||
@ -67,7 +68,7 @@ type OwnProps = {
|
|||||||
isTranscriptionError?: boolean;
|
isTranscriptionError?: boolean;
|
||||||
autoPlay?: boolean;
|
autoPlay?: boolean;
|
||||||
onHideTranscription?: (isHidden: boolean) => void;
|
onHideTranscription?: (isHidden: boolean) => void;
|
||||||
onPlay: (messageId: number, chatId: string) => void;
|
onPlay?: (messageId: number, chatId: string) => void;
|
||||||
onPause?: NoneToVoidFunction;
|
onPause?: NoneToVoidFunction;
|
||||||
onReadMedia?: () => void;
|
onReadMedia?: () => void;
|
||||||
onCancelUpload?: () => void;
|
onCancelUpload?: () => void;
|
||||||
@ -112,9 +113,10 @@ const Audio: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
content: {
|
content: {
|
||||||
audio, voice, video,
|
audio: contentAudio, voice, video,
|
||||||
}, isMediaUnread,
|
}, isMediaUnread,
|
||||||
} = message;
|
} = message;
|
||||||
|
const audio = contentAudio || getMessageWebPageAudio(message);
|
||||||
const isVoice = Boolean(voice || video);
|
const isVoice = Boolean(voice || video);
|
||||||
const isSeeking = useRef<boolean>(false);
|
const isSeeking = useRef<boolean>(false);
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
@ -145,7 +147,7 @@ const Audio: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const handleForcePlay = useLastCallback(() => {
|
const handleForcePlay = useLastCallback(() => {
|
||||||
setIsActivated(true);
|
setIsActivated(true);
|
||||||
onPlay(message.id, message.chatId);
|
onPlay?.(message.id, message.chatId);
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleTrackChange = useLastCallback(() => {
|
const handleTrackChange = useLastCallback(() => {
|
||||||
@ -228,7 +230,7 @@ const Audio: FC<OwnProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isPlaying) {
|
if (!isPlaying) {
|
||||||
onPlay(message.id, message.chatId);
|
onPlay?.(message.id, message.chatId);
|
||||||
}
|
}
|
||||||
|
|
||||||
getActions().setAudioPlayerOrigin({ origin });
|
getActions().setAudioPlayerOrigin({ origin });
|
||||||
|
|||||||
@ -642,7 +642,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.has-replies:not(.custom-shape),
|
&.has-replies:not(.custom-shape),
|
||||||
&.text {
|
&.text:not(.web-page) {
|
||||||
.media-inner,
|
.media-inner,
|
||||||
.Album {
|
.Album {
|
||||||
--border-bottom-left-radius: 0;
|
--border-bottom-left-radius: 0;
|
||||||
|
|||||||
@ -1228,6 +1228,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
backgroundEmojiId={sender?.color?.backgroundEmojiId}
|
backgroundEmojiId={sender?.color?.backgroundEmojiId}
|
||||||
shouldWarnAboutSvg={shouldWarnAboutSvg}
|
shouldWarnAboutSvg={shouldWarnAboutSvg}
|
||||||
autoLoadFileMaxSizeMb={autoLoadFileMaxSizeMb}
|
autoLoadFileMaxSizeMb={autoLoadFileMaxSizeMb}
|
||||||
|
onAudioPlay={handleAudioPlay}
|
||||||
onMediaClick={handleMediaClick}
|
onMediaClick={handleMediaClick}
|
||||||
onCancelMediaTransfer={handleCancelUpload}
|
onCancelMediaTransfer={handleCancelUpload}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -9,6 +9,10 @@
|
|||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.with-video {
|
||||||
|
padding: 0.1875rem 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
&.with-document {
|
&.with-document {
|
||||||
--file-icon-border-color: var(--accent-background-color);
|
--file-icon-border-color: var(--accent-background-color);
|
||||||
@ -77,13 +81,15 @@
|
|||||||
|
|
||||||
.media-inner {
|
.media-inner {
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
margin-bottom: 0.375rem !important;
|
|
||||||
|
|
||||||
&,
|
&,
|
||||||
& img,
|
& img,
|
||||||
& canvas,
|
& canvas,
|
||||||
&.small-image img {
|
&.small-image img {
|
||||||
border-radius: var(--border-radius-messages-small) !important;
|
--border-top-left-radius: var(--border-radius-messages-small);
|
||||||
|
--border-top-right-radius: var(--border-radius-messages-small);
|
||||||
|
--border-bottom-left-radius: var(--border-radius-messages-small);
|
||||||
|
--border-bottom-right-radius: var(--border-radius-messages-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.square-image {
|
&.square-image {
|
||||||
@ -100,11 +106,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.with-video .media-inner {
|
|
||||||
margin-top: 0.5rem !important;
|
|
||||||
margin-bottom: 1rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-content:not(.has-reactions) & {
|
.message-content:not(.has-reactions) & {
|
||||||
margin-bottom: calc(var(--message-meta-height)) !important;
|
margin-bottom: calc(var(--message-meta-height)) !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { getActions } from '../../../global';
|
|||||||
|
|
||||||
import type { ApiMessage, ApiTypeStory } from '../../../api/types';
|
import type { ApiMessage, ApiTypeStory } from '../../../api/types';
|
||||||
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||||
import type { ISettings } from '../../../types';
|
import { AudioOrigin, type ISettings } from '../../../types';
|
||||||
|
|
||||||
import { getMessageWebPage } from '../../../global/helpers';
|
import { getMessageWebPage } from '../../../global/helpers';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
@ -18,6 +18,7 @@ import useEnsureStory from '../../../hooks/useEnsureStory';
|
|||||||
import useLang from '../../../hooks/useLang';
|
import useLang from '../../../hooks/useLang';
|
||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
|
|
||||||
|
import Audio from '../../common/Audio';
|
||||||
import Document from '../../common/Document';
|
import Document from '../../common/Document';
|
||||||
import EmojiIconBackground from '../../common/embedded/EmojiIconBackground';
|
import EmojiIconBackground from '../../common/embedded/EmojiIconBackground';
|
||||||
import SafeLink from '../../common/SafeLink';
|
import SafeLink from '../../common/SafeLink';
|
||||||
@ -47,8 +48,9 @@ type OwnProps = {
|
|||||||
story?: ApiTypeStory;
|
story?: ApiTypeStory;
|
||||||
shouldWarnAboutSvg?: boolean;
|
shouldWarnAboutSvg?: boolean;
|
||||||
autoLoadFileMaxSizeMb?: number;
|
autoLoadFileMaxSizeMb?: number;
|
||||||
onMediaClick?: () => void;
|
onAudioPlay?: NoneToVoidFunction;
|
||||||
onCancelMediaTransfer?: () => void;
|
onMediaClick?: NoneToVoidFunction;
|
||||||
|
onCancelMediaTransfer?: NoneToVoidFunction;
|
||||||
};
|
};
|
||||||
|
|
||||||
const WebPage: FC<OwnProps> = ({
|
const WebPage: FC<OwnProps> = ({
|
||||||
@ -68,6 +70,7 @@ const WebPage: FC<OwnProps> = ({
|
|||||||
shouldWarnAboutSvg,
|
shouldWarnAboutSvg,
|
||||||
autoLoadFileMaxSizeMb,
|
autoLoadFileMaxSizeMb,
|
||||||
onMediaClick,
|
onMediaClick,
|
||||||
|
onAudioPlay,
|
||||||
onCancelMediaTransfer,
|
onCancelMediaTransfer,
|
||||||
}) => {
|
}) => {
|
||||||
const { openTelegramLink } = getActions();
|
const { openTelegramLink } = getActions();
|
||||||
@ -103,6 +106,7 @@ const WebPage: FC<OwnProps> = ({
|
|||||||
description,
|
description,
|
||||||
photo,
|
photo,
|
||||||
video,
|
video,
|
||||||
|
audio,
|
||||||
type,
|
type,
|
||||||
document,
|
document,
|
||||||
} = webPage;
|
} = webPage;
|
||||||
@ -200,6 +204,17 @@ const WebPage: FC<OwnProps> = ({
|
|||||||
onCancelUpload={onCancelMediaTransfer}
|
onCancelUpload={onCancelMediaTransfer}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{!inPreview && audio && (
|
||||||
|
<Audio
|
||||||
|
theme={theme}
|
||||||
|
message={message}
|
||||||
|
origin={AudioOrigin.Inline}
|
||||||
|
noAvatars={noAvatars}
|
||||||
|
isDownloading={isDownloading}
|
||||||
|
onPlay={onAudioPlay}
|
||||||
|
onCancelUpload={onCancelMediaTransfer}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{!inPreview && document && (
|
{!inPreview && document && (
|
||||||
<Document
|
<Document
|
||||||
message={message}
|
message={message}
|
||||||
@ -211,6 +226,18 @@ const WebPage: FC<OwnProps> = ({
|
|||||||
shouldWarnAboutSvg={shouldWarnAboutSvg}
|
shouldWarnAboutSvg={shouldWarnAboutSvg}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{inPreview && displayUrl && !isArticle && (
|
||||||
|
<div className="WebPage-text">
|
||||||
|
{backgroundEmojiId && (
|
||||||
|
<EmojiIconBackground
|
||||||
|
emojiDocumentId={backgroundEmojiId}
|
||||||
|
className="WebPage--background-icons"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<p className="site-name">{displayUrl}</p>
|
||||||
|
<p className="site-description">{lang('Chat.Empty.LinkPreview')}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{quickButtonLangKey && renderQuickButton(quickButtonLangKey)}
|
{quickButtonLangKey && renderQuickButton(quickButtonLangKey)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -155,6 +155,10 @@ export function getMessageWebPageVideo(message: MediaContainer) {
|
|||||||
return getMessageWebPage(message)?.video;
|
return getMessageWebPage(message)?.video;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getMessageWebPageAudio(message: MediaContainer) {
|
||||||
|
return getMessageWebPage(message)?.audio;
|
||||||
|
}
|
||||||
|
|
||||||
export function getMessageDocumentVideo(message: MediaContainer) {
|
export function getMessageDocumentVideo(message: MediaContainer) {
|
||||||
return isMessageDocumentVideo(message) ? getMessageDocument(message) : undefined;
|
return isMessageDocumentVideo(message) ? getMessageDocument(message) : undefined;
|
||||||
}
|
}
|
||||||
@ -218,8 +222,9 @@ export function getMessageMediaHash(
|
|||||||
const actionPhoto = getMessageActionPhoto(message);
|
const actionPhoto = getMessageActionPhoto(message);
|
||||||
const messageVideo = video || getMessageWebPageVideo(message) || getMessageDocumentVideo(message);
|
const messageVideo = video || getMessageWebPageVideo(message) || getMessageDocumentVideo(message);
|
||||||
const messageDocument = document || getMessageWebPageDocument(message);
|
const messageDocument = document || getMessageWebPageDocument(message);
|
||||||
|
const messageAudio = audio || getMessageWebPageAudio(message);
|
||||||
|
|
||||||
const content = actionPhoto || messagePhoto || messageVideo || sticker || audio || voice || messageDocument;
|
const content = actionPhoto || messagePhoto || messageVideo || sticker || messageAudio || voice || messageDocument;
|
||||||
if (!content) {
|
if (!content) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -288,13 +293,13 @@ export function getMessageMediaHash(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audio) {
|
if (messageAudio) {
|
||||||
switch (target) {
|
switch (target) {
|
||||||
case 'micro':
|
case 'micro':
|
||||||
case 'pictogram':
|
case 'pictogram':
|
||||||
return getAudioHasCover(audio) ? `${base}?size=m` : undefined;
|
return getAudioHasCover(messageAudio) ? `${base}?size=m` : undefined;
|
||||||
case 'inline':
|
case 'inline':
|
||||||
return getVideoOrAudioBaseHash(audio, base);
|
return getVideoOrAudioBaseHash(messageAudio, base);
|
||||||
case 'download':
|
case 'download':
|
||||||
return `${base}?download`;
|
return `${base}?download`;
|
||||||
}
|
}
|
||||||
@ -517,7 +522,7 @@ export function getMessageContentIds(
|
|||||||
|
|
||||||
export function getMediaDuration(message: ApiMessage) {
|
export function getMediaDuration(message: ApiMessage) {
|
||||||
const { audio, voice, video } = getMessageContent(message);
|
const { audio, voice, video } = getMessageContent(message);
|
||||||
const media = audio || voice || video || getMessageWebPageVideo(message);
|
const media = audio || voice || video || getMessageWebPageVideo(message) || getMessageWebPageAudio(message);
|
||||||
if (!media) {
|
if (!media) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user