103 lines
3.6 KiB
Rust
103 lines
3.6 KiB
Rust
use crate::drivers::primary_lcd::PrimaryDisplayError;
|
|
use crate::peripherals::Peripherals;
|
|
use alloc::boxed::Box;
|
|
use alloc::vec;
|
|
use core::error;
|
|
|
|
use crate::card::model::Card;
|
|
use crate::card::{decoder::split_nfc_hex, mock::*};
|
|
|
|
use crate::navigation::inputs::ButtonAction;
|
|
use crate::navigation::outputs::Outputs;
|
|
use crate::views::card_view::CardView;
|
|
use crate::views::journal_view::JournalView;
|
|
use crate::views::{menu_item, settings_menu::SettingsMenu, view::View};
|
|
|
|
use crate::navigation::navigation::{Action, Navigable, NewState};
|
|
use embedded_graphics::pixelcolor::Rgb565;
|
|
use embedded_graphics::prelude::RgbColor;
|
|
use embedded_graphics_core::draw_target::DrawTarget;
|
|
|
|
pub const MAX_SELECTED: i32 = 4;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct MainMenu {
|
|
pub selected: i32,
|
|
}
|
|
|
|
impl Navigable for MainMenu {
|
|
fn display(
|
|
&self,
|
|
outputs: &mut Outputs,
|
|
_: &Peripherals,
|
|
) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send {
|
|
async move {
|
|
let display = &mut outputs.primary_display;
|
|
display.clear(Rgb565::BLACK).unwrap();
|
|
|
|
menu_item::show(display, "Scan card", 0, self.selected)
|
|
.map_err(PrimaryDisplayError::from)?;
|
|
menu_item::show(display, "Last card", 1, self.selected)
|
|
.map_err(PrimaryDisplayError::from)?;
|
|
menu_item::show(display, "Journal", 2, self.selected)
|
|
.map_err(PrimaryDisplayError::from)?;
|
|
menu_item::show(display, "Settings", 3, self.selected)
|
|
.map_err(PrimaryDisplayError::from)?;
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
fn handle_input(&self, input: Action) -> impl core::future::Future<Output = NewState> + Send {
|
|
async move {
|
|
let Action::Button(input) = input else {
|
|
// Skip timer inputs
|
|
return NewState {
|
|
view: View::Main(self.clone()),
|
|
replace_view: true,
|
|
redraw: false,
|
|
};
|
|
};
|
|
|
|
let card_mock1 = Card::try_from(split_nfc_hex(&MOCK_PAYLOAD3).unwrap()).unwrap();
|
|
let card_mock2 = Card::try_from(split_nfc_hex(&MOCK_PAYLOAD2).unwrap()).unwrap();
|
|
|
|
let new_menu = match input {
|
|
ButtonAction::Up => {
|
|
let new_selected = if (self.selected - 1) < 0 {
|
|
MAX_SELECTED - 1
|
|
} else {
|
|
self.selected - 1
|
|
};
|
|
View::Main(MainMenu {
|
|
selected: new_selected,
|
|
})
|
|
}
|
|
ButtonAction::Down => {
|
|
let new_selected = self.selected.wrapping_add(1) % MAX_SELECTED;
|
|
View::Main(MainMenu {
|
|
selected: new_selected,
|
|
})
|
|
}
|
|
ButtonAction::Ok => match self.selected {
|
|
0 => View::Scan(crate::views::scan_menu::ScanMenu { progress: 0 }),
|
|
1 => View::Card(CardView { card: card_mock1 }),
|
|
2 => View::Journal(JournalView {
|
|
cards: vec![card_mock1, card_mock2],
|
|
selected_card: 0,
|
|
}),
|
|
3 => View::Settings(SettingsMenu { selected: 0 }),
|
|
_ => View::Main(self.clone()),
|
|
},
|
|
_ => View::Main(self.clone()),
|
|
};
|
|
|
|
NewState {
|
|
replace_view: matches!(new_menu, View::Main(_)),
|
|
view: new_menu,
|
|
redraw: true,
|
|
}
|
|
}
|
|
}
|
|
}
|