Раздел: App
Идентификатор:theme· Экран:ui/theme/ThemeSettingsScreen.kt
Снимок: 2026-10-11
1. Зачем и что это
Экран сделан в стиле терминала: шапка TerminalHeader с приглашением y83@theme :~$, а секции пронумерованы как «01 / APPEARANCE», «02 / FONT» и т. д. Так же оформлены экраны настроек Codex — см. ../codex-chat.md.
Отдельного «экрана цветов» нет: палитра (ui/theme/Color.kt, SemanticColors.kt) зашита в приложение, пользователь меняет только режим свет/тьма и типографику. Правило палитры: цвета только токенами MaterialTheme.colorScheme, контраст WCAG AA (скилл y83-ux).
2. Как попасть
Хаб инструментов → секция App → карточка «Тема» (hub_theme_title = «Тема», подпись hub_theme_subtitle = «Цвета, шрифты и размер текста»).
| Откуда ещё | Путь |
|---|---|
| Главная | тайл «Тема» (если не скрыт в Настройках главной) |
| Мост | app_navigate с screen: "theme" (bridge/BridgeScreenCatalog.kt) |
Маршрут: Screen.kt:144 ("theme" -> Screen.Theme) → MainRouter.kt:184 (ThemeSettingsScreen(onBack = …)).
3. Экран: элементы и действия
| Элемент | Что делает | Где в коде |
|---|---|---|
Шапка y83@theme :~$ | Терминальная шапка, кнопка «назад» | ThemeSettingsScreen, TerminalHeader |
Секция 01 / APPEARANCE | Три карточки режима: Dark / Light / System | ThemeModeSection |
Секция 02 / FONT | Сетка из 9 семейств шрифтов | FontSection, FontCard |
Секция 03 / SIZES | 7 строк размеров со слайдерами | SizeSection, SizeCard |
Секция 04 / LIVE PREVIEW | Живой предпросмотр баблов чата EN + RU | ChatPreviewSection |
| Секция сброса | Кнопка «Reset appearance» + диалог подтверждения | ResetSection |
Карточка режима выбрана, если у неё бордер primary 2.dp и фон surfaceContainerLow; невыбранная — бордер outlineVariant 1.dp и фон surfaceContainerLowest. Цвет анимируется через animateColorAsState.
4. Возможности подробно
Режим темы
Три режима (themeModeOptions, ThemeSettingsScreen.kt:74):
| id | Подпись | Иконка |
|---|---|---|
dark | Dark | DarkMode |
light | Light | LightMode |
system | System | PhoneAndroid |
Тап по карточке сразу пишет App.saveThemeMode(id) — пересоздания активности не требуется, потому что режим читается как Flow (App.themeModeFlow) и Theme.kt:92 подставляет его в MaterialTheme.
Шрифты чата
Девять семейств (fontOptions, ThemeSettingsScreen.kt:87):
| id | Название | Характер |
|---|---|---|
system | System | системный шрифт Android |
inter | Inter | UI |
golos | Golos Text | кириллица |
manrope | Manrope | геометрический |
nunito | Nunito | скруглённый |
comfortaa | Comfortaa | дисплейный |
ptsansnarrow | PT Sans Narrow | узкий |
literata | Literata | с засечками |
jetbrains | JetBrains Mono | моноширинный |
Семейства объявлены в ui/theme/Type.kt (Inter, GolosText, Manrope, Nunito, Comfortaa, PTSansNarrow, Literata, JetBrainsMono), файлы шрифтов лежат в app/src/main/res/font/ (20 .ttf, включая Raleway — он используется в UI, но не в списке чата).
Размеры текста
Семь независимых параметров (ChatFontConfig, ui/theme/Type.kt:60), каждый со слайдером:
| Тип | Смысл | Дефолт |
|---|---|---|
Agent | ответы агента | 14 |
User | реплики пользователя | 14 |
Reasoning | «размышления» | 14 |
Event | события ленты | 14 |
Meta | подписи и метки | 11 |
Code | блоки кода | 14 |
Plan | строки плана | 14 |
Диапазон общий: MIN_SIZE = 11, MAX_SIZE = 20. Значение читается функцией ChatFontConfig.sizeOf(ChatTextType), записывается — withSize(type, size).
Образцы текста в строках размеров намеренно двуязычные («как выглядит агентский текст / мой / плана»), поэтому лежат в ресурсах с translatable="false" (R.string.theme_sample_*), а список sizeRows — это getter: строки берутся в момент показа, чтобы примерка шрифта не ломалась о мёртвый контекст.
Живой предпросмотр
ChatPreviewSection рисует настоящие баблы чата теми же стилями, что и лента: бабл пользователя справа (primaryContainer/onPrimaryContainer, скругление 16,16,4,16), бабл агента слева (surface/onSurface, 16,16,16,4), оба разными выбранными размерами. Текст — английский и русский одновременно: так видно, не ломает ли шрифт кириллицу.
Сброс
Кнопка «Reset appearance» открывает AlertDialog и по подтверждению делает App.saveThemeMode("system") + App.saveChatFonts(DefaultChatFonts) — то есть возвращает системный режим, system и заводские размеры. Отмена ничего не меняет.
5. Данные: БД, файлы, настройки
Всё в SharedPreferences (App.PREFS_NAME), без БД.
| Что | Ключ | Тип | Дефолт |
|---|---|---|---|
| Режим темы | theme_mode | String | dark |
| Семейство шрифта | chat_font_family | String | system |
| Размер agent | chat_size_agent | Int | 14 |
| Размер user | chat_size_user | Int | 14 |
| Размер reasoning | chat_size_reasoning | Int | 14 |
| Размер event | chat_size_event | Int | 14 |
| Размер meta | chat_size_meta | Int | 11 |
| Размер code | chat_size_code | Int | 14 |
| Размер plan | chat_size_plan | Int | 14 |
Чтение — App.loadDisplayPrefs() при App.init, запись — App.saveChatFonts(cfg) и App.saveThemeMode(mode) (обе с .apply()), актуальное значение — App.chatFonts: MutableStateFlow<ChatFontConfig> и App.themeModeFlow.
6. Backend: REST/роуты
Неприменимо: экран работает целиком на устройстве, обращений к бэкенду нет.
7. Мост и MCP
| Что | Как | Примечание |
|---|---|---|
| Открыть экран | app_navigate / app_ui_*, screen: "theme" | BridgeScreenCatalog.kt |
Отдельной bridge-команды «прочитать тему» нет; агент читает настройки только из prefs-файла приложения (в коде моста такой команды не найдено).
8. Настройки, конфиг, квоты и лимиты
| Параметр | Значение | Где задаётся |
|---|---|---|
| Размер шрифта | 11…20 | Экран, слайдер |
| Число размеров | 7 (ChatTextType) | Код: ui/theme/Type.kt |
| Число шрифтов | 9 | Код: ThemeSettingsScreen.fontOptions |
| Сетка отступов | 4dp (16/12/8) | Скилл y83-ux |
Квот и лимитов, требующих сервера, нет.
9. Ловушки и ограничения
- Сброс необратим:
Reset appearanceвозвращает и режим, и шрифт, и все семь размеров к заводским — отдельного сброса только размеров нет. - Тёмный дефолт, а не системный: при первом запуске
theme_mode=dark, хотя в диалоге сброса написано «restore the system appearance mode» — то есть после сброса поведение отличается от исходного. - Тексты экрана частично на английском (
01 / APPEARANCE,Font,Reset appearance): экран не проходит стадиюi18nворот как чистый файл, в отличие от строк вres/values*. - Размеры чата не применяются к UI — только к тексту ленты Codex; подписи интерфейса живут по теме Material.
- Живой предпросмотр показывает только два бабла: стили остальных пяти типов видно лишь в строке образцов.
10. Источники правды
app/src/main/java/com/y83/ws/ui/theme/ThemeSettingsScreen.kt— экран.app/src/main/java/com/y83/ws/ui/theme/Type.kt—ChatFontConfig, семейства,chatStyle.app/src/main/java/com/y83/ws/ui/theme/Theme.kt— подстановка режима и шрифтов.app/src/main/java/com/y83/ws/ui/theme/Color.kt,SemanticColors.kt— палитра.app/src/main/java/com/y83/ws/App.kt— ключиPREF_THEME_MODE,PREF_CHAT_*,save*.app/src/main/res/font/— файлы шрифтов;app/src/main/res/values/strings.xml—theme_sample_*.app/src/main/java/com/y83/ws/data/InstrumentCatalog.kt— карточка хаба.