myYouTube/analytics/2026-09-18-feed-card-cleanup.md

61 lines
11 KiB
Markdown
Raw Permalink Normal View History

# Чистка карточек видео: убрать «Смотреть» и «Скачать» из ленты, оставить действия на /local
## Задача
Убрать из карточек видео (`VideoCard`) кнопки «Смотреть» и «Скачать» на всех ленточных маршрутах: `/`, `/category/:id`, `/uncategorized`, `/search`, а также на странице видео канала `/channels/:id/videos`. Карточка остаётся кликабельной целиком через превью и заголовок (это ссылки), скачивание остаётся доступным со страницы видео. Исключение — `/local` («На сервере»): там кнопка скачивания остаётся, т.к. показывает статус загрузки и участвует в управлении копиями. Кнопка «Смотреть» не нужна нигде в карточках (включая /local) — превью/заголовок и так ведут на страницу видео.
## Контекст
- `VideoCard` (frontend/src/components/VideoCard.tsx) сейчас рендерит: thumbnail-Link (с `aria-label="Смотреть: …"`), title-Link, `.video-meta`, и блок `.video-actions` с двумя элементами: «Смотреть» (`Link className="button-link"` + `Icon name="play"`) и `<DownloadButton video={video} />`.
- `VideoCard` используется ровно в двух местах: `Feed.tsx` (строка 113 — все режимы ленты, включая `/local` и `/search`) и `ChannelVideos.tsx` (строка 21). Компактные карточки в режиме «Каналы» (`CompactVideoCard`) уже без кнопок и не затрагиваются.
- `DownloadButton` остаётся нужным в трёх местах: карточки `/local`, страница видео `VideoPage` (`showDelete` — там живёт «Удалить копию»), и он не меняется. На карточке `/local` сегодня он рендерится **без** `showDelete` (кнопки «Удалить копию» в карточке нет и не было — она только на `VideoPage`); на `/local` показываются статусы («Скачать» / «Скачивается N%» / «В очереди…» / «На сервере» / «Повторить» / «Загрузить снова»). Поведение на `/local` менять не требуется — сохранить как есть.
- Кнопка «Смотреть» — единственное использование класса `.button-link` и иконки `Icon` в `VideoCard`. После удаления кнопки класс `.button-link` становится мёртвым во всём CSS (проверено rg: только App.css и VideoCard.tsx), а импорт `Icon` в `VideoCard` — неиспользуемым (`noUnusedLocals` в tsconfig → ошибка сборки, если не убрать).
- В `DownloadButton` кэш-инвалидация на завершении/удалении (`['feed']`, `['video', id]`) не зависит от места рендера — на `/local` и `VideoPage` она продолжит работать как раньше.
## Затронутые подсистемы и файлы
Только frontend. Backend, тесты, миграции — не трогаем.
- `frontend/src/components/VideoCard.tsx` — добавить опциональный проп `showActions` (default `false`); блок `.video-actions` рендерить только при `showActions` и только с `<DownloadButton>`; удалить «Смотреть» и импорт `Icon`; `DownloadButton` импорт оставить; `aria-label` на thumbnail-Link сохранить.
- `frontend/src/pages/Feed.tsx` — передать `showActions={isLocal}` в `VideoCard` (строка 113). `isLocal` уже вычислен (строка 19).
- `frontend/src/pages/ChannelVideos.tsx` — без изменений (проп по умолчанию `false`).
- `frontend/src/App.css` — чистка мёртвых правил `.button-link`:
- строка 58 (transition-список) — убрать `.button-link`;
- строка 59 (общий стиль кнопок) — убрать `.button-link`;
- строки 62–63 (`.button-secondary, .button-link` + hover) — оставить только `.button-secondary`;
- строка 91 — `.video-actions .button-link, .video-actions .button-secondary` → оставить только `.video-actions .button-secondary` (secondary внутри actions остаётся: его рендерит DownloadButton на /local);
- строка 280 (media ≤620px) — убрать `.video-actions .button-link,` из списка;
- строка 307 (pointer: coarse) — убрать `.video-actions .button-link,` из списка;
- `.video-actions` (строка 90) и `.download-*` правила остаются — используются DownloadButton на `/local` и `VideoPage`.
- `README.md` — не трогаем (кнопки карточек в README не документируются; это полировка UI, не фича).
## Критерии приёмки
1. На `/`, `/category/:id`, `/uncategorized`, `/search` и `/channels/:id/videos` в карточках нет ни «Смотреть», ни «Скачать»; карточка кликабельна через превью и заголовок, `aria-label="Смотреть: …"` на thumbnail-Link сохранён.
2. На `/local` кнопка скачивания осталась и ведёт себя как раньше: статусы (Скачать/Скачивается N%/В очереди…/Обработка…/На сервере/Повторить/Загрузить снова) и инвалидация кэшей `['feed']`/`['video', id]` по завершении работают. «Смотреть» в карточках нет и на `/local`.
3. `DownloadButton` не сломан нигде: на `VideoPage` (`showDelete`) — скачивание, статусы и «Удалить копию» (с инвалидацией) работают как раньше.
4. CSS почищен: `rg "button-link" frontend/src` не находит ни одного вхождения (ни в CSS, ни в TSX); правила `.video-actions` и `.download-*` остаются живыми (используются DownloadButton).
5. `npm run lint` и `npm run build` в `frontend/` чистые (нет unused-импортов/локалов).
6. Backend не тронут: `git status` показывает изменения только в `frontend/` и `analytics/`; `pytest` не требуется (изменений backend/тестов нет), при желании прогоняется без изменений.
7. Деплой по правилу команды: `docker compose up -d --build`, `curl http://localhost:8080/api/health` → OK.
## План
1. `VideoCard.tsx`: `interface Props { video: FeedVideoDto; showActions?: boolean }`; деструктуризация `({ video, showActions = false })`; `.video-actions` рендерить условно `{showActions && <div className="video-actions"><DownloadButton video={video} /></div>}`; удалить «Смотреть»-Link и импорт `Icon`.
2. `Feed.tsx`: `<VideoCard key={…} video={video} showActions={isLocal} />`.
3. `App.css`: вычистить `.button-link` из строк 58, 59, 62, 63, 91, 280, 307 (по списку выше), не трогая `.video-actions` и `.download-*`.
4. Проверки: `rg -n "button-link" frontend/src` → пусто; `npm run lint`, `npm run build` в `frontend/`; ручная проверка: лента/категории/поиск/страница канала без кнопок, `/local` с кнопкой и статусами, `VideoPage` с «Удалить копию»; деплой и health-проверка.
## Риски и ограничения
- **Не потерять действия на /local**: условие рендера должно опираться на `isLocal` из `Feed.tsx`, а не на проп, вычисляемый внутри карточки (VideoCard не знает маршрут надёжно — точнее держать флаг в родителе). `ChannelVideos` по умолчанию без действий.
- **`Icon`/`DownloadButton` импорты**: после удаления «Смотреть» импорт `Icon` в `VideoCard` неиспользуемый — при `noUnusedLocals` сборка упадёт, если его оставить; импорт `DownloadButton` нужен (условный рендер).
- **«Удалить копию» на карточке /local**: в карточке её нет и не было (DownloadButton там рендерится без `showDelete`); критерий — «не сломать», а не «добавить». Удаление копии остаётся на `VideoPage` (проп `showDelete` не трогаем).
- **CSS-чистка**: класс `.button-link` после правки нигде не используется — удалять его правила целиком; `.video-actions .button-secondary` оставить (secondary-кнопки DownloadButton в блоке действий). Медиа-правила ≤620px и pointer:coarse править точечно, не трогая соседние селекторы.
- **Empty-state /local**: подсказка «Нажми „Скачать“ у понравившегося ролика…» остаётся корректной, т.к. на /local кнопка сохраняется. Но на обычной ленте кнопки больше нет — путь скачивания теперь только через страницу видео (это осознанное UX-решение задачи).
- **`Feed.tsx` уже загружен**: изменения ограничиваются одной строкой рендера — не усложнять компонент дополнительной логикой.
## Журнал изменений
- 2026-09-18: документ создан перед реализацией. Зафиксированы решения: проп `showActions` в `VideoCard` (default false); «Смотреть» убирается везде, DownloadButton остаётся только на `/local` (как сегодня, без `showDelete`); `ChannelVideos` не меняется; CSS: полное удаление мёртвого класса `.button-link`, сохранение `.video-actions`/`.download-*`; README не трогаем; backend не трогаем.