import { ArchivedFormat, CollectionIncludingMembersAndLinkCount, LinkIncludingShortenedCollectionAndTags, } from "@/types/global"; import { useEffect, useMemo, useRef, useState } from "react"; import useLinkStore from "@/store/links"; import unescapeString from "@/lib/client/unescapeString"; import LinkActions from "@/components/LinkViews/LinkComponents/LinkActions"; import LinkDate from "@/components/LinkViews/LinkComponents/LinkDate"; import LinkCollection from "@/components/LinkViews/LinkComponents/LinkCollection"; import Image from "next/image"; import { previewAvailable } from "@/lib/shared/getArchiveValidity"; import LinkIcon from "./LinkIcon"; import useOnScreen from "@/hooks/useOnScreen"; import { generateLinkHref } from "@/lib/client/generateLinkHref"; import usePermissions from "@/hooks/usePermissions"; import toast from "react-hot-toast"; import LinkTypeBadge from "./LinkTypeBadge"; import { useTranslation } from "next-i18next"; import { useCollections } from "@/hooks/store/collections"; import { useUser } from "@/hooks/store/user"; import { useGetLink, useLinks } from "@/hooks/store/links"; import { useRouter } from "next/router"; import useLocalSettingsStore from "@/store/localSettings"; import LinkPin from "./LinkPin"; type Props = { link: LinkIncludingShortenedCollectionAndTags; count: number; columns: number; className?: string; editMode?: boolean; }; export default function LinkCard({ link, columns, editMode }: Props) { const { t } = useTranslation(); const heightMap = { 1: "h-44", 2: "h-40", 3: "h-36", 4: "h-32", 5: "h-28", 6: "h-24", 7: "h-20", 8: "h-20", }; const imageHeightClass = useMemo( () => (columns ? heightMap[columns as keyof typeof heightMap] : "h-40"), [columns] ); const { data: collections = [] } = useCollections(); const { data: user = {} } = useUser(); const { setSelectedLinks, selectedLinks } = useLinkStore(); const { settings: { show }, } = useLocalSettingsStore(); const { data: { data: links = [] }, } = useLinks(); const getLink = useGetLink(); useEffect(() => { if (!editMode) { setSelectedLinks([]); } }, [editMode]); const handleCheckboxClick = ( link: LinkIncludingShortenedCollectionAndTags ) => { if (selectedLinks.includes(link)) { setSelectedLinks(selectedLinks.filter((e) => e !== link)); } else { setSelectedLinks([...selectedLinks, link]); } }; let shortendURL; try { if (link.url) { shortendURL = new URL(link.url).host.toLowerCase(); } } catch (error) { console.log(error); } const [collection, setCollection] = useState( collections.find( (e) => e.id === link.collection.id ) as CollectionIncludingMembersAndLinkCount ); useEffect(() => { setCollection( collections.find( (e) => e.id === link.collection.id ) as CollectionIncludingMembersAndLinkCount ); }, [collections, links]); const ref = useRef(null); const isVisible = useOnScreen(ref); const permissions = usePermissions(collection?.id as number); const router = useRouter(); const isPublicRoute = router.pathname.startsWith("/public") ? true : false; useEffect(() => { let interval: NodeJS.Timeout | null = null; if ( isVisible && !link.preview?.startsWith("archives") && link.preview !== "unavailable" ) { interval = setInterval(async () => { getLink.mutateAsync({ id: link.id as number, isPublicRoute: isPublicRoute, }); }, 5000); } return () => { if (interval) { clearInterval(interval); } }; }, [isVisible, link.preview]); const selectedStyle = selectedLinks.some( (selectedLink) => selectedLink.id === link.id ) ? "border-primary bg-base-300" : "border-neutral-content"; const selectable = editMode && (permissions === true || permissions?.canCreate || permissions?.canDelete); return (
selectable ? handleCheckboxClick(link) : editMode ? toast.error(t("link_selection_error")) : undefined } >
!editMode && window.open(generateLinkHref(link, user), "_blank") } > {show.image && (
{previewAvailable(link) ? ( { const target = e.target as HTMLElement; target.style.display = "none"; }} /> ) : link.preview === "unavailable" ? (
) : (
)} {show.icon && (
)}

)}
{show.name && (

{unescapeString(link.name)}

)} {show.link && }
{(show.collection || show.date) && (

{show.collection && !isPublicRoute && (
)} {show.date && }
)}
{/* Overlay on hover */}
{!isPublicRoute && }
); }