Launcher: a grid of icons, with badges; the list stays as a Setting

The Launcher shows the Apps as a 4 x 3 grid of 32 x 32 icons, the
selected one's name under it (issue #9). The icons are the website's
own, doubled, and two drawn the same way for SSH and the Shell; they
are PNGs in assets/icons, turned into arrays by scripts/make_icons.py,
which CI checks. The selected tile is the website's: dark blue on cyan,
with notched corners.

- GridModel (lib/ui, host-tested) holds the selection and the scrolling.
- App::badge(): a dot on the tile for unread IRC messages, a Track
  recording, a Capture running, an SSH session open.
- Settings > Launcher: Grid or List.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162FokPdvY2KsS4NBfwyWPk
This commit is contained in:
2026-10-09 23:14:37 +02:00
co-authored by Claude Opus 5.5
parent aadfd8cb37
commit e2326e113b
40 changed files with 907 additions and 24 deletions
+1
View File
@@ -53,6 +53,7 @@ const Definition kDefinitions[] = {
{"ssh_key", Kind::String, 0, "", 0, 800},
{"ssh_public", Kind::String, 0, "", 0, 200},
{"ssh_font", Kind::Int, 1, nullptr, 0, 4},
{"launcher_list", Kind::Bool, 0, nullptr, 0, 1}, // off: the grid
};
static_assert(sizeof(kDefinitions) / sizeof(kDefinitions[0]) == static_cast<size_t>(Setting::Count),
"every Setting needs a definition");
+1
View File
@@ -41,6 +41,7 @@ enum class Setting : uint8_t {
SshKey, // string: this device's own SSH private key, as OpenSSH writes one: never shown
SshPublic, // string: its public half, the line to put in a server's authorized_keys
SshFont, // int: the terminal's font, 0 (smallest) to 4
LauncherList, // bool: the Launcher is a list of names instead of a grid of icons (issue #9)
Count
};