Files
ds-galo/openspec/specs/android-client/spec.md
T
iu e4fc6f0ce9 chore(openspec): архивировать android-album-sort и синхронизировать основные спеки
android-client: +1 требование — выбор порядка карточек и направления, порядок
охватывает весь список вместе с альбомами устройства.
2026-10-16 13:27:30 +03:00

48 KiB

android-client Specification

Purpose

Android-клиент для self-hosted galo: настройка подключения к серверу, авторизация, просмотр альбомов и медиа, а также фоновая загрузка фотографий и видео с телефона с офлайн-кэшем.

Requirements

Requirement: Настройка подключения к серверу

Приложение SHALL требовать явного указания базового URL инстанса galo при первом запуске и SHALL проверять доступность сервера перед переходом к работе.

Scenario: Успешная настройка

  • WHEN пользователь вводит достижимый базовый URL и подтверждает
  • THEN приложение проверяет GET /api/health и при успехе переходит к входу

Scenario: Сервер недоступен

  • WHEN сервер недоступен или health вернул ошибку
  • THEN приложение показывает ошибку и остаётся на экране настройки, сохраняя введённый URL

Requirement: Небезопасное соединение по LAN

Приложение SHALL по умолчанию запрещать незашифрованный HTTP и SHALL разрешать его только после явного включения пользователем режима небезопасного соединения.

Scenario: HTTP без разрешения

  • WHEN пользователь указывает http-URL и режим небезопасного соединения выключен
  • THEN приложение блокирует подключение и предлагает включить режим

Scenario: Режим включён

  • WHEN пользователь включил режим небезопасного соединения
  • THEN HTTP-подключение разрешено, а интерфейс явно отмечает небезопасное соединение

Requirement: Разрешение относительных URL объектов

Приложение SHALL трактовать относительные URL объектов из REST-ответов и SSE как пути на выбранном базовом URL сервера.

Scenario: Отдача объекта

  • WHEN API возвращает thumb_url вида /api/objects/<key>?...
  • THEN приложение запрашивает объект с того же инстанса, что и базовый URL

Requirement: Вход и хранение сессии

Приложение SHALL позволять вход и регистрацию по email и паролю и SHALL хранить токены только в защищённом хранилище платформы.

Scenario: Успешный вход

  • WHEN вход проходит успешно
  • THEN токены сохраняются в защищённом хранилище, пользователь видит список альбомов

Scenario: Перезапуск с сессией

  • WHEN приложение перезапущено с сохранённой сессией
  • THEN пользователь остаётся авторизованным без повторного ввода пароля

Requirement: Автоматическое обновление токена

Приложение SHALL автоматически обновлять access-токен при ответе 401, пока refresh-токен действителен, и SHALL завершать сессию при неудачном обновлении.

Scenario: Прозрачное обновление

  • WHEN запрос получает 401 и refresh-токен действителен
  • THEN приложение обновляет токен и повторяет исходный запрос без участия пользователя

Scenario: Обновление не удалось

  • WHEN обновление токена завершилось ошибкой
  • THEN сессия очищается и пользователь возвращается на экран входа

Requirement: Список альбомов

Приложение SHALL показывать доступные пользователю альбомы одним смешанным списком: серверные альбомы, получаемые из API, а при отсутствии сети — из локального кэша, и альбомы устройства. Элементы SHALL различать источник. Связанная пара «альбом устройства → серверный альбом» SHALL отображаться одной карточкой альбома устройства с указателем связи и меткой режима; связанный серверный альбом SHALL NOT показываться в списке отдельной записью.

Scenario: Онлайн

  • WHEN авторизованный пользователь открывает приложение
  • THEN отображается список альбомов с обложками или плейсхолдером

Scenario: Офлайн из кэша

  • WHEN сеть недоступна, но кэш существует
  • THEN список альбомов отображается из кэша с признаком офлайн-режима

Scenario: Альбомы устройства

  • WHEN у приложения есть доступ к медиа устройства
  • THEN в списке появляются альбомы устройства наряду с серверными и помечены источником

Scenario: Связанная пара

  • WHEN альбом устройства синхронизируется с серверным альбомом
  • THEN в списке показывается одна карточка альбома устройства с указателем связи и меткой режима, а связанный серверный альбом отдельной записью не показывается

Requirement: Экран альбома устройства и настройки синхронизации

Приложение SHALL открывать альбом устройства с сеткой медиа и SHALL предоставлять настройки синхронизации этого альбома по свайпу вправо. Настройки SHALL содержать только выбор режима синхронизации.

Scenario: Открытие альбома устройства

  • WHEN пользователь выбирает альбом устройства в списке
  • THEN открывается сетка медиа этого альбома

Scenario: Настройки по свайпу

  • WHEN пользователь свайпает вправо в открытом альбоме устройства
  • THEN открываются настройки синхронизации с выбором режима и только им

Scenario: Метка перенесённого элемента

  • WHEN оригинал элемента разгружен на сервер в режиме переноса
  • THEN в сетке на элементе показывается значок облака

Requirement: Доступ к альбомам устройства

Приложение SHALL запрашивать доступ к медиа устройства, нужный для перечисления альбомов и чтения файлов, и SHALL работать без него, не показывая альбомы устройства.

Scenario: Доступ предоставлен

  • WHEN пользователь предоставляет доступ к медиа устройства
  • THEN приложение перечисляет альбомы устройства и их содержимое

Scenario: Доступ не предоставлен

  • WHEN доступ к медиа устройства не предоставлен
  • THEN приложение продолжает работать с серверными альбомами и не показывает альбомы устройства

Requirement: Постраничный просмотр альбома

Приложение SHALL показывать сетку медиа альбома с постраничной загрузкой по курсору и SHALL подгружать следующую страницу при достижении конца списка.

Scenario: Догрузка страницы

  • WHEN пользователь прокручивает сетку до конца
  • THEN приложение запрашивает следующую страницу по курсору и добавляет её к сетке

Scenario: Пустой альбом

  • WHEN в альбоме нет медиа
  • THEN отображается пустое состояние

Requirement: Просмотр медиа на весь экран

Полноэкранный просмотр SHALL поддерживать изображение с зумом пальцами, видео с постером и управлением воспроизведением, а также панораму 360; навигация между элементами альбома SHALL выполняться свайпом.

Scenario: Свайп между элементами

  • WHEN пользователь свайпает в просмотре
  • THEN показывается следующий или предыдущий элемент альбома без выхода из просмотра

Scenario: Видео

  • WHEN открыт видеоэлемент
  • THEN показывается постер и доступно воспроизведение с перемоткой

Requirement: Обновления в реальном времени

Пока экран альбома активен, приложение SHALL отображать изменения по SSE (новые, обновлённые и удалённые медиа, социальные события) и SHALL догонять пропущенное при переподключении.

Scenario: Новое фото с другого устройства

  • WHEN другое устройство добавляет фото в открытый альбом
  • THEN новое фото появляется в сетке без ручного обновления

Scenario: Переподключение

  • WHEN SSE-соединение разорвалось и восстановилось
  • THEN приложение дозагружает изменения, произошедшие за время разрыва

Requirement: Выбор медиа и альбома для загрузки

Приложение SHALL предоставлять выбор одного или нескольких фото и видео из системной галереи и SHALL требовать выбора альбома назначения перед постановкой в очередь.

Scenario: Постановка в очередь

  • WHEN пользователь выбрал файлы и альбом назначения
  • THEN задания загрузки ставятся в очередь и пользователь видит их статус

Scenario: Отказ сервера

  • WHEN сервер отклоняет загрузку (например, из-за прав или размера)
  • THEN задание помечается ошибкой с причиной от сервера

Requirement: Фоновая очередь загрузки

Загрузка SHALL выполняться по одному файлу за HTTP-запрос и SHALL продолжаться при уходе приложения из foreground, показывая прогресс в уведомлении; при ошибке SHALL выполняться повтор с нарастающей задержкой.

Scenario: Уход в фон

  • WHEN приложение уходит в фон во время загрузки
  • THEN загрузка продолжается и прогресс отображается в уведомлении

Scenario: Повтор при ошибке

  • WHEN загрузка файла завершилась сетевой ошибкой
  • THEN задание повторяется, а после исчерпания попыток помечается ошибкой

Requirement: Условия сети для загрузки

Приложение SHALL позволять ограничить загрузку сетью Wi-Fi; при ожидании подходящей сети задание остаётся в очереди и не выполняется.

Scenario: Только Wi-Fi

  • WHEN ограничение «только Wi-Fi» включено, а доступна только сотовая сеть
  • THEN загрузка не начинается до появления Wi-Fi, а задание остаётся в очереди

Requirement: Сохранность очереди между запусками

Очередь загрузки SHALL сохраняться на устройстве и SHALL продолжаться после перезапуска приложения или устройства.

Scenario: Возобновление после перезапуска

  • WHEN приложение или устройство перезапускается при незавершённой очереди
  • THEN незавершённые задания возобновляются

Requirement: Конвертация HEIC в JPEG

Файлы HEIC/HEIF SHALL конвертироваться на устройстве в JPEG перед загрузкой с сохранением даты съёмки и геолокации.

Scenario: Загрузка HEIC

  • WHEN пользователь ставит в очередь HEIC-файл
  • THEN загружается JPEG-версия, а дата съёмки и координаты из EXIF сохраняются

Scenario: Ошибка конвертации

  • WHEN конвертация завершилась ошибкой
  • THEN задание помечается ошибкой, повреждённый файл не загружается

Requirement: Кэш медиа по устойчивому ключу

Приложение SHALL кэшировать полученные превью и оригиналы по устойчивому идентификатору объекта, не зависящему от подписи и срока действия URL.

Scenario: Смена подписи

  • WHEN URL одного и того же объекта со временем получает новую подпись
  • THEN приложение переиспользует закэшированный объект вместо повторной загрузки

Scenario: Офлайн-отдача из кэша

  • WHEN сеть недоступна, а объект есть в кэше
  • THEN объект отображается из кэша

Requirement: Единый формат ошибок API

Приложение SHALL распознавать ошибки API формата {error:{code,message}} и SHALL показывать пользователю понятное сообщение.

Scenario: Ошибка с кодом и сообщением

  • WHEN сервер возвращает ошибку с code и message
  • THEN приложение показывает сообщение, при необходимости адаптированное под язык интерфейса

Requirement: Зум изображения жестами

Полноэкранный просмотр изображения SHALL поддерживать увеличение и уменьшение щипком (pinch), а при увеличенном изображении — панорамирование перетаскиванием.

Scenario: Щипок увеличивает изображение

  • WHEN пользователь разводит пальцы на изображении
  • THEN изображение увеличивается относительно вписанного вида

Scenario: Панорамирование при увеличении

  • WHEN изображение увеличено, и пользователь перетаскивает его пальцем
  • THEN видимая область изображения смещается, а границы изображения не отрываются от краёв области просмотра

Requirement: Двойной тап переключает вписанный вид и 100%

Двойной тап по изображению SHALL переключать вписанный вид и масштаб 100% натурального размера с якорем в точку нажатия.

Scenario: Вход в 100% из вписанного вида

  • WHEN изображение показано вписанным, и пользователь делает двойной тап
  • THEN изображение показывается в масштабе 100% натурального размера с центром в точке нажатия

Scenario: Возврат во вписанный вид

  • WHEN изображение увеличено, и пользователь делает двойной тап
  • THEN изображение возвращается во вписанный вид

Requirement: Предел зума по натуральному размеру

Зум изображения SHALL ограничиваться снизу вписанным видом, а сверху — 200% натурального размера изображения; при входе в зум SHALL догружаться оригинал изображения.

Scenario: Верхний предел

  • WHEN пользователь продолжает увеличивать изображение за 200% натурального размера
  • THEN масштаб останавливается на 200%, изображение не увеличивается дальше

Scenario: Оригинал при увеличении

  • WHEN пользователь входит в зум
  • THEN догружается оригинал изображения и подменяет превью по факту загрузки

Requirement: Навигация и сброс при зуме

Пока изображение увеличено, горизонтальный свайп SHALL NOT листать альбом, а жест SHALL отдаваться панорамированию; при переходе на другой элемент просмотра зум SHALL сбрасываться во вписанный вид.

Scenario: Свайп не листает увеличенное изображение

  • WHEN изображение увеличено, и пользователь свайпает по нему
  • THEN альбом не листается, а изображение панорамируется

Scenario: Сброс при смене фото

  • WHEN пользователь переходит на другой элемент и возвращается к увеличенному изображению
  • THEN изображение показывается во вписанном виде

Requirement: Индикатор загрузки оригинала

Пока оригинал изображения загружается после входа в зум, приложение SHALL показывать индикатор загрузки в правом верхнем углу области просмотра.

Scenario: Оригинал загружается

  • WHEN пользователь входит в зум, и оригинал ещё загружается
  • THEN в правом верхнем углу показывается индикатор загрузки

Scenario: Загрузка завершена

  • WHEN оригинал загружен или недоступен
  • THEN индикатор загрузки скрыт

Requirement: Проверка доступа «Все файлы» при запуске

Приложение SHALL при запуске, когда оно уже настроено и авторизовано, проверять наличие доступа «Все файлы» и при его отсутствии SHALL предлагать его включить, открывая системный экран настроек.

Scenario: Доступ не выдан

  • WHEN приложение запущено и доступ «Все файлы» не выдан
  • THEN показывается диалог с предложением включить доступ

Scenario: Включение доступа

  • WHEN пользователь подтверждает
  • THEN открывается системный экран выдачи доступа «Все файлы»

Scenario: Доступ уже выдан

  • WHEN доступ уже выдан
  • THEN диалог не показывается

Requirement: Возврат оригиналов при выходе из переноса

При переключении альбома из режима переноса в «копии» или «выключено» приложение SHALL возвращать оригиналы с сервера (когда пользователь выбирает возврат), а незавершённый возврат SHALL довосстанавливаться при следующей проверке (при запуске и при открытии альбома).

Scenario: Перенос → копии

  • WHEN пользователь переключает альбом из переноса в копии и подтверждает возврат оригиналов
  • THEN оригиналы скачиваются с сервера и заменяют превью на устройстве

Scenario: Довосстановление

  • WHEN альбом не в режиме переноса, но содержит превью с серверным фото
  • THEN при запуске или открытии альбома оригиналы довосстанавливаются

Scenario: Перенос → выключено

  • WHEN пользователь переключает перенос в выключено
  • THEN предлагается вернуть оригиналы или оставить превью

Requirement: Единая проверка соответствия режиму

При запуске и при открытии альбома приложение SHALL приводить локальное содержимое в соответствие режиму для всех сочетаний состояния ассета: в «переносе» разгружать уже загруженные оригиналы, а в «копиях»/«выключено» восстанавливать превью; отсутствующий локальный индекс SHALL восстанавливаться по метке происхождения.

Scenario: Копии с разгруженными файлами

  • WHEN альбом в режиме копий, а часть файлов разгружена (превью)
  • THEN проверка восстанавливает оригиналы

Scenario: Перенос с неразгруженными файлами

  • WHEN альбом в режиме переноса, файл есть на сервере, но оригинал ещё на телефоне
  • THEN проверка разгружает оригинал

Scenario: Потерянный индекс

  • WHEN у разгруженного медиа нет записи в локальном индексе
  • THEN связь и происхождение восстанавливаются по метке в файле

Scenario: Выключенный режим

  • WHEN альбом без синхронизации содержит превью
  • THEN оригиналы восстанавливаются, а сервер не затрагивается

Requirement: Отсутствие дублей и гонок при синхронизации

Проверка синхронизации SHALL выполняться последовательно (без одновременных проходов по одной галерее) и SHALL NOT ставить повторную загрузку, пока по тому же элементу уже есть задание в очереди. Метка происхождения в разгруженном файле SHALL хранить режим синхронизации, а не состояние элемента, чтобы восстановление не меняло режим галереи.

Scenario: Повторная проверка во время загрузки

  • WHEN проверка запускается снова, пока загрузка элемента ещё стоит в очереди
  • THEN повторная загрузка не ставится

Scenario: Метка происхождения хранит режим

  • WHEN разгруженный файл восстанавливается после переустановки
  • THEN режим галереи берётся из метки как режим (перенос/копии), а не как состояние элемента

Requirement: Подпись карточки альбома

Карточка альбома SHALL показывать в первой строке имя альбома, а для связанной пары — со стрелкой имя связанного серверного альбома, и только когда имена различаются. Вторая строка SHALL показывать значками расположение содержимого и число элементов: значок карты памяти для локального без синхронизации, значки карты памяти и облака для режима копий, значок облака для режима переноса; для серверного альбома — значок облака.

Scenario: Локальный без синхронизации

  • WHEN показан локальный альбом без синхронизации
  • THEN вторая строка показывает значок карты памяти и число элементов

Scenario: Режим копий

  • WHEN локальный альбом синхронизируется в режиме копий
  • THEN вторая строка показывает значки карты памяти и облака и число элементов

Scenario: Режим переноса

  • WHEN локальный альбом синхронизируется в режиме переноса
  • THEN вторая строка показывает значок облака и число элементов

Scenario: Разные имена связанной пары

  • WHEN имя локального альбома не совпадает с именем связанного серверного
  • THEN первая строка показывает «имя → имя серверного»

Scenario: Одинаковые имена

  • WHEN имена совпадают
  • THEN стрелка и имя серверного не показываются

Requirement: Панель атрибутов и действий альбома

Приложение SHALL открывать панель «Атрибуты и действия» по свайпу справа налево на экране любого альбома — серверного и локального. Панель SHALL повторять структуру web: разделы «Обложка», «Информация», «Навигация» и раздел «Действия».

Scenario: Открытие свайпом

  • WHEN пользователь свайпает справа налево в открытом альбоме
  • THEN открывается панель «Атрибуты и действия»

Scenario: Структура панели

  • WHEN панель открыта
  • THEN показаны разделы «Обложка», «Информация», «Навигация» и «Действия»

Scenario: Закрытие панели

  • WHEN пользователь закрывает панель (свайп в обратную сторону или касание вне панели)
  • THEN панель скрывается, сетка медиа снова доступна

Requirement: Источник атрибутов локального альбома

Для локального альбома приложение SHALL показывать ту же панель «Атрибуты и действия», что и для серверного, а метаданные SHALL брать локально (имя, число элементов, локальная обложка, режим синхронизации, связанный серверный альбом). Действия локального альбома SHALL применяться локально.

Scenario: Локальные метаданные

  • WHEN пользователь открывает панель локального альбома
  • THEN раздел «Информация» показывает локальные имя, число элементов и обложку

Scenario: Неактивная навигация без связи

  • WHEN локальный альбом не связан с серверным
  • THEN строки «Участники» и «Ссылки для просмотра» показаны, но неактивны

Scenario: Активная навигация при связи

  • WHEN локальный альбом связан с серверным
  • THEN строки «Участники» и «Ссылки для просмотра» активны и относятся к связанному серверному альбому

Requirement: Переименование и обложка локального альбома

Для локального альбома действие «Переименовать» SHALL менять отображаемое имя в приложении, не изменяя медиа или bucket на устройстве, а «Выбрать обложку»/«Сбросить» SHALL назначать или снимать обложку из медиа этого альбома. Имя и обложка SHALL храниться локально.

Scenario: Переименование

  • WHEN пользователь вводит новое имя локального альбома
  • THEN панель, заголовок и карточка в списке альбомов показывают новое имя

Scenario: Назначение и сброс обложки

  • WHEN пользователь выбирает медиа обложкой или сбрасывает её
  • THEN панель и карточка альбома отражают выбор

Requirement: Удаление локального альбома с телефона

Действие «Удалить» локального альбома SHALL после подтверждения удалять все фото и видео этого альбома с устройства, запрашивая при необходимости системное согласие.

Scenario: Подтверждение

  • WHEN пользователь выбирает «Удалить» локального альбома
  • THEN открывается диалог с предупреждением, что медиа будут удалены с телефона

Scenario: Удаление

  • WHEN пользователь подтверждает удаление
  • THEN медиа удаляются с устройства, а альбом исчезает из приложения

Requirement: Атрибуты альбома

Панель SHALL показывать обложку с выбором и сбросом, информацию (название, описание, число фото и участников) и переходы к участникам, настройкам и ссылкам для просмотра. Управление обложкой и раздел «Навигация» SHALL быть доступны только владельцу и администратору.

Scenario: Управление обложкой

  • WHEN владелец или администратор выбирает или сбрасывает обложку
  • THEN изменение сохраняется на сервере и отражается в списке и панели

Scenario: Наблюдатель

  • WHEN наблюдатель открывает панель
  • THEN управление обложкой не показывается, а строки «Настройки» и «Ссылки для просмотра» неактивны

Scenario: Переход к настройкам

  • WHEN владелец или администратор открывает настройки из раздела «Навигация»
  • THEN доступны правка названия и описания и управление ссылками для просмотра

Requirement: Действия с альбомом

Панель SHALL содержать действия «Переименовать» и «Удалить». Удаление SHALL подтверждаться диалогом, а удалённый альбом SHALL помещать свои фото в корзину.

Scenario: Переименование

  • WHEN владелец или администратор выбирает «Переименовать» и вводит новое название
  • THEN название сохраняется на сервере и отражается в списке и заголовке

Scenario: Удаление с подтверждением

  • WHEN владелец выбирает «Удалить» и подтверждает в диалоге
  • THEN альбом удаляется, а его фото попадают в корзину

Requirement: Лист атрибутов и действий фото

Полноэкранный просмотр SHALL открывать лист «Атрибуты и действия» по свайпу вверх как в серверном, так и в device-просмотре. Лист SHALL повторять структуру web: разделы «Информация», «Метки» и «Действия». При зуме изображения, панораме или активном управлении видео свайп вверх SHALL NOT открывать лист.

Scenario: Открытие листа

  • WHEN пользователь свайпает вверх во вписанном изображении
  • THEN открывается лист «Атрибуты и действия» для текущего элемента

Scenario: Зум или панорама

  • WHEN изображение увеличено или открыта панорама, и пользователь свайпает вверх
  • THEN лист не открывается, жест обрабатывается изображением

Scenario: Видео

  • WHEN открыт видеоэлемент, и пользователь взаимодействует с плеером
  • THEN свайп вверх не мешает управлению воспроизведением

Requirement: Атрибуты фото в листе

Раздел «Информация» SHALL показывать автора, размер файла, тип, разрешение, EXIF-атрибуты, дату съёмки, координаты и дату загрузки. Раздел «Метки» SHALL позволять добавлять и снимать метки с поиском по меткам пользователя и созданием новых.

Scenario: Информация

  • WHEN лист открыт
  • THEN раздел «Информация» показывает метаданные и EXIF текущего фото

Scenario: Метки

  • WHEN пользователь добавляет или снимает метку в разделе «Метки»
  • THEN изменение сразу отражается в просмотре без перезагрузки

Requirement: Настройки списка атрибутов

Раздел «Информация» SHALL давать доступ к настройкам со списком EXIF-атрибутов, где пользователь отмечает отображаемые атрибуты и задаёт их подписи, с действиями «отметить все» и «снять все». Настройки SHALL применяться ко всем фото и сохраняться в профиле пользователя.

Scenario: Открытие настроек

  • WHEN пользователь открывает настройки атрибутов
  • THEN показан список EXIF-атрибутов с галочками видимости и полями подписей

Scenario: Сохранение настроек

  • WHEN пользователь отмечает атрибуты, задаёт подписи и сохраняет
  • THEN настройки сохраняются в профиле и применяются в разделе «Информация»

Scenario: Сброс настроек

  • WHEN пользователь сбрасывает настройки
  • THEN применяется базовый набор атрибутов с исходными подписями

Requirement: Действия с фото в листе

Раздел «Действия» SHALL содержать «Скачать», «Переместить», «Копировать», «Установить как обложку альбома» (по правам) и «Удалить»; из сетки также «Открыть (просмотр)». Удаление SHALL подтверждаться диалогом. Переименование SHALL выполняться по тапу на имя файла.

Scenario: Состав действий

  • WHEN лист открыт
  • THEN показаны действия «Скачать», «Переместить», «Копировать», «Установить как обложку» и «Удалить» по правам

Scenario: Удаление фото

  • WHEN пользователь выбирает «Удалить» и подтверждает
  • THEN фото уходит в корзину, а просмотр переходит к соседнему элементу

Scenario: Переименование фото

  • WHEN автор, владелец или администратор меняет имя файла на непустое
  • THEN новое имя сохраняется и отражается в просмотре и сетке

Requirement: Источник атрибутов device-медиа

Для device-медиа приложение SHALL показывать атрибуты и действия сопоставленного серверного фото, когда сопоставление есть, и локальные атрибуты и действия (имя, размер, тип, разрешение, дата, путь) при его отсутствии.

Scenario: Сопоставлено серверному фото

  • WHEN device-медиа сопоставлено серверному фото
  • THEN лист показывает серверные атрибуты и серверные действия этого фото

Scenario: Не сопоставлено

  • WHEN сопоставления с серверным фото нет
  • THEN лист показывает локальные атрибуты и локальные действия элемента

Requirement: Живое обновление списка альбомов

Пока пользователь авторизован, приложение SHALL поддерживать персональный поток и применять события жизненного цикла альбома к локальному кэшу: создавать или заменять альбом по полученному объекту и удалять его по идентификатору, не выполняя дополнительный запрос списка.

Scenario: Альбом создан или изменён в другом месте

  • WHEN в персональный поток приходит событие создания или изменения доступного альбома
  • THEN альбом появляется в списке или заменяется без запроса списка

Scenario: Неизвестное событие

  • WHEN в персональный поток приходит событие, не относящееся к жизненному циклу альбома
  • THEN приложение не меняет локальный список

Scenario: Навигация между экранами

  • WHEN пользователь переходит с главного экрана на другой экран приложения
  • THEN подписка на персональный поток не пересоздаётся

Scenario: Выход из аккаунта

  • WHEN пользователь выходит из аккаунта
  • THEN подписка на персональный поток закрывается

Requirement: Догон списка при переподключении персонального потока

После восстановления персонального потока приложение SHALL приводить локальный список альбомов в соответствие с серверным снимком, чтобы отразить изменения, пропущенные за время разрыва соединения.

Scenario: Переподключение

  • WHEN персональный поток восстановился после разрыва
  • THEN приложение перезапрашивает список альбомов, удаляя из кэша альбомы, которых на сервере больше нет

Requirement: Потеря доступа к альбому

Приложение SHALL переставать отображать альбом, удалённый владельцем или ставший недоступным после исключения участника: альбом SHALL исчезать из локального кэша и списка, а экран открытого альбома SHALL возвращаться к списку.

Scenario: Альбом удалён во время просмотра

  • WHEN владелец удаляет альбом, пока участник просматривает экран этого альбома
  • THEN экран перестаёт показывать альбом и возвращается к списку

Scenario: Участник исключён

  • WHEN участника исключают из альбома
  • THEN альбом исчезает из его списка, а открытый экран возвращается к списку

Scenario: Экран альбома не открыт

  • WHEN альбом удалён, а его экран не открыт
  • THEN карточка альбома исчезает из списка

Scenario: Отсутствие альбома в кэше без сети

  • WHEN приложение открывает экран альбома, которого нет в кэше, и сеть недоступна
  • THEN экран не считается потерявшим доступ и не закрывается сам

Requirement: Выбор сортировки списка альбомов

Приложение SHALL предоставлять выбор порядка карточек в списке альбомов: «по времени изменения», «по названию» или «по числу фото», а также обратный порядок для выбранного варианта. Выбор SHALL сохраняться локально на устройстве и применяться при следующем запуске. Порядок SHALL применяться ко всему списку: карточки альбомов устройства и серверных альбомов упорядочиваются вместе.

Scenario: Выбор варианта

  • WHEN пользователь выбирает вариант сортировки
  • THEN карточки списка перестраиваются в соответствии с выбором

Scenario: Обратный порядок

  • WHEN пользователь включает обратный порядок
  • THEN выбранный вариант применяется в обратном направлении

Scenario: Альбомы устройства

  • WHEN выбрана любая сортировка
  • THEN карточки альбомов устройства упорядочиваются вместе с серверными, а для варианта «по времени изменения» используется дата самого свежего элемента альбома устройства

Scenario: Сортировка по умолчанию

  • WHEN пользователь ещё не выбирал сортировку
  • THEN карточки упорядочены по времени изменения, самые свежие сверху, обратный порядок выключен

Scenario: Сохранение выбора

  • WHEN пользователь перезапускает приложение
  • THEN список открывается с сохранёнными вариантом и направлением