refactor(desktop): rebuild the About page as labeled settings groups - #4571
Conversation
… mode The About page mapped `buildMode === 'packaged'` to 正式版, so a packaged nightly install (version `0.2.0-dev.<run>.<date>`) wore a release badge that contradicted its own version string. Build mode and release channel answer different questions - how the binary was produced vs which feed it follows - and the page only ever saw the former. `app:info` now carries `updateChannel`, resolved from the packaged manifest by the same `desktopUpdateChannelFromManifest` parse that drives the updater, so the pill and the update feed share one authority. The pill logic moves into a pure `aboutChannelBadge` helper: nightly → Nightly (orange), release → 正式版 (blue), dev → 本地开发版 · commit (neutral, a checkout is not a release artifact either). Generated-by: Maka
…late anatomy The old page had no focus: five privacy bullets opened it, the actions a user actually needs were scattered (update check mid-page, diagnostics + shortcut + issue link crammed into one bottom row), and the page promised 运行环境 without showing any. A dev build also printed the same 本地开发版不检查 GitHub 发布 更新 sentence twice - once as row detail, once as help text. The page now follows the vendored Astryx pages/settings template anatomy: two-column Grid sections (Heading 3 + supporting lede left, content right) with a bare Divider between sections, and no row hairlines - the kit makes dividers opt-in everywhere. Facts (channel / runtime / workspace) render as a MetadataList, the same label-to-value construction the MCP detail panel uses. Order follows the page's real jobs: identity facts, software updates, support and diagnostics (merged from the old 参考 + 版本信息 sections), privacy last, compressed from five bullets to three. Support stays outside the info conditional so diagnostics remain copyable when app.info fails - the state the existing SSR test locks in. The channel pill's helper moves into about-update-status.ts instead of a new module: the architecture ledger forbids growing the legacy AppShell closure, and this was that module's seam already. The ledger shrinks by the two dependencies the page no longer imports. Generated-by: Maka
The diagnostics report printed `Build: packaged @ <sha>`, which cannot tell a nightly install from a release one — the two channels update from different feeds and reproduce different bugs. Read the channel from the packaged manifest through a total helper that degrades to `unknown` instead of throwing, because the report must still copy when the manifest itself is what broke.
The About page was the only settings page that bypassed `SettingsSection`: a bespoke hero with two Badges, three hand-written Dividers, two-column Grids, and a primary button on a support action. The release channel — the one fact a nightly user needs first — was a pill label. Make the channel the page's lead: a Token next to the product name (nightly orange, dev gray, release unmarked), the version and build as supporting text, and one sentence on what the channel means. Every group below is a `SettingsSection`: update status as a single row, version facts as a bare MetadataList with the workspace path collapsed to `~`, support as three quiet row actions, and the privacy list. No Badge, Grid, Divider, or primary button remains; Astryx's Badge guidance excludes versions and dates, and Token carries categorical state. `PageHeader` in `@maka/ui` lost its last caller and is removed with its styles. Stories gain packaged nightly and release variants so both channels render in Storybook; the About e2e and channel tests follow the new structure.
The rebuilt About page had five groups, and three of them restated something the reader already had. The 版本信息 readout repeated the lead verbatim — channel, version and build are the two lines directly above it — while its remaining two rows are answered better elsewhere: the runtime triple and the workspace path are both in the diagnostic report the 支持 group copies, and the workspace path is the 数据 page's own subject. A five-row MetadataList that duplicates its own header and defers on the rest is not a group. 软件更新 was a titled group around a single status sentence. Its title named what the sentence already said, and its lede promised background checks the sidebar prompt delivers. The status line and its 检查更新 button move into the lead, where they read as one more fact about this install rather than a section of their own. 隐私 keeps its title and its three commitments; the lede under it only counted them. That leaves the lead (unlabeled — the page title says 关于), 支持 and 本地优先 · 隐私默认: two anchor hairlines instead of four, and no group whose content is available one click away. The copy keys the removed rows owned go with them, along with the release channel's name string — a release install wears no token, so nothing renders it. 复制诊断信息's helper line drops its inventory of report fields for the two facts that govern the decision: it is redacted, and it only reaches the clipboard.
The lead's 48px Sparkles plate was the page's last hand-written CSS, and it decorated a heading that already reads as the product's name. Its whole file goes with it: about.css held nothing else after the hero, heading row and tagline rules were retired, so the stylesheet and its @import in settings.css are gone too. About now renders with zero `.settings*` selectors of its own. The generated ledgers follow the two deletions: the renderer architecture entry loses `@maka/ui/icons`, and the Astryx surface inventory drops page-header.tsx (removed with the About rebuild) and about.css. Both were regenerated, not hand-edited.
Sun-GLiang
left a comment
There was a problem hiding this comment.
Review notes focused on the public UI contract, failure-path coverage, and PR/spec consistency.
…row controls
Three findings from the adversarial review and the ablation, plus their
consequences.
A dev checkout said the same thing twice in a row: the channel sentence
("本地开发构建,不检查更新。") and, immediately under it, the updater's own
"本地开发版不检查 GitHub 发布更新。请使用正式安装包。" beside a permanently
disabled button. The update row now renders only where it can act, so the
channel sentence carries the fact alone. With no caller left,
`aboutUpdateStatusDetail` loses its `isDevBuild` short-circuit and
`updateDevBuildHelp` is gone.
The three row-end controls were named "复制" / "打开" / "查看" — verbs that
mean nothing without the row label a screen reader reads separately.
Each now carries an aria-label naming what it acts on.
`desktopDiagnosticUpdateChannel` shipped with no test at all. It has one
now, over a real manifest in a temp directory: both packaged feeds, the
unpackaged checkout, and the three ways a manifest can fail to name a
channel. Replacing the body with `return 'unknown'` fails it.
The ablation's removals: `wrap="wrap"` on the lead row (its content is
129px against a 380px floor — it can never wrap), `align="start"` on the
status row (pixel-identical at every width), the e2e's `正式版` count-0
assertion (that string no longer exists in any copy), and the story
fixture's `homePath` (About shows no path since the version readout went;
its only consumer is the 工作区 page, whose story does not need it).
Also: `about-settings-page.test.ts` matched the row label rather than the
button, so deleting the button kept it green; `copyHelp` gets the
workspace-path clause back, because the report does carry a `Workspace:`
line and the user decides before clicking; and `packages/ui/README.md`
stopped importing the deleted `PageHeader` in its barrel example.
jackwener
left a comment
There was a problem hiding this comment.
I reviewed this at b942c6f00c50da68640384cfc3d85d598292e9f9. No P0 or P1. One P2, already inlined by Sun-GLiang and still present.
About was the one settings page built outside SettingsSection. Rebuilding it as a lead group plus labeled rows, putting the release channel in that lead, dropping the restated version table and the duplicate dev "does not update" sentence, and deleting PageHeader with its last caller is the smaller cut. Support stays reachable when app.info fails. Row-end controls are named by the row, not by the verb on their face.
Sun-GLiang's other two P2s are closed on this head: packages/ui/README.md no longer imports PageHeader, and desktopDiagnosticUpdateChannel is tested for missing, malformed, and invalid-channel manifests returning unknown without throwing.
Still present: Privacy is not an unchanged list. main has five bullets; this head consolidates them into three. The facts are the same (local data and credentials, no telemetry, explicit permission plus local retention). The E2E test even says "three commitments, not the old wall of five bullets." Describe that consolidation in the summary, or put the five bullets back.
Refactor. Hosted test is green. MERGEABLE. I am not merging it.
简体中文
我审的是 b942c6f00c50da68640384cfc3d85d598292e9f9。没有 P0/P1。一条 P2,Sun-GLiang 已行内,本 head 仍在。
关于页收回 SettingsSection、频道放到 lead、删掉重复的版本表和开发版「不检查更新」第二句、PageHeader 随最后调用方一起删,切法对。Support 不依赖 app.info。
另外两条 P2 在本 head 已关上:README 不再 import PageHeader;诊断频道 fallback 有测试。
仍在:隐私不是「未改清单」。main 五条,这里收成三条,事实还在,摘要写错了。E2E 自己也写了「不是旧的五条」。改摘要,或改回五条。
这是重构。hosted test 绿。我不合入。
Automated review notice: This comment was posted by an automated review agent operated by WAWQAQ. It is not an independent human review and does not replace one.
hqhq1025
left a comment
There was a problem hiding this comment.
Reviewed exact head b942c6f00c50da68640384cfc3d85d598292e9f9. No P0/P1 blockers and no new code findings.
The current head correctly distinguishes packaged release/nightly channels through the same manifest authority used by the updater, keeps diagnostics copyable through an unknown fallback, and keeps support actions reachable when app.info fails. The prior README and fallback-test comments are fixed on this head. The existing inline P2 about the PR summary saying Privacy: unchanged list while the implementation consolidates five bullets into three remains an editorial mismatch; I did not duplicate it.
Validation covered a clean install, build:test, full typecheck, 38 focused tests, changed-file Biome, renderer architecture, Astryx inventory, ASF headers, git diff --check, the About Electron E2E under Xvfb, and a clean synthetic merge onto current main. Hosted test is green. I did not validate the visual result in a real signed nightly/release installation.
Review notice: This review was prepared by an automated review agent operated by hqhq1025 and is published at the direction of AstroHan, who has read these findings and is the human accountable for them.
Summary
The About page was the only settings page built outside
SettingsSection: a bespoke hero with two Badges, three hand-written Dividers, two-column Grids, and a primary button on a support action. The release channel — the first thing a nightly user needs to know — was a pill label, and a dev build's "does not check for updates" sentence rendered twice.This rebuilds the page as the
settings-sidebartemplate's anatomy — a lead group plus labeled row groups — and makes the channel the lead:Token(nightly orange, dev gray, release unmarked), version and build as supporting text, and one sentence on what the channel means. Astryx's Badge guidance excludes versions and dates; Token carries categorical state.The diagnostics report gains a
Channel:line, read from the packaged manifest through a helper that degrades tounknownrather than throwing, so the report still copies when the manifest itself is broken.PageHeaderin@maka/uilost its last caller and is removed with its styles, and the page's own stylesheet goes with the icon plate it styled; nothing on the page is styled outside Astryx now.Before (
main) vs. after (this branch), dev build, same viewport:The two packaged channels are new Storybook variants with no
maincounterpart; nightly (left) vs. release (right):Verification
npm run format,npm run lintat the root: clean.apps/desktop:npm run typecheck(preload, main, renderer, storybook),npm run test:dist(1971 pass, 0 fail),npx playwright test about-page.spec.ts(1 passed).node apps/desktop/scripts/check-renderer-architecture.mjs: passed, ledger unchanged.product-settings-pages--about,--about-nightly,--about-release, light and dark, 1280 wide (screenshots above).AI use
Select exactly one:
Tool(s) and scope: Claude Code drafted the page, stories, tests, and this description under review.
Checklist
Does this PR entail a change in behavior?