From 88c8678c2c063fa6fb0cebd67d326f6b092c7e97 Mon Sep 17 00:00:00 2001 From: Reboot-Codes Date: Tue, 03 Jun 2025 17:30:43 +0000 Subject: [PATCH] Add screen switching --- Cargo.lock | 1 + .direnv/flake-profile | 2 +- toolbox/ratchet/Cargo.toml | 2 +- toolbox/ratchet/dev.sh | 1 + toolbox/carbon-steel/src/lib.rs | 16 +++++++++------- toolbox/ratchet/src/main.rs | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------- toolbox/carbon-steel/src/connections/mod.rs | 2 ++ toolbox/ratchet/src/screens/mod.rs | 25 +++++++------------------ toolbox/ratchet/src/screens/configurator/mod.rs | 40 +++++++++++++++++++++++++++++++++------- toolbox/ratchet/src/screens/welcome/mod.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- toolbox/ratchet/src/screens/wizard/mod.rs | 48 +++++++++++++++++++++++++++++++++++++----------- 11 file(s) changed, 338 insertion(s)(+), 76 deletion(s)(-) diff --git a/Cargo.lock b/Cargo.lock --- a/Cargo.lock +++ b/Cargo.lock @@ -8126,6 +8126,7 @@ "bytes", "libc", "mio 1.0.3", + "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", "socket2", diff --git a/.direnv/flake-profile b/.direnv/flake-profile --- a/.direnv/flake-profile +++ b/.direnv/flake-profile @@ -1,1 +1,1 @@ -flake-profile-12-link \ No newline at end of file +flake-profile-17-link \ No newline at end of file diff --git a/toolbox/ratchet/Cargo.toml b/toolbox/ratchet/Cargo.toml --- a/toolbox/ratchet/Cargo.toml +++ b/toolbox/ratchet/Cargo.toml @@ -6,7 +6,7 @@ [dependencies] iced = { version = "0.13.1", features = ["tokio"] } carbon-steel = { path = "../carbon-steel" } -tokio = "1.45.1" +tokio = { version = "1.45.1", features = ["full"] } serde = "1.0.219" env_logger = "0.11.8" anyhow = "1.0.98" diff --git a/toolbox/ratchet/dev.sh b/toolbox/ratchet/dev.sh new file mode 100644 --- /dev/null +++ b/toolbox/ratchet/dev.sh @@ -0,0 +1,1 @@ +RATCHET_LOG="ratchet=debug" cargo run -p ratchet diff --git a/toolbox/carbon-steel/src/lib.rs b/toolbox/carbon-steel/src/lib.rs --- a/toolbox/carbon-steel/src/lib.rs +++ b/toolbox/carbon-steel/src/lib.rs @@ -1,14 +1,16 @@ +pub mod connections; + pub fn add(left: u64, right: u64) -> u64 { - left + right + left + right } #[cfg(test)] mod tests { - use super::*; + use super::*; - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } } diff --git a/toolbox/ratchet/src/main.rs b/toolbox/ratchet/src/main.rs --- a/toolbox/ratchet/src/main.rs +++ b/toolbox/ratchet/src/main.rs @@ -1,37 +1,36 @@ +#![feature(iter_collect_into)] + pub mod screens; // pub mod util; -use std::env; +use std::{ + collections::HashMap, + env, +}; -use screens::TopLevelScreen; -use screens::welcome::WelcomeScreen; +use carbon_steel::connections::ConnectionConfiguration; use iced::{ - Center, Element, Task, Theme, - widget::{ - Column, - button, - column, - text, - }, }; +use log::debug; use crate::screens::{ CurrentTopLevelScreen, MoveToScreen, + configurator::ConfiguratorScreen, + wizard::WizardScreen, }; -fn theme(state: &MainAppState) -> Theme { +fn theme(_state: &MainAppState) -> Theme { Theme::TokyoNight } pub const APP_NAME: &str = "Ratchet"; pub fn main() -> iced::Result { - // TODO:: Create a logger that will send logs to a FIFO buffer to send over WS via EvtBuzz env_logger::Builder::new() .parse_filters(&env::var("RATCHET_LOG").unwrap_or("info".to_string())) .init(); @@ -41,9 +40,25 @@ .run() } -#[derive(Default)] pub struct MainAppState { pub screen: CurrentTopLevelScreen, + pub current_connection: Option, + pub connections: HashMap, +} + +impl Default for MainAppState { + fn default() -> Self { + // Load state when the app starts up... + let mut connections = HashMap::new(); + + connections.insert("main".to_string(), ConnectionConfiguration {}); + + MainAppState { + screen: Default::default(), + current_connection: None, + connections, + } + } } #[derive(Debug, Clone)] @@ -54,19 +69,158 @@ impl MainAppState { fn update(&mut self, message: Message) -> Task { match message { - Message::MoveToScreen(screen) => match screen { - MoveToScreen::Welcome => Task::none(), - MoveToScreen::Wizard(_) => todo!(), - MoveToScreen::Configurator(instance_id) => todo!(), + Message::MoveToScreen(ref screen) => match screen { + MoveToScreen::Welcome => match &mut self.screen { + CurrentTopLevelScreen::Welcome(_welcome_screen) => Task::none(), + CurrentTopLevelScreen::Wizard(wizard_screen) => { + let action = wizard_screen.update(message.clone()); + + match action { + screens::wizard::Action::None => Task::none(), + screens::wizard::Action::MoveToScreen(move_to_screen) => match move_to_screen { + MoveToScreen::Welcome => { + self.screen = CurrentTopLevelScreen::Welcome(Default::default()); + Task::none() + } + MoveToScreen::Wizard(_starting_point) => Task::none(), + MoveToScreen::Configurator(id) => { + let (screen, task) = ConfiguratorScreen::new(id); + + self.screen = CurrentTopLevelScreen::Configurator(screen); + task + } + }, + } + } + CurrentTopLevelScreen::Configurator(configurator_screen) => { + let action = configurator_screen.update(message.clone()); + + match action { + screens::configurator::Action::None => Task::none(), + screens::configurator::Action::MoveToScreen(move_to_screen) => match move_to_screen { + MoveToScreen::Welcome => { + self.screen = CurrentTopLevelScreen::Welcome(Default::default()); + Task::none() + } + MoveToScreen::Configurator(_id) => Task::none(), + MoveToScreen::Wizard(starting_point) => { + let (screen, task) = WizardScreen::new(starting_point); + + self.screen = CurrentTopLevelScreen::Wizard(screen); + task + } + }, + } + } + }, + MoveToScreen::Wizard(_starting_point) => match &mut self.screen { + CurrentTopLevelScreen::Welcome(welcome_screen) => { + let action = welcome_screen.update(message.clone()); + + match action { + screens::welcome::Action::None => Task::none(), + screens::welcome::Action::MoveToScreen(move_to_screen) => match move_to_screen { + MoveToScreen::Welcome => Task::none(), + MoveToScreen::Wizard(starting_point) => { + let (screen, task) = WizardScreen::new(starting_point); + + self.screen = CurrentTopLevelScreen::Wizard(screen); + task + } + MoveToScreen::Configurator(id) => { + let (screen, task) = ConfiguratorScreen::new(id); + + self.screen = CurrentTopLevelScreen::Configurator(screen); + task + } + }, + } + } + CurrentTopLevelScreen::Wizard(_wizard_screen) => Task::none(), + CurrentTopLevelScreen::Configurator(configurator_screen) => { + let action = configurator_screen.update(message.clone()); + + match action { + screens::configurator::Action::None => Task::none(), + screens::configurator::Action::MoveToScreen(move_to_screen) => match move_to_screen { + MoveToScreen::Welcome => { + self.screen = CurrentTopLevelScreen::Welcome(Default::default()); + Task::none() + } + MoveToScreen::Configurator(_id) => Task::none(), + MoveToScreen::Wizard(starting_point) => { + let (screen, task) = WizardScreen::new(starting_point); + + self.screen = CurrentTopLevelScreen::Wizard(screen); + task + } + }, + } + } + }, + MoveToScreen::Configurator(_instance_id) => match &mut self.screen { + CurrentTopLevelScreen::Welcome(welcome_screen) => { + let action = welcome_screen.update(message.clone()); + + match action { + screens::welcome::Action::None => Task::none(), + screens::welcome::Action::MoveToScreen(move_to_screen) => match move_to_screen { + MoveToScreen::Welcome => Task::none(), + MoveToScreen::Wizard(starting_point) => { + let (screen, task) = WizardScreen::new(starting_point); + + self.screen = CurrentTopLevelScreen::Wizard(screen); + task + } + MoveToScreen::Configurator(id) => { + let (screen, task) = ConfiguratorScreen::new(id); + + self.screen = CurrentTopLevelScreen::Configurator(screen); + task + } + }, + } + } + CurrentTopLevelScreen::Wizard(wizard_screen) => { + let action = wizard_screen.update(message.clone()); + + match action { + screens::wizard::Action::None => Task::none(), + screens::wizard::Action::MoveToScreen(move_to_screen) => match move_to_screen { + MoveToScreen::Welcome => { + self.screen = CurrentTopLevelScreen::Welcome(Default::default()); + Task::none() + } + MoveToScreen::Wizard(_starting_point) => Task::none(), + MoveToScreen::Configurator(id) => { + let (screen, task) = ConfiguratorScreen::new(id); + + self.screen = CurrentTopLevelScreen::Configurator(screen); + task + } + }, + } + } + CurrentTopLevelScreen::Configurator(_configurator_screen) => Task::none(), + }, }, } } fn view(&self) -> Element { match &self.screen { - CurrentTopLevelScreen::Welcome(welcome) => welcome.view(self), - CurrentTopLevelScreen::Wizard(wizard_screen) => todo!(), - CurrentTopLevelScreen::Configurator(configurator_screen) => todo!(), + CurrentTopLevelScreen::Welcome(welcome_screen) => { + debug!("Switching to Welcome Screen..."); + welcome_screen.view(self) + } + CurrentTopLevelScreen::Wizard(wizard_screen) => { + debug!("Switching to Configuration Generation Wizard..."); + wizard_screen.view(self) + } + CurrentTopLevelScreen::Configurator(configurator_screen) => { + debug!("Switching to Instance Configurator"); + configurator_screen.view(self) + } } } } diff --git a/toolbox/carbon-steel/src/connections/mod.rs b/toolbox/carbon-steel/src/connections/mod.rs new file mode 100644 --- /dev/null +++ b/toolbox/carbon-steel/src/connections/mod.rs @@ -0,0 +1,2 @@ +#[derive(Debug, Clone)] +pub struct ConnectionConfiguration {} diff --git a/toolbox/ratchet/src/screens/mod.rs b/toolbox/ratchet/src/screens/mod.rs --- a/toolbox/ratchet/src/screens/mod.rs +++ b/toolbox/ratchet/src/screens/mod.rs @@ -1,15 +1,9 @@ -use iced::Element; - -use crate::{ - MainAppState, - Message, - screens::{ - configurator::ConfiguratorScreen, - welcome::WelcomeScreen, - wizard::{ - WizardScreen, - WizardStartingPoints, - }, +use crate::screens::{ + configurator::ConfiguratorScreen, + welcome::WelcomeScreen, + wizard::{ + WizardScreen, + WizardStep, }, }; @@ -33,11 +27,6 @@ #[derive(Debug, Clone)] pub enum MoveToScreen { Welcome, - Wizard(WizardStartingPoints), + Wizard(WizardStep), Configurator(String), -} - -pub trait TopLevelScreen { - fn view(&self, state: &MainAppState) -> Element; - fn update(&mut self, message: Message); } diff --git a/toolbox/ratchet/src/screens/configurator/mod.rs b/toolbox/ratchet/src/screens/configurator/mod.rs --- a/toolbox/ratchet/src/screens/configurator/mod.rs +++ b/toolbox/ratchet/src/screens/configurator/mod.rs @@ -1,16 +1,42 @@ -use crate::screens::TopLevelScreen; +use iced::{ + Task, + widget::button, +}; + +use crate::screens::MoveToScreen; #[derive(Debug, Clone)] pub struct ConfiguratorScreen { - current_instance: String, + pub instance_id: String, } -impl TopLevelScreen for ConfiguratorScreen { - fn view(&self, state: &crate::MainAppState) -> iced::Element { - todo!() +#[derive(Debug, Clone, Default)] +pub enum Action { + #[default] + None, + MoveToScreen(MoveToScreen), +} + +impl ConfiguratorScreen { + pub fn new(id: String) -> (Self, Task) { + (ConfiguratorScreen { instance_id: id }, Task::none()) } - fn update(&mut self, message: crate::Message) { - todo!() + pub fn view(&self, _state: &crate::MainAppState) -> iced::Element { + button("Hallo, Welt") + .on_press(crate::Message::MoveToScreen(MoveToScreen::Welcome)) + .into() + } + + pub fn update(&mut self, message: crate::Message) -> Action { + match message { + crate::Message::MoveToScreen(target_screen) => match target_screen { + super::MoveToScreen::Welcome => Action::MoveToScreen(MoveToScreen::Welcome), + super::MoveToScreen::Configurator(_id) => Action::None, + super::MoveToScreen::Wizard(starting_point) => { + Action::MoveToScreen(MoveToScreen::Wizard(starting_point)) + } + }, + } } } diff --git a/toolbox/ratchet/src/screens/welcome/mod.rs b/toolbox/ratchet/src/screens/welcome/mod.rs --- a/toolbox/ratchet/src/screens/welcome/mod.rs +++ b/toolbox/ratchet/src/screens/welcome/mod.rs @@ -1,21 +1,82 @@ -use iced::widget::text; -use log::debug; -use std::collections::HashMap; +use carbon_steel::connections::ConnectionConfiguration; +use iced::widget::{ + button, + column, + text, +}; +use log::{ + debug, + info, +}; +use std::{ + collections::HashMap, + sync::Arc, +}; -use crate::screens::TopLevelScreen; +use crate::screens::MoveToScreen; #[derive(Debug, Clone, Default)] -pub struct WelcomeScreen { - connections: HashMap, +pub struct WelcomeScreen {} + +#[derive(Debug, Clone, Default)] +pub enum Action { + #[default] + None, + MoveToScreen(MoveToScreen), } -impl TopLevelScreen for WelcomeScreen { - fn update(&mut self, message: crate::Message) { - debug!("{:?}", &message); +impl WelcomeScreen { + pub fn update(&mut self, message: crate::Message) -> Action { + match message { + crate::Message::MoveToScreen(target_screen) => match target_screen { + super::MoveToScreen::Welcome => Action::None, + super::MoveToScreen::Wizard(starting_point) => { + Action::MoveToScreen(MoveToScreen::Wizard(starting_point)) + } + super::MoveToScreen::Configurator(id) => { + Action::MoveToScreen(MoveToScreen::Configurator(id)) + } + }, + } } - fn view(&self, state: &crate::MainAppState) -> iced::Element { - text("I am 300px tall!").height(300).into() + pub fn view(&self, state: &crate::MainAppState) -> iced::Element { + let mut elements = vec![ + text("Hey there!").size(32).into(), + text("Using Ratchet v0.0.1").into(), + ]; + + let connections = state.connections.clone(); + let num_connections = connections.len(); + + info!("Loading pre-existing connections into UI state..."); + if num_connections > 0 { + debug!("Connections found!"); + elements.push(text("Existing connections:").size(24).into()); + as Clone>::clone(&connections) + .into_iter() + .map(|(id, configuration)| { + debug!( + "Found \"{}\", with config: {:?}", + id.clone(), + configuration.clone() + ); + + button("Connection") + .on_press(crate::Message::MoveToScreen( + super::MoveToScreen::Configurator(id.clone()), + )) + .into() + }) + .collect_into(&mut elements); + } else { + debug!("No connections found..."); + elements.push(text("No existing connections!").into()); + } + + elements.push(text("Create a new...").into()); + + column(elements).into() } } diff --git a/toolbox/ratchet/src/screens/wizard/mod.rs b/toolbox/ratchet/src/screens/wizard/mod.rs --- a/toolbox/ratchet/src/screens/wizard/mod.rs +++ b/toolbox/ratchet/src/screens/wizard/mod.rs @@ -1,22 +1,48 @@ -use crate::screens::TopLevelScreen; +use iced::Task; -#[derive(Debug, Clone)] +use crate::screens::MoveToScreen; + +#[derive(Default, Debug, Clone)] pub struct WizardScreen { step: WizardStep, } -impl TopLevelScreen for WizardScreen { - fn view(&self, state: &crate::MainAppState) -> iced::Element { +#[derive(Debug, Clone, Default)] +pub enum Action { + #[default] + None, + MoveToScreen(MoveToScreen), +} + +impl WizardScreen { + pub fn new(starting_point: WizardStep) -> (Self, Task) { + ( + WizardScreen { + step: starting_point, + }, + Task::none(), + ) + } + + pub fn view(&self, _state: &crate::MainAppState) -> iced::Element { todo!() } - fn update(&mut self, message: crate::Message) { - todo!() + pub fn update(&mut self, message: crate::Message) -> Action { + match message { + crate::Message::MoveToScreen(target_screen) => match target_screen { + super::MoveToScreen::Welcome => Action::MoveToScreen(MoveToScreen::Welcome), + super::MoveToScreen::Wizard(_starting_point) => Action::None, + super::MoveToScreen::Configurator(id) => { + Action::MoveToScreen(MoveToScreen::Configurator(id)) + } + }, + } } } -#[derive(Debug, Clone, Copy)] -pub enum WizardStartingPoints {} - -#[derive(Debug, Clone, Copy)] -pub enum WizardStep {} +#[derive(Default, Debug, Clone, Copy)] +pub enum WizardStep { + #[default] + ConnectionType, +} -- tangled.sh