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',
}}
>
-
+
)}
>
)
}
+function getYoutubeVideoId(youtubeLink: string) {
+ const regExp = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
+ const match = youtubeLink.match(regExp)
+ if (match && match[2].length == 11) {
+ return match[2]
+ } else {
+ return undefined
+ }
+}
+function YoutubeEmbed({ src }: { src: string }) {
+ const youtubeId = useMemo(() => getYoutubeVideoId(src), [src])
+
+ if (!youtubeId) return null
+
+ return (
+
+ )
+}
+
+function GeneralEmbed({ src }: { src: string }) {
+ return (
+
+ )
+}
+
export default Embed
diff --git a/yarn.lock b/yarn.lock
index 486771efc..6017d08cb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11710,6 +11710,11 @@ react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+react-lite-youtube-embed@^2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/react-lite-youtube-embed/-/react-lite-youtube-embed-2.4.0.tgz#1f56a12be1061d50431444d52d836bd09a1283a2"
+ integrity sha512-Xo6cM1zPlROvvM97JkqQIoXstlQDaC4+DawmM7BB7Hh1cXrkBHEGq1iJlQxBTUWAUklmpcC7ph7qg7CztXtABQ==
+
react-markdown@6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-6.0.3.tgz#625ec767fa321d91801129387e7d31ee0cb99254"