"use client" import { useCallback, useEffect, useMemo, useRef, useState } from "react" import Link from "next/link" import { Button } from "@/components/ui/button" import { ArrowLeft } from "lucide-react" import { OnlyOfficeMount } from "@/components/drive/onlyoffice-mount" import { OfficeEditorChrome } from "@/components/drive/office-editor-chrome" import { displayFileBaseName } from "@/lib/drive/display-file-name" import { getGuestEditorIdentity } from "@/lib/drive/guest-editor-identity" import { resolvePublicShareEditReturnTo, shouldShowPublicShareEditorBack } from "@/lib/drive/public-share-url" import type { PublicShareRootType } from "@/lib/drive/public-share-url" import { useDriveDocumentTitle } from "@/lib/drive/use-drive-document-title" function fileNameFromPath(filePath: string, fallback?: string): string { const base = filePath.split("/").filter(Boolean).pop() return base || fallback || filePath } export function PublicOfficeEditor({ token, filePath, password, returnTo, mode = "edit", fileDisplayName, shareRoot, }: { token: string filePath: string password?: string returnTo?: string | null mode?: "edit" | "view" fileDisplayName?: string shareRoot?: PublicShareRootType | null }) { const instanceSeq = useRef(0) const guest = useMemo(() => getGuestEditorIdentity(token), [token]) const [config, setConfig] = useState | null>(null) const [serverUrl, setServerUrl] = useState("") const [editorId, setEditorId] = useState(null) const [error, setError] = useState(null) const [resolvedMode, setResolvedMode] = useState<"edit" | "view">(mode) const fileName = fileDisplayName || fileNameFromPath(filePath) const title = displayFileBaseName(fileName) useDriveDocumentTitle(title) const backHref = useMemo( () => resolvePublicShareEditReturnTo(token, returnTo, filePath), [token, returnTo, filePath] ) const showBack = shouldShowPublicShareEditorBack(shareRoot, returnTo, filePath) useEffect(() => { let cancelled = false setConfig(null) setServerUrl("") setEditorId(null) setError(null) setResolvedMode(mode) void (async () => { try { const res = await fetch( `/api/v1/drive/public/shares/${encodeURIComponent(token)}/office/session`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ path: filePath, mode, password: password ?? "", guest_id: guest.guestId, guest_name: guest.guestName, display_name: fileName, }), } ) if (!res.ok) throw new Error("session_failed") const data = (await res.json()) as { config: Record serverUrl: string mode?: "edit" | "view" } if (cancelled) return instanceSeq.current += 1 setConfig(data.config) setServerUrl(data.serverUrl || process.env.NEXT_PUBLIC_ONLYOFFICE_URL || "") setEditorId(`ultidrive-public-editor-${instanceSeq.current}`) if (data.mode === "edit" || data.mode === "view") { setResolvedMode(data.mode) } else { const editorConfig = data.config?.editorConfig as { mode?: string } | undefined if (editorConfig?.mode === "edit" || editorConfig?.mode === "view") { setResolvedMode(editorConfig.mode) } } } catch { if (!cancelled) setError("Impossible de charger l’éditeur.") } })() return () => { cancelled = true } }, [token, filePath, password, mode, fileName]) const handleEditorError = useCallback((message: string) => { setError(message) }, []) if (error) { return (

{error}

{showBack ? ( ) : null}
) } if (!config || !editorId || !serverUrl) { return

Ouverture du document…

} return (
Lecture seule ) : null } />
) }