morpheus_bootloader/tui/iso_manager/
state.rsuse morpheus_core::iso::{IsoEntry, IsoStorageManager, MAX_ISOS};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ViewMode {
List,
Details,
ConfirmDelete,
ConfirmBoot,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Action {
None,
Back,
Boot(usize),
Delete(usize),
Refresh,
}
pub struct IsoManagerState {
pub mode: ViewMode,
pub selected: usize,
pub count: usize,
pub names: [[u8; 64]; MAX_ISOS],
pub name_lens: [usize; MAX_ISOS],
pub sizes_mb: [u64; MAX_ISOS],
pub chunk_counts: [usize; MAX_ISOS],
pub complete: [bool; MAX_ISOS],
pub error_msg: Option<&'static str>,
}
impl IsoManagerState {
pub fn new() -> Self {
Self {
mode: ViewMode::List,
selected: 0,
count: 0,
names: [[0u8; 64]; MAX_ISOS],
name_lens: [0; MAX_ISOS],
sizes_mb: [0; MAX_ISOS],
chunk_counts: [0; MAX_ISOS],
complete: [false; MAX_ISOS],
error_msg: None,
}
}
pub fn load_from_manager(&mut self, manager: &IsoStorageManager) {
self.count = manager.count();
self.selected = self.selected.min(self.count.saturating_sub(1));
for (i, (_, entry)) in manager.iter().enumerate() {
if i >= MAX_ISOS {
break;
}
let manifest = &entry.manifest;
let name_len = manifest.name_len.min(64);
self.names[i][..name_len].copy_from_slice(&manifest.name[..name_len]);
self.name_lens[i] = name_len;
self.sizes_mb[i] = manifest.total_size / (1024 * 1024);
self.chunk_counts[i] = manifest.chunks.count;
self.complete[i] = manifest.is_complete();
}
}
pub fn selected_name(&self) -> &str {
if self.selected < self.count {
core::str::from_utf8(&self.names[self.selected][..self.name_lens[self.selected]])
.unwrap_or("???")
} else {
""
}
}
pub fn selected_size_mb(&self) -> u64 {
if self.selected < self.count {
self.sizes_mb[self.selected]
} else {
0
}
}
pub fn selected_chunks(&self) -> usize {
if self.selected < self.count {
self.chunk_counts[self.selected]
} else {
0
}
}
pub fn selected_complete(&self) -> bool {
if self.selected < self.count {
self.complete[self.selected]
} else {
false
}
}
pub fn select_prev(&mut self) {
if self.selected > 0 {
self.selected -= 1;
}
}
pub fn select_next(&mut self) {
if self.count > 0 && self.selected < self.count - 1 {
self.selected += 1;
}
}
pub fn handle_key(&mut self, scan_code: u16, unicode: u16) -> Action {
match self.mode {
ViewMode::List => self.handle_list_key(scan_code, unicode),
ViewMode::Details => self.handle_details_key(scan_code, unicode),
ViewMode::ConfirmDelete => self.handle_confirm_delete_key(scan_code, unicode),
ViewMode::ConfirmBoot => self.handle_confirm_boot_key(scan_code, unicode),
}
}
fn handle_list_key(&mut self, scan_code: u16, unicode: u16) -> Action {
if scan_code == 0x17 {
return Action::Back;
}
if scan_code == 0x01 {
self.select_prev();
return Action::None;
}
if scan_code == 0x02 {
self.select_next();
return Action::None;
}
if unicode == 0x0D && self.count > 0 {
self.mode = ViewMode::Details;
return Action::None;
}
if (unicode == 0x64 || unicode == 0x44) && self.count > 0 {
self.mode = ViewMode::ConfirmDelete;
return Action::None;
}
if (unicode == 0x62 || unicode == 0x42) && self.count > 0 && self.selected_complete() {
self.mode = ViewMode::ConfirmBoot;
return Action::None;
}
if unicode == 0x72 || unicode == 0x52 {
return Action::Refresh;
}
Action::None
}
fn handle_details_key(&mut self, scan_code: u16, unicode: u16) -> Action {
if scan_code == 0x17 || unicode == 0x08 {
self.mode = ViewMode::List;
return Action::None;
}
if (unicode == 0x62 || unicode == 0x42) && self.selected_complete() {
self.mode = ViewMode::ConfirmBoot;
return Action::None;
}
if unicode == 0x64 || unicode == 0x44 {
self.mode = ViewMode::ConfirmDelete;
return Action::None;
}
Action::None
}
fn handle_confirm_delete_key(&mut self, _scan_code: u16, unicode: u16) -> Action {
if unicode == 0x79 || unicode == 0x59 {
let idx = self.selected;
self.mode = ViewMode::List;
return Action::Delete(idx);
}
if unicode == 0x6E || unicode == 0x4E || unicode == 0x1B {
self.mode = ViewMode::List;
return Action::None;
}
Action::None
}
fn handle_confirm_boot_key(&mut self, _scan_code: u16, unicode: u16) -> Action {
if unicode == 0x79 || unicode == 0x59 {
let idx = self.selected;
self.mode = ViewMode::List;
return Action::Boot(idx);
}
if unicode == 0x6E || unicode == 0x4E || unicode == 0x1B {
self.mode = ViewMode::List;
return Action::None;
}
Action::None
}
pub fn set_error(&mut self, msg: &'static str) {
self.error_msg = Some(msg);
}
pub fn clear_error(&mut self) {
self.error_msg = None;
}
}
impl Default for IsoManagerState {
fn default() -> Self {
Self::new()
}
}