aboutsummaryrefslogtreecommitdiffstats
path: root/apps/web/components/dashboard/preview/content-renderers/XRenderer.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/XRenderer.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/XRenderer.tsx')
-rw-r--r--apps/web/components/dashboard/preview/content-renderers/XRenderer.tsx58
1 files changed, 58 insertions, 0 deletions
diff --git a/apps/web/components/dashboard/preview/content-renderers/XRenderer.tsx b/apps/web/components/dashboard/preview/content-renderers/XRenderer.tsx
new file mode 100644
index 00000000..e3e43843
--- /dev/null
+++ b/apps/web/components/dashboard/preview/content-renderers/XRenderer.tsx
@@ -0,0 +1,58 @@
+import { MessageSquare } from "lucide-react";
+import { Tweet } from "react-tweet";
+
+import { BookmarkTypes, ZBookmark } from "@karakeep/shared/types/bookmarks";
+
+import { ContentRenderer } from "./types";
+
+function extractTweetId(url: string): string | null {
+ const patterns = [
+ /(?:twitter\.com|x\.com)\/\w+\/status\/(\d+)/,
+ /(?:twitter\.com|x\.com)\/i\/web\/status\/(\d+)/,
+ ];
+
+ for (const pattern of patterns) {
+ const match = url.match(pattern);
+ if (match) {
+ return match[1];
+ }
+ }
+ return null;
+}
+
+function canRenderX(bookmark: ZBookmark): boolean {
+ if (bookmark.content.type !== BookmarkTypes.LINK) {
+ return false;
+ }
+
+ const url = bookmark.content.url;
+ return extractTweetId(url) !== null;
+}
+
+function XRendererComponent({ bookmark }: { bookmark: ZBookmark }) {
+ if (bookmark.content.type !== BookmarkTypes.LINK) {
+ return null;
+ }
+
+ const tweetId = extractTweetId(bookmark.content.url);
+ if (!tweetId) {
+ return null;
+ }
+
+ return (
+ <div className="relative h-full w-full overflow-auto">
+ <div className="flex justify-center p-4">
+ <Tweet id={tweetId} />
+ </div>
+ </div>
+ );
+}
+
+export const xRenderer: ContentRenderer = {
+ id: "x",
+ name: "X (Twitter)",
+ icon: MessageSquare,
+ canRender: canRenderX,
+ component: XRendererComponent,
+ priority: 10,
+};