fix: address reader-UI feedback (shorts, search, tags, login, UX)

- Shorts: confirm via youtube.com/shorts/<id> probe (SOCS cookie bypasses the
  consent redirect) instead of a 60s heuristic; concurrent probing, shorts_probed
  flag, scheduled refinement (migration 0005)
- Search: match title + channel name only (descriptions caused noisy results)
- Faceted tag filtering: AND across categories (language AND topic narrows),
  OR within a category; any/all toggle applies to topics
- Language detection: majority vote over individual titles (fixes misdetections
  like multipoleguy -> English; drops bogus Polish/Romanian)
- Login: drop forced consent so returning sign-in is quick (select_account)
- Feed cards: clickable channel name (opens channel), persistent saved badge,
  undo toast on hide, Hidden view to restore; tag chips show counts in tooltip
This commit is contained in:
npeter83 2026-06-11 03:07:49 +02:00
parent e56502789f
commit 8c245e986f
17 changed files with 306 additions and 35 deletions

View file

@ -0,0 +1,29 @@
import { useSyncExternalStore } from "react";
import { dismiss, getToasts, subscribe } from "../lib/toast";
export default function Toaster() {
const toasts = useSyncExternalStore(subscribe, getToasts, getToasts);
return (
<div className="fixed bottom-4 right-4 z-50 flex flex-col gap-2">
{toasts.map((t) => (
<div
key={t.id}
className="bg-surface border border-border rounded-xl shadow-2xl px-4 py-3 flex items-center gap-4 animate-[fadeIn_0.15s_ease]"
>
<span className="text-sm">{t.message}</span>
{t.action && (
<button
onClick={() => {
t.action!.onClick();
dismiss(t.id);
}}
className="text-accent text-sm font-semibold hover:underline"
>
{t.action.label}
</button>
)}
</div>
))}
</div>
);
}