mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 15:06:20 +00:00
wired-tools: hoist variable-highlight toggle + overlays to the store
Move the highlight feature pair into useWiredCreatorToolsUiStore: isVariableHighlightActive (toggle UI flag) and variableHighlightOverlays (computed screen-space overlay positions). The two screen-coords effects in WiredCreatorToolsView stay where they are (they need React's lifecycle to install / tear down WiredSelectionVisualizer highlights on the active room objects) but now write to setVariableHighlightOverlays. WiredVariablesTabView drops the isVariableHighlightActive + onToggleVariableHighlight props and consumes the store directly — same shape as the previous tab-prop reductions on this branch. The toggle button keeps the same UX (Highlight ↔ Undo) but no longer crosses the prop boundary. Direct benefit: closing and reopening the panel while a variable highlight is active no longer flickers the overlays off and back on — the active flag + the last-computed overlay set both persist in zustand and the effect re-runs from the same starting point. Tests: three new cases on the store (toggle via direct + updater, overlay replace + clear, close/reopen persistence). 190/190 passing. variableHighlightObjectsRef stays a useRef inside the component: it tracks the live PIXI objects WiredSelectionVisualizer drew onto, used only for the cleanup pass — refs don't trigger renders and don't need to live in the store.
This commit is contained in:
@@ -77,8 +77,10 @@ export const WiredCreatorToolsView: FC<{}> = () =>
|
||||
const setIsManagedGiveOpen = useWiredCreatorToolsUiStore(s => s.setIsManagedGiveOpen);
|
||||
const [ managedGiveVariableItemId, setManagedGiveVariableItemId ] = useState(0);
|
||||
const [ managedGiveValue, setManagedGiveValue ] = useState('0');
|
||||
const [ isVariableHighlightActive, setIsVariableHighlightActive ] = useState(false);
|
||||
const [ variableHighlightOverlays, setVariableHighlightOverlays ] = useState<VariableHighlightOverlay[]>([]);
|
||||
const isVariableHighlightActive = useWiredCreatorToolsUiStore(s => s.isVariableHighlightActive);
|
||||
const setIsVariableHighlightActive = useWiredCreatorToolsUiStore(s => s.setIsVariableHighlightActive);
|
||||
const variableHighlightOverlays = useWiredCreatorToolsUiStore(s => s.variableHighlightOverlays);
|
||||
const setVariableHighlightOverlays = useWiredCreatorToolsUiStore(s => s.setVariableHighlightOverlays);
|
||||
const variableHighlightObjectsRef = useRef<Array<{ category: number; objectId: number; }>>([]);
|
||||
const shouldPauseVariableSnapshotRefresh = (!!editingVariable || !!editingManagedHolderVariableId || isInspectionGiveOpen || isManagedGiveOpen);
|
||||
const [ selectedVariableKeys, setSelectedVariableKeys ] = useState<Record<VariablesElementType, string>>({
|
||||
@@ -3145,8 +3147,6 @@ export const WiredCreatorToolsView: FC<{}> = () =>
|
||||
selectedVariableDefinition={ selectedVariableDefinition }
|
||||
onPickVariable={ key => setSelectedVariableKeys(prev => ({ ...prev, [variablesType]: key })) }
|
||||
canVariableHighlight={ canVariableHighlight }
|
||||
isVariableHighlightActive={ isVariableHighlightActive }
|
||||
onToggleVariableHighlight={ () => setIsVariableHighlightActive(value => !value) }
|
||||
variableManageCanOpen={ variableManageCanOpen }
|
||||
onOpenManagePanel={ () =>
|
||||
{
|
||||
|
||||
@@ -10,8 +10,6 @@ export interface WiredVariablesTabViewProps
|
||||
selectedVariableDefinition: VariableDefinition | null;
|
||||
onPickVariable: (key: string) => void;
|
||||
canVariableHighlight: boolean;
|
||||
isVariableHighlightActive: boolean;
|
||||
onToggleVariableHighlight: () => void;
|
||||
variableManageCanOpen: boolean;
|
||||
onOpenManagePanel: () => void;
|
||||
selectedVariableProperties: { key: string; value: string; }[];
|
||||
@@ -30,8 +28,6 @@ export const WiredVariablesTabView: FC<WiredVariablesTabViewProps> = ({
|
||||
selectedVariableDefinition,
|
||||
onPickVariable,
|
||||
canVariableHighlight,
|
||||
isVariableHighlightActive,
|
||||
onToggleVariableHighlight,
|
||||
variableManageCanOpen,
|
||||
onOpenManagePanel,
|
||||
selectedVariableProperties,
|
||||
@@ -40,6 +36,8 @@ export const WiredVariablesTabView: FC<WiredVariablesTabViewProps> = ({
|
||||
{
|
||||
const variablesType = useWiredCreatorToolsUiStore(s => s.variablesType);
|
||||
const setVariablesType = useWiredCreatorToolsUiStore(s => s.setVariablesType);
|
||||
const isVariableHighlightActive = useWiredCreatorToolsUiStore(s => s.isVariableHighlightActive);
|
||||
const setIsVariableHighlightActive = useWiredCreatorToolsUiStore(s => s.setIsVariableHighlightActive);
|
||||
|
||||
return (
|
||||
<div className="p-3 min-h-[360px] flex gap-4">
|
||||
@@ -83,7 +81,7 @@ export const WiredVariablesTabView: FC<WiredVariablesTabViewProps> = ({
|
||||
<Button
|
||||
disabled={ !canVariableHighlight }
|
||||
variant="secondary"
|
||||
onClick={ onToggleVariableHighlight }>
|
||||
onClick={ () => setIsVariableHighlightActive(value => !value) }>
|
||||
{ isVariableHighlightActive ? 'Undo' : 'Highlight' }
|
||||
</Button>
|
||||
<Button
|
||||
|
||||
@@ -22,7 +22,9 @@ const INITIAL = {
|
||||
selectedFurniLiveState: null,
|
||||
selectedUser: null,
|
||||
selectedUserLiveState: null,
|
||||
selectedUserActionVersion: 0
|
||||
selectedUserActionVersion: 0,
|
||||
isVariableHighlightActive: false,
|
||||
variableHighlightOverlays: []
|
||||
};
|
||||
|
||||
describe('useWiredCreatorToolsUiStore', () =>
|
||||
@@ -56,6 +58,8 @@ describe('useWiredCreatorToolsUiStore', () =>
|
||||
expect(state.selectedUser).toBeNull();
|
||||
expect(state.selectedUserLiveState).toBeNull();
|
||||
expect(state.selectedUserActionVersion).toBe(0);
|
||||
expect(state.isVariableHighlightActive).toBe(false);
|
||||
expect(state.variableHighlightOverlays).toEqual([]);
|
||||
});
|
||||
|
||||
describe('setIsVisible', () =>
|
||||
@@ -314,4 +318,42 @@ describe('useWiredCreatorToolsUiStore', () =>
|
||||
expect(useWiredCreatorToolsUiStore.getState().selectedFurni).toEqual(furniSelection);
|
||||
});
|
||||
});
|
||||
|
||||
describe('variable highlight', () =>
|
||||
{
|
||||
const overlay = { itemId: 1, key: 'foo', x: 100, y: 200, screenX: 100, screenY: 200, value: '42', objectId: 7, category: 10 } as never;
|
||||
|
||||
it('setIsVariableHighlightActive accepts a direct boolean and a toggle updater', () =>
|
||||
{
|
||||
useWiredCreatorToolsUiStore.getState().setIsVariableHighlightActive(true);
|
||||
expect(useWiredCreatorToolsUiStore.getState().isVariableHighlightActive).toBe(true);
|
||||
|
||||
useWiredCreatorToolsUiStore.getState().setIsVariableHighlightActive(prev => !prev);
|
||||
expect(useWiredCreatorToolsUiStore.getState().isVariableHighlightActive).toBe(false);
|
||||
|
||||
useWiredCreatorToolsUiStore.getState().setIsVariableHighlightActive(prev => !prev);
|
||||
expect(useWiredCreatorToolsUiStore.getState().isVariableHighlightActive).toBe(true);
|
||||
});
|
||||
|
||||
it('setVariableHighlightOverlays replaces the overlay array', () =>
|
||||
{
|
||||
useWiredCreatorToolsUiStore.getState().setVariableHighlightOverlays([ overlay ]);
|
||||
expect(useWiredCreatorToolsUiStore.getState().variableHighlightOverlays).toEqual([ overlay ]);
|
||||
|
||||
useWiredCreatorToolsUiStore.getState().setVariableHighlightOverlays([]);
|
||||
expect(useWiredCreatorToolsUiStore.getState().variableHighlightOverlays).toEqual([]);
|
||||
});
|
||||
|
||||
it('the highlight survives a panel close/reopen lifecycle', () =>
|
||||
{
|
||||
useWiredCreatorToolsUiStore.getState().setIsVariableHighlightActive(true);
|
||||
useWiredCreatorToolsUiStore.getState().setVariableHighlightOverlays([ overlay ]);
|
||||
|
||||
useWiredCreatorToolsUiStore.getState().setIsVisible(false);
|
||||
useWiredCreatorToolsUiStore.getState().setIsVisible(true);
|
||||
|
||||
expect(useWiredCreatorToolsUiStore.getState().isVariableHighlightActive).toBe(true);
|
||||
expect(useWiredCreatorToolsUiStore.getState().variableHighlightOverlays).toEqual([ overlay ]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createNitroStore } from '../../state/createNitroStore';
|
||||
import { createEmptyMonitorSnapshot } from './WiredCreatorTools.helpers';
|
||||
import { InspectionElementType, InspectionFurniLiveState, InspectionFurniSelection, InspectionUserLiveState, InspectionUserSelection, MonitorSnapshot, VariablesElementType, WiredToolsTab } from './WiredCreatorTools.types';
|
||||
import { InspectionElementType, InspectionFurniLiveState, InspectionFurniSelection, InspectionUserLiveState, InspectionUserSelection, MonitorSnapshot, VariableHighlightOverlay, VariablesElementType, WiredToolsTab } from './WiredCreatorTools.types';
|
||||
|
||||
type MonitorSeverityFilter = 'ALL' | 'ERROR' | 'WARNING';
|
||||
type Updater<T> = T | ((prev: T) => T);
|
||||
@@ -55,6 +55,16 @@ interface WiredCreatorToolsUiState
|
||||
selectedUserLiveState: InspectionUserLiveState | null;
|
||||
selectedUserActionVersion: number;
|
||||
|
||||
/**
|
||||
* Variable highlight feature: the toggle UI flag (`isActive`) plus
|
||||
* the computed screen-space overlays the parent's effect populates
|
||||
* from `WiredSelectionVisualizer` + `GetRoomObjectScreenLocation`.
|
||||
* Stored together so a panel close/reopen cycle keeps the active
|
||||
* highlight visible instead of re-toggling from scratch.
|
||||
*/
|
||||
isVariableHighlightActive: boolean;
|
||||
variableHighlightOverlays: VariableHighlightOverlay[];
|
||||
|
||||
setIsVisible: (next: Updater<boolean>) => void;
|
||||
setActiveTab: (next: WiredToolsTab) => void;
|
||||
setInspectionType: (next: InspectionElementType) => void;
|
||||
@@ -81,6 +91,9 @@ interface WiredCreatorToolsUiState
|
||||
setSelectedUser: (next: InspectionUserSelection | null) => void;
|
||||
setSelectedUserLiveState: (next: Updater<InspectionUserLiveState | null>) => void;
|
||||
setSelectedUserActionVersion: (next: Updater<number>) => void;
|
||||
|
||||
setIsVariableHighlightActive: (next: Updater<boolean>) => void;
|
||||
setVariableHighlightOverlays: (next: VariableHighlightOverlay[]) => void;
|
||||
}
|
||||
|
||||
export const useWiredCreatorToolsUiStore = createNitroStore<WiredCreatorToolsUiState>()((set) => ({
|
||||
@@ -110,6 +123,9 @@ export const useWiredCreatorToolsUiStore = createNitroStore<WiredCreatorToolsUiS
|
||||
selectedUserLiveState: null,
|
||||
selectedUserActionVersion: 0,
|
||||
|
||||
isVariableHighlightActive: false,
|
||||
variableHighlightOverlays: [],
|
||||
|
||||
setIsVisible: (next) => set(state => ({ isVisible: apply(state.isVisible, next) })),
|
||||
setActiveTab: (next) => set({ activeTab: next }),
|
||||
setInspectionType: (next) => set({ inspectionType: next }),
|
||||
@@ -135,5 +151,8 @@ export const useWiredCreatorToolsUiStore = createNitroStore<WiredCreatorToolsUiS
|
||||
setSelectedFurniLiveState: (next) => set(state => ({ selectedFurniLiveState: apply(state.selectedFurniLiveState, next) })),
|
||||
setSelectedUser: (next) => set({ selectedUser: next }),
|
||||
setSelectedUserLiveState: (next) => set(state => ({ selectedUserLiveState: apply(state.selectedUserLiveState, next) })),
|
||||
setSelectedUserActionVersion: (next) => set(state => ({ selectedUserActionVersion: apply(state.selectedUserActionVersion, next) }))
|
||||
setSelectedUserActionVersion: (next) => set(state => ({ selectedUserActionVersion: apply(state.selectedUserActionVersion, next) })),
|
||||
|
||||
setIsVariableHighlightActive: (next) => set(state => ({ isVariableHighlightActive: apply(state.isVariableHighlightActive, next) })),
|
||||
setVariableHighlightOverlays: (next) => set({ variableHighlightOverlays: next })
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user