From 4d1ce4c108cac00b646f3a3ec1cd2ac47ec472fc Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Fri, 1 Nov 2024 21:34:25 -0700 Subject: [PATCH] Add initial Home/Screen switching code --- .config/config.json5 | 25 ++++++++++++++++++++++++ src/action.rs | 7 +++++++ src/app.rs | 41 +++++++++++++++++++++++++++++++++++++++- src/components/footer.rs | 36 ++++++++++++++++++++++------------- src/components/left.rs | 20 +++++++++++++++----- 5 files changed, 110 insertions(+), 19 deletions(-) diff --git a/.config/config.json5 b/.config/config.json5 index c746239..1c953c3 100644 --- a/.config/config.json5 +++ b/.config/config.json5 @@ -1,6 +1,31 @@ { "keybindings": { "Home": { + "": "PrevScreen", + "": "Process", + "": "Quit", // Quit the application + "": "Quit", // Another way to quit + "": "Quit", // Yet another way to quit + "": "Suspend" // Suspend the application + }, + "SelectDisks": { + "": "PrevScreen", + "": "Process", + "": "Quit", // Quit the application + "": "Quit", // Another way to quit + "": "Quit", // Yet another way to quit + "": "Suspend" // Suspend the application + }, + "SelectParts": { + "": "PrevScreen", + "": "Process", + "": "Quit", // Quit the application + "": "Quit", // Another way to quit + "": "Quit", // Yet another way to quit + "": "Suspend" // Suspend the application + }, + "Done": { + "": "Quit", "": "Quit", // Quit the application "": "Quit", // Another way to quit "": "Quit", // Yet another way to quit diff --git a/src/action.rs b/src/action.rs index 2830433..5c181b8 100644 --- a/src/action.rs +++ b/src/action.rs @@ -1,6 +1,8 @@ use serde::{Deserialize, Serialize}; use strum::Display; +use crate::app::Mode; + #[derive(Debug, Clone, PartialEq, Eq, Display, Serialize, Deserialize)] pub enum Action { Tick, @@ -12,4 +14,9 @@ pub enum Action { ClearScreen, Error(String), Help, + SetMode(Mode), + PrevScreen, + Process, + SelectDisks(Option, Option), // indicies for (source, dest) + SelectParts(Option, Option), // indicies for (boot, os) } diff --git a/src/app.rs b/src/app.rs index 9553fff..e59f456 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,4 +1,4 @@ -use std::iter::zip; +use std::{collections::HashMap, iter::zip}; use color_eyre::Result; use crossterm::event::KeyEvent; @@ -25,6 +25,7 @@ pub struct App { tick_rate: f64, frame_rate: f64, components: Vec>, + component_indices: HashMap, should_quit: bool, should_suspend: bool, mode: Mode, @@ -37,6 +38,29 @@ pub struct App { pub enum Mode { #[default] Home, + SelectDisks, + SelectParts, + Done, +} + +impl Mode { + pub fn next_screen(cur_mode: Mode) -> Mode { + match cur_mode { + Mode::Home => Mode::SelectDisks, + Mode::SelectDisks => Mode::SelectParts, + Mode::SelectParts => Mode::Done, + Mode::Done => Mode::Done, + } + } + + pub fn prev_screen(cur_mode: Mode) -> Mode { + match cur_mode { + Mode::Home => Mode::Home, + Mode::SelectDisks => Mode::Home, + Mode::SelectParts => Mode::SelectDisks, + Mode::Done => Mode::SelectParts, + } + } } impl App { @@ -53,6 +77,14 @@ impl App { Box::new(Footer::new()), Box::new(Popup::new()), ], + component_indices: HashMap::from([ + (String::from("title"), 0), + (String::from("fps"), 1), + (String::from("left"), 2), + (String::from("right"), 3), + (String::from("footer"), 4), + (String::from("popup"), 5), + ]), should_quit: false, should_suspend: false, config: Config::new()?, @@ -160,6 +192,13 @@ impl App { Action::ClearScreen => tui.terminal.clear()?, Action::Resize(w, h) => self.handle_resize(tui, w, h)?, Action::Render => self.render(tui)?, + Action::PrevScreen => self + .action_tx + .send(Action::SetMode(Mode::prev_screen(self.mode)))?, + Action::Process => self + .action_tx + .send(Action::SetMode(Mode::next_screen(self.mode)))?, + Action::SetMode(new_mode) => self.mode = new_mode, _ => {} } for component in self.components.iter_mut() { diff --git a/src/components/footer.rs b/src/components/footer.rs index b202c5e..6d52bd9 100644 --- a/src/components/footer.rs +++ b/src/components/footer.rs @@ -3,18 +3,21 @@ use ratatui::{prelude::*, widgets::*}; use tokio::sync::mpsc::UnboundedSender; use super::Component; -use crate::{action::Action, config::Config}; +use crate::{action::Action, app::Mode, config::Config}; #[derive(Default)] pub struct Footer { command_tx: Option>, config: Config, - show_install_driver: bool, + footer_text: String, } impl Footer { pub fn new() -> Self { - Self::default() + Self { + footer_text: String::from("(Enter) to select / (b) to go back / (q) to quit"), + ..Default::default() + } } } @@ -37,22 +40,29 @@ impl Component for Footer { Action::Render => { // add any logic here that should run on every render } + Action::SetMode(new_mode) => { + self.footer_text = match new_mode { + Mode::SelectDisks => String::from( + "(Enter) to select / (b) to go back / (i) to install driver / (q) to quit", + ), + Mode::Done => String::from("(Enter) or (q) to quit"), + _ => String::from("(Enter) to select / (b) to go back / (q) to quit"), + } + } _ => {} } Ok(None) } fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { - let footer_text = Span::styled( - if self.show_install_driver { - "(Enter) to select / (b) to go back / (i) to install driver / (q) to quit" - } else { - "(Enter) to select / (b) to go back / (q) to quit" - }, - Style::default().fg(Color::DarkGray), - ); - let footer = Paragraph::new(Line::from(footer_text).centered()) - .block(Block::default().borders(Borders::ALL)); + let footer = Paragraph::new( + Line::from(Span::styled( + &self.footer_text, + Style::default().fg(Color::DarkGray), + )) + .centered(), + ) + .block(Block::default().borders(Borders::ALL)); frame.render_widget(footer, area); Ok(()) } diff --git a/src/components/left.rs b/src/components/left.rs index 4d15747..e32b78a 100644 --- a/src/components/left.rs +++ b/src/components/left.rs @@ -4,17 +4,21 @@ use ratatui::{prelude::*, widgets::*}; use tokio::sync::mpsc::UnboundedSender; use super::Component; -use crate::{action::Action, config::Config}; +use crate::{action::Action, app::Mode, config::Config}; #[derive(Default)] pub struct Left { command_tx: Option>, config: Config, + title_text: String, } impl Left { pub fn new() -> Self { - Self::default() + Self { + title_text: String::from("Home"), + ..Default::default() + } } } @@ -43,6 +47,12 @@ impl Component for Left { Action::Render => { // add any logic here that should run on every render } + Action::SetMode(new_mode) => match new_mode { + Mode::Home => self.title_text = String::from("Home"), + Mode::SelectDisks => self.title_text = String::from("Select Source Disk"), + Mode::SelectParts => self.title_text = String::from("Select Boot Partition"), + Mode::Done => self.title_text = String::from("Done"), + }, _ => {} } Ok(None) @@ -55,9 +65,9 @@ impl Component for Left { .areas(area); // Title - let title_text = String::from("Hello world!"); - let title = Paragraph::new(Line::from(title_text).centered()) - .block(Block::default().borders(Borders::NONE)); + let title = + Paragraph::new(Line::from(Span::styled(&self.title_text, Style::default())).centered()) + .block(Block::default().borders(Borders::NONE)); frame.render_widget(title, title_area); // Body