Files
ds-galo/openspec/specs/ui-workspace/spec.md
T
iu 50b9983be4 feat(web): сохранять размер миниатюр при скрытых боковых панелях
В скрытом режиме панели больше не растягивают плитки: сетка пересчитывает
число колонок так, чтобы размер миниатюры остался прежним, а в строке
помещалось больше фото. Каркас публикует ширину, которую занимают панели в
текущей раскладке (рейл на широких экранах, панель на сверхшироких), сетка
использует её для пересчёта, а навигация курсора стрелками учитывает
реальное число колонок.
2026-10-20 21:38:02 +03:00

55 KiB
Raw Blame History

ui-workspace Specification

Purpose

Рабочий стол веб-приложения: постоянный каркас с рейлом альбомов, контекстной панелью, режимом просмотра фото и адаптивным поведением, обеспечивающий цельный «lightroom»-вид.

Requirements

Requirement: Рабочий стол приложения

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

Scenario: Внутренний экран

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

Scenario: Публичный экран

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

Requirement: Рейл альбомов

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

Scenario: Активный альбом

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

Requirement: Создание альбома

Создание альбома SHALL выполняться через иконочную кнопку с подсказкой, открывающую модальное окно ввода названия, вместо инлайн-формы.

Scenario: Создание через модалку

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

Scenario: Пустое название

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

Requirement: Контекстная панель альбома

Правая панель SHALL показывать превью обложки, название, счётчики фото и участников, управление обложкой и переходы к участникам, настройкам и ссылкам. Элементы управления обложкой SHALL быть доступны только owner и admin.

Scenario: Владелец альбома

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

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

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

Requirement: Режим просмотра фотографии

Просмотр фото SHALL быть отдельным маршрутом внутри каркаса с крупным изображением, лентой миниатюр снизу и панелью метаданных и комментариев. Тот же режим SHALL использоваться на публичных share-страницах. Миниатюры нижней ленты SHALL давать обратную связь при наведении указателя: изображение SHALL плавно увеличиваться внутри плитки; тот же эффект SHALL применяться при фокусе с клавиатуры.

Scenario: Открытие фото

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

Scenario: Навигация в просмотре

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

Scenario: Публичный просмотр

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

Scenario: Наведение на миниатюру

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

Requirement: Плотность сетки

Сетка SHALL давать пользователю управлять размером миниатюр: сдвиг регулятора вправо SHALL увеличивать миниатюры, влево — уменьшать. Регулятор SHALL сопровождаться кнопками шага в сторону уменьшения и увеличения. Выбранный размер SHALL сохраняться между сессиями и SHALL быть общим для обзора альбомов и сетки фото альбома. Клавиши + и - SHALL менять размер миниатюр на шаг так же, как кнопки регулятора; при вводе текста и в открытых диалогах либо меню эти клавиши SHALL сохранять обычное действие.

Scenario: Изменение размера

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

Scenario: Направление регулятора

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

Scenario: Кнопки шага

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

Scenario: Клавиши размера

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

Scenario: Клавиши в поле ввода

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

Scenario: Единый размер в обоих местах

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

Requirement: Загрузка фотографий из рабочего стола

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

Scenario: Перетаскивание

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

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

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

Scenario: Загрузка видео

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

Requirement: Темы и графитовый хром

Тёмная тема SHALL использовать графитовый хром Lightroom и SHALL применяться по умолчанию; нейтральная тема SHALL быть тёплым графитом; остальные темы SHALL оставаться доступными, а скроллбары SHALL быть стилизованы в цвет темы.

Scenario: Первый вход

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

Scenario: Смена темы

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

Scenario: Нейтральная тема

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

Requirement: Адаптивность рабочего стола

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

Scenario: Узкий экран

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

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

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

Requirement: Доступность рабочего стола

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

Scenario: Клавиатурная навигация

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

Requirement: Изменение ширины панелей

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

Scenario: Перетаскивание разделителя

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

Scenario: Сохранение ширины

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

Requirement: Скрытие боковых панелей

В режиме просмотра альбома SHALL быть доступна кнопка скрытия левой и правой боковых панелей в верхней панели сетки рядом с регулятором размера миниатюр и хоткей Tab. В скрытом режиме панели SHALL не занимать место в раскладке, содержимое альбома SHALL занимать всю ширину, а панели SHALL показываться при наведении указателя на левую или правую кромку окна и скрываться после ухода указателя. Хоткей SHALL не срабатывать при вводе текста в поля и при открытых модальных диалогах или меню. Размер миниатюр в скрытом режиме SHALL сохраняться: вместо растянутых плиток сетка SHALL показывать больше фото в строке.

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

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

Scenario: Размер миниатюр при скрытых панелях

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

Scenario: Переключение хоткеем

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

Scenario: Появление у кромки

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

Scenario: Скрытие после ухода указателя

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

Scenario: Поля ввода и диалоги

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

Requirement: Сворачиваемые разделы панели

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

Scenario: Сворачивание раздела

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

Scenario: Метаданные фото

  • WHEN открыт просмотр фото
  • THEN раздел «Информация» показывает размер, тип, разрешение, дату съёмки, координаты и извлечённые EXIF-атрибуты

Requirement: Полноэкранный просмотр фотографии

В режиме просмотра SHALL быть доступен переход в полноэкранный режим кнопкой и хоткеем f. В полноэкранном режиме верхняя и нижняя панели SHALL скрываться и показываться у соответствующей кромки экрана.

Scenario: Вход в полный экран

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

Scenario: Панель по кромке

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

Scenario: Выход из полного экрана

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

Scenario: Полноэкранный режим приложения

  • WHEN включён полноэкранный режим приложения, и пользователь нажимает f
  • THEN открывается полноэкранный просмотр фото (вложенно), а полноэкранный режим приложения не выключается

Requirement: Зум в просмотре

Просмотр SHALL поддерживать зум колесом мыши без прокрутки, с привязкой к указателю и верхним пределом 200% размеров фото. Space SHALL возвращать изображение из любого зума во вписанный вид, а из вписанного — в 100%. При зуме SHALL догружаться оригинал изображения. Стрелки соседних фото SHALL появляться у левой/правой кромки и прятаться в зуме. Зум SHALL работать и в полноэкранном режиме.

Scenario: Зум колесом к указателю

  • WHEN пользователь вращает колесо мыши над фото
  • THEN масштаб меняется относительно курсора, страница не прокручивается, предел — 200%

Scenario: Пробел

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

Scenario: Оригинал в зуме

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

Scenario: Стрелки соседних фото

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

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

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

Requirement: Удаление фото из просмотра

Автор фото, владелец и админ альбома SHALL иметь возможность удалить текущее фото из режима просмотра; удаление SHALL подтверждаться диалогом.

Scenario: Подтверждение удаления

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

Scenario: Лента после удаления

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

Requirement: Возврат к обзору

Из альбома и из режима просмотра SHALL быть доступен возврат к обзору альбомов.

Scenario: Возврат из альбома

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

Scenario: Возврат из просмотра

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

Requirement: Настройки списка атрибутов информации

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

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

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

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 открывать режим просмотра фото. На сенсорных экранах одиночное касание по фото SHALL открывать режим просмотра этого фото и не SHALL выделять его; выделение на сенсорных экранах SHALL выполняться долгим нажатием.

Scenario: Одиночный выбор

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

Scenario: Двойной выбор

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

Scenario: Касание на сенсорном экране

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

Scenario: Смена альбома

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

Requirement: Мультивыбор фото в сетке

В режиме альбома пользователь SHALL выбирать несколько фото: обычный клик — одно фото, Ctrl/Cmd-клик — добавить или убрать, Shift-клик — диапазон. Выбранные фото SHALL быть отмечены.

Scenario: Мультивыбор

  • WHEN пользователь кликает по фото с зажатым Ctrl/Cmd или Shift
  • THEN соответствующие фото отмечены, а панель показывает количество выбранных

Requirement: Действия с выбранными фото

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

Scenario: Действия

  • WHEN выбрано одно или несколько фото
  • THEN панель показывает раздел «Действия» с пунктами «Открыть (просмотр)», «Переместить», «Копировать» и «Удалить»

Requirement: Перетаскивание выбранных фото на альбом

Выбранные фото SHALL перетаскиваться на альбом в рейле; при отпускании SHALL открываться диалог выбора переноса или копирования с указанием целевого альбома. Во время такого перетаскивания зона загрузки файлов SHALL не показываться.

Scenario: Перетаскивание на альбом

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

Requirement: Корзина в списке альбомов

Рейл альбомов SHALL содержать вход в корзину последним элементом списка (с иконкой корзины). Экран обзора альбомов SHALL не показывать пустую правую панель.

Scenario: Вход в корзину

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

Scenario: Обзор без панели

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

Requirement: Действия в режиме просмотра

В режиме просмотра правая панель 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 альбом удаляется, а его фото попадают в корзину

Requirement: Счётчики в рейле

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

Scenario: Счётчики

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

Requirement: Метки в панели фото

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

Scenario: Раздел «Метки»

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

Scenario: Обновление без перезагрузки

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

Requirement: Компактный верхний хром

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

Scenario: Компактные верхние панели

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

Scenario: Прозрачная панель просмотра

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

Requirement: Курсор в сетке фото

Сетка SHALL хранить курсор — текущую ячейку, отдельную от выделения. Перемещение курсора SHALL не менять выделение и не обновлять правую панель. Курсор SHALL отображаться контуром, отличимым от рамки выделения, SHALL сохраняться при снятии выделения и SHALL устанавливаться на фото при клике по нему мышью.

Scenario: Синхронизация с мышью

  • WHEN пользователь кликает по фото в сетке
  • THEN фото выделено, а курсор установлен на нём

Scenario: Перемещение не меняет выделение

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

Scenario: Курсор переживает снятие выделения

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

Scenario: Отображение курсора

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

Requirement: Клавиши сетки фото

При фокусе в сетке клавиши SHALL управлять курсором и выделением: ←/→ — на соседнее фото с переходом на соседнюю строку, ↑/↓ — на строку (density.cols) с упором в границы. Space SHALL переключать выделение ячейки под курсором, Shift+стрелки — двигать курсор и расширять выделение от якоря, Enter — открывать просмотр, Esc — снимать выделение. Вне фокуса сетки клавиши SHALL не действовать.

Scenario: Горизонтальное перемещение

  • WHEN курсор не в конце строки и нажато →
  • THEN курсор переходит на следующее фото

Scenario: Перенос на соседнюю строку

  • WHEN курсор в конце строки и нажато →
  • THEN курсор переходит на первое фото следующей строки

Scenario: Вертикальные границы

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

Scenario: Переключение выделения

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

Scenario: Расширение выделения

  • WHEN нажато Shift вместе со стрелкой
  • THEN курсор двигается, а выделение расширяется от якоря до курсора

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

  • WHEN нажато Enter
  • THEN открывается просмотр фото под курсором

Scenario: Снятие выделения клавишей

  • WHEN нажато Esc
  • THEN выделение снимается, а курсор остаётся

Scenario: Прокрутка к курсору

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

Scenario: Догрузка при выходе за загруженные фото

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

Scenario: Вне фокуса сетки

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

Requirement: Снятие выделения кликом по пустому месту

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

Scenario: Клик по пустому месту

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

Scenario: Мультивыделение

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

Scenario: Клик по фото

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

Scenario: Клик по органам управления

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

Scenario: Фокус остаётся в сетке

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

Requirement: Возврат фокуса из просмотра

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

Scenario: Возврат из просмотра

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

Scenario: Последнее просмотренное фото

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

Scenario: Фото вне первой страницы

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

Scenario: Возврат в другой альбом

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

Scenario: Клавиатура после возврата

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

Requirement: Просмотр 360-панорамы

Фото с тегом pano360 SHALL открываться в режиме сферического обзора (equirect) вместо плоского изображения. Перетаскивание SHALL менять направление взгляда и SHALL перемещать сцену вслед за указателем по обеим осям согласованно, колесо — угол обзора, Space — сбрасывать вид. Остальные фото SHALL просматриваться как прежде. При недоступности WebGL или сбое загрузки/декодирования SHALL показываться плоское изображение. На публичных share-страницах панорамный режим SHALL не активироваться.

Scenario: Обзор панорамы

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

Scenario: Направление перетаскивания

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

Scenario: Обычное фото

  • WHEN пользователь открывает фото без тега pano360
  • THEN показывается обычное плоское изображение

Scenario: Управление обзором

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

Scenario: Навигация между фото

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

Scenario: Нет WebGL

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

Scenario: Публичная share-страница

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

Requirement: Резкость миниатюр

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

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 доступны скачивание оригинала, перенос, копирование и удаление по правам

Requirement: Плитка видео в сетке

Плитка видео в сетке SHALL показывать постер, признак видео и длительность; открытие плитки SHALL открывать режим просмотра.

Scenario: Постер и признак

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

Scenario: Постер не готов

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

Scenario: Открытие из сетки

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

Requirement: Очистка корзины в интерфейсе

Экран корзины SHALL содержать действие «Очистить корзину», доступное, когда в корзине есть элементы. Действие SHALL открывать подтверждение и после подтверждения очищать корзину, а список и счётчик корзины в рейле SHALL отражать результат.

Scenario: Наличие действия

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

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

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

Scenario: Обновление после очистки

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

Requirement: Синхронизация счётчика корзины

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

Scenario: Помещение фото в корзину

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

Scenario: Восстановление из корзины

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

Scenario: Окончательное удаление

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

Scenario: Удаление альбома

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