Skip to content

feat(extension): live-layout CSP fix + scatter-then-organize settle + structural radial Circular - #170

Merged
dgtalbug merged 3 commits into
mainfrom
feature/obsidian-graph-polish
Jun 7, 2026
Merged

feat(extension): live-layout CSP fix + scatter-then-organize settle + structural radial Circular#170
dgtalbug merged 3 commits into
mainfrom
feature/obsidian-graph-polish

Conversation

@dgtalbug

@dgtalbug dgtalbug commented Jun 7, 2026

Copy link
Copy Markdown
Owner

Summary

Three graph-UX follow-ups to PR #169 (graph overhaul). Webview-only; no core/host/contract change. extension 669 green.

Commits

  • 03d8db9 fix: worker-src blob: in webview CSP — THE reason the live layout never animated: default-src 'none' with no worker-src CSP-blocked the FA2 Web Worker (blob URL), so it silently fell back to a static seed. Added the directive + a regression test.
  • 852e86f livelier settle (scatter-then-organize) — we pre-solved 200 FA2 iterations before first paint, so the worker had nothing to animate ('moves but feels dead'). Now an 8-iteration warm-up + the worker visibly organizes; slowDown 3→1 (energetic), run 2.5s→3.5s. Plus scalingRatio 6→8 for wider main-view spacing.
  • 58836eb structural radial Circular — the flat single-ring Circular is now concentric-by-role: hubs at the centre (in-degree + entry-point), leaves on the rim, ring radius grows with node count, ring order minimises edge crossings.

Test plan

  • pnpm check green: core 282 / exporters 161 / extension 669
  • New tests: CSP worker-src assertion; structural-radial (hub more central than leaves)
  • No core/host/exporters/contract change

🤖 Generated with Claude Code

dgtalbug added 3 commits June 7, 2026 23:48
…out animates

THE reason nodes were static: the webview CSP was default-src 'none' with no
worker-src. graphology's FA2LayoutSupervisor creates its Web Worker from a Blob
URL; with no worker-src the browser falls back to child-src → default-src 'none'
and CSP-blocks the worker. The supervisor threw on construction, the try/catch
swallowed it, and the graph silently fell back to the static seed layout — so no
animation ever ran.

Add 'worker-src blob:' to the CSP. Sigma already auto-refreshes on graph node-attr
updates (bindGraphHandlers → scheduleRefresh), so once the worker ticks positions
the canvas repaints → live settle. Added an html.test assertion so the directive
can't silently regress.
…acing

Lively: the graph was pre-solved (200 FA2 iterations) before first paint, so the
live worker had nothing left to animate — 'moves but feels dead'. Now when the
live worker will run, the seed is a light 8-iteration warm-up (grouped but loose)
and the worker visibly ORGANIZES it; slowDown 3→1 makes per-tick motion
energetic; run window 2.5s→3.5s. Full 200-iter pre-solve kept only for the
no-worker static fallback.

Cleaner spacing (both views): main-view FA2 scalingRatio 6→8 spreads nodes wider
(less tangle). Focused view: ring radius now grows with node count (min arc per
card) so dense rings expand outward instead of packing cards on top of each other;
base ring spacing 220→280.

extension 668.
…ves on the rim

The Circular preset was a flat single ring (all nodes equidistant, arbitrary
order) — not the GitNexus-style structured circle. Rework it into a concentric
radial layout driven by graph role:

- leaves (outDegree 0) → outermost ring
- hubs (high in-degree + entry-point bonus) → innermost rings
- others ranked between by in-degree, spread across the inner rings

Within each ring, nodes are ordered by the mean angle of their already-placed
inner neighbours so ring→ring edges run centre→out (radial), which minimises
crossings (cannot eliminate them for non-planar graphs). Ring radius grows with
node count (min arc per node) so dense rings expand outward instead of stacking.

Also aligned the preset-file FA2 settings (scalingRatio 8) with the tuned mount
settings so re-applying ForceAtlas2 matches the initial layout. extension 669
(+ a test asserting hubs land more central than leaves).
@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7acc3a74-55eb-4e88-9ab2-203c11170a00

📥 Commits

Reviewing files that changed from the base of the PR and between 56dd4ed and 58836eb.

📒 Files selected for processing (6)
  • packages/extension/src/webview/blast-radius/focusedLayout.ts
  • packages/extension/src/webview/components/SigmaController.ts
  • packages/extension/src/webview/components/graphLayoutPresets.test.ts
  • packages/extension/src/webview/components/graphLayoutPresets.ts
  • packages/extension/src/webview/html.test.ts
  • packages/extension/src/webview/html.ts

📝 Walkthrough

Summary

User-visible / reviewer-relevant changes:

  • CSP fix enables FA2 web worker execution: Added worker-src 'blob:' directive to webview Content Security Policy, allowing the ForceAtlas2 layout worker (created from Blob URL) to run. Previously silently blocked by default CSP.
  • Circular layout restructured by node role: Replaced flat single-ring layout with concentric radial rings: hubs (high in-degree + entry-points) positioned centrally, leaves on outer rings, ranked by in-degree. Ring ordering uses inner-neighbor angles to reduce crossings.
  • Live layout startup optimized for visibility: Changed from heavy 200-iteration pre-solve to lightweight 8-iteration warm-up seed when worker available; increases apparent responsiveness with visible organization. Full pre-solve retained for static fallback (no worker). Adjusted scalingRatio (6→8) and slowDown (3→1) for wider spacing and energetic initial animation.
  • Ring spacing adjusted for dense graphs: FOCUSED_RING_SPACING increased (220→280) and ring radius now computed as max(ring * spacing, perimeterNeed) to expand dense rings outward based on FOCUSED_MIN_ARC_PER_NODE, reducing node overlap.

Risks:

  • Mount-time FA2 behavior now conditionally differs based on Worker availability (lightweight vs. full pre-solve). Graph initial state depends on runtime worker detection.
  • Circular layout behavior significantly changed; dependent code/plugins expecting single-ring structure will see different positioning.
  • Ring radius calculation is now node-count-dependent; sparse vs. dense ring behaviors differ.

Validation:

  • Regression test added for CSP directive presence.
  • New structural-radial test asserts hub nodes are more central than leaves; focused-layout ring-spacing validated indirectly through component tests.
  • Live-worker timing behavior (8-iteration warm-up vs. full pre-solve) not explicitly tested; validated via integration ("pnpm checks green").

Package/schema impact:

  • Webview-only changes; no core, host, exporter, or contract modifications.

Walkthrough

Five files updated across focused-card layout geometry, circular preset redesign, ForceAtlas2 seeding tuning, and Content Security Policy. Ring-based placement now dynamically expands for node density; circular preset applies role-based concentric rings instead of flat placement; mount-time warm-up iterations adapt to worker availability; and CSP explicitly permits blob-backed workers.

Changes

Radial layout and preset geometry

Layer / File(s) Summary
Focused layout ring expansion
packages/extension/src/webview/blast-radius/focusedLayout.ts
FOCUSED_RING_SPACING increased from 220 to 280; ring radius now computes as max(ring * spacing, perimeterNeed) using new FOCUSED_MIN_ARC_PER_NODE constant to prevent overlap in dense rings.
Circular preset structural radial redesign
packages/extension/src/webview/components/graphLayoutPresets.ts, packages/extension/src/webview/components/graphLayoutPresets.test.ts
Replaced single-ring layout with role-based concentric rings: leaves to outer ring, non-leaves ranked by in-degree with entry-point bonus, nodes ordered by mean inner-neighbor angle, radius computed from arc-per-node perimeter. Toolbar description updated. Hub-and-leaves test verifies hub is closer to origin than leaves.

ForceAtlas2 worker-aware tuning and enablement

Layer / File(s) Summary
ForceAtlas2 parameters and mount warm-up
packages/extension/src/webview/components/SigmaController.ts, packages/extension/src/webview/components/graphLayoutPresets.ts
scalingRatio adjusted to 8 in preset settings; added separate warm-up iteration count. mount() now conditionally runs lightweight FA2 warm-up (when Worker available) or full pre-solve (static fallback).
Web Worker CSP enablement
packages/extension/src/webview/html.ts, packages/extension/src/webview/html.test.ts
Added worker-src blob: CSP directive to permit ForceAtlas2 layout worker creation from Blob URLs. Test validates CSP includes the directive.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Circular preset redesign is dense logic with new ring assignment, centrality scoring, and coordinate math. Focused layout and FA2 tuning are straightforward constant/parameter changes. CSP is minimal. Geometry changes are semantically independent but interrelated in observable behavior. Requires tracing radial placement logic and validating hub/leaf ordering.

Possibly related PRs

  • dgtalbug/dextree#169: The focused-layout ring-radius and arc-sizing logic is directly part of the focused-card radial-on-select UX added in PR #169.
  • dgtalbug/dextree#154: SigmaController mount() ForceAtlas2 pre-solve and warm-up timing are in the same controller lifecycle logic refactored by PR #154.

Suggested labels

area:extension, type:feat


📐 Rings expand when crowded now,
🌐 Circular nodes find their role,
💼 Workers bloom from blobs below—
✨ Geometry made whole.


Comment @coderabbitai help to get the list of available commands and usage tips.

@dgtalbug
dgtalbug merged commit 8aaeb99 into main Jun 7, 2026
8 of 9 checks passed
@dgtalbug
dgtalbug deleted the feature/obsidian-graph-polish branch June 7, 2026 18:58
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Jun 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant