import React, { useMemo, useRef, useState, useEffect } from "react"; import MarkdownPreview from "@uiw/react-markdown-preview"; import katex from "katex"; import { checkForLUDS, convertDate, getParsedRepEvent, minimizeKey, detectDirection, } from "@/Helpers/Encryptions"; import { getComponent } from "@/Helpers/ClientHelpers"; import { getContentTranslationConfig, shuffleArray } from "@/Helpers/Helpers"; import UserProfilePic from "@/Components/UserProfilePic"; import Date_ from "@/Components/Date_"; import Follow from "@/Components/Follow"; import ZapTip from "@/Components/ZapTip"; import ShowUsersList from "@/Components/ShowUsersList"; import ArrowUp from "@/Components/ArrowUp"; import CheckNOSTRClient from "@/Components/CheckNOSTRClient"; import { useDispatch, useSelector } from "react-redux"; import TopicsTags from "@/Content/TopicsTags"; import DynamicIndicator from "@/Components/DynamicIndicator"; import useRepEventStats from "@/Hooks/useRepEventStats"; import RepEventCommentsSection from "@/Components/RepEventCommentsSection"; import Backbar from "@/Components/Backbar"; import { useTranslation } from "react-i18next"; import { translate } from "@/Helpers/Controlers"; import LoadingDots from "@/Components/LoadingDots"; import { setToast } from "@/Store/Slides/Publishers"; import PagePlaceholder from "@/Components/PagePlaceholder"; import bannedList from "@/Content/BannedList"; import ZapAd from "@/Components/ZapAd"; import useUserProfile from "@/Hooks/useUsersProfile"; import { saveUsers } from "@/Helpers/DB"; import useIsMute from "@/Hooks/useIsMute"; import EventOptions from "@/Components/ElementOptions/EventOptions"; import { getSubData } from "@/Helpers/Controlers"; import Link from "next/link"; import { customHistory } from "@/Helpers/History"; import PostReaction from "@/Components/PostReaction"; import { useTheme } from "next-themes"; import LoadingLogo from "@/Components/LoadingLogo"; import Icon from "@/Components/Icon"; export default function Article({ event, userProfile, naddrData }) { const { t } = useTranslation(); const dispatch = useDispatch(); const userKeys = useSelector((state) => state.userKeys); const { resolvedTheme } = useTheme(); const isDarkMode = ["dark", "gray", "system"].includes(resolvedTheme); const [isLoading, setIsLoading] = useState(event ? false : true); const [post, setPost] = useState(event); const [usersList, setUsersList] = useState(false); const [showPreview, setShowPreview] = useState(false); const [showCommentsSection, setShowCommentsSections] = useState(false); const [translatedTitle, setTranslatedTitle] = useState(""); const [translatedDescription, setTranslatedDescription] = useState(""); const [translatedDir, setTranslatedDir] = useState(false); const [translatedContent, setTranslatedContent] = useState(""); const [showTranslation, setShowTranslation] = useState(false); const [isContentTranslating, setIsContentTranslating] = useState(false); const containerRef = useRef(null); const { muteUnmute, isMuted } = useIsMute( naddrData ? naddrData.pubkey : null, ); const customService = getContentTranslationConfig(); useEffect(() => { const handleScroll = () => { if (containerRef.current) { setShowPreview(containerRef.current.scrollTop >= 200); } }; const observer = new MutationObserver((mutations) => { for (let mutation of mutations) { if (mutation.type === "childList") { const container = document.querySelector(".page-container"); if (container) { containerRef.current = container; container.addEventListener("scroll", handleScroll); observer.disconnect(); } } } }); observer.observe(document.body, { childList: true, subtree: true }); return () => { if (containerRef.current) { containerRef.current.removeEventListener("scroll", handleScroll); } observer.disconnect(); }; }, []); useEffect(() => { const fetchPost = async () => { setIsLoading(true); const res = await getSubData( [ { authors: naddrData.pubkey ? [naddrData.pubkey] : undefined, kinds: [naddrData.kind], "#d": [naddrData.identifier], }, ], 5000, naddrData.relays || undefined, undefined, 1, ); if (res.data.length === 0) { setIsLoading(false); return; } let post_ = { ...res.data[0], }; let parsedPost = getParsedRepEvent(post_); saveUsers([post_.pubkey]); setPost(parsedPost); setIsLoading(false); }; if (!event && naddrData) fetchPost(); if (!event && !naddrData) setIsLoading(false); }, []); useEffect(() => { if (post && customService?.autoTranslate) translateArticle(); }, [post]); const translateArticle = async () => { setIsContentTranslating(true); if (translatedContent) { setShowTranslation(true); setIsContentTranslating(false); return; } try { let res = await translate( [post.title, post.description || " ", post.content].join(" ABCAF "), ); if (res.status === 500) { dispatch( setToast({ type: 2, desc: t("AZ5VQXL"), }), ); } if (res.status === 400) { dispatch( setToast({ type: 2, desc: t("AJeHuH1"), }), ); } if (res.status === 200) { setTranslatedTitle(res.res.split("ABCAF")[0]); setTranslatedDescription(res.res.split("ABCAF")[1]); setTranslatedContent(res.res.split("ABCAF")[2]); setTranslatedDir(detectDirection(res.res.split("ABCAF")[2])); setShowTranslation(true); } setIsContentTranslating(false); } catch (err) { setShowTranslation(false); setIsContentTranslating(false); dispatch( setToast({ type: 2, desc: t("AZ5VQXL"), }), ); } }; if (bannedList.includes(post?.pubkey)) { customHistory("/"); return; } if (isLoading) return (
); if (!post && !isLoading) return (

{t("AH90wGL")}

{t("Agge1Vg")}

); return (
{usersList && ( setUsersList(false)} title={usersList.title} list={usersList.list} extras={usersList.extras} extrasType={usersList.extrasType} /> )} {post.title && ( <>
{isMuted && ( )} {!isMuted && (
{showCommentsSection && ( setShowCommentsSections(false)} kind={post.kind} event={post} /> )} {!showCommentsSection && (
{showPreview && ( <>

{t("AsXpL4b", { name: userProfile.display_name || userProfile.name || minimizeKey(post.pubkey), })}

{showTranslation ? translatedTitle : post.title}

)} {!showPreview && (
{userKeys.pub !== post.pubkey && (
)} {userKeys.pub === post.pubkey && ( { localStorage.setItem( "ArticleToEdit", JSON.stringify({ post_pubkey: post.pubkey, post_id: post.id, post_kind: post.kind, post_title: post.title, post_desc: post.description, post_thumbnail: post.image, post_tags: post.items, post_d: post.d, post_content: post.content, post_published_at: post.published_at, }), ); }} > )}
)}

{showTranslation ? translatedTitle : post.title}

{t("AHhPGax", { date: "" })}

{post.description && (
{showTranslation ? translatedDescription : post.description}
)} {post.tTags?.length > 0 && (
{post.tTags?.map((tag, index) => { return ( {tag} ); })}
)}
{post.image && (
)}
{ if ( node.tagName === "a" && parent && /^h(1|2|3|4|5|6)/.test(parent.tagName) ) { parent.children = parent.children.slice(1); } }} components={{ p: ({ children }) => { return (
{getComponent(children)}
); }, h1: ({ children }) => { return

{children}

; }, h2: ({ children }) => { return

{children}

; }, h3: ({ children }) => { return

{children}

; }, h4: ({ children }) => { return

{children}

; }, h5: ({ children }) => { return
{children}
; }, h6: ({ children }) => { return
{children}
; }, li: ({ children }) => { return
  • {children}
  • ; }, code: ({ inline, children, className, ...props }) => { if (!children) return; const txt = children[0] || ""; if (inline) { if ( typeof txt === "string" && /^\$\$(.*)\$\$/.test(txt) ) { const html = katex.renderToString( txt.replace(/^\$\$(.*)\$\$/, "$1"), { throwOnError: false, }, ); return ( ); } return ( ); } if ( typeof txt === "string" && typeof className === "string" && /^language-katex/.test( className.toLocaleLowerCase(), ) ) { const html = katex.renderToString(txt, { throwOnError: false, }); return ( ); } return ( {children} ); }, }} />
    )}
    )}
    {!showCommentsSection && !isMuted && (
    {!isContentTranslating && !showTranslation && ( )} {!isContentTranslating && showTranslation && ( )} {isContentTranslating && ( )}
    )} )} {!post.title && (

    {t("AawvPaR")}

    {t("AwARx3K")}

    )}
    ); } const ReaderIndicator = () => { const [scrollPercent, setScrollPercent] = useState(0); useEffect(() => { const handleScroll = (container) => { if (container) { const scrollHeight = container.scrollHeight; const clientHeight = window.innerHeight; const scrollTop = container.scrollTop; const remaining = 100 - (1 - scrollTop / (scrollHeight - clientHeight)) * 100; setScrollPercent(remaining); } }; const container = document.querySelector(".page-container"); if (container) { container.addEventListener("scroll", () => handleScroll(container)); } return () => { if (container) { container.removeEventListener("scroll", () => handleScroll(container)); } }; }, []); return (
    ); }; const AuthPreview = ({ pubkey }) => { const { t } = useTranslation(); const { userProfile, isNip05Verified } = useUserProfile(pubkey); return (

    {t("AVG3Uga")}

    {userProfile.display_name || userProfile.name}

    {isNip05Verified && }
    ); }; const ReadMore = () => { const { t } = useTranslation(); const [readMore, setReadMore] = useState([]); useEffect(() => { const fetchData = async () => { try { let tempArray = shuffleArray(TopicsTags); let tempArray_2 = tempArray.splice(0, 5); let tags = shuffleArray( tempArray_2.map((item) => [item.main_tag, ...item.sub_tags]).flat(), ); let recommendedPosts = await getSubData( [ { kinds: [30023], "#t": tags, limit: 5, }, ], 50, undefined, undefined, 5, ); if (recommendedPosts.data.length > 0) { setReadMore(recommendedPosts.data.map((_) => getParsedRepEvent(_))); saveUsers(recommendedPosts.pubkeys); } } catch (err) { console.log(err); } }; fetchData(); }, []); return ( <> {readMore.length > 0 && (

    {t("AArGqN7")}

    {readMore.map((post) => { if (post.image) return (
    {post.image && (
    )}

    {post.title}

    ); })}
    )} ); }; const PostStats = ({ post, userProfile, showCommentsSection, setShowCommentsSections, }) => { const { postActions } = useRepEventStats(post.aTag, post.pubkey); return ( <> {postActions?.zaps?.zaps?.length > 0 && (
    setUsersList({ title: t("AVDZ5cJ"), list: postActions.zaps.zaps.map((item) => item.pubkey), extras: postActions.zaps.zaps, }) } margin={false} />
    )}
    setShowCommentsSections({ comment: false })} setOpenComment={() => setShowCommentsSections({ comment: true })} />
    ); };