"use client"; import { useEffect, useState } from "react"; import Link from "next/link"; import { TagsEditor } from "@/components/dashboard/bookmarks/TagsEditor"; import { FullPageSpinner } from "@/components/ui/full-page-spinner"; import { Separator } from "@/components/ui/separator"; import { Skeleton } from "@/components/ui/skeleton"; import { Tooltip, TooltipContent, TooltipPortal, TooltipTrigger, } from "@/components/ui/tooltip"; import { api } from "@/lib/trpc"; import dayjs from "dayjs"; import relativeTime from "dayjs/plugin/relativeTime"; import { CalendarDays, ExternalLink } from "lucide-react"; import type { ZBookmark } from "@hoarder/shared/types/bookmarks"; import { isBookmarkStillCrawling, isBookmarkStillLoading, } from "@hoarder/shared-react/utils/bookmarkUtils"; import ActionBar from "./ActionBar"; import { AssetContentSection } from "./AssetContentSection"; import { EditableTitle } from "./EditableTitle"; import LinkContentSection from "./LinkContentSection"; import { NoteEditor } from "./NoteEditor"; import { TextContentSection } from "./TextContentSection"; dayjs.extend(relativeTime); function ContentLoading() { return (
); } function CreationTime({ createdAt }: { createdAt: Date }) { const [fromNow, setFromNow] = useState(""); const [localCreatedAt, setLocalCreatedAt] = useState(""); // This is to avoid hydration errors when server and clients are in different timezones useEffect(() => { setFromNow(dayjs(createdAt).fromNow()); setLocalCreatedAt(createdAt.toLocaleString()); }, [createdAt]); return ( {fromNow} {localCreatedAt} ); } function getSourceUrl(bookmark: ZBookmark) { if (bookmark.content.type === "link") { return bookmark.content.url; } if (bookmark.content.type === "asset") { return bookmark.content.sourceUrl; } return null; } export default function BookmarkPreview({ bookmarkId, initialData, }: { bookmarkId: string; initialData?: ZBookmark; }) { const { data: bookmark } = api.bookmarks.getBookmark.useQuery( { bookmarkId, }, { initialData, refetchInterval: (query) => { const data = query.state.data; if (!data) { return false; } // If the link is not crawled or not tagged if (isBookmarkStillLoading(data)) { return 1000; } return false; }, }, ); if (!bookmark) { return ; } let content; switch (bookmark.content.type) { case "link": { content = ; break; } case "text": { content = ; break; } case "asset": { content = ; break; } } const sourceUrl = getSourceUrl(bookmark); return (
{isBookmarkStillCrawling(bookmark) ? : content}
{sourceUrl && ( View Original )}

Tags

Note

); }