fix(reorder): trap layer-list drag drop as a data change and persist it

List_PreviewMouseMove reorders StagedScene.Elements via RemoveAt/Insert,
bypassing SceneGraph's mutation surface, but never scheduled a save — the
new z-order was lost on restart. The drop now sets _dragReordered and
EndListDrag funnels it through MainViewModel.OnSceneElementsReordered()
(InvalidateBake + ScheduleSave, same background-save path as every other
mutation). Integration test (RealApp + temp DB) reproduces the exact
code-behind mutation and asserts the debounced save lands the new Source
SortOrder. Derivation reference: standard WPF ItemsControl drag-reorder
pattern (OBS layering semantics: bottom-most layer = index 0).
This commit is contained in:
2026-09-18 08:18:51 -07:00
parent fd5198df9f
commit c11788574e
4 changed files with 197 additions and 10 deletions
+23 -10
View File
@@ -1,22 +1,17 @@
# HANDOFF — 2026-09-17 (webcam attainability refinement committed locally at `75723ac` — no push)
# HANDOFF — 2026-09-18 (layer drag-reorder persistence fix committed locally — no push)
## Branch / Commit State
`main` HEAD = **`75723ac` fix(webcam): offer the Web Cam row only when a camera is attainable
(live lock), not merely selected** (local). Below it:
`main` HEAD = **layer drag-reorder now traps + persists** (local, this session — the new
`LayerReorderPersistenceTests`). Below it:
- `75723ac` fix(webcam): offer the Web Cam row only when a camera is attainable (live lock)
- `9d00955` feat(webcam): app-default gate slice — per-scene offer, Add places default directly,
identity survives removal
- `1e4017d` feat(webcam): resource lifecycle startup slice — poll-on-start, single-cam lock,
persistent Layers alert
- `94a934f` reader-output-subtype ladder + WinRT per-call wrap rule
- `64a5a6d` slice-18 C4 blit-on-change composite cache
- `b37b8a3` slice-17 overlap GPU readbacks with monotonic publish gate
**No push yet** — still awaiting the device take + user greenlight. Working tree clean.
> Correcting the previous handoff, which still listed HEAD as `1e4017d`: the gate slice
> (`9d00955`) and its attainability refinement (`75723ac`) are both committed now.
**No push yet.** Working tree clean.
## ⚠️ Branding (2026-09-14, creator-corrected): product = **llamacasty**, internals = ytLive
@@ -63,6 +58,18 @@ the availability layer. TASK 26's app-wide gate is **superseded** by creator dir
**Task docs:** `TASKS.md` Open items + `ai.md` Webcam section updated (supersession recorded).
## ✅ Committed — layer-list drag-to-reorder persists (creator-reported, 2026-09-18)
The drag code in `Controls/LeftPanel.xaml.cs` reordered `StagedScene.Elements` directly
(`RemoveAt`/`Insert` in `List_PreviewMouseMove`), bypassing `SceneGraph`'s mutation surface — the
collection changed visually but nothing ever scheduled a save, so the new z-order was lost on
restart. Fix: the drag sets `_dragReordered` and `EndListDrag` funnels the drop through the new
`MainViewModel.OnSceneElementsReordered()` (Sources.cs) = `SceneGraph.InvalidateBake(staged) +
ScheduleSave()`, i.e. the same background-save path every other mutation uses. **Good Dog test**
`LayerReorderPersistenceTests` (real App + temp DB): reproduces the exact code-behind mutation,
calls the trap, pumps the dispatcher until the debounced save lands, asserts the DB `Source`
SortOrder matches the in-memory `Elements` order.
## ✅ Earlier committed — webcam resource lifecycle (startup slice, `1e4017d`)
Startup poll + tri-state (`ValidateWebcamResourceStartupAsync` after `LoadLayout`): 0 → run on,
@@ -77,6 +84,9 @@ claim — `CameraConflictProbe` reads process names only, no device handles; do
## ⚠️ Open items
- **RenameRecordingDialog too short (creator-reported, QUEUED next):** the recording save/confirm
dialog cuts off the file-name textbox — increase its height by ~20% (+ its one integration test,
Good Dog).
- **Webcam take fix 2 of 2 — the 09:16 crash is UNFIXED (hard, untested):** hypothesis — native WMF
death when `MediaCapture.Failed` fires mid-stream and `SafeStopAsync` (fire-and-forget) disposes
reader+capture while the frame thread sits in `TryAcquireLatestFrame`/`Marshal.Copy` (outside the
@@ -133,6 +143,9 @@ claim — `CameraConflictProbe` reads process names only, no device handles; do
- ffmpeg/ffprobe: `/mnt/c/Program Files/Krita (x64)/bin/` with Windows paths.
- `MyMistakes.md`: WINRT resource-allocation RECIPE, freeze-audit RECIPE, A/V sync recipe, deadline
pacing, CoreMessaging DQ, WGC-CLIP + slice blocks. Grep before re-deriving.
- **Scene.Elements layer tests:** any seeded scene with `HasBackground=1` loads a healed
`Background` element pinned at `Elements[0]` (created by `EnsureBackground` on `StagedScene` set) —
compute expected layer orders from the live collection, never hardcode indices.
- `C:\tmpout` is for ffmpeg evidence artifacts; keep them out of the repo.
## Next step