Made compontent more generic and replaced link finder function
This commit is contained in:
parent
522ca5beda
commit
7733baef00
2 changed files with 122 additions and 53 deletions
|
@ -16,6 +16,7 @@ import PlaySVG from '../../../../public/res/ic/outlined/play.svg';
|
||||||
|
|
||||||
import { getBlobSafeMimeType } from '../../../util/mimetypes';
|
import { getBlobSafeMimeType } from '../../../util/mimetypes';
|
||||||
import initMatrix from '../../../client/initMatrix';
|
import initMatrix from '../../../client/initMatrix';
|
||||||
|
import settings from '../../../client/state/settings';
|
||||||
|
|
||||||
async function getDecryptedBlob(response, type, decryptData) {
|
async function getDecryptedBlob(response, type, decryptData) {
|
||||||
const arrayBuffer = await response.arrayBuffer();
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
|
@ -362,23 +363,106 @@ Video.propTypes = {
|
||||||
blurhash: PropTypes.string,
|
blurhash: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
function YoutubeEmbed({ link }) {
|
function IframePlayer({
|
||||||
const url = new URL(link);
|
children, link, sitename, title, thumbnail,
|
||||||
|
}) {
|
||||||
const [urlPreviewInfo, setUrlPreviewInfo] = useState(null);
|
|
||||||
const [videoStarted, setVideoStarted] = useState(false);
|
const [videoStarted, setVideoStarted] = useState(false);
|
||||||
|
|
||||||
const mx = initMatrix.matrixClient;
|
|
||||||
|
|
||||||
const handlePlayVideo = () => {
|
const handlePlayVideo = () => {
|
||||||
setVideoStarted(true);
|
setVideoStarted(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="file-container">
|
||||||
|
<div className="file-header">
|
||||||
|
<Text className="file-name" variant="b3">{`${sitename} - ${title}`}</Text>
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
size="extra-small"
|
||||||
|
tooltip="Open in new tab"
|
||||||
|
src={ExternalSVG}
|
||||||
|
onClick={() => window.open(link)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className="video-container"
|
||||||
|
>
|
||||||
|
{!videoStarted && <img src={thumbnail} alt={`${sitename} thumbnail`} />}
|
||||||
|
{!videoStarted && <IconButton onClick={handlePlayVideo} tooltip="Play video" src={PlaySVG} />}
|
||||||
|
|
||||||
|
{videoStarted && (
|
||||||
|
<div>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
IframePlayer.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
link: PropTypes.string.isRequired,
|
||||||
|
sitename: PropTypes.string.isRequired,
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
thumbnail: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
function Embed({ link }) {
|
||||||
|
const url = new URL(link);
|
||||||
|
|
||||||
|
if (settings.showYoutubeEmbedPlayer && (((url.host === 'www.youtube.com' || url.host === 'youtube.com') && url.pathname === '/watch') || url.host === 'youtu.be' || url.host === 'www.youtu.be')) {
|
||||||
|
return <YoutubeEmbed link={link} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: url preview
|
||||||
|
// const [urlPreviewInfo, setUrlPreviewInfo] = useState(null);
|
||||||
|
// const mx = initMatrix.matrixClient;
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// let unmounted = false;
|
||||||
|
|
||||||
|
// async function getThumbnail() {
|
||||||
|
// const info = await mx.getUrlPreview(link, 0);
|
||||||
|
// console.log('DEBUG', info);
|
||||||
|
// if (unmounted) return;
|
||||||
|
|
||||||
|
// setUrlPreviewInfo(info);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// getThumbnail();
|
||||||
|
|
||||||
|
// return () => {
|
||||||
|
// unmounted = true;
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (urlPreviewInfo !== null) {
|
||||||
|
// return <div>url preview here!/div>;
|
||||||
|
// }
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Embed.propTypes = {
|
||||||
|
link: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
function YoutubeEmbed({ link }) {
|
||||||
|
const [urlPreviewInfo, setUrlPreviewInfo] = useState(null);
|
||||||
|
const mx = initMatrix.matrixClient;
|
||||||
|
const url = new URL(link);
|
||||||
|
|
||||||
|
// fix for no embed information on www.youtu.be
|
||||||
|
if (url.host === 'www.youtu.be') {
|
||||||
|
url.host = 'youtu.be';
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let unmounted = false;
|
let unmounted = false;
|
||||||
|
|
||||||
async function getThumbnail() {
|
async function getThumbnail() {
|
||||||
const info = await mx.getUrlPreview(link, 0);
|
const info = await mx.getUrlPreview(url.toString(), 0);
|
||||||
if (unmounted) return;
|
if (unmounted) return;
|
||||||
|
|
||||||
setUrlPreviewInfo(info);
|
setUrlPreviewInfo(info);
|
||||||
|
@ -391,54 +475,38 @@ function YoutubeEmbed({ link }) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
let embedURL = `https://www.youtube-nocookie.com/embed/${url.searchParams.get('v')}?autoplay=1`;
|
let videoID;
|
||||||
if (url.searchParams.has('t')) {
|
if (url.host === 'youtu.be' || url.host === 'www.youtu.be') {
|
||||||
|
videoID = url.pathname.slice(1);
|
||||||
|
} else {
|
||||||
|
videoID = url.searchParams.get('v');
|
||||||
|
}
|
||||||
|
|
||||||
|
let embedURL = `https://www.youtube-nocookie.com/embed/${videoID}?autoplay=1`;
|
||||||
|
if (url.searchParams.has('t')) { // timestamp flag
|
||||||
embedURL += `&start=${url.searchParams.get('t')}`;
|
embedURL += `&start=${url.searchParams.get('t')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
if (urlPreviewInfo !== null) {
|
||||||
<div className="file-container">
|
return (
|
||||||
{urlPreviewInfo !== null && (
|
<IframePlayer link={link} sitename="Youtube" title={urlPreviewInfo['og:title']} thumbnail={mx.mxcUrlToHttp(urlPreviewInfo['og:image'])}>
|
||||||
<div>
|
<iframe
|
||||||
|
src={embedURL}
|
||||||
|
title="YouTube video player"
|
||||||
|
frameBorder="0"
|
||||||
|
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
|
||||||
|
allowFullScreen
|
||||||
|
/>
|
||||||
|
</IframePlayer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
<div className="file-header">
|
return null;
|
||||||
<Text className="file-name" variant="b3">{`Youtube - ${urlPreviewInfo['og:title']}`}</Text>
|
|
||||||
|
|
||||||
<IconButton
|
|
||||||
size="extra-small"
|
|
||||||
tooltip="Open in new tab"
|
|
||||||
src={ExternalSVG}
|
|
||||||
onClick={() => window.open(link)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="video-container"
|
|
||||||
>
|
|
||||||
{!videoStarted && <img src={mx.mxcUrlToHttp(urlPreviewInfo['og:image'])} alt="Youtube thumbnail" />}
|
|
||||||
{!videoStarted && <IconButton onClick={handlePlayVideo} tooltip="Play video" src={PlaySVG} />}
|
|
||||||
|
|
||||||
{videoStarted && (
|
|
||||||
<iframe
|
|
||||||
src={embedURL}
|
|
||||||
title="YouTube video player"
|
|
||||||
frameborder="0"
|
|
||||||
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
|
|
||||||
allowFullScreen
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
YoutubeEmbed.propTypes = {
|
YoutubeEmbed.propTypes = {
|
||||||
link: PropTypes.string.isRequired,
|
link: PropTypes.string.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
File, Image, Sticker, Audio, Video, YoutubeEmbed,
|
File, Image, Sticker, Audio, Video, YoutubeEmbed, Embed, IframePlayer,
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,7 @@ import React, {
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import './Message.scss';
|
import './Message.scss';
|
||||||
|
|
||||||
|
import { find } from 'linkifyjs';
|
||||||
import { twemojify } from '../../../util/twemojify';
|
import { twemojify } from '../../../util/twemojify';
|
||||||
|
|
||||||
import initMatrix from '../../../client/initMatrix';
|
import initMatrix from '../../../client/initMatrix';
|
||||||
|
@ -29,7 +30,6 @@ import IconButton from '../../atoms/button/IconButton';
|
||||||
import Time from '../../atoms/time/Time';
|
import Time from '../../atoms/time/Time';
|
||||||
import ContextMenu, { MenuHeader, MenuItem, MenuBorder } from '../../atoms/context-menu/ContextMenu';
|
import ContextMenu, { MenuHeader, MenuItem, MenuBorder } from '../../atoms/context-menu/ContextMenu';
|
||||||
import * as Media from '../media/Media';
|
import * as Media from '../media/Media';
|
||||||
import settings from '../../../client/state/settings';
|
|
||||||
|
|
||||||
import ReplyArrowIC from '../../../../public/res/ic/outlined/reply-arrow.svg';
|
import ReplyArrowIC from '../../../../public/res/ic/outlined/reply-arrow.svg';
|
||||||
import EmojiAddIC from '../../../../public/res/ic/outlined/emoji-add.svg';
|
import EmojiAddIC from '../../../../public/res/ic/outlined/emoji-add.svg';
|
||||||
|
@ -42,7 +42,7 @@ import BinIC from '../../../../public/res/ic/outlined/bin.svg';
|
||||||
import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
|
import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
|
||||||
import { getBlobSafeMimeType } from '../../../util/mimetypes';
|
import { getBlobSafeMimeType } from '../../../util/mimetypes';
|
||||||
import { html, plain } from '../../../util/markdown';
|
import { html, plain } from '../../../util/markdown';
|
||||||
import { YoutubeEmbed } from '../media/Media';
|
import { Embed } from '../media/Media';
|
||||||
|
|
||||||
function PlaceholderMessage() {
|
function PlaceholderMessage() {
|
||||||
return (
|
return (
|
||||||
|
@ -718,8 +718,9 @@ function getEditedBody(editedMEvent) {
|
||||||
return [parsedContent.body, isCustomHTML, newContent.formatted_body ?? null];
|
return [parsedContent.body, isCustomHTML, newContent.formatted_body ?? null];
|
||||||
}
|
}
|
||||||
|
|
||||||
function findYoutubeLinks(body) {
|
function findLinks(body) {
|
||||||
return [...new Set(body.match(/https?:\/\/(?:www\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)[^ \n]+/g))] ?? [];
|
return find(body, 'url')
|
||||||
|
.filter((v, i, a) => a.findIndex((v2) => (v2.href === v.href)) === i);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Message({
|
function Message({
|
||||||
|
@ -807,8 +808,8 @@ function Message({
|
||||||
isEdited={isEdited}
|
isEdited={isEdited}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{settings.showYoutubeEmbedPlayer && findYoutubeLinks(body).map((link) => (
|
{findLinks(body).map((link) => (
|
||||||
<YoutubeEmbed key={link} link={link} />
|
<Embed key={link.href} link={link.href} />
|
||||||
))}
|
))}
|
||||||
{isEdit && (
|
{isEdit && (
|
||||||
<MessageEdit
|
<MessageEdit
|
||||||
|
|
Loading…
Reference in a new issue