"use client" import * as React from "react" import { WebViewerInstance } from "@pdftron/webviewer"; import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog" import { Building2, FileIcon, Loader2 } from "lucide-react" import { Button } from "@/components/ui/button" import fs from "fs" interface Version { id: number stage: string revision: string uploaderType: string uploaderName: string | null comment: string | null status: string | null planDate: string | null actualDate: string | null approvedDate: string | null DocumentSubmitDate: Date attachments: Attachment[] selected: boolean } type ViewDocumentDialogProps = { versions: Version[] } export function ViewDocumentDialog({versions}: ViewDocumentDialogProps){ const [open, setOpen] = React.useState(false) return ( <> {open && } ); } function DocumentViewer({open, setOpen, versions}){ const [instance, setInstance] = React.useState(null) const [viwerLoading, setViewerLoading] = React.useState(true) const [fileSetLoading, setFileSetLoading] = React.useState(true) const viewer = React.useRef(null); const initialized = React.useRef(false); const isCancelled = React.useRef(false); // 초기화 중단용 flag const cleanupHtmlStyle = () => { const htmlElement = document.documentElement; // 기존 style 속성 가져오기 const originalStyle = htmlElement.getAttribute("style") || ""; // "color-scheme: light" 또는 "color-scheme: dark" 찾기 const colorSchemeStyle = originalStyle .split(";") .map((s) => s.trim()) .find((s) => s.startsWith("color-scheme:")); // 새로운 스타일 적용 (color-scheme만 유지) if (colorSchemeStyle) { htmlElement.setAttribute("style", colorSchemeStyle + ";"); } else { htmlElement.removeAttribute("style"); // color-scheme도 없으면 style 속성 자체 삭제 } console.log("html style 삭제") }; React.useEffect(() => { if (open && !initialized.current) { initialized.current = true; isCancelled.current = false; // 다시 열릴 때는 false로 리셋 requestAnimationFrame(() => { if (viewer.current) { import("@pdftron/webviewer").then(({ default: WebViewer }) => { console.log(isCancelled.current) if (isCancelled.current) { console.log("📛 WebViewer 초기화 취소됨 (Dialog 닫힘)"); return; } WebViewer( { path: "/pdftronWeb", licenseKey: "demo:1739264618684:616161d7030000000091db1c97c6f386d41d3506ab5b507381ef2ee2bd", fullAPI: true, css:"/globals.css" }, viewer.current as HTMLDivElement ).then(async (instance: WebViewerInstance) => { setInstance(instance); instance.UI.enableFeatures([instance.UI.Feature.MultiTab]); instance.UI.disableElements(["addTabButton", "multiTabsEmptyPage"]); setViewerLoading(false); }); }); } }); } return async () => { // cleanup 시에는 중단 flag 세움 if(instance){ await instance.UI.dispose() } await setTimeout(() => cleanupHtmlStyle(), 500) }; }, [open]); React.useEffect(() => { const loadDocument = async () => { if(instance && versions.length > 0){ const { UI } = instance; const optionsArray = [] versions.forEach(c => { const {attachments} = c attachments.forEach(c2 => { const {fileName, filePath, fileType} = c2 const options = { filename: fileName, ...(fileType.includes("xlsx") && { officeOptions: { formatOptions: { applyPageBreaksToSheet: true, }, }, }), }; optionsArray.push({ filePath, options }) }) }) const tabIds = []; for (const option of optionsArray) { const { filePath, options } = option; const response = await fetch(filePath); const blob = await response.blob(); const tab = await UI.TabManager.addTab(blob, options); tabIds.push(tab); // 탭 ID 저장 } if (tabIds.length > 0) { await UI.TabManager.setActiveTab(tabIds[0]); } setFileSetLoading(false) } } loadDocument(); }, [instance, versions]) return ( { console.log({val, fileSetLoading}) if(!val && fileSetLoading){ return; } if (instance) { try { await instance.UI.dispose(); setInstance(null); // 상태도 초기화 } catch (e) { console.warn("dispose error", e); } } // cleanupHtmlStyle() setViewerLoading(false); setOpen(prev => !prev) await setTimeout(() => cleanupHtmlStyle(), 1000) }}> 문서 미리보기 첨부파일 미리보기
{viwerLoading &&

문서 뷰어 로딩 중...

}
); }