6.9 KiB
6.9 KiB
Proposal
Why
Android-клиент работает только с серверными альбомами и ручной загрузкой через системный Photo Picker: он не видит альбомы самого телефона, не следит за их изменениями и не освобождает место. Основной мобильный сценарий — «снимаю на телефон и не думаю о переносе» — не покрыт. Нужна синхронизация альбомов устройства с серверным альбомом в трёх режимах, с отслеживанием изменений.
What Changes
- Смешанный список альбомов: альбомы устройства (MediaStore bucket'ы) и серверные альбомы в одном списке; связанная пара «телефонный → серверный» показывается одной карточкой устройства с указателем связи и меткой режима, а связанный серверный альбом из списка скрывается.
- Экран альбома устройства с настройками по свайпу вправо: только выбор режима синхронизации; целевой серверный альбом выбирается (или создаётся) при включении, допускается n:1.
- Три режима синхронизации альбома:
- A — выключена: оригиналы на телефоне, превью генерируются и хранятся на телефоне; сервера не касается.
- B — копии оригиналов: оригиналы остаются на телефоне, копии загружаются на сервер.
- C — перенос оригиналов: оригиналы уходят на сервер, на телефоне вместо них остаются превью; замена файла в галерее выполняется автоматически (широкий доступ к файлам запрашивается при включении режима, без системного диалога); видео заменяется постером.
- Отслеживание и синхронизация изменений (добавление, удаление, переименование,
перенос между альбомами, правка контента как «новый + удалить старый»)
автоматически в фоне (
MediaStore.getGeneration/ContentObserver+ периодический WorkManager) и при открытом приложении (SSE +?since=). - Идентичность и дедупликация по content-hash (sha256) относительно контрольной суммы объекта на сервере; удаление на сервере — только для «наших» загрузок.
- Провенанс, переживающий переустановку: в EXIF разгруженных в C превью пишется метка (серверный альбом/фото, hash оригинала), по которой связь и провенанс восстанавливаются.
- Возврат оригиналов из C («вернуть оригиналы»); отвязка и выключение синхронизации никогда не удаляют фотографии с сервера.
- Сервер начинает отдавать контрольную сумму оригинала в данных фото (малая
правка API, без миграции БД —
checksumуже хранится). - BREAKING: нет (добавляемое поле ответа; существующие клиенты не ломаются).
Capabilities
New Capabilities
phone-album-sync: синхронизация альбома устройства с существующим серверным альбомом — режимы A/B/C, отслеживание изменений, идентичность и дедуп по content-hash, политика удалений, разгрузка места и провенанс.
Modified Capabilities
android-client: смешанный список альбомов устройства и сервера, экран и настройки синхронизации телефонного альбома, широкий доступ к медиа (READ_MEDIA_*) и фоновая работа синхронизации.photos: данные фото включают контрольную сумму оригинала, чтобы клиент мог сопоставлять локальный ассет с серверным фото и не загружать дубли.
Impact
android/: новый источник MediaStore (bucket'ы и ассеты), движок синхронизации и очередь на существующемUploadRepository/UploadWorker, локальный индекс и провенанс в Room, кэш превью, EXIF-метка, чтение/запись превью (широкий доступ к файламMANAGE_EXTERNAL_STORAGE), правки навигации (GaloNavHost), манифеста (права) иAppContainer.backend/: отдатьchecksumв моделях/запросах/ответах фото. Миграции БД не требуются.- Зависимости клиента: MediaStore, ExifInterface, MediaMetadataRetriever, WorkManager, Room, Coil — большинство уже подключено.
- Платформенные ограничения: согласие ОС на изменение/удаление чужого медиа;
фоновая работа ограничена WorkManager; Google Play ограничивает
READ_MEDIA_*. - Предпосылка (побочно, вне объёма этой правки):
.gitignoreсодержит правилоdata/, из-за которого весь Kotlin-слойandroid/.../com/galo/android/data/не отслеживается git и отсутствует в git-истории. До реализации это нужно устранить, иначе новые файлы синхронизации тоже не попадут в коммит. - Вне объёма: iOS; синхронизация на уровне сервера (устройства/сессии на бэкенде); многопользовательские конфликты владения; редактирование изображений.