"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
)}
);
}