From d5450610f127507f349fcf82daac3f00bcbd7fd8 Mon Sep 17 00:00:00 2001 From: Jan-Henrik Bruhn Date: Mon, 19 Jan 2026 11:37:05 +0100 Subject: [PATCH] Fix state management bugs in tangible configuration 1. Fix state dropdown not updating when new states are added: - Replace useMemo with proper Zustand selector subscription - Component now re-renders when timeline states change 2. Add auto-save trigger to state operations: - createState now triggers auto-save after 1 second - updateState now triggers auto-save after 1 second - deleteState now triggers auto-save after 1 second - Consistent with label and tangible operations Co-Authored-By: Claude Sonnet 4.5 --- src/components/Config/TangibleConfig.tsx | 12 +++++++++--- src/stores/timelineStore.ts | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/components/Config/TangibleConfig.tsx b/src/components/Config/TangibleConfig.tsx index 9882a10..0c03804 100644 --- a/src/components/Config/TangibleConfig.tsx +++ b/src/components/Config/TangibleConfig.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useMemo } from 'react'; +import { useState, useEffect } from 'react'; import { useGraphWithHistory } from '../../hooks/useGraphWithHistory'; import { useConfirm } from '../../hooks/useConfirm'; import { useToastStore } from '../../stores/toastStore'; @@ -18,12 +18,18 @@ const TangibleConfigModal = ({ isOpen, onClose, initialEditingTangibleId }: Prop const { tangibles, labels, addTangible, updateTangible, deleteTangible } = useGraphWithHistory(); const { confirm, ConfirmDialogComponent } = useConfirm(); const { showToast } = useToastStore(); - const { getAllStates } = useTimelineStore(); const [editingTangible, setEditingTangible] = useState(null); // Get all available states for state mode - const availableStates = useMemo(() => getAllStates(), [getAllStates]); + // Use Zustand selector to properly subscribe to state changes + const availableStates = useTimelineStore((state) => { + const { activeDocumentId } = state; + if (!activeDocumentId) return []; + const timeline = state.timelines.get(activeDocumentId); + if (!timeline) return []; + return Array.from(timeline.states.values()); + }); // Set editing tangible when initialEditingTangibleId changes useEffect(() => { diff --git a/src/stores/timelineStore.ts b/src/stores/timelineStore.ts index e61e970..26c651c 100644 --- a/src/stores/timelineStore.ts +++ b/src/stores/timelineStore.ts @@ -225,6 +225,11 @@ export const useTimelineStore = create( // Mark document as dirty useWorkspaceStore.getState().markDocumentDirty(activeDocumentId); + // Trigger auto-save after 1 second (consistent with other operations) + setTimeout(() => { + useWorkspaceStore.getState().saveDocument(activeDocumentId); + }, 1000); + useToastStore.getState().showToast(`State "${label}" created`, "success"); return newStateId; @@ -365,6 +370,11 @@ export const useTimelineStore = create( // Mark document as dirty useWorkspaceStore.getState().markDocumentDirty(activeDocumentId); + + // Trigger auto-save after 1 second (consistent with other operations) + setTimeout(() => { + useWorkspaceStore.getState().saveDocument(activeDocumentId); + }, 1000); }, deleteState: (stateId: StateId) => { @@ -453,6 +463,11 @@ export const useTimelineStore = create( // Mark document as dirty useWorkspaceStore.getState().markDocumentDirty(activeDocumentId); + // Trigger auto-save after 1 second (consistent with other operations) + setTimeout(() => { + useWorkspaceStore.getState().saveDocument(activeDocumentId); + }, 1000); + useToastStore .getState() .showToast(`State "${stateName}" deleted`, "info");