From ada8c8c01544f8ce954246873cb304f3b9f69dbe Mon Sep 17 00:00:00 2001 From: Marko Bencun Date: Thu, 18 May 2023 05:04:11 +0200 Subject: [PATCH] bip85: show checkmark instead of "Continue" at the end of the mnemonic So far it has been "Continue" as showing the mnemonic was always in the middle of some other workflow. With BIP-85, showing the BIP-39 mnemonic is at the end of a workflow, so a checkmark is more appropriate. --- src/rust/bitbox02-rust/src/hww/api/bip85.rs | 2 +- src/rust/bitbox02-rust/src/hww/api/show_mnemonic.rs | 6 ++++-- src/rust/bitbox02-rust/src/workflow/menu.rs | 1 + src/rust/bitbox02-rust/src/workflow/mnemonic.rs | 7 ++++++- src/rust/bitbox02/src/ui/types.rs | 1 + src/rust/bitbox02/src/ui/ui.rs | 1 + src/ui/components/menu.c | 12 ++++++++++-- src/ui/components/menu.h | 9 ++++++--- 8 files changed, 30 insertions(+), 9 deletions(-) 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);