13 KiB
Spec Delta
Purpose
Android-клиент для self-hosted galo: настройка подключения к серверу, авторизация, просмотр альбомов и медиа, а также фоновая загрузка фотографий и видео с телефона с офлайн-кэшем.
ADDED 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, а при отсутствии сети — из локального кэша.
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 приложение показывает сообщение, при необходимости адаптированное под язык интерфейса