aboutsummaryrefslogtreecommitdiffstats
path: root/apps/web/components/dashboard/preview/content-renderers/TikTokRenderer.tsx
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2025-08-03 23:35:06 -0700
committerMohamedBassem <me@mbassem.com>2025-08-03 23:59:45 -0700
commitc68e5099797d5b49ed6441ce04d7c77105327f73 (patch)
tree296fe5f473f46d802fcf94fa203ca37672112c30 /apps/web/components/dashboard/preview/content-renderers/TikTokRenderer.tsx
parent03aa17200ed80c2978bf496991c6afbb5a04258b (diff)
downloadkarakeep-c68e5099797d5b49ed6441ce04d7c77105327f73.tar.zst
feat(web): Add special cards for specific websites. Fixes #1344
Diffstat (limited to 'apps/web/components/dashboard/preview/content-renderers/TikTokRenderer.tsx')
-rw-r--r--apps/web/components/dashboard/preview/content-renderers/TikTokRenderer.tsx68
1 files changed, 68 insertions, 0 deletions
diff --git a/apps/web/components/dashboard/preview/content-renderers/TikTokRenderer.tsx b/apps/web/components/dashboard/preview/content-renderers/TikTokRenderer.tsx
new file mode 100644
index 00000000..ecd0c956
--- /dev/null
+++ b/apps/web/components/dashboard/preview/content-renderers/TikTokRenderer.tsx
@@ -0,0 +1,68 @@
+import { Video } from "lucide-react";
+
+import { BookmarkTypes, ZBookmark } from "@karakeep/shared/types/bookmarks";
+
+import { ContentRenderer } from "./types";
+
+function extractTikTokVideoId(url: string): string | null {
+ const patterns = [
+ /tiktok\.com\/@[^/]+\/video\/(\d+)/,
+ /tiktok\.com\/t\/([A-Za-z0-9]+)/,
+ /vm\.tiktok\.com\/([A-Za-z0-9]+)/,
+ /tiktok\.com\/v\/(\d+)/,
+ ];
+
+ for (const pattern of patterns) {
+ const match = url.match(pattern);
+ if (match) {
+ return match[1];
+ }
+ }
+ return null;
+}
+
+function canRenderTikTok(bookmark: ZBookmark): boolean {
+ if (bookmark.content.type !== BookmarkTypes.LINK) {
+ return false;
+ }
+
+ const url = bookmark.content.url;
+ return extractTikTokVideoId(url) !== null;
+}
+
+function TikTokRendererComponent({ bookmark }: { bookmark: ZBookmark }) {
+ if (bookmark.content.type !== BookmarkTypes.LINK) {
+ return null;
+ }
+
+ const videoId = extractTikTokVideoId(bookmark.content.url);
+ if (!videoId) {
+ return null;
+ }
+
+ // TikTok embed URL format
+ const embedUrl = `https://www.tiktok.com/embed/v2/${videoId}`;
+
+ return (
+ <div className="relative h-full w-full overflow-hidden">
+ <div className="absolute inset-0 h-full w-full">
+ <iframe
+ src={embedUrl}
+ title="TikTok video"
+ className="h-full w-full border-0"
+ allow="encrypted-media"
+ sandbox="allow-scripts allow-same-origin allow-popups"
+ />
+ </div>
+ </div>
+ );
+}
+
+export const tikTokRenderer: ContentRenderer = {
+ id: "tiktok",
+ name: "TikTok",
+ icon: Video,
+ canRender: canRenderTikTok,
+ component: TikTokRendererComponent,
+ priority: 10,
+};