diff --git a/apps/web/components/document-cards/tweet-preview.tsx b/apps/web/components/document-cards/tweet-preview.tsx index 807ba5b9a..77e90971c 100644 --- a/apps/web/components/document-cards/tweet-preview.tsx +++ b/apps/web/components/document-cards/tweet-preview.tsx @@ -1,6 +1,6 @@ "use client" -import { Suspense } from "react" +import { Suspense, useMemo } from "react" import type { Tweet } from "react-tweet/api" import { TweetBody, enrichTweet, TweetSkeleton } from "react-tweet" import { cn } from "@lib/utils" @@ -117,14 +117,52 @@ function CustomTweetMedia({ ) } +function isTweetLike(value: unknown): value is Tweet { + return ( + typeof value === "object" && + value !== null && + !Array.isArray(value) && + "user" in value + ) +} + +function parseTweetData(data: Tweet | string): Tweet | null { + if (!data) return null + if (typeof data !== "string") return isTweetLike(data) ? data : null + try { + const parsed: unknown = JSON.parse(data) + if (isTweetLike(parsed)) return parsed + console.warn("TweetPreview: parsed value did not match Tweet shape") + return null + } catch (error) { + console.warn("TweetPreview: failed to parse tweet data", error) + return null + } +} + +function TweetPreviewFallback({ noBgColor }: { noBgColor?: boolean }) { + return ( +