Implemented Scan card menu
This commit was merged in pull request #29.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
+16
-6
@@ -20,12 +20,22 @@ impl NavigationState {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn back(&mut self) -> View {
|
||||
let screen = self.screens.pop().unwrap();
|
||||
if self.screens.is_empty() {
|
||||
log::info!("last screen");
|
||||
return screen;
|
||||
pub fn back(&mut self) -> &View {
|
||||
match &self.screens.len() {
|
||||
0 => {
|
||||
log::info!("No screens to go back to");
|
||||
return self.screens.last().unwrap();
|
||||
}
|
||||
1 => {
|
||||
log::info!("Only one screen on stack, cannot go back");
|
||||
return self.screens.last().unwrap();
|
||||
}
|
||||
_ => {
|
||||
log::info!("Going back to previous screen");
|
||||
self.screens.pop();
|
||||
return self.screens.last().unwrap();
|
||||
}
|
||||
|
||||
}
|
||||
self.screens.pop().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user