"use client";
import Image from "next/image";
import Link from "next/link";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Separator } from "@/components/ui/separator";
import { Skeleton } from "@/components/ui/skeleton";
import {
Tooltip,
TooltipContent,
TooltipPortal,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import {
isBookmarkStillCrawling,
isBookmarkStillLoading,
} from "@/lib/bookmarkUtils";
import { api } from "@/lib/trpc";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import { CalendarDays, ExternalLink } from "lucide-react";
import Markdown from "react-markdown";
import type { ZBookmark } from "@hoarder/trpc/types/bookmarks";
import { TagsEditor } from "./TagsEditor";
dayjs.extend(relativeTime);
function ContentLoading() {
return (
);
}
function CreationTime({ createdAt }: { createdAt: Date }) {
return (
{dayjs(createdAt).fromNow()}
{createdAt.toLocaleString()}
);
}
function LinkHeader({ bookmark }: { bookmark: ZBookmark }) {
if (bookmark.content.type !== "link") {
throw new Error("Unexpected content type");
}
const title = bookmark.content.title ?? bookmark.content.url;
return (
{title}
{title}
View Original
);
}
function TextContentSection({ bookmark }: { bookmark: ZBookmark }) {
let content;
switch (bookmark.content.type) {
case "link": {
if (!bookmark.content.htmlContent) {
content = (
Failed to fetch link content ...
);
} else {
content = (
);
}
break;
}
case "text": {
content = (
{bookmark.content.text}
);
break;
}
}
return {content};
}
function AssetContentSection({ bookmark }: { bookmark: ZBookmark }) {
if (bookmark.content.type != "asset") {
throw new Error("Invalid content type");
}
let content;
switch (bookmark.content.assetType) {
case "image": {
switch (bookmark.content.assetType) {
case "image": {
content = (
);
}
}
break;
}
}
return content;
}
export default function BookmarkPreview({
initialData,
}: {
initialData: ZBookmark;
}) {
const { data: bookmark } = api.bookmarks.getBookmark.useQuery(
{
bookmarkId: initialData.id,
},
{
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;
},
},
);
let content;
switch (bookmark.content.type) {
case "link":
case "text": {
content = ;
break;
}
case "asset": {
content = ;
break;
}
}
const linkHeader = bookmark.content.type == "link" && (
);
return (