Skip to content

Commit 2196197

Browse files
unhappychoiceclaude
andcommitted
feat: implement ScreenManager core architecture and UpdateStrategy system
- Add centralized ScreenManager for screen transitions and rendering - Implement Screen trait with dual rendering support (crossterm/ratatui) - Add UpdateStrategy system (InputOnly/TimeBased/Hybrid) for flexible screen updates - Add terminal lifecycle management with proper setup/cleanup - Create BasicScreen as example implementation - Add comprehensive documentation and demo example Phase 1 & 2 of issue #43 ScreenManager refactoring complete. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 4c22865 commit 2196197

File tree

5 files changed

+741
-0
lines changed

5 files changed

+741
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ exclude = [
2626
name = "gittype"
2727
path = "src/main.rs"
2828

29+
[[example]]
30+
name = "screen_manager_demo"
31+
path = "examples/screen_manager_demo.rs"
32+
2933
[dependencies]
3034
clap = { version = "4.0", features = ["derive"] }
3135
tree-sitter = "0.25"
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# ScreenManager Architecture
2+
3+
## Overview
4+
5+
The ScreenManager is a centralized system for managing screen transitions, rendering loops, input handling, and terminal lifecycle in GitType. This architecture provides a unified approach for handling all screen-related operations and supports both crossterm and ratatui rendering backends.
6+
7+
## Key Components
8+
9+
### ScreenManager
10+
11+
The core component that coordinates all screen operations:
12+
13+
```rust
14+
pub struct ScreenManager {
15+
screens: HashMap<ScreenType, Box<dyn Screen>>,
16+
screen_stack: Vec<ScreenType>,
17+
current_screen_type: ScreenType,
18+
should_exit: bool,
19+
terminal_initialized: bool,
20+
last_update: Instant,
21+
render_backend: RenderBackend,
22+
}
23+
```
24+
25+
Features:
26+
- **Centralized Rendering Loop**: ScreenManager owns and manages the main rendering loop
27+
- **Input Handling**: ScreenManager handles all keyboard input events and dispatches to current screen
28+
- **Screen Management**: Uses screen stack for nested screens/dialogs
29+
- **Terminal Lifecycle**: Manages raw mode, cursor visibility, and alternate screen
30+
- **Dual Rendering Support**: Supports both crossterm and ratatui backends
31+
32+
### Screen Trait
33+
34+
All screens implement the `Screen` trait:
35+
36+
```rust
37+
pub trait Screen: Send {
38+
fn init(&mut self) -> Result<()>;
39+
fn handle_key_event(&mut self, key_event: KeyEvent) -> Result<ScreenTransition>;
40+
fn render_crossterm(&self, stdout: &mut Stdout) -> Result<()>;
41+
fn render_ratatui(&self, _frame: &mut ratatui::Frame) -> Result<()>;
42+
fn cleanup(&mut self) -> Result<()>;
43+
fn should_exit(&self) -> bool;
44+
fn get_update_strategy(&self) -> UpdateStrategy;
45+
fn update(&mut self) -> Result<bool>;
46+
}
47+
```
48+
49+
### Update Strategy System
50+
51+
Screens can define how they should be updated:
52+
53+
```rust
54+
pub enum UpdateStrategy {
55+
InputOnly, // Update only on input events
56+
TimeBased(Duration), // Update at regular intervals
57+
Hybrid { // Both input and time-based
58+
interval: Duration,
59+
input_priority: bool,
60+
},
61+
}
62+
```
63+
64+
#### Strategy Examples:
65+
- **Title Screen**: `InputOnly` - Only updates when user presses keys
66+
- **Loading Screen**: `TimeBased(Duration::from_millis(100))` - Updates progress regularly
67+
- **Typing Screen**: `Hybrid { interval: Duration::from_millis(500), input_priority: true }` - Updates on input + cursor blink
68+
- **Animation Screen**: `TimeBased(Duration::from_millis(50))` - Smooth animation updates
69+
70+
### Screen Types
71+
72+
```rust
73+
pub enum ScreenType {
74+
Title, Loading, Typing, StageSummary, SessionSummary,
75+
ExitSummary, Cancel, Failure, History, Analytics,
76+
SessionDetail, Sharing, Animation, VersionCheck,
77+
InfoDialog, DetailsDialog,
78+
}
79+
```
80+
81+
### Screen Transitions
82+
83+
```rust
84+
pub enum ScreenTransition {
85+
None, // No transition
86+
Push(ScreenType), // Push new screen onto stack
87+
Pop, // Pop current screen from stack
88+
Replace(ScreenType), // Replace current screen
89+
PopTo(ScreenType), // Pop until reaching specific screen
90+
Exit, // Exit application
91+
}
92+
```
93+
94+
## Usage Example
95+
96+
```rust
97+
use gittype::game::{BasicScreen, ScreenManager, ScreenType, UpdateStrategy};
98+
99+
fn main() -> gittype::Result<()> {
100+
let mut screen_manager = ScreenManager::new();
101+
102+
// Create a screen with input-only updates
103+
let title_screen = BasicScreen::new(
104+
"My App".to_string(),
105+
vec!["Welcome!".to_string()],
106+
UpdateStrategy::InputOnly,
107+
);
108+
109+
// Register the screen
110+
screen_manager.register_screen(ScreenType::Title, Box::new(title_screen));
111+
112+
// Run the application
113+
screen_manager.run()?;
114+
115+
Ok(())
116+
}
117+
```
118+
119+
## Benefits
120+
121+
1. **Maintainability**: Centralized control makes code easier to understand and modify
122+
2. **Consistency**: All screens follow the same patterns and lifecycle
123+
3. **Performance**: Single rendering loop reduces overhead and improves responsiveness
124+
4. **Extensibility**: Adding new screens becomes straightforward with clear interfaces
125+
5. **Testing**: Easier to unit test individual screens and transitions
126+
6. **Error Handling**: Centralized error handling for screen-related issues
127+
7. **Flexibility**: Support for different rendering backends and update strategies
128+
8. **Terminal Stability**: Reduced terminal configuration overhead and more stable terminal state
129+
9. **Power Efficiency**: Screens can optimize their update frequency based on needs
130+
131+
## Implementation Strategy
132+
133+
### Phase 1: Core Architecture ✅
134+
- [x] Create `ScreenManager` with rendering loop and input handling
135+
- [x] Define `Screen` trait with dual rendering support and update strategies
136+
- [x] Implement `ScreenType` enum and transition system
137+
- [x] Add terminal lifecycle management
138+
139+
### Phase 2: Update Strategy System ✅
140+
- [x] Implement `UpdateStrategy` enum and logic
141+
- [x] Create timer-based update mechanism for time-driven screens
142+
- [x] Add hybrid update support for complex screens
143+
- [x] Optimize rendering pipeline to avoid unnecessary updates
144+
145+
### Phase 3: Screen Migration (In Progress)
146+
- [ ] Refactor existing screens to implement new `Screen` trait
147+
- [ ] Move rendering logic to use centralized system
148+
- [ ] Update input handling to use event dispatching
149+
- [ ] Assign appropriate update strategies to each screen
150+
151+
### Phase 4: Integration (Planned)
152+
- [ ] Integrate ScreenManager into StageManager
153+
- [ ] Remove duplicate rendering and input code
154+
- [ ] Test all screen transitions and functionality
155+
- [ ] Optimize terminal initialization/cleanup
156+
157+
### Phase 5: Optimization (Planned)
158+
- [ ] Performance tuning of rendering loop
159+
- [ ] Add ratatui rendering implementations
160+
- [ ] Fine-tune update strategies for optimal performance
161+
- [ ] Documentation and testing
162+
163+
## Best Practices
164+
165+
1. **Screen Lifecycle**: Always implement proper init/cleanup in screens
166+
2. **Update Strategy**: Choose the most appropriate update strategy for each screen
167+
3. **Error Handling**: Handle errors gracefully in screen implementations
168+
4. **Resource Management**: Clean up resources in the cleanup method
169+
5. **Performance**: Avoid unnecessary renders by returning `false` from `update()` when no changes occur
170+
6. **Input Handling**: Use screen transitions to control navigation flow
171+
7. **Testing**: Test screens individually and integration with ScreenManager
172+
173+
## Migration Guide
174+
175+
To migrate existing screens to the new architecture:
176+
177+
1. Implement the `Screen` trait for your screen struct
178+
2. Move rendering logic to `render_crossterm()` method
179+
3. Move input handling to `handle_key_event()` method
180+
4. Define appropriate `UpdateStrategy` in `get_update_strategy()`
181+
5. Register screen with ScreenManager
182+
6. Remove old direct terminal management code
183+
184+
This architecture provides a solid foundation for building complex terminal applications with proper separation of concerns and consistent behavior across all screens.

examples/screen_manager_demo.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use gittype::game::{BasicScreen, ScreenManager, ScreenType, UpdateStrategy};
2+
3+
fn main() -> gittype::Result<()> {
4+
let mut screen_manager = ScreenManager::new();
5+
6+
let title_screen = BasicScreen::new(
7+
"ScreenManager Demo".to_string(),
8+
vec![
9+
"Welcome to the new ScreenManager architecture!".to_string(),
10+
"".to_string(),
11+
"Features implemented:".to_string(),
12+
"✓ Centralized rendering loop".to_string(),
13+
"✓ Input handling with event dispatching".to_string(),
14+
"✓ Screen management with stack support".to_string(),
15+
"✓ Dual rendering support (crossterm/ratatui)".to_string(),
16+
"✓ Flexible update strategies".to_string(),
17+
"✓ Terminal lifecycle management".to_string(),
18+
"".to_string(),
19+
"Update Strategies:".to_string(),
20+
"• InputOnly - Updates only on user input".to_string(),
21+
"• TimeBased - Updates at regular intervals".to_string(),
22+
"• Hybrid - Combines both strategies".to_string(),
23+
"".to_string(),
24+
"This screen uses InputOnly strategy.".to_string(),
25+
],
26+
UpdateStrategy::InputOnly,
27+
);
28+
29+
screen_manager.register_screen(ScreenType::Title, Box::new(title_screen));
30+
31+
screen_manager.run()?;
32+
33+
Ok(())
34+
}

src/game/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pub mod ascii_rank_titles_generated;
33
pub mod context_loader;
44
pub mod models;
55
pub mod rank_messages;
6+
pub mod screen_manager;
67
pub mod screens;
78
pub mod stage_builder;
89
pub mod stage_manager;
@@ -13,6 +14,7 @@ pub mod typing_core;
1314

1415
pub use crate::models::Challenge;
1516
pub use crate::models::SessionResult;
17+
pub use screen_manager::{BasicScreen, RenderBackend, Screen, ScreenManager, ScreenTransition, ScreenType, UpdateStrategy};
1618
pub use screens::TypingScreen;
1719
pub use stage_builder::{DifficultyLevel, GameMode, StageBuilder, StageConfig};
1820
pub use stage_manager::StageManager;

0 commit comments

Comments
 (0)