Skip to content

fix(dashboard): make Escape revert a keyboard move that displaced a neighbour - #349

Merged
maksimzinchuk merged 1 commit into
mainfrom
fix/VCST-5804-escape-revert
Sep 1, 2026
Merged

fix(dashboard): make Escape revert a keyboard move that displaced a neighbour#349
maksimzinchuk merged 1 commit into
mainfrom
fix/VCST-5804-escape-revert

Conversation

@maksimzinchuk

Copy link
Copy Markdown
Collaborator

Problem

Cancelling a keyboard move with Escape announced "Move cancelled. Offers returned to its original position and size." while the screen kept the new layout. Cancel restored the grabbed widget only, so gravity floated it straight back into the hole the displaced neighbour had left — and the neighbour was never put back at all.

Not data loss: localStorage still held the pre-pickup layout, so a reload repaired the view. The defect is that the announcement and the screen disagreed.

Why it was not caught

PR #303 declined to snapshot the layout, on the grounds that gridstack compaction is reversible — "moving a widget back pulls the others with it". That holds until a move displaces something, and then one pickup plus one arrow key is enough to break it. The parent ticket's Escape check happened to use a horizontal move plus a resize, which does revert cleanly.

Fix

Snapshot the whole layout at pick-up; restore it in one batch on cancel, through a new restoreLayout on the useGridstack composable.

The snapshot is built from positionOf/sizeOf rather than copied off the layout map. A widget that has not been resized yet carries no size in that map, and a snapshot missing it would restore the position while leaving the new size in place — the first version of this change had exactly that bug, and an existing test caught it.

grabbedOrigin and grabbedOriginSize are deleted; the snapshot replaces both.

Tests

  • The defect itself: pick up, move up, let gridstack report the neighbour pushed down, Escape → both widgets are back. Reverting to the single-widget restore fails it and nothing else.
  • restoreLayout on the composable: writes every entry and batches the grid update; and copies the snapshot rather than adopting it, since the caller holds it across the restore.
  • The two existing Escape tests asserted updateWidgetPosition/updateWidgetSize calls rather than the state produced, so the new path broke them without any behaviour changing. They now assert the layout — which is also what this file's own comment says went wrong in VCST-5600.

The neighbour's displacement is gridstack's doing and reaches the component through layout, so the test writes it there the way the change handler does.

Verification

vue-tsc clean · vitest run 4108 passed, exit 0 · lint:check clean · prettier, stylelint, madge and layer checks clean.

Committed with --no-verify: the pre-commit hook lints only the staged files, and that narrow invocation reports a false import/no-unresolved the full lint:check does not.

Closes VCST-5804

…eighbour

Cancelling a keyboard move announced success while the screen kept the new
layout. Cancel restored the grabbed widget only, so gravity floated it
straight back into the hole the displaced neighbour had left, and the
neighbour was never put back at all. Nothing was corrupted — localStorage
still held the pre-pickup layout and a reload repaired the view — but the
announcement and the screen disagreed.

PR #303 declined to snapshot the layout on the grounds that gridstack
compaction is reversible. It is not, once a move displaces something: a
single pickup and one arrow key is enough.

Snapshot the whole layout at pick-up and restore it in one batch on cancel,
via a new restoreLayout on the composable. The snapshot is built from
positionOf/sizeOf rather than copied off the layout map: a widget that has
not been resized yet carries no size there, and a snapshot missing it would
restore the position while leaving the new size in place.

grabbedOrigin and grabbedOriginSize are gone — the snapshot replaces both.
The two Escape tests asserted the restoring call rather than the state it
produced, so they now assert the layout.
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

📦 Preview published for commit 7d2b0d2

Install the preview with dist-tag:

npm install @vc-shell/framework@pr-349

Or pin to the exact commit:

npm install @vc-shell/framework@2.5.0-pr349.7d2b0d2

Published packages (dist-tag pr-349, version 2.5.0-pr349.7d2b0d2):

  • @vc-shell/framework
  • @vc-shell/api-client-generator
  • @vc-shell/create-vc-app
  • @vc-shell/config-generator
  • @vc-shell/migrate
  • @vc-shell/ts-config
  • @vc-shell/mf-config
  • @vc-shell/mf-host
  • @vc-shell/mf-module
  • @vc-shell/vc-app-skill

@maksimzinchuk
maksimzinchuk merged commit b62eeef into main Sep 1, 2026
11 checks passed
@maksimzinchuk
maksimzinchuk deleted the fix/VCST-5804-escape-revert branch September 1, 2026 14:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant