From ab3dc3832277580b4d05c301301f2a34858994d9 Mon Sep 17 00:00:00 2001 From: Ayush Singh <ayush@beagleboard.org> Date: Tue, 26 Nov 2024 19:04:06 +0530 Subject: [PATCH] gui: Improve cancel messages - More accurate messages when cancelled by user (seperate for preparation, flashing and verification) Changelog: other Signed-off-by: Ayush Singh <ayush@beagleboard.org> --- gui/src/helpers.rs | 74 ++++++++++++++++++++++++++++------- gui/src/main.rs | 27 ++++++++----- gui/src/pages/flash.rs | 89 ++++++++++++++++++------------------------ gui/src/pages/mod.rs | 4 +- 4 files changed, 115 insertions(+), 79 deletions(-) diff --git a/gui/src/helpers.rs b/gui/src/helpers.rs index 7afdea0..e5cb80e 100644 --- a/gui/src/helpers.rs +++ b/gui/src/helpers.rs @@ -43,19 +43,28 @@ pub struct ProgressBarState { label: Cow<'static, str>, progress: f32, state: ProgressBarStatus, + inner_state: Option<bb_imager::DownloadFlashingStatus>, } impl ProgressBarState { pub const FLASHING_SUCCESS: Self = - Self::const_new("Flashing Successful", 1.0, ProgressBarStatus::Success); - pub const PREPARING: Self = Self::loading("Preparing..."); - pub const VERIFYING: Self = Self::loading("Verifying..."); - - const fn const_new(label: &'static str, progress: f32, state: ProgressBarStatus) -> Self { + Self::const_new("Flashing Successful", 1.0, ProgressBarStatus::Success, None); + pub const PREPARING: Self = + Self::loading("Preparing...", bb_imager::DownloadFlashingStatus::Preparing); + pub const VERIFYING: Self = + Self::loading("Verifying...", bb_imager::DownloadFlashingStatus::Verifying); + + const fn const_new( + label: &'static str, + progress: f32, + state: ProgressBarStatus, + inner_state: Option<bb_imager::DownloadFlashingStatus>, + ) -> Self { Self { label: Cow::Borrowed(label), progress, state, + inner_state, } } @@ -63,29 +72,40 @@ impl ProgressBarState { self.label.to_string() } - fn new(label: impl Into<Cow<'static, str>>, progress: f32, state: ProgressBarStatus) -> Self { + fn new( + label: impl Into<Cow<'static, str>>, + progress: f32, + state: ProgressBarStatus, + inner_state: Option<bb_imager::DownloadFlashingStatus>, + ) -> Self { Self { label: label.into(), progress, state, + inner_state, } } /// Progress should be between 0 to 1.0 - fn progress(prefix: &'static str, progress: f32) -> Self { + fn progress( + prefix: &'static str, + progress: f32, + inner_state: bb_imager::DownloadFlashingStatus, + ) -> Self { Self::new( format!("{prefix}... {}%", (progress * 100.0).round() as usize), progress, ProgressBarStatus::Normal, + Some(inner_state), ) } - const fn loading(label: &'static str) -> Self { - Self::const_new(label, 0.5, ProgressBarStatus::Loading) + const fn loading(label: &'static str, inner_state: bb_imager::DownloadFlashingStatus) -> Self { + Self::const_new(label, 0.5, ProgressBarStatus::Loading, Some(inner_state)) } pub fn fail(label: impl Into<Cow<'static, str>>) -> Self { - Self::new(label, 1.0, ProgressBarStatus::Fail) + Self::new(label, 1.0, ProgressBarStatus::Fail, None) } pub fn bar(&self) -> widget::Column<'_, BBImagerMessage> { @@ -104,19 +124,43 @@ impl ProgressBarState { .padding(30) .spacing(10) } + + pub fn cancel(&self) -> Option<Self> { + match self.inner_state? { + bb_imager::DownloadFlashingStatus::Preparing => { + Some(Self::fail("Preparation cancelled by user")) + } + bb_imager::DownloadFlashingStatus::DownloadingProgress(_) => { + Some(Self::fail("Downloading cancelled by user")) + } + bb_imager::DownloadFlashingStatus::FlashingProgress(_) => { + Some(Self::fail("Flashing cancelled by user")) + } + bb_imager::DownloadFlashingStatus::Verifying + | bb_imager::DownloadFlashingStatus::VerifyingProgress(_) => { + Some(Self::fail("Verification cancelled by user")) + } + } + } } impl From<bb_imager::DownloadFlashingStatus> for ProgressBarState { fn from(value: bb_imager::DownloadFlashingStatus) -> Self { match value { bb_imager::DownloadFlashingStatus::Preparing => Self::PREPARING, - bb_imager::DownloadFlashingStatus::DownloadingProgress(p) => { - Self::progress("Downloading Image", p) - } - bb_imager::DownloadFlashingStatus::FlashingProgress(p) => Self::progress("Flashing", p), + bb_imager::DownloadFlashingStatus::DownloadingProgress(p) => Self::progress( + "Downloading Image", + p, + bb_imager::DownloadFlashingStatus::DownloadingProgress(0.0), + ), + bb_imager::DownloadFlashingStatus::FlashingProgress(p) => Self::progress( + "Flashing", + p, + bb_imager::DownloadFlashingStatus::FlashingProgress(0.0), + ), bb_imager::DownloadFlashingStatus::Verifying => Self::VERIFYING, bb_imager::DownloadFlashingStatus::VerifyingProgress(p) => { - Self::progress("Verifying", p) + Self::progress("Verifying", p, bb_imager::DownloadFlashingStatus::Verifying) } } } diff --git a/gui/src/main.rs b/gui/src/main.rs index 0040a89..a9753cb 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -61,6 +61,7 @@ struct BBImager { search_bar: String, cancel_flashing: Option<iced::task::Handle>, flashing_config: Option<bb_imager::FlashingConfig>, + flashing_state: Option<pages::flash::FlashingState>, timezones: widget::combo_box::State<String>, keymaps: widget::combo_box::State<String>, @@ -199,10 +200,8 @@ impl BBImager { return Task::batch(jobs.chain([self.refresh_destinations()])); } BBImagerMessage::ProgressBar(x) => { - // Ignore progress bar update if not in the current screen - if let Screen::Flashing(s) = self.screen.clone() { - self.screen = - Screen::Flashing(s.update_progress(x, self.cancel_flashing.is_some())) + if let Some(state) = self.flashing_state.take() { + self.flashing_state = Some(state.update(x)); } } BBImagerMessage::SelectImage(x) => { @@ -272,17 +271,22 @@ impl BBImager { task.abort(); } - return Task::done(BBImagerMessage::StopFlashing(ProgressBarState::fail( - "Flashing Cancelled by user", - ))); + if let Some(x) = &self.flashing_state { + if let Some(y) = x.progress.cancel() { + return Task::done(BBImagerMessage::StopFlashing(y)); + } + } } BBImagerMessage::StartFlashing => { let docs_url = &self .boards .device(self.selected_board.as_ref().expect("Missing board")) .documentation; - self.screen = - Screen::Flashing(pages::flash::FlashingScreen::new(docs_url.to_string())); + self.screen = Screen::Flashing; + self.flashing_state = Some(pages::flash::FlashingState::new( + ProgressBarState::PREPARING, + docs_url.to_string(), + )); let dst = self.selected_dst.clone().expect("No destination selected"); let img = self.selected_image.clone().expect("Missing os image"); @@ -411,7 +415,10 @@ impl BBImager { &self.timezones, &self.keymaps, ), - Screen::Flashing(s) => s.view(), + Screen::Flashing => pages::flash::view( + self.flashing_state.as_ref().unwrap(), + self.cancel_flashing.is_some(), + ), } } diff --git a/gui/src/pages/flash.rs b/gui/src/pages/flash.rs index d55d583..9568206 100644 --- a/gui/src/pages/flash.rs +++ b/gui/src/pages/flash.rs @@ -7,70 +7,24 @@ use crate::{ }; #[derive(Debug, Clone)] -pub struct FlashingScreen { - progress: ProgressBarState, +pub struct FlashingState { + pub(crate) progress: ProgressBarState, documentation: String, - running: bool, } -impl Default for FlashingScreen { - fn default() -> Self { - FlashingScreen { - progress: ProgressBarState::PREPARING, - documentation: String::new(), - running: true, - } - } -} - -impl FlashingScreen { - pub fn new(documentation: String) -> Self { +impl FlashingState { + pub fn new(progress: ProgressBarState, documentation: String) -> Self { Self { documentation, - ..Default::default() + progress, } } - pub fn update_progress(mut self, progress: ProgressBarState, running: bool) -> Self { + pub fn update(mut self, progress: ProgressBarState) -> Self { self.progress = progress; - self.running = running; self } - pub fn view(&self) -> Element<BBImagerMessage> { - widget::responsive(|size| { - let prog_bar = self.progress.bar(); - - let btn = if self.running { - home_btn("CANCEL", true, iced::Length::Shrink) - .on_press(BBImagerMessage::CancelFlashing) - } else { - home_btn("HOME", true, iced::Length::Shrink) - .on_press(BBImagerMessage::SwitchScreen(Screen::Home)) - }; - - let bottom = widget::container( - widget::column![self.about().height(size.height - 410.0), btn, prog_bar] - .width(iced::Length::Fill) - .height(iced::Length::Fill) - .align_x(iced::Alignment::Center), - ) - .style(|_| { - widget::container::background( - iced::Color::parse("#aa5137").expect("unexpected error"), - ) - }); - - widget::column![helpers::logo(), bottom] - .spacing(10) - .width(iced::Length::Fill) - .height(iced::Length::Fill) - .align_x(iced::Alignment::Center) - .into() - }) - .into() - } - fn about(&self) -> widget::Container<'_, BBImagerMessage> { widget::container(widget::scrollable(widget::rich_text![ widget::span(constants::BEAGLE_BOARD_ABOUT) @@ -86,3 +40,34 @@ impl FlashingScreen { .padding(32) } } + +pub fn view(state: &FlashingState, running: bool) -> Element<BBImagerMessage> { + widget::responsive(move |size| { + let prog_bar = state.progress.bar(); + + let btn = if running { + home_btn("CANCEL", true, iced::Length::Shrink).on_press(BBImagerMessage::CancelFlashing) + } else { + home_btn("HOME", true, iced::Length::Shrink) + .on_press(BBImagerMessage::SwitchScreen(Screen::Home)) + }; + + let bottom = widget::container( + widget::column![state.about().height(size.height - 410.0), btn, prog_bar] + .width(iced::Length::Fill) + .height(iced::Length::Fill) + .align_x(iced::Alignment::Center), + ) + .style(|_| { + widget::container::background(iced::Color::parse("#aa5137").expect("unexpected error")) + }); + + widget::column![helpers::logo(), bottom] + .spacing(10) + .width(iced::Length::Fill) + .height(iced::Length::Fill) + .align_x(iced::Alignment::Center) + .into() + }) + .into() +} diff --git a/gui/src/pages/mod.rs b/gui/src/pages/mod.rs index 15f4f2e..112c6ac 100644 --- a/gui/src/pages/mod.rs +++ b/gui/src/pages/mod.rs @@ -5,7 +5,7 @@ pub mod flash; pub mod home; pub mod image_selection; -#[derive(Default, Debug, Clone)] +#[derive(Default, Debug, Clone, Copy)] pub enum Screen { #[default] Home, @@ -13,5 +13,5 @@ pub enum Screen { ImageSelection, DestinationSelection, ExtraConfiguration, - Flashing(flash::FlashingScreen), + Flashing, } -- GitLab