"use client" import { useCallback, useEffect, useMemo, useState } from "react" import { useRouter } from "next/navigation" import Link from "next/link" import { apiClient } from "@/lib/api/client" import { Button } from "@/components/ui/button" import { ArrowLeft, Loader2 } from "lucide-react" import { OfficeEditorChrome } from "@/components/drive/office-editor-chrome" import { RichTextDocumentEditor } from "@/components/drive/richtext-document" import { useDriveMutations, useDriveShares } from "@/lib/api/hooks/use-drive-queries" import { displayFileBaseName } from "@/lib/drive/display-file-name" import { resolveRenameName } from "@/lib/drive/drive-default-name" import { driveFolderHref } from "@/lib/drive/drive-sidebar-tree" import { buildDriveEditHref, resolveDriveEditReturnTo } from "@/lib/drive/drive-url" import { useDriveDocumentTitle } from "@/lib/drive/use-drive-document-title" import { useDriveUIStore } from "@/lib/stores/drive-ui-store" import { colorForGuestId } from "@/lib/drive/guest-editor-identity" import type { RichTextSaveStatus, RichTextSessionResponse } from "@/lib/drive/richtext-types" import { useChromeIdentity } from "@/lib/hooks/use-chrome-identity" import { cn } from "@/lib/utils" function fileNameFromPath(filePath: string): string { return filePath.split("/").filter(Boolean).pop() ?? filePath } function renameTargetPath(filePath: string, newName: string): string { const parent = filePath.replace(/\/[^/]+$/, "") || "/" const base = parent === "/" ? "" : parent return `${base}/${newName}`.replace(/\/+/g, "/") || `/${newName}` } function saveStatusLabel(status: RichTextSaveStatus): string { switch (status) { case "saving": return "Enregistrement…" case "saved": return "Enregistré" case "error": return "Erreur d'enregistrement" default: return "" } } export function RichTextEditor({ filePath, returnTo, }: { filePath: string returnTo?: string | null }) { const router = useRouter() const identity = useChromeIdentity() const setSharePath = useDriveUIStore((s) => s.setSharePath) const [session, setSession] = useState(null) const [error, setError] = useState(null) const [saveStatus, setSaveStatus] = useState("idle") const [displayPath, setDisplayPath] = useState(filePath) useEffect(() => { setDisplayPath(filePath) }, [filePath]) const fileName = fileNameFromPath(displayPath) const title = displayFileBaseName(fileName) useDriveDocumentTitle(title) const backHref = useMemo( () => resolveDriveEditReturnTo(returnTo, displayPath, (folderPath) => driveFolderHref("files", folderPath) ), [returnTo, displayPath] ) const { data: sharesData } = useDriveShares(displayPath, Boolean(displayPath)) const { rename } = useDriveMutations() useEffect(() => { let cancelled = false setSession(null) setError(null) void (async () => { try { const res = await apiClient.post("/richtext/session", { path: displayPath, mode: "edit", }) if (!cancelled) setSession(res) } catch (e) { if (!cancelled) setError(e instanceof Error ? e.message : "Impossible d'ouvrir le document") } })() return () => { cancelled = true } }, [displayPath]) const handleRename = useCallback( async (input: string) => { const newName = resolveRenameName({ name: fileName, type: "file" }, input) if (displayFileBaseName(fileName) === input.trim()) return await rename.mutateAsync({ path: displayPath, new_name: newName }) const nextPath = renameTargetPath(displayPath, newName) setDisplayPath(nextPath) router.replace(buildDriveEditHref(nextPath, returnTo ?? undefined, "richtext")) }, [displayPath, fileName, rename, returnTo, router] ) const openShare = useCallback(() => { setSharePath(displayPath) }, [displayPath, setSharePath]) const statusText = saveStatusLabel(saveStatus) const collabUserName = identity?.name?.trim() || identity?.email || "Utilisateur" const collabUserColor = colorForGuestId(identity?.email ?? collabUserName) if (error) { return (

{error}

) } return (
{statusText} ) : null } />
{!session ? (
) : ( )}
) }