diff --git a/package-lock.json b/package-lock.json
index 938dd44..70d7cb0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -37,6 +37,7 @@
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"react-syntax-highlighter": "^15.5.0",
+ "react-youtube": "^10.1.0",
"readable-web-to-node-stream": "^3.0.2",
"remark-gfm": "^3.0.1",
"sass": "^1.54.3",
@@ -17606,6 +17607,11 @@
"split": "^1.0.1"
}
},
+ "node_modules/load-script": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz",
+ "integrity": "sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA=="
+ },
"node_modules/loader-runner": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
@@ -22462,6 +22468,22 @@
"react-dom": ">=16.6.0"
}
},
+ "node_modules/react-youtube": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/react-youtube/-/react-youtube-10.1.0.tgz",
+ "integrity": "sha512-ZfGtcVpk0SSZtWCSTYOQKhfx5/1cfyEW1JN/mugGNfAxT3rmVJeMbGpA9+e78yG21ls5nc/5uZJETE3cm3knBg==",
+ "dependencies": {
+ "fast-deep-equal": "3.1.3",
+ "prop-types": "15.8.1",
+ "youtube-player": "5.5.2"
+ },
+ "engines": {
+ "node": ">= 14.x"
+ },
+ "peerDependencies": {
+ "react": ">=0.14.1"
+ }
+ },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -23815,6 +23837,11 @@
"ws": "^7.4.2"
}
},
+ "node_modules/sister": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/sister/-/sister-3.0.2.tgz",
+ "integrity": "sha512-p19rtTs+NksBRKW9qn0UhZ8/TUI9BPw9lmtHny+Y3TinWlOa9jWh9xB0AtPSdmOy49NJJJSSe0Ey4C7h0TrcYA=="
+ },
"node_modules/sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@@ -26912,6 +26939,29 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/youtube-player": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/youtube-player/-/youtube-player-5.5.2.tgz",
+ "integrity": "sha512-ZGtsemSpXnDky2AUYWgxjaopgB+shFHgXVpiJFeNB5nWEugpW1KWYDaHKuLqh2b67r24GtP6HoSW5swvf0fFIQ==",
+ "dependencies": {
+ "debug": "^2.6.6",
+ "load-script": "^1.0.0",
+ "sister": "^3.0.0"
+ }
+ },
+ "node_modules/youtube-player/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/youtube-player/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
"node_modules/zwitch": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.2.tgz",
@@ -39915,6 +39965,11 @@
"split": "^1.0.1"
}
},
+ "load-script": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz",
+ "integrity": "sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA=="
+ },
"loader-runner": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
@@ -43220,6 +43275,16 @@
"prop-types": "^15.6.2"
}
},
+ "react-youtube": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/react-youtube/-/react-youtube-10.1.0.tgz",
+ "integrity": "sha512-ZfGtcVpk0SSZtWCSTYOQKhfx5/1cfyEW1JN/mugGNfAxT3rmVJeMbGpA9+e78yG21ls5nc/5uZJETE3cm3knBg==",
+ "requires": {
+ "fast-deep-equal": "3.1.3",
+ "prop-types": "15.8.1",
+ "youtube-player": "5.5.2"
+ }
+ },
"read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -44194,6 +44259,11 @@
"ws": "^7.4.2"
}
},
+ "sister": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/sister/-/sister-3.0.2.tgz",
+ "integrity": "sha512-p19rtTs+NksBRKW9qn0UhZ8/TUI9BPw9lmtHny+Y3TinWlOa9jWh9xB0AtPSdmOy49NJJJSSe0Ey4C7h0TrcYA=="
+ },
"sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@@ -46496,6 +46566,31 @@
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
},
+ "youtube-player": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/youtube-player/-/youtube-player-5.5.2.tgz",
+ "integrity": "sha512-ZGtsemSpXnDky2AUYWgxjaopgB+shFHgXVpiJFeNB5nWEugpW1KWYDaHKuLqh2b67r24GtP6HoSW5swvf0fFIQ==",
+ "requires": {
+ "debug": "^2.6.6",
+ "load-script": "^1.0.0",
+ "sister": "^3.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ }
+ }
+ },
"zwitch": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.2.tgz",
diff --git a/package.json b/package.json
index 9832315..0ec2f9e 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"react-syntax-highlighter": "^15.5.0",
+ "react-youtube": "^10.1.0",
"readable-web-to-node-stream": "^3.0.2",
"remark-gfm": "^3.0.1",
"sass": "^1.54.3",
diff --git a/src/components/Message/Message.tsx b/src/components/Message/Message.tsx
index de8f05f..796b1cf 100644
--- a/src/components/Message/Message.tsx
+++ b/src/components/Message/Message.tsx
@@ -1,4 +1,5 @@
import { HTMLAttributes } from 'react'
+import YouTube from 'react-youtube'
import Box from '@mui/material/Box'
import Tooltip from '@mui/material/Tooltip'
import Typography, { TypographyProps } from '@mui/material/Typography'
@@ -81,6 +82,20 @@ const componentMap = {
const spaceNeededForSideDateTooltip = 850
+const getYouTubeVideoId = (videoUrl: string) => {
+ const trimmedMessage = videoUrl.trim()
+
+ const matchArray =
+ trimmedMessage.match(/https:\/\/www.youtube.com\/watch\?v=(\S{8,})$/) ||
+ trimmedMessage.match(/https:\/\/youtu.be\/(\S{8,})$/)
+
+ return matchArray?.pop()
+}
+
+const isYouTubeLink = (message: IMessage) => {
+ return typeof getYouTubeVideoId(message.text) === 'string'
+}
+
export const Message = ({ message, showAuthor, userId }: MessageProps) => {
let backgroundColor: string
@@ -131,6 +146,8 @@ export const Message = ({ message, showAuthor, userId }: MessageProps) => {
>
{isInlineMedia(message) ? (
+ ) : isYouTubeLink(message) ? (
+
) : (