fix: read live node width in draw() instead of a stale LiteGraph cache; cache-bust shared module imports
- LiteGraph caches a widget's .width the first time it lays a custom-typed widget out and reuses that cached value on every later draw() call. For a divider/status/preset widget added before the node reaches its final size, that cached width goes stale and never updates, making section-divider lines and the status box stop partway across the node instead of spanning it, and clipping/unevenly sizing the preset chips. All three shared widgets now read node.size[0] directly in draw() instead of trusting the widgetWidth parameter, which sidesteps the stale cache entirely. - Add a ?v=2 query string to every import of the shared/*.mjs modules. aiohttp's static file server doesn't send Cache-Control: no-store for these (unlike the top-level registered extension .js files), so browsers were free to keep serving an old cached copy even across a hard reload. A versioned import URL forces a fresh fetch regardless of cache state.
This commit is contained in:
@@ -6,6 +6,16 @@
|
||||
// rather than a hardcoded value — a fixed/wrong computeSize previously broke
|
||||
// node layout on click when this was tried without care (see the comment on
|
||||
// the preset-chip widget in smart_resize.js's git history).
|
||||
//
|
||||
// draw() intentionally ignores its own `widgetWidth` parameter and reads
|
||||
// `node.size[0]` instead. LiteGraph caches a `.width` on custom-typed widget
|
||||
// objects the first time it lays them out and reuses that cached value on
|
||||
// later draws — for a widget added before the node reaches its final size
|
||||
// (e.g. before later Python widgets are added, or before an explicit
|
||||
// node.setSize() call), that cache goes stale and draw() keeps receiving the
|
||||
// old, too-narrow width forever, making the divider line/status box stop
|
||||
// partway across the node instead of spanning it. node.size[0] is always
|
||||
// live, so reading it directly sidesteps the stale cache entirely.
|
||||
|
||||
const DIVIDER_HEIGHT = 20;
|
||||
|
||||
@@ -20,6 +30,7 @@ export function createDividerWidget(label) {
|
||||
return [width, DIVIDER_HEIGHT];
|
||||
},
|
||||
draw(ctx, node, widgetWidth, y, height) {
|
||||
const w = node?.size?.[0] || widgetWidth;
|
||||
const lx = 14;
|
||||
ctx.save();
|
||||
ctx.font = "bold 10px sans-serif";
|
||||
@@ -30,7 +41,7 @@ export function createDividerWidget(label) {
|
||||
const lineX = lx + ctx.measureText(label).width + 8;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(lineX, y + height / 2);
|
||||
ctx.lineTo(widgetWidth - 14, y + height / 2);
|
||||
ctx.lineTo(w - 14, y + height / 2);
|
||||
ctx.strokeStyle = "#333";
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
@@ -53,8 +64,9 @@ export function createStatusWidget(placeholderText) {
|
||||
return [width, STATUS_HEIGHT];
|
||||
},
|
||||
draw(ctx, node, widgetWidth, y, height) {
|
||||
const w = node?.size?.[0] || widgetWidth;
|
||||
const margin = 14;
|
||||
const innerW = widgetWidth - margin * 2;
|
||||
const innerW = w - margin * 2;
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
if (ctx.roundRect) ctx.roundRect(margin, y + 2, innerW, height - 4, 4);
|
||||
@@ -68,7 +80,7 @@ export function createStatusWidget(placeholderText) {
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.fillStyle = this._text ? "#f28f41" : "#666";
|
||||
ctx.fillText(this._text || placeholderText, widgetWidth / 2, y + height / 2);
|
||||
ctx.fillText(this._text || placeholderText, w / 2, y + height / 2);
|
||||
ctx.restore();
|
||||
},
|
||||
};
|
||||
|
||||
@@ -15,9 +15,12 @@ function createClassicPresetWidget(node, targetWidget, presets) {
|
||||
return [width, PRESET_ROW_HEIGHT];
|
||||
},
|
||||
draw(ctx, node, widgetWidth, y, height) {
|
||||
// Read the live node width rather than the (possibly stale-cached)
|
||||
// widgetWidth parameter — see the comment in canvas_widgets.mjs.
|
||||
const w = node?.size?.[0] || widgetWidth;
|
||||
const margin = 14;
|
||||
const gap = 5;
|
||||
const innerW = Math.max(40, widgetWidth - margin * 2);
|
||||
const innerW = Math.max(40, w - margin * 2);
|
||||
const n = presets.length;
|
||||
const cellW = Math.max(10, (innerW - gap * (n - 1)) / n);
|
||||
const h = Math.min(height - 2, 18);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { createDividerWidget, createStatusWidget } from "./shared/canvas_widgets.mjs";
|
||||
import { createPresetPickerWidget } from "./shared/preset_picker_widget.mjs";
|
||||
import { isVueNodes } from "./shared/nodes2.mjs";
|
||||
import { createDividerWidget, createStatusWidget } from "./shared/canvas_widgets.mjs?v=2";
|
||||
import { createPresetPickerWidget } from "./shared/preset_picker_widget.mjs?v=2";
|
||||
import { isVueNodes } from "./shared/nodes2.mjs?v=2";
|
||||
|
||||
app.registerExtension({
|
||||
name: "Craftopia.SmartBatchResize",
|
||||
@@ -149,5 +149,12 @@ app.registerExtension({
|
||||
node.setDirtyCanvas(true);
|
||||
};
|
||||
|
||||
// Force a full size/layout recompute now that every widget has been
|
||||
// added and repositioned. Without this, the preset-chip row's very
|
||||
// first paint can use a stale/undersized widgetWidth (from before the
|
||||
// node's final layout settled), rendering uneven or clipped chips
|
||||
// until the next unrelated redraw fixes it.
|
||||
node.setSize(node.computeSize());
|
||||
node.setDirtyCanvas(true, true);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { createDividerWidget, createStatusWidget } from "./shared/canvas_widgets.mjs";
|
||||
import { createDividerWidget, createStatusWidget } from "./shared/canvas_widgets.mjs?v=2";
|
||||
|
||||
app.registerExtension({
|
||||
name: "Craftopia.SmartProfileSwitch",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { createStatusWidget } from "./shared/canvas_widgets.mjs";
|
||||
import { createStatusWidget } from "./shared/canvas_widgets.mjs?v=2";
|
||||
|
||||
app.registerExtension({
|
||||
name: "Craftopia.SmartPromptController",
|
||||
|
||||
+8
-2
@@ -1,6 +1,6 @@
|
||||
import { app } from "../../scripts/app.js";
|
||||
import { createPresetPickerWidget } from "./shared/preset_picker_widget.mjs";
|
||||
import { isVueNodes } from "./shared/nodes2.mjs";
|
||||
import { createPresetPickerWidget } from "./shared/preset_picker_widget.mjs?v=2";
|
||||
import { isVueNodes } from "./shared/nodes2.mjs?v=2";
|
||||
|
||||
app.registerExtension({
|
||||
name: "Craftopia.SmartResize",
|
||||
@@ -40,5 +40,11 @@ app.registerExtension({
|
||||
node.widgets.splice(lsIdx + 1, 0, presetWidget);
|
||||
}
|
||||
}
|
||||
|
||||
// Force a full size/layout recompute now that the preset widget has
|
||||
// been added and repositioned — see the comment in
|
||||
// smart_batch_resize.js for why this is needed.
|
||||
node.setSize(node.computeSize());
|
||||
node.setDirtyCanvas(true, true);
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user