"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"; // 인터페이스 interface Attachment { id: number; fileName: string; filePath: string; fileType?: string; } 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 && ( )} ); } const DocumentViewer: React.FC<{ open: boolean; setOpen: React.Dispatch>; versions: Version[]; }> = ({ 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 () => { // cleanup 시에는 중단 flag 세움 if (instance) { instance.UI.dispose(); } setTimeout(() => cleanupHtmlStyle(), 500); }; }, [open]); React.useEffect(() => { const loadDocument = async () => { if (instance && versions.length > 0) { const { UI } = instance; const optionsArray: any[] = []; versions.forEach((c) => { const { attachments } = c; attachments.forEach((c2) => { const { fileName, filePath, fileType } = c2; const fileTypeCur = fileType ?? ""; const options = { filename: fileName, ...(fileTypeCur.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 && (

문서 뷰어 로딩 중...

)}
); };