App.tsx
1 import { useState, useEffect, useCallback } from 'react'; 2 import { HomePage } from './pages/HomePage'; 3 import { ReviewPage } from './pages/ReviewPage'; 4 import { UpdateBanner } from '../components/UpdateBanner'; 5 import { applyCodeFont } from '../components/SettingsDialog'; 6 import { applyTheme } from '../lib/theme'; 7 import type { ReviewGuide } from '../lib/types'; 8 9 type Page = 'home' | 'review'; 10 11 export function App() { 12 const [page, setPage] = useState<Page>('home'); 13 14 useEffect(() => { 15 void window.electronAPI.loadPreferences().then((prefs) => { 16 if (prefs.codeFont) applyCodeFont(prefs.codeFont); 17 applyTheme(prefs.theme); 18 }); 19 }, []); 20 21 // When a background auto-review completes, the history list will refresh itself 22 // via the new-review-in-history event — handled in HomePage. 23 const [review, setReview] = useState<ReviewGuide | null>(null); 24 const [prefillPrUrl, setPrefillPrUrl] = useState<string | undefined>(); 25 26 const handleReviewReady = useCallback((r: ReviewGuide) => { 27 setPrefillPrUrl(undefined); 28 setReview(r); 29 setPage('review'); 30 }, []); 31 32 function handleBack() { 33 setReview(null); 34 setPage('home'); 35 } 36 37 function handleReReview(prUrl: string) { 38 setPrefillPrUrl(prUrl); 39 setReview(null); 40 setPage('home'); 41 } 42 43 // Navigate to a completed review when notification is clicked 44 useEffect(() => { 45 window.electronAPI.onReviewNavigate((reviewId) => { 46 void window.electronAPI.loadReview(reviewId).then((r) => { 47 handleReviewReady(r); 48 }); 49 }); 50 return () => { 51 window.electronAPI.offReviewNavigate(); 52 }; 53 }, [handleReviewReady]); 54 55 return ( 56 <> 57 {/* Skip-to-content link — visually hidden until focused. Lets 58 keyboard users jump straight to the slide/page content 59 without tabbing through the persistent header chrome. */} 60 <a 61 href="#main-content" 62 className="sr-only focus:not-sr-only focus:fixed focus:top-3 focus:left-3 focus:z-[100] focus:bg-background focus:text-foreground focus:px-3 focus:py-2 focus:border focus:border-[var(--ring)] focus:text-sm" 63 > 64 Skip to content 65 </a> 66 <UpdateBanner /> 67 <div id="main-content"> 68 {page === 'home' && <HomePage onReviewReady={handleReviewReady} prefillPrUrl={prefillPrUrl} />} 69 {page === 'review' && review && ( 70 <ReviewPage review={review} onBack={handleBack} onReReview={handleReReview} /> 71 )} 72 </div> 73 </> 74 ); 75 }