Split FrameSettings.tsx, and make its surface gating a reviewable table - #473
Open
mariusandra wants to merge 1 commit into
Open
Split FrameSettings.tsx, and make its surface gating a reviewable table#473mariusandra wants to merge 1 commit into
mariusandra wants to merge 1 commit into
Conversation
The per-frame Settings panel was one 4,297-line component whose surface gating was forty nested ternaries over `cloudProfile`, `esp32CloudProfile`, `inFrameAdminMode` and `hideForCloud`. It could not be reviewed by hand, and it had drifted: commit 97c8c75 wrapped a long stretch of JSX in `{!cloudProfile ? …}` and swept the cloud's "SSH keys" section inside it, so the settings nav offered a link to an anchor no cloud frame rendered, and a cloud Linux frame's SD-card keys could not be edited at all. `frameSettingsSurface.ts` is now the panel's only surface gate: a table of every section with the surfaces that render it, the surfaces whose nav links it (with a written reason wherever a section opts out), and the per-frame conditions each section still decides for itself. `<FrameSettingsSection>` refuses to render a section the table does not list for the current surface, so nothing can appear on a plane by accident. The panel resolves to one of four surfaces — backend, frameAdmin, cloudLinux, cloudEsp32 — because a cloud ESP32 accepts a strictly narrower `set_settings` set than a cloud Pi. frame-settings-surface.test.ts pins that table against `allowedFrameSettingsSections` in workspaceSurfaces.ts in both directions, so a nav link can no longer point at a heading the panel does not draw. The panel test gains the two SSH-keys cases. The file splits into: the ESP32 board tables (esp32Hardware.ts, pure data), the derived-values context (frameSettingsContext.tsx), the field blocks the cloud and self-hosted surfaces share (fields/sharedFields.tsx), the actions dropdown, and six section modules. FrameSettings.tsx is now the list of sections and their keys. Verified by rendering all thirteen frame/surface combinations before and after and diffing the HTML: byte-identical everywhere except the restored SSH-keys section. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qunf3ap3xUWL5iYZA4ZopM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
frontend/src/scenes/frame/panels/FrameSettings/FrameSettings.tsxwas one4,297-line component. Its surface gating was forty nested ternaries over
cloudProfile,esp32CloudProfile,inFrameAdminModeandhideForCloud,spread over two thousand lines between where a flag was derived and where it
was used.
docs/review-todo.mdlisted the split as a larger task because thatgating "cannot be reviewed by hand, which is how a cloud-only finding survived
the first pass".
The drift it was hiding
Commit
97c8c750wrapped a long stretch of the JSX in{!cloudProfile ? … }and swept the cloud's SSH keys section inside it.
cloudProfile === hideForCloud, so{hideForCloud && !esp32CloudProfile ? …}nested in thatbranch is dead code: for a release, a cloud-managed Linux frame rendered no SSH
keys section at all, while
allowedFrameSettingsSections.cloudkept offering anav link to its anchor. This PR restores it and adds tests for both directions.
The gate is now a table
frameSettingsSurface.tslists every section the panel can render, with:surfaces— which of the four surfaces render it,nav— which surfaces link it from the settings sub-navigation (defaults tosurfaces;[]requires a writtennavNotesaying why not),conditions— prose for the per-frame and per-firmware conditions that stayin the component (which panel is attached, what version the device reported).
The panel resolves to one of four surfaces rather than three planes:
backend,frameAdmin,cloudLinux,cloudEsp32— because a cloud ESP32accepts a strictly narrower
set_settingsset than a cloud Pi, andset_settingsrefuses the whole push on the first key the device does notknow.
<FrameSettingsSection sectionKey="…">is the only gate: it renders nothingwhen the table does not list the current surface, and throws on an unknown key.
No section tests the mode for itself.
Tests
cloud/apps/auth-web/src/test/shared-spa/frame-settings-surface.test.ts(new,20 cases) pins the table against
allowedFrameSettingsSectionsinworkspaceSurfaces.tsin both directions — every nav link points at a sectionthat mode renders, and every linkable section a mode renders has a nav link —
plus the table's own well-formedness and the surface rules the SSH-keys and
Power sections turn on. The existing panel test gains the two SSH-keys cases.
The split
FrameSettings.tsxframeSettingsSurface.tsframeSettingsContext.tsxesp32Hardware.tsfields/sharedFields.tsxsections/*.tsxFrameActionsMenu.tsxTwo small cleanups came with it: the panel no longer mounts
settingsLogicfora value it never read, and
CloudSettingsSectionnow goes through the tablerather than a bare
inFrameAdminModetest.Verification
Beyond the suites: the panel was rendered for thirteen frame/surface
combinations (rpios, buildroot, embedded ESP32, virtual, TLS on, admin auth on,
mounts, QR + reboot, silent-retry errors, a store scene, frameAdmin, cloud
Linux, cloud ESP32) on
mainand on this branch, and the HTML diffed. The onlydifference across all thirteen is the restored SSH-keys section — everything
else is byte-identical.
tsc --noEmitclean, prettier clean,node build.mjsbuilds, and all 712shared-SPA tests pass.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Qunf3ap3xUWL5iYZA4ZopM