fix: several smaller improvements

This commit is contained in:
2026-03-14 22:13:38 +01:00
parent a1ad4d52cf
commit bcb9c5946d
5 changed files with 35 additions and 50 deletions

View File

@@ -1,13 +1,11 @@
/**
* Hook for canvas graph state and persistence. Wraps useGraphStateWithHistory
* with initial graph from project storage (or example). Save is explicit via save();
* autosave runs on an interval (~10s) and saves when the graph has changed.
* with initial graph from project storage (or example). Save is explicit via save().
*/
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useCallback, useMemo, useRef, useState } from 'react'
import { useGraphStateWithHistory } from '@/hooks/useGraphStateWithHistory'
import { getInitialGraph } from '@/app/canvas/canvasGraphUtils'
import { useCanvasStore } from '@/app/canvas/canvasStore'
import { saveGraphToStorage, PROJECT_VERSION } from '@/app/pleroma/projectGraphStorage'
import type { AppNode, AppEdge } from '@/lib/graph/nodeTypes'
@@ -20,70 +18,46 @@ export type UseCanvasGraphResult = ReturnType<typeof useGraphStateWithHistory> &
saveStatus: SaveStatus
}
const AUTOSAVE_INTERVAL_MS = 10_000
export function useCanvasGraph(projectId: string | undefined): UseCanvasGraphResult {
const initialGraph = useMemo(() => getInitialGraph(projectId), [projectId])
const result = useGraphStateWithHistory(initialGraph.nodes, initialGraph.edges)
const { nodes, edges } = result
const storeNodes = useCanvasStore((s) => s.graph.nodes)
const storeEdges = useCanvasStore((s) => s.graph.edges)
const nodesRef = useRef(nodes)
const edgesRef = useRef(edges)
nodesRef.current = nodes
edgesRef.current = edges
const [isSaving, setIsSaving] = useState(false)
const lastSavedSnapshotRef = useRef(
const [lastSavedSerialized, setLastSavedSerialized] = useState(() =>
JSON.stringify({ nodes: initialGraph.nodes, edges: initialGraph.edges })
)
const serializedFromStore = useMemo(
() => JSON.stringify({ nodes: storeNodes, edges: storeEdges }),
[storeNodes, storeEdges]
const currentSerialized = useMemo(
() => JSON.stringify({ nodes, edges }),
[nodes, edges]
)
const isDirty = serializedFromStore !== lastSavedSnapshotRef.current
const isDirty = currentSerialized !== lastSavedSerialized
const saveStatus: SaveStatus = isSaving ? 'saving' : isDirty ? 'unsaved' : 'saved'
const performSave = useCallback(() => {
if (!projectId) return
const current = JSON.stringify({
nodes: nodesRef.current,
edges: edgesRef.current,
})
if (current === lastSavedSnapshotRef.current) return
setIsSaving(true)
saveGraphToStorage(projectId, {
version: PROJECT_VERSION,
nodes: nodesRef.current,
edges: edgesRef.current,
})
lastSavedSnapshotRef.current = current
setIsSaving(false)
}, [projectId])
const save = useCallback(() => {
if (!projectId) return
const snapshot = JSON.stringify({
nodes: nodesRef.current,
edges: edgesRef.current,
})
setIsSaving(true)
saveGraphToStorage(projectId, {
version: PROJECT_VERSION,
nodes: nodesRef.current,
edges: edgesRef.current,
})
lastSavedSnapshotRef.current = JSON.stringify({
nodes: nodesRef.current,
edges: edgesRef.current,
})
setIsSaving(false)
const SAVING_DISPLAY_MS = 360
setTimeout(() => {
setLastSavedSerialized(snapshot)
setIsSaving(false)
}, SAVING_DISPLAY_MS)
}, [projectId])
useEffect(() => {
if (!projectId) return
const id = setInterval(performSave, AUTOSAVE_INTERVAL_MS)
return () => clearInterval(id)
}, [projectId, performSave])
return { ...result, save, saveStatus }
}