mirror of
https://github.com/penpot/penpot.git
synced 2026-08-09 06:18:47 +00:00
🐛 Guard renders against heavy graphs; add ?safe escape hatch
A heavy file could freeze the tab on load-and-render despite the animation gate: the render guard counted nodes only, and the edge-bundling plugin is iteration-heavy in edges. Guard now also trips on edges (8000), edge bundling only activates at <= 300 edges, and /dbg/graph?safe disables auto-render entirely (counts + "Render anyway"), so a page that hung can always be re-entered with the session intact. Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
This commit is contained in:
parent
82746bbf06
commit
dd5c9b0cba
@ -570,9 +570,16 @@ Graph Console
|
||||
// Legend glyph characters mirroring the G6 node types above.
|
||||
const GLYPH_CHARS = { diamond: "◆", rect: "■", hexagon: "⬢",
|
||||
circle: "●", triangle: "▲", star: "★" };
|
||||
// Above this many nodes the view is not rendered automatically; the
|
||||
// "Render anyway" button forces it (~1.5 s per 2k nodes, measured).
|
||||
// Above this many nodes/edges the view is not rendered automatically;
|
||||
// the "Render anyway" button forces it (~1.5 s per 2k nodes, measured;
|
||||
// edges gate the guard too since plugin/combo cost scales with them).
|
||||
// Escape hatch: /dbg/graph?safe disables auto-render entirely, so a
|
||||
// page that hung on render can always be re-entered.
|
||||
const RENDER_GUARD_NODES = 4000;
|
||||
const RENDER_GUARD_EDGES = 8000;
|
||||
// Edge bundling is iteration-heavy in the number of edges — a
|
||||
// page-freezing cost at scale; bundle only small graphs.
|
||||
const BUNDLE_MAX_EDGES = 300;
|
||||
// G6's entrance/update animation is nice didactics on small graphs but
|
||||
// the performance killer at scale (>2 min at 1700 nodes vs ~1.5 s off);
|
||||
// keep it only below this node count.
|
||||
@ -910,7 +917,7 @@ Graph Console
|
||||
// empty canvas clears. Runs alongside the node:click inspector.
|
||||
{ type: "click-select", degree: 1,
|
||||
state: "selected", neighborState: "active", unselectedState: "inactive" }],
|
||||
plugins: [{key: "edge-bundling", type: "edge-bundling"},{
|
||||
plugins: [{
|
||||
key: "toolbar",
|
||||
type: "toolbar",
|
||||
position: "top-left",
|
||||
@ -936,6 +943,9 @@ Graph Console
|
||||
}]
|
||||
};
|
||||
if (layoutCfg) opts.layout = layoutCfg;
|
||||
if (g6data.edges.length <= BUNDLE_MAX_EDGES) {
|
||||
opts.plugins.unshift({ key: "edge-bundling", type: "edge-bundling" });
|
||||
}
|
||||
g6graph = new G6.Graph(opts);
|
||||
// Re-attached on every instance creation (layout/animation switches
|
||||
// destroy and recreate the graph).
|
||||
@ -1070,9 +1080,14 @@ Graph Console
|
||||
? " — query filter: " + data.nodes.length + " of "
|
||||
+ lastGraphData.nodes.length + " nodes"
|
||||
: "";
|
||||
if (shown.nodes.length > RENDER_GUARD_NODES && !renderForced) {
|
||||
const safeMode = new URLSearchParams(location.search).has("safe");
|
||||
if ((safeMode
|
||||
|| shown.nodes.length > RENDER_GUARD_NODES
|
||||
|| shown.edges.length > RENDER_GUARD_EDGES) && !renderForced) {
|
||||
graphViewStatus.textContent =
|
||||
graphStatusText(data) + filterNote + " — too large to render automatically";
|
||||
graphStatusText(data) + filterNote
|
||||
+ (safeMode ? " — safe mode (?safe): auto-render off"
|
||||
: " — too large to render automatically");
|
||||
if (anywayBtn) anywayBtn.style.display = "inline";
|
||||
return;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user