Files
han-app/VM4_Expo-mobile
..

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. Установить зависимости:

    npm install
    
  4. Зарегистрировать han-chat://auth/callback как допустимый redirect URI клиента Keycloak.

Локальные проверки

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.jsonenv), а не из локального .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

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.

Перед сборкой (рекомендуется)

npm run typecheck
npm test

Preview — APK на телефон

npx eas-cli build --profile preview --platform android

После успеха откройте ссылку из вывода CLI (или https://expo.dev/accounts/anzh/projects/han-chat/builds) и скачайте APK.

Preview RuStore — проверка soft/force update

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-сборки

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.

Полезные команды

# только отправить билд и сразу вернуть ссылку (не ждать окончания)
npx eas-cli build --profile google-play --platform android --no-wait

# статус конкретной сборки
npx eas-cli build:view <BUILD_ID>

# список последних сборок
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 <BUILD_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.