@@ -9,124 +9,16 @@ use ratatui::prelude::*;
99use ratatui:: widgets:: ListState ;
1010use tokio:: task:: JoinHandle ;
1111
12- use crate :: models:: { AppState , GpuItem , LeaderboardItem , SubmissionModeItem } ;
13- use crate :: views:: selection:: SelectionItem ;
12+ use crate :: models:: {
13+ AppState , GpuItem , GpuSelectionView , LeaderboardItem , LeaderboardSelectionView ,
14+ SelectionAction , SelectionItem , SelectionView , SubmissionModeItem , SubmissionModeSelectionView ,
15+ } ;
1416use crate :: service;
1517use crate :: utils;
18+ use crate :: views:: file_selection_page:: { FileSelectionAction , FileSelectionView } ;
1619use crate :: views:: loading_page:: { LoadingPage , LoadingPageState } ;
17- use crate :: views:: result_page:: { ResultPageState , ResultView , ResultAction } ;
18- use crate :: views:: welcome_page:: { WelcomeView , WelcomeAction } ;
19- use crate :: views:: file_selection_page:: { FileSelectionView , FileSelectionAction } ;
20- use crate :: views:: selection:: { SelectionView , SelectionAction } ;
21-
22- // Selection view implementations for different types
23- pub struct LeaderboardSelectionView {
24- leaderboards : Vec < LeaderboardItem > ,
25- leaderboards_state : ListState ,
26- }
27-
28- impl LeaderboardSelectionView {
29- pub fn new ( leaderboards : Vec < LeaderboardItem > ) -> Self {
30- let mut state = ListState :: default ( ) ;
31- state. select ( Some ( 0 ) ) ;
32- Self {
33- leaderboards,
34- leaderboards_state : state,
35- }
36- }
37- }
38-
39- impl SelectionView < LeaderboardItem > for LeaderboardSelectionView {
40- fn title ( & self ) -> String {
41- "Select Leaderboard" . to_string ( )
42- }
43-
44- fn items ( & self ) -> & [ LeaderboardItem ] {
45- & self . leaderboards
46- }
47-
48- fn state ( & self ) -> & ListState {
49- & self . leaderboards_state
50- }
51-
52- fn state_mut ( & mut self ) -> & mut ListState {
53- & mut self . leaderboards_state
54- }
55- }
56-
57- pub struct GpuSelectionView {
58- gpus : Vec < GpuItem > ,
59- gpus_state : ListState ,
60- leaderboard_name : String ,
61- }
62-
63- impl GpuSelectionView {
64- pub fn new ( gpus : Vec < GpuItem > , leaderboard_name : String ) -> Self {
65- let mut state = ListState :: default ( ) ;
66- state. select ( Some ( 0 ) ) ;
67- Self {
68- gpus,
69- gpus_state : state,
70- leaderboard_name,
71- }
72- }
73- }
74-
75- impl SelectionView < GpuItem > for GpuSelectionView {
76- fn title ( & self ) -> String {
77- format ! ( "Select GPU for '{}'" , self . leaderboard_name)
78- }
79-
80- fn items ( & self ) -> & [ GpuItem ] {
81- & self . gpus
82- }
83-
84- fn state ( & self ) -> & ListState {
85- & self . gpus_state
86- }
87-
88- fn state_mut ( & mut self ) -> & mut ListState {
89- & mut self . gpus_state
90- }
91- }
92-
93- pub struct SubmissionModeSelectionView {
94- submission_modes : Vec < SubmissionModeItem > ,
95- submission_modes_state : ListState ,
96- leaderboard_name : String ,
97- gpu_name : String ,
98- }
99-
100- impl SubmissionModeSelectionView {
101- pub fn new ( submission_modes : Vec < SubmissionModeItem > , leaderboard_name : String , gpu_name : String ) -> Self {
102- let mut state = ListState :: default ( ) ;
103- state. select ( Some ( 0 ) ) ;
104- Self {
105- submission_modes,
106- submission_modes_state : state,
107- leaderboard_name,
108- gpu_name,
109- }
110- }
111- }
112-
113- impl SelectionView < SubmissionModeItem > for SubmissionModeSelectionView {
114- fn title ( & self ) -> String {
115- format ! ( "Select Submission Mode for '{}' on '{}'" , self . leaderboard_name, self . gpu_name)
116- }
117-
118- fn items ( & self ) -> & [ SubmissionModeItem ] {
119- & self . submission_modes
120- }
121-
122- fn state ( & self ) -> & ListState {
123- & self . submission_modes_state
124- }
125-
126- fn state_mut ( & mut self ) -> & mut ListState {
127- & mut self . submission_modes_state
128- }
129- }
20+ use crate :: views:: result_page:: { ResultAction , ResultPageState , ResultView } ;
21+ use crate :: views:: welcome_page:: { WelcomeAction , WelcomeView } ;
13022
13123#[ derive( Default ) ]
13224pub struct App {
@@ -293,7 +185,9 @@ impl App {
293185 return Ok ( true ) ;
294186 }
295187 WelcomeAction :: ViewHistory => {
296- self . show_error ( "View History feature is not yet implemented" . to_string ( ) ) ;
188+ self . show_error (
189+ "View History feature is not yet implemented" . to_string ( ) ,
190+ ) ;
297191 return Ok ( true ) ;
298192 }
299193 WelcomeAction :: Handled => return Ok ( true ) ,
@@ -306,28 +200,35 @@ impl App {
306200 match view. handle_key_event ( key) ? {
307201 FileSelectionAction :: FileSelected ( filepath) => {
308202 self . filepath = filepath. clone ( ) ;
309-
203+
310204 // Parse directives from the selected file
311205 match utils:: get_popcorn_directives ( & filepath) {
312206 Ok ( ( directives, has_multiple_gpus) ) => {
313207 if has_multiple_gpus {
314208 self . show_error ( "Multiple GPUs are not supported yet. Please specify only one GPU." . to_string ( ) ) ;
315209 return Ok ( true ) ;
316210 }
317-
211+
318212 // Apply directives to determine next state
319213 self . initialize_with_directives ( directives) ;
320-
214+
321215 // Spawn appropriate task based on the new state
216+ // TODO: make spawn_x tasks also show error if they fail, a lot of duplicate code
322217 match self . app_state {
323218 AppState :: LeaderboardSelection => {
324219 if let Err ( e) = self . spawn_load_leaderboards ( ) {
325- self . show_error ( format ! ( "Error starting leaderboard fetch: {}" , e) ) ;
220+ self . show_error ( format ! (
221+ "Error starting leaderboard fetch: {}" ,
222+ e
223+ ) ) ;
326224 }
327225 }
328226 AppState :: GpuSelection => {
329227 if let Err ( e) = self . spawn_load_gpus ( ) {
330- self . show_error ( format ! ( "Error starting GPU fetch: {}" , e) ) ;
228+ self . show_error ( format ! (
229+ "Error starting GPU fetch: {}" ,
230+ e
231+ ) ) ;
331232 }
332233 }
333234 AppState :: SubmissionModeSelection => {
@@ -337,15 +238,17 @@ impl App {
337238 }
338239 }
339240 Err ( e) => {
340- self . show_error ( format ! ( "Error parsing file directives: {}" , e) ) ;
241+ self . show_error ( format ! (
242+ "Error parsing file directives: {}" ,
243+ e
244+ ) ) ;
341245 return Ok ( true ) ;
342246 }
343247 }
344248 return Ok ( true ) ;
345249 }
346250 FileSelectionAction :: Handled => return Ok ( true ) ,
347251 FileSelectionAction :: NotHandled => return Ok ( false ) ,
348- _ => return Ok ( true ) ,
349252 }
350253 }
351254 }
@@ -354,7 +257,7 @@ impl App {
354257 match view. handle_key_event ( key) {
355258 SelectionAction :: Selected ( idx) => {
356259 self . selected_leaderboard = Some ( view. items ( ) [ idx] . title ( ) . to_string ( ) ) ;
357-
260+
358261 if self . selected_gpu . is_none ( ) {
359262 self . app_state = AppState :: GpuSelection ;
360263 if let Err ( e) = self . spawn_load_gpus ( ) {
@@ -492,7 +395,7 @@ impl App {
492395 Ok ( Ok ( leaderboards) ) => {
493396 self . leaderboards = leaderboards. clone ( ) ;
494397 self . leaderboard_view = Some ( LeaderboardSelectionView :: new ( leaderboards) ) ;
495-
398+
496399 if let Some ( selected_name) = & self . selected_leaderboard {
497400 if let Some ( index) = self
498401 . leaderboards
@@ -504,11 +407,12 @@ impl App {
504407 }
505408 if self . selected_gpu . is_some ( ) {
506409 self . app_state = AppState :: SubmissionModeSelection ;
507- self . submission_mode_view = Some ( SubmissionModeSelectionView :: new (
508- self . submission_modes . clone ( ) ,
509- self . selected_leaderboard . as_ref ( ) . unwrap ( ) . clone ( ) ,
510- self . selected_gpu . as_ref ( ) . unwrap ( ) . clone ( ) ,
511- ) ) ;
410+ self . submission_mode_view =
411+ Some ( SubmissionModeSelectionView :: new (
412+ self . submission_modes . clone ( ) ,
413+ self . selected_leaderboard . as_ref ( ) . unwrap ( ) . clone ( ) ,
414+ self . selected_gpu . as_ref ( ) . unwrap ( ) . clone ( ) ,
415+ ) ) ;
512416 } else {
513417 self . app_state = AppState :: GpuSelection ;
514418 if let Err ( e) = self . spawn_load_gpus ( ) {
@@ -527,9 +431,7 @@ impl App {
527431 view. state_mut ( ) . select ( Some ( 0 ) ) ;
528432 }
529433 }
530- Ok ( Err ( e) ) => {
531- self . show_error ( format ! ( "Error fetching leaderboards: {}" , e) )
532- }
434+ Ok ( Err ( e) ) => self . show_error ( format ! ( "Error fetching leaderboards: {}" , e) ) ,
533435 Err ( e) => self . show_error ( format ! ( "Task join error: {}" , e) ) ,
534436 }
535437 }
@@ -545,9 +447,12 @@ impl App {
545447 self . gpus = gpus. clone ( ) ;
546448 self . gpu_view = Some ( GpuSelectionView :: new (
547449 gpus,
548- self . selected_leaderboard . as_ref ( ) . unwrap_or ( & "N/A" . to_string ( ) ) . clone ( ) ,
450+ self . selected_leaderboard
451+ . as_ref ( )
452+ . unwrap_or ( & "N/A" . to_string ( ) )
453+ . clone ( ) ,
549454 ) ) ;
550-
455+
551456 if let Some ( selected_name) = & self . selected_gpu {
552457 if let Some ( index) = self
553458 . gpus
@@ -589,24 +494,28 @@ impl App {
589494 Ok ( Ok ( status) ) => {
590495 // Process the status text
591496 let trimmed = status. trim ( ) ;
592- let content = if trimmed. starts_with ( '[' ) && trimmed. ends_with ( ']' ) && trimmed. len ( ) >= 2 {
497+ let content = if trimmed. starts_with ( '[' )
498+ && trimmed. ends_with ( ']' )
499+ && trimmed. len ( ) >= 2
500+ {
593501 & trimmed[ 1 ..trimmed. len ( ) - 1 ]
594502 } else {
595503 trimmed
596504 } ;
597505 let content = content. replace ( "\\ n" , "\n " ) ;
598-
506+
599507 // Create result view and transition to showing result
600508 self . result_view = Some ( ResultView :: new ( content) ) ;
601509 self . app_state = AppState :: ShowingResult ;
602510 }
603511 Ok ( Err ( e) ) => {
604512 // Show error in result view
605- self . result_view = Some ( ResultView :: new ( format ! ( "Submission error: {}" , e) ) ) ;
513+ self . result_view =
514+ Some ( ResultView :: new ( format ! ( "Submission error: {}" , e) ) ) ;
606515 self . app_state = AppState :: ShowingResult ;
607516 }
608517 Err ( e) => {
609- // Show task join error in result view
518+ // Show task join error in result view
610519 self . result_view = Some ( ResultView :: new ( format ! ( "Task join error: {}" , e) ) ) ;
611520 self . app_state = AppState :: ShowingResult ;
612521 }
@@ -690,7 +599,7 @@ pub async fn run_submit_tui(
690599
691600 // First apply directives as defaults
692601 app. initialize_with_directives ( directives) ;
693-
602+
694603 // Then override with CLI flags if provided
695604 if let Some ( gpu_flag) = gpu {
696605 app. selected_gpu = Some ( gpu_flag) ;
@@ -761,4 +670,4 @@ pub async fn run_submit_tui(
761670 terminal. show_cursor ( ) ?;
762671
763672 Ok ( ( ) )
764- }
673+ }
0 commit comments