import React, { useEffect, useState } from "react"; import { LinkIncludingShortenedCollectionAndTags, ArchivedFormat, } from "@/types/global"; import Link from "next/link"; import { pdfAvailable, readabilityAvailable, monolithAvailable, screenshotAvailable, previewAvailable, } from "@/lib/shared/getArchiveValidity"; import PreservedFormatRow from "@/components/PreserverdFormatRow"; import getPublicUserData from "@/lib/client/getPublicUserData"; import { useTranslation } from "next-i18next"; import { BeatLoader } from "react-spinners"; import { useUser } from "@/hooks/store/user"; import { useGetLink, useUpdateLink, useUpdatePreview, } from "@/hooks/store/links"; import LinkIcon from "./LinkViews/LinkComponents/LinkIcon"; import CopyButton from "./CopyButton"; import { useRouter } from "next/router"; import Icon from "./Icon"; import { IconWeight } from "@phosphor-icons/react"; import Image from "next/image"; import clsx from "clsx"; import toast from "react-hot-toast"; import CollectionSelection from "./InputSelect/CollectionSelection"; import TagSelection from "./InputSelect/TagSelection"; import unescapeString from "@/lib/client/unescapeString"; import IconPopover from "./IconPopover"; import TextInput from "./TextInput"; import usePermissions from "@/hooks/usePermissions"; type Props = { className?: string; activeLink: LinkIncludingShortenedCollectionAndTags; standalone?: boolean; mode?: "view" | "edit"; setMode?: Function; }; export default function LinkDetails({ className, activeLink, standalone, mode = "view", setMode, }: Props) { const [link, setLink] = useState(activeLink); useEffect(() => { setLink(activeLink); }, [activeLink]); const permissions = usePermissions(link.collection.id as number); const { t } = useTranslation(); const getLink = useGetLink(); const { data: user = {} } = useUser(); const [collectionOwner, setCollectionOwner] = useState({ id: null as unknown as number, name: "", username: "", image: "", archiveAsScreenshot: undefined as unknown as boolean, archiveAsMonolith: undefined as unknown as boolean, archiveAsPDF: undefined as unknown as boolean, }); useEffect(() => { const fetchOwner = async () => { if (link.collection.ownerId !== user.id) { const owner = await getPublicUserData( link.collection.ownerId as number ); setCollectionOwner(owner); } else if (link.collection.ownerId === user.id) { setCollectionOwner({ id: user.id as number, name: user.name, username: user.username as string, image: user.image as string, archiveAsScreenshot: user.archiveAsScreenshot as boolean, archiveAsMonolith: user.archiveAsScreenshot as boolean, archiveAsPDF: user.archiveAsPDF as boolean, }); } }; fetchOwner(); }, [link.collection.ownerId]); const isReady = () => { return ( link && (collectionOwner.archiveAsScreenshot === true ? link.pdf && link.pdf !== "pending" : true) && (collectionOwner.archiveAsMonolith === true ? link.monolith && link.monolith !== "pending" : true) && (collectionOwner.archiveAsPDF === true ? link.pdf && link.pdf !== "pending" : true) && link.readable && link.readable !== "pending" ); }; const atLeastOneFormatAvailable = () => { return ( screenshotAvailable(link) || pdfAvailable(link) || readabilityAvailable(link) || monolithAvailable(link) ); }; useEffect(() => { (async () => { await getLink.mutateAsync({ id: link.id as number, }); })(); let interval: any; if (!isReady()) { interval = setInterval(async () => { await getLink.mutateAsync({ id: link.id as number, }); }, 5000); } else { if (interval) { clearInterval(interval); } } return () => { if (interval) { clearInterval(interval); } }; }, [link.monolith]); const router = useRouter(); const isPublicRoute = router.pathname.startsWith("/public") ? true : false; const updateLink = useUpdateLink(); const updatePreview = useUpdatePreview(); const submit = async (e?: any) => { e?.preventDefault(); const { updatedAt: b, ...oldLink } = activeLink; const { updatedAt: a, ...newLink } = link; if (JSON.stringify(oldLink) === JSON.stringify(newLink)) { return; } const load = toast.loading(t("updating")); await updateLink.mutateAsync(link, { onSettled: (data, error) => { toast.dismiss(load); if (error) { toast.error(error.message); } else { toast.success(t("updated")); setMode && setMode("view"); setLink(data); } }, }); }; const setCollection = (e: any) => { if (e?.__isNew__) e.value = null; setLink({ ...link, collection: { id: e?.value, name: e?.label, ownerId: e?.ownerId }, }); }; const setTags = (e: any) => { const tagNames = e.map((e: any) => ({ name: e.label })); setLink({ ...link, tags: tagNames }); }; const [iconPopover, setIconPopover] = useState(false); return (
{previewAvailable(link) ? ( { const target = e.target as HTMLElement; target.style.display = "none"; }} /> ) : link.preview === "unavailable" ? (
) : (
)} {!standalone && (permissions === true || permissions?.canUpdate) && (
)}
{!standalone && (permissions === true || permissions?.canUpdate) ? (
setIconPopover(true)} />
{iconPopover && ( setLink({ ...link, color })} weight={(link.iconWeight || "regular") as IconWeight} setWeight={(iconWeight: string) => setLink({ ...link, iconWeight }) } iconName={link.icon as string} setIconName={(icon: string) => setLink({ ...link, icon })} reset={() => setLink({ ...link, color: "", icon: "", iconWeight: "", }) } className="top-12" onClose={() => { setIconPopover(false); submit(); }} /> )}
) : (
setIconPopover(true)} />
)}
{mode === "view" && (

{link.name || t("untitled")}

)} {mode === "edit" && ( <>

{t("name")}

setLink({ ...link, name: e.target.value })} placeholder={t("placeholder_example_link")} className="bg-base-200" />
)} {link.url && mode === "view" ? ( <>

{t("link")}

{link.url}
) : activeLink.url ? ( <>

{t("link")}

setLink({ ...link, url: e.target.value })} placeholder={t("placeholder_example_link")} className="bg-base-200" />
) : undefined}

{t("collection")}

{mode === "view" ? (

{link.collection.name}

{link.collection.icon ? ( ) : ( )}
) : ( )}

{t("tags")}

{mode === "view" ? (
{link.tags && link.tags[0] ? ( link.tags.map((tag) => isPublicRoute ? (
{tag.name}
) : ( {tag.name} ) ) ) : (
{t("no_tags")}
)}
) : ( ({ label: e.name, value: e.id, }))} /> )}

{t("description")}

{mode === "view" ? (
{link.description ? (

{link.description}

) : (

{t("no_description_provided")}

)}
) : (