feat: feed UI, in-app player, offline mode, settings
Adds an end-to-end integration test that runs the real pipeline against live YouTube Atom feeds, verifying the merged feed is newest-first across channels.
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { fileUrl } from "../api";
|
||||
import type { FeedItem } from "../types";
|
||||
import { compactViews, relativeTime } from "./format";
|
||||
|
||||
interface Props {
|
||||
item: FeedItem;
|
||||
path: string;
|
||||
onClose: () => void;
|
||||
onDelete: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays the local file through Tauri's asset protocol. Every download is
|
||||
* H.264/AAC in MP4 precisely so WKWebView can decode it natively.
|
||||
*/
|
||||
export default function Player({ item, path, onClose, onDelete }: Props) {
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 bg-ink/97 flex flex-col">
|
||||
<div className="flex items-center gap-3 px-5 py-3 border-b border-edge">
|
||||
<button onClick={onClose}
|
||||
className="rounded-full px-3 py-1.5 text-xs font-medium bg-surface hover:bg-raised cursor-pointer">
|
||||
← Back
|
||||
</button>
|
||||
<span className="text-sm text-muted truncate flex-1">{item.channel_title}</span>
|
||||
<button onClick={onDelete}
|
||||
className="rounded-full px-3 py-1.5 text-xs font-medium bg-surface text-muted
|
||||
hover:bg-red-500/20 hover:text-red-300 cursor-pointer">
|
||||
Delete download
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 min-h-0 bg-black grid place-items-center">
|
||||
<video key={path} src={fileUrl(path)} controls autoPlay
|
||||
className="max-h-full max-w-full" />
|
||||
</div>
|
||||
|
||||
<div className="px-5 py-4 max-h-56 overflow-y-auto border-t border-edge">
|
||||
<h2 className="font-semibold text-lg leading-snug">{item.title}</h2>
|
||||
<div className="mt-1 text-xs text-muted">
|
||||
{[compactViews(item.views), relativeTime(item.published)]
|
||||
.filter(Boolean)
|
||||
.join(" · ")}
|
||||
</div>
|
||||
{item.description && (
|
||||
<p className="mt-3 text-sm text-muted whitespace-pre-wrap leading-relaxed">
|
||||
{item.description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user