# Proposal ## Why Список альбомов в Android-клиенте обновляется только REST-снимком при открытии экрана, поэтому изменения, сделанные с другого устройства или в веб-клиенте (создание, переименование, смена обложки, изменение состава участников, удаление альбома, изменение состава фото), не доходят до открытого приложения до ручного обновления. На вебе это уже решено персональным потоком `GET /api/sse/me`, и сервер события публикует, но Android к этому потоку не подключён. Отдельно открытый экран альбома не обрабатывает потерю доступа: при удалении альбома владельцем или исключении участника экран продолжает отображать устаревшие данные (или пустую сетку с заголовком-заглушкой), а карточка остаётся в списке. ## What Changes - Android подписывается на персональный поток `GET /api/sse/me` и применяет `album.created`, `album.updated` и `album.deleted` к локальному кэшу (Room) без дополнительного запроса списка. - Подписка привязана к сессии: создаётся при входе на главный экран и завершается при выходе из аккаунта, не пересоздаётся при навигации между экранами. - Применение события — это мутация кэша: `upsert` объекта альбома или удаление альбома и связанных с ним фото. Список и открытый экран альбома наблюдают Room и обновляются сами, дополнительных запросов на каждое событие нет. - `album.deleted` (удаление владельцем или исключение участника) убирает альбом из кэша; открытый экран этого альбома перестаёт его показывать и возвращается к списку. - При переподключении персонального потока клиент догоняет состояние REST-снимком списка альбомов, поэтому изменения, пропущенные во время разрыва, не теряются. - Порядок элементов списка — правило отображения клиента: событие, применённое к локальному кэшу, может изменить позицию альбома (Android упорядочивает серверные альбомы по времени изменения). - События `notification` в персональном потоке игнорируются: в Android нет экрана уведомлений и приглашений. - **BREAKING**: нет. Изменение аддитивное: пер-альбомный контракт событий и REST остаются прежними, неизвестные клиенту события он уже сейчас игнорирует. ## Capabilities ### New Capabilities _Нет — поведение расширяет существующие способности `android-client` и `realtime`._ ### Modified Capabilities - `android-client`: добавляется живое обновление списка альбомов из персонального потока (применение событий к кэшу без запроса списка, догон при переподключении) и обработка потери доступа к альбому (удаление из кэша, уход открытого экрана). - `realtime`: сценарий «Обновление альбома из списка» больше не требует сохранять порядок списка от всех клиентов — порядок становится правилом отображения клиента. ## Impact - **Код (Android):** новый клиент персонального потока (`data/network`), парсер событий жизненного цикла альбома, применение событий в `data/repo` (Room), подписка в `ui/albums/AlbumsViewModel`, обработка потери доступа в `ui/album/AlbumViewModel` и `ui/album/AlbumScreen`, `di/AppContainer`. - **Схема Room:** без изменений (новых колонок и миграций не требуется). - **API:** новых эндпоинтов нет; существующий `GET /api/sse/me` начинает использоваться мобильным клиентом. Для авторизации используется заголовок `Authorization` (у Android есть интерцептор), поэтому query-параметр `token` не нужен. - **Не затрагивается:** веб-клиент, бэкенд (события и веер уже реализованы), схема БД, пер-альбомный поток, загрузка и синхронизация медиа. - **Известное ограничение (фиксируется, не закрывается здесь):** пер-альбомный SSE проверяет доступ только при подключении, поэтому исключённый участник продолжает получать события альбома до разрыва соединения. Персональный поток закрывает список и открытый экран, но не отменяет установленное соединение.