Remove watch/download buttons from feed video cards
Cards stay fully clickable via thumbnail and title; downloads are managed from the video page. On the Saved page the download button remains (status/delete), and the dead .button-link styles are removed.
This commit is contained in:
parent
d4950f6979
commit
fb6e639309
4 changed files with 71 additions and 14 deletions
|
|
@ -55,12 +55,12 @@ h2 { color: var(--text); font-size: 18px; line-height: 1.3; font-weight: 650; }
|
|||
.page-subtitle { margin: 0; color: var(--muted); font-size: 14px; line-height: 1.5; }
|
||||
.page-subtitle a { color: var(--accent); text-decoration: none; font-weight: 650; }
|
||||
.page-subtitle a:hover { text-decoration: underline; }
|
||||
button, .button-primary, .button-secondary, .button-quiet, .button-danger, .button-link { transition: background .16s, color .16s, border-color .16s; }
|
||||
.button-primary, .button-secondary, .button-danger, .button-link { min-height: 42px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; border-radius: 8px; padding: 0 15px; text-decoration: none; font-size: 13px; font-weight: 650; white-space: nowrap; }
|
||||
button, .button-primary, .button-secondary, .button-quiet, .button-danger { transition: background .16s, color .16s, border-color .16s; }
|
||||
.button-primary, .button-secondary, .button-danger { min-height: 42px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; border-radius: 8px; padding: 0 15px; text-decoration: none; font-size: 13px; font-weight: 650; white-space: nowrap; }
|
||||
.button-primary { border: 1px solid var(--accent); background: var(--accent); color: #081521; }
|
||||
.button-primary:hover { background: #79c1ff; border-color: #79c1ff; }
|
||||
.button-secondary, .button-link { border: 1px solid var(--border); background: var(--surface-raised); color: var(--text); }
|
||||
.button-secondary:hover, .button-link:hover { background: var(--hover); border-color: #555; }
|
||||
.button-secondary { border: 1px solid var(--border); background: var(--surface-raised); color: var(--text); }
|
||||
.button-secondary:hover { background: var(--hover); border-color: #555; }
|
||||
.button-quiet { min-height: 40px; padding: 0 10px; display: inline-flex; align-items: center; gap: 7px; background: transparent; border: 0; color: var(--muted); border-radius: 8px; font-size: 13px; text-decoration: none; }
|
||||
.button-quiet:hover { color: var(--text); background: var(--hover); }
|
||||
.button-danger { background: #a72c2a; border: 1px solid #a72c2a; color: white; }
|
||||
|
|
@ -88,7 +88,7 @@ button, .button-primary, .button-secondary, .button-quiet, .button-danger, .butt
|
|||
.video-channel { color: #c8c8c8; }
|
||||
.video-meta span + span::before { content: '·'; margin-right: 7px; color: var(--subtle); }
|
||||
.video-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: auto; padding-top: 13px; }
|
||||
.video-actions .button-link, .video-actions .button-secondary { min-height: 36px; padding: 0 11px; }
|
||||
.video-actions .button-secondary { min-height: 36px; padding: 0 11px; }
|
||||
.download-inline-actions, .download-error { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 6px; }
|
||||
.download-badge { position: relative; display: inline-flex; align-items: center; gap: 5px; min-height: 36px; overflow: hidden; border-radius: 7px; padding: 0 10px; background: var(--surface-raised); color: var(--muted); font-size: 12px; white-space: nowrap; }
|
||||
.download-badge.completed { color: var(--success); background: var(--success-soft); }
|
||||
|
|
@ -277,7 +277,7 @@ button, .button-primary, .button-secondary, .button-quiet, .button-danger, .butt
|
|||
.video-thumbnail { border-radius: 9px; }
|
||||
.video-info { padding: 10px 2px 0; }
|
||||
.video-actions { padding-top: 11px; }
|
||||
.video-actions .button-link, .video-actions .button-secondary, .download-badge { min-height: 44px; }
|
||||
.video-actions .button-secondary, .download-badge { min-height: 44px; }
|
||||
.channels-toolbar { align-items: stretch; }
|
||||
.manage-link { width: 43px; flex: none; overflow: hidden; font-size: 0; padding: 0; }
|
||||
.manage-link svg { flex: none; }
|
||||
|
|
@ -304,7 +304,7 @@ button, .button-primary, .button-secondary, .button-quiet, .button-danger, .butt
|
|||
}
|
||||
@media (min-width: 621px) and (max-width: 699px) { .video-grid { grid-template-columns: 1fr; } }
|
||||
@media (pointer: coarse) {
|
||||
.video-actions .button-link, .video-actions .button-secondary, .download-badge, .category-nav button, .local-filter-nav a, .mobile-category-nav a, .chip, .chip-edit, .category-checkbox, .unsubscribe-button, .sidebar-badge { min-height: 44px; }
|
||||
.video-actions .button-secondary, .download-badge, .category-nav button, .local-filter-nav a, .mobile-category-nav a, .chip, .chip-edit, .category-checkbox, .unsubscribe-button, .sidebar-badge { min-height: 44px; }
|
||||
.sidebar-badge { display: inline-flex; align-items: center; }
|
||||
.view-toggle a { min-height: 44px; }
|
||||
.reorder-buttons .icon-button { width: 40px; height: 40px; }
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ import { Link, useLocation } from 'react-router-dom'
|
|||
import type { FeedVideoDto } from '../api/client'
|
||||
import { formatDuration, formatRelativeTime } from '../utils/format'
|
||||
import DownloadButton from './DownloadButton'
|
||||
import Icon from './Icon'
|
||||
|
||||
interface Props {
|
||||
video: FeedVideoDto
|
||||
showActions?: boolean
|
||||
}
|
||||
|
||||
function VideoCard({ video }: Props) {
|
||||
function VideoCard({ video, showActions = false }: Props) {
|
||||
const duration = formatDuration(video.duration_seconds)
|
||||
const href = `/video/${video.youtube_video_id}`
|
||||
const location = useLocation()
|
||||
|
|
@ -30,10 +30,7 @@ function VideoCard({ video }: Props) {
|
|||
{video.title}
|
||||
</Link>
|
||||
<div className="video-meta"><span className="video-channel">{video.channel.title}</span><span>{formatRelativeTime(video.published_at)}</span></div>
|
||||
<div className="video-actions">
|
||||
<Link to={href} state={{ from }} onClick={rememberScroll} className="button-link"><Icon name="play" size={16} /> Смотреть</Link>
|
||||
<DownloadButton video={video} />
|
||||
</div>
|
||||
{showActions && <div className="video-actions"><DownloadButton video={video} /></div>}
|
||||
</div>
|
||||
</li>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ function Feed() {
|
|||
{hasInvalidCategory || (categoryId && categoriesQuery.data && !category) ? <div className="empty-state"><h2>Категория не найдена</h2><Link className="button-primary" to="/">Ко всем видео</Link></div> : isChannelsView ? <ChannelActivityList categoryId={categoryNumber} uncategorized={isUncategorized} syncRunning={syncRunning} /> : <>
|
||||
{feedQuery.isLoading && <ul className="video-grid">{Array.from({ length: 8 }, (_, index) => <VideoSkeleton key={index} />)}</ul>}
|
||||
{feedQuery.isError && <div className="empty-state" role="alert"><Icon name="alert" size={28} /><h2>Не удалось загрузить видео</h2><p>Проверь соединение и попробуй ещё раз.</p><button className="button-primary" onClick={() => feedQuery.refetch()}>Повторить</button></div>}
|
||||
{!feedQuery.isLoading && !feedQuery.isError && items.length > 0 && <ul className="video-grid">{items.map((video) => <VideoCard key={video.youtube_video_id} video={video} />)}</ul>}
|
||||
{!feedQuery.isLoading && !feedQuery.isError && items.length > 0 && <ul className="video-grid">{items.map((video) => <VideoCard key={video.youtube_video_id} video={video} showActions={isLocal} />)}</ul>}
|
||||
{!feedQuery.isLoading && !feedQuery.isError && items.length === 0 && <div className="empty-state"><span className="empty-icon"><Icon name={syncRunning ? 'refresh' : isLocal ? 'server' : search ? 'search' : 'folder'} size={28} /></span><h2>{syncRunning ? 'Загружаем новые видео' : search ? 'Ничего не найдено' : isLocal ? 'Пока нет сохранённых видео' : isUncategorized ? 'Все каналы распределены' : 'Здесь пока нет видео'}</h2><p>{syncRunning ? 'Подписки и лента обновляются. Видео появятся здесь автоматически.' : search ? 'Попробуй другой запрос.' : isLocal ? 'Нажми «Скачать» у понравившегося ролика, и он появится здесь.' : 'Добавь каналы в категорию или обнови ленту.'}</p>{!search && !isLocal && !syncRunning && <Link className="button-primary" to="/channels">Перейти к каналам</Link>}</div>}
|
||||
{feedQuery.hasNextPage && <button className="button-secondary load-more" onClick={() => feedQuery.fetchNextPage()} disabled={feedQuery.isFetchingNextPage}>{feedQuery.isFetchingNextPage ? 'Загрузка…' : 'Показать ещё'}</button>}
|
||||
</>}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue