Skip to content

feat(desktop): product About text, theme lines and content theme parts - #28

Merged
doodlewind merged 1 commit into
mainfrom
feat/desktop-product-about-theme
Oct 4, 2026
Merged

doodlewind merged 1 commit into
mainfrom
feat/desktop-product-about-theme

Conversation

@doodlewind

@doodlewind doodlewind commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

What changed

About text from the product. The About dialog's body lines and its link no longer live in programs.tsx. They come from shells/desktop/pocket.about.json, which sits beside pocket.system.json and is imported at bundle time through pocket-apps.ts (DESKTOP_ABOUT, read by readAbout):

{ "body": ["One line of text.", "Another line."], "link": "example.org/product" }

The System manifest was the first choice of carrier, as it is for DESKTOP_NAME. Its schema (PocketSystemV1, additionalProperties: false) has no description or homepage field, and the schema is not changed here, so the text has its own file. body holds one text line per entry; the dialog does not wrap them and its fixed size holds four above the link. Both fields are optional: without body the dialog shows no lines, without link no link row. This repository's file holds the four lines and the link the dialog showed before, so its About is unchanged. A product that bundles the System UI under its own manifest replaces the file.

Theme lines. The System UI protocol (src/system-ui/svc.ts) gains one line in each direction:

host → System UI   {t:"theme", id}   select the theme: "classic", "xp" or "aqua"
System UI → host   {t:"theme", id}   the active theme

The host line calls the same setTheme the Settings menu calls, so windows keep their client rectangles and open menus close. An id that names no theme, a missing id and a non-string id are ignored (isThemeId in theme.ts). The System UI reports once after boot and after every frame that ends in another theme than the one last reported, whether the Settings menu, the cycle chord or the host's line changed it. Lines that arrive within one frame produce one report.

Content parts in the theme contract. DesktopTheme gains parts for what a program draws inside its window, filled in for all three themes:

Part What it is
listWell, listRow(selected, zebra), listText, listDetailText a list box, a row's fill, and the text colours of a row's two lines
scrollTrack, scrollThumb the position mark of a list box that overflows
groupBox, groupLabel, groupLabelText a titled frame; the theme sets the label on the top edge (Classic, XP) or above the frame (Aqua)
fieldWell a box around a value shown for reading or copying
radioRing(checked), radioFace(checked), radioDot a radio mark
progressTrack, progressFill a progress bar
optionRow, contentButton(primary) the two controls a Pocket app presses

ChromeMetrics gains listPad, scrollW and groupPadX, the geometry a program truncates and wraps text against.

optionRow and contentButton carry focus: and active: variants in the literal. A Pocket app's guest runs the framework focus manager, and the core applies those variants to the focused and the pressed node; dialogButton keeps its pressed argument because the System UI hit-tests its own dialogs. The Shut Down dialog now draws its radio marks from radioRing / radioFace / radioDot. Classic's three literals are the ones the dialog had, so Classic paints the same pixels; XP and Aqua get their own mark. The header rule of theme.ts stands: no theme id is special-cased outside that file.

No other product's name in the UI. XP_THEME.label is "XP" (was "Windows XP"), the Shut Down dialog's caption is "Shut Down" (was "Shut Down Windows"), and the (C:) listing shows a folder named System (was Windows) and the file type Batch File (was MS-DOS Batch File). The README names the theme XP as well; the site already did.

The caption does not carry DESKTOP_NAME. The dialog is 300px wide, and Aqua centers the title between the control cluster and a balancing spacer: rendered in the sim at 2×, "Shut Down Pocket Shell Desktop" lost its first and last characters there, while "Shut Down" fits in all three themes.

Found in the same sweep and left unchanged:

  • docs/xp-theme.png and docs/aqua-theme.png show the Settings flyout with the old label. They are documentation assets regenerated by bun run desktop capture; a recapture also changes the welcome note's first line, which still reads "Pocket Desktop" in the committed images, so it is a docs refresh of its own.
  • THIRD_PARTY.md and the header of gen-assets.ts name Windows XP and Mac OS X where they state which fonts those systems ship and why Inter stands in. Comments and identifiers (XP_THEME, xp-*.svg) keep their names.
  • The welcome note names the font W95FA, which is that font's name.

Why Pocket Studio needs it

Pocket Studio puts this System UI on the laptop in its room, under its own System manifest (title Pocket Nexus), with three Pocket apps of its own.

  • Its About dialog said "A desktop compositor demo on the portable Rust backend." and linked to this repository.
  • Its apps drew in one light look of their own. They now import theme.ts and draw from the content parts, with the five theme font slots and the icons in their own packs, so each window matches the desktop around it in all three themes.
  • The page hosting the desktop had no way to learn the active theme and could set it only by sending cycle chords at boot. With the two lines it stores the viewer's choice, restores it at boot, and passes each change on to the apps.
  • The theme picker and the Shut Down caption showed another product's name.

Verification

Run in a clean clone of this branch with the pinned PocketJS submodule (0ca1b362), after bun run setup.

Command Result
bun run check exit 0
— check:assets 289 tracked files, no ignored outputs tracked
— typecheck (root and four shells) clean
— 3DS / iPod / touch tests 40 / 72 / 66 pass, 0 fail
— shells/desktop test 70 pass, 0 fail (9 new)
— shells/desktop test:sim 8 pass, 0 fail (2 new, 2 extended)
— shells/desktop test:wrap, test:text 3 pass, 6 pass
bun run desktop test:web Ready, Hero AppInstance composited

New coverage:

  • system-ui.test.ts: DESKTOP_ABOUT equals the file and the four lines and link the dialog had; readAbout with a missing body, a missing link, entries that are not strings and values that are not objects; the theme labels are Classic 98, XP, Aqua; isThemeId; every content part of every theme parses as a class literal (parseClassLiteral from the pinned compiler, since a literal the compiler rejects compiles to no style and fails no build); the three metrics mirror their literals; optionRow and contentButton carry both variants; a selected row differs from an unselected one; Classic's radio literals equal the ones ShutdownView had.
  • system-ui-sim.test.ts, "the shell reports its theme and takes the host's theme line": one report after boot and none while the theme stands; the cycle chord, the host's line and a pick in the Settings flyout each produce one report; the active theme again, an unknown id, a numeric id and a missing id change neither the tree nor the reports; the host's line closes an open launcher; two lines within one frame give one report of the last.
  • system-ui-sim.test.ts, "no text of the desktop names another product": no text node matches Windows or MS-DOS with the welcome note, the theme flyout, the Shut Down dialog and the (C:) listing on screen; the dialog's caption is one text node reading Shut Down; in each theme the dialog holds that theme's checked and unchecked radio marks; the listing holds System and Batch File.
  • The existing theme-switch test reads the flyout's rows as exactly Classic 98, XP, Aqua; the existing About test reads each body line and the link from DESKTOP_ABOUT, in order.

With the host theme handler disabled, both new sim tests fail.

Not run locally, left to CI: desktop test:rust, desktop build, desktop package:linux, the site build and its smoke check.

🤖 Generated with Claude Code

The About dialog's body lines and its link come from pocket.about.json beside
the System manifest, read at bundle time through pocket-apps.ts. The manifest
schema has no field for product copy, so the text has its own file; both of
its fields are optional. This repository's file holds the text the dialog
showed before, so its About is unchanged; a product that bundles the System UI
under its own pocket.system.json replaces the file.

The System UI protocol gains a theme line in each direction. The host sends
{t:"theme", id} to select a theme; an id that names no theme is ignored. The
shell sends {t:"theme", id} once after boot and after every frame that ends in
another theme, whether the Settings menu, the cycle chord or the host's line
changed it.

DesktopTheme gains content parts for what a program draws inside its window: a
list box with its rows and a scroll mark, a group frame, a value well, a radio
mark, a progress bar, and the option row and push button a Pocket app presses,
which carry the focus: and active: variants the framework's focus manager
applies. The Shut Down dialog draws its radio marks from them, and a Pocket app
that imports theme.ts draws its window in the active theme. Three metrics
(listPad, scrollW, groupPadX) carry the geometry a program lays text out
against.

No text of the desktop names another product: the XP theme's label is "XP",
the Shut Down dialog's caption is "Shut Down", and the (C:) listing shows a
"System" folder and a "Batch File" type. The caption carries no name because
the dialog is 300px wide and Aqua's centered caption clips a longer title.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@doodlewind
doodlewind force-pushed the feat/desktop-product-about-theme branch from e582514 to cecd944 Compare October 4, 2026 09:43
@doodlewind
doodlewind marked this pull request as ready for review October 4, 2026 10:00
@doodlewind
doodlewind merged commit a2e5cc8 into main Oct 4, 2026
2 checks passed
@doodlewind
doodlewind deleted the feat/desktop-product-about-theme branch October 4, 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