Skip to content

R8a: gate notifications on type preference, wire up node font styling (findings #10, #11) - #174

Merged
dovvnloading merged 1 commit into
mainfrom
r8a/notification-gating-and-font-wiring
Jul 29, 2026
Merged

R8a: gate notifications on type preference, wire up node font styling (findings #10, #11)#174
dovvnloading merged 1 commit into
mainfrom
r8a/notification-gating-and-font-wiring

Conversation

@dovvnloading

Copy link
Copy Markdown
Owner

Problem

Two settings from the R8a audit persisted real state that nothing consumed:

  • Finding Modernize cloud and Ollama model settings #10: Settings' Info/Success/Warning/Error notification-type checkboxes wrote real preferences via SettingsManager.set_notification_preferences, and get_notification_type_enabled already existed to read them back, but NotificationState.show() set visible = True unconditionally. Unchecking a type had no effect on whether its banner appeared.
  • Finding Modernize Graphlink Composer to a production-grade request surface #11: The View popover's FONT section (family select, size slider, color swatches) already round-tripped real setFontFamily/setFontSize/setFontColor intents into scene state, but nothing on the frontend ever consumed scene.fontFamily/fontSizePt/fontColor as CSS. Changing any of the three controls visibly changed nothing on the canvas.

Change

  • backend/notifications.py: register_notifications now takes an optional SettingsManager. NotificationState.show() early-returns (leaving any currently-visible banner untouched) when the message's type is disabled in preferences. The gate lives in the one method every existing notifications.show(...) call site already goes through (canvas.py, agents.py, chat_library.py, settings.py, plugins.py, autosave.py, crash_recovery.py), so all of them are covered without individual changes. backend/app.py now passes the session's real settings manager through.
  • web_ui/src/app/canvas/SceneCanvas.tsx: writes scene.fontFamily/fontSizePt/fontColor onto the canvas wrapper as --gl-node-font-family/-size/-color custom properties. fontSizePt is points (backend field font_size_pt, range 8-16, default 9) — pt is a real CSS unit, so no conversion needed beyond the correct suffix.
  • web_ui/src/app/styles.css: .scene-node, .scene-node-title, and .scene-node-body reference the new tokens with their prior literal values as fallbacks. Scoped to the shared base rules (title bar, generic body text) rather than each node kind's own content styling, so markdown heading hierarchy and monospace code blocks keep their own intentional typography.

Test plan

Layer Result
npx tsc --noEmit clean
npx vitest run (full suite) 868/868 passed
python -m pytest -q (full suite) 1041/1041 passed (8 new)
npm run lint clean (0 errors)

New coverage: backend/tests/test_notifications.py (gating on/off per type, a suppressed show() doesn't clobber a currently-visible banner of a different type, dismiss() unaffected by preferences, register_notifications wiring, and the pre-existing no-settings-manager call sites still always show).

Live-verified end to end against a running instance (real WS round-trip, not a mock): dragging the font-size slider, picking a font family, and picking a font color each immediately restyled a real canvas node's title and body text to the new values; the initial page load already reflected the backend's default font settings correctly.

… (findings #10, #11)

Two dead settings from the R8a audit, both with real backend/UI wiring
already in place on one side only.

- Notification-type gating (finding #10): Settings' Info/Success/Warning/
  Error checkboxes persisted real preferences via SettingsManager.
  set_notification_preferences, and get_notification_type_enabled already
  existed to read them back - nothing ever called it. NotificationState.show()
  set visible=True unconditionally regardless of what the user had
  unchecked. register_notifications now takes an optional SettingsManager;
  show() early-returns (leaving the current banner, if any, untouched) when
  the message's type is disabled. Gating lives in the one method every call
  site already goes through, so every existing notifications.show(...) call
  across canvas.py, agents.py, chat_library.py, settings.py, plugins.py,
  autosave.py, and crash_recovery.py is covered without touching any of
  them.

- View popover FONT section (finding #11): the family/size/color controls
  already round-tripped real setFontFamily/setFontSize/setFontColor intents
  into scene state - nothing consumed scene.fontFamily/fontSizePt/fontColor
  as CSS. SceneCanvas now writes them as --gl-node-font-family/-size/-color
  custom properties on the canvas wrapper (fontSizePt is points, not
  pixels - the existing 8-16 range and 9pt default only make sense that
  way, and pt is a real CSS unit). .scene-node/.scene-node-title/
  .scene-node-body reference the tokens with their prior literal values as
  fallbacks, so every node's title and generic body text now responds to
  the FONT section live. Scoped to the shared base rules rather than each
  node kind's own content styling (markdown headings, code blocks) so
  typographic hierarchy and monospace code stay intact.

Live-verified end to end in a running instance: changing the font size
slider, family select, and color swatch each visibly restyled a real
canvas node's title and body text; toggling a notification type off
suppressed that type's banner while leaving others unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dovvnloading
dovvnloading merged commit a5be489 into main Jul 29, 2026
2 checks passed
@dovvnloading
dovvnloading deleted the r8a/notification-gating-and-font-wiring branch July 29, 2026 10:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant