import { useCallback, useEffect, useRef, useState } from 'react'; import { useParams } from 'react-router-dom'; import EditorLayout from '../components/EditorLayout.jsx'; import ReadOnlyBanner from '../components/ReadOnlyBanner.jsx'; import SaveStatus from '../components/SaveStatus.jsx'; import StatusBadge from '../components/StatusBadge.jsx'; import { useEditLock } from '../hooks/useEditLock.js'; import { useServerAutosave } from '../hooks/useServerAutosave.js'; import { ApiError, fetchEditDocument, friendlyErrorMessage, } from '../lib/api.js'; import { downloadDocument } from '../lib/download.js'; import { STR } from '../lib/strings.js'; import LinkErrorPage from './LinkErrorPage.jsx'; export default function SharedEditPage() { const { token } = useParams(); const [doc, setDoc] = useState(null); const [title, setTitle] = useState(''); const [content, setContent] = useState(''); const [mode, setMode] = useState('markdown'); const [loadError, setLoadError] = useState(null); const [loading, setLoading] = useState(true); const [lockLost, setLockLost] = useState(false); const editorRef = useRef(null); const { lockState, acquire, release, hasLock, lockToken, clientId } = useEditLock(token, !!doc && !loadError); const canEdit = hasLock && !lockLost; const { saveStatus, saveNow } = useServerAutosave({ editToken: token, clientId, lockToken, enabled: canEdit, title, mode, content, }); useEffect(() => { let cancelled = false; (async () => { setLoading(true); setLoadError(null); try { const data = await fetchEditDocument(token); if (cancelled) return; setDoc(data); setTitle(data.title); setContent(data.content); setMode(data.mode); } catch (err) { if (!cancelled) setLoadError(err); } finally { if (!cancelled) setLoading(false); } })(); return () => { cancelled = true; }; }, [token]); const lockRequestedRef = useRef(false); useEffect(() => { lockRequestedRef.current = false; }, [token]); useEffect(() => { if (!doc || loadError || lockRequestedRef.current) return; lockRequestedRef.current = true; acquire().catch(() => {}); }, [doc, loadError, acquire]); useEffect(() => { if (lockState.status === 'lost') { setLockLost(true); } if (saveStatus === 'no_permission') { setLockLost(true); } }, [lockState.status, saveStatus]); const handleSaveServer = useCallback(async () => { const ok = await saveNow(); if (!ok) setLockLost(true); }, [saveNow]); const handleRelease = useCallback(async () => { await release(); setLockLost(true); }, [release]); const handleDownload = useCallback(() => { downloadDocument(content, mode, title); }, [content, mode, title]); if (loading) { return (
{STR.LOADING_DOCUMENT}
{canEdit ? STR.SHARED_EDIT : STR.SHARED_VIEW}