From c010abd5a3fdb1ff1961baf39931568c6872b101 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Wed, 17 Jun 2026 13:55:43 +0200 Subject: [PATCH 1/3] feat(channels): YouTube link on channel name + done checkmarks - Channel name: middle-click opens the channel's YouTube page in a new tab (left-click still opens the in-app detail) plus an explicit external-link icon. - recent/full sync badges show a check icon when the state is reached. - New i18n key channels.row.openOnYouTube (HU/EN/DE). --- frontend/src/components/Channels.tsx | 41 +++++++++++++++++++--- frontend/src/i18n/locales/de/channels.json | 1 + frontend/src/i18n/locales/en/channels.json | 1 + frontend/src/i18n/locales/hu/channels.json | 1 + 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/Channels.tsx b/frontend/src/components/Channels.tsx index 3db9eb1..dc37a27 100644 --- a/frontend/src/components/Channels.tsx +++ b/frontend/src/components/Channels.tsx @@ -4,6 +4,8 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { ArrowDown, ArrowUp, + Check, + ExternalLink, Eye, EyeOff, History, @@ -361,10 +363,11 @@ function SyncBadge({ ok, label, hint }: { ok: boolean; label: string; hint?: str return ( + {ok && } {label} @@ -393,6 +396,9 @@ function ChannelRow({ onToggleTag: (tagId: number) => void; }) { const { t } = useTranslation(); + const ytUrl = c.handle + ? `https://www.youtube.com/@${c.handle.replace(/^@/, "")}` + : `https://www.youtube.com/channel/${c.id}`; return (
- +
+ + + + + + +
{t("channels.row.stored", { count: c.stored_videos, formatted: c.stored_videos.toLocaleString() })} {c.subscriber_count != null && · {t("channels.row.subs", { count: c.subscriber_count, formatted: c.subscriber_count.toLocaleString() })}} diff --git a/frontend/src/i18n/locales/de/channels.json b/frontend/src/i18n/locales/de/channels.json index 8638c94..f57b703 100644 --- a/frontend/src/i18n/locales/de/channels.json +++ b/frontend/src/i18n/locales/de/channels.json @@ -36,6 +36,7 @@ "row": { "stored": "{{formatted}} gespeichert", "subs": "{{formatted}} Abonnenten", + "openOnYouTube": "Auf YouTube öffnen", "priorityHint": "Deine Einstufung für diesen Kanal. Sortiere den Feed nach „Kanalpriorität“, um Kanäle mit höherer Priorität nach oben zu bringen.", "raisePriority": "Priorität erhöhen", "lowerPriority": "Priorität senken", diff --git a/frontend/src/i18n/locales/en/channels.json b/frontend/src/i18n/locales/en/channels.json index 9ecd280..0adc427 100644 --- a/frontend/src/i18n/locales/en/channels.json +++ b/frontend/src/i18n/locales/en/channels.json @@ -36,6 +36,7 @@ "row": { "stored": "{{formatted}} stored", "subs": "{{formatted}} subs", + "openOnYouTube": "Open on YouTube", "priorityHint": "Your ranking for this channel. Sort the feed by “Channel priority” to bring higher-priority channels to the top.", "raisePriority": "Raise priority", "lowerPriority": "Lower priority", diff --git a/frontend/src/i18n/locales/hu/channels.json b/frontend/src/i18n/locales/hu/channels.json index 30904eb..fc36ce7 100644 --- a/frontend/src/i18n/locales/hu/channels.json +++ b/frontend/src/i18n/locales/hu/channels.json @@ -36,6 +36,7 @@ "row": { "stored": "{{formatted}} tárolt", "subs": "{{formatted}} feliratkozó", + "openOnYouTube": "Megnyitás a YouTube-on", "priorityHint": "A te rangsorod ehhez a csatornához. Rendezd a hírfolyamot „Csatorna prioritás” szerint, hogy a magasabb prioritású csatornák felülre kerüljenek.", "raisePriority": "Prioritás növelése", "lowerPriority": "Prioritás csökkentése", From c74ef1e6325bd82a0f5715ad40197c6f1da2d6fb Mon Sep 17 00:00:00 2001 From: npeter83 Date: Wed, 17 Jun 2026 13:55:43 +0200 Subject: [PATCH 2/3] feat(playlists): move the new-playlist input to the top of the rail --- frontend/src/components/Playlists.tsx | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/frontend/src/components/Playlists.tsx b/frontend/src/components/Playlists.tsx index 93512f0..8bf346e 100644 --- a/frontend/src/components/Playlists.tsx +++ b/frontend/src/components/Playlists.tsx @@ -580,6 +580,21 @@ export default function Playlists({ canWrite }: { canWrite: boolean }) {
)} +
{ + e.preventDefault(); + if (newName.trim()) createMut.mutate(newName.trim()); + }} + className="flex items-center gap-1.5 mb-3 pb-3 border-b border-border" + > + + setNewName(e.target.value)} + placeholder={t("playlists.newPlaylist")} + className="flex-1 min-w-0 bg-card border border-border rounded-md px-2 py-1 text-xs outline-none focus:border-accent" + /> + {playlists.length === 0 && !listQuery.isLoading && (
{t("playlists.noneYet")}
)} @@ -618,21 +633,6 @@ export default function Playlists({ canWrite }: { canWrite: boolean }) { ))}
-
{ - e.preventDefault(); - if (newName.trim()) createMut.mutate(newName.trim()); - }} - className="flex items-center gap-1.5 mt-3 pt-3 border-t border-border" - > - - setNewName(e.target.value)} - placeholder={t("playlists.newPlaylist")} - className="flex-1 min-w-0 bg-card border border-border rounded-md px-2 py-1 text-xs outline-none focus:border-accent" - /> -
From ea2b9842e11771e095aa699caacd7a3fb5b3515b Mon Sep 17 00:00:00 2001 From: npeter83 Date: Wed, 17 Jun 2026 13:55:43 +0200 Subject: [PATCH 3/3] fix(stats): keep daily usage bars always visible Each day now has a full-height track behind a solid accent fill, so low-usage days no longer render as a near-invisible sliver that only stood out on hover. --- frontend/src/components/Stats.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/Stats.tsx b/frontend/src/components/Stats.tsx index f8dd9c3..46a776e 100644 --- a/frontend/src/components/Stats.tsx +++ b/frontend/src/components/Stats.tsx @@ -63,15 +63,21 @@ export default function Stats() { ) : (
{data.daily.map((d) => ( + // Each day gets a full-height track so the column is always visible + // (even on near-zero days); the accent fill renders the value on top.
+ > +
+
))}
)}