implement error view which displays all error on the display #48

Merged
rhetenor merged 1 commits from rhetenor/errorview AGit into main 2026-08-29 22:21:19 +02:00
17 changed files with 316 additions and 92 deletions
Showing only changes of commit ef10eec216 - Show all commits
Generated
+18
View File
@@ -363,6 +363,7 @@ dependencies = [
"embedded-hal-bus", "embedded-hal-bus",
"embedded-io 0.7.1", "embedded-io 0.7.1",
"embedded-storage", "embedded-storage",
"embedded-text",
"esp-alloc", "esp-alloc",
"esp-bootloader-esp-idf", "esp-bootloader-esp-idf",
"esp-hal", "esp-hal",
@@ -1049,6 +1050,17 @@ dependencies = [
"embedded-storage", "embedded-storage",
] ]
[[package]]
name = "embedded-text"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cf5c72c52db2f7dbe4a9c1ed81cd21301e8d66311b194fa41c04fb4f71843ba"
dependencies = [
"az",
"embedded-graphics",
"object-chain",
]
[[package]] [[package]]
name = "enumset" name = "enumset"
version = "1.1.14" version = "1.1.14"
@@ -2130,6 +2142,12 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "object-chain"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41af26158b0f5530f7b79955006c2727cd23d0d8e7c3109dc316db0a919784dd"
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.21.4" version = "1.21.4"
+1
View File
@@ -54,6 +54,7 @@ esp-storage = "0.9.0"
embedded-storage = "0.3.1" embedded-storage = "0.3.1"
binary_serde = "1.0.25" binary_serde = "1.0.25"
static_assertions = { version = "1.1.0", default-features = false } static_assertions = { version = "1.1.0", default-features = false }
embedded-text = "0.7.3"
[build-dependencies] [build-dependencies]
log = "0.4.27" log = "0.4.27"
+37 -5
View File
@@ -1,10 +1,15 @@
use crate::alloc::string::ToString;
use crate::card::model::Card; use crate::card::model::Card;
use crate::navigation::inputs::ButtonAction; use crate::navigation::inputs::ButtonAction;
use crate::navigation::inputs::Inputs; use crate::navigation::inputs::Inputs;
use crate::navigation::outputs::Outputs; use crate::navigation::outputs::Outputs;
use crate::navigation::state::NavigationState; use crate::navigation::state::NavigationState;
use crate::peripherals::Peripherals; use crate::peripherals::Peripherals;
use crate::views::error_view::ErrorView;
use crate::views::view::View; use crate::views::view::View;
use alloc::boxed::Box;
use alloc::string::String;
use core::error;
use embassy_futures::select::{Either, select}; use embassy_futures::select::{Either, select};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
@@ -32,21 +37,45 @@ pub trait Navigable {
&self, &self,
outputs: &mut Outputs, outputs: &mut Outputs,
peripherals: &Peripherals, peripherals: &Peripherals,
) -> impl core::future::Future<Output = ()> + Send; ) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send;
fn handle_input(&self, input: Action) -> impl core::future::Future<Output = NewState> + Send; fn handle_input(&self, input: Action) -> impl core::future::Future<Output = NewState> + Send;
} }
#[embassy_executor::task] #[embassy_executor::task]
pub async fn run(mut inputs: Inputs, mut outputs: Outputs, peripherals: &'static Peripherals) { pub async fn run(mut inputs: Inputs, mut outputs: Outputs, peripherals: &'static Peripherals) {
async fn display_error(
error: String,
state: &mut NavigationState,
outputs: &mut Outputs,
peripherals: &Peripherals,
) -> () {
let error_view = ErrorView {
error: error.to_string(),
};
state.screens.push(View::Error(error_view));
state
.screens
.last()
// Unwrap: we just pushed the state
.unwrap()
.display(outputs, peripherals)
.await
// Unwrap: display will panic on error in error view
.unwrap();
}
log::info!("starting navigation"); log::info!("starting navigation");
let mut state = NavigationState::new(); let mut state = NavigationState::new();
state if let Err(error) = state
.screens .screens
.last() .last()
.unwrap() .unwrap()
.display(&mut outputs, peripherals) .display(&mut outputs, peripherals)
.await; .await
{
display_error(error.to_string(), &mut state, &mut outputs, &peripherals).await;
};
loop { loop {
let selection = select( let selection = select(
@@ -92,12 +121,15 @@ pub async fn run(mut inputs: Inputs, mut outputs: Outputs, peripherals: &'static
state.screens.push(new_state.view); state.screens.push(new_state.view);
if action != Action::Timer || new_state.redraw { if action != Action::Timer || new_state.redraw {
state if let Err(error) = state
.screens .screens
.last() .last()
.unwrap() .unwrap()
.display(&mut outputs, peripherals) .display(&mut outputs, peripherals)
.await; .await
{
display_error(error.to_string(), &mut state, &mut outputs, &peripherals).await;
}
} }
Timer::after(Duration::from_millis(DEBOUNCE_DURATION_MILLIS)).await; Timer::after(Duration::from_millis(DEBOUNCE_DURATION_MILLIS)).await;
+6 -6
View File
@@ -1,6 +1,6 @@
pub struct MemoryRegion { pub struct MemoryRegion {
offset: u32, pub offset: u32,
size: usize, pub size: usize,
} }
impl MemoryRegion { impl MemoryRegion {
@@ -15,13 +15,13 @@ impl MemoryRegion {
} }
} }
const MAX_FLASH: usize = 16 * 1024 * 1024; pub const MAX_FLASH: usize = 16 * 1024 * 1024;
const MAGIC_REGION: MemoryRegion = MemoryRegion::new(0, 4); pub const MAGIC_REGION: MemoryRegion = MemoryRegion::new(0, 4);
const SETTINGS_REGION: MemoryRegion = MemoryRegion::new(MAGIC_REGION.end() as u32, 1024); pub const SETTINGS_REGION: MemoryRegion = MemoryRegion::new(MAGIC_REGION.end() as u32, 1024);
const CARDSTORE_REGION: MemoryRegion = MemoryRegion::new( pub const CARDSTORE_REGION: MemoryRegion = MemoryRegion::new(
SETTINGS_REGION.end() as u32, SETTINGS_REGION.end() as u32,
MAX_FLASH - SETTINGS_REGION.end(), MAX_FLASH - SETTINGS_REGION.end(),
); );
+16 -2
View File
@@ -1,5 +1,7 @@
use alloc::collections::BTreeMap; use alloc::collections::BTreeMap;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::error::Error;
use core::fmt::Display;
use binary_serde::{BinarySerde, DeserializeError, Endianness}; use binary_serde::{BinarySerde, DeserializeError, Endianness};
@@ -67,7 +69,19 @@ impl AllocationTableEntry {
pub enum CardStoreError { pub enum CardStoreError {
Store(FlashStoreError), Store(FlashStoreError),
CorruptedEntry(DeserializeError), CorruptedEntry(DeserializeError),
NoEntry, NoEntry(u32),
}
impl Error for CardStoreError {}
impl Display for CardStoreError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
CardStoreError::Store(e) => e.fmt(f),
CardStoreError::CorruptedEntry(e) => e.fmt(f),
CardStoreError::NoEntry(uuid) => write!(f, "No Card Entry\nuuid: 0x{uuid:x}"),
}
}
} }
impl From<FlashStoreError> for CardStoreError { impl From<FlashStoreError> for CardStoreError {
@@ -129,7 +143,7 @@ impl CardStore {
let entry = self let entry = self
.allocation_table .allocation_table
.get(&uuid) .get(&uuid)
.ok_or(CardStoreError::NoEntry)?; .ok_or(CardStoreError::NoEntry(uuid))?;
let mut raw_card: [u8; size_of::<RawCard>()] = [0; size_of::<RawCard>()]; let mut raw_card: [u8; size_of::<RawCard>()] = [0; size_of::<RawCard>()];
self.store.read(entry.offset, &mut raw_card).await?; self.store.read(entry.offset, &mut raw_card).await?;
+32 -5
View File
@@ -1,3 +1,6 @@
use core::error::Error;
use core::fmt::Display;
use crate::navigation::navigation::Mutex; use crate::navigation::navigation::Mutex;
use embedded_storage::nor_flash::NorFlash; use embedded_storage::nor_flash::NorFlash;
use embedded_storage::nor_flash::ReadNorFlash; use embedded_storage::nor_flash::ReadNorFlash;
@@ -5,7 +8,23 @@ use esp_storage::{FlashStorage, FlashStorageError};
use crate::peripherals::storage::MAGIC_REGION; use crate::peripherals::storage::MAGIC_REGION;
pub type FlashStoreError = FlashStorageError; #[derive(Debug)]
pub struct FlashStoreError(FlashStorageError);
impl From<FlashStorageError> for FlashStoreError {
fn from(value: FlashStorageError) -> Self {
Self(value)
}
}
impl Error for FlashStoreError {}
impl Display for FlashStoreError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
use core::fmt::Debug;
self.0.fmt(f)
}
}
const FLASH_ADDR: u32 = 0x9000; const FLASH_ADDR: u32 = 0x9000;
@@ -37,12 +56,17 @@ impl FlashStore {
} }
pub async fn read(&self, offset: u32, bytes: &mut [u8]) -> Result<(), FlashStoreError> { pub async fn read(&self, offset: u32, bytes: &mut [u8]) -> Result<(), FlashStoreError> {
self.storage.lock().await.read(FLASH_ADDR + offset, bytes) self.storage.lock().await.read(FLASH_ADDR + offset, bytes)?;
Ok(())
} }
pub async fn write(&self, offset: u32, bytes: &mut [u8]) -> Result<(), FlashStoreError> { pub async fn write(&self, offset: u32, bytes: &mut [u8]) -> Result<(), FlashStoreError> {
log::debug!("Writing {} bytes at offset 0x{offset:08x}", bytes.len()); log::debug!("Writing {} bytes at offset 0x{offset:08x}", bytes.len());
self.storage.lock().await.write(FLASH_ADDR + offset, bytes) self.storage
.lock()
.await
.write(FLASH_ADDR + offset, bytes)?;
Ok(())
} }
pub async fn write_erase(&self, offset: u32, bytes: &mut [u8]) -> Result<(), FlashStoreError> { pub async fn write_erase(&self, offset: u32, bytes: &mut [u8]) -> Result<(), FlashStoreError> {
@@ -52,7 +76,8 @@ impl FlashStore {
); );
let mut lock = self.storage.lock().await; let mut lock = self.storage.lock().await;
lock.erase(FLASH_ADDR + offset, FLASH_ADDR + bytes.len() as u32)?; lock.erase(FLASH_ADDR + offset, FLASH_ADDR + bytes.len() as u32)?;
lock.write(FLASH_ADDR + offset, bytes) lock.write(FLASH_ADDR + offset, bytes)?;
Ok(())
} }
pub fn has_magic_bytes(storage: &mut FlashStorage) -> Result<bool, FlashStoreError> { pub fn has_magic_bytes(storage: &mut FlashStorage) -> Result<bool, FlashStoreError> {
@@ -75,7 +100,9 @@ impl FlashStore {
if Self::has_magic_bytes(storage)? { if Self::has_magic_bytes(storage)? {
Ok(()) Ok(())
} else { } else {
Err(FlashStoreError::Other(FLASH_INITIALIZE_MAGIC as i32)) Err(FlashStoreError(FlashStorageError::Other(
FLASH_INITIALIZE_MAGIC as i32,
)))
} }
} }
} }
+1
View File
@@ -1,4 +1,5 @@
pub mod card_view; pub mod card_view;
pub mod error_view;
pub mod flash_info_view; pub mod flash_info_view;
pub mod journal_view; pub mod journal_view;
pub mod main_menu; pub mod main_menu;
+4 -1
View File
@@ -2,7 +2,9 @@ use crate::display::sprite::render_sprite_onto_ili9341;
use crate::navigation::navigation::NewState; use crate::navigation::navigation::NewState;
use crate::navigation::outputs::Outputs; use crate::navigation::outputs::Outputs;
use crate::peripherals::Peripherals; use crate::peripherals::Peripherals;
use alloc::boxed::Box;
use alloc::format; use alloc::format;
use core::error;
use embedded_graphics::mono_font::MonoTextStyle; use embedded_graphics::mono_font::MonoTextStyle;
use embedded_graphics::mono_font::ascii::FONT_6X10; use embedded_graphics::mono_font::ascii::FONT_6X10;
use embedded_graphics::pixelcolor::Rgb565; use embedded_graphics::pixelcolor::Rgb565;
@@ -30,7 +32,7 @@ impl Navigable for CardView {
&self, &self,
outputs: &mut Outputs, outputs: &mut Outputs,
_: &Peripherals, _: &Peripherals,
) -> impl core::future::Future<Output = ()> + Send { ) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send {
async move { async move {
let display = &mut outputs.primary_display; let display = &mut outputs.primary_display;
display.clear(Rgb565::BLACK).unwrap(); display.clear(Rgb565::BLACK).unwrap();
@@ -100,6 +102,7 @@ impl Navigable for CardView {
let palette: Palette = self.card.cardtype.clone().into(); let palette: Palette = self.card.cardtype.clone().into();
render_sprite_onto_ili9341(display, self.card.sprite.data.as_slice(), &palette); render_sprite_onto_ili9341(display, self.card.sprite.data.as_slice(), &palette);
Ok(())
} }
} }
+94
View File
@@ -0,0 +1,94 @@
use crate::navigation::navigation::Action;
use crate::navigation::navigation::Navigable;
use crate::navigation::navigation::NewState;
use crate::navigation::outputs::Outputs;
use crate::peripherals::Peripherals;
use crate::views::view::View;
use alloc::boxed::Box;
use alloc::format;
use alloc::string::String;
use core::error;
use embedded_graphics::{
Drawable,
mono_font::{MonoTextStyle, ascii::FONT_10X20},
pixelcolor::Rgb565,
prelude::*,
primitives::Rectangle,
text::Text,
};
use embedded_text::{
TextBox,
alignment::HorizontalAlignment,
style::{HeightMode, TextBoxStyleBuilder},
};
#[derive(Debug, Clone)]
pub struct ErrorView {
pub error: String,
}
impl Navigable for ErrorView {
fn display(
&self,
outputs: &mut Outputs,
_: &Peripherals,
) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send {
async move {
let style = MonoTextStyle::new(&FONT_10X20, Rgb565::RED);
let display_area = outputs.primary_display.bounding_box();
Text::new(
"Error",
Point::new((display_area.size.width / 2 - 25) as i32, 30),
style,
)
.draw(&mut outputs.primary_display)
.unwrap_or_else(|error| {
panic!(
"Error: {error:?}\nDraw error while rendering error: {}",
self.error
)
});
let style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);
let textbox_style = TextBoxStyleBuilder::new()
.height_mode(HeightMode::FitToText)
.alignment(HorizontalAlignment::Center)
.build();
let bounds = Rectangle::new(Point::new(0, 30), display_area.size);
TextBox::with_textbox_style(&format!("{}", self.error), bounds, style, textbox_style)
.draw(&mut outputs.primary_display)
.unwrap_or_else(|error| {
panic!(
"Error: {error:?}\nDraw error while rendering error: {}",
self.error
)
});
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::Error(self.clone()),
replace_view: true,
redraw: false,
};
};
let new_menu = match input {
_ => View::Error(self.clone()),
};
NewState {
replace_view: matches!(new_menu, View::FlashInfo(_)),
view: new_menu,
redraw: true,
}
}
}
}
+15 -4
View File
@@ -1,10 +1,12 @@
use crate::navigation::inputs::ButtonAction;
use crate::navigation::navigation::Action; use crate::navigation::navigation::Action;
use crate::navigation::navigation::Navigable; use crate::navigation::navigation::Navigable;
use crate::navigation::navigation::NewState; use crate::navigation::navigation::NewState;
use crate::navigation::outputs::Outputs; use crate::navigation::outputs::Outputs;
use crate::peripherals::Peripherals; use crate::peripherals::Peripherals;
use crate::peripherals::storage::MAGIC_REGION;
use crate::views::view::View; use crate::views::view::View;
use alloc::boxed::Box;
use core::error;
use embedded_graphics::mono_font::MonoTextStyle; use embedded_graphics::mono_font::MonoTextStyle;
use embedded_graphics::mono_font::ascii::FONT_10X20; use embedded_graphics::mono_font::ascii::FONT_10X20;
use embedded_graphics::pixelcolor::Rgb565; use embedded_graphics::pixelcolor::Rgb565;
@@ -22,11 +24,20 @@ impl Navigable for FlashInfoView {
&self, &self,
outputs: &mut Outputs, outputs: &mut Outputs,
peripherals: &Peripherals, peripherals: &Peripherals,
) -> impl core::future::Future<Output = ()> + Send { ) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send {
async move {
let style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE); let style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);
let mut magic_bytes: [u8; MAGIC_REGION.size] = [0; MAGIC_REGION.size];
peripherals
.store
.lock()
.await
.flash_store
.read(MAGIC_REGION.offset, &mut magic_bytes)
.await?;
Text::new("Flash Initialized: {:?}", Point::new(40, 40), style); Text::new("Flash Initialized: {:?}", Point::new(40, 40), style);
Ok(())
core::future::ready(()) }
} }
fn handle_input(&self, input: Action) -> impl core::future::Future<Output = NewState> + Send { fn handle_input(&self, input: Action) -> impl core::future::Future<Output = NewState> + Send {
+4 -1
View File
@@ -1,3 +1,5 @@
use alloc::boxed::Box;
use core::error;
use crate::peripherals::Peripherals; use crate::peripherals::Peripherals;
use core::future; use core::future;
@@ -27,9 +29,10 @@ impl Navigable for JournalView {
&self, &self,
outputs: &mut Outputs, outputs: &mut Outputs,
_: &Peripherals, _: &Peripherals,
) -> impl core::future::Future<Output = ()> + Send { ) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send {
async move { async move {
outputs.primary_display.clear(Rgb565::BLACK).unwrap(); outputs.primary_display.clear(Rgb565::BLACK).unwrap();
Ok(())
} }
} }
+8 -3
View File
@@ -1,5 +1,7 @@
use crate::peripherals::Peripherals; use crate::peripherals::Peripherals;
use alloc::boxed::Box;
use alloc::vec; use alloc::vec;
use core::error;
use crate::card::model::Card; use crate::card::model::Card;
use crate::card::{decoder::split_nfc_hex, mock::*}; use crate::card::{decoder::split_nfc_hex, mock::*};
@@ -15,6 +17,7 @@ use embedded_graphics::pixelcolor::Rgb565;
use embedded_graphics::prelude::RgbColor; use embedded_graphics::prelude::RgbColor;
use embedded_graphics_core::draw_target::DrawTarget; use embedded_graphics_core::draw_target::DrawTarget;
use crate::peripherals::storage::cardstore::CardStoreError;
pub const MAX_SELECTED: i32 = 4; pub const MAX_SELECTED: i32 = 4;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -26,8 +29,9 @@ impl Navigable for MainMenu {
fn display( fn display(
&self, &self,
outputs: &mut Outputs, outputs: &mut Outputs,
_: &Peripherals _: &Peripherals,
) -> impl core::future::Future<Output = ()> + Send { ) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send {
async move {
let display = &mut outputs.primary_display; let display = &mut outputs.primary_display;
display.clear(Rgb565::BLACK).unwrap(); display.clear(Rgb565::BLACK).unwrap();
@@ -36,7 +40,8 @@ impl Navigable for MainMenu {
menu_item::show(display, "Journal", 2, self.selected); menu_item::show(display, "Journal", 2, self.selected);
menu_item::show(display, "Settings", 3, self.selected); menu_item::show(display, "Settings", 3, self.selected);
core::future::ready(()) Ok(())
}
} }
fn handle_input(&self, input: Action) -> impl core::future::Future<Output = NewState> + Send { fn handle_input(&self, input: Action) -> impl core::future::Future<Output = NewState> + Send {
+2
View File
@@ -1,3 +1,5 @@
use alloc::boxed::Box;
use core::error;
use crate::peripherals::Peripherals; use crate::peripherals::Peripherals;
use embedded_graphics::Drawable; use embedded_graphics::Drawable;
use embedded_graphics::draw_target::DrawTarget; use embedded_graphics::draw_target::DrawTarget;
+7 -4
View File
@@ -3,6 +3,8 @@ use crate::navigation::navigation::CARD_DATA;
use crate::navigation::navigation::NewState; use crate::navigation::navigation::NewState;
use crate::navigation::outputs::Outputs; use crate::navigation::outputs::Outputs;
use crate::peripherals::Peripherals; use crate::peripherals::Peripherals;
use alloc::boxed::Box;
use core::error;
use alloc::format; use alloc::format;
use embedded_graphics::Drawable; use embedded_graphics::Drawable;
@@ -37,8 +39,9 @@ impl Navigable for ScanMenu {
fn display( fn display(
&self, &self,
outputs: &mut Outputs, outputs: &mut Outputs,
_: &Peripherals _: &Peripherals,
) -> impl core::future::Future<Output = ()> + Send { ) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send {
async move {
let display = &mut outputs.primary_display; let display = &mut outputs.primary_display;
let style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE); let style = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);
display.clear(Rgb565::BLACK).unwrap(); display.clear(Rgb565::BLACK).unwrap();
@@ -84,8 +87,8 @@ impl Navigable for ScanMenu {
Text::with_text_style(&text, display_area.center(), character_style, text_style) Text::with_text_style(&text, display_area.center(), character_style, text_style)
.draw(display) .draw(display)
.unwrap(); .unwrap();
Ok(())
core::future::ready(()) }
} }
fn handle_input(&self, input: Action) -> impl core::future::Future<Output = NewState> + Send { fn handle_input(&self, input: Action) -> impl core::future::Future<Output = NewState> + Send {
+7 -4
View File
@@ -2,6 +2,8 @@ use crate::navigation::navigation::{Action, Navigable, NewState};
use crate::navigation::outputs::Outputs; use crate::navigation::outputs::Outputs;
use crate::peripherals::Peripherals; use crate::peripherals::Peripherals;
use crate::views::{flash_info_view::FlashInfoView, menu_item, view::View}; use crate::views::{flash_info_view::FlashInfoView, menu_item, view::View};
use alloc::boxed::Box;
use core::error;
use crate::navigation::inputs::ButtonAction; use crate::navigation::inputs::ButtonAction;
@@ -20,15 +22,16 @@ impl Navigable for SettingsMenu {
fn display( fn display(
&self, &self,
outputs: &mut Outputs, outputs: &mut Outputs,
_: &Peripherals _: &Peripherals,
) -> impl core::future::Future<Output = ()> + Send { ) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send {
async move {
let display = &mut outputs.primary_display; let display = &mut outputs.primary_display;
display.clear(Rgb565::BLACK).unwrap(); display.clear(Rgb565::BLACK).unwrap();
menu_item::show(display, "System Inforation", 0, self.selected); menu_item::show(display, "System Inforation", 0, self.selected);
menu_item::show(display, "Wifi Information", 1, self.selected); menu_item::show(display, "Wifi Information", 1, self.selected);
menu_item::show(display, "Flash Information", 2, self.selected); menu_item::show(display, "Flash Information", 2, self.selected);
Ok(())
core::future::ready(()) }
} }
fn handle_input(&self, input: Action) -> impl core::future::Future<Output = NewState> + Send { fn handle_input(&self, input: Action) -> impl core::future::Future<Output = NewState> + Send {
+2
View File
@@ -1 +1,3 @@
use alloc::boxed::Box;
use core::error;
// Status bar view module // Status bar view module
+9 -4
View File
@@ -2,14 +2,17 @@ use crate::navigation::outputs::Outputs;
use crate::peripherals::Peripherals; use crate::peripherals::Peripherals;
use crate::views::card_view::CardView; use crate::views::card_view::CardView;
use crate::views::{ use crate::views::{
flash_info_view::FlashInfoView, journal_view::JournalView, main_menu::MainMenu, error_view::ErrorView, flash_info_view::FlashInfoView, journal_view::JournalView,
scan_menu::ScanMenu, settings_menu::SettingsMenu, main_menu::MainMenu, scan_menu::ScanMenu, settings_menu::SettingsMenu,
}; };
use alloc::boxed::Box;
use core::error;
use crate::navigation::navigation::{Navigable, NewState}; use crate::navigation::navigation::{Navigable, NewState};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum View { pub enum View {
Error(ErrorView),
Main(MainMenu), Main(MainMenu),
Scan(ScanMenu), Scan(ScanMenu),
Settings(SettingsMenu), Settings(SettingsMenu),
@@ -22,10 +25,11 @@ impl Navigable for View {
fn display( fn display(
&self, &self,
outputs: &mut Outputs, outputs: &mut Outputs,
peripherals: &Peripherals peripherals: &Peripherals,
) -> impl core::future::Future<Output = ()> + Send { ) -> impl core::future::Future<Output = Result<(), Box<dyn error::Error>>> + Send {
async move { async move {
match self { match self {
View::Error(error_view) => error_view.display(outputs, peripherals).await,
View::Main(main_menu) => main_menu.display(outputs, peripherals).await, View::Main(main_menu) => main_menu.display(outputs, peripherals).await,
View::Scan(scan_menu) => scan_menu.display(outputs, peripherals).await, View::Scan(scan_menu) => scan_menu.display(outputs, peripherals).await,
View::Settings(settings_menu) => settings_menu.display(outputs, peripherals).await, View::Settings(settings_menu) => settings_menu.display(outputs, peripherals).await,
@@ -44,6 +48,7 @@ impl Navigable for View {
) -> impl core::future::Future<Output = NewState> + Send { ) -> impl core::future::Future<Output = NewState> + Send {
async move { async move {
match self { match self {
View::Error(error_view) => error_view.handle_input(input).await,
View::Main(main_menu) => main_menu.handle_input(input).await, View::Main(main_menu) => main_menu.handle_input(input).await,
View::Scan(scan_menu) => scan_menu.handle_input(input).await, View::Scan(scan_menu) => scan_menu.handle_input(input).await,
View::Settings(settings_menu) => settings_menu.handle_input(input).await, View::Settings(settings_menu) => settings_menu.handle_input(input).await,