Implemented Scan card menu

This commit was merged in pull request #29.
This commit is contained in:
2026-08-22 13:35:58 +02:00
parent cf6c068394
commit b44ae59c8b
14 changed files with 189 additions and 89 deletions
+56 -23
View File
@@ -1,11 +1,17 @@
use crate::card::model::Card;
use crate::navigation::state::NavigationState;
use crate::views::view::View;
use crate::{display::primary_lcd::PrimaryLcdDisplay, navigation::inputs::Inputs};
use embassy_futures::select::Either6;
use embassy_futures::select::{Either, Either6, select};
use embassy_futures::select::select6;
use embassy_time::{Duration, Timer};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
pub type Mutex<T> = embassy_sync::mutex::Mutex<CriticalSectionRawMutex, T>;
pub type Signal<T> = embassy_sync::signal::Signal<CriticalSectionRawMutex, T>;
pub static CARD_DATA: Mutex<Option<Card>> = Mutex::new(None);
const DEBOUNCE_DURATION_MILLIS: u64 = 100;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -16,6 +22,13 @@ pub enum Action {
Right,
Ok,
Back,
Timer,
}
pub struct NewState {
pub view: View,
pub replace_view: bool,
pub redraw: bool,
}
pub trait Navigable {
@@ -23,52 +36,72 @@ pub trait Navigable {
&self,
display: &mut PrimaryLcdDisplay<'static>,
) -> impl core::future::Future<Output = ()> + Send;
fn handle_input(&self, input: Action) -> impl core::future::Future<Output = View> + Send;
fn handle_input(&self, input: Action) -> impl core::future::Future<Output = NewState> + Send;
}
#[embassy_executor::task]
pub async fn run(mut inputs: Inputs, display: &'static mut PrimaryLcdDisplay<'static>) {
pub async fn run(mut inputs: Inputs, display: &'static mut PrimaryLcdDisplay<'static>, ) {
log::info!("starting navigation");
let mut state = NavigationState::new();
state.screens.last().unwrap().display(display).await;
loop {
let selection = select6(
let selection_buttons = select6(
inputs.up.wait_for_low(),
inputs.down.wait_for_low(),
inputs.left.wait_for_low(),
inputs.right.wait_for_low(),
inputs.ok.wait_for_low(),
inputs.back.wait_for_low(),
)
.await;
);
let selection = select(selection_buttons, Timer::after(Duration::from_millis(DEBOUNCE_DURATION_MILLIS))).await;
let action = match selection {
Either6::First(_) => Action::Up,
Either6::Second(_) => Action::Down,
Either6::Third(_) => Action::Left,
Either6::Fourth(_) => Action::Right,
Either6::Fifth(_) => Action::Ok,
Either6::Sixth(_) => Action::Back,
Either::First(selection_buttons) => match selection_buttons {
Either6::First(_) => Action::Up,
Either6::Second(_) => Action::Down,
Either6::Third(_) => Action::Back,
Either6::Fourth(_) => Action::Ok,
Either6::Fifth(_) => Action::Ok,
Either6::Sixth(_) => Action::Back,
},
Either::Second(_) => Action::Timer,
};
log::info!("Action: {:?}", action);
let screen = match action {
Action::Back => state.back(),
_ => {
state
.screens
.last()
.expect("no screen on stack")
.handle_input(action)
.await
let new_state = if action == Action::Back {
if state.screens.len() > 1 {
state.screens.pop();
}
NewState {
view: state.screens.last().expect("no screen on stack").clone(),
replace_view: false,
redraw: true,
}
} else {
let new_state = state
.screens
.last()
.expect("no screen on stack")
.handle_input(action)
.await;
if action == Action::Timer && !new_state.redraw {
continue;
}
new_state
};
screen.display(display).await;
state.screens.push(screen);
if new_state.replace_view {
state.screens.pop();
}
state.screens.push(new_state.view);
if action != Action::Timer || new_state.redraw {
state.screens.last().unwrap().display(display).await;
}
Timer::after(Duration::from_millis(DEBOUNCE_DURATION_MILLIS)).await;
}