Commit Graph

6 Commits

Author SHA1 Message Date
simoleo89 ba77806f52 wired-tools(store): hoist variable-key records (selectedInspectionVariableKeys, selectedVariableKeys)
Move the last two `Record<...Type, string>` useStates out of
WiredCreatorToolsView into useWiredCreatorToolsUiStore. Both writers
were already using the `prev => ({ ...prev, [key]: value })` updater
shape, so the new store setters expose `Updater<Record<...>>` to keep
existing call sites verbatim.

Initial values default to empty strings; the existing
`variableDefinitionsByType` sync effect at WiredCreatorToolsView.tsx
:1543-1574 already populates valid keys on first render and reconciles
whenever the server-side definitions change. Closing/reopening the panel
now preserves the active picker key instead of resetting it.

Tests: 4 new cases on the store (updater shape, single-key patch
preserving siblings, direct-record write path, panel-lifecycle
persistence). Suite: 197/197 (was 193/193).
2026-05-18 20:36:17 +02:00
simoleo89 181ca096d0 wired-tools: hoist inline editor state (variables + managed holder) to the store
Move the four inline-editor useStates out of WiredCreatorToolsView and
into useWiredCreatorToolsUiStore:

- editingVariable / editingValue — Inspection-tab variables-table
  inline edit (current key being edited + in-flight input text).
- editingManagedHolderVariableId / editingManagedHolderValue — same
  pair for the Variable Manage panel's holder rows (id 0 = none).

WiredInspectionTabView drops three more props (editingVariable,
editingValue, onEditingValueChange) and consumes the store directly
for the read sides + the per-keystroke setEditingValue. The cancel /
keydown / begin handlers stay in the parent because they wrap
shouldPauseVariableSnapshotRefresh-aware logic plus selection
bookkeeping that doesn't belong to a pure tab body.

The shouldPauseVariableSnapshotRefresh derived flag still reads from
the same store now-backed values; no behaviour change on the polling
suppression path.

Tests: three new cases (set+read pair, null-clear, managed-holder
0-as-sentinel reset). 193/193 passing.
2026-05-16 12:37:29 +02:00
simoleo89 0fc32a1e19 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.
2026-05-16 12:31:19 +02:00
simoleo89 8182e06be4 wired-tools: hoist inspection selection (+ live state + action version) to the store
Five more useStates leave WiredCreatorToolsView: selectedFurni,
selectedFurniLiveState, selectedUser, selectedUserLiveState, and the
monotonic selectedUserActionVersion counter. All five now live in
useWiredCreatorToolsUiStore; the room-event listeners
(useObjectSelectedEvent, the per-kind useMessageEvent + useNitroEvent
handlers, the per-action effects that bump the version counter) stay
in the component because they need React's subscription lifecycle —
they just call the store actions instead of setState.

Same persistence benefit as the previous monitorSnapshot pass: the
currently-inspected target survives a panel close/reopen instead of
being dropped to null on remount. Live-state setters and the action
version counter accept Updater<T> so the many `previousValue => ...`
call sites stayed verbatim.

Tests: six new cases (setSelectedFurni + null clear, functional
updater on FurniLiveState, paired setSelectedUser + LiveState,
monotonic ActionVersion via updater, close/reopen persistence). The
test fixtures use the real interface shapes — InspectionFurniSelection
includes a renderer-typed `info: AvatarInfoFurni` that is cast
through `as never` so the test doesn't have to construct the full
avatar info shape. 187/187 passing.
2026-05-16 12:25:31 +02:00
simoleo89 82bccd4040 wired-tools: hoist monitorSnapshot + polling reset to the Zustand store
Move the monitor snapshot off WiredCreatorToolsView's useState into
useWiredCreatorToolsUiStore. The WiredMonitorDataEvent listener still
lives in the component (it can't move alongside without dragging
useMessageEvent into the store), but it now writes to setMonitorSnapshot
and the room-change reset calls resetMonitorSnapshot() instead of
re-instantiating the default in the component.

Direct benefit: the snapshot now survives closing and reopening the
panel between two server pushes. Before this commit, the parent
remounted on every visibility flip (parent renders null while
`!isVisible`) which dropped the snapshot back to the empty default;
the user would briefly see zeroed stats until the next `monitor:fetch`
roundtrip landed. Holding the snapshot in zustand decouples the data
from the component's mount lifecycle.

Tests: three new cases on the store cover setMonitorSnapshot,
resetMonitorSnapshot returning a fresh empty instance, and the
"close/reopen panel preserves snapshot" lifecycle. Total 181/181.
2026-05-16 12:20:35 +02:00
simoleo89 8b4308af16 tests: co-locate every Vitest suite next to its subject under src/
Eliminate the parallel `tests/` tree. Each `*.test.ts` / `*.test.tsx`
now sits in the same directory as the module it covers, mirroring its
filename (`Foo.ts` ↔ `Foo.test.ts`). The renderer-SDK mock used by
component / hook tests moves to `src/__mocks__/nitro-renderer.ts` and
the Vitest setup file becomes `src/test-setup.ts` — both still wired
through `vitest.config.mts` exactly as before, only the paths changed.

All 13 suites + 178/178 cases still pass. The production build is
unaffected: rollup only follows imports from `src/index.tsx` and never
crosses into `.test.ts` files, so test code is naturally tree-shaken
out of the bundle. `yarn build` output is byte-for-byte the same on
the user-facing chunks.

tsconfig drops the now-redundant `tests` include entry. CLAUDE.md
'Layout convention' replaces the old `tests/` row with three rows
documenting the new co-located convention, the `__mocks__/` directory
and the `test-setup.ts` entry; ARCHITECTURE.md picks up the same
update. The 'DO NOT CHANGE' qualifier on the layout is preserved —
this rewrite IS the change, decided deliberately to make tests a
first-class part of the source tree rather than a sibling project.
2026-05-16 11:35:03 +02:00