Compare commits
2 Commits
f9860fd701
...
f242bbd8a6
| Author | SHA1 | Date | |
|---|---|---|---|
| f242bbd8a6 | |||
| 85bb0c8c0b |
@@ -20,7 +20,12 @@ class GridStackLayout extends HTMLElement {
|
||||
disconnectedCallback() {
|
||||
this.observer?.disconnect();
|
||||
this.observer = undefined;
|
||||
clearTimeout(this.persistTimer);
|
||||
// Write out a still-pending debounced save instead of dropping it:
|
||||
// a drag/resize followed straight away by navigating to another route
|
||||
// detaches this element inside the debounce window, which used to lose
|
||||
// the very last layout change. The server is not notified — its view is
|
||||
// going away with us.
|
||||
this.flushPersist();
|
||||
this.grid?.destroy(false); // keep DOM — Flow owns the children
|
||||
this.grid = undefined;
|
||||
}
|
||||
@@ -99,16 +104,28 @@ class GridStackLayout extends HTMLElement {
|
||||
|
||||
private schedulePersist() {
|
||||
clearTimeout(this.persistTimer);
|
||||
this.persistTimer = setTimeout(() => this.persist(), 150);
|
||||
this.persistTimer = setTimeout(() => {
|
||||
this.persistTimer = undefined;
|
||||
this.persist();
|
||||
}, 150);
|
||||
}
|
||||
|
||||
private persist() {
|
||||
private flushPersist() {
|
||||
if (this.persistTimer === undefined) return;
|
||||
clearTimeout(this.persistTimer);
|
||||
this.persistTimer = undefined;
|
||||
this.persist(false);
|
||||
}
|
||||
|
||||
private persist(notifyServer = true) {
|
||||
if (!this.grid) return;
|
||||
const nodes = this.grid.save(false) as GridStackNode[];
|
||||
if (this.storageKey) {
|
||||
localStorage.setItem(STORAGE_PREFIX + this.storageKey, JSON.stringify(nodes));
|
||||
}
|
||||
(this as any).$server?.onLayoutChange(JSON.stringify(nodes));
|
||||
if (notifyServer) {
|
||||
(this as any).$server?.onLayoutChange(JSON.stringify(nodes));
|
||||
}
|
||||
}
|
||||
|
||||
private restore() {
|
||||
@@ -122,13 +139,22 @@ class GridStackLayout extends HTMLElement {
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
if (!Array.isArray(nodes)) return;
|
||||
|
||||
for (const node of nodes) {
|
||||
if (!node.id) continue;
|
||||
const el = this.querySelector(`:scope > [gs-id="${node.id}"]`) as HTMLElement | null;
|
||||
if (!el) continue; // item no longer present server-side — skip, degrade gracefully
|
||||
this.grid.update(el, { x: node.x, y: node.y, w: node.w, h: node.h });
|
||||
}
|
||||
// Items dropped server-side since the layout was saved are skipped, so a
|
||||
// stale entry degrades gracefully instead of blocking the restore.
|
||||
const known = nodes.filter((node) => node.id
|
||||
&& this.querySelector(`:scope > [gs-id="${CSS.escape(String(node.id))}"]`));
|
||||
if (!known.length) return;
|
||||
|
||||
// load() rather than a per-item update() loop: it sorts the saved nodes,
|
||||
// pulls them out of the engine before re-placing them, and does the whole
|
||||
// thing in one batch. Updating item by item let a later item collide with
|
||||
// one already put back and push it off its saved spot for good — the
|
||||
// restored layout was then not the one the user left. load() also re-applies
|
||||
// gridstack's w/h defaults, which save() omits when they are 1.
|
||||
// `false` keeps add/remove off: Flow owns which children exist.
|
||||
this.grid.load(known, false);
|
||||
}
|
||||
|
||||
private intAttr(el: HTMLElement, name: string): number | undefined {
|
||||
|
||||
@@ -179,18 +179,17 @@ public class GridStackLayout extends Component implements HasSize, HasStyle {
|
||||
String id = node.path("id").asString(null);
|
||||
if (id == null) continue;
|
||||
|
||||
findItem(id).ifPresent(item -> item.setPosition(
|
||||
node.path("x").asInt(),
|
||||
node.path("y").asInt(),
|
||||
node.path("w").asInt(),
|
||||
node.path("h").asInt()));
|
||||
// gridstack omits w/h from its saved layout when they are 1, so a
|
||||
// missing value means 1 — defaulting to 0 wrote a zero-sized widget
|
||||
// back onto the item and lost its size on the next attach.
|
||||
int x = node.path("x").asInt(0);
|
||||
int y = node.path("y").asInt(0);
|
||||
int w = node.path("w").asInt(1);
|
||||
int h = node.path("h").asInt(1);
|
||||
|
||||
positions.add(new GridStackItem.Position(
|
||||
id,
|
||||
node.path("x").asInt(),
|
||||
node.path("y").asInt(),
|
||||
node.path("w").asInt(),
|
||||
node.path("h").asInt()));
|
||||
findItem(id).ifPresent(item -> item.setPosition(x, y, w, h));
|
||||
|
||||
positions.add(new GridStackItem.Position(id, x, y, w, h));
|
||||
}
|
||||
|
||||
fireEvent(new LayoutChangeEvent(this, true, positions));
|
||||
|
||||
Reference in New Issue
Block a user