@@ -30,6 +30,7 @@ pub struct App {
3030 stats : Stats ,
3131 selected_lesson : usize ,
3232 lessons : Vec < Lesson > ,
33+ lesson_scroll_offset : usize ,
3334 selected_duration : usize ,
3435 selected_duration_value : crate :: engine:: SessionDuration ,
3536 keyboard_visible : bool ,
@@ -147,11 +148,12 @@ impl App {
147148
148149 Ok ( Self {
149150 session : None ,
150- state : AppState :: DurationMenu ,
151+ state : AppState :: LessonMenu , // Start with lesson selection
151152 storage,
152153 stats,
153154 selected_lesson : 0 ,
154155 lessons,
156+ lesson_scroll_offset : 0 ,
155157 selected_duration : 2 , // Default to 5 minutes (index 2)
156158 selected_duration_value : crate :: engine:: SessionDuration :: FiveMinutes ,
157159 keyboard_visible : true , // Default visible
@@ -212,12 +214,12 @@ impl App {
212214 loop {
213215 // Render
214216 terminal. draw ( |f| match self . state {
217+ AppState :: LessonMenu => {
218+ ui:: render_menu ( f, & self . lessons , self . selected_lesson , self . lesson_scroll_offset ) ;
219+ }
215220 AppState :: DurationMenu => {
216221 ui:: render_duration_menu ( f, self . selected_duration ) ;
217222 }
218- AppState :: LessonMenu => {
219- ui:: render_menu ( f, & self . lessons , self . selected_lesson ) ;
220- }
221223 AppState :: Running | AppState :: Completed => {
222224 if let Some ( session) = & self . session {
223225 let result = calculate_results ( session) ;
@@ -231,6 +233,7 @@ impl App {
231233 result. error_count ,
232234 ) ;
233235 } else {
236+ let lesson_name = & self . lessons [ self . selected_lesson ] . title ;
234237 ui:: render (
235238 f,
236239 session,
@@ -240,6 +243,7 @@ impl App {
240243 & self . keyboard_layout ,
241244 & self . stats . adaptive_analytics ,
242245 & self . keyboard_config ,
246+ lesson_name,
243247 ) ;
244248 }
245249 }
@@ -292,63 +296,75 @@ impl App {
292296 }
293297
294298 match self . state {
295- AppState :: DurationMenu => match key. code {
299+ AppState :: LessonMenu => match key. code {
296300 KeyCode :: Esc | KeyCode :: Char ( 'q' ) => {
301+ // Quit from first menu
297302 self . state = AppState :: Quit ;
298303 }
299304 KeyCode :: Up | KeyCode :: Char ( 'k' ) => {
300- if self . selected_duration > 0 {
301- self . selected_duration -= 1 ;
305+ if self . selected_lesson > 0 {
306+ self . selected_lesson -= 1 ;
307+ // Scroll up if selection goes above viewport
308+ if self . selected_lesson < self . lesson_scroll_offset {
309+ self . lesson_scroll_offset = self . selected_lesson ;
310+ }
302311 }
303312 }
304313 KeyCode :: Down | KeyCode :: Char ( 'j' ) => {
305- let max_idx = crate :: engine:: SessionDuration :: all ( ) . len ( ) - 1 ;
306- if self . selected_duration < max_idx {
307- self . selected_duration += 1 ;
314+ if self . selected_lesson < self . lessons . len ( ) - 1 {
315+ self . selected_lesson += 1 ;
316+ // Scroll down if selection goes below viewport (using conservative estimate of 20)
317+ let viewport_height = 20 ;
318+ if self . selected_lesson >= self . lesson_scroll_offset + viewport_height {
319+ self . lesson_scroll_offset = self . selected_lesson - viewport_height + 1 ;
320+ }
308321 }
309322 }
310323 KeyCode :: Enter | KeyCode :: Char ( ' ' ) => {
311- // Save selected duration and move to lesson menu
312- self . selected_duration_value =
313- crate :: engine:: SessionDuration :: all ( ) [ self . selected_duration ] ;
314- self . state = AppState :: LessonMenu ;
324+ // Go to duration menu after lesson selected
325+ self . state = AppState :: DurationMenu ;
326+ }
327+ KeyCode :: Char ( c) if c. is_ascii_digit ( ) => {
328+ // Allow direct selection with numbers
329+ if let Some ( digit) = c. to_digit ( 10 ) {
330+ let index = ( digit as usize ) . saturating_sub ( 1 ) ;
331+ if index < self . lessons . len ( ) {
332+ self . selected_lesson = index;
333+ // Go to duration menu after lesson selected
334+ self . state = AppState :: DurationMenu ;
335+ }
336+ }
315337 }
316338 _ => { }
317339 } ,
318- AppState :: LessonMenu => match key. code {
340+ AppState :: DurationMenu => match key. code {
319341 KeyCode :: Esc | KeyCode :: Char ( 'q' ) => {
320- // Go back to duration menu
321- self . state = AppState :: DurationMenu ;
342+ // Go back to lesson menu
343+ self . state = AppState :: LessonMenu ;
322344 }
323345 KeyCode :: Up | KeyCode :: Char ( 'k' ) => {
324- if self . selected_lesson > 0 {
325- self . selected_lesson -= 1 ;
346+ if self . selected_duration > 0 {
347+ self . selected_duration -= 1 ;
326348 }
327349 }
328350 KeyCode :: Down | KeyCode :: Char ( 'j' ) => {
329- if self . selected_lesson < self . lessons . len ( ) - 1 {
330- self . selected_lesson += 1 ;
351+ let max_idx = crate :: engine:: SessionDuration :: all ( ) . len ( ) - 1 ;
352+ if self . selected_duration < max_idx {
353+ self . selected_duration += 1 ;
331354 }
332355 }
333356 KeyCode :: Enter | KeyCode :: Char ( ' ' ) => {
357+ // Save selected duration and start lesson
358+ self . selected_duration_value =
359+ crate :: engine:: SessionDuration :: all ( ) [ self . selected_duration ] ;
334360 self . start_lesson ( self . selected_lesson ) ;
335361 }
336- KeyCode :: Char ( c) if c. is_ascii_digit ( ) => {
337- // Allow direct selection with numbers 1-6
338- if let Some ( digit) = c. to_digit ( 10 ) {
339- let index = ( digit as usize ) . saturating_sub ( 1 ) ;
340- if index < self . lessons . len ( ) {
341- self . selected_lesson = index;
342- self . start_lesson ( index) ;
343- }
344- }
345- }
346362 _ => { }
347363 } ,
348364 AppState :: Running => match key. code {
349365 KeyCode :: Esc => {
350- // Return to duration menu (discard session)
351- self . state = AppState :: DurationMenu ;
366+ // Return to lesson menu (discard session)
367+ self . state = AppState :: LessonMenu ;
352368 self . session = None ;
353369 }
354370 KeyCode :: Tab => {
@@ -383,13 +399,13 @@ impl App {
383399 AppState :: Completed => {
384400 match key. code {
385401 KeyCode :: Char ( 'q' ) | KeyCode :: Esc => {
386- // Return to duration menu
387- self . state = AppState :: DurationMenu ;
402+ // Return to lesson menu
403+ self . state = AppState :: LessonMenu ;
388404 self . session = None ;
389405 }
390406 KeyCode :: Char ( 'r' ) => {
391- // Restart same lesson with same duration
392- self . start_lesson ( self . selected_lesson ) ;
407+ // Re-select duration for restart
408+ self . state = AppState :: DurationMenu ;
393409 }
394410 _ => { }
395411 }
0 commit comments