[as] feat: 웹기안기 '열기' 기능 추가(개발용)
This commit is contained in:
@@ -1,12 +1,17 @@
|
||||
"use client";
|
||||
|
||||
import { Download, Fullscreen, Save } from "lucide-react";
|
||||
import { useId } from "react";
|
||||
|
||||
import { Button } from "@common/components";
|
||||
import { Download, FolderOpen, Fullscreen, Save } from "lucide-react";
|
||||
|
||||
import { Button, cn } from "@common/components";
|
||||
|
||||
const WEBHYP_DEV_MODE = process.env.NEXT_PUBLIC_WEBHYP_DEV_MODE === "true";
|
||||
|
||||
interface HangulGiangiToolbarProps {
|
||||
isBusy?: boolean;
|
||||
canSave?: boolean;
|
||||
onOpen: (file: File) => void;
|
||||
onSave: () => void;
|
||||
onDownload: () => void;
|
||||
onFullscreen: () => void;
|
||||
@@ -15,12 +20,51 @@ interface HangulGiangiToolbarProps {
|
||||
function HangulGiangiToolbar({
|
||||
isBusy = false,
|
||||
canSave = true,
|
||||
onOpen,
|
||||
onSave,
|
||||
onDownload,
|
||||
onFullscreen,
|
||||
}: HangulGiangiToolbarProps) {
|
||||
const openInputId = useId();
|
||||
|
||||
return (
|
||||
<div className="flex w-full flex-nowrap items-center gap-2 border-b border-border bg-background p-3">
|
||||
{WEBHYP_DEV_MODE && (
|
||||
<label
|
||||
htmlFor={openInputId}
|
||||
className={cn("cursor-pointer", isBusy && "pointer-events-none")}
|
||||
>
|
||||
<input
|
||||
id={openInputId}
|
||||
type="file"
|
||||
accept=".hwpx,application/haansofthwpx"
|
||||
disabled={isBusy}
|
||||
className="peer sr-only"
|
||||
aria-label="열기"
|
||||
onChange={(event) => {
|
||||
const file = event.target.files?.[0];
|
||||
if (file) onOpen(file);
|
||||
event.target.value = "";
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
color="white"
|
||||
size="sm"
|
||||
disabled={isBusy}
|
||||
className={cn(
|
||||
"peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-2",
|
||||
isBusy && "pointer-events-none opacity-50",
|
||||
)}
|
||||
asChild
|
||||
>
|
||||
<span>
|
||||
<FolderOpen className="!size-5" />
|
||||
열기
|
||||
</span>
|
||||
</Button>
|
||||
</label>
|
||||
)}
|
||||
{canSave && (
|
||||
<Button type="button" color="white" size="sm" disabled={isBusy} onClick={onSave}>
|
||||
<Save className="!size-5" />
|
||||
|
||||
@@ -70,43 +70,46 @@ function HangulGiangi({
|
||||
return () => window.clearInterval(timer);
|
||||
}, [isCtrlReady, onReady]);
|
||||
|
||||
const handleOpen = useCallback(() => {
|
||||
const ctrl = resolveHwpCtrl(iframeRef.current, isCtrlReady);
|
||||
if (!ctrl) return;
|
||||
const openHwpxBlob = useCallback(
|
||||
(blob: Blob, fileName: string) => {
|
||||
const ctrl = resolveHwpCtrl(iframeRef.current, isCtrlReady);
|
||||
if (!ctrl) return;
|
||||
|
||||
setIsBusy(true);
|
||||
openingDocumentKeyRef.current = documentKey;
|
||||
attemptedDocumentKeyRef.current = documentKey;
|
||||
try {
|
||||
const documentFile = new File([documentBlob], documentFileName, {
|
||||
type: HWPX_CONTENT_TYPE,
|
||||
});
|
||||
const isAccepted = ctrl.Open(
|
||||
documentFile,
|
||||
"HWPX",
|
||||
"",
|
||||
(result) => {
|
||||
const callbackDocumentKey = getCallbackDocumentKey(result.CallbackUserData, documentKey);
|
||||
if (openingDocumentKeyRef.current !== callbackDocumentKey) return;
|
||||
setIsBusy(true);
|
||||
openingDocumentKeyRef.current = documentKey;
|
||||
attemptedDocumentKeyRef.current = documentKey;
|
||||
try {
|
||||
const documentFile = new File([blob], fileName, {
|
||||
type: HWPX_CONTENT_TYPE,
|
||||
});
|
||||
const isAccepted = ctrl.Open(
|
||||
documentFile,
|
||||
"HWPX",
|
||||
"",
|
||||
(result) => {
|
||||
const callbackDocumentKey = getCallbackDocumentKey(result.CallbackUserData, documentKey);
|
||||
if (openingDocumentKeyRef.current !== callbackDocumentKey) return;
|
||||
|
||||
openingDocumentKeyRef.current = null;
|
||||
setIsBusy(false);
|
||||
if (!result.result) return;
|
||||
openingDocumentKeyRef.current = null;
|
||||
setIsBusy(false);
|
||||
if (!result.result) return;
|
||||
|
||||
openedDocumentKeyRef.current = callbackDocumentKey;
|
||||
},
|
||||
{ documentKey } satisfies DocumentCallbackUserData,
|
||||
);
|
||||
openedDocumentKeyRef.current = callbackDocumentKey;
|
||||
},
|
||||
{ documentKey } satisfies DocumentCallbackUserData,
|
||||
);
|
||||
|
||||
if (isAccepted) return;
|
||||
if (isAccepted) return;
|
||||
|
||||
openingDocumentKeyRef.current = null;
|
||||
setIsBusy(false);
|
||||
} catch {
|
||||
openingDocumentKeyRef.current = null;
|
||||
setIsBusy(false);
|
||||
}
|
||||
}, [documentBlob, documentFileName, documentKey, isCtrlReady]);
|
||||
openingDocumentKeyRef.current = null;
|
||||
setIsBusy(false);
|
||||
} catch {
|
||||
openingDocumentKeyRef.current = null;
|
||||
setIsBusy(false);
|
||||
}
|
||||
},
|
||||
[documentKey, isCtrlReady],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
@@ -117,8 +120,19 @@ function HangulGiangi({
|
||||
) {
|
||||
return;
|
||||
}
|
||||
handleOpen();
|
||||
}, [documentKey, handleOpen, isCtrlReady]);
|
||||
openHwpxBlob(documentBlob, documentFileName);
|
||||
}, [documentBlob, documentFileName, documentKey, isCtrlReady, openHwpxBlob]);
|
||||
|
||||
const handleToolbarOpen = useCallback(
|
||||
(file: File) => {
|
||||
if (!file.name.toLowerCase().endsWith(".hwpx")) {
|
||||
alert("HWPX 파일만 열 수 있습니다.");
|
||||
return;
|
||||
}
|
||||
openHwpxBlob(file, file.name);
|
||||
},
|
||||
[openHwpxBlob],
|
||||
);
|
||||
|
||||
const handleSave = useCallback(() => {
|
||||
const ctrl = resolveHwpCtrl(iframeRef.current, isCtrlReady);
|
||||
@@ -185,6 +199,7 @@ function HangulGiangi({
|
||||
<HangulGiangiToolbar
|
||||
isBusy={isBusy || !isCtrlReady}
|
||||
canSave={canSave}
|
||||
onOpen={handleToolbarOpen}
|
||||
onSave={handleSave}
|
||||
onDownload={handleDownload}
|
||||
onFullscreen={handleFullscreen}
|
||||
|
||||
Reference in New Issue
Block a user