feat(android): статус синхронизации на карточке и безопасная разгрузка
Карточка альбома устройства получает третью строку: метку режима («Копии»/ «Перенос») и ход загрузки. Процент считается как (uploaded + running) / total для обоих синхронизируемых режимов, пульсирует только при активной загрузке, показывает очередь, ожидание Wi-Fi и ошибку. В режиме переноса карточка показывает и карту памяти, и облако — режимы различает метка, а не значки. Разгрузка оригиналов теперь требует подтверждённой серверной копии в текущем целевом альбоме: устаревший serverPhotoId перепроверяется по альбому, смена цели переносит уже загруженные фото и отклоняется, если перенести нельзя. Потеря серверной копии видна на карточке и на экране альбома, автозатирания превью нет. Изменения OpenSpec: android-album-card-sync-status, safe-album-offload.
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
# Proposal
|
||||
|
||||
## Why
|
||||
|
||||
Реальный инцидент: альбом устройства U2 синхронизировался в режиме переноса в серверный
|
||||
альбом A (фото загружены, локальные оригиналы заменены превью), затем альбом A удалили на
|
||||
сервере, а альбом устройства перепривязали к новому серверному альбому U2. В U2 уехало всего
|
||||
1 фото: остальные на телефоне уже были превью, и загрузить их заново было нечем. Оригиналы
|
||||
остались только в корзине сервера, а приложение молча оставило телефон с превью.
|
||||
|
||||
Три причины:
|
||||
- решение о разгрузке принимается по `serverPhotoId` в локальном индексе, без проверки, что
|
||||
это фото вообще есть в **текущем** целевом альбоме;
|
||||
- смена целевого альбома только перезаписывает связь: уже загруженные фото никто не переносит
|
||||
на сервере, а из превью повторно не загрузить;
|
||||
- потеря серверной копии — тихий тупик: `ORPHANED` виден, но нигде не сказано, что оригинал
|
||||
утрачен, и нет явного предупреждения.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Доверие только к живой копии.** Записанный `serverPhotoId` считается действительным,
|
||||
только если это фото присутствует в целевом альбоме. Если копии нет: при локальном
|
||||
оригинале ассет загружается заново, при одном превью элемент помечается потерявшим копию.
|
||||
- **Разгрузка только под защитой.** Замена оригинала превью выполняется, только если копия
|
||||
подтверждена в целевом альбоме; разгрузка «по памяти индекса» запрещена. Автоматическая
|
||||
разгрузка в режиме переноса сохраняется.
|
||||
- **Смена цели переносит копии.** При смене целевого альбома приложение сначала переносит на
|
||||
сервере уже загруженные этим альбомом устройства фото в новый альбом и переключает связь
|
||||
только если перенос удался; иначе связь не меняется и пользователь получает отказ.
|
||||
- **Потеря копии видна.** Экран альбома устройства и карточка альбома в списке показывают,
|
||||
сколько фото осталось без серверной копии; никакого автоматического удаления превью.
|
||||
- **BREAKING**: нет. Меняются только защитные условия; успешные сценарии (загрузка,
|
||||
разгрузка, повторная синхронизация) сохраняют поведение.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
_Нет — поведение относится к существующим способностям._
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `phone-album-sync`: разгрузка требует живой копии в текущем целевом альбоме; записанный
|
||||
`serverPhotoId` перепроверяется по целевому альбому; смена целевого альбома переносит уже
|
||||
загруженные фото и отклоняется, если перенести нельзя.
|
||||
- `android-client`: потеря серверной копии показывается на экране альбома устройства и на
|
||||
карточке в списке; автоматического удаления превью нет.
|
||||
|
||||
## Impact
|
||||
|
||||
- **Код (Android):** `data/sync/SyncPlan` (доверие к живой копии), `data/sync/SyncCoordinator`
|
||||
(защищённая разгрузка, перенос при смене цели), `data/sync/OffloadManager` (условие разгрузки),
|
||||
`data/upload/UploadWorker` (передача живой копии после загрузки), `data/db/dao/SyncDao` и
|
||||
`data/repo/SyncRepository` (счёт потерянных копий), `ui/devicealbum/DeviceAlbumViewModel`
|
||||
(смена цели, разгрузка, предупреждение), `ui/devicealbum/DeviceAlbumScreen` (баннер),
|
||||
`domain/sync/AlbumSyncProgress` и `ui/albums/*` (сигнал на карточке).
|
||||
- **Схема Room:** без изменений; добавляются только запросы.
|
||||
- **API и бэкенд:** не затрагиваются (используется существующий `/api/photo-batch/move`).
|
||||
- **Веб-клиент:** не затрагивается.
|
||||
- **Не затрагивается:** ручные загрузки в серверный альбом; восстановление уже потерянных
|
||||
копий из корзины сервера (по решению пользователя это отдельная задача).
|
||||
Reference in New Issue
Block a user