From d033d8b93fa81235bd04a576b0e2ec8fd1634b8a Mon Sep 17 00:00:00 2001 From: fromost Date: Wed, 15 Oct 2025 21:57:33 +0800 Subject: [PATCH] Reformat code --- src/app.rs | 53 +++++++++++++--------- src/cli.rs | 53 ++++++++++------------ src/config/mod.rs | 47 +++++++++++++------ src/config/types.rs | 8 ++-- src/constants.rs | 19 ++++---- src/crawler/dlsite.rs | 4 +- src/crawler/mod.rs | 32 +++++++------ src/event.rs | 12 ++--- src/helpers/mod.rs | 1 + src/main.rs | 14 +++--- src/types/game.rs | 2 +- src/types/mod.rs | 2 +- src/widgets/components/mod.rs | 2 +- src/widgets/components/textarea.rs | 53 ++++++++++------------ src/widgets/mod.rs | 2 +- src/widgets/popups/folder.rs | 16 +++---- src/widgets/popups/mod.rs | 2 +- src/widgets/views/main_view.rs | 73 +++++++++++++++--------------- src/widgets/views/mod.rs | 5 +- 19 files changed, 206 insertions(+), 194 deletions(-) diff --git a/src/app.rs b/src/app.rs index faf567d..e646735 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,16 +1,16 @@ -use std::any::{Any}; -use crate::event::{AppEvent, EventHandler}; -use ratatui::{DefaultTerminal, Frame}; -use std::time::Duration; -use color_eyre::Result; -use crossterm::event::{Event, KeyEvent}; -use crossterm::event::Event as CrosstermEvent; -use diesel::{Connection, SqliteConnection}; -use rat_cursor::HasScreenCursor; use crate::config::types::ApplicationConfig; use crate::constants::{APP_CONFIG_DIR, APP_CONIFG_FILE_PATH, APP_DATA_DIR}; -use crate::widgets::views::{View}; +use crate::event::{AppEvent, EventHandler}; use crate::widgets::views::MainView; +use crate::widgets::views::View; +use color_eyre::Result; +use crossterm::event::Event as CrosstermEvent; +use crossterm::event::{Event, KeyEvent}; +use diesel::{Connection, SqliteConnection}; +use rat_cursor::HasScreenCursor; +use ratatui::{DefaultTerminal, Frame}; +use std::any::Any; +use std::time::Duration; pub(crate) struct App { events: EventHandler, @@ -25,17 +25,21 @@ struct AppState { impl App { pub async fn create() -> Self { - let app_conf = - if APP_CONIFG_FILE_PATH.exists() { ApplicationConfig::from_file(&APP_CONIFG_FILE_PATH).unwrap() } - else { ApplicationConfig::new() }; + let app_conf = if APP_CONIFG_FILE_PATH.exists() { + ApplicationConfig::from_file(&APP_CONIFG_FILE_PATH).unwrap() + } else { + ApplicationConfig::new() + }; Self::initialize_folders(); let db_conn = Self::establish_db_connection(app_conf.clone()); - let state = AppState { view: Some(Box::new(MainView::new(&app_conf))) }; + let state = AppState { + view: Some(Box::new(MainView::new(&app_conf))), + }; Self { events: EventHandler::new(Duration::from_millis(app_conf.basic_config.tick_rate)), db_connection: db_conn, app_config: app_conf, - state + state, } } @@ -59,10 +63,11 @@ impl App { terminal.draw(|frame| self.draw(frame))?; let event = self.events.next().await?; self.update(event)?; - if let Some(view) = self.state.view.as_mut() && - let Some(main_view) = view.downcast_ref::() && - !main_view.is_running() { - break Ok(()) + if let Some(view) = self.state.view.as_mut() + && let Some(main_view) = view.downcast_ref::() + && !main_view.is_running() + { + break Ok(()); } } } @@ -79,7 +84,7 @@ impl App { } fn handle_key_event(&mut self, key: &KeyEvent) -> Result<()> { - if let Some(any) = self.state.view .as_mut() { + if let Some(any) = self.state.view.as_mut() { if let Some(main_view) = any.downcast_mut::() { main_view.handle_key_input(key)?; } @@ -99,11 +104,15 @@ impl App { fn draw(&mut self, frame: &mut Frame) { if let Some(view) = self.state.view.as_mut() { if let Some(main_view) = view.downcast_mut::() { - frame.render_stateful_widget(MainView::new(&self.app_config), frame.area(), &mut main_view.state); + frame.render_stateful_widget( + MainView::new(&self.app_config), + frame.area(), + &mut main_view.state, + ); if let Some(pos) = main_view.screen_cursor() { frame.set_cursor_position(pos); } } } } -} \ No newline at end of file +} diff --git a/src/cli.rs b/src/cli.rs index 060e9eb..0856bb8 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,29 +1,25 @@ -use std::io::stdout; -use std::path::PathBuf; -use clap::{command, Args, Command, Parser, Subcommand}; -use color_eyre::Result; -use crossterm::cursor::{Hide, Show}; -use crossterm::execute; -use crossterm::terminal::{EnterAlternateScreen, LeaveAlternateScreen}; -use ratatui::crossterm; use crate::app; use crate::config::types::ApplicationConfig; use crate::constants::APP_CONIFG_FILE_PATH; +use clap::{command, Args, Command, Parser, Subcommand}; +use color_eyre::Result; +use ratatui::crossterm; +use std::path::PathBuf; #[derive(Parser, Debug)] struct FolderAddCommand { - path: String + path: String, } #[derive(Parser, Debug)] enum FolderSubCommand { - Add(FolderAddCommand) + Add(FolderAddCommand), } #[derive(Parser, Debug)] struct FolderCommand { #[command(subcommand)] - subcommand: FolderSubCommand + subcommand: FolderSubCommand, } #[derive(Parser, Debug)] @@ -35,20 +31,18 @@ enum CliSubCommand { #[command(version, about)] pub(crate) struct Cli { #[command(subcommand)] - subcommand: Option + subcommand: Option, } impl Subcommand for Cli { fn augment_subcommands(cmd: Command) -> Command { - cmd.subcommand(FolderCommand::augment_args( - Command::new("folder")) - ).subcommand_required(true) + cmd.subcommand(FolderCommand::augment_args(Command::new("folder"))) + .subcommand_required(true) } fn augment_subcommands_for_update(cmd: Command) -> Command { - cmd.subcommand(FolderCommand::augment_args - (Command::new("folder")) - ).subcommand_required(true) + cmd.subcommand(FolderCommand::augment_args(Command::new("folder"))) + .subcommand_required(true) } fn has_subcommand(name: &str) -> bool { @@ -58,15 +52,13 @@ impl Subcommand for Cli { impl Subcommand for FolderCommand { fn augment_subcommands(cmd: Command) -> Command { - cmd.subcommand(FolderAddCommand::augment_args( - Command::new("add")) - ).subcommand_required(true) + cmd.subcommand(FolderAddCommand::augment_args(Command::new("add"))) + .subcommand_required(true) } fn augment_subcommands_for_update(cmd: Command) -> Command { - cmd.subcommand(FolderAddCommand::augment_args( - Command::new("add")) - ).subcommand_required(true) + cmd.subcommand(FolderAddCommand::augment_args(Command::new("add"))) + .subcommand_required(true) } fn has_subcommand(name: &str) -> bool { @@ -77,10 +69,10 @@ impl Subcommand for FolderCommand { impl Cli { pub async fn run(&self) -> Result<()> { if self.subcommand.is_none() { - return self.start_tui().await + return self.start_tui().await; } if let Some(sub_command) = &self.subcommand { - return sub_command.handle().await + return sub_command.handle().await; } Ok(()) } @@ -101,7 +93,7 @@ impl Cli { impl CliSubCommand { pub async fn handle(&self) -> Result<()> { match self { - CliSubCommand::Folder(cmd) => cmd.subcommand.handle().await + CliSubCommand::Folder(cmd) => cmd.subcommand.handle().await, } } } @@ -119,7 +111,10 @@ impl FolderAddCommand { let mut config = ApplicationConfig::from_file(&APP_CONIFG_FILE_PATH.to_path_buf())?; let path = PathBuf::from(&self.path); let abs_path = path.canonicalize()?; - config.path_config.dlsite_paths.push(abs_path.to_str().unwrap().to_string()); + config + .path_config + .dlsite_paths + .push(abs_path.to_str().unwrap().to_string()); config.write_to_file(&APP_CONIFG_FILE_PATH.to_path_buf()) } -} \ No newline at end of file +} diff --git a/src/config/mod.rs b/src/config/mod.rs index 4caea87..db670ad 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,8 +1,8 @@ -use std::path::{PathBuf}; -use ini::Ini; -use color_eyre::Result; use crate::config::types::{ApplicationConfig, BasicConfig, PathConfig}; use crate::constants::{APP_CONIFG_FILE_PATH, APP_DATA_DIR}; +use color_eyre::Result; +use ini::Ini; +use std::path::PathBuf; pub mod types; @@ -16,26 +16,37 @@ impl ApplicationConfig { }; let path_conf_section = conf.section(Some("Path")).unwrap(); let path_conf = PathConfig { - dlsite_paths: path_conf_section.get("DLSite").unwrap() - .split(":").map(|s| s.to_string()).collect(), + dlsite_paths: path_conf_section + .get("DLSite") + .unwrap() + .split(":") + .map(|s| s.to_string()) + .collect(), }; Ok(Self { basic_config: basic_conf, - path_config: path_conf + path_config: path_conf, }) } pub fn new() -> Self { let conf = Self { basic_config: BasicConfig { - db_path: APP_DATA_DIR.clone().join("games.db").to_str().unwrap().to_string(), - tick_rate: 250 + db_path: APP_DATA_DIR + .clone() + .join("games.db") + .to_str() + .unwrap() + .to_string(), + tick_rate: 250, }, path_config: PathConfig { - dlsite_paths: vec![] - } + dlsite_paths: vec![], + }, }; - conf.clone().write_to_file(&APP_CONIFG_FILE_PATH.to_path_buf()).unwrap(); + conf.clone() + .write_to_file(&APP_CONIFG_FILE_PATH.to_path_buf()) + .unwrap(); conf } @@ -44,10 +55,16 @@ impl ApplicationConfig { conf.with_section(Some("Basic")) .set("DBPath", self.basic_config.db_path) .set("TickRate", self.basic_config.tick_rate.to_string()); - conf.with_section(Some("Path")) - .set("DLSite", self.path_config.dlsite_paths.into_iter() - .filter(|x| !x.is_empty()).collect::>().join(":")); + conf.with_section(Some("Path")).set( + "DLSite", + self.path_config + .dlsite_paths + .into_iter() + .filter(|x| !x.is_empty()) + .collect::>() + .join(":"), + ); conf.write_to_file(path)?; Ok(()) } -} \ No newline at end of file +} diff --git a/src/config/types.rs b/src/config/types.rs index 3cb08b0..dc97b81 100644 --- a/src/config/types.rs +++ b/src/config/types.rs @@ -1,16 +1,16 @@ #[derive(Clone)] pub(crate) struct ApplicationConfig { pub(crate) basic_config: BasicConfig, - pub(crate) path_config: PathConfig + pub(crate) path_config: PathConfig, } #[derive(Clone)] pub(crate) struct BasicConfig { pub(crate) db_path: String, - pub(crate) tick_rate: u64 + pub(crate) tick_rate: u64, } #[derive(Clone)] pub(crate) struct PathConfig { - pub(crate) dlsite_paths: Vec -} \ No newline at end of file + pub(crate) dlsite_paths: Vec, +} diff --git a/src/constants.rs b/src/constants.rs index 7eb462a..a9287a6 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,16 +1,13 @@ -use std::path::PathBuf; use directories::BaseDirs; use lazy_static::lazy_static; +use std::path::PathBuf; const APP_DIR_NAME: &str = "sus_manager"; -lazy_static!( +lazy_static! { static ref BASE_DIRS: BaseDirs = BaseDirs::new().unwrap(); - pub static ref APP_CONFIG_DIR: PathBuf = BASE_DIRS.config_dir().to_path_buf() - .join(APP_DIR_NAME); - pub static ref APP_DATA_DIR: PathBuf = BASE_DIRS.data_dir().to_path_buf() - .join(APP_DIR_NAME); - pub static ref APP_CACHE_PATH: PathBuf = BASE_DIRS.cache_dir().to_path_buf() - .join(APP_DIR_NAME); - pub static ref APP_CONIFG_FILE_PATH: PathBuf = APP_CONFIG_DIR.clone() - .join("config.ini"); -); \ No newline at end of file + pub static ref APP_CONFIG_DIR: PathBuf = + BASE_DIRS.config_dir().to_path_buf().join(APP_DIR_NAME); + pub static ref APP_DATA_DIR: PathBuf = BASE_DIRS.data_dir().to_path_buf().join(APP_DIR_NAME); + pub static ref APP_CACHE_PATH: PathBuf = BASE_DIRS.cache_dir().to_path_buf().join(APP_DIR_NAME); + pub static ref APP_CONIFG_FILE_PATH: PathBuf = APP_CONFIG_DIR.clone().join("config.ini"); +} \ No newline at end of file diff --git a/src/crawler/dlsite.rs b/src/crawler/dlsite.rs index 75b1fa8..b791ca5 100644 --- a/src/crawler/dlsite.rs +++ b/src/crawler/dlsite.rs @@ -5,6 +5,4 @@ pub(crate) struct DLSiteCrawler { crawler: Crawler, } -impl DLSiteCrawler { - -} \ No newline at end of file +impl DLSiteCrawler {} diff --git a/src/crawler/mod.rs b/src/crawler/mod.rs index 2942116..24625b7 100644 --- a/src/crawler/mod.rs +++ b/src/crawler/mod.rs @@ -1,17 +1,17 @@ mod dlsite; -use reqwest::{Client, Url}; -use robotstxt::{DefaultMatcher}; +use crate::constants::APP_CACHE_PATH; use color_eyre::Result; +use reqwest::{Client, Url}; +use robotstxt::DefaultMatcher; use scraper::Html; -use crate::constants::{APP_CACHE_PATH}; #[derive(Clone)] pub(crate) struct Crawler { id: String, base_url: Url, client: Client, - robots_txt: String + robots_txt: String, } impl Crawler { @@ -23,7 +23,11 @@ impl Crawler { base_url, }; let mut matcher = DefaultMatcher::default(); - let is_access_allowed = matcher.one_agent_allowed_by_robots(&crawler.robots_txt, "reqwest", crawler.base_url.as_str()); + let is_access_allowed = matcher.one_agent_allowed_by_robots( + &crawler.robots_txt, + "reqwest", + crawler.base_url.as_str(), + ); if !is_access_allowed { panic!("Crawler cannot access site {}", crawler.base_url.as_str()); } @@ -31,20 +35,22 @@ impl Crawler { } async fn get_robots_txt(id: &str, base_url: &Url) -> Result { - let local_robots_path = APP_CACHE_PATH.clone() - .join(id).join("robots.txt"); + let local_robots_path = APP_CACHE_PATH.clone().join(id).join("robots.txt"); if !local_robots_path.exists() { let mut robots_url = base_url.clone(); robots_url.set_path("/robots.txt"); - let response = reqwest::get(robots_url).await - .expect(format!("Failed to get robots.txt in `{}/robots.txt`", base_url.as_str()).as_str()); + let response = reqwest::get(robots_url).await.expect( + format!( + "Failed to get robots.txt in `{}/robots.txt`", + base_url.as_str() + ) + .as_str(), + ); let content = response.text().await?; tokio::fs::create_dir_all(local_robots_path.parent().unwrap()).await?; tokio::fs::write(&local_robots_path, &content).await?; Ok(content) - - } - else { + } else { Ok(tokio::fs::read_to_string(&local_robots_path).await?) } } @@ -55,4 +61,4 @@ impl Crawler { let html_text = &self.client.get(url).send().await?.text().await?; Ok(Html::parse_document(html_text)) } -} \ No newline at end of file +} diff --git a/src/event.rs b/src/event.rs index 51dc529..df19ee4 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,8 +1,8 @@ -use futures::FutureExt; -use color_eyre::eyre::{Result, eyre}; -use std::time::Duration; +use color_eyre::eyre::{eyre, Result}; use crossterm::event::EventStream; +use futures::FutureExt; use futures::StreamExt; +use std::time::Duration; use tokio::sync::mpsc::UnboundedSender; use tokio::task::JoinHandle; @@ -16,7 +16,7 @@ pub(crate) enum AppEvent { pub(crate) struct EventHandler { _tx: UnboundedSender, rx: tokio::sync::mpsc::UnboundedReceiver, - pub task: JoinHandle<()> + pub task: JoinHandle<()>, } impl EventHandler { @@ -45,9 +45,7 @@ impl EventHandler { } } }); - Self { - _tx, rx, task - } + Self { _tx, rx, task } } pub(crate) async fn next(&mut self) -> Result { diff --git a/src/helpers/mod.rs b/src/helpers/mod.rs index e69de29..8b13789 100644 --- a/src/helpers/mod.rs +++ b/src/helpers/mod.rs @@ -0,0 +1 @@ + diff --git a/src/main.rs b/src/main.rs index 12950b1..934e534 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,18 +1,18 @@ mod app; +mod cli; +mod config; +mod constants; +mod crawler; mod event; +mod helpers; mod schema; mod types; -mod config; -mod helpers; -mod crawler; -mod constants; -mod cli; mod widgets; -use clap::{Parser}; +use crate::cli::Cli; +use clap::Parser; use color_eyre::Result; use tokio; -use crate::cli::Cli; #[tokio::main] async fn main() -> Result<()> { diff --git a/src/types/game.rs b/src/types/game.rs index 7dafe46..42353cd 100644 --- a/src/types/game.rs +++ b/src/types/game.rs @@ -10,5 +10,5 @@ pub(crate) struct GameList { #[diesel(table_name = crate::schema::dl_games)] #[diesel(check_for_backend(diesel::sqlite::Sqlite))] pub(crate) struct DLSiteGame { - serial_number: String + serial_number: String, } diff --git a/src/types/mod.rs b/src/types/mod.rs index 68c160d..f7ee1cd 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1 +1 @@ -pub mod game; \ No newline at end of file +pub mod game; diff --git a/src/widgets/components/mod.rs b/src/widgets/components/mod.rs index 8e4a897..4162e37 100644 --- a/src/widgets/components/mod.rs +++ b/src/widgets/components/mod.rs @@ -1,2 +1,2 @@ mod textarea; -pub use textarea::*; \ No newline at end of file +pub use textarea::*; diff --git a/src/widgets/components/textarea.rs b/src/widgets/components/textarea.rs index 705a1b0..fd4c4bd 100644 --- a/src/widgets/components/textarea.rs +++ b/src/widgets/components/textarea.rs @@ -1,60 +1,53 @@ -use crossterm::event::{Event}; +use color_eyre::Result; +use crossterm::event::Event; +use rat_cursor::HasScreenCursor; use ratatui::buffer::Buffer; use ratatui::layout::{Constraint, Direction, Layout, Rect}; use ratatui::prelude::StatefulWidget; +use ratatui::style::{Color, Stylize}; use ratatui::text::Text; use ratatui::widgets::{Block, Borders, Paragraph, Widget}; -use tui_input::backend::crossterm::{EventHandler}; -use tui_input::{Input}; -use color_eyre::Result; -use rat_cursor::HasScreenCursor; -use ratatui::style::{Color, Stylize}; +use tui_input::backend::crossterm::EventHandler; +use tui_input::Input; #[derive(Clone)] pub struct TextArea { input: Input, title: String, style: TextAreaStyle, - area: Option, + input_area: Option, pub active: bool, } #[derive(Clone)] pub enum TextAreaStyle { - Block, SingleLine + Block, + SingleLine, } impl StatefulWidget for TextArea { type State = TextArea; fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) where - Self: Sized + Self: Sized, { let input_value = state.input.value().to_string(); let title = self.title.clone(); if matches!(self.style, TextAreaStyle::Block) { - let block = Block::default() - .borders(Borders::ALL) - .title(title); - let paragraph = Paragraph::new(Text::from(input_value)) - .block(block); + let block = Block::default().borders(Borders::ALL).title(title); + let paragraph = Paragraph::new(Text::from(input_value)).block(block); + state.input_area = Some(area); paragraph.render(area, buf); - } - else if matches!(self.style, TextAreaStyle::SingleLine) { + } else if matches!(self.style, TextAreaStyle::SingleLine) { let chunks = Layout::default() .direction(Direction::Horizontal) - .constraints([ - Constraint::Percentage(10), - Constraint::Fill(0), - ]) + .constraints([Constraint::Percentage(10), Constraint::Fill(0)]) .split(area); let text = Text::from(self.title); let line = Paragraph::new(text); - let input_text = Text::from(input_value) - .fg(Color::White); - let paragraph = Paragraph::new(input_text) - .bg(Color::Green); - state.area = Some(chunks[1]); + let input_text = Text::from(input_value).fg(Color::White); + let paragraph = Paragraph::new(input_text).bg(Color::Green); + state.input_area = Some(chunks[1]); line.render(chunks[0], buf); paragraph.render(chunks[1], buf); } @@ -63,10 +56,10 @@ impl StatefulWidget for TextArea { impl HasScreenCursor for TextArea { fn screen_cursor(&self) -> Option<(u16, u16)> { - if self.area.is_none() { + if self.input_area.is_none() { return None; } - let area = self.area.unwrap(); + let area = self.input_area.unwrap(); let width = area.width.max(3) - 3; let scroll = self.input.visual_scroll(width as usize); let x = (self.input.visual_cursor().max(scroll) - scroll) as u16; @@ -81,12 +74,12 @@ impl TextArea { title: title.to_string(), active: false, style: style.unwrap_or(TextAreaStyle::SingleLine), - area: None, + input_area: None, } } pub fn handle_input(&mut self, event: &Event) -> Result<()> { - let state_result = self.input.handle_event(event); + let _ = self.input.handle_event(event); Ok(()) } -} \ No newline at end of file +} diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index 3d9b7ff..e2f6435 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -1,3 +1,3 @@ pub mod components; pub mod popups; -pub mod views; \ No newline at end of file +pub mod views; diff --git a/src/widgets/popups/folder.rs b/src/widgets/popups/folder.rs index 743803e..fec5a56 100644 --- a/src/widgets/popups/folder.rs +++ b/src/widgets/popups/folder.rs @@ -1,21 +1,19 @@ +use crate::widgets::components::TextArea; use ratatui::buffer::Buffer; use ratatui::layout::{Constraint, Direction, Layout, Margin, Rect}; use ratatui::prelude::{StatefulWidget, Widget}; use ratatui::widgets::{Block, Borders}; -use crate::widgets::components::TextArea; #[derive(Clone)] pub struct AddFolderPopup { - pub textarea: TextArea + pub textarea: TextArea, } impl AddFolderPopup { pub fn new() -> Self { let mut textarea = TextArea::new("Folder Path", "", None); textarea.active = true; - Self { - textarea - } + Self { textarea } } } @@ -23,7 +21,7 @@ impl StatefulWidget for AddFolderPopup { type State = AddFolderPopup; fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) where - Self: Sized + Self: Sized, { let popup_area = Rect { x: area.width / 4, @@ -37,10 +35,8 @@ impl StatefulWidget for AddFolderPopup { block.render(popup_area, buf); let chunks = Layout::default() .direction(Direction::Vertical) - .constraints(vec![ - Constraint::Length(1) - ]) + .constraints(vec![Constraint::Length(1)]) .split(popup_area.inner(Margin::new(1, 1))); self.textarea.render(chunks[0], buf, &mut state.textarea); } -} \ No newline at end of file +} diff --git a/src/widgets/popups/mod.rs b/src/widgets/popups/mod.rs index 994f0d3..e9011fb 100644 --- a/src/widgets/popups/mod.rs +++ b/src/widgets/popups/mod.rs @@ -1 +1 @@ -pub mod folder; \ No newline at end of file +pub mod folder; diff --git a/src/widgets/views/main_view.rs b/src/widgets/views/main_view.rs index b343486..597d528 100644 --- a/src/widgets/views/main_view.rs +++ b/src/widgets/views/main_view.rs @@ -1,16 +1,15 @@ -use std::any::Any; -use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind}; -use crossterm::event::KeyCode::Char; -use rat_cursor::HasScreenCursor; -use ratatui::buffer::Buffer; -use ratatui::Frame; -use ratatui::layout::{Constraint, Direction, Layout, Rect}; -use ratatui::prelude::{Color, Line, Span, Style, Text, Widget}; -use ratatui::widgets::{Block, Borders, Paragraph, StatefulWidget}; use crate::config::types::ApplicationConfig; use crate::constants::APP_CONIFG_FILE_PATH; use crate::widgets::popups::folder::AddFolderPopup; -use crate::widgets::views::{View}; +use crate::widgets::views::View; +use crossterm::event::KeyCode::Char; +use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind}; +use rat_cursor::HasScreenCursor; +use ratatui::buffer::Buffer; +use ratatui::layout::{Constraint, Direction, Layout, Rect}; +use ratatui::prelude::{Color, Line, Span, Style, Text, Widget}; +use ratatui::widgets::{Block, Borders, Paragraph, StatefulWidget}; +use std::any::Any; pub struct MainView { app_config: ApplicationConfig, @@ -27,7 +26,7 @@ pub struct MainViewState { enum Status { Running, Exiting, - Popup + Popup, } impl MainView { @@ -35,9 +34,9 @@ impl MainView { Self { state: MainViewState { popup: None, - status: Status::Running + status: Status::Running, }, - app_config: app_conf.clone() + app_config: app_conf.clone(), } } @@ -59,8 +58,9 @@ impl MainView { impl View for MainView { fn handle_input(&mut self, event: &Event) -> color_eyre::Result<()> { - if let Some(any) = self.state.popup.as_mut() && - let Some(popup) = any.downcast_mut::(){ + if let Some(any) = self.state.popup.as_mut() + && let Some(popup) = any.downcast_mut::() + { popup.textarea.handle_input(event)?; } Ok(()) @@ -90,7 +90,7 @@ impl StatefulWidget for MainView { type State = MainViewState; fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) where - Self: Sized + Self: Sized, { let chunks = Layout::default() .direction(Direction::Vertical) @@ -101,12 +101,13 @@ impl StatefulWidget for MainView { ]) .split(area); - Self::render_header(state,chunks[0], buf); - Self::render_game_list(state,chunks[1], buf); - Self::render_footer(state,chunks[2], buf); + Self::render_header(chunks[0], buf); + Self::render_game_list(chunks[1], buf); + Self::render_footer(state, chunks[2], buf); - if let Some(boxed) = state.popup.as_mut() && - let Some(popup) = boxed.downcast_mut::() { + if let Some(boxed) = state.popup.as_mut() + && let Some(popup) = boxed.downcast_mut::() + { popup.clone().render(area, buf, popup); } } @@ -114,16 +115,17 @@ impl StatefulWidget for MainView { impl HasScreenCursor for MainView { fn screen_cursor(&self) -> Option<(u16, u16)> { - if let Some(popup) = &self.state.popup && - let Some(add_folder) = popup.downcast_ref::() { - return add_folder.textarea.screen_cursor() + if let Some(popup) = &self.state.popup + && let Some(add_folder) = popup.downcast_ref::() + { + return add_folder.textarea.screen_cursor(); } None } } impl MainView { - fn render_game_list(state: &mut MainViewState, area: Rect, buf: &mut Buffer) { + fn render_game_list(area: Rect, buf: &mut Buffer) { let game_list = Block::new() .title(Line::raw("Games")) .borders(Borders::ALL) @@ -131,20 +133,19 @@ impl MainView { game_list.render(area, buf); } - fn render_header(state: &mut MainViewState, area: Rect, buf: &mut Buffer) { - let title = Paragraph::new( - Text::styled( - "SuS Manager", - Style::default().fg(Color::Green), - ) - ); + fn render_header(area: Rect, buf: &mut Buffer) { + let title = Paragraph::new(Text::styled( + "SuS Manager", + Style::default().fg(Color::Green), + )); title.render(area, buf); } fn render_footer(state: &mut MainViewState, area: Rect, buf: &mut Buffer) { - let mut navigation_text = vec![ - Span::styled("(q) quit / (a) add folders", Style::default().fg(Color::Green)), - ]; + let mut navigation_text = vec![Span::styled( + "(q) quit / (a) add folders", + Style::default().fg(Color::Green), + )]; if matches!(state.status, Status::Popup) { navigation_text[0] = Span::styled("(Esc) close", Style::default().fg(Color::Green)); } @@ -152,4 +153,4 @@ impl MainView { let footer = Paragraph::new(line); footer.render(area, buf); } -} \ No newline at end of file +} diff --git a/src/widgets/views/mod.rs b/src/widgets/views/mod.rs index 4446cdb..826a6ba 100644 --- a/src/widgets/views/mod.rs +++ b/src/widgets/views/mod.rs @@ -2,9 +2,10 @@ mod main_view; use crossterm::event::{Event, KeyEvent}; pub use main_view::MainView; +use std::any::Any; -pub trait View { +pub trait View: Any + 'static { fn handle_input(&mut self, event: &Event) -> color_eyre::Result<()>; fn handle_key_input(&mut self, key: &KeyEvent) -> color_eyre::Result<()>; fn is_running(&self) -> bool; -} \ No newline at end of file +}