Files
sus-manager/ui/src/app.rs
2025-12-14 21:34:06 +08:00

89 lines
2.6 KiB
Rust
Executable File

use crate::event::{AppEvent, EventHandler};
use crate::widgets::views::{AppView, MainView};
use color_eyre::Result;
use crossterm::event::{Event};
use ratatui::{DefaultTerminal, Frame};
use std::time::Duration;
use color_eyre::eyre::eyre;
use db::RocksDBFactory;
use models::config::ApplicationConfig;
use models::dlsite::{DLSiteCategory, DLSiteGenre, DLSiteManiax};
pub(crate) struct App {
events: EventHandler,
state: AppState,
db_factory: RocksDBFactory
}
#[derive(Clone)]
pub struct AppState {
view: Option<AppView>,
}
impl App {
pub async fn create() -> Result<Self> {
let config = ApplicationConfig::get_config()?;
let mut db_factory = RocksDBFactory::default();
db_factory.register::<DLSiteManiax>();
db_factory.register::<DLSiteGenre>();
db_factory.register::<DLSiteCategory>();
let state = AppState {
view: Some(AppView::Main(MainView::new(db_factory.clone())?)),
};
let app = Self {
events: EventHandler::new(Duration::from_millis(config.basic_config.tick_rate)),
state,
db_factory
};
Ok(app)
}
pub async fn run(mut self, terminal: &mut DefaultTerminal) -> Result<()> {
loop {
let event = self.events.next().await?;
self.update(event)?;
let Some(current_view) = self.state.view.as_mut() else {
continue;
};
let view = current_view.get_view();
if !view.is_running() { break Ok(()) }
terminal.draw(|frame| self.draw(frame))?;
}
}
fn update(&mut self, event: AppEvent) -> Result<()> {
if let AppEvent::Raw(cross_event) = event {
self.handle_event(&cross_event)?;
}
Ok(())
}
fn handle_event(&mut self, key: &Event) -> Result<()> {
let Some(current_view) = self.state.view.as_mut() else {
return Err(eyre!("there is no view"));
};
let view = current_view.get_view();
view.handle_input(key)?;
Ok(())
}
fn draw(&mut self, frame: &mut Frame) {
let Some(current_view) = self.state.view.as_mut() else {
return;
};
let view = current_view.get_view();
if let Some(pos) = view.screen_cursor() {
frame.set_cursor_position(pos);
}
match current_view {
AppView::Main(main_view) => {
frame.render_stateful_widget(
main_view.clone(),
frame.area(),
&mut main_view.state,
);
}
}
}
}