Skip to content

Commit

Permalink
src/ui: Update NBGL UI based on new API
Browse files Browse the repository at this point in the history
  • Loading branch information
Xavier Chapron committed Apr 11, 2024
1 parent 23f7b03 commit a06b24f
Show file tree
Hide file tree
Showing 36 changed files with 98 additions and 148 deletions.
5 changes: 0 additions & 5 deletions src/ui/menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@
*/
void ui_menu_main(void);

/**
* Show settings menu (App version, developer name and settings).
*/
void ui_menu_settings(void);

/**
* Show about submenu (copyright, date).
*/
Expand Down
133 changes: 64 additions & 69 deletions src/ui/menu_nbgl.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,91 +34,74 @@ void app_quit(void) {
os_sched_exit(-1);
}

// home page definition
void ui_menu_main(void) {
// This parameter shall be set to false if the settings page contains only information
// about the application (version , developer name, ...). It shall be set to
// true if the settings page also contains user configurable parameters related to the
// operation of the application.
#define SETTINGS_BUTTON_ENABLED (true)

nbgl_useCaseHome(APPNAME,
&C_app_boilerplate_64px,
NULL,
SETTINGS_BUTTON_ENABLED,
ui_menu_settings,
app_quit);
}

// -----------------------------------------------------------
// --------------------- SETTINGS MENU -----------------------
// -----------------------------------------------------------

static const char* const INFO_TYPES[] = {"Version", "Developer"};
static const char* const INFO_CONTENTS[] = {APPVERSION, "Ledger"};
#define SETTING_INFO_NB 2
static const char* const INFO_TYPES[SETTING_INFO_NB] = {"Version", "Developer"};
static const char* const INFO_CONTENTS[SETTING_INFO_NB] = {APPVERSION, "Ledger"};

// settings switches definitions
enum { DUMMY_SWITCH_1_TOKEN = FIRST_USER_TOKEN, DUMMY_SWITCH_2_TOKEN };
enum { DUMMY_SWITCH_1_ID = 0, DUMMY_SWITCH_2_ID, SETTINGS_SWITCHES_NB };

static nbgl_layoutSwitch_t switches[SETTINGS_SWITCHES_NB] = {0};
static nbgl_contentSwitch_t switches[SETTINGS_SWITCHES_NB] = {0};

static bool nav_callback(uint8_t page, nbgl_pageContent_t* content) {
UNUSED(page);
static const nbgl_contentInfoList_t infoList = {
.nbInfos = SETTING_INFO_NB,
.infoTypes = INFO_TYPES,
.infoContents = INFO_CONTENTS,
};

// the first settings page contains only the version and the developer name
// of the app (shall be always on the first setting page)
if (page == 0) {
content->type = INFOS_LIST;
content->infosList.nbInfos = 2;
content->infosList.infoTypes = INFO_TYPES;
content->infosList.infoContents = INFO_CONTENTS;
}
// the second settings page contains 2 toggle setting switches
else if (page == 1) {
switches[DUMMY_SWITCH_1_ID].initState = (nbgl_state_t) N_storage.dummy1_allowed;
switches[DUMMY_SWITCH_1_ID].text = "Dummy 1";
switches[DUMMY_SWITCH_1_ID].subText = "Allow dummy 1\nin transactions";
switches[DUMMY_SWITCH_1_ID].token = DUMMY_SWITCH_1_TOKEN;
switches[DUMMY_SWITCH_1_ID].tuneId = TUNE_TAP_CASUAL;

switches[DUMMY_SWITCH_2_ID].initState = (nbgl_state_t) N_storage.dummy2_allowed;
switches[DUMMY_SWITCH_2_ID].text = "Dummy 2";
switches[DUMMY_SWITCH_2_ID].subText = "Allow dummy 2\nin transactions";
switches[DUMMY_SWITCH_2_ID].token = DUMMY_SWITCH_2_TOKEN;
switches[DUMMY_SWITCH_2_ID].tuneId = TUNE_TAP_CASUAL;

content->type = SWITCHES_LIST;
content->switchesList.nbSwitches = SETTINGS_SWITCHES_NB;
content->switchesList.switches = (nbgl_layoutSwitch_t*) switches;
} else {
return false;
}
// valid page so return true
return true;
}
static uint8_t initSettingPage;
static void review_warning_choice(bool confirm);
static void controls_callback(int token, uint8_t index, int page);

// settings menu definition
#define SETTING_CONTENTS_NB 1
static const nbgl_content_t contents[SETTING_CONTENTS_NB] = {
{.type = SWITCHES_LIST,
.content.switchesList.nbSwitches = SETTINGS_SWITCHES_NB,
.content.switchesList.switches = switches,
.contentActionCallback = controls_callback}};

static const nbgl_genericContents_t settingContents = {.callbackCallNeeded = false,
.contentsList = contents,
.nbContents = SETTING_CONTENTS_NB};

// callback for setting warning choice
static void review_warning_choice(bool confirm) {
uint8_t switch_value;
if (confirm) {
// toggle the switch value
switch_value = !N_storage.dummy2_allowed;
switches[DUMMY_SWITCH_2_ID].initState = (nbgl_state_t) switch_value;
// store the new setting value in NVM
nvm_write((void*) &N_storage.dummy2_allowed, &switch_value, 1);
}

// return to the settings menu
ui_menu_settings();
// Reset setting menu to the right page
nbgl_useCaseHomeAndSettings(APPNAME,
&C_app_boilerplate_64px,
NULL,
initSettingPage,
&settingContents,
&infoList,
NULL,
app_quit);
}

static void controls_callback(int token, uint8_t index) {
static void controls_callback(int token, uint8_t index, int page) {
UNUSED(index);

initSettingPage = page;

uint8_t switch_value;
if (token == DUMMY_SWITCH_1_TOKEN) {
// Dummy 1 switch touched
// toggle the switch value
switch_value = !N_storage.dummy1_allowed;
switches[DUMMY_SWITCH_1_ID].initState = (nbgl_state_t) switch_value;
// store the new setting value in NVM
nvm_write((void*) &N_storage.dummy1_allowed, &switch_value, 1);
} else if (token == DUMMY_SWITCH_2_TOKEN) {
Expand All @@ -128,7 +111,7 @@ static void controls_callback(int token, uint8_t index) {
// to activate the dummy 2 setting
if (!N_storage.dummy2_allowed) {
// Display the warning message and ask the user to confirm
nbgl_useCaseChoice(&C_warning64px,
nbgl_useCaseChoice(&C_Warning_64px,
"Dummy 2",
"Are you sure to\nallow dummy 2\nin transactions?",
"I understand, confirm",
Expand All @@ -137,24 +120,36 @@ static void controls_callback(int token, uint8_t index) {
} else {
// toggle the switch value
switch_value = !N_storage.dummy2_allowed;
switches[DUMMY_SWITCH_2_ID].initState = (nbgl_state_t) switch_value;
// store the new setting value in NVM
nvm_write((void*) &N_storage.dummy2_allowed, &switch_value, 1);
}
}
}

// settings menu definition
void ui_menu_settings() {
#define TOTAL_SETTINGS_PAGE (2)
#define INIT_SETTINGS_PAGE (0)
#define DISABLE_SUB_SETTINGS (false)
nbgl_useCaseSettings(APPNAME,
INIT_SETTINGS_PAGE,
TOTAL_SETTINGS_PAGE,
DISABLE_SUB_SETTINGS,
ui_menu_main,
nav_callback,
controls_callback);
// home page definition
void ui_menu_main(void) {
// Initialize switches data
switches[DUMMY_SWITCH_1_ID].initState = (nbgl_state_t) N_storage.dummy1_allowed;
switches[DUMMY_SWITCH_1_ID].text = "Dummy 1";
switches[DUMMY_SWITCH_1_ID].subText = "Allow dummy 1\nin transactions";
switches[DUMMY_SWITCH_1_ID].token = DUMMY_SWITCH_1_TOKEN;
switches[DUMMY_SWITCH_1_ID].tuneId = TUNE_TAP_CASUAL;

switches[DUMMY_SWITCH_2_ID].initState = (nbgl_state_t) N_storage.dummy2_allowed;
switches[DUMMY_SWITCH_2_ID].text = "Dummy 2";
switches[DUMMY_SWITCH_2_ID].subText = "Allow dummy 2\nin transactions";
switches[DUMMY_SWITCH_2_ID].token = DUMMY_SWITCH_2_TOKEN;
switches[DUMMY_SWITCH_2_ID].tuneId = TUNE_TAP_CASUAL;

nbgl_useCaseHomeAndSettings(APPNAME,
&C_app_boilerplate_64px,
NULL,
INIT_HOME_PAGE,
&settingContents,
&infoList,
NULL,
app_quit);
}

#endif
35 changes: 11 additions & 24 deletions src/ui/nbgl_display_address.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,35 +38,22 @@

static char g_address[43];

static void confirm_address_rejection(void) {
// display a status page and go back to main
validate_pubkey(false);
nbgl_useCaseStatus("Address verification\ncancelled", false, ui_menu_main);
}

static void confirm_address_approval(void) {
// display a success status page and go back to main
validate_pubkey(true);
nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, ui_menu_main);
}

static void review_choice(bool confirm) {
// Answer, display a status page and go back to main
validate_pubkey(confirm);
if (confirm) {
confirm_address_approval();
nbgl_useCaseReviewStatus(STATUS_TYPE_ADDRESS_VERIFIED, ui_menu_main);
} else {
confirm_address_rejection();
nbgl_useCaseReviewStatus(STATUS_TYPE_ADDRESS_REJECTED, ui_menu_main);
}
}

static void continue_review(void) {
nbgl_useCaseAddressConfirmation(g_address, review_choice);
}

int ui_display_address() {
if (G_context.req_type != CONFIRM_ADDRESS || G_context.state != STATE_NONE) {
G_context.state = STATE_NONE;
return io_send_sw(SW_BAD_STATE);
}

memset(g_address, 0, sizeof(g_address));
uint8_t address[ADDRESS_LEN] = {0};
if (!address_from_pubkey(G_context.pk_info.raw_public_key, address, sizeof(address))) {
Expand All @@ -77,12 +64,12 @@ int ui_display_address() {
return io_send_sw(SW_DISPLAY_ADDRESS_FAIL);
}

nbgl_useCaseReviewStart(&C_app_boilerplate_64px,
"Verify BOL address",
NULL,
"Cancel",
continue_review,
confirm_address_rejection);
nbgl_useCaseAddressReview(g_address,
NULL,
&C_app_boilerplate_64px,
"Verify BOL address",
NULL,
review_choice);
return 0;
}

Expand Down
68 changes: 22 additions & 46 deletions src/ui/nbgl_display_transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,54 +44,18 @@ static char g_address[43];

static nbgl_layoutTagValue_t pairs[2];
static nbgl_layoutTagValueList_t pairList;
static nbgl_pageInfoLongPress_t infoLongPress;

static void confirm_transaction_rejection(void) {
// display a status page and go back to main
validate_transaction(false);
nbgl_useCaseStatus("Transaction rejected", false, ui_menu_main);
}

static void ask_transaction_rejection_confirmation(void) {
// display a choice to confirm/cancel rejection
nbgl_useCaseConfirm("Reject transaction?",
NULL,
"Yes, Reject",
"Go back to transaction",
confirm_transaction_rejection);
}

// called when long press button on 3rd page is long-touched or when reject footer is touched
static void review_choice(bool confirm) {
// Answer, display a status page and go back to main
validate_transaction(confirm);
if (confirm) {
// display a status page and go back to main
validate_transaction(true);
nbgl_useCaseStatus("TRANSACTION\nSIGNED", true, ui_menu_main);
nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_SIGNED, ui_menu_main);
} else {
ask_transaction_rejection_confirmation();
nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_REJECTED, ui_menu_main);
}
}

static void review_continue(void) {
// Setup data to display
pairs[0].item = "Amount";
pairs[0].value = g_amount;
pairs[1].item = "Address";
pairs[1].value = g_address;

// Setup list
pairList.nbMaxLinesForValue = 0;
pairList.nbPairs = 2;
pairList.pairs = pairs;

// Info long press
infoLongPress.icon = &C_app_boilerplate_64px;
infoLongPress.text = "Sign transaction\nto send BOL";
infoLongPress.longPressText = "Hold to sign";

nbgl_useCaseStaticReview(&pairList, &infoLongPress, "Reject transaction", review_choice);
}

// Public function to start the transaction review
// - Check if the app is in the right state for transaction review
// - Format the amount and address strings in g_amount and g_address buffers
Expand Down Expand Up @@ -119,13 +83,25 @@ int ui_display_transaction() {
return io_send_sw(SW_DISPLAY_ADDRESS_FAIL);
}

// Setup data to display
pairs[0].item = "Amount";
pairs[0].value = g_amount;
pairs[1].item = "Address";
pairs[1].value = g_address;

// Setup list
pairList.nbMaxLinesForValue = 0;
pairList.nbPairs = 2;
pairList.pairs = pairs;

// Start review
nbgl_useCaseReviewStart(&C_app_boilerplate_64px,
"Review transaction\nto send BOL",
NULL,
"Reject transaction",
review_continue,
ask_transaction_rejection_confirmation);
nbgl_useCaseReview(TYPE_TRANSACTION,
&pairList,
&C_app_boilerplate_64px,
"Review transaction\nto send BOL",
NULL,
"Sign transaction\nto send BOL",
review_choice);
return 0;
}

Expand Down
Binary file modified tests/snapshots/stax/test_app_mainmenu/00001.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_app_mainmenu/00002.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_app_mainmenu/00003.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_app_mainmenu/00004.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_app_mainmenu/00005.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_app_mainmenu/00006.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_app_mainmenu/00007.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed tests/snapshots/stax/test_app_mainmenu/00008.png
Binary file not shown.
Binary file removed tests/snapshots/stax/test_app_mainmenu/00009.png
Binary file not shown.
Binary file removed tests/snapshots/stax/test_app_mainmenu/00010.png
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_get_public_key_confirm_accepted/00001.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_get_public_key_confirm_accepted/00003.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_sign_tx_long_tx/00000.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_sign_tx_long_tx/00001.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_sign_tx_long_tx/00002.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_sign_tx_long_tx/00003.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_sign_tx_refused/part0/00000.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_sign_tx_refused/part1/00000.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_sign_tx_refused/part1/00001.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_sign_tx_refused/part2/00000.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/snapshots/stax/test_sign_tx_refused/part2/00001.png
Binary file modified tests/snapshots/stax/test_sign_tx_refused/part2/00002.png
Binary file modified tests/snapshots/stax/test_sign_tx_short_tx/00000.png
Binary file modified tests/snapshots/stax/test_sign_tx_short_tx/00001.png
Binary file modified tests/snapshots/stax/test_sign_tx_short_tx/00002.png
Binary file modified tests/snapshots/stax/test_sign_tx_short_tx/00003.png
5 changes: 1 addition & 4 deletions tests/test_app_mainmenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,11 @@ def test_app_mainmenu(firmware, navigator, test_name):
else:
instructions = [
NavInsID.USE_CASE_HOME_SETTINGS,
NavInsID.USE_CASE_SETTINGS_NEXT,
NavIns(NavInsID.TOUCH, (200, 113)),
NavIns(NavInsID.TOUCH, (200, 261)),
NavInsID.USE_CASE_CHOICE_CONFIRM,
NavInsID.USE_CASE_SETTINGS_NEXT,
NavIns(NavInsID.TOUCH, (200, 261)),
NavIns(NavInsID.TOUCH, (200, 261)),
NavInsID.USE_CASE_CHOICE_REJECT,
NavInsID.USE_CASE_SETTINGS_NEXT,
NavInsID.USE_CASE_SETTINGS_MULTI_PAGE_EXIT
]
navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, test_name, instructions,
Expand Down

0 comments on commit a06b24f

Please sign in to comment.