Карточка альбома устройства получает третью строку: метку режима («Копии»/ «Перенос») и ход загрузки. Процент считается как (uploaded + running) / total для обоих синхронизируемых режимов, пульсирует только при активной загрузке, показывает очередь, ожидание Wi-Fi и ошибку. В режиме переноса карточка показывает и карту памяти, и облако — режимы различает метка, а не значки. Разгрузка оригиналов теперь требует подтверждённой серверной копии в текущем целевом альбоме: устаревший serverPhotoId перепроверяется по альбому, смена цели переносит уже загруженные фото и отклоняется, если перенести нельзя. Потеря серверной копии видна на карточке и на экране альбома, автозатирания превью нет. Изменения OpenSpec: android-album-card-sync-status, safe-album-offload.
5.6 KiB
5.6 KiB
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). - Веб-клиент: не затрагивается.
- Не затрагивается: ручные загрузки в серверный альбом; восстановление уже потерянных копий из корзины сервера (по решению пользователя это отдельная задача).