mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
zoom: _saveZoom is view-only — editor 500% can no longer leak into the per-space store
The exit-editor restore re-saved the view zoom from a rAF; on a slow
tablet the floor-tab click lands before that rAF (input runs first in
the frame), the snap.space guard skipped the fix-up save and the editor
wheel zoom (500%) stayed in _zoomBySpace/LS_ZOOM — the second floor
switch brought it back into view mode (owner's dacha report). Now
_saveZoom simply refuses to write while _mode is not 'view': the wheel
inside the editors keeps zooming but never touches the per-space view
store, so no fix-up is needed at all. The snapshot restore keeps
bringing the pre-editor viewport back. Smoke: smoke_zoom_out.mjs grows
the owner's exact scenario (both floors zoomed in view, editor 5.0,
same-tick switch after exit, two floor switches) — red before, green
now; the 6d16f69 asserts stay green.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -108,6 +108,42 @@ out.viewZoomSurvivesSpaceSwitch = await page.evaluate(async () => {
|
||||
});
|
||||
await page.evaluate(() => window.__card._resetZoom());
|
||||
|
||||
// -- owner's dacha regression: editor 500% must never reach the per-space
|
||||
// view store. View zoom set on BOTH floors, editor cranked to 5.0, back to
|
||||
// view — and the floor tab is clicked in the SAME tick (on the tablet the
|
||||
// exit re-render janks, so the click runs before the restore rAF and the
|
||||
// old fix-up save was skipped). Two switches later the stale 5.0 came back.
|
||||
out.editorZoomNeverInSpaceStore = await page.evaluate(async () => {
|
||||
const c = window.__card;
|
||||
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
const raf2 = () => new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)));
|
||||
c._setMode('view');
|
||||
c._resetZoom(); c._zoomAt(10, 10, 1.6); c._saveZoom(); // floor 1 view zoom
|
||||
c._slideTo('garden', 'left'); await wait(350);
|
||||
c._resetZoom(); c._zoomAt(10, 10, 1.4); c._saveZoom(); // floor 2 view zoom
|
||||
c._setMode('devices'); await raf2();
|
||||
c._zoomAt(10, 10, 5.0); c._saveZoom(); // 500% — a working tool
|
||||
const lsInEditor = JSON.parse(localStorage.getItem('houseplan_card_zoom_v1') || '{}');
|
||||
c._setMode('view');
|
||||
c._slideTo('f1', 'right'); await wait(350); // same tick as the exit — beats the rAF
|
||||
const firstSwitch = Math.abs(c._zoom - 1.6) < 0.01;
|
||||
c._slideTo('garden', 'left'); await wait(350);
|
||||
const secondSwitch = Math.abs(c._zoom - 1.4) < 0.01; // used to come back as 5.0
|
||||
const ls = JSON.parse(localStorage.getItem('houseplan_card_zoom_v1') || '{}');
|
||||
c._slideTo('f1', 'right'); await wait(350); c._resetZoom(); // leave the stage as the next tests expect
|
||||
return {
|
||||
editorNotPersisted: Math.abs((lsInEditor.garden || 1) - 1.4) < 0.01,
|
||||
firstSwitch,
|
||||
secondSwitch,
|
||||
lsClean: Math.abs((ls.garden || 1) - 1.4) < 0.01 && Math.abs((ls.f1 || 1) - 1.6) < 0.01,
|
||||
};
|
||||
});
|
||||
out.editorZoomStaysOutOfLs = out.editorZoomNeverInSpaceStore.editorNotPersisted;
|
||||
out.ownerFirstSwitchOk = out.editorZoomNeverInSpaceStore.firstSwitch;
|
||||
out.ownerSecondSwitchOk = out.editorZoomNeverInSpaceStore.secondSwitch;
|
||||
out.ownerLsClean = out.editorZoomNeverInSpaceStore.lsClean;
|
||||
delete out.editorZoomNeverInSpaceStore;
|
||||
|
||||
// -- devices outside rooms stretch the default frame ---------------------
|
||||
out.devicesStretchFrame = await page.evaluate(() => {
|
||||
const c = window.__card;
|
||||
|
||||
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -1543,8 +1543,16 @@ class HouseplanCard extends LitElement {
|
||||
this._saveZoom();
|
||||
}
|
||||
|
||||
/** Save the current space zoom to localStorage. */
|
||||
/** Save the current space zoom to localStorage (view mode only). */
|
||||
private _saveZoom(): void {
|
||||
// Editor zoom is a working tool, never the viewing intent: while an editor
|
||||
// is open the wheel/pinch keep calling _saveZoom, but the per-space VIEW
|
||||
// zoom must not learn about it. The exit-editor restore used to re-save the
|
||||
// view zoom from a rAF — on a slow tablet the floor-tab click lands BEFORE
|
||||
// that rAF (input runs first in the frame), the space guard skipped the
|
||||
// fix-up and the editor 500% stayed in _zoomBySpace/LS_ZOOM for the next
|
||||
// visit to that floor. Editors do not need zoom persistence at all.
|
||||
if (this._mode !== 'view') return;
|
||||
this._zoomBySpace = { ...this._zoomBySpace, [this._space]: this._zoom };
|
||||
try {
|
||||
localStorage.setItem(LS_ZOOM, JSON.stringify(this._zoomBySpace));
|
||||
|
||||
Reference in New Issue
Block a user