/** * FeedPage - Shows latest episodes across all subscribed shows * Reverse chronological order, grouped by date */ import { createSignal, For, Show } from "solid-js"; import { useFeedStore } from "@/stores/feed"; import { format } from "date-fns"; import type { Episode } from "@/types/episode"; import type { Feed } from "@/types/feed"; import { useTheme } from "@/context/ThemeContext"; import { SelectableBox, SelectableText } from "@/components/Selectable"; import { useNavigation } from "@/context/NavigationContext"; import { LoadingIndicator } from "@/components/LoadingIndicator"; import { TABS } from "@/utils/navigation"; enum FeedPaneType { FEED = 1, } export const FeedPaneCount = 1; const ITEMS_PER_BATCH = 50; export function FeedPage() { const feedStore = useFeedStore(); const nav = useNavigation(); const { theme } = useTheme(); const [selectedEpisodeID, setSelectedEpisodeID] = createSignal< string | undefined >(); const allEpisodes = () => feedStore.getAllEpisodesChronological(); const formatDate = (date: Date): string => { return format(date, "MMM d, yyyy"); }; const groupEpisodesByDate = () => { const groups: Record> = {}; for (const item of allEpisodes()) { const dateKey = formatDate(new Date(item.episode.pubDate)); if (!groups[dateKey]) { groups[dateKey] = []; } groups[dateKey].push(item); } return Object.entries(groups).sort(([a, _aItems], [b, _bItems]) => { // Convert date strings back to Date objects for proper chronological sorting const dateA = new Date(a); const dateB = new Date(b); // Sort in descending order (newest first) return dateB.getTime() - dateA.getTime(); }); }; const formatDuration = (seconds: number): string => { const mins = Math.floor(seconds / 60); const hrs = Math.floor(mins / 60); if (hrs > 0) return `${hrs}h ${mins % 60}m`; return `${mins}m`; }; return ( 0} fallback={ No episodes yet. Subscribe to shows from Discover or Search. } > {([date, items]) => ( false} primary> {date} {(item) => { const isSelected = () => { if ( nav.activeTab() == TABS.FEED && nav.activeDepth() == FeedPaneType.FEED && selectedEpisodeID() && selectedEpisodeID() === item.episode.id ) { return true; } return false; }; return ( { // Selection is handled by App's keyboard navigation }} > {item.episode.title} {item.feed.podcast.title} {formatDuration(item.episode.duration)} ); }} )} ); }