diff --git a/package.json b/package.json index baadeee2f..7e9052d42 100644 --- a/package.json +++ b/package.json @@ -145,6 +145,7 @@ "react-hook-form": "~5.6.0", "react-icons": "^4.4.0", "react-infinite-scroll-component": "^6.1.0", + "react-lite-youtube-embed": "^2.4.0", "react-markdown": "6.0.3", "react-redux": "^7.2.0", "react-responsive": "^8.2.0", diff --git a/src/components/posts/embed/Embed.module.sass b/src/components/posts/embed/Embed.module.sass index 2ecb46c05..995533c21 100644 --- a/src/components/posts/embed/Embed.module.sass +++ b/src/components/posts/embed/Embed.module.sass @@ -4,3 +4,44 @@ width: 100% height: 384px box-shadow: $shadow + +.YoutubeEmbedIframe + width: 100% + height: 100% + position: absolute + +.YoutubeEmbedWrapper + position: absolute + top: 0 + left: 0 + width: 100% + height: 100% + background-position: center + + .YoutubeEmbedPlayer + position: absolute + border: none + cursor: pointer + background: red + border-radius: 1em + width: 5rem + height: 3.5rem + top: 50% + left: 50% + transform: translate(-50%, -50%) + + &:before + content: "" + position: absolute + left: 50% + top: 50% + transform: translate(-50%, -50%) + border-top: 11px solid transparent + border-right: 0px solid transparent + border-bottom: 11px solid transparent + border-left: 19px solid white + + &:global(.youtube-activated) + .YoutubeEmbedPlayer + display: none + \ No newline at end of file diff --git a/src/components/posts/embed/Embed.tsx b/src/components/posts/embed/Embed.tsx index e89ec501c..489deef0c 100644 --- a/src/components/posts/embed/Embed.tsx +++ b/src/components/posts/embed/Embed.tsx @@ -1,11 +1,20 @@ import clsx from 'clsx' +import { useMemo } from 'react' +import LiteYouTubeEmbed from 'react-lite-youtube-embed' +import styles from './Embed.module.sass' type EmbedProps = { link: string className?: string } -const allowEmbedList = ['vimeo', 'youtube', 'youtu.be', 'soundcloud'] +const allowEmbedList = ['vimeo', 'youtube', 'youtu.be', 'soundcloud'] as const +const componentMap: { + [key in (typeof allowEmbedList)[number]]?: (props: { src: string }) => JSX.Element | null +} = { + 'youtu.be': YoutubeEmbed, + youtube: YoutubeEmbed, +} const getEmbedUrl = (url: string, embed: string | undefined) => { if (!embed) return @@ -25,6 +34,9 @@ const Embed = ({ link, className }: EmbedProps) => { const embed = allowEmbedList.find(embed => link.includes(embed)) const src = getEmbedUrl(link, embed) + if (!src) return null + let Component = componentMap[embed as (typeof allowEmbedList)[number]] || GeneralEmbed + return ( <> {src && ( @@ -38,21 +50,60 @@ const Embed = ({ link, className }: EmbedProps) => { overflow: 'hidden', }} > -