1818//! use gittype::domain::events::EventBus;
1919//! use gittype::presentation::tui::ScreenManager;
2020//! use gittype::presentation::tui::screens::TitleScreen;
21+ //! use gittype::presentation::game::GameData;
22+ //! use ratatui::backend::CrosstermBackend;
23+ //! use ratatui::Terminal;
24+ //! use std::io::stdout;
2125//!
2226//! fn example() -> gittype::Result<()> {
2327//! let event_bus = EventBus::new();
2428//! let screen = TitleScreen::new(event_bus.clone());
29+ //! let game_data = GameData::instance();
30+ //! let backend = CrosstermBackend::new(stdout());
31+ //! let terminal = Terminal::new(backend).unwrap();
2532//!
26- //! let mut manager = ScreenManager::new(event_bus);
33+ //! let mut manager = ScreenManager::new(event_bus, game_data, terminal );
2734//! manager.register_screen(screen);
2835//! manager.initialize_terminal()?;
2936//! manager.run()
@@ -53,7 +60,7 @@ use crossterm::style::ResetColor;
5360use crossterm:: terminal:: {
5461 disable_raw_mode, enable_raw_mode, Clear , ClearType , EnterAlternateScreen , LeaveAlternateScreen ,
5562} ;
56- use ratatui:: backend:: CrosstermBackend ;
63+ use ratatui:: backend:: { Backend , CrosstermBackend } ;
5764use ratatui:: Terminal ;
5865use std:: collections:: HashMap ;
5966use std:: io:: { stdout, Stdout , Write } ;
@@ -62,37 +69,49 @@ use std::thread::sleep;
6269use std:: time:: { Duration , Instant } ;
6370
6471/// Central manager for screen transitions, rendering, and input handling
65- pub struct ScreenManager {
72+ pub struct ScreenManager < B : Backend + Send + ' static = CrosstermBackend < Stdout > > {
6673 screens : HashMap < ScreenType , Box < dyn Screen > > ,
6774 screen_stack : Vec < ScreenType > ,
6875 current_screen_type : ScreenType ,
6976 terminal_initialized : bool ,
7077 last_update : Instant ,
71- ratatui_terminal : Option < Terminal < CrosstermBackend < Stdout > > > ,
78+ ratatui_terminal : Terminal < B > ,
7279 exit_requested : bool ,
7380
7481 // Pending screen transition - shared across threads
7582 pending_transition : Arc < Mutex < Option < ScreenTransition > > > ,
7683
7784 // Event bus for UI events
7885 event_bus : EventBus ,
86+
87+ // Game data
88+ game_data : Arc < Mutex < GameData > > ,
7989}
8090
81- impl ScreenManager {
82- pub fn new ( event_bus : EventBus ) -> Self {
91+ impl < B : Backend + Send + ' static > ScreenManager < B > {
92+ pub fn new (
93+ event_bus : EventBus ,
94+ game_data : Arc < Mutex < GameData > > ,
95+ terminal : Terminal < B > ,
96+ ) -> Self {
8397 Self {
8498 screens : HashMap :: new ( ) ,
8599 screen_stack : Vec :: new ( ) ,
86100 current_screen_type : ScreenType :: Title ,
87101 terminal_initialized : false ,
88102 last_update : Instant :: now ( ) ,
89- ratatui_terminal : None ,
103+ ratatui_terminal : terminal ,
90104 exit_requested : false ,
91105 pending_transition : Arc :: new ( Mutex :: new ( None ) ) ,
92106 event_bus : event_bus. clone ( ) ,
107+ game_data,
93108 }
94109 }
95110
111+ fn get_game_data ( & self ) -> Arc < Mutex < GameData > > {
112+ self . game_data . clone ( )
113+ }
114+
96115 pub fn get_event_bus ( & self ) -> EventBus {
97116 self . event_bus . clone ( )
98117 }
@@ -222,10 +241,7 @@ impl ScreenManager {
222241 self . terminal_initialized = false ;
223242 }
224243
225- // Clean up ratatui terminal
226- if let Some ( _terminal) = self . ratatui_terminal . take ( ) {
227- // Terminal cleanup is handled automatically when dropped
228- }
244+ // Ratatui terminal cleanup is handled automatically when dropped
229245
230246 Ok ( ( ) )
231247 }
@@ -264,7 +280,9 @@ impl ScreenManager {
264280 log:: info!( "Initializing screen: {:?}" , self . current_screen_type) ;
265281
266282 // Get data using provider and call init_with_data
267- let data = Self :: get_screen_data ( self . current_screen_type . clone ( ) ) ?;
283+ // If get_screen_data fails (e.g., for test screens), use empty data
284+ let data = Self :: get_screen_data ( self . current_screen_type . clone ( ) )
285+ . unwrap_or_else ( |_| Box :: new ( ( ) ) ) ;
268286 new_screen. init_with_data ( data) . map_err ( |e| {
269287 GitTypeError :: ScreenInitializationError ( format ! (
270288 "Failed to initialize screen {:?}: {}" ,
@@ -318,11 +336,9 @@ impl ScreenManager {
318336
319337 fn clear_screen ( & mut self ) -> Result < ( ) > {
320338 // Clear the ratatui terminal buffer
321- if let Some ( terminal) = & mut self . ratatui_terminal {
322- terminal. clear ( ) . map_err ( |e| {
323- GitTypeError :: TerminalError ( format ! ( "Failed to clear ratatui terminal: {}" , e) )
324- } ) ?;
325- }
339+ self . ratatui_terminal . clear ( ) . map_err ( |e| {
340+ GitTypeError :: TerminalError ( format ! ( "Failed to clear ratatui terminal: {}" , e) )
341+ } ) ?;
326342 Ok ( ( ) )
327343 }
328344
@@ -507,6 +523,9 @@ impl ScreenManager {
507523 }
508524
509525 fn update_and_render ( & mut self ) -> Result < ( ) > {
526+ // Get game_data before mutable borrow to avoid borrow checker error
527+ let game_data = self . get_game_data ( ) ;
528+
510529 if let Some ( screen) = self . screens . get_mut ( & self . current_screen_type ) {
511530 let strategy = screen. get_update_strategy ( ) ;
512531 let now = Instant :: now ( ) ;
@@ -525,8 +544,13 @@ impl ScreenManager {
525544
526545 // Special handling for LoadingScreen auto-transition
527546 if self . current_screen_type == ScreenType :: Loading && !needs_render {
547+ let data = game_data. lock ( ) . unwrap ( ) ;
548+ let loading_completed = data. loading_completed ;
549+ let loading_failed = data. loading_failed ;
550+ drop ( data) ;
551+
528552 // LoadingScreen completed, transition to Title
529- if GameData :: is_loading_completed ( ) {
553+ if loading_completed {
530554 // Update TitleScreen data with challenge counts after loading is complete
531555 self . handle_transition ( ScreenTransition :: Replace ( ScreenType :: Title ) ) ?;
532556
@@ -537,7 +561,7 @@ impl ScreenManager {
537561 }
538562
539563 return Ok ( ( ) ) ;
540- } else if GameData :: is_loading_failed ( ) {
564+ } else if loading_failed {
541565 // Could transition to an error screen or back to title
542566 self . handle_transition ( ScreenTransition :: Replace ( ScreenType :: Title ) ) ?;
543567 return Ok ( ( ) ) ;
@@ -620,26 +644,14 @@ impl ScreenManager {
620644 }
621645
622646 pub fn render_current_screen ( & mut self ) -> Result < ( ) > {
623- // Initialize ratatui terminal if not already done
624- if self . ratatui_terminal . is_none ( ) {
625- let backend = CrosstermBackend :: new ( stdout ( ) ) ;
626- let terminal = Terminal :: new ( backend) . map_err ( |e| {
627- GitTypeError :: TerminalError ( format ! ( "Failed to create ratatui terminal: {}" , e) )
628- } ) ?;
629- self . ratatui_terminal = Some ( terminal) ;
630- }
631-
632- // Use the persistent terminal instance
633- if let Some ( terminal) = & mut self . ratatui_terminal {
634- if let Some ( screen) = self . screens . get_mut ( & self . current_screen_type ) {
635- terminal
636- . draw ( |frame| {
637- let _ = screen. render_ratatui ( frame) ;
638- } )
639- . map_err ( |e| {
640- GitTypeError :: TerminalError ( format ! ( "Failed to draw ratatui frame: {}" , e) )
641- } ) ?;
642- }
647+ if let Some ( screen) = self . screens . get_mut ( & self . current_screen_type ) {
648+ self . ratatui_terminal
649+ . draw ( |frame| {
650+ let _ = screen. render_ratatui ( frame) ;
651+ } )
652+ . map_err ( |e| {
653+ GitTypeError :: TerminalError ( format ! ( "Failed to draw ratatui frame: {}" , e) )
654+ } ) ?;
643655 }
644656
645657 Ok ( ( ) )
@@ -696,14 +708,16 @@ impl ScreenManager {
696708 }
697709}
698710
699- impl Drop for ScreenManager {
711+ impl < B : Backend + Send + ' static > Drop for ScreenManager < B > {
700712 fn drop ( & mut self ) {
701713 let _ = self . cleanup_terminal ( ) ;
702714 }
703715}
704716
705- impl Default for ScreenManager {
717+ impl Default for ScreenManager < CrosstermBackend < Stdout > > {
706718 fn default ( ) -> Self {
707- Self :: new ( EventBus :: new ( ) )
719+ let backend = CrosstermBackend :: new ( stdout ( ) ) ;
720+ let terminal = Terminal :: new ( backend) . expect ( "Failed to create terminal" ) ;
721+ Self :: new ( EventBus :: new ( ) , GameData :: instance ( ) , terminal)
708722 }
709723}
0 commit comments