# HAN Chat Mobile Мобильный клиент HAN Chat на Expo SDK 57. Текущая версия приложения — `1.0.1`, native identity — Android `versionCode: 2` и iOS `buildNumber: 2`. ## Подготовка 1. Установить Node.js и npm. 2. Скопировать `.env.example` в `.env` и указать адреса API и Keycloak. 3. Установить зависимости: ```bash npm install ``` 4. Зарегистрировать `han-chat://auth/callback` как допустимый redirect URI клиента Keycloak. ## Локальные проверки ```bash npm run typecheck npm test ``` Запуск приложения выполняется отдельно командой `npm run android`. Проект использует managed Expo workflow и не хранит каталоги `android/` и `ios/`. ## Store-only обновления Приложение не загружает JS/asset OTA-обновления. Оно читает `mobile_update` из `GET /api/v1/public/app-config` и отправляет пользователя в магазин своей сборки. Канал фиксируется на этапе EAS build: - `EXPO_PUBLIC_DISTRIBUTION_STORE=google_play`; - `EXPO_PUBLIC_DISTRIBUTION_STORE=rustore`; - `EXPO_PUBLIC_DISTRIBUTION_STORE=app_store`. Неизвестное или отсутствующее значение отключает механику. Поэтому профили `development` и `preview` имеют значение `disabled`. Профиль `preview-rustore` намеренно задаёт `rustore`, чтобы проверять update policy на внутреннем APK через dev-backend. Решение принимается только по целому native build: - build ниже `minimum_build` — обязательное (`force`) обновление; - build ниже `latest_build`, но не ниже minimum — мягкое (`soft`) обновление; - build не ниже latest — обновление не показывается. Soft-карточку можно закрыть; выбор запоминается в SecureStore отдельно для пары `канал + latest_build`. Force-карточка блокирует Android Back и не имеет способов закрытия. Проверка выполняется на холодном старте и при возврате в foreground, параллельные проверки объединяются. Сетевая ошибка, невалидный build или недоверенный URL работают fail-open и не блокируют интерфейс. Допускаются только HTTPS-ссылки соответствующего магазина: `play.google.com/store/apps/details?id=ru.han.chat`, `www.rustore.ru/catalog/app/ru.han.chat` и App Store URL на `apps.apple.com` с Apple ID. ## Сборка (EAS) Профили заданы в `eas.json`. Env для билда берётся из профиля (`eas.json` → `env`), а не из локального `.env`. | Профиль | Артефакт | API | `EXPO_PUBLIC_APP_ENV` | |---|---|---|---| | `preview` | APK (внутренняя установка) | `dev-chat.han0107.ru` | update policy отключена | | `preview-rustore` | APK (тест RuStore policy) | `dev-chat.han0107.ru` | `rustore` | | `google-play` | AAB (Google Play) | `chat.han0107.ru` | `google_play` | | `rustore` | AAB (RuStore) | `chat.han0107.ru` | `rustore` | | `app-store` | iOS App Store | `chat.han0107.ru` | `app_store` | | `development` | Dev Client | из окружения/локально | update policy отключена | ### Один раз: вход в Expo ```powershell cd C:\Users\MI\Documents\Assistent\HAN_chat_specification\VM4_Expo-mobile npx eas-cli login npx eas-cli whoami ``` Проект уже привязан (`owner: anzh`, `projectId` в `app.config.ts`). Android keystore хранится remote на Expo. ### Перед сборкой (рекомендуется) ```powershell npm run typecheck npm test ``` ### Preview — APK на телефон ```powershell npx eas-cli build --profile preview --platform android ``` После успеха откройте ссылку из вывода CLI (или `https://expo.dev/accounts/anzh/projects/han-chat/builds`) и скачайте APK. ### Preview RuStore — проверка soft/force update ```powershell npx eas-cli build:version:get --platform android --profile preview-rustore npx eas-cli build --profile preview-rustore --platform android ``` Профиль использует dev API и встраивает канал `rustore`, но не увеличивает общий remote Android `versionCode` (`autoIncrement: false`). Запишите build из `build:version:get` или карточки завершённой сборки. Для build `B` настройте политику RuStore на dev-backend: - soft: `latest_build=B+1`, `minimum_build<=B`; - force: `latest_build=B+1`, `minimum_build=B+1`; - none: `latest_build<=B`. После изменения dev settings примените штатный `seed-settings`, подождите до истечения cache TTL и перезапустите APK. Для повторной проверки soft на том же `latest_build` очистите данные приложения или увеличьте `latest_build`, так как «Позже» сохраняется в SecureStore без TTL. APK имеет тот же package `ru.han.chat` и подпись EAS, поэтому может заменить установленную store-сборку. Используйте отдельное тестовое устройство или заранее учтите замену приложения и его локальных данных. ### Store-сборки ```powershell npx eas-cli build --profile google-play --platform android npx eas-cli build --profile rustore --platform android npx eas-cli build --profile app-store --platform ios ``` Native build поднимается через `appVersionSource: remote` и platform-specific `autoIncrement`. Google Play и RuStore используют общий Android application ID `ru.han.chat`, поэтому их последовательные сборки увеличивают один remote `versionCode`: например, первая получит `7`, следующая — `8`. Backend-пороги магазинов поэтому заполняются независимо по фактически опубликованным артефактам. Локальные `versionCode: 2`/`buildNumber: 2` служат исходной native identity, но при remote source фактическое значение сборки определяет EAS. ### Полезные команды ```powershell # только отправить билд и сразу вернуть ссылку (не ждать окончания) npx eas-cli build --profile google-play --platform android --no-wait # статус конкретной сборки npx eas-cli build:view # список последних сборок npx eas-cli build:list --platform android --limit 5 # прочитать текущий remote versionCode/buildNumber npx eas-cli build:version:get --platform android --profile google-play npx eas-cli build:version:get --platform android --profile rustore npx eas-cli build:version:get --platform ios --profile app-store # скачать артефакт готовой сборки npx eas-cli build:download --id # синхронизировать versionCode с Play Console (если нужно вручную) npx eas-cli build:version:set ``` Полная процедура rollout, включения soft/force policy и отката: `../VM1_app/codebase/backend/deployment/RUNBOOK.mobile-updates.ru.md`. ### Keycloak redirect URI Для боевого хоста в клиенте `han-chat-frontend` должны быть exact URI: - `https://chat.han0107.ru/mobile/oidc/callback` - `han-chat://auth/callback` Для preview — те же пути на `https://dev-chat.han0107.ru`.