mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
perf: reuse masonry after cancelled resize
Issue: #322 User-Visible: no
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -199,6 +199,9 @@ if (target) {
|
||||
// The second gesture leaves the circle by much more than its hit radius.
|
||||
// Pointer capture must keep the real browser stream alive; Esc then cancels
|
||||
// the already-visible overlay without a second persistence write.
|
||||
await page.evaluate(() => {
|
||||
window.__resizeWallUnionBefore = window.__card._wallUnionGeometry();
|
||||
});
|
||||
const outsideDistance = Math.max(120, target.hitWidth * 2);
|
||||
await page.mouse.move(...target.start);
|
||||
await page.mouse.down();
|
||||
@@ -211,11 +214,16 @@ if (target) {
|
||||
await page.mouse.up();
|
||||
await settle();
|
||||
check('resize_pointer.escape_restores_config', await persistedGeometry(), stableAfterUndo);
|
||||
check('resize_pointer.escape_reuses_pre_drag_wall_union', await page.evaluate(() =>
|
||||
window.__card._wallUnionGeometry() === window.__resizeWallUnionBefore), true);
|
||||
await page.waitForTimeout(650);
|
||||
check('resize_pointer.escape_zero_extra_write', await page.evaluate(() => window.__resizeWrites.length), writesBefore + 2);
|
||||
|
||||
// A different pointer cannot take over an active drag. Losing capture for
|
||||
// the owning pointer is an abort, never a commit of the visible preview.
|
||||
await page.evaluate(() => {
|
||||
window.__resizeWallUnionBefore = window.__card._wallUnionGeometry();
|
||||
});
|
||||
await page.mouse.move(...target.start);
|
||||
await page.mouse.down();
|
||||
await page.evaluate(({ x, y }) => {
|
||||
@@ -246,6 +254,8 @@ if (target) {
|
||||
await settle();
|
||||
check('resize_pointer.capture_loss_restores_dom', await domHasSharedX(400), true);
|
||||
check('resize_pointer.capture_loss_restores_config', await persistedGeometry(), stableAfterUndo);
|
||||
check('resize_pointer.capture_loss_reuses_pre_drag_wall_union', await page.evaluate(() =>
|
||||
window.__card._wallUnionGeometry() === window.__resizeWallUnionBefore), true);
|
||||
await page.waitForTimeout(650);
|
||||
check('resize_pointer.capture_loss_zero_extra_write', await page.evaluate(() => window.__resizeWrites.length), writesBefore + 2);
|
||||
}
|
||||
|
||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
@@ -2,7 +2,7 @@
|
||||
"version": 1,
|
||||
"fixture": "synthetic-only",
|
||||
"chromium": "151.0.7922.34",
|
||||
"sourceFingerprint": "b02ada1b0cc255adaac71a7493e154c2ce867dce60a65ab1b3cfdf39058605f2",
|
||||
"sourceFingerprint": "d3f9271c3a64836abe0b0907e6f33c8c78cca844bc1cdb5f96d198d664f457bb",
|
||||
"captureScriptSha256": "ce2e9542fed9dade3085be87d16f69adb2ac8262893ad78ad966b1b9673f2983",
|
||||
"command": "npm run build && node demo/docs/capture.mjs",
|
||||
"scenarios": {
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "b02ada1b0cc255adaac71a7493e154c2ce867dce60a65ab1b3cfdf39058605f2",
|
||||
"sourceSha256": "d3f9271c3a64836abe0b0907e6f33c8c78cca844bc1cdb5f96d198d664f457bb",
|
||||
"imageSha256": "36223106c073f07d8cc3ecf8eaab37192ebb2687daba65c5c21047d0b7890de0"
|
||||
},
|
||||
"view-touch": {
|
||||
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "b02ada1b0cc255adaac71a7493e154c2ce867dce60a65ab1b3cfdf39058605f2",
|
||||
"sourceSha256": "d3f9271c3a64836abe0b0907e6f33c8c78cca844bc1cdb5f96d198d664f457bb",
|
||||
"imageSha256": "41e3ba67f8db0e98f26f484293af83ef937c369ca5ca6a59a3350d8954c906f4"
|
||||
},
|
||||
"space-create": {
|
||||
@@ -36,7 +36,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "b02ada1b0cc255adaac71a7493e154c2ce867dce60a65ab1b3cfdf39058605f2",
|
||||
"sourceSha256": "d3f9271c3a64836abe0b0907e6f33c8c78cca844bc1cdb5f96d198d664f457bb",
|
||||
"imageSha256": "0dc024726327f60f4a9ceaf3044381691f81f1090af81d1812e870f22d9343ba"
|
||||
},
|
||||
"room-contour-close": {
|
||||
@@ -47,7 +47,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "b02ada1b0cc255adaac71a7493e154c2ce867dce60a65ab1b3cfdf39058605f2",
|
||||
"sourceSha256": "d3f9271c3a64836abe0b0907e6f33c8c78cca844bc1cdb5f96d198d664f457bb",
|
||||
"imageSha256": "44cfaa95bd51e2cd628400e28db0ad8b2f0cd904385845bd402494f3f5c0d93c"
|
||||
},
|
||||
"plan-context-tray": {
|
||||
@@ -58,7 +58,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "b02ada1b0cc255adaac71a7493e154c2ce867dce60a65ab1b3cfdf39058605f2",
|
||||
"sourceSha256": "d3f9271c3a64836abe0b0907e6f33c8c78cca844bc1cdb5f96d198d664f457bb",
|
||||
"imageSha256": "e0662429b423fb74151b583dcc2c8635b001b637d03bbf7a6b16aec46399c3f8"
|
||||
},
|
||||
"device-editor": {
|
||||
@@ -69,7 +69,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "b02ada1b0cc255adaac71a7493e154c2ce867dce60a65ab1b3cfdf39058605f2",
|
||||
"sourceSha256": "d3f9271c3a64836abe0b0907e6f33c8c78cca844bc1cdb5f96d198d664f457bb",
|
||||
"imageSha256": "d0ffd31ce80bfde21ab75da356a5fc1af38246f2b301030880320620c228d89d"
|
||||
},
|
||||
"device-display-preview": {
|
||||
@@ -80,7 +80,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "b02ada1b0cc255adaac71a7493e154c2ce867dce60a65ab1b3cfdf39058605f2",
|
||||
"sourceSha256": "d3f9271c3a64836abe0b0907e6f33c8c78cca844bc1cdb5f96d198d664f457bb",
|
||||
"imageSha256": "2cdabae1f89c3286e4fac0ce30f757ee1690b707ab8a5488748b7cd420626160"
|
||||
},
|
||||
"background-editor": {
|
||||
@@ -91,7 +91,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "b02ada1b0cc255adaac71a7493e154c2ce867dce60a65ab1b3cfdf39058605f2",
|
||||
"sourceSha256": "d3f9271c3a64836abe0b0907e6f33c8c78cca844bc1cdb5f96d198d664f457bb",
|
||||
"imageSha256": "30147bb00a90eea7136b4cee30995f6e6a9217b5132f3e8d3ad7471413b1af8a"
|
||||
},
|
||||
"room-card": {
|
||||
@@ -102,7 +102,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "b02ada1b0cc255adaac71a7493e154c2ce867dce60a65ab1b3cfdf39058605f2",
|
||||
"sourceSha256": "d3f9271c3a64836abe0b0907e6f33c8c78cca844bc1cdb5f96d198d664f457bb",
|
||||
"imageSha256": "029a3e69ec647a8a370d99e6bb7f9225833c526739076022f6b52ba54bff30ea"
|
||||
},
|
||||
"device-info": {
|
||||
@@ -113,7 +113,7 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "b02ada1b0cc255adaac71a7493e154c2ce867dce60a65ab1b3cfdf39058605f2",
|
||||
"sourceSha256": "d3f9271c3a64836abe0b0907e6f33c8c78cca844bc1cdb5f96d198d664f457bb",
|
||||
"imageSha256": "dd492f53150b7149085daada5cce9eeae9bde9e7ea1d86679a54b3041f72f517"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1684,6 +1684,9 @@ class HouseplanCard extends LitElement {
|
||||
d: number;
|
||||
changed: string[];
|
||||
rejectNotified: boolean;
|
||||
/** Exact pre-drag masonry retained so Cancel can restore the real frame
|
||||
* without rebuilding the same expensive boolean union under a new epoch. */
|
||||
wallUnionBefore: ReturnType<typeof wallBodiesUnionPath>;
|
||||
} | null = null;
|
||||
private _rszEligibilityCache: {
|
||||
key: string;
|
||||
@@ -9016,11 +9019,15 @@ class HouseplanCard extends LitElement {
|
||||
capturePointer(ev);
|
||||
const plan = resolution.plan;
|
||||
const start = this._svgPoint(ev);
|
||||
const wallUnionKey = `${this._space}|${this._cfgEpoch}|${rooms.length}`;
|
||||
const wallUnionBefore = this._wallUnionCache?.key === wallUnionKey
|
||||
? this._wallUnionCache.value : null;
|
||||
this._rszDrag = {
|
||||
pid: ev.pointerId, start: [start[0], start[1]], roomId, plan,
|
||||
opts: this._rszOptsFor(plan.a, plan.b),
|
||||
rooms, openings: this._rszOpenings(), snap: this._rszSnapshot(),
|
||||
moved: false, d: 0, changed: [...plan.roomIds], rejectNotified: false,
|
||||
wallUnionBefore,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9126,12 +9133,27 @@ class HouseplanCard extends LitElement {
|
||||
private _rszCancelDrag(): void {
|
||||
const g = this._rszDrag;
|
||||
if (!g) return;
|
||||
const snapshotStillCurrent = this._rszSnapshot() === g.snap;
|
||||
this._rszDrag = null;
|
||||
this._rszLive = null;
|
||||
// HP-1550-01/-03: a cancel just drops the overlay — the real config was
|
||||
// never touched, so there is nothing to restore, no undo step and no write
|
||||
this._rszPreview = null;
|
||||
this._cfgEpoch++;
|
||||
if (snapshotStillCurrent && g.wallUnionBefore) {
|
||||
// The server-backed geometry did not change during the gesture. The
|
||||
// preview advanced the structural epoch and temporarily selected its
|
||||
// candidate union, but Cancel returns to the byte-identical pre-drag
|
||||
// config. Alias that already-proved result under the fresh epoch instead
|
||||
// of paying another O(n log n) polygon union on the next paint.
|
||||
const space = this._spaceModel();
|
||||
if (space) {
|
||||
const key = `${this._space}|${this._cfgEpoch}|${space.rooms.length}`;
|
||||
const entry = { key, value: g.wallUnionBefore };
|
||||
lruWrite(this._wallUnionPool, key, entry, 8);
|
||||
this._wallUnionCache = entry;
|
||||
}
|
||||
}
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user