feat(app,learn): the device's appearance and language, halkyon_app's, as Learn's Settings show them

The developer asked for Todo, Train and Meditate to offer Learn's
Appearance and Language (ADR 0014's amendment of 4 Nov 2026). Their
model, store, cubit and card move into halkyon_app: Appearance and Look
(a BCP 47 tag, null for the device's language), FileLookStore keeping it
in the app's support folder as JSON written by rename (per device, not
synced, read before the first frame), LookCubit for the apps to provide
above InstanceGate, and LookSettingsCard / DeviceLookCard with the texts
moved from Learn's arbs (look*, the same words). Each app passes the
languages it speaks, named in their own language.

Learn keeps its stored choice where it was, among its DeviceSettings,
and feeds the shared card from them: no migration, so nobody's language
or appearance moves, and nothing changes on its screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-04 22:30:29 +01:00
commit 23d3bcb4ca
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -117,3 +117,34 @@ every service of an instance (ADR 0016). The app side was Learn's alone; it move
- **Chosen without the developer, flagged:** the person's tab comes first in Train too,
where Profile used to open on Progress, so that every app opens it alike.
## Amendment (4 Nov 2026): every app's appearance and language
The developer asked for Todo, Train and Meditate to offer what Learn's Settings offer
first: the app's appearance (the device's theme, light, dark) and its language (the
device's, or one the app speaks, each named in its own language). They had passed a fixed
look (the system's theme and language). It moved into `halkyon_app`:
- **The model** (`Appearance`, `Look`, `AppLanguage`, `localeOfTag`): the appearance and a
BCP 47 tag, null for the device's language, as Learn's device settings kept them.
- **Kept on the device, per device** (`FileLookStore`, `<app support>/look.json`): not
synced, read before the first frame and applied before anyone signs in, as Learn's.
Alternatives: the person's synced settings (they would apply only after signing in, and
the start screens would speak another language than the app); shared preferences (a
plugin more, where a small JSON file written by rename does, as the instances and
what's new are kept).
- **Applied** by a `LookCubit` that each app opens in `main` and provides above
`InstanceGate` (its `readLook`), so `SessionGate`'s start screens and the person's
`MaterialApp` follow it at once.
- **Shown** by `DeviceLookCard` (on the cubit) or `LookSettingsCard` (given the look and
what to do with a choice): two menus, side by side from medium windows, the texts
halkyon_app's (`look*`, moved from Learn's `settingsAppearance*`, `settingsLanguage*`,
the same words). Each app passes its own languages (`todoLanguages`, `trainLanguages`,
`meditateLanguages`, Learn's `appLanguages`), today all three it speaks: English (UK),
English (US), Deutsch. The card comes first of the app's own settings, right after the
Sync and operator's cards, as in Learn.
- **Learn keeps its stored choice where it is**: the appearance and language stay among
its `DeviceSettings` (`device_settings.json`), its card feeding the shared one. Chosen
over moving them into `look.json` and reading the old values once, which is less code in
the end but a migration that, done wrong, loses someone's language; keeping them needs
none and changes nothing anyone sees. Moving them can follow later, once.