"use client"; import Image from "next/image"; import Link from "next/link"; import { api } from "@/lib/trpc"; import type { ZBookmarkTypeLink } from "@hoarder/shared/types/bookmarks"; import { getBookmarkLinkImageUrl, isBookmarkStillCrawling, isBookmarkStillLoading, } from "@hoarder/shared-react/utils/bookmarkUtils"; import { BookmarkLayoutAdaptingCard } from "./BookmarkLayoutAdaptingCard"; function LinkTitle({ bookmark }: { bookmark: ZBookmarkTypeLink }) { const link = bookmark.content; const parsedUrl = new URL(link.url); return ( {bookmark.title ?? link?.title ?? parsedUrl.host} ); } function LinkImage({ bookmark, className, }: { bookmark: ZBookmarkTypeLink; className?: string; }) { const link = bookmark.content; const imgComponent = (url: string, unoptimized: boolean) => ( card banner ); const imageDetails = getBookmarkLinkImageUrl(link); let img: React.ReactNode = null; if (isBookmarkStillCrawling(bookmark)) { img = imgComponent("/blur.avif", false); } else if (imageDetails) { img = imgComponent(imageDetails.url, !imageDetails.localAsset); } else { // No image found // A dummy white pixel for when there's no image. img = imgComponent( "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAA1JREFUGFdj+P///38ACfsD/QVDRcoAAAAASUVORK5CYII=", true, ); } return (
{img}
); } function LinkUrl({ bookmark }: { bookmark: ZBookmarkTypeLink }) { const link = bookmark.content; const parsedUrl = new URL(link.url); return ( {parsedUrl.host} ); } export default function LinkCard({ bookmark: initialData, className, }: { bookmark: ZBookmarkTypeLink; className?: string; }) { 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; }, }, ); if (bookmark.content.type !== "link") { throw new Error("Invalid bookmark type"); } const bookmarkLink = { ...bookmark, content: bookmark.content }; return ( } footer={} bookmark={bookmarkLink} wrapTags={false} image={(_layout, className) => ( )} className={className} /> ); }