Раздел: App
Идентификатор:homesettings· Экран:ui/home/HomeSettingsScreen.kt
Снимок: 2026-10-11
1. Зачем и что это
Это единственный экран, который меняет композицию главной — сам каталог инструментов при этом не трогается, скрытый инструмент остаётся доступен через хаб.
Экран построен по правилам инвариантов тумблеров, которые в проекте зафиксированы для экранов Skills/MCP: карточка не переезжает при выключении (она просто гаснет), состояние подписано словами и дублируется счётчиком в заголовке секции, а массовые операции вынесены в отдельную строку «Показать все / Скрыть все».
2. Как попасть
Хаб инструментов → секция App → карточка «Настройки главной» (hub_homesettings_title, подпись «Порядок тайлов главной и скрытые агенты»).
| Откуда ещё | Путь |
|---|---|
| Главная | кнопка настроек в верхней панели (ui/home/HomeTopBar.kt) |
| Мост | app_navigate с screen: "homesettings" |
Маршрут: Screen.kt:152 ("homesettings" -> Screen.HomeSettings) → MainRouter.kt:193 (HomeSettingsScreen(onBack = …)).
3. Экран: элементы и действия
| Элемент | Что делает | Где в коде |
|---|---|---|
Шапка y83@home :~$ | Терминальная шапка; meta — счётчики «видимые/все» по тайлам и агентам, бейдж «по умолчанию» или «свой» | HomeSettingsScreen:127 |
| Секция «Тайлы» | Список всех тайлов главной, у каждого стрелки вверх/вниз и Switch | itemsIndexed(tiles) → TileRow |
| «Показать все» / «Скрыть все» (тайлы) | Массово ставит visible = true/false всем тайлам | BulkActionsRow, колбэк в шапке секции |
| Секция «Агенты» | Список агентов главной из AgentCatalog.homeItems + удалённый агент, у каждого Switch | items(agents) → AgentRow |
| «Показать все» / «Скрыть все» (агенты) | Очищает hiddenAgents или добавляет всех в скрытые | BulkActionsRow |
| «Сбросить» | Диалог подтверждения → App.saveHomeDashboard(defaultHomeConfig()) | ResetSection |
У тайла в строке есть: иконка (гаснет при выключении), заголовок каталога, подпись каталога (2 строки, maxLines = 2, ellipsis), две IconButton 48.dp со стрелками ArrowUpward/ArrowDownward (дизейблены на краях списка) и Switch с contentDescription вида «Скрыть X» / «Показать X» — то есть озвучка корректная и для TalkBack.
4. Возможности подробно
Что попадает в список тайлов
homeTiles(config) фильтрует конфиг по InstrumentCatalog.byId(it.id)?.showOnHome == true, то есть показываются только пункты хаба, у которых showOnHome = true. Инструменты, существующие только в хабе (например, выключенный video), в списке главной не появляются.
Каталог — единственный источник правды
HomeSettingsScreen не хранит собственный список: он читает InstrumentCatalog. Поэтому добавление нового пункта в InstrumentCatalog автоматически делает его тайлом главной и строкой этого экрана — без правок здесь.
Порядок и перемещение
Порядок хранится числом order у каждого TileItem. Перемещение реализовано функцией movedTiles(tiles, index, offset): она меняет местами два элемента и возвращает новый список; при выходе за границы возвращает исходный список (кнопки на краях всё равно задизейблены). canonicalConfig() перед сохранением перенумеровывает order по фактическому индексу, поэтому в prefs всегда лежит плотная последовательность без дыр.
Счётчики и бейдж
В шапке meta показываются две строки — hub_home_meta_tiles и hub_home_meta_agents вида «3/5», а справа бейдж hub_home_badge_default или hub_home_badge_custom. Признак «свой» вычисляется сравнением canonicalConfig(config) с defaultHomeConfig() — то есть с учётом нормализации.
Агенты
Список собирается из AgentCatalog.homeItems (все невыключенные агенты) плюс отдельная строка «Удалённые агенты» с иконкой Dns и id AgentCatalog.REMOTE_HOME_ID = "remote". Агенты скрываются через множество hiddenAgents, а не флагом у каждого, — при загрузке конфига множество пересекается с актуальным homeAgentIds, поэтому удалённые из каталога агенты молча выпадают из конфига.
Нормализация и совместимость
HomeDashboardConfig.normalized() дополняет конфиг пунктами каталога, которых в нём ещё нет, ставит им visible = true и order за последним. Операция идемпотентна и вызывается при чтении из prefs (fromJson → normalized()), при сохранении (saveHomeDashboard → normalized()) и при сравнении с дефолтом. Побочный эффект важен: новый инструмент, добавленный в InstrumentCatalog после того как пользователь настроил главную, сам появится на главной — иначе он молча пропал бы у того, у кого сохранён старый список.
5. Данные: БД, файлы, настройки
| Что | Где лежит | Как меняется | Кто читает |
|---|---|---|---|
| Конфиг главной | SharedPreferences, ключ home_dashboard_config, JSON-строка | App.saveHomeDashboard(config) | Главный экран при отрисовке тайлов и агентов |
| Структура | HomeDashboardConfig(tiles: List<TileItem>, hiddenAgents: Set<String>) | — | ui/home, MainScreen |
Формат JSON: {"tiles":[{"id":"…","visible":true,"order":0}], "hiddenAgents":["remote"]}. toJson пишет тайлы в отсортированном по order виде; fromJson отбрасывает записи с пустым id и с id, которого больше нет в InstrumentCatalog (совместимость при удалении инструмента), и при любом исключении возвращает HomeDashboardConfig().normalized() — то есть битый prefs не ломает главную.
6. Backend: REST/роуты
Неприменимо: экран работает локально, сеть не используется.
7. Мост и MCP
| Что | Как | Примечание |
|---|---|---|
| Открыть экран | app_navigate с screen: "homesettings" | BridgeScreenCatalog.kt |
Команды моста для чтения или правки композиции главной в коде не найдено: агент может открыть экран и сделать скриншот, но изменить конфиг программно не может.
8. Настройки, конфиг, квоты и лимиты
| Параметр | Значение | Где задаётся |
|---|---|---|
| Размер сетки тайлов | 4 колонки на главной | Код главного экрана |
| Отступы | 4dp-сетка, 16dp по краям | Скилл y83-ux |
| Радиус карточек | 16.dp | ui/components |
| Правило выделения | бордер primary 2.dp, не secondaryContainer | Скилл y83-ux |
9. Ловушки и ограничения
- Скрытие инструмента в хабе не скрывает его на главной и наоборот. Это две независимые настройки:
InstrumentDef.enabled(каталог) иTileItem.visible(конфиг главной). - Сквозная нумерация в хабе. После правки
canonicalConfigномера снова становятся плотными, поэтому файл конфига не является источником истины для отображения — только для порядка. - Переустановка/откат версии. Если id инструмента исчез из каталога, его запись молча выбрасывается при следующем чтении из prefs.
- Раздел «Агенты» — только агенты главной. Агенты, не входящие в
AgentCatalog.homeItems, этим экраном не скрываются. - Ошибки записи в prefs не обрабатываются.
saveHomeDashboardне имеет try/catch: привилегированный путь к prefs отсутствует, так что отказ записи означает проблему с файлом, а не с правами.
10. Источники правды
app/src/main/java/com/y83/ws/ui/home/HomeSettingsScreen.kt— экран.app/src/main/java/com/y83/ws/data/HomeDashboardConfig.kt— конфиг,fromJson/toJson/normalized().app/src/main/java/com/y83/ws/data/InstrumentCatalog.kt— каталог инструментов (единственный источник для тайлов).app/src/main/java/com/y83/ws/data/AgentCatalog.kt—homeItems,REMOTE_HOME_ID.app/src/main/java/com/y83/ws/App.kt—PREF_HOME_DASHBOARD,saveHomeDashboard.app/src/main/res/values/strings_hub.xml— строкиhub_home_*.