Спеки+беклог: закрытие батча UI-задач (favicon, cancelled, значок типа, ellipsis, oob-панель)
Реализованное поведение перенесено в openspec/specs: - web-ui: cancelled скрыт по умолчанию наравне с deleted; значок типа в карточке; - review: панель действий обновляется oob-фрагментом при свопе источника. Пять закрытых задач удалены из docs/backlog + индекса. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -40,12 +40,9 @@ Tududi (проект `jellybit`) больше **не** держит беклог
|
||||
|
||||
## Низкий
|
||||
|
||||
- [Значок типа (фильм/сериал) в списке загрузок](spisok-znachok-tipa.md) — показать 🎬/📺 в строке списка; media type сейчас не доходит до листинга (нужно протащить в запрос и card.html)
|
||||
- [Ревью уведомлений в Telegram (аудит текстов и формата)](telegram-revyu-uvedomleniy.md) — зонтичный проход по всем текстам бота: полнота карточек, единый язык, оформление; порождает под-задачи
|
||||
- [Download id в Telegram моноширинным (code) для tap-to-copy](telegram-download-id-code.md) — слать id как `code`; требует включить parse mode (HTML) в send() + escape всех текстов
|
||||
- [Кнопка «Обновить имя»: полный формат ярлыка (Название (режиссёр, год), сезон)](knopka-obnovit-imya-polnyj-format.md) — Перелив имени даёт усечённое «Title (Year)» вместо полного формата add-шага (режиссёр+сезон); нужный `render` уже есть
|
||||
- [Скрывать отменённые (cancelled) в общем списке наравне с удалёнными](skryvat-otmenennye-v-spiske.md) — cancelled шумит в ленте; тумблер «показать удалённые» должен раскрывать и cancelled, и deleted
|
||||
- [Панель действий ревью вне htmx-свопа блока источника](panel-review-vne-swap.md) — При выборе источника одним кликом обновляется только блок источника (#source-block)…
|
||||
- [Мгновенные обновления через SSE](sse-obnovleniya.md) — Живые обновления прогресса сейчас на htmx-поллинге (фаза 2 веб-UI) — просто и работает…
|
||||
- [Шум ERROR фоновых циклов при недоступной зависимости](oshibki-klassifikaciya-i-konvencii-logirovaniya.md) — Остаток задачи логирования: ext.* ERROR-шторм при недоступном qBittorrent + эскалация устойчивого сбоя тика _(ревью Fable)_
|
||||
- [Версии/качество одного тайтла (репаки, апгрейд 1080p → 2160p)](versii-kachestvo-repaki.md) — По калибровке болей (2026-07-02) — не боль, из приоритета выпало
|
||||
@@ -53,7 +50,6 @@ Tududi (проект `jellybit`) больше **не** держит беклог
|
||||
- [Выбор из нескольких находок метабазы в Telegram](telegram-vybor-nahodok.md) — Когда распознавание даёт несколько подходящих кандидатов в метабазе, предлагать их в…
|
||||
- [Улучшения UI: показывать матч с записью метабазы в Telegram](telegram-match-metabazy.md) — Название/год/провайдер+id в боте уже выводятся; осталась кликабельная ссылка на запись
|
||||
- [Добавление торрентов файлом/ссылкой — «единое окно» (остаток: URL)](dobavlenie-edinoe-okno.md) — magnet и .torrent-файл приняты; остался фетч .torrent по URL (нужен SSRF-гард)
|
||||
- [Форма приёма: длинное имя .torrent-файла ломает верстку add-row](torrent-fayl-dlinnoe-imya.md) — длинное имя файла распирает лейбл файл-пикера, поле source сжимается — нужен ellipsis
|
||||
- [Раздачи-копии диска (DVD/BluRay: VIDEO_TS/BDMV)](disk-kopii-video-ts-bdmv.md) — Иногда для очень редких фильмов скачивается не один видеофайл, а полная копия диска…
|
||||
- [Проверка свободного места перед copy-fallback](svobodnoe-mesto-copy-fallback.md) — Когда хардлинк невозможен (EXDEV/ENOTSUP/…), layout копирует файл, дублируя место на диске
|
||||
- [Кэш метабаз (и опционально LLM)](kesh-metabaz.md) — Повторные и ретраящиеся прогоны распознавания бьют TMDB/TVDB/TVMaze одним и тем же…
|
||||
@@ -61,7 +57,6 @@ Tududi (проект `jellybit`) больше **не** держит беклог
|
||||
- [[идея] Завершение загрузки через webhook](webhook-zavershenie-zagruzki.md) — ИДЕЯ (решим по опыту эксплуатации)
|
||||
- [Авторизация веб-UI (на будущее)](avtorizaciya-web-ui.md) — Решено для v1: без авторизации в доверенной LAN, опц
|
||||
- [Современный Web-UI как PWA](web-ui-pwa.md) — Переделать веб-интерфейс в современное PWA-приложение (устанавливаемое, отзывчивое…
|
||||
- [Сделать фавиконку для jellybit](favicon.md) — мелкая косметика: иконка вкладки/PWA для веб-UI
|
||||
- [Идентичность инфохэшей: split v1/v2 одного торрента + крафт-магнет отравляет владение (F4, F5)](review-f4-f5-infohash-identity.md) — split v1/v2 идентичность и крафт-магнет отравляют владение инфохэшами _(ревью 2026-07-08)_
|
||||
- [Приём/UI: мелкие фиксы границ и парсинга (F7, F8, F9, F10, N2)](review-f7-f10-ingest-ui-fixes.md) — мелочи приёма/UI: oversized→500, гонки дедупа, парсинг magnet, cap контекста, руны _(ревью 2026-07-08)_
|
||||
- [Жизненный цикл: мелкие находки (MINOR-8, MINOR-9, NIT-11, NIT-12)](review-lifecycle-minor.md) — claim-token распознавания, I/O под глобальным mutex, мелкие lookup/retry _(ревью 2026-07-08)_
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Сделать фавиконку для jellybit
|
||||
|
||||
**Приоритет:** низкий
|
||||
|
||||
_Описание не заполнено._
|
||||
@@ -1,7 +0,0 @@
|
||||
# Панель действий ревью вне htmx-свопа блока источника
|
||||
|
||||
**Приоритет:** низкий
|
||||
|
||||
При выборе источника одним кликом обновляется только блок источника (#source-block) htmx-свопом, а нижняя панель действий (кнопка «Применить», завязанная на HasLinks) — вне блока и не обновляется до полной перезагрузки. Практически не мешает (хардлинки только по явному «Применить», Apply без плана вернёт ошибку), но в краевом случае (источник с пустым предпросмотром из-за коллизии) кнопка может остаться/пропасть не синхронно. Решение намечено в дизайне review-unified-source-block: обновлять панель hx-swap-oob из того же партиала.
|
||||
|
||||
Связано: openspec/specs/review, openspec/specs/web-ui, пакет httpapi.
|
||||
@@ -1,35 +0,0 @@
|
||||
# Скрывать отменённые (cancelled) в общем списке наравне с удалёнными
|
||||
|
||||
**Приоритет:** низкий · **Теги:** web-ui
|
||||
|
||||
Отменённые загрузки (`cancelled`) должны по умолчанию скрываться в общем списке
|
||||
так же, как удалённые (`deleted`), а тумблер «Показать всё, включая удалённые»
|
||||
(`web/templates/index.html:52`) должен показывать **и те, и те**. Сейчас под
|
||||
группой `all` скрыт только `deleted`, а `cancelled` всегда виден и шумит в ленте
|
||||
— тем более что новый стоп-кран «Закрыть» будет плодить `cancelled`-записи.
|
||||
|
||||
Где править:
|
||||
- `internal/store/list.go:62-66` — ветка `else if !f.IncludeDeleted` под группой
|
||||
`all` скрывает только `StateDeleted` (`state <> ?`). Расширить до
|
||||
`state NOT IN (deleted, cancelled)`.
|
||||
- Осмыслить семантику флага `ListFilter.IncludeDeleted` (`list.go:45`): теперь он
|
||||
«показывать скрытые терминальные» (deleted **и** cancelled). Либо переименовать
|
||||
(`IncludeHidden`/`IncludeTerminal`), либо оставить имя и уточнить комментарий.
|
||||
- Метка тумблера (`index.html:52`) и текст — при желании подправить («…включая
|
||||
отменённые и удалённые»); `ShowAll`/`all=1` уже управляет показом.
|
||||
- Комментарии-инварианты про «под all видны» в `internal/store/list.go:22-26` и
|
||||
`statesInGroup` (cancelled/reverted/deleted не имеют чипа) — привести в
|
||||
соответствие.
|
||||
|
||||
Замечания:
|
||||
- `cancelled` своей группы-чипа не имеет (`statesInGroup`, `list.go:29-40`) — под
|
||||
группами `review/active/done/problem` он и так не появляется, правка нужна
|
||||
только в ветке `all`.
|
||||
- `reverted` пользователь не упоминал — по умолчанию оставляем видимым; при
|
||||
желании обсудить симметрию отдельно.
|
||||
- Обновить тест `TestListDownloadsPageFilterAndDeleted`
|
||||
(`internal/store/list_test.go`) — добавить `cancelled` в скрытые по умолчанию и
|
||||
видимые под `IncludeDeleted`.
|
||||
|
||||
Связано: `openspec/specs/web-ui`, пакеты `internal/store`, `internal/httpapi`,
|
||||
конвенция [web-ui](../conventions/web-ui.md).
|
||||
@@ -1,25 +0,0 @@
|
||||
# Значок типа (фильм/сериал) в списке загрузок
|
||||
|
||||
**Приоритет:** низкий
|
||||
|
||||
В строке списка загрузок показывать значок типа контента — 🎬 фильм / 📺 сериал,
|
||||
как уже делается на экране деталей/ревью и в карточке бота
|
||||
(`internal/tgbot/render.go:231-233`). Сейчас партиал строки списка
|
||||
`web/templates/partials/card.html` (define `"card"`) типа не показывает — только
|
||||
заголовок, ID, дату/размер, статус-бейдж и прогресс.
|
||||
|
||||
Что учесть:
|
||||
|
||||
- Media type в модели строки списка отсутствует: `downloadView`
|
||||
(`internal/httpapi/httpapi.go:200`) и `store.Download`
|
||||
(`internal/store/download.go:175`) его не несут. В detail/review он берётся из
|
||||
`rd.Plan.Type` (`internal/httpapi/download.go:139`). Каноничный тип —
|
||||
`recognize.MediaType` (`movie`/`series`).
|
||||
- Нужно протащить `MediaType`/`IsSeries` в листинг: расширить запрос
|
||||
`ListDownloadsPage` (сейчас через LEFT JOIN тянет только `rec_title`) и сборку
|
||||
`buildCardView`, затем добавить значок в `card.html`.
|
||||
- Тип может быть ещё не распознан (загрузка на раннем шаге) — предусмотреть
|
||||
отсутствие значка/нейтральный плейсхолдер.
|
||||
|
||||
Связано: `internal/httpapi`, `web/templates/partials/card.html`,
|
||||
[docs/specs/architecture.md](../specs/architecture.md).
|
||||
@@ -1,30 +0,0 @@
|
||||
# Форма приёма: длинное имя .torrent-файла ломает верстку add-row
|
||||
|
||||
**Приоритет:** низкий · **Теги:** web-ui, ingest
|
||||
|
||||
При выборе `.torrent`-файла с длинным именем (типичный релиз с трекера, напр.
|
||||
«Бухта вдов Widow's Bay Сезон 1 Серии 1-10 из 10 (Хиро Мурай) [2026, США, …,
|
||||
WEB-DL 1080p] 7 x MVO (HDr [rutracker-6869937].torrent») кнопка-лейбл файл-пикера
|
||||
раздувается на всю ширину и ломает раскладку строки добавления: поле `source`
|
||||
сжимается/прячется, «Добавить» уезжает.
|
||||
|
||||
Причина: onchange пишет полное `files[0].name` в `[data-file-label]`
|
||||
(`web/templates/index.html:26-30`), а у `.btn-file` нет ограничения ширины
|
||||
(`web/static/css/jellybit.css:194` — только цвет). В `.add-row`
|
||||
(`display:flex`, `.input{flex:1}`) лейбл распирается по контенту и съедает строку.
|
||||
|
||||
Фикс (косметика, без домена):
|
||||
- CSS `.btn-file`: `max-width` + `overflow:hidden; text-overflow:ellipsis;
|
||||
white-space:nowrap` — имя усекается многоточием, а не растягивает строку.
|
||||
- Опц.: показывать базовое имя без `.torrent` и класть полное в `title`
|
||||
(тултип). Полное имя всё равно уходит на сабмит через сам file-input
|
||||
(`header.Filename`), правка чисто визуальная.
|
||||
|
||||
Смежное (проверить заодно, не обязательно тем же фиксом): на приёме `source_ref`
|
||||
выводится из имени раздачи/файла и может быть очень длинным. В списке/карточке он
|
||||
усечён (`shorten(oneLine(d.SourceRef), 120)` — `internal/httpapi/download.go:67`),
|
||||
так что отображение ок; убедиться лишь, что нет жёсткого лимита колонки в БД,
|
||||
роняющего сам приём длинного имени.
|
||||
|
||||
Связано: `openspec/specs/ingest`, `openspec/specs/web-ui`, пакет `httpapi`,
|
||||
конвенция [web-ui](../conventions/web-ui.md).
|
||||
@@ -117,7 +117,11 @@ qBittorrent, но и **готов к раскладке** — раздача в
|
||||
выполняться через раундтрип на сервер (форма/htmx), без клиентского пересчёта
|
||||
доменного состояния; при этом инфо-часть и предпросмотр раскладки SHALL
|
||||
немедленно обновляться под выбранный источник (частичный своп блока, без полной
|
||||
перезагрузки страницы). Экран SHALL позволять операции над этим списком:
|
||||
перезагрузки страницы). Тем же ответом свопа SHALL синхронно обновляться панель
|
||||
действий — в частности доступность команды **Применить**, зависящая от наличия
|
||||
предпросмотра раскладки, — через out-of-band-фрагмент, чтобы кнопка не
|
||||
рассинхронизировалась с блоком источника (например при пустом предпросмотре
|
||||
из-за коллизии путей). Экран SHALL позволять операции над этим списком:
|
||||
выбрать кандидата базы, переключиться на другого кандидата и снять матч с базы
|
||||
обратно на нейронку («без базы»). Список источников SHALL показываться только
|
||||
при наличии плана распознавания.
|
||||
@@ -139,6 +143,8 @@ qBittorrent, но и **готов к раскладке** — раздача в
|
||||
отдельного нажатия кнопки «выбрать»
|
||||
- **AND** инфо-часть и предпросмотр раскладки сразу обновляются под выбранного
|
||||
кандидата без полной перезагрузки страницы
|
||||
- **AND** панель действий обновляется тем же ответом (out-of-band): доступность
|
||||
«Применить» синхронна наличию предпросмотра раскладки
|
||||
|
||||
#### Scenario: Снятие матча в пользу нейронки
|
||||
|
||||
|
||||
@@ -93,10 +93,12 @@ self-hosted шрифтов, единая дизайн-система (`jellybit.
|
||||
и страницу просмотра одной загрузки (`/download/{id}`) с распознаванием,
|
||||
файлами→раскладкой, историей, блоком информации о торренте и — для сидирующих
|
||||
задач — секцией живой статистики раздачи. Карточки активных (downloading)
|
||||
загрузок в списке SHALL содержать индикатор прогресса. Фильтр, поиск и номер
|
||||
загрузок в списке SHALL содержать индикатор прогресса. Карточка загрузки с
|
||||
распознанным типом SHALL нести значок типа (фильм/сериал). Фильтр, поиск и номер
|
||||
страницы SHALL передаваться GET-параметрами запроса (например `f`, `q`, `page`)
|
||||
и SHALL работать без клиентского JavaScript. Состояние `deleted` SHALL быть
|
||||
скрыто в списке по умолчанию (с переключателем «показать всё»). Механика живого
|
||||
и SHALL работать без клиентского JavaScript. Терминальные состояния `deleted` и
|
||||
`cancelled` SHALL быть скрыты в списке по умолчанию (переключатель «показать
|
||||
всё» раскрывает оба). Механика живого
|
||||
обновления прогресса и наполнение секции раздачи определяются capability
|
||||
`live-status`.
|
||||
|
||||
@@ -112,12 +114,18 @@ self-hosted шрифтов, единая дизайн-система (`jellybit.
|
||||
- **THEN** её карточка содержит индикатор прогресса (прогресс-бар со скоростью
|
||||
и ETA)
|
||||
|
||||
#### Scenario: Удалённые скрыты по умолчанию
|
||||
#### Scenario: Отменённые и удалённые скрыты по умолчанию
|
||||
|
||||
- **WHEN** в списке есть загрузки в состоянии `deleted` и фильтр «показать
|
||||
всё» не включён
|
||||
- **WHEN** в списке есть загрузки в состоянии `deleted` или `cancelled` и фильтр
|
||||
«показать всё» не включён
|
||||
- **THEN** они не отображаются, но доступны при включённом переключателе
|
||||
|
||||
#### Scenario: Значок типа в карточке списка
|
||||
|
||||
- **WHEN** загрузка в списке имеет распознанный тип (`movie` или `series`)
|
||||
- **THEN** её карточка показывает значок типа (🎬 фильм / 📺 сериал); при
|
||||
отсутствии распознанного типа значок не показывается
|
||||
|
||||
#### Scenario: Пагинация списка
|
||||
|
||||
- **WHEN** загрузок под текущим фильтром больше, чем помещается на одну
|
||||
|
||||
Reference in New Issue
Block a user