11import { useState , useEffect , useCallback , useRef , useMemo , type MutableRefObject } from 'react'
22import InputScreen from '@/components/InputScreen'
33import ParsingProgress from '@/components/ParsingProgress'
4+ import ProfilerOverlay from '@/components/ProfilerOverlay'
45import { calculateStats } from '@/lib/stats'
56import { calculateFunStats } from '@/lib/funStats'
67import { generateInsights } from '@/lib/insights'
@@ -12,6 +13,7 @@ import RevealSequence from '@/components/dashboard/RevealSequence'
1213import ErrorBoundary from '@/components/ErrorBoundary'
1314import { DEMO_FLIGHTS } from '@/components/landing/demoFlights'
1415import type { Flight , ParseProgress , WorkerOutMessage } from '@/lib/types'
16+ import type { ProfilerReport } from '@/lib/profiler'
1517
1618type AppState = 'landing' | 'parsing' | 'reveal' | 'results'
1719
@@ -27,8 +29,11 @@ function App() {
2729 const [ error , setError ] = useState < string | null > ( null )
2830 const [ cachedData , setCachedData ] = useState < SyncData | null > ( null )
2931 const [ lastImportAt , setLastImportAt ] = useState < string | null > ( null )
32+ const [ profilerEnabled , setProfilerEnabled ] = useState ( false )
33+ const [ profilerReport , setProfilerReport ] = useState < ProfilerReport | null > ( null )
3034 const workerRef = useRef < Worker | null > ( null )
3135 const generationRef = useRef ( 0 ) as MutableRefObject < number >
36+ const profilerEnabledRef = useRef ( false )
3237 // Existing flights for merging with new imports
3338 const existingFlightsRef = useRef < Flight [ ] > ( [ ] )
3439
@@ -63,6 +68,9 @@ function App() {
6368 setAppState ( merged . length > 0 ? 'reveal' : 'results' )
6469 break
6570 }
71+ case 'profiler-report' :
72+ setProfilerReport ( msg . data )
73+ break
6674 case 'error' :
6775 setError ( msg . data . message )
6876 setProgress ( ( p ) => ( { ...p , phase : 'error' , message : msg . data . message } ) )
@@ -77,6 +85,7 @@ function App() {
7785 }
7886
7987 workerRef . current = worker
88+ worker . postMessage ( { type : 'set-profiler' , data : profilerEnabledRef . current } )
8089 worker . postMessage ( { type : 'init-llm' } )
8190 return worker
8291 } , [ ] )
@@ -94,9 +103,18 @@ function App() {
94103 // eslint-disable-next-line react-hooks/exhaustive-deps
95104 } , [ ] )
96105
106+ const handleProfilerToggle = useCallback ( ( ) => {
107+ const next = ! profilerEnabledRef . current
108+ profilerEnabledRef . current = next
109+ setProfilerEnabled ( next )
110+ if ( ! next ) setProfilerReport ( null )
111+ workerRef . current ?. postMessage ( { type : 'set-profiler' , data : next } )
112+ } , [ ] )
113+
97114 const handleFileUpload = useCallback ( ( files : File [ ] ) => {
98115 setAppState ( 'parsing' )
99116 setError ( null )
117+ setProfilerReport ( null )
100118 setProgress ( { phase : 'scanning' , current : 0 , total : 0 , flightsFound : 0 , message : 'Preparing files...' } )
101119
102120 // Preserve existing flights for merge
@@ -108,6 +126,8 @@ function App() {
108126 if ( ! granted ) console . warn ( 'Durable storage not granted. Model cache may be evicted' )
109127 } )
110128
129+ // Ensure worker has latest profiler state
130+ workerRef . current ?. postMessage ( { type : 'set-profiler' , data : profilerEnabledRef . current } )
111131 // Send File objects directly to worker (structured-cloneable)
112132 // No FileReader needed -- the worker streams them with File.stream()
113133 workerRef . current ?. postMessage ( { type : 'parse-mbox-files' , data : files } )
@@ -149,6 +169,14 @@ function App() {
149169 existingFlightsRef . current = [ ]
150170 } , [ createWorker ] )
151171
172+ const profilerOverlay = (
173+ < ProfilerOverlay
174+ enabled = { profilerEnabled }
175+ onToggle = { handleProfilerToggle }
176+ report = { profilerReport }
177+ />
178+ )
179+
152180 if ( appState === 'landing' ) {
153181 return (
154182 < div className = "animate-fade-in" >
@@ -167,6 +195,7 @@ function App() {
167195 </ button >
168196 </ div >
169197 ) }
198+ { profilerOverlay }
170199 </ div >
171200 )
172201 }
@@ -176,18 +205,22 @@ function App() {
176205 < div className = "min-h-screen glass-bg text-white flex flex-col items-center justify-center px-4 animate-fade-in" >
177206 < h1 className = "text-3xl font-bold mb-8" > FlightWrapped</ h1 >
178207 < ParsingProgress progress = { progress } onReset = { resetToLanding } />
208+ { profilerOverlay }
179209 </ div >
180210 )
181211 }
182212
183213 if ( appState === 'reveal' ) {
184214 return (
185- < RevealSequence
186- stats = { stats }
187- funStats = { funStats }
188- archetype = { archetype }
189- onComplete = { ( ) => setAppState ( 'results' ) }
190- />
215+ < >
216+ < RevealSequence
217+ stats = { stats }
218+ funStats = { funStats }
219+ archetype = { archetype }
220+ onComplete = { ( ) => setAppState ( 'results' ) }
221+ />
222+ { profilerOverlay }
223+ </ >
191224 )
192225 }
193226
@@ -205,6 +238,7 @@ function App() {
205238 onFileUpload = { handleFileUpload }
206239 />
207240 </ div >
241+ { profilerOverlay }
208242 </ ErrorBoundary >
209243 )
210244}
0 commit comments