Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions engraphis/classic_assets/dashboard.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 24 additions & 9 deletions engraphis/dashboard_assets/engraphis-graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -912,8 +912,9 @@
});
}

/* The dashboard already honours `prefers-reduced-motion` for the classic renderer; this
engine must not quietly reintroduce perpetual motion for the same user. */
/* Reduced motion still controls cosmetic animation and camera transitions. Physics is
deliberately controlled by the visible Freeze switch instead: otherwise the switch can
say "off" while an OS preference silently leaves every graph static. */
function reduced() {
if (typeof opts.reducedMotion === 'function') return !!opts.reducedMotion();
try {
Expand Down Expand Up @@ -1381,13 +1382,24 @@
Shared so reheat() and freeze() cannot drift back to the small-graph constant. */
function alphaDecay() { return large ? 0.055 : 0.035; }

// Rendering while frozen deliberately gives force-graph a one-tick budget. Keep the
// matching live values in one place so unfreezing after a style, scope, or data render
// cannot reheat against that stale one-tick budget.
function setSimulationBudget(live) {
const simulate = live && !staticFullLayout;
if (fg.cooldownTime) fg.cooldownTime(simulate ? (large ? 1100 : 2200) : 0);
if (fg.cooldownTicks) fg.cooldownTicks(simulate ? (large ? 80 : 160) : 1);
if (fg.warmupTicks) fg.warmupTicks(simulate ? (large ? 18 : 40) : 0);
}

function render(fit, reheat) {
if (destroyed) return;
if (suspended) {
pendingRender = pendingRender ? [pendingRender[0] || fit, pendingRender[1] || reheat] : [fit, reheat];
return;
}
const motion = !reduced();
const motion = !state.settings.frozen;
Comment thread
Coding-Dev-Tools marked this conversation as resolved.
Comment thread
Coding-Dev-Tools marked this conversation as resolved.
const reducedMotion = reduced();
Comment thread
Coding-Dev-Tools marked this conversation as resolved.
const next = visible();
/* Reuse the arrays force-graph already holds when the view is unchanged: the sizing and
colouring pass below must write onto the objects the vendor is painting from, and the
Expand Down Expand Up @@ -1432,9 +1444,7 @@
/* Bound the simulation the way the classic path does. Without these force-graph keeps its
15-second default window, so every load and every reheat of a large store runs the
layout — and repaints every node and link — for more than ten seconds longer. */
if (fg.cooldownTime) fg.cooldownTime(motion && !staticFullLayout ? (large ? 1100 : 2200) : 0);
if (fg.cooldownTicks) fg.cooldownTicks(motion && !staticFullLayout ? (large ? 80 : 160) : 1);
if (fg.warmupTicks) fg.warmupTicks(motion && !staticFullLayout ? (large ? 18 : 40) : 0);
setSimulationBudget(motion);
if (fg.d3AlphaDecay) fg.d3AlphaDecay(staticFullLayout ? 1 : alphaDecay());
if (fg.d3VelocityDecay) fg.d3VelocityDecay(large ? 0.45 : 0.38);
if (fg.linkCurvature) {
Expand All @@ -1446,6 +1456,7 @@
const flowing = !fullGraph
&& state.settings.flow !== false
&& motion
&& !reducedMotion
&& data.links.length <= PARTICLE_LINK_LIMIT;
const particles = !flowing
? 0
Expand All @@ -1462,8 +1473,9 @@
but Style, Color by and Labels all just changed how the *same* data must be drawn. */
if (reused) invalidate();
if (fit) {
const animateFit = motion && !reducedMotion;
clearTimeout(fitTimer);
fitTimer = setTimeout(() => { if (!destroyed) autoFit(motion ? 600 : 0, 40); }, motion ? 320 : 0);
fitTimer = setTimeout(() => { if (!destroyed) autoFit(animateFit ? 600 : 0, 40); }, animateFit ? 320 : 0);
}
if (opts.onStats) opts.onStats({ nodes: data.nodes.length, links: data.links.length, total: raw.nodes.length, totalLinks: raw.links.length, preset: (PRESETS[state.settings.mode] || PRESETS.compact).label, collapsed: collapsed, ghosts: data.nodes.filter(n => n.ghost).length, bridges: data.links.filter(l => l.bridge).length, suggested: data.links.filter(l => l.suggested).length });
}
Expand Down Expand Up @@ -1781,7 +1793,7 @@
};
api.fit = () => { if (!destroyed) fg.zoomToFit(reduced() ? 0 : 500, 40); };
api.reheat = () => {
if (destroyed || reduced() || staticFullLayout) return;
if (destroyed || state.settings.frozen || staticFullLayout) return;
raw.nodes.forEach(n => { n.fx = undefined; n.fy = undefined; });
if (fg.d3ReheatSimulation) { fg.d3AlphaDecay(alphaDecay()); fg.d3ReheatSimulation(); }
};
Expand All @@ -1798,7 +1810,10 @@
if (staticFullLayout) return;
raw.nodes.forEach(n => { n.fx = undefined; n.fy = undefined; });
applyForces();
if (reduced()) return;
setSimulationBudget(true);
// A frozen render removes relation-flow particles. Reapply the live paint settings
// before reheating so the enabled flow switch immediately becomes visible again.
render(false, false);
fg.d3AlphaDecay(alphaDecay());
if (fg.d3ReheatSimulation) fg.d3ReheatSimulation();
};
Expand Down
6 changes: 3 additions & 3 deletions engraphis/dashboard_assets/ledger.js
Original file line number Diff line number Diff line change
Expand Up @@ -1596,7 +1596,6 @@
palette: byId('graph-palette').value,
flow: byId('graph-flow').getAttribute('aria-checked') === 'true',
labels: byId('graph-labels').getAttribute('aria-checked') === 'true',
frozen: state.graphFrozen,
tuning: graphTuningSettings(),
minDegree: number(byId('graph-min-degree').value),
depth: number(byId('graph-depth').value),
Expand Down Expand Up @@ -1654,7 +1653,9 @@
byId('graph-ghosts').checked = graphPreference('ghosts', byId('graph-ghosts').checked) !== false;
byId('graph-size').value = graphPreference('size', byId('graph-size').value,
['degree', 'betweenness']);
state.graphFrozen = graphPreference('frozen', false) === true;
// Freeze is deliberately session-only. A previously frozen arrangement must not make a
// freshly opened graph look broken; physics starts live until the person clicks Freeze.
state.graphFrozen = false;
setGraphSwitch('graph-freeze', state.graphFrozen);
setGraphSwitch('graph-flow', graphPreference('flow', true) !== false);
setGraphSwitch('graph-labels', graphPreference('labels', false) === true);
Expand Down Expand Up @@ -1700,7 +1701,6 @@
? view.repoFilter.slice(0, 200) : byId('graph-repo-filter').value;
state.graphIncludeCode = typeof view.includeCode === 'boolean'
? view.includeCode : state.graphIncludeCode;
state.graphFrozen = typeof view.frozen === 'boolean' ? view.frozen : state.graphFrozen;
byId('graph-preset').value = preset;
byId('graph-style').value = style;
byId('graph-color').value = color;
Expand Down
Loading