import unescapeString from "@/lib/client/unescapeString"; import { readabilityAvailable } from "@/lib/shared/getArchiveValidity"; import isValidUrl from "@/lib/shared/isValidUrl"; import useLinkStore from "@/store/links"; import { ArchivedFormat, CollectionIncludingMembersAndLinkCount, LinkIncludingShortenedCollectionAndTags, } from "@/types/global"; import ColorThief, { RGBColor } from "colorthief"; import DOMPurify from "dompurify"; import Image from "next/image"; import Link from "next/link"; import { useRouter } from "next/router"; import React, { useEffect, useMemo, useState } from "react"; import LinkActions from "./LinkViews/LinkComponents/LinkActions"; import useCollectionStore from "@/store/collections"; import { useTranslation } from "next-i18next"; type LinkContent = { title: string; content: string; textContent: string; length: number; excerpt: string; byline: string; dir: string; siteName: string; lang: string; }; type Props = { link: LinkIncludingShortenedCollectionAndTags; }; export default function ReadableView({ link }: Props) { const { t } = useTranslation(); const [linkContent, setLinkContent] = useState(); const [imageError, setImageError] = useState(false); const [colorPalette, setColorPalette] = useState(); const [date, setDate] = useState(); const colorThief = new ColorThief(); const router = useRouter(); const { getLink } = useLinkStore(); const { collections } = useCollectionStore(); const collection = useMemo(() => { return collections.find( (e) => e.id === link.collection.id ) as CollectionIncludingMembersAndLinkCount; }, [collections, link]); useEffect(() => { const fetchLinkContent = async () => { if (router.query.id && readabilityAvailable(link)) { const response = await fetch( `/api/v1/archives/${link?.id}?format=${ArchivedFormat.readability}` ); const data = await response?.json(); setLinkContent(data); } }; fetchLinkContent(); setDate(link.importDate || link.createdAt); }, [link]); useEffect(() => { if (link) getLink(link?.id as number); let interval: any; if ( link && (link?.image === "pending" || link?.pdf === "pending" || link?.readable === "pending" || link?.singlefile === "pending" || !link?.image || !link?.pdf || !link?.readable || !link?.singlefile) ) { interval = setInterval(() => getLink(link.id as number), 5000); } else { if (interval) { clearInterval(interval); } } return () => { if (interval) { clearInterval(interval); } }; }, [link?.image, link?.pdf, link?.readable, link?.singlefile]); const rgbToHex = (r: number, g: number, b: number): string => "#" + [r, g, b] .map((x) => { const hex = x.toString(16); return hex.length === 1 ? "0" + hex : hex; }) .join(""); useEffect(() => { const banner = document.getElementById("link-banner"); const bannerInner = document.getElementById("link-banner-inner"); if (colorPalette && banner && bannerInner) { if (colorPalette[0] && colorPalette[1]) { banner.style.background = `linear-gradient(to bottom, ${rgbToHex( colorPalette[0][0], colorPalette[0][1], colorPalette[0][2] )}20, ${rgbToHex( colorPalette[1][0], colorPalette[1][1], colorPalette[1][2] )}20)`; } if (colorPalette[2] && colorPalette[3]) { bannerInner.style.background = `linear-gradient(to bottom, ${rgbToHex( colorPalette[2][0], colorPalette[2][1], colorPalette[2][2] )}30, ${rgbToHex( colorPalette[3][0], colorPalette[3][1], colorPalette[3][2] )})30`; } } }, [colorPalette]); return (
{link?.readable?.startsWith("archives") ? (
) : (

{t("link_preservation_in_queue")}

{t("check_back_later")}

)}
); }