# Spec Delta ## Purpose Синхронизация альбома устройства с существующим серверным альбомом: режимы A/B/C, отслеживание изменений, идентичность и дедупликация, политика удалений, разгрузка места и провенанс разгруженных превью. ## ADDED Requirements ### Requirement: Режимы синхронизации альбома устройства Альбом устройства SHALL иметь выбираемый режим синхронизации: выключена (A — только локально), копии оригиналов на сервере (B), перенос оригиналов на сервер (C). Пока режим A, приложение SHALL показывать альбом локально и SHALL NOT обращаться к серверу по этому альбому. #### Scenario: Выключенная синхронизация - **WHEN** у альбома устройства выбран режим A - **THEN** приложение показывает альбом из локальных файлов и не отправляет запросы на сервер по этому альбому #### Scenario: Копии оригиналов - **WHEN** у альбома устройства выбран режим B - **THEN** оригиналы остаются на устройстве, а их копии загружаются в целевой серверный альбом #### Scenario: Перенос оригиналов - **WHEN** у альбома устройства выбран режим C - **THEN** оригиналы загружаются на сервер, а на устройстве вместо них остаются превью ### Requirement: Выбор целевого серверного альбома При включении синхронизации пользователь SHALL выбрать серверный альбом назначения — существующий или созданный на месте, с именем, предзаполненным именем альбома устройства. Несколько альбомов устройства SHALL иметь возможность указывать на один серверный альбом. #### Scenario: Выбор цели - **WHEN** пользователь включает синхронизацию альбома устройства - **THEN** приложение предлагает выбрать существующий серверный альбом или создать новый с предзаполненным именем и сохраняет выбор #### Scenario: Несколько источников в одну цель - **WHEN** два альбома устройства указывают на один серверный альбом - **THEN** оба синхронизируются в него, а связь каждого отражается отдельно ### Requirement: Отслеживание изменений на устройстве Приложение SHALL отслеживать изменения содержимого синхронизируемого альбома устройства — добавление, удаление, переименование, перенос между альбомами и изменение содержимого — и SHALL хранить локальный индекс, позволяющий обнаружить удаления, произошедшие вне приложения. #### Scenario: Добавление - **WHEN** в альбоме устройства появляется новое медиа - **THEN** приложение фиксирует его как новое и ставит в очередь синхронизации #### Scenario: Удаление вне приложения - **WHEN** медиа удалено из альбома устройства другим приложением или системной галереей - **THEN** приложение обнаруживает отсутствие по локальному индексу #### Scenario: Переименование и перенос - **WHEN** медиа переименовано или перемещено между альбомами устройства - **THEN** приложение фиксирует изменение имени или принадлежности альбому ### Requirement: Синхронизация изменений с сервером Для каждого отслеженного изменения приложение SHALL применить его к целевому серверному альбому: загрузить новое содержимое, переименовать и перенести через API, а изменение содержимого SHALL трактовать как новую загрузку с удалением устаревшей собственной загрузки. #### Scenario: Новое содержимое - **WHEN** в альбоме устройства появилось медиа, которого нет на сервере - **THEN** приложение загружает его в целевой серверный альбом #### Scenario: Переименование доходит до сервера - **WHEN** медиа переименовано на устройстве и уже синхронизировано - **THEN** приложение переименовывает соответствующее серверное фото #### Scenario: Изменение содержимого - **WHEN** содержимое медиа изменено на устройстве - **THEN** приложение загружает новую версию, а устаревшую собственную загрузку удаляет ### Requirement: Идентичность по контрольной сумме Приложение SHALL сопоставлять локальный ассет с серверным фото по контрольной сумме содержимого и SHALL NOT повторно загружать содержимое, уже присутствующее на сервере. #### Scenario: Повторная синхронизация - **WHEN** синхронизация запускается повторно без изменений содержимого - **THEN** приложение не создаёт новых загрузок #### Scenario: Уже загруженное содержимое - **WHEN** содержимое ассета уже присутствует на сервере (в том числе загружено ранее) - **THEN** приложение связывает ассет с существующим серверным фото без загрузки ### Requirement: Удаление только собственных загрузок При удалении содержимого на устройстве приложение SHALL удалять на сервере только фото, загруженные этим клиентом, и SHALL сохранять остальные фото целевого альбома, в том числе загруженные из других источников. #### Scenario: Собственная загрузка - **WHEN** удалено содержимое, которое загрузил этот клиент, и его контрольная сумма отсутствует во всех локальных альбомах, льющихся в этот серверный - **THEN** приложение удаляет соответствующее серверное фото #### Scenario: Чужие фото - **WHEN** в целевом серверном альбоме есть фото, загруженные из других источников - **THEN** приложение не удаляет их ### Requirement: Отражение серверных изменений на устройстве Приложение SHALL отражать изменения целевого серверного альбома — новые фото, переименования, теги, подписи и удаления — в локальном представлении, SHALL NOT изменять или удалять оригиналы на устройстве. #### Scenario: Новое с другого устройства - **WHEN** другое устройство добавляет фото в целевой серверный альбом - **THEN** приложение показывает его в серверном представлении альбома #### Scenario: Удалено на сервере - **WHEN** серверное фото удалено на сервере - **THEN** приложение убирает его из локального представления, не трогая оригинал на устройстве ### Requirement: Разгрузка оригиналов в режиме переноса В режиме C после успешной загрузки приложение SHALL автоматически заменять оригинал на устройстве превью, без отдельного действия на экране; видео SHALL заменяться постером-кадром. При включении режима C приложение SHALL запрашивать широкий доступ к файлам, чтобы замена выполнялась без системного диалога согласия. #### Scenario: Разгрузка фото - **WHEN** оригинал фото успешно загружен - **THEN** файл в галерее автоматически заменяется превью с сохранением даты съёмки и места в альбоме #### Scenario: Разгрузка видео - **WHEN** оригинал видео успешно загружен - **THEN** видео в галерее автоматически заменяется статичным постером-кадром, а элемент в приложении остаётся видео с оригиналом на сервере #### Scenario: Доступ к файлам для разгрузки - **WHEN** пользователь включает режим переноса - **THEN** приложение запрашивает широкий доступ к файлам, и разгрузка выполняется без системного диалога согласия ### Requirement: Провенанс разгруженных превью Разгруженные превью и постеры видео SHALL содержать метаданные провенанса, достаточные для восстановления связи с серверным альбомом и принадлежности загрузок после переустановки приложения. #### Scenario: Восстановление после переустановки - **WHEN** приложение переустановлено или его данные очищены, а альбом устройства содержит разгруженные превью - **THEN** приложение восстанавливает связь с серверным альбомом и принадлежность своих загрузок из метаданных превью #### Scenario: Метка утрачена - **WHEN** метаданные провенанса недоступны (например, файл перезаписан сторонним редактором) - **THEN** элемент считается неопознанным, не удаляется и не загружается повторно ### Requirement: Возврат оригиналов и отвязка При выходе из режима C приложение SHALL предложить вернуть оригиналы на устройство и SHALL предупредить, если пользователь отказывается. Отвязка альбома и выключение синхронизации SHALL NOT удалять фото с сервера. #### Scenario: Возврат оригиналов - **WHEN** пользователь выходит из режима C и соглашается вернуть оригиналы - **THEN** приложение возвращает оригиналы на устройство вместо превью #### Scenario: Отказ от возврата - **WHEN** пользователь выходит из режима C и отказывается возвращать оригиналы - **THEN** приложение предупреждает, что на устройстве останутся только превью #### Scenario: Отвязка - **WHEN** пользователь отвязывает альбом устройства от серверного - **THEN** фото на сервере сохраняются #### Scenario: Выключение синхронизации - **WHEN** пользователь выключает синхронизацию альбома устройства - **THEN** связь с серверным альбомом снимается, а фото на сервере сохраняются ### Requirement: Автоматическая фоновая синхронизация Синхронизация SHALL выполняться автоматически: при открытом приложении — по событиям изменения, в фоне — периодически, с учётом ограничений сети, выбранных пользователем. В режиме C разгрузка оригиналов SHALL выполняться автоматически после успешной загрузки. #### Scenario: Фоновая синхронизация - **WHEN** приложение не открыто, а в альбоме устройства появились изменения - **THEN** синхронизация выполняется в фоне при ближайшей возможности #### Scenario: Ограничение сети - **WHEN** включено ограничение «только Wi-Fi», а доступна только сотовая сеть - **THEN** синхронизация не начинается до появления Wi-Fi #### Scenario: Автоматическая разгрузка - **WHEN** оригиналы загружены в режиме C - **THEN** замена оригиналов превью выполняется автоматически, без отдельного подтверждения ### Requirement: Локальные превью Приложение SHALL генерировать превью на устройстве и хранить их локально; при просмотре элемента без локального оригинала приложение SHALL подгружать оригинал с сервера. #### Scenario: Сетка из превью - **WHEN** открыт альбом устройства - **THEN** сетка показывает локальные превью #### Scenario: Просмотр без локального оригинала - **WHEN** пользователь открывает элемент, чей оригинал разгружен на сервер - **THEN** приложение подгружает оригинал с сервера для полноэкранного просмотра