LihonT 2 Luna beta: source release
Mod for TikTok 47.1.3 (arm64) in Material 3 style: bottom bar, profile menu, TikTok settings and comments; downloads without the watermark; switches for ads, live streams and the Shop tab; badges of other mods next to names and the niche mod badge (members service); app icons; mod settings screen. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
126
docs/settings-model.md
Normal file
126
docs/settings-model.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Модель настроек LihonT 2
|
||||
|
||||
Первая схема настроек, 15 октября 2026. Код написан в `src/lihont/two/settings/`
|
||||
без зависимости от классов или хранилищ других модов.
|
||||
|
||||
## Значения
|
||||
|
||||
| Поле | Тип и допустимые значения | По умолчанию | Применение после подключения |
|
||||
|---|---|---|---|
|
||||
| `region` | Строка, один из 249 ISO 3166-1 alpha-2 кодов, верхний регистр | `JP` | Следующий запуск процесса |
|
||||
| `profileBanners` | Boolean | `true` | Следующий запуск процесса |
|
||||
| `commentReposts` | Boolean | `true` | Следующий запуск процесса |
|
||||
| `theme` | `system`, `light`, `dark` | `system` | Следующее создание экрана настроек |
|
||||
|
||||
Перечень стран фиксирован в модели и не зависит от локали Android. Это список
|
||||
стран и территорий ISO; названия для списка в интерфейсе будут локализованы
|
||||
отдельно. `regionIso()` возвращает код в нижнем регистре для будущих хуков.
|
||||
Ни телефонный префикс, ни MCC/MNC не вычисляются из позиции в этом списке.
|
||||
|
||||
Для выбранного региона кроме `JP` метод `needsBannerWarning()` возвращает
|
||||
`true`: интерфейс должен предупредить, что баннеры могут быть недоступны. Для
|
||||
Японии предупреждения нет. Показ диалога будет реализован на этапе интерфейса.
|
||||
|
||||
`ModSettings` неизменяемый: методы `with…` создают новый набор. По умолчанию
|
||||
баннеры и репосты запрошены локально, но модель не сообщает, что сервер их выдал.
|
||||
Тема относится к собственным экранам мода; сохранение темы пока не меняет TikTok.
|
||||
|
||||
## Хранилище и жизненный цикл
|
||||
|
||||
`SettingsRepository` получает `Storage`. На первом открытии создаёт файл со
|
||||
значениями по умолчанию. На следующих открытиях полностью проверяет сохранённый
|
||||
документ. Повреждённый файл, неизвестная версия или ошибка чтения приводят к
|
||||
ошибке открытия и сохраняют исходные данные. Тихой замены на defaults нет.
|
||||
|
||||
Нужен **один экземпляр репозитория на процесс приложения**. Это обязательство
|
||||
будущего хоста; сейчас хост и инициализация из TikTok отсутствуют. Запись из
|
||||
нескольких процессов не поддерживается.
|
||||
|
||||
- `current()` — последний успешно сохранённый набор, для интерфейса.
|
||||
- `active()` — набор, загруженный при создании репозитория, для будущих хуков.
|
||||
- `restartRequired()` — различаются ли регион, баннеры или репосты между этими
|
||||
наборами. Возврат к активным значениям снимает признак перезапуска. Тема в это
|
||||
сравнение не входит.
|
||||
- `save()` сначала записывает полный документ, затем публикует новое состояние.
|
||||
Ошибка записи не меняет опубликованный набор.
|
||||
- `reset()` сохраняет defaults. Если активные значения отличались от defaults,
|
||||
необходимость перезапуска остаётся.
|
||||
|
||||
`AndroidSettingsStorage` использует приватный `Context.getFilesDir()` и файл
|
||||
`lihont-settings.json`. Разрешения на файлы и доступ к сети не требуются. Запись
|
||||
идёт во временный файл в той же директории, выполняет `fsync`, затем атомарный
|
||||
`android.system.Os.rename`. Старый файл не удаляется до замены. При ошибке до
|
||||
замены старые данные сохраняются. Ошибки чтения не трактуются как первый запуск.
|
||||
Доступен на minSDK 23; шифрование настроек не требуется, секретов в схеме нет.
|
||||
|
||||
## Формат импорта и экспорта
|
||||
|
||||
```json
|
||||
{
|
||||
"format": "lihont.settings",
|
||||
"schemaVersion": 1,
|
||||
"values": {
|
||||
"region": "JP",
|
||||
"profileBanners": true,
|
||||
"commentReposts": true,
|
||||
"theme": "system"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`exportJson()` возвращает сохранённые значения. `importJson()` **заменяет весь
|
||||
набор**, предварительно проверив структуру, формат, версию, точные типы и
|
||||
допустимые значения. Частичного импорта и приведения строк к boolean нет.
|
||||
|
||||
Лишние, отсутствующие и повторяющиеся ключи, неизвестные страны и темы,
|
||||
повреждённый JSON, `null`, массивы, дробная версия, данные после документа и
|
||||
документ длиннее 16 384 символов отклоняются. Файл Android читается как строгий
|
||||
UTF-8 и ограничен 16 384 байтами; стандартный экспорт содержит только ASCII.
|
||||
Ошибка проверки не вызывает запись. Ошибка записи не обновляет `current()`.
|
||||
|
||||
Это **первая** схема: предыдущих форматов настроек у LihonT 2 нет. Поэтому версии
|
||||
0 и выше 1 отклоняются с сохранением файла. При появлении схемы 2 потребуется
|
||||
явная миграция 1 → 2 и её тесты до изменения номера. Настройки старой серии и
|
||||
других модов автоматически не импортируются.
|
||||
|
||||
Формат и API готовы для будущего интерфейса резервных копий. Кнопки экспорта и
|
||||
импорта в APK на этом этапе не добавляются.
|
||||
|
||||
## Граница текущего этапа
|
||||
|
||||
Сейчас это модель, кодек и адаптер хранения. Они ещё не подключены к экрану
|
||||
TikTok Settings, региональным вызовам, флагам баннеров или репостам. Существующий
|
||||
`LihonTRegion` в прежнем тестовом APK по-прежнему возвращает фиксированный `by`.
|
||||
Новые значения `JP` не выдаются за изменение аккаунта или серверного региона.
|
||||
|
||||
Следующий этап — собственный хост настроек с инициализацией репозитория и
|
||||
обработкой ошибок хранения. Затем подключаются функции по roadmap и проверяются
|
||||
на устройстве.
|
||||
|
||||
## Проверка
|
||||
|
||||
Из корня проекта:
|
||||
|
||||
```powershell
|
||||
py -m unittest discover -s tests -v
|
||||
py -c "from lihont.toolchain import Toolchain; print(Toolchain('tools').compile_dex('src/lihont/two', 'work/settings-model/runtime', 23))"
|
||||
```
|
||||
|
||||
JVM-тесты компилируют и исполняют реальные `ModSettings`, `SettingsCodec` и
|
||||
`SettingsRepository`. Android-адаптер компилируется против `android.jar`, затем
|
||||
весь runtime проходит D8 с minAPI 23. JVM-тесты не подменяют проверку Android
|
||||
файловой системы на устройстве; её включаем в интеграционный этап.
|
||||
|
||||
## Подключение флагов TikTok
|
||||
|
||||
`lihont.two.settings.SettingsHost` держит единственный `SettingsRepository` процесса.
|
||||
Им пользуются экран настроек и `lihont.two.LihonTFlags`, поэтому `active()` — это то,
|
||||
что видели хуки с первого чтения, а `restartRequired()` сравнивает экран именно с ним.
|
||||
|
||||
- Переключатель включён: чтение флага возвращает значение LihonT (см. `profile_features.py`).
|
||||
- Переключатель выключен: возвращается значение, которое прочитал сам TikTok. LihonT
|
||||
ничего не подставляет и не утверждает, что функция доступна.
|
||||
- Приложение ещё не создано или файл временно не читается: для этого вызова действуют
|
||||
значения по умолчанию, результат не запоминается.
|
||||
- Файл повреждён или записан более новой схемой: процесс до перезапуска работает со
|
||||
значениями по умолчанию; экран настроек при этом показывает ошибку и файл не трогает.
|
||||
Reference in New Issue
Block a user