2026-02-16 14:43:09 +09:00

94 lines
2.6 KiB
TypeScript

'use client'
import { type AnyNodeId, initSpatialGridSync, useScene } from '@pascal-app/core'
import { useViewer } from '@pascal-app/viewer'
import { useEffect, useRef } from 'react'
import useEditor from '@/store/use-editor'
import { getLocalProperty, updateLocalPropertyScene } from './property-store'
/**
* Hook for local property scene management (guest users)
* Loads scene from localStorage and auto-saves changes
*/
export function useLocalPropertyScene(propertyId?: string) {
const saveTimeoutRef = useRef<NodeJS.Timeout | undefined>(undefined)
const currentPropertyIdRef = useRef<string | null>(null)
const lastPropertyIdRef = useRef<string | null>(null)
// Load scene when property ID changes
useEffect(() => {
if (!propertyId || !propertyId.startsWith('local_')) {
return
}
if (lastPropertyIdRef.current === propertyId) {
return
}
lastPropertyIdRef.current = propertyId
currentPropertyIdRef.current = propertyId
const property = getLocalProperty(propertyId)
if (property?.scene_graph) {
const { nodes, rootNodeIds } = property.scene_graph
useScene.getState().setScene(nodes, rootNodeIds as AnyNodeId[])
initSpatialGridSync()
} else {
useScene.getState().clearScene()
}
useEditor.getState().setPhase('site')
useViewer.getState().setSelection({
buildingId: null,
levelId: null,
selectedIds: [],
zoneId: null,
})
}, [propertyId])
// Auto-save to localStorage with debouncing
useEffect(() => {
if (!propertyId || !propertyId.startsWith('local_')) {
currentPropertyIdRef.current = null
return
}
currentPropertyIdRef.current = propertyId
let lastNodesSnapshot = JSON.stringify(useScene.getState().nodes)
const unsubscribe = useScene.subscribe((state) => {
const currentNodesSnapshot = JSON.stringify(state.nodes)
if (currentNodesSnapshot === lastNodesSnapshot) {
return
}
lastNodesSnapshot = currentNodesSnapshot
const nodes = state.nodes
if (saveTimeoutRef.current) {
clearTimeout(saveTimeoutRef.current)
}
// Debounce save by 1 second (faster than cloud save)
saveTimeoutRef.current = setTimeout(() => {
const currentId = currentPropertyIdRef.current
if (!currentId) return
const rootNodeIds = useScene.getState().rootNodeIds
const sceneGraph = { nodes, rootNodeIds }
updateLocalPropertyScene(currentId, sceneGraph)
}, 1000)
})
return () => {
if (saveTimeoutRef.current) {
clearTimeout(saveTimeoutRef.current)
}
unsubscribe()
}
}, [propertyId])
}