Fix review findings and remove Uncategorized from sidebar

Backend: cache Google access tokens (drop dead access_token_expires_at,
migration 0007), handle MeTube cleared/canceled events by URL, return
email from /auth/status only when authenticated, move Google base URLs
into settings, run container as non-root.

Frontend: include local feed filters in the query key, remove dead
Saved page and unused assets, drop stale CategoryNav props and classes,
send Content-Type only with a body, remove Uncategorized from sidebar.
This commit is contained in:
vrubelroman 2026-09-17 17:22:22 +00:00
parent 6c704cac97
commit fde9a439df
25 changed files with 420 additions and 174 deletions

View file

@ -11,11 +11,11 @@ function ChannelVideos() {
const channelQuery = useQuery({ queryKey: ['channel', id], queryFn: () => getChannel(id), enabled: valid })
const feedQuery = useInfiniteQuery({ queryKey: ['feed', 'channel', id], queryFn: ({ pageParam }) => getFeed({ channelId: id, cursor: pageParam }), initialPageParam: undefined as string | undefined, getNextPageParam: (lastPage) => lastPage.next_cursor ?? undefined, enabled: valid })
const items = feedQuery.data?.pages.flatMap((page) => page.items) ?? []
return <section className="page feed-screen">
return <section className="page">
<Link to="/channels" className="back-link"><Icon name="arrow" size={17} /> Каналы</Link>
<div className="page-heading"><div><p className="eyebrow">Видео канала</p><h1>{channelQuery.data?.title ?? 'Канал'}</h1><p className="page-subtitle">Последние ролики из твоих подписок.</p></div></div>
{(channelQuery.isError || feedQuery.isError || !valid) && <div className="empty-state" role="alert"><h2>Не удалось открыть канал</h2><Link to="/channels" className="button-primary">К списку каналов</Link></div>}
{feedQuery.isLoading && <div className="video-grid">{Array.from({ length: 6 }, (_, index) => <div className="video-card skeleton-card" key={index}><div className="skeleton-thumbnail" /><div className="video-info"><div className="skeleton-line wide" /><div className="skeleton-line" /></div></div>)}</div>}
{feedQuery.isLoading && <div className="video-grid">{Array.from({ length: 6 }, (_, index) => <div className="video-card" key={index}><div className="skeleton-thumbnail" /><div className="video-info"><div className="skeleton-line wide" /><div className="skeleton-line" /></div></div>)}</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 && <div className="empty-state"><h2>Пока нет видео</h2><p>Обнови ленту, чтобы получить новые ролики канала.</p></div>}
{feedQuery.hasNextPage && <button className="button-secondary load-more" onClick={() => feedQuery.fetchNextPage()} disabled={feedQuery.isFetchingNextPage}>{feedQuery.isFetchingNextPage ? 'Загрузка…' : 'Показать ещё'}</button>}