aboutsummaryrefslogtreecommitdiffstats
path: root/apps/web/components/dashboard/preview/content-renderers/YouTubeRenderer.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/components/dashboard/preview/content-renderers/YouTubeRenderer.tsx')
-rw-r--r--apps/web/components/dashboard/preview/content-renderers/YouTubeRenderer.tsx66
1 files changed, 66 insertions, 0 deletions
diff --git a/apps/web/components/dashboard/preview/content-renderers/YouTubeRenderer.tsx b/apps/web/components/dashboard/preview/content-renderers/YouTubeRenderer.tsx
new file mode 100644
index 00000000..992eb71e
--- /dev/null
+++ b/apps/web/components/dashboard/preview/content-renderers/YouTubeRenderer.tsx
@@ -0,0 +1,66 @@
+import { Play } from "lucide-react";
+
+import { BookmarkTypes, ZBookmark } from "@karakeep/shared/types/bookmarks";
+
+import { ContentRenderer } from "./types";
+
+function extractYouTubeVideoId(url: string): string | null {
+ const patterns = [
+ /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/,
+ /youtube\.com\/v\/([^&\n?#]+)/,
+ /youtube\.com\/shorts\/([^&\n?#]+)/,
+ ];
+
+ for (const pattern of patterns) {
+ const match = url.match(pattern);
+ if (match) {
+ return match[1];
+ }
+ }
+ return null;
+}
+
+function canRenderYouTube(bookmark: ZBookmark): boolean {
+ if (bookmark.content.type !== BookmarkTypes.LINK) {
+ return false;
+ }
+
+ const url = bookmark.content.url;
+ return extractYouTubeVideoId(url) !== null;
+}
+
+function YouTubeRendererComponent({ bookmark }: { bookmark: ZBookmark }) {
+ if (bookmark.content.type !== BookmarkTypes.LINK) {
+ return null;
+ }
+
+ const videoId = extractYouTubeVideoId(bookmark.content.url);
+ if (!videoId) {
+ return null;
+ }
+
+ const embedUrl = `https://www.youtube.com/embed/${videoId}`;
+
+ return (
+ <div className="relative h-full w-full overflow-hidden">
+ <div className="absolute inset-0 h-full w-full">
+ <iframe
+ src={embedUrl}
+ title="YouTube video player"
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
+ allowFullScreen
+ className="h-full w-full border-0"
+ />
+ </div>
+ </div>
+ );
+}
+
+export const youTubeRenderer: ContentRenderer = {
+ id: "youtube",
+ name: "YouTube",
+ icon: Play,
+ canRender: canRenderYouTube,
+ component: YouTubeRendererComponent,
+ priority: 10,
+};