diff --git a/src/rust/bitbox02-rust/src/hww/api/bip85.rs b/src/rust/bitbox02-rust/src/hww/api/bip85.rs index 52a2a586b5..5d629a5991 100644 --- a/src/rust/bitbox02-rust/src/hww/api/bip85.rs +++ b/src/rust/bitbox02-rust/src/hww/api/bip85.rs @@ -100,7 +100,7 @@ pub async fn process(pb::Bip85Request {}: &pb::Bip85Request) -> Result = mnemonic.split(' ').collect(); - mnemonic::show_mnemonic(&words).await?; + mnemonic::show_mnemonic(&words, false).await?; status::status("Finished", true).await; diff --git a/src/rust/bitbox02-rust/src/hww/api/show_mnemonic.rs b/src/rust/bitbox02-rust/src/hww/api/show_mnemonic.rs index ac9c29aa76..3fefca7a27 100644 --- a/src/rust/bitbox02-rust/src/hww/api/show_mnemonic.rs +++ b/src/rust/bitbox02-rust/src/hww/api/show_mnemonic.rs @@ -88,7 +88,7 @@ pub async fn process() -> Result { let words: Vec<&str> = mnemonic_sentence.split(' ').collect(); // Part 1) Scroll through words - mnemonic::show_mnemonic(&words).await?; + mnemonic::show_mnemonic(&words, true).await?; confirm::confirm(&confirm::Params { title: "", @@ -109,7 +109,9 @@ pub async fn process() -> Result { loop { match mnemonic::confirm_word(&choices, &title).await? { selected_idx if selected_idx == correct_idx => break, - selected_idx if selected_idx == back_idx => mnemonic::show_mnemonic(&words).await?, + selected_idx if selected_idx == back_idx => { + mnemonic::show_mnemonic(&words, true).await? + } _ => status::status("Incorrect word\nTry again", false).await, } } diff --git a/src/rust/bitbox02-rust/src/workflow/menu.rs b/src/rust/bitbox02-rust/src/workflow/menu.rs index 1819309e40..9611f292b1 100644 --- a/src/rust/bitbox02-rust/src/workflow/menu.rs +++ b/src/rust/bitbox02-rust/src/workflow/menu.rs @@ -29,6 +29,7 @@ pub async fn pick(words: &[&str], title: Option<&str>) -> Result]) -> Vec<&str> { } /// Displays all mnemonic words in a scroll-through screen. -pub async fn show_mnemonic(words: &[&str]) -> Result<(), CancelError> { +/// +/// If `continue_on_finish` is true, a "Continue" button appears when reaching the last +/// word. Otherwise, a checkmark appears. +pub async fn show_mnemonic(words: &[&str], continue_on_finish: bool) -> Result<(), CancelError> { let result = RefCell::new(None); let mut component = bitbox02::ui::menu_create(bitbox02::ui::MenuParams { words, @@ -41,6 +44,7 @@ pub async fn show_mnemonic(words: &[&str]) -> Result<(), CancelError> { finish_on_last_cb: Some(Box::new(|| { set_result(&result, ()); })), + continue_on_finish, cancel_cb: Some(Box::new(|| { cancel(&result); })), @@ -58,6 +62,7 @@ pub async fn confirm_word(choices: &[&str], title: &str) -> Result { pub title: Option<&'a str>, pub select_word_cb: Option>, pub finish_on_last_cb: Option>, + pub continue_on_finish: bool, pub cancel_cb: Option>, } diff --git a/src/rust/bitbox02/src/ui/ui.rs b/src/rust/bitbox02/src/ui/ui.rs index 6a194296c3..ac110d32fe 100644 --- a/src/rust/bitbox02/src/ui/ui.rs +++ b/src/rust/bitbox02/src/ui/ui.rs @@ -291,6 +291,7 @@ pub fn menu_create(params: MenuParams<'_>) -> Component<'_> { .map_or_else(|| core::ptr::null(), |title| title.as_ptr()), finish_on_last_cb, finish_on_last_cb_param, + params.continue_on_finish, cancel_cb, cancel_cb_param, core::ptr::null_mut(), diff --git a/src/ui/components/menu.c b/src/ui/components/menu.c index fab1df30b8..6a45f1d88d 100644 --- a/src/ui/components/menu.c +++ b/src/ui/components/menu.c @@ -44,6 +44,7 @@ typedef struct { component_t* finish_on_last_button; void (*finish_on_last_cb)(void*); void* finish_on_last_cb_param; + bool continue_on_finish; void (*cancel_cb)(void*); void* cancel_cb_param; } menu_data_t; @@ -107,8 +108,13 @@ static void _update_positions(component_t* menu, int32_t velocity) if (data->index == data->length - 1 && data->finish_on_last_cb != NULL && data->finish_on_last_button == NULL) { - data->finish_on_last_button = - button_create("Continue", top_slider, SCREEN_WIDTH - 23, _finish, menu); + if (data->continue_on_finish) { + data->finish_on_last_button = + button_create("Continue", top_slider, SCREEN_WIDTH - 23, _finish, menu); + } else { + data->finish_on_last_button = + icon_button_create(top_slider, ICON_BUTTON_CHECK, _finish); + } ui_util_add_sub_component(menu, data->finish_on_last_button); } } @@ -238,6 +244,7 @@ component_t* menu_create( const char* title, void (*finish_on_last_cb)(void*), void* finish_on_last_cb_param, + bool continue_on_finish, void (*cancel_cb)(void*), void* cancel_cb_param, component_t* parent) @@ -274,6 +281,7 @@ component_t* menu_create( data->finish_on_last_cb = finish_on_last_cb; data->finish_on_last_cb_param = finish_on_last_cb_param; data->finish_on_last_button = NULL; + data->continue_on_finish = continue_on_finish; data->cancel_cb = cancel_cb; data->cancel_cb_param = cancel_cb_param; menu->data = data; diff --git a/src/ui/components/menu.h b/src/ui/components/menu.h index e27714b232..0f9758fb52 100644 --- a/src/ui/components/menu.h +++ b/src/ui/components/menu.h @@ -23,13 +23,15 @@ * @param[in] words The words that are displayed on the screen, and through which you can slide * through. * @param[in] select_word_cb If specified, the callback will be called if the user selects a word. - * The parameter is the index of the selected word. Should not be used with show_index. + * The parameter is the index of the selected word. * @param[in] length The word list length. * @param[in] title Title for the window. * If NULL, displays the index of the current word instead (starting at 1). * For no title, set this to "". - * @param[in] finish_on_last_cb If set, a checkmark appears when reaching the last word, calling - * this callback. + * @param[in] finish_on_last_cb If set, a checkmark or continue button appears when reaching the + * last word, calling this callback. + * @param[in] continue_on_finish determines if the button at the last word is "Continue" or a + * checkmark. * @param[in] cancel_cb Called when the cancel button is pressed. * @param[in] parent The parent component. */ @@ -41,6 +43,7 @@ component_t* menu_create( const char* title, void (*finish_on_last_cb)(void*), void* finish_on_last_cb_param, + bool continue_on_finish, void (*cancel_cb)(void*), void* cancel_cb_param, component_t* parent);