import { Bookmark, Check, Eye, EyeOff, ListFilter } from "lucide-react";
import clsx from "clsx";
import type { Video } from "../lib/api";
import { formatDuration, formatViews, relativeTime } from "../lib/format";
function Actions({
video,
onState,
onChannelFilter,
}: {
video: Video;
onState: (id: string, status: string) => void;
onChannelFilter?: (channelId: string, channelName: string) => void;
}) {
const act = (status: string) => (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
onState(video.id, video.status === status ? "new" : status);
};
return (
{onChannelFilter && (
)}
);
}
// Plain left-click opens the in-app player (the experiment); Ctrl/Cmd/middle-click
// keep the native "open youtube.com in a new tab" behavior via the underlying href.
function openInApp(
e: React.MouseEvent,
video: Video,
onOpen?: (v: Video) => void
): void {
if (!onOpen || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) return;
e.preventDefault();
onOpen(video);
}
function Thumb({
video,
className,
onOpen,
}: {
video: Video;
className?: string;
onOpen?: (v: Video) => void;
}) {
return (
openInApp(e, video, onOpen)}
className={clsx(
"block relative rounded-xl overflow-hidden bg-surface border border-border shadow-md group-hover:shadow-2xl transition-shadow",
className
)}
>
{video.thumbnail_url ? (
) : (
)}
{video.duration_seconds != null && (
{formatDuration(video.duration_seconds)}
)}
{video.live_status === "was_live" && (
stream
)}
{video.status === "saved" && (
)}
);
}
export default function VideoCard({
video,
view,
onState,
onChannelFilter,
onOpen,
}: {
video: Video;
view: "grid" | "list";
onState: (id: string, status: string) => void;
onChannelFilter?: (channelId: string, channelName: string) => void;
onOpen?: (v: Video) => void;
}) {
const watched = video.status === "watched";
const meta = (
<>
{video.view_count != null && <>{formatViews(video.view_count)} views ยท >}
{relativeTime(video.published_at)}
>
);
const title = (
openInApp(e, video, onOpen)}
className="font-medium leading-snug line-clamp-2 hover:text-accent"
>
{video.title}
);
if (view === "list") {
return (
);
}
return (
{video.channel_thumbnail && (

)}
);
}