Skip to content

Commit a06b24f

Browse files
author
Xavier Chapron
committed
src/ui: Update NBGL UI based on new API
1 parent 23f7b03 commit a06b24f

File tree

36 files changed

+98
-148
lines changed

36 files changed

+98
-148
lines changed

src/ui/menu.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@
55
*/
66
void ui_menu_main(void);
77

8-
/**
9-
* Show settings menu (App version, developer name and settings).
10-
*/
11-
void ui_menu_settings(void);
12-
138
/**
149
* Show about submenu (copyright, date).
1510
*/

src/ui/menu_nbgl.c

Lines changed: 64 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -34,91 +34,74 @@ void app_quit(void) {
3434
os_sched_exit(-1);
3535
}
3636

37-
// home page definition
38-
void ui_menu_main(void) {
39-
// This parameter shall be set to false if the settings page contains only information
40-
// about the application (version , developer name, ...). It shall be set to
41-
// true if the settings page also contains user configurable parameters related to the
42-
// operation of the application.
43-
#define SETTINGS_BUTTON_ENABLED (true)
44-
45-
nbgl_useCaseHome(APPNAME,
46-
&C_app_boilerplate_64px,
47-
NULL,
48-
SETTINGS_BUTTON_ENABLED,
49-
ui_menu_settings,
50-
app_quit);
51-
}
52-
5337
// -----------------------------------------------------------
5438
// --------------------- SETTINGS MENU -----------------------
5539
// -----------------------------------------------------------
56-
57-
static const char* const INFO_TYPES[] = {"Version", "Developer"};
58-
static const char* const INFO_CONTENTS[] = {APPVERSION, "Ledger"};
40+
#define SETTING_INFO_NB 2
41+
static const char* const INFO_TYPES[SETTING_INFO_NB] = {"Version", "Developer"};
42+
static const char* const INFO_CONTENTS[SETTING_INFO_NB] = {APPVERSION, "Ledger"};
5943

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

64-
static nbgl_layoutSwitch_t switches[SETTINGS_SWITCHES_NB] = {0};
48+
static nbgl_contentSwitch_t switches[SETTINGS_SWITCHES_NB] = {0};
6549

66-
static bool nav_callback(uint8_t page, nbgl_pageContent_t* content) {
67-
UNUSED(page);
50+
static const nbgl_contentInfoList_t infoList = {
51+
.nbInfos = SETTING_INFO_NB,
52+
.infoTypes = INFO_TYPES,
53+
.infoContents = INFO_CONTENTS,
54+
};
6855

69-
// the first settings page contains only the version and the developer name
70-
// of the app (shall be always on the first setting page)
71-
if (page == 0) {
72-
content->type = INFOS_LIST;
73-
content->infosList.nbInfos = 2;
74-
content->infosList.infoTypes = INFO_TYPES;
75-
content->infosList.infoContents = INFO_CONTENTS;
76-
}
77-
// the second settings page contains 2 toggle setting switches
78-
else if (page == 1) {
79-
switches[DUMMY_SWITCH_1_ID].initState = (nbgl_state_t) N_storage.dummy1_allowed;
80-
switches[DUMMY_SWITCH_1_ID].text = "Dummy 1";
81-
switches[DUMMY_SWITCH_1_ID].subText = "Allow dummy 1\nin transactions";
82-
switches[DUMMY_SWITCH_1_ID].token = DUMMY_SWITCH_1_TOKEN;
83-
switches[DUMMY_SWITCH_1_ID].tuneId = TUNE_TAP_CASUAL;
84-
85-
switches[DUMMY_SWITCH_2_ID].initState = (nbgl_state_t) N_storage.dummy2_allowed;
86-
switches[DUMMY_SWITCH_2_ID].text = "Dummy 2";
87-
switches[DUMMY_SWITCH_2_ID].subText = "Allow dummy 2\nin transactions";
88-
switches[DUMMY_SWITCH_2_ID].token = DUMMY_SWITCH_2_TOKEN;
89-
switches[DUMMY_SWITCH_2_ID].tuneId = TUNE_TAP_CASUAL;
90-
91-
content->type = SWITCHES_LIST;
92-
content->switchesList.nbSwitches = SETTINGS_SWITCHES_NB;
93-
content->switchesList.switches = (nbgl_layoutSwitch_t*) switches;
94-
} else {
95-
return false;
96-
}
97-
// valid page so return true
98-
return true;
99-
}
56+
static uint8_t initSettingPage;
57+
static void review_warning_choice(bool confirm);
58+
static void controls_callback(int token, uint8_t index, int page);
59+
60+
// settings menu definition
61+
#define SETTING_CONTENTS_NB 1
62+
static const nbgl_content_t contents[SETTING_CONTENTS_NB] = {
63+
{.type = SWITCHES_LIST,
64+
.content.switchesList.nbSwitches = SETTINGS_SWITCHES_NB,
65+
.content.switchesList.switches = switches,
66+
.contentActionCallback = controls_callback}};
67+
68+
static const nbgl_genericContents_t settingContents = {.callbackCallNeeded = false,
69+
.contentsList = contents,
70+
.nbContents = SETTING_CONTENTS_NB};
10071

10172
// callback for setting warning choice
10273
static void review_warning_choice(bool confirm) {
10374
uint8_t switch_value;
10475
if (confirm) {
10576
// toggle the switch value
10677
switch_value = !N_storage.dummy2_allowed;
78+
switches[DUMMY_SWITCH_2_ID].initState = (nbgl_state_t) switch_value;
10779
// store the new setting value in NVM
10880
nvm_write((void*) &N_storage.dummy2_allowed, &switch_value, 1);
10981
}
11082

111-
// return to the settings menu
112-
ui_menu_settings();
83+
// Reset setting menu to the right page
84+
nbgl_useCaseHomeAndSettings(APPNAME,
85+
&C_app_boilerplate_64px,
86+
NULL,
87+
initSettingPage,
88+
&settingContents,
89+
&infoList,
90+
NULL,
91+
app_quit);
11392
}
11493

115-
static void controls_callback(int token, uint8_t index) {
94+
static void controls_callback(int token, uint8_t index, int page) {
11695
UNUSED(index);
96+
97+
initSettingPage = page;
98+
11799
uint8_t switch_value;
118100
if (token == DUMMY_SWITCH_1_TOKEN) {
119101
// Dummy 1 switch touched
120102
// toggle the switch value
121103
switch_value = !N_storage.dummy1_allowed;
104+
switches[DUMMY_SWITCH_1_ID].initState = (nbgl_state_t) switch_value;
122105
// store the new setting value in NVM
123106
nvm_write((void*) &N_storage.dummy1_allowed, &switch_value, 1);
124107
} else if (token == DUMMY_SWITCH_2_TOKEN) {
@@ -128,7 +111,7 @@ static void controls_callback(int token, uint8_t index) {
128111
// to activate the dummy 2 setting
129112
if (!N_storage.dummy2_allowed) {
130113
// Display the warning message and ask the user to confirm
131-
nbgl_useCaseChoice(&C_warning64px,
114+
nbgl_useCaseChoice(&C_Warning_64px,
132115
"Dummy 2",
133116
"Are you sure to\nallow dummy 2\nin transactions?",
134117
"I understand, confirm",
@@ -137,24 +120,36 @@ static void controls_callback(int token, uint8_t index) {
137120
} else {
138121
// toggle the switch value
139122
switch_value = !N_storage.dummy2_allowed;
123+
switches[DUMMY_SWITCH_2_ID].initState = (nbgl_state_t) switch_value;
140124
// store the new setting value in NVM
141125
nvm_write((void*) &N_storage.dummy2_allowed, &switch_value, 1);
142126
}
143127
}
144128
}
145129

146-
// settings menu definition
147-
void ui_menu_settings() {
148-
#define TOTAL_SETTINGS_PAGE (2)
149-
#define INIT_SETTINGS_PAGE (0)
150-
#define DISABLE_SUB_SETTINGS (false)
151-
nbgl_useCaseSettings(APPNAME,
152-
INIT_SETTINGS_PAGE,
153-
TOTAL_SETTINGS_PAGE,
154-
DISABLE_SUB_SETTINGS,
155-
ui_menu_main,
156-
nav_callback,
157-
controls_callback);
130+
// home page definition
131+
void ui_menu_main(void) {
132+
// Initialize switches data
133+
switches[DUMMY_SWITCH_1_ID].initState = (nbgl_state_t) N_storage.dummy1_allowed;
134+
switches[DUMMY_SWITCH_1_ID].text = "Dummy 1";
135+
switches[DUMMY_SWITCH_1_ID].subText = "Allow dummy 1\nin transactions";
136+
switches[DUMMY_SWITCH_1_ID].token = DUMMY_SWITCH_1_TOKEN;
137+
switches[DUMMY_SWITCH_1_ID].tuneId = TUNE_TAP_CASUAL;
138+
139+
switches[DUMMY_SWITCH_2_ID].initState = (nbgl_state_t) N_storage.dummy2_allowed;
140+
switches[DUMMY_SWITCH_2_ID].text = "Dummy 2";
141+
switches[DUMMY_SWITCH_2_ID].subText = "Allow dummy 2\nin transactions";
142+
switches[DUMMY_SWITCH_2_ID].token = DUMMY_SWITCH_2_TOKEN;
143+
switches[DUMMY_SWITCH_2_ID].tuneId = TUNE_TAP_CASUAL;
144+
145+
nbgl_useCaseHomeAndSettings(APPNAME,
146+
&C_app_boilerplate_64px,
147+
NULL,
148+
INIT_HOME_PAGE,
149+
&settingContents,
150+
&infoList,
151+
NULL,
152+
app_quit);
158153
}
159154

160155
#endif

src/ui/nbgl_display_address.c

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,35 +38,22 @@
3838

3939
static char g_address[43];
4040

41-
static void confirm_address_rejection(void) {
42-
// display a status page and go back to main
43-
validate_pubkey(false);
44-
nbgl_useCaseStatus("Address verification\ncancelled", false, ui_menu_main);
45-
}
46-
47-
static void confirm_address_approval(void) {
48-
// display a success status page and go back to main
49-
validate_pubkey(true);
50-
nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, ui_menu_main);
51-
}
52-
5341
static void review_choice(bool confirm) {
42+
// Answer, display a status page and go back to main
43+
validate_pubkey(confirm);
5444
if (confirm) {
55-
confirm_address_approval();
45+
nbgl_useCaseReviewStatus(STATUS_TYPE_ADDRESS_VERIFIED, ui_menu_main);
5646
} else {
57-
confirm_address_rejection();
47+
nbgl_useCaseReviewStatus(STATUS_TYPE_ADDRESS_REJECTED, ui_menu_main);
5848
}
5949
}
6050

61-
static void continue_review(void) {
62-
nbgl_useCaseAddressConfirmation(g_address, review_choice);
63-
}
64-
6551
int ui_display_address() {
6652
if (G_context.req_type != CONFIRM_ADDRESS || G_context.state != STATE_NONE) {
6753
G_context.state = STATE_NONE;
6854
return io_send_sw(SW_BAD_STATE);
6955
}
56+
7057
memset(g_address, 0, sizeof(g_address));
7158
uint8_t address[ADDRESS_LEN] = {0};
7259
if (!address_from_pubkey(G_context.pk_info.raw_public_key, address, sizeof(address))) {
@@ -77,12 +64,12 @@ int ui_display_address() {
7764
return io_send_sw(SW_DISPLAY_ADDRESS_FAIL);
7865
}
7966

80-
nbgl_useCaseReviewStart(&C_app_boilerplate_64px,
81-
"Verify BOL address",
82-
NULL,
83-
"Cancel",
84-
continue_review,
85-
confirm_address_rejection);
67+
nbgl_useCaseAddressReview(g_address,
68+
NULL,
69+
&C_app_boilerplate_64px,
70+
"Verify BOL address",
71+
NULL,
72+
review_choice);
8673
return 0;
8774
}
8875

src/ui/nbgl_display_transaction.c

Lines changed: 22 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -44,54 +44,18 @@ static char g_address[43];
4444

4545
static nbgl_layoutTagValue_t pairs[2];
4646
static nbgl_layoutTagValueList_t pairList;
47-
static nbgl_pageInfoLongPress_t infoLongPress;
48-
49-
static void confirm_transaction_rejection(void) {
50-
// display a status page and go back to main
51-
validate_transaction(false);
52-
nbgl_useCaseStatus("Transaction rejected", false, ui_menu_main);
53-
}
54-
55-
static void ask_transaction_rejection_confirmation(void) {
56-
// display a choice to confirm/cancel rejection
57-
nbgl_useCaseConfirm("Reject transaction?",
58-
NULL,
59-
"Yes, Reject",
60-
"Go back to transaction",
61-
confirm_transaction_rejection);
62-
}
6347

6448
// called when long press button on 3rd page is long-touched or when reject footer is touched
6549
static void review_choice(bool confirm) {
50+
// Answer, display a status page and go back to main
51+
validate_transaction(confirm);
6652
if (confirm) {
67-
// display a status page and go back to main
68-
validate_transaction(true);
69-
nbgl_useCaseStatus("TRANSACTION\nSIGNED", true, ui_menu_main);
53+
nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_SIGNED, ui_menu_main);
7054
} else {
71-
ask_transaction_rejection_confirmation();
55+
nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_REJECTED, ui_menu_main);
7256
}
7357
}
7458

75-
static void review_continue(void) {
76-
// Setup data to display
77-
pairs[0].item = "Amount";
78-
pairs[0].value = g_amount;
79-
pairs[1].item = "Address";
80-
pairs[1].value = g_address;
81-
82-
// Setup list
83-
pairList.nbMaxLinesForValue = 0;
84-
pairList.nbPairs = 2;
85-
pairList.pairs = pairs;
86-
87-
// Info long press
88-
infoLongPress.icon = &C_app_boilerplate_64px;
89-
infoLongPress.text = "Sign transaction\nto send BOL";
90-
infoLongPress.longPressText = "Hold to sign";
91-
92-
nbgl_useCaseStaticReview(&pairList, &infoLongPress, "Reject transaction", review_choice);
93-
}
94-
9559
// Public function to start the transaction review
9660
// - Check if the app is in the right state for transaction review
9761
// - Format the amount and address strings in g_amount and g_address buffers
@@ -119,13 +83,25 @@ int ui_display_transaction() {
11983
return io_send_sw(SW_DISPLAY_ADDRESS_FAIL);
12084
}
12185

86+
// Setup data to display
87+
pairs[0].item = "Amount";
88+
pairs[0].value = g_amount;
89+
pairs[1].item = "Address";
90+
pairs[1].value = g_address;
91+
92+
// Setup list
93+
pairList.nbMaxLinesForValue = 0;
94+
pairList.nbPairs = 2;
95+
pairList.pairs = pairs;
96+
12297
// Start review
123-
nbgl_useCaseReviewStart(&C_app_boilerplate_64px,
124-
"Review transaction\nto send BOL",
125-
NULL,
126-
"Reject transaction",
127-
review_continue,
128-
ask_transaction_rejection_confirmation);
98+
nbgl_useCaseReview(TYPE_TRANSACTION,
99+
&pairList,
100+
&C_app_boilerplate_64px,
101+
"Review transaction\nto send BOL",
102+
NULL,
103+
"Sign transaction\nto send BOL",
104+
review_choice);
129105
return 0;
130106
}
131107

3.18 KB
Loading
48 Bytes
Loading
-972 Bytes
Loading
986 Bytes
Loading
3.22 KB
Loading
-3.23 KB
Loading
-622 Bytes
Loading
-10.4 KB
Binary file not shown.
-8.15 KB
Binary file not shown.
-10.8 KB
Binary file not shown.
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
126 Bytes
Loading
Loading
-955 Bytes
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
-955 Bytes
Loading

tests/test_app_mainmenu.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,11 @@ def test_app_mainmenu(firmware, navigator, test_name):
1515
else:
1616
instructions = [
1717
NavInsID.USE_CASE_HOME_SETTINGS,
18-
NavInsID.USE_CASE_SETTINGS_NEXT,
1918
NavIns(NavInsID.TOUCH, (200, 113)),
2019
NavIns(NavInsID.TOUCH, (200, 261)),
2120
NavInsID.USE_CASE_CHOICE_CONFIRM,
22-
NavInsID.USE_CASE_SETTINGS_NEXT,
2321
NavIns(NavInsID.TOUCH, (200, 261)),
24-
NavIns(NavInsID.TOUCH, (200, 261)),
25-
NavInsID.USE_CASE_CHOICE_REJECT,
22+
NavInsID.USE_CASE_SETTINGS_NEXT,
2623
NavInsID.USE_CASE_SETTINGS_MULTI_PAGE_EXIT
2724
]
2825
navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, test_name, instructions,

0 commit comments

Comments
 (0)