From 8a7456adbd159bd84cd2d17242a415e693d42344 Mon Sep 17 00:00:00 2001 From: rhetenor Date: Tue, 18 Aug 2026 18:53:17 +0000 Subject: [PATCH] implement back button --- src/navigation/main_menu.rs | 14 +++++++------- src/navigation/navigation.rs | 28 +++++++++++++++++++++------- src/navigation/scan_menu.rs | 6 +++--- src/navigation/settings_menu.rs | 6 +++--- src/navigation/state.rs | 31 +++++++++++++++++++++---------- 5 files changed, 55 insertions(+), 30 deletions(-) diff --git a/src/navigation/main_menu.rs b/src/navigation/main_menu.rs index 5d7cb71..3ebff0c 100644 --- a/src/navigation/main_menu.rs +++ b/src/navigation/main_menu.rs @@ -9,7 +9,7 @@ use embedded_graphics::pixelcolor::Rgb565; use embedded_graphics::prelude::RgbColor; use embedded_graphics_core::draw_target::DrawTarget; -use super::state::Menu; +use super::state::ScreenItem; pub const MAX_SELECTED: i32 = 3; @@ -35,7 +35,7 @@ impl super::navigation::Navigable for MainMenu { fn handle_input( &self, input: super::navigation::Action, - ) -> impl core::future::Future + Send { + ) -> impl core::future::Future + Send { let new_menu = match input { super::navigation::Action::Up => { let new_selected = if (self.selected - 1) < 0 { @@ -43,21 +43,21 @@ impl super::navigation::Navigable for MainMenu { } else { self.selected - 1 }; - Menu::Main(MainMenu { + ScreenItem::Main(MainMenu { selected: new_selected, }) } super::navigation::Action::Down => { let new_selected = self.selected.wrapping_add(1) % MAX_SELECTED; - Menu::Main(MainMenu { + ScreenItem::Main(MainMenu { selected: new_selected, }) } super::navigation::Action::Ok => match self.selected { - 2 => Menu::Settings(SettingsMenu { selected: 0 }), - _ => Menu::Main(self.clone()), + 2 => ScreenItem::Settings(SettingsMenu { selected: 0 }), + _ => ScreenItem::Main(self.clone()), }, - _ => Menu::Main(self.clone()), + _ => ScreenItem::Main(self.clone()), }; future::ready(new_menu) diff --git a/src/navigation/navigation.rs b/src/navigation/navigation.rs index 153ee41..b0b008d 100644 --- a/src/navigation/navigation.rs +++ b/src/navigation/navigation.rs @@ -1,5 +1,5 @@ use crate::navigation::scan_menu::ScanMenu; -use crate::navigation::state::{Menu, NavigationState}; +use crate::navigation::state::{NavigationState, ScreenItem}; use crate::{display::primary_lcd::PrimaryLcdDisplay, navigation::inputs::Inputs}; use embassy_futures::select::Either6; @@ -23,15 +23,16 @@ pub trait Navigable { &self, display: &mut PrimaryLcdDisplay<'static>, ) -> impl core::future::Future + Send; - fn handle_input(&self, input: Action) -> impl core::future::Future + Send; + fn handle_input(&self, input: Action) -> impl core::future::Future + Send; } #[embassy_executor::task] pub async fn run(mut inputs: Inputs, display: &'static mut PrimaryLcdDisplay<'static>) { - let mut state = NavigationState::default(); - // state.current_screen = Menu::Scan(ScanMenu { progress: (100 * 30 / 255) as u8 }); - log::info!("starting navigation"); + + let mut state = NavigationState::new(); + state.screens.last().unwrap().display(display).await; + loop { let selection = select6( inputs.up.wait_for_low(), @@ -53,8 +54,21 @@ pub async fn run(mut inputs: Inputs, display: &'static mut PrimaryLcdDisplay<'st }; log::info!("Action: {:?}", action); - state.current_screen = state.current_screen.handle_input(action).await; - state.current_screen.display(display).await; + + let screen = match action { + Action::Back => state.back(), + _ => { + state + .screens + .last() + .expect("no screen on stack") + .handle_input(action) + .await + } + }; + + screen.display(display).await; + state.screens.push(screen); Timer::after(Duration::from_millis(DEBOUNCE_DURATION_MILLIS)).await; } diff --git a/src/navigation/scan_menu.rs b/src/navigation/scan_menu.rs index f344f48..31dc505 100644 --- a/src/navigation/scan_menu.rs +++ b/src/navigation/scan_menu.rs @@ -22,7 +22,7 @@ use embedded_graphics::text::TextStyleBuilder; use embedded_graphics_core::draw_target::DrawTarget; use super::navigation::Action; -use super::state::Menu; +use super::state::ScreenItem; #[derive(Debug, Clone)] pub struct ScanMenu { @@ -82,14 +82,14 @@ impl super::navigation::Navigable for ScanMenu { core::future::ready(()) } - fn handle_input(&self, input: Action) -> impl core::future::Future + Send { + fn handle_input(&self, input: Action) -> impl core::future::Future + Send { async move { let new_progress = match input { Action::Up => self.progress.wrapping_add(5), _ => self.progress, }; - Menu::Scan(ScanMenu { + ScreenItem::Scan(ScanMenu { progress: new_progress, }) } diff --git a/src/navigation/settings_menu.rs b/src/navigation/settings_menu.rs index c1a5eff..022e79f 100644 --- a/src/navigation/settings_menu.rs +++ b/src/navigation/settings_menu.rs @@ -1,5 +1,5 @@ use crate::navigation::menu_item; -use crate::navigation::state::Menu; +use crate::navigation::state::ScreenItem; use crate::{display::primary_lcd::PrimaryLcdDisplay, navigation::inputs::Inputs}; use embedded_graphics::pixelcolor::Rgb565; @@ -27,7 +27,7 @@ impl super::navigation::Navigable for SettingsMenu { fn handle_input( &self, input: super::navigation::Action, - ) -> impl core::future::Future + Send { - async move { Menu::Settings(SettingsMenu { selected: 0 }) } + ) -> impl core::future::Future + Send { + async move { ScreenItem::Settings(SettingsMenu { selected: 0 }) } } } diff --git a/src/navigation/state.rs b/src/navigation/state.rs index 7171f45..2d9da45 100644 --- a/src/navigation/state.rs +++ b/src/navigation/state.rs @@ -1,24 +1,26 @@ use crate::navigation::{ main_menu::MainMenu, navigation::Navigable, scan_menu::ScanMenu, settings_menu::SettingsMenu, }; +use alloc::vec; +use alloc::vec::Vec; #[derive(Debug, Clone)] -pub enum Menu { +pub enum ScreenItem { Main(MainMenu), Scan(ScanMenu), Settings(SettingsMenu), } -impl Navigable for Menu { +impl Navigable for ScreenItem { fn display( &self, display: &mut crate::display::primary_lcd::PrimaryLcdDisplay<'static>, ) -> impl core::future::Future + Send { async move { match self { - Menu::Main(main_menu) => main_menu.display(display).await, - Menu::Scan(scan_menu) => scan_menu.display(display).await, - Menu::Settings(settings_menu) => settings_menu.display(display).await, + ScreenItem::Main(main_menu) => main_menu.display(display).await, + ScreenItem::Scan(scan_menu) => scan_menu.display(display).await, + ScreenItem::Settings(settings_menu) => settings_menu.display(display).await, } } } @@ -29,9 +31,9 @@ impl Navigable for Menu { ) -> impl core::future::Future + Send { async move { match self { - Menu::Main(main_menu) => main_menu.handle_input(input).await, - Menu::Scan(scan_menu) => scan_menu.handle_input(input).await, - Menu::Settings(settings_menu) => settings_menu.handle_input(input).await, + ScreenItem::Main(main_menu) => main_menu.handle_input(input).await, + ScreenItem::Scan(scan_menu) => scan_menu.handle_input(input).await, + ScreenItem::Settings(settings_menu) => settings_menu.handle_input(input).await, } } } @@ -39,13 +41,13 @@ impl Navigable for Menu { #[derive(Debug, Clone)] pub struct NavigationState { - pub current_screen: Menu, + pub screens: Vec, } impl Default for NavigationState { fn default() -> Self { Self { - current_screen: Menu::Main(MainMenu { selected: 0 }), + screens: vec![ScreenItem::Main(MainMenu { selected: 0 })], } } } @@ -54,4 +56,13 @@ impl NavigationState { pub fn new() -> Self { Self::default() } + + pub fn back(&mut self) -> ScreenItem { + let screen = self.screens.pop().unwrap(); + if self.screens.is_empty() { + log::info!("last screen"); + return screen; + } + self.screens.pop().unwrap() + } }