import React, { useEffect, useRef } from 'react'; import { Article, ReaderSettings } from '../types'; import { FileText, MousePointerClick } from 'lucide-react'; interface ReaderViewProps { article?: Article | null; settings?: ReaderSettings; onToggleAutoScroll?: () => void; onSegmentSelect?: (index: number) => void; } export const ReaderView: React.FC = ({ article, settings, onToggleAutoScroll, onSegmentSelect }) => { const scrollRef = useRef(null); // Auto-scroll to active segment useEffect(() => { if (!article || article.status !== 'PLAYING' || settings?.autoScroll === false) return; const activeEl = document.getElementById(`segment-${article.currentSegmentIndex}`); if (activeEl && scrollRef.current) { activeEl.scrollIntoView({ behavior: 'smooth', block: 'center' }); } }, [article?.currentSegmentIndex, article?.status, settings?.autoScroll]); // Default settings fallback const s = settings || { isDarkMode: false, fontSize: 'lg', lineHeight: 'relaxed', fontFamily: 'serif', autoScroll: true }; const getFontClass = () => { switch(s.fontFamily) { case 'sans': return 'font-sans'; case 'mono': return 'font-mono'; default: return 'font-serif'; } }; const getSizeClass = () => { switch(s.fontSize) { case 'sm': return 'text-sm'; case 'base': return 'text-base'; case 'xl': return 'text-xl'; case '2xl': return 'text-2xl'; default: return 'text-lg'; } }; const getLeadingClass = () => { switch(s.lineHeight) { case 'normal': return 'leading-normal'; case 'loose': return 'leading-loose'; default: return 'leading-relaxed'; } }; if (!article) { return (

Select an article to read along

The text will appear here while you listen.

); } return (

{article.title}

{new URL(article.url).hostname}
{/* Auto Scroll Toggle */}
{article.segments.length > 0 ? ( article.segments.map((segment, idx) => { const isActive = article.currentSegmentIndex === idx; return (
onSegmentSelect?.(idx)} title="Click to play from here" className={` transition-all duration-200 whitespace-pre-wrap rounded-xl p-3 sm:p-4 -mx-2 sm:-mx-4 border-l-4 mb-2 ${getLeadingClass()} ${isActive ? 'text-slate-900 dark:text-white bg-blue-50 dark:bg-blue-900/20 border-blue-500 shadow-sm' : 'text-slate-700 dark:text-slate-300 border-transparent hover:bg-slate-100 dark:hover:bg-slate-800/50 cursor-pointer hover:border-slate-300 dark:hover:border-slate-600' } `} > {segment.text}
); }) ) : ( // Loading State skeleton
{[1,2,3,4].map(i => (
))}

Extracting article content...

)}
); };