18#include "os_helpers.h"
29typedef struct ReviewContext_s {
33 const char *reviewTitle;
34 const char *reviewSubTitle;
35 const char *finishTitle;
40 uint8_t dataDirection;
41 uint8_t currentTagValueIndex;
42 uint8_t currentExtensionPage;
43 uint8_t nbExtensionPages;
49typedef struct ChoiceContext_s {
53 const char *subMessage;
54 const char *confirmText;
55 const char *cancelText;
60typedef struct ConfirmContext_s {
62 const char *subMessage;
63 const char *confirmText;
64 const char *cancelText;
69typedef struct ContentContext_s {
72 const char *rejectText;
78typedef struct HomeContext_s {
88typedef struct ActionContext_s {
93typedef struct KeypadContext_s {
107typedef struct KeyboardContext_s {
110 uint16_t entryMaxLen;
112 uint8_t keyboardIndex;
125 GENERIC_REVIEW_USE_CASE,
126 ADDRESS_REVIEW_USE_CASE,
127 STREAMING_START_REVIEW_USE_CASE,
128 STREAMING_CONTINUE_REVIEW_USE_CASE,
129 STREAMING_FINISH_REVIEW_USE_CASE,
143typedef struct UseCaseContext_s {
148 uint8_t firstPairPage;
153 ReviewContext_t review;
154 ChoiceContext_t choice;
155 ConfirmContext_t confirm;
157 ContentContext_t content;
159 KeypadContext_t keypad;
162 KeyboardContext_t keyboard;
164 ActionContext_t action;
168typedef struct PageContent_s {
182typedef struct ReviewWithWarningContext_s {
187 const char *reviewTitle;
188 const char *reviewSubTitle;
189 const char *finishTitle;
192 uint8_t securityReportLevel;
195 uint8_t nbWarningPages;
196 uint8_t firstWarningPage;
197 uint8_t barDetailIdx;
198} ReviewWithWarningContext_t;
209static UseCaseContext_t context;
211static ReviewWithWarningContext_t reviewWithWarnCtx;
229static void displaySpinner(
const char *text);
231static void startUseCaseHome(
void);
232static void startUseCaseInfo(
void);
233static void startUseCaseSettings(
void);
234static void startUseCaseSettingsAtPage(uint8_t initSettingPage);
235static void startUseCaseContent(
void);
237static void statusTickerCallback(
void);
240static void displayWarningStep(
void);
245 switch (content->
type) {
275 if (contentIdx >= genericContents->
nbContents) {
281 if (content == NULL) {
287 if (context.content.navCallback) {
288 if (context.content.navCallback(contentIdx, &pageContent) ==
true) {
291 switch (content->
type) {
340 uint8_t *elemContentIdx,
346 uint8_t elemNbPages = 0;
348 switch (context.type) {
349 case SETTINGS_USE_CASE:
351 case GENERIC_SETTINGS:
352 genericContents = context.home.settingContents;
354 case CONTENT_USE_CASE:
355 case GENERIC_REVIEW_USE_CASE:
356 genericContents = &context.content.genericContents;
361 for (
unsigned int i = 0; i < genericContents->
nbContents; i++) {
362 p_content = getContentAtIdx(genericContents, i, content);
363 elemNbPages = getContentNbElement(p_content);
364 if (nbPages + elemNbPages > elemIdx) {
365 *elemContentIdx = context.currentPage - nbPages;
368 nbPages += elemNbPages;
374static const char *getChoiceName(uint8_t choiceIndex)
384 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
385 if (p_content == NULL) {
387 "getChoiceName(): p_content is NULL for page %d\n",
388 context.currentPage);
391 switch (p_content->
type) {
394 names = (
char **) PIC(contentChoices->
names);
399 names = (
char **) PIC(contentBars->
barTexts);
400 nbValues = contentBars->
nbBars;
406 if (choiceIndex >= nbValues) {
410 return (
const char *) PIC(names[choiceIndex]);
413static void onChoiceSelected(uint8_t choiceIndex)
422 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
423 if (p_content == NULL) {
425 "onChoiceSelected(): p_content is NULL for page %d\n",
426 context.currentPage);
429 switch (p_content->
type) {
432 if (choiceIndex < contentChoices->nbChoices) {
433 token = contentChoices->
token;
438 if (choiceIndex < contentBars->nbBars) {
439 token = ((
const uint8_t *) PIC(contentBars->
tokens))[choiceIndex];
455 if (context.content.controlsCallback != NULL) {
456 context.content.controlsCallback(token, choiceIndex);
464 if ((context.type == GENERIC_SETTINGS) && (context.home.quitCallback != NULL)) {
465 context.home.quitCallback();
468 if (context.type == SETTINGS_USE_CASE) {
472 if (context.content.quitCallback != NULL) {
473 context.content.quitCallback();
483 bool *isCenteredInfo)
487 if (tagValueList->
pairs != NULL) {
488 pair = PIC(&tagValueList->
pairs[index]);
491 pair = PIC(tagValueList->
callback(index));
494 *value = pair->
value;
499 *isCenteredInfo =
true;
507static void onReviewAccept(
void)
509 if (context.review.onChoice) {
510 context.review.onChoice(
true);
514static void onReviewReject(
void)
516 if (context.review.onChoice) {
517 context.review.onChoice(
false);
521static void onChoiceAccept(
void)
523 if (context.choice.onChoice) {
524 context.choice.onChoice(
true);
528static void onChoiceReject(
void)
530 if (context.choice.onChoice) {
531 context.choice.onChoice(
false);
535static void onConfirmAccept(
void)
537 if (context.confirm.currentStep) {
540 if (context.confirm.onConfirm) {
541 context.confirm.onConfirm();
545static void onConfirmReject(
void)
547 if (context.confirm.currentStep) {
554static void onSwitchAction(
void)
561 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
564 "onSwitchAction(): p_content is NULL or not a switches list for page %d\n",
565 context.currentPage);
570 switch (context.type) {
571 case SETTINGS_USE_CASE:
573 case GENERIC_SETTINGS:
576 case CONTENT_USE_CASE:
577 case GENERIC_REVIEW_USE_CASE:
587 context.currentPage);
589 else if (context.content.controlsCallback != NULL) {
590 context.content.controlsCallback(contentSwitch->
token, 0);
600 ForcedType_t forcedType,
612 .tickerIntervale = 0,
618 if ((context.type == STREAMING_CONTINUE_REVIEW_USE_CASE)
619 && (context.review.skipCallback != NULL) && (context.review.nbDataSets > 1)) {
622 if ((context.type == STATUS_USE_CASE) || (context.type == SPINNER_USE_CASE)) {
625 if ((context.type == CONFIRM_USE_CASE) && (context.confirm.currentStep != NULL)) {
630 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
632 switch (p_content->
type) {
654 else if ((icon == NULL) && (forcedType != FORCE_CENTERED_INFO)) {
656 if (subTxt != NULL) {
662 newStep =
nbgl_stepDrawText(pos, onActionCallback, p_ticker, txt, subTxt, style, modal);
670 if ((subTxt != NULL) || (context.stepCallback != NULL) || context.forceAction) {
678 if (context.type == CONFIRM_USE_CASE) {
679 context.confirm.currentStep = newStep;
685 const char *description,
694 switchInfo.
text = title;
695 switchInfo.
subText = description;
708 if (context.currentPage > 0) {
709 context.currentPage--;
713 else if ((context.type != STREAMING_CONTINUE_REVIEW_USE_CASE)
714 || (context.review.skipCallback == NULL) || (context.review.nbDataSets == 1)) {
721 if (context.currentPage < (
int) (context.nbPages - 1)) {
722 context.currentPage++;
732 if (context.stepCallback != NULL) {
733 context.stepCallback();
735 else if ((context.type == CONTENT_USE_CASE) || (context.type == SETTINGS_USE_CASE)
736 || (context.type == GENERIC_SETTINGS)
737 || (context.type == GENERIC_REVIEW_USE_CASE)) {
738 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
739 if (p_content != NULL) {
740 switch (p_content->
type) {
754 token = ((
const uint8_t *) PIC(
765 if (elemIdx < p_content->content.tagValueConfirm.tagValueList.nbPairs) {
774 bool used_action_callback
776 ContextType_t prev_type = context.type;
777 if (used_action_callback) {
782 else if (context.content.controlsCallback != NULL) {
783 context.content.controlsCallback(token, index);
789 if (context.type != prev_type) {
802 if (used_action_callback
820 if (!buttonGenericCallback(event, &pos)) {
825 context.review.dataDirection = pos;
827 displayReviewPage(pos);
839 && (context.currentPage > context.firstPairPage)) {
840 context.currentPage--;
847 && (context.currentPage < (
int) (context.nbPages - 1))
848 && (context.currentPage > context.firstPairPage)) {
849 context.currentPage++;
855 if (context.firstPairPage == 0) {
857 context.review.skipCallback();
861 context.currentPage = context.nbPages - 2;
870 if (context.firstPairPage == 0) {
871 displayStreamingReviewPage(pos);
874 displayReviewPage(pos);
884 context.action.actionCallback();
893 if (!buttonGenericCallback(event, &pos)) {
898 context.review.dataDirection = pos;
901 displayStreamingReviewPage(pos);
909 if (!buttonGenericCallback(event, &pos)) {
913 displaySettingsPage(pos,
false);
921 if (!buttonGenericCallback(event, &pos)) {
925 displayInfoPage(pos);
933 if (!buttonGenericCallback(event, &pos)) {
937 displayHomePage(pos);
945 if (!buttonGenericCallback(event, &pos)) {
949 displayChoicePage(pos);
957 if (!buttonGenericCallback(event, &pos)) {
970 if (context.stepCallback != NULL) {
971 context.stepCallback();
981 if (!buttonGenericCallback(event, &pos)) {
985 displayContent(pos,
false);
989static void statusTickerCallback(
void)
991 if (context.stepCallback != NULL) {
992 context.stepCallback();
1004 if (context.review.currentExtensionPage > 0) {
1005 context.review.currentExtensionPage--;
1011 if (context.review.currentExtensionPage < (context.review.nbExtensionPages - 1)) {
1012 context.review.currentExtensionPage++;
1018 if (context.review.currentExtensionPage == (context.review.nbExtensionPages - 1)) {
1028 displayExtensionStep(pos);
1037 const char *text = NULL;
1038 const char *subText = NULL;
1040 if (context.review.extensionStepCtx != NULL) {
1043 if (context.review.currentExtensionPage < (context.review.nbExtensionPages - 1)) {
1044 if (context.review.currentExtensionPage == 0) {
1051 switch (context.review.extension->aliasType) {
1053 text = context.review.extension->title;
1054 subText = context.review.extension->fullValue;
1057 bool has_scope = (context.review.extension->aliasSubName != NULL);
1058 bool has_tn = (context.review.extension->explanation != NULL);
1059 uint8_t page = context.review.currentExtensionPage;
1061 text = context.review.extension->title;
1062 subText = has_scope ? context.review.extension->aliasSubName
1063 : context.review.extension->fullValue;
1065 else if (has_scope && page == 1) {
1066 text = context.review.extension->title;
1067 subText = context.review.extension->fullValue;
1070 text = context.review.extension->explanation;
1075 infoList = context.review.extension->infolist;
1076 text = PIC(infoList->
infoTypes[context.review.currentExtensionPage]);
1077 subText = PIC(infoList->
infoContents[context.review.currentExtensionPage]);
1080 tagValueList = context.review.extension->tagValuelist;
1081 text = PIC(tagValueList->
pairs[context.review.currentExtensionPage].
item);
1082 subText = PIC(tagValueList->
pairs[context.review.currentExtensionPage].
value);
1092 else if (context.review.currentExtensionPage == (context.review.nbExtensionPages - 1)) {
1094 info.
icon = &C_icon_back_x;
1095 info.
text1 =
"Back";
1098 context.review.extensionStepCtx
1104static void displayAliasFullValue(
void)
1106 const char *text = NULL;
1107 const char *subText = NULL;
1109 bool isCenteredInfo;
1111 getPairData(context.review.tagValueList,
1112 context.review.currentTagValueIndex,
1115 &context.review.extension,
1118 if (context.review.extension == NULL) {
1121 "displayAliasFullValue: extension nor found for pair %d\n",
1122 context.review.currentTagValueIndex);
1125 context.review.currentExtensionPage = 0;
1126 context.review.extensionStepCtx = NULL;
1128 switch (context.review.extension->aliasType) {
1130 context.review.nbExtensionPages = 2;
1133 context.review.nbExtensionPages
1134 = 2 + ((context.review.extension->aliasSubName != NULL) ? 1 : 0)
1135 + ((context.review.extension->explanation != NULL) ? 1 : 0);
1138 context.review.nbExtensionPages = context.review.extension->infolist->nbInfos + 1;
1141 context.review.nbExtensionPages = context.review.extension->tagValuelist->nbPairs + 1;
1145 "displayAliasFullValue: unsupported alias type %d\n",
1146 context.review.extension->aliasType);
1152static void getLastPageInfo(
bool approve,
const nbgl_icon_details_t **icon,
const char **text)
1156 *icon = &C_icon_validate_14;
1158 if ((context.type == REVIEW_USE_CASE) && (context.review.finishTitle != NULL)) {
1159 *text = context.review.finishTitle;
1162 *text =
"Confirm contact details";
1165 else if (context.type == ADDRESS_REVIEW_USE_CASE) {
1170 if (context.review.finishTitle != NULL) {
1171 *text = context.review.finishTitle;
1177 *text =
"Accept risk and sign transaction";
1180 *text =
"Sign transaction";
1185 *text =
"Accept risk and sign message";
1188 *text =
"Sign message";
1193 *text =
"Accept risk and sign operation";
1196 *text =
"Sign operation";
1202 context.stepCallback = onReviewAccept;
1206 *icon = &C_icon_crossmark;
1207 if ((context.type == ADDRESS_REVIEW_USE_CASE)
1212 *text =
"Reject transaction";
1215 *text =
"Reject message";
1218 *text =
"Reject operation";
1220 context.stepCallback = onReviewReject;
1227 uint8_t reviewPages = 0;
1228 uint8_t finalPages = 0;
1229 uint8_t pairIndex = 0;
1230 const char *text = NULL;
1231 const char *subText = NULL;
1233 uint8_t currentIndex = 0;
1234 uint8_t titleIndex = 255;
1235 uint8_t subIndex = 255;
1236 uint8_t approveIndex = 255;
1237 uint8_t rejectIndex = 255;
1239 ForcedType_t forcedType = NO_FORCED_TYPE;
1241 context.stepCallback = NULL;
1245 titleIndex = currentIndex++;
1247 if (context.review.reviewSubTitle) {
1249 subIndex = currentIndex++;
1252 approveIndex = context.nbPages - 2;
1253 rejectIndex = context.nbPages - 1;
1254 finalPages = approveIndex;
1257 if (context.currentPage >= finalPages) {
1258 if (context.currentPage == approveIndex) {
1260 getLastPageInfo(
true, &icon, &text);
1262 else if (context.currentPage == rejectIndex) {
1264 getLastPageInfo(
false, &icon, &text);
1267 else if (context.currentPage < reviewPages) {
1268 if (context.currentPage == titleIndex) {
1270 icon = context.review.icon;
1271 text = context.review.reviewTitle;
1273 else if (context.currentPage == subIndex) {
1275 text = context.review.reviewSubTitle;
1278 else if ((context.review.address != NULL) && (context.currentPage == reviewPages)) {
1281 subText = context.review.address;
1287 if ((context.operationType &
SKIPPABLE_OPERATION) && (context.review.skipDisplay ==
false)
1288 && ((context.currentPage > reviewPages)
1292 if ((context.review.nbDataSets == 1) || (context.currentPage > 0)) {
1295 info.
icon = &C_Information_circle_14px;
1296 info.
text1 =
"Press right button to continue message or \bpress both to skip\b";
1299 context.review.skipDisplay =
true;
1300 context.firstPairPage = reviewPages;
1303 context.review.skipDisplay =
false;
1304 bool isCenteredInfo =
false;
1305 pairIndex = context.currentPage - reviewPages;
1306 if (context.review.address != NULL) {
1309 getPairData(context.review.tagValueList,
1316 if (extension != NULL) {
1317 context.stepCallback = displayAliasFullValue;
1318 context.review.currentTagValueIndex = pairIndex;
1319 forcedType = FORCE_BUTTON;
1322 if (isCenteredInfo) {
1323 forcedType = FORCE_CENTERED_INFO;
1328 drawStep(pos, icon, text, subText, reviewCallback,
false, forcedType,
false);
1335 const char *text = NULL;
1336 const char *subText = NULL;
1338 uint8_t reviewPages = 0;
1339 uint8_t titleIndex = 255;
1340 uint8_t subIndex = 255;
1342 ForcedType_t forcedType = NO_FORCED_TYPE;
1344 context.stepCallback = NULL;
1345 switch (context.type) {
1346 case STREAMING_START_REVIEW_USE_CASE:
1348 titleIndex = reviewPages++;
1349 if (context.review.reviewSubTitle) {
1351 subIndex = reviewPages++;
1354 if (context.currentPage >= reviewPages) {
1359 if (context.currentPage == titleIndex) {
1361 icon = context.review.icon;
1362 text = context.review.reviewTitle;
1364 else if (context.currentPage == subIndex) {
1366 text = context.review.reviewSubTitle;
1370 case STREAMING_CONTINUE_REVIEW_USE_CASE:
1371 if (context.currentPage >= context.review.tagValueList->nbPairs) {
1378 if ((context.review.skipCallback != NULL) && (context.review.skipDisplay ==
false)
1379 && ((context.review.nbDataSets > 1) || (context.currentPage > 0)
1383 if ((context.review.nbDataSets == 1) || (context.currentPage > 0)) {
1386 info.
icon = &C_Information_circle_14px;
1387 info.
text1 =
"Press right button to continue message or \bpress both to skip\b";
1390 context.review.skipDisplay =
true;
1393 context.review.skipDisplay =
false;
1394 bool isCenteredInfo =
false;
1395 getPairData(context.review.tagValueList,
1396 context.currentPage,
1402 if (extension != NULL) {
1403 forcedType = FORCE_BUTTON;
1406 if (isCenteredInfo) {
1407 forcedType = FORCE_CENTERED_INFO;
1412 case STREAMING_FINISH_REVIEW_USE_CASE:
1414 if (context.currentPage == 0) {
1416 getLastPageInfo(
true, &icon, &text);
1420 getLastPageInfo(
false, &icon, &text);
1425 drawStep(pos, icon, text, subText, streamingReviewCallback,
false, forcedType,
false);
1432 const char *text = NULL;
1433 const char *subText = NULL;
1436 context.stepCallback = NULL;
1438 if (context.currentPage < (context.nbPages - 1)) {
1440 ((
const char *
const *) PIC(context.home.infosList->infoTypes))[context.currentPage]);
1442 ((
const char *
const *) PIC(context.home.infosList->infoContents))[context.currentPage]);
1445 icon = &C_icon_back_x;
1447 context.stepCallback = startUseCaseHome;
1450 drawStep(pos, icon, text, subText, infoCallback,
false, FORCE_CENTERED_INFO,
false);
1455static void getContentPage(
bool toogle_state, PageContent_t *contentPage)
1457 uint8_t elemIdx = 0;
1462 char **names = NULL;
1464 char **texts = NULL;
1465 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
1466 if (p_content == NULL) {
1468 "getContentPage(): p_content is NULL for page %d\n",
1469 context.currentPage);
1472 switch (p_content->
type) {
1489 &contentPage->subText,
1490 &contentPage->extension,
1492 &contentPage->isCenteredInfo);
1495 if (elemIdx < p_content->content.tagValueConfirm.tagValueList.nbPairs) {
1499 &contentPage->subText,
1500 &contentPage->extension,
1502 &contentPage->isCenteredInfo);
1506 contentPage->icon = &C_icon_validate_14;
1507 contentPage->isAction =
true;
1511 contentPage->isSwitch =
true;
1514 contentPage->
text = contentSwitch->
text;
1515 contentPage->state = contentSwitch->
initState;
1519 context.stepCallback = onSwitchAction;
1520 contentPage->subText = contentSwitch->
subText;
1525 contentPage->subText
1537 names = (
char **) PIC(contentChoices->
names);
1540 if (contentChoices->
title != NULL) {
1541 contentPage->text = PIC(contentChoices->
title);
1542 contentPage->subText = (
const char *) PIC(names[elemIdx]);
1544 else if ((context.type == CONTENT_USE_CASE) && (context.content.title != NULL)) {
1545 contentPage->text = PIC(context.content.title);
1546 contentPage->subText = (
const char *) PIC(names[elemIdx]);
1548 else if (((context.type == GENERIC_SETTINGS) || (context.type == SETTINGS_USE_CASE))
1549 && (context.home.appName != NULL)) {
1556 contentPage->text = PIC(context.home.appName);
1557 contentPage->subText = (
const char *) PIC(names[elemIdx]);
1560 contentPage->text = (
const char *) PIC(names[elemIdx]);
1567 && (elemIdx == contentChoices->
initChoice)) {
1569 contentPage->bottomIcon =
true;
1577 texts = (
char **) PIC(contentBars->
barTexts);
1580 if (contentBars->
title != NULL) {
1581 contentPage->text = PIC(contentBars->
title);
1582 contentPage->subText = PIC(texts[elemIdx]);
1584 else if ((context.type == CONTENT_USE_CASE) && (context.content.title != NULL)) {
1585 contentPage->text = PIC(context.content.title);
1586 contentPage->subText = PIC(texts[elemIdx]);
1588 else if ((context.type == GENERIC_SETTINGS) && (context.home.appName != NULL)) {
1589 contentPage->text = PIC(context.home.appName);
1590 contentPage->subText = PIC(texts[elemIdx]);
1593 contentPage->text = PIC(texts[elemIdx]);
1601 contentPage->icon = &C_icon_down;
1602 contentPage->bottomIcon =
true;
1612 PageContent_t contentPage = {0};
1614 context.stepCallback = NULL;
1616 if (context.currentPage < (context.nbPages - 1)) {
1617 getContentPage(toogle_state, &contentPage);
1620 contentPage.icon = &C_icon_back_x;
1621 contentPage.text =
"Back";
1622 if (context.type == GENERIC_SETTINGS) {
1623 context.stepCallback = context.home.quitCallback;
1626 context.stepCallback = startUseCaseHome;
1630 if (contentPage.isSwitch) {
1632 pos, contentPage.text, contentPage.subText, contentPage.state, settingsCallback,
false);
1638 contentPage.subText,
1642 contentPage.bottomIcon);
1648static void startUseCaseHome(
void)
1650 switch (context.type) {
1651 case SETTINGS_USE_CASE:
1653 context.currentPage = 1;
1654 if (context.home.homeAction) {
1656 context.currentPage++;
1661 context.currentPage = 1;
1662 if (context.home.homeAction) {
1664 context.currentPage++;
1666 if (context.home.settingContents) {
1668 context.currentPage++;
1673 context.currentPage = 0;
1677 context.type = HOME_USE_CASE;
1678 context.nbPages = 2;
1679 if (context.home.settingContents) {
1682 if (context.home.infosList) {
1685 if (context.home.homeAction) {
1691static void startUseCaseInfo(
void)
1693 context.type = INFO_USE_CASE;
1694 context.nbPages = context.home.infosList->nbInfos + 1;
1695 context.currentPage = 0;
1700static void startUseCaseSettingsAtPage(uint8_t initSettingPage)
1706 if (context.type != GENERIC_SETTINGS) {
1707 context.
type = SETTINGS_USE_CASE;
1710 context.nbPages = 1;
1711 for (
unsigned int i = 0; i < context.home.settingContents->nbContents; i++) {
1712 p_content = getContentAtIdx(context.home.settingContents, i, &content);
1713 context.nbPages += getContentNbElement(p_content);
1715 context.currentPage = initSettingPage;
1720static void startUseCaseSettings(
void)
1722 startUseCaseSettingsAtPage(0);
1725static void startUseCaseContent(
void)
1727 uint8_t contentIdx = 0;
1731 context.nbPages = 1;
1733 for (contentIdx = 0; contentIdx < context.content.genericContents.nbContents; contentIdx++) {
1734 p_content = getContentAtIdx(&context.content.genericContents, contentIdx, &content);
1735 context.nbPages += getContentNbElement(p_content);
1739 if (context.currentPage >= context.nbPages) {
1749 const char *text = NULL;
1750 const char *subText = NULL;
1752 uint8_t currentIndex = 0;
1753 uint8_t homeIndex = 255;
1754 uint8_t actionIndex = 255;
1755 uint8_t settingsIndex = 255;
1756 uint8_t infoIndex = 255;
1758 context.stepCallback = NULL;
1761 homeIndex = currentIndex++;
1762 if (context.home.homeAction) {
1763 actionIndex = currentIndex++;
1765 if (context.home.settingContents) {
1766 settingsIndex = currentIndex++;
1768 if (context.home.infosList) {
1769 infoIndex = currentIndex++;
1772 if (context.currentPage == homeIndex) {
1774 icon = context.home.appIcon;
1775 if (context.home.tagline != NULL) {
1776 text = context.home.tagline;
1779 text = context.home.appName;
1780 subText =
"app is ready";
1783 else if (context.currentPage == actionIndex) {
1785 icon = context.home.homeAction->icon;
1786 text = PIC(context.home.homeAction->text);
1787 context.stepCallback = context.home.homeAction->callback;
1789 else if (context.currentPage == settingsIndex) {
1791 icon = &C_icon_coggle;
1792 text =
"App settings";
1793 context.stepCallback = startUseCaseSettings;
1795 else if (context.currentPage == infoIndex) {
1797 icon = &C_Information_circle_14px;
1799 context.stepCallback = startUseCaseInfo;
1802 icon = &C_Quit_14px;
1804 context.stepCallback = context.home.quitCallback;
1807 drawStep(pos, icon, text, subText, homeCallback,
false, NO_FORCED_TYPE,
false);
1820static uint8_t getChoiceNbIntroPages(
void)
1822 uint8_t nbPages = 0;
1825 if ((context.choice.title == NULL) && (context.choice.message == NULL)) {
1828 if (context.choice.icon != NULL) {
1831 if ((context.choice.title != NULL) && (context.choice.message != NULL)) {
1834 if (context.choice.subMessage != NULL) {
1838 return (nbPages > 0) ? nbPages : 1;
1843static const char *getChoiceIntroSubText(uint8_t page)
1848 uint8_t elemPage = 0;
1850 if (context.choice.icon != NULL) {
1851 if (page == elemPage) {
1857 if ((context.choice.title != NULL) && (context.choice.message != NULL)) {
1859 if (page == elemPage) {
1860 return context.choice.message;
1865 return (page == elemPage) ? context.choice.subMessage : NULL;
1871 const char *text = NULL;
1872 const char *subText = NULL;
1875 uint8_t acceptPage = getChoiceNbIntroPages();
1878 uint8_t nbDetailPages = 0;
1880 if ((context.choice.details != NULL) && (context.choice.details->type ==
BAR_LIST_WARNING)) {
1881 nbDetailPages = context.choice.details->barList.nbBars;
1883 context.stepCallback = NULL;
1885 if (context.currentPage < acceptPage) {
1888 text = (context.choice.title != NULL) ? context.choice.title : context.choice.message;
1889 if (context.currentPage == 0) {
1890 icon = context.choice.icon;
1892 subText = getChoiceIntroSubText(context.currentPage);
1894 else if (context.currentPage < (acceptPage + nbDetailPages)) {
1896 uint8_t idx = context.currentPage - acceptPage;
1897 text = (context.choice.details->barList.texts != NULL)
1898 ? context.choice.details->barList.texts[idx]
1900 subText = (context.choice.details->barList.subTexts != NULL)
1901 ? context.choice.details->barList.subTexts[idx]
1904 else if (context.currentPage == (acceptPage + nbDetailPages)) {
1905 icon = &C_icon_validate_14;
1906 text = context.choice.confirmText;
1907 context.stepCallback = onChoiceAccept;
1910 icon = &C_icon_crossmark;
1911 text = context.choice.cancelText;
1912 context.stepCallback = onChoiceReject;
1916 drawStep(pos, icon, text, subText, genericChoiceCallback,
false, NO_FORCED_TYPE,
false);
1923 const char *text = NULL;
1924 const char *subText = NULL;
1927 context.stepCallback = NULL;
1928 switch (context.currentPage) {
1931 text = context.confirm.message;
1932 subText = context.confirm.subMessage;
1936 icon = &C_icon_validate_14;
1937 text = context.confirm.confirmText;
1938 context.stepCallback = onConfirmAccept;
1942 icon = &C_icon_crossmark;
1943 text = context.confirm.cancelText;
1944 context.stepCallback = onConfirmReject;
1948 drawStep(pos, icon, text, subText, genericConfirmCallback,
true, NO_FORCED_TYPE,
false);
1955 PageContent_t contentPage = {0};
1956 ForcedType_t forcedType = NO_FORCED_TYPE;
1958 context.stepCallback = NULL;
1960 if (context.currentPage < (context.nbPages - 1)) {
1961 getContentPage(toogle_state, &contentPage);
1962 if (contentPage.isCenteredInfo) {
1963 forcedType = FORCE_CENTERED_INFO;
1965 context.forceAction = contentPage.isAction;
1968 if (context.content.rejectText) {
1969 contentPage.text = context.content.rejectText;
1972 contentPage.text =
"Back";
1974 if (context.type == GENERIC_REVIEW_USE_CASE) {
1975 contentPage.icon = &C_icon_crossmark;
1978 contentPage.icon = &C_icon_back_x;
1980 context.stepCallback = context.content.quitCallback;
1983 if (contentPage.isSwitch) {
1985 pos, contentPage.text, contentPage.subText, contentPage.state, contentCallback,
false);
1991 contentPage.subText,
1995 contentPage.bottomIcon);
1997 context.forceAction =
false;
2001static void displaySpinner(
const char *text)
2003 drawStep(
SINGLE_STEP, &C_icon_processing, text, NULL, NULL,
false, NO_FORCED_TYPE,
false);
2008static void useCaseReview(ContextType_t type,
2012 const char *reviewTitle,
2013 const char *reviewSubTitle,
2014 const char *finishTitle,
2017 memset(&context, 0,
sizeof(UseCaseContext_t));
2018 context.type = type;
2019 context.operationType = operationType;
2020 context.review.tagValueList = tagValueList;
2021 context.review.reviewTitle = reviewTitle;
2022 context.review.reviewSubTitle = reviewSubTitle;
2023 context.review.finishTitle = finishTitle;
2024 context.review.icon = icon;
2025 context.review.onChoice = choiceCallback;
2026 context.currentPage = 0;
2028 context.nbPages = tagValueList->
nbPairs + 3;
2029 if (reviewSubTitle) {
2037static void setPinCodeText(
void)
2039 bool enableValidate =
false;
2040 bool enableBackspace =
true;
2043 enableValidate = (context.keypad.pinLen >= context.keypad.pinMinDigits);
2045 enableBackspace = (context.keypad.pinLen > 0) || (context.keypad.backCallback != NULL);
2047 context.keypad.hidden,
2048 context.keypad.pinLen,
2049 (
const char *) context.keypad.pinEntry);
2051 context.keypad.layoutCtx, context.keypad.keypadIndex, enableValidate, enableBackspace);
2057static void keypadCallback(
char touchedKey)
2059 switch (touchedKey) {
2061 if (context.keypad.pinLen > 0) {
2062 context.keypad.pinLen--;
2063 context.keypad.pinEntry[context.keypad.pinLen] = 0;
2065 else if (context.keypad.backCallback != NULL) {
2066 context.keypad.backCallback();
2073 context.keypad.validatePin(context.keypad.pinEntry, context.keypad.pinLen);
2077 if ((touchedKey >= 0x30) && (touchedKey < 0x40)) {
2078 if (context.keypad.pinLen < context.keypad.pinMaxDigits) {
2079 context.keypad.pinEntry[context.keypad.pinLen] = touchedKey;
2080 context.keypad.pinLen++;
2093 const char **buttons;
2094 int firstButtonToken;
2095 uint8_t nbUsedButtons;
2099} savedKeyboardContext;
2114static void displaySuggestionSelection(
void)
2117 savedKeyboardContext.buttons = context.keyboard.content.suggestionButtons.buttons;
2118 savedKeyboardContext.firstButtonToken
2119 = context.keyboard.content.suggestionButtons.firstButtonToken;
2120 savedKeyboardContext.nbUsedButtons = context.keyboard.content.suggestionButtons.nbUsedButtons;
2121 savedKeyboardContext.onButtonCallback = context.keyboard.onButtonCallback;
2122 savedKeyboardContext.backCallback = context.keyboard.backCallback;
2126 context.keyboard.layoutCtx = NULL;
2128 snprintf(savedKeyboardContext.title,
2129 sizeof(savedKeyboardContext.title),
2131 context.keyboard.content.number);
2135 savedKeyboardContext.backCallback,
2136 suggestionNavCallback,
2137 savedKeyboardContext.onButtonCallback);
2141static void keyboardCallback(
char touchedKey)
2144 size_t textLen = strlen(context.keyboard.entryBuffer);
2145 PRINTF(
"[keyboardCallback] touchedKey: '%c'\n", touchedKey);
2149 context.keyboard.backCallback();
2152 context.keyboard.entryBuffer[--textLen] =
'\0';
2155 context.keyboard.actionCallback();
2159 context.keyboard.entryBuffer[textLen] = touchedKey;
2160 context.keyboard.entryBuffer[++textLen] =
'\0';
2165 context.keyboard.getSuggestButtons(&context.keyboard.content, &mask);
2167 = &context.keyboard.content.suggestionButtons;
2174 bool allCandidatesFit;
2182 displaySuggestionSelection();
2186 else if (textLen >= context.keyboard.entryMaxLen) {
2192 context.keyboard.layoutCtx, context.keyboard.textIndex, context.keyboard.entryBuffer);
2198static void launchReviewAfterWarning(
void)
2200 if (reviewWithWarnCtx.type == REVIEW_USE_CASE) {
2201 useCaseReview(reviewWithWarnCtx.type,
2202 reviewWithWarnCtx.operationType,
2203 reviewWithWarnCtx.tagValueList,
2204 reviewWithWarnCtx.icon,
2205 reviewWithWarnCtx.reviewTitle,
2206 reviewWithWarnCtx.reviewSubTitle,
2207 reviewWithWarnCtx.finishTitle,
2208 reviewWithWarnCtx.choiceCallback);
2210 else if (reviewWithWarnCtx.type == STREAMING_START_REVIEW_USE_CASE) {
2220 displayWarningStep();
2225static void displayBarDetailStep(
void)
2228 = &reviewWithWarnCtx.warning->introDetails->
barList.
details[reviewWithWarnCtx.barDetailIdx];
2251 if (reviewWithWarnCtx.warningPage > 0) {
2252 reviewWithWarnCtx.warningPage--;
2257 if (reviewWithWarnCtx.warningPage < (reviewWithWarnCtx.nbWarningPages - 1)) {
2258 reviewWithWarnCtx.warningPage++;
2260 else if ((reviewWithWarnCtx.warning->predefinedSet == 0)
2261 && (reviewWithWarnCtx.warning->info != NULL)) {
2262 launchReviewAfterWarning();
2269 if (reviewWithWarnCtx.warningPage == reviewWithWarnCtx.firstWarningPage) {
2270 launchReviewAfterWarning();
2273 else if (reviewWithWarnCtx.warningPage == (reviewWithWarnCtx.nbWarningPages - 1)) {
2274 reviewWithWarnCtx.choiceCallback(
false);
2278 else if ((event ==
BUTTON_BOTH_PRESSED) && (reviewWithWarnCtx.warning->introDetails != NULL)
2280 && (reviewWithWarnCtx.warningPage > reviewWithWarnCtx.firstWarningPage)) {
2282 barIdx = reviewWithWarnCtx.warningPage - reviewWithWarnCtx.firstWarningPage - 1;
2283 if ((reviewWithWarnCtx.warning->introDetails->barList.details != NULL)
2284 && (reviewWithWarnCtx.warning->introDetails->barList.details[barIdx].type
2286 reviewWithWarnCtx.barDetailIdx = barIdx;
2287 displayBarDetailStep();
2294 displayWarningStep();
2298static void displayWarningStep(
void)
2303 if ((reviewWithWarnCtx.warning->prelude) && (reviewWithWarnCtx.warningPage == 0)) {
2308 reviewWithWarnCtx.warning->prelude->title,
2309 reviewWithWarnCtx.warning->prelude->description,
2316 if (reviewWithWarnCtx.warningPage == reviewWithWarnCtx.firstWarningPage) {
2318 info.
icon = &C_icon_warning;
2319 info.
text1 =
"Blind signing ahead";
2320 info.
text2 =
"To accept risk, press both buttons";
2321 pos = (reviewWithWarnCtx.firstWarningPage == 0) ?
FIRST_STEP
2325 else if (reviewWithWarnCtx.warningPage == (reviewWithWarnCtx.nbWarningPages - 1)) {
2326 getLastPageInfo(
false, &info.
icon, &info.
text1);
2330 else if ((reviewWithWarnCtx.warning->predefinedSet == 0)
2331 && (reviewWithWarnCtx.warning->info != NULL)) {
2332 if (reviewWithWarnCtx.warningPage == reviewWithWarnCtx.firstWarningPage) {
2333 info.
icon = reviewWithWarnCtx.warning->info->icon;
2334 info.
text1 = reviewWithWarnCtx.warning->info->title;
2335 info.
text2 = reviewWithWarnCtx.warning->info->description;
2336 pos = (reviewWithWarnCtx.firstWarningPage == 0) ?
FIRST_STEP
2340 else if ((reviewWithWarnCtx.warning->introDetails != NULL)
2343 barIdx = reviewWithWarnCtx.warningPage - reviewWithWarnCtx.firstWarningPage - 1;
2344 if (reviewWithWarnCtx.warning->introDetails->barList.icons) {
2345 info.
icon = reviewWithWarnCtx.warning->introDetails->barList.icons[barIdx];
2347 info.
text1 = reviewWithWarnCtx.warning->introDetails->barList.texts[barIdx];
2348 if (reviewWithWarnCtx.warning->introDetails->barList.subTexts) {
2349 info.
text2 = reviewWithWarnCtx.warning->introDetails->barList.subTexts[barIdx];
2353 else if (reviewWithWarnCtx.warningPage == (reviewWithWarnCtx.nbWarningPages - 1)) {
2354 if ((reviewWithWarnCtx.warning->introDetails != NULL)
2356 info.
icon = reviewWithWarnCtx.warning->introDetails->centeredInfo.icon;
2357 info.
text1 = reviewWithWarnCtx.warning->introDetails->centeredInfo.title;
2358 info.
text2 = reviewWithWarnCtx.warning->introDetails->centeredInfo.description;
2377static void displayInitialWarning(
void)
2380 reviewWithWarnCtx.warningPage = 0;
2382 || ((reviewWithWarnCtx.warning->introDetails)
2384 reviewWithWarnCtx.nbWarningPages = 2;
2386 else if ((reviewWithWarnCtx.warning->introDetails)
2388 reviewWithWarnCtx.nbWarningPages
2389 = reviewWithWarnCtx.warning->introDetails->barList.nbBars + 1;
2393 reviewWithWarnCtx.nbWarningPages = 1;
2396 reviewWithWarnCtx.firstWarningPage = 0;
2397 displayWarningStep();
2401static void displayPrelude(
void)
2404 reviewWithWarnCtx.warningPage = 0;
2406 || ((reviewWithWarnCtx.warning->introDetails)
2408 reviewWithWarnCtx.nbWarningPages = 3;
2412 reviewWithWarnCtx.nbWarningPages = 2;
2414 reviewWithWarnCtx.firstWarningPage = 1;
2415 displayWarningStep();
2436 bool *requireSpecificDisplay)
2439 UNUSED(tagValueList);
2441 *requireSpecificDisplay =
true;
2461 bool *requireSpecificDisplay)
2464 UNUSED(tagValueList);
2466 UNUSED(isSkippable);
2467 *requireSpecificDisplay =
true;
2505 UNUSED(switchesList);
2545 UNUSED(choicesList);
2559 uint8_t nbPages = 0;
2560 uint8_t nbPairs = tagValueList->
nbPairs;
2561 uint8_t nbPairsInPage;
2565 while (i < tagValueList->nbPairs) {
2569 nbPairs -= nbPairsInPage;
2595 memset(&context, 0,
sizeof(UseCaseContext_t));
2596 context.type = CONTENT_USE_CASE;
2597 context.currentPage = initPage;
2598 context.content.title = title;
2599 context.content.quitCallback = quitCallback;
2600 context.content.navCallback = navCallback;
2601 context.content.controlsCallback = controlsCallback;
2602 context.content.genericContents.callbackCallNeeded =
true;
2603 context.content.genericContents.nbContents = nbPages;
2605 startUseCaseContent();
2624 const char *tagline,
2625 const uint8_t initSettingPage,
2631 memset(&context, 0,
sizeof(UseCaseContext_t));
2632 context.home.appName = appName;
2633 context.home.appIcon = appIcon;
2634 context.home.tagline = tagline;
2635 context.home.settingContents = PIC(settingContents);
2636 context.home.infosList = PIC(infosList);
2637 context.home.homeAction = action;
2638 context.home.quitCallback = quitCallback;
2640 if ((initSettingPage !=
INIT_HOME_PAGE) && (settingContents != NULL)) {
2641 startUseCaseSettingsAtPage(initSettingPage);
2666 memset(&context, 0,
sizeof(UseCaseContext_t));
2667 context.type = GENERIC_SETTINGS;
2668 context.home.appName = appName;
2669 context.home.settingContents = PIC(settingContents);
2670 context.home.infosList = PIC(infosList);
2671 context.home.quitCallback = quitCallback;
2673 startUseCaseSettingsAtPage(initPage);
2712 const char *reviewTitle,
2713 const char *reviewSubTitle,
2714 const char *finishTitle,
2717 useCaseReview(REVIEW_USE_CASE,
2752 const char *reviewTitle,
2753 const char *reviewSubTitle,
2754 const char *finishTitle,
2760 ContextType_t type = REVIEW_USE_CASE;
2763 if ((warning == NULL)
2783 memset(&reviewWithWarnCtx, 0,
sizeof(reviewWithWarnCtx));
2784 reviewWithWarnCtx.type = type;
2785 reviewWithWarnCtx.operationType = operationType;
2786 reviewWithWarnCtx.tagValueList = tagValueList;
2787 reviewWithWarnCtx.icon = icon;
2788 reviewWithWarnCtx.reviewTitle = reviewTitle;
2789 reviewWithWarnCtx.reviewSubTitle = reviewSubTitle;
2790 reviewWithWarnCtx.finishTitle = finishTitle;
2791 reviewWithWarnCtx.warning = warning;
2792 reviewWithWarnCtx.choiceCallback = choiceCallback;
2795 if (reviewWithWarnCtx.warning->prelude) {
2800 displayInitialWarning();
2836 const char *reviewTitle,
2837 const char *reviewSubTitle,
2838 const char *finishTitle,
2849 &blindSigningWarning,
2870 const char *reviewTitle,
2871 const char *reviewSubTitle,
2872 const char *finishTitle,
2903 const char *reviewTitle,
2904 const char *reviewSubTitle,
2907 memset(&context, 0,
sizeof(UseCaseContext_t));
2908 context.type = ADDRESS_REVIEW_USE_CASE;
2909 context.review.address = address;
2910 context.review.reviewTitle = reviewTitle;
2911 context.review.reviewSubTitle = reviewSubTitle;
2912 context.review.icon = icon;
2913 context.review.onChoice = choiceCallback;
2914 context.currentPage = 0;
2917 context.nbPages = reviewSubTitle ? 5 : 4;
2918 if (additionalTagValueList) {
2919 context.review.tagValueList = PIC(additionalTagValueList);
2920 context.nbPages += additionalTagValueList->
nbPairs;
2935 const char *rejectText,
2938 memset(&context, 0,
sizeof(UseCaseContext_t));
2939 context.type = GENERIC_REVIEW_USE_CASE;
2940 context.content.rejectText = rejectText;
2941 context.content.quitCallback = rejectCallback;
2942 context.content.genericContents.nbContents = contents->
nbContents;
2948 context.content.genericContents.contentsList = PIC(contents->
contentsList);
2951 startUseCaseContent();
2965 memset(&context, 0,
sizeof(UseCaseContext_t));
2966 context.type = STATUS_USE_CASE;
2967 context.stepCallback = quitCallback;
2968 context.currentPage = 0;
2969 context.nbPages = 1;
2975 statusButtonCallback,
2992 switch (reviewStatusType) {
2994 msg =
"Operation signed";
2998 msg =
"Operation rejected";
3002 msg =
"Transaction signed";
3006 msg =
"Transaction rejected";
3010 msg =
"Message signed";
3014 msg =
"Message rejected";
3018 msg =
"Address verified";
3022 msg =
"Address verification cancelled";
3045 const char *reviewTitle,
3046 const char *reviewSubTitle,
3050 streamingOpType = operationType;
3052 memset(&context, 0,
sizeof(UseCaseContext_t));
3053 context.type = STREAMING_START_REVIEW_USE_CASE;
3054 context.operationType = operationType;
3055 context.review.reviewTitle = reviewTitle;
3056 context.review.reviewSubTitle = reviewSubTitle;
3057 context.review.icon = icon;
3058 context.review.onChoice = choiceCallback;
3059 context.currentPage = 0;
3060 context.nbPages = reviewSubTitle ? 3 : 2;
3080 const char *reviewTitle,
3081 const char *reviewSubTitle,
3085 operationType, icon, reviewTitle, reviewSubTitle, &blindSigningWarning, choiceCallback);
3105 const char *reviewTitle,
3106 const char *reviewSubTitle,
3110 memset(&context, 0,
sizeof(UseCaseContext_t));
3111 context.type = STREAMING_START_REVIEW_USE_CASE;
3112 context.operationType = operationType;
3113 context.review.reviewTitle = reviewTitle;
3114 context.review.reviewSubTitle = reviewSubTitle;
3115 context.review.icon = icon;
3116 context.review.onChoice = choiceCallback;
3117 context.currentPage = 0;
3118 context.nbPages = reviewSubTitle ? 3 : 2;
3121 streamingOpType = operationType;
3124 if ((warning == NULL)
3136 memset(&reviewWithWarnCtx, 0,
sizeof(reviewWithWarnCtx));
3138 reviewWithWarnCtx.type = context.type;
3139 reviewWithWarnCtx.operationType = operationType;
3140 reviewWithWarnCtx.icon = icon;
3141 reviewWithWarnCtx.reviewTitle = reviewTitle;
3142 reviewWithWarnCtx.reviewSubTitle = reviewSubTitle;
3143 reviewWithWarnCtx.choiceCallback = choiceCallback;
3144 reviewWithWarnCtx.warning = warning;
3147 if (reviewWithWarnCtx.warning->prelude) {
3152 displayInitialWarning();
3176 uint8_t curNbDataSets = context.review.nbDataSets;
3178 memset(&context, 0,
sizeof(UseCaseContext_t));
3179 context.type = STREAMING_CONTINUE_REVIEW_USE_CASE;
3180 context.operationType = streamingOpType;
3181 context.review.tagValueList = tagValueList;
3182 context.review.onChoice = choiceCallback;
3183 context.currentPage = 0;
3184 context.nbPages = tagValueList->
nbPairs + 1;
3185 context.review.skipCallback = skipCallback;
3186 context.review.nbDataSets = curNbDataSets + 1;
3210 memset(&context, 0,
sizeof(UseCaseContext_t));
3211 context.type = STREAMING_FINISH_REVIEW_USE_CASE;
3212 context.operationType = streamingOpType;
3213 context.review.onChoice = choiceCallback;
3214 context.review.finishTitle = finishTitle;
3215 context.currentPage = 0;
3216 context.nbPages = 2;
3228 memset(&context, 0,
sizeof(UseCaseContext_t));
3229 context.type = SPINNER_USE_CASE;
3230 context.currentPage = 0;
3231 context.nbPages = 1;
3233 displaySpinner(text);
3249 const char *message,
3250 const char *subMessage,
3251 const char *confirmText,
3252 const char *cancelText,
3256 icon, message, subMessage, confirmText, cancelText, NULL, callback);
3263 const char *message,
3264 const char *subMessage,
3265 const char *confirmText,
3266 const char *cancelText,
3270 memset(&context, 0,
sizeof(UseCaseContext_t));
3271 context.type = CHOICE_USE_CASE;
3272 context.choice.icon = icon;
3273 context.choice.title = title;
3274 context.choice.message = message;
3275 context.choice.subMessage = subMessage;
3276 context.choice.confirmText = confirmText;
3277 context.choice.cancelText = cancelText;
3278 context.choice.onChoice = callback;
3279 context.choice.details = details;
3280 context.currentPage = 0;
3281 context.nbPages = 2 + getChoiceNbIntroPages();
3282 if (details != NULL) {
3307 const char *message,
3308 const char *subMessage,
3309 const char *confirmText,
3310 const char *cancelText,
3314 startChoice(icon, NULL, message, subMessage, confirmText, cancelText, details, callback);
3322 const char *message,
3323 const char *subMessage,
3324 const char *confirmText,
3325 const char *cancelText,
3330 startChoice(centerIcon, title, message, subMessage, confirmText, cancelText, details, callback);
3347 const char *subMessage,
3348 const char *confirmText,
3349 const char *cancelText,
3352 memset(&context, 0,
sizeof(UseCaseContext_t));
3353 context.type = CONFIRM_USE_CASE;
3354 context.confirm.message = message;
3355 context.confirm.subMessage = subMessage;
3356 context.confirm.confirmText = confirmText;
3357 context.confirm.cancelText = cancelText;
3358 context.confirm.onConfirm = callback;
3359 context.currentPage = 0;
3360 context.nbPages = 1 + 2;
3375 const char *message,
3376 const char *actionText,
3384 memset(&context, 0,
sizeof(UseCaseContext_t));
3385 context.type = ACTION_USE_CASE;
3386 context.action.actionCallback = callback;
3388 centeredInfo.
icon = icon;
3389 centeredInfo.
text1 = message;
3425 memset(&context, 0,
sizeof(KeypadContext_t));
3426 context.type = KEYPAD_USE_CASE;
3427 context.currentPage = 0;
3428 context.nbPages = 1;
3429 context.keypad.validatePin = validatePinCallback;
3430 context.keypad.backCallback = backCallback;
3431 context.keypad.pinMinDigits = minDigits;
3432 context.keypad.pinMaxDigits = maxDigits;
3433 context.keypad.hidden = hidden;
3440 USE_CASE_LOGGER,
"nbgl_useCaseKeypad(): layout setup failed (status=%d)\n", status);
3443 context.keypad.keypadIndex = status;
3448 USE_CASE_LOGGER,
"nbgl_useCaseKeypad(): layout setup failed (status=%d)\n", status);
3453 if (context.keypad.backCallback != NULL) {
3494 .mode = params->
mode,
3500 memset(&context, 0,
sizeof(UseCaseContext_t));
3501 context.type = KEYBOARD_USE_CASE;
3502 context.currentPage = 0;
3503 context.nbPages = 1;
3504 context.keyboard.entryBuffer = PIC(params->
entryBuffer);
3505 context.keyboard.entryMaxLen = params->
entryMaxLen;
3506 context.keyboard.entryBuffer[0] =
'\0';
3508 context.keyboard.content.type = params->
type;
3511 context.keyboard.backCallback = PIC(backCallback);
3513 switch (params->
type) {
3520 context.keyboard.getSuggestButtons
3542 USE_CASE_LOGGER,
"nbgl_useCaseKeyboard(): layout setup failed (status=%d)\n", status);
3545 context.keyboard.keyboardIndex = status;
3551 USE_CASE_LOGGER,
"nbgl_useCaseKeyboard(): layout setup failed (status=%d)\n", status);
3554 context.keyboard.textIndex = status;
nbgl_contentCenteredInfoStyle_t
possible styles for Centered Info Area
@ BOLD_TEXT1_INFO
bold is used for text1 (but '\b' can switch to regular)
@ BUTTON_INFO
bold is used for text1 and text2 as a white button
@ REGULAR_INFO
both texts regular (but '\b' can switch to bold)
@ CHOICES_LIST
list of choices through radio buttons
@ CENTERED_INFO
a centered info
@ SWITCHES_LIST
list of switches with descriptions
@ INFOS_LIST
list of infos with titles
@ TAG_VALUE_CONFIRM
tag/value pairs and a black button/footer to confirm/cancel.
@ TAG_VALUE_LIST
list of tag/value pairs
@ BARS_LIST
list of touchable bars (with > on the right to go to sub-pages)
@ INFO_BUTTON
a centered info and a simple black button
@ INFO_LIST_ALIAS
alias is list of infos
@ ENS_ALIAS
alias comes from ENS
@ ADDRESS_BOOK_ALIAS
alias comes from Address Book
void(* nbgl_contentActionCallback_t)(int token, uint8_t index, int page)
prototype of function to be called when an action on a content object occurs
#define LOG_WARN(__logger,...)
#define LOG_DEBUG(__logger,...)
static void actionCallback(nbgl_step_t stepCtx, nbgl_buttonEvent_t event)
static void drawStep(FlowContext_t *ctx, nbgl_stepPosition_t pos, bool modal, const nbgl_icon_details_t *icon, const char *txt, const char *subTxt)
void(* nbgl_stepCallback_t)(void)
prototype of function to be called when a step is using a callback on "double-key" action
void(* nbgl_layoutTouchCallback_t)(int token, uint8_t index)
prototype of function to be called when an object is touched
int nbgl_layoutAddKeyboard(nbgl_layout_t *layout, const nbgl_layoutKbd_t *kbdInfo)
Creates a keyboard on bottom of the screen, with the given configuration.
int nbgl_layoutUpdateKeyboard(nbgl_layout_t *layout, uint8_t index, uint32_t keyMask)
Updates an existing keyboard on bottom of the screen, with the given configuration.
int nbgl_layoutUpdateKeypad(nbgl_layout_t *layout, uint8_t index, bool enableValidate, bool enableBackspace)
Updates an existing keypad on bottom of the screen, with the given configuration.
@ HORIZONTAL_NAV
'<' and '>' are displayed, to navigate between pages and steps
int nbgl_layoutAddKeypadContent(nbgl_layout_t *layout, bool hidden, uint8_t nbDigits, const char *text)
Adds an area with a title and a placeholder for hidden digits on top of a keypad, to represent the en...
int nbgl_layoutUpdateEnteredText(nbgl_layout_t *layout, uint8_t index, const char *text)
Updates an existing "text entry" area, created with nbgl_layoutAddEnteredText()
@ LEFT_ARROW
left arrow is used
@ RIGHT_ARROW
right arrow is used
int nbgl_layoutAddNavigation(nbgl_layout_t *layout, nbgl_layoutNavigation_t *info)
Creates navigation arrows on side(s) of the screen.
int nbgl_layoutAddEnteredText(nbgl_layout_t *layout, const char *text, bool lettersOnly)
Adds a "text entry" area under the previously entered object. The max number of really displayable ch...
int nbgl_layoutAddCenteredInfo(nbgl_layout_t *layout, const nbgl_layoutCenteredInfo_t *info)
Creates an area on the center of the main panel, with a possible icon/image, a possible text in black...
int nbgl_layoutDraw(nbgl_layout_t *layout)
Applies given layout. The screen will be redrawn.
#define NB_MAX_SUGGESTION_BUTTONS
void * nbgl_layout_t
type shared externally
int nbgl_layoutUpdateKeypadContent(nbgl_layout_t *layout, bool hidden, uint8_t nbActiveDigits, const char *text)
Updates an existing set of hidden digits, with the given configuration.
nbgl_layout_t * nbgl_layoutGet(const nbgl_layoutDescription_t *description)
returns a layout of the given type. The layout is reset
int nbgl_layoutAddKeypad(nbgl_layout_t *layout, keyboardCallback_t callback, const char *text, bool shuffled)
Adds a keypad on bottom of the screen, with the associated callback.
@ KEYBOARD_WITH_BUTTON
text entry area + confirmation button
@ KEYBOARD_WITH_SUGGESTIONS
text entry area + suggestion buttons
int nbgl_layoutRelease(nbgl_layout_t *layout)
Release the layout obtained with nbgl_layoutGet()
#define KEYBOARD_MAX_TITLE
@ BUTTON_BOTH_PRESSED
Sent when both buttons are released.
@ BUTTON_LEFT_PRESSED
Sent when Left button is released.
@ BUTTON_RIGHT_PRESSED
Send when Right button is released.
struct PACKED__ nbgl_screenTickerConfiguration_s nbgl_screenTickerConfiguration_t
struct to configure a screen layer
void nbgl_screenRedraw(void)
void(* nbgl_stepButtonCallback_t)(nbgl_step_t stepCtx, nbgl_buttonEvent_t event)
prototype of function to be called when buttons are touched on a screen
#define GET_POS_OF_STEP(_step, _nb_steps)
nbgl_step_t nbgl_stepDrawSwitch(nbgl_stepPosition_t pos, nbgl_stepButtonCallback_t onActionCallback, nbgl_screenTickerConfiguration_t *ticker, nbgl_layoutSwitch_t *switchInfo, bool modal)
draw a step page with a switch and navigation arrows to navigate to other pages.
void * nbgl_step_t
type shared externally
uint8_t nbgl_stepPosition_t
this type is a bitfield containing:
@ NEITHER_FIRST_NOR_LAST_STEP
neither first nor last in a multiple steps flow
@ SINGLE_STEP
single step flow
@ LAST_STEP
last in a multiple steps flow
@ FIRST_STEP
first in a multiple steps flow
nbgl_step_t nbgl_stepDrawMenuList(nbgl_stepMenuListCallback_t onActionCallback, nbgl_screenTickerConfiguration_t *ticker, nbgl_layoutMenuList_t *list, bool modal)
draw a step page with a menu list and navigation arrows to parse it. This step must be alone
#define ACTION_ON_ANY_BUTTON
When action callback applies only on both button press.
int nbgl_stepRelease(nbgl_step_t step)
Release the step obtained with any of the nbgl_stepDrawXXX() functions.
#define FORWARD_DIRECTION
When the flow is navigated from last to first step.
nbgl_step_t nbgl_stepDrawText(nbgl_stepPosition_t pos, nbgl_stepButtonCallback_t onActionCallback, nbgl_screenTickerConfiguration_t *ticker, const char *text, const char *subText, nbgl_contentCenteredInfoStyle_t style, bool modal)
draws a text type step, that can be multi-pages, depending of the length of text and subText....
nbgl_step_t nbgl_stepDrawCenteredInfo(nbgl_stepPosition_t pos, nbgl_stepButtonCallback_t onActionCallback, nbgl_screenTickerConfiguration_t *ticker, nbgl_layoutCenteredInfo_t *info, bool modal)
draw a step with a centered info (icon + text). This is always a single page step
#define BACKWARD_DIRECTION
When action callback applies on any button press.
nbgl_state_t
to represent a boolean state.
struct PACKED__ nbgl_icon_details_s nbgl_icon_details_t
Represents all information about an icon.
API of the Advanced BOLOS Graphical Library, for typical application use-cases.
@ NO_TYPE_WARNING
Invalid type (to use for bars leading to nothing)
@ CENTERED_INFO_WARNING
Centered info.
@ BAR_LIST_WARNING
list of touchable bars, to display sub-pages
uint8_t nbgl_useCaseGetNbTagValuesInPageExt(uint8_t nbPairs, const nbgl_contentTagValueList_t *tagValueList, uint8_t startIndex, bool isSkippable, bool *requireSpecificDisplay)
void(* nbgl_callback_t)(void)
prototype of generic callback function
#define SKIPPABLE_OPERATION
This is to use in nbgl_operationType_t when the operation is skippable. This is used to add a Skip bu...
void nbgl_useCaseGenericSettings(const char *appName, uint8_t initPage, const nbgl_genericContents_t *settingContents, const nbgl_contentInfoList_t *infosList, nbgl_callback_t quitCallback)
uint32_t nbgl_operationType_t
This mask is used to describe the type of operation to review with additional options It is a mask of...
void nbgl_useCaseReview(nbgl_operationType_t operationType, const nbgl_contentTagValueList_t *tagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *finishTitle, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseAction(const nbgl_icon_details_t *icon, const char *message, const char *actionText, nbgl_callback_t callback)
uint8_t nbgl_useCaseGetNbTagValuesInPage(uint8_t nbPairs, const nbgl_contentTagValueList_t *tagValueList, uint8_t startIndex, bool *requireSpecificDisplay)
uint8_t nbgl_useCaseGetNbPagesForTagValueList(const nbgl_contentTagValueList_t *tagValueList)
void(* nbgl_pinValidCallback_t)(const uint8_t *pin, uint8_t pinLen)
prototype of pin validation callback function
void nbgl_useCaseReviewStreamingStart(nbgl_operationType_t operationType, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseHomeAndSettings(const char *appName, const nbgl_icon_details_t *appIcon, const char *tagline, const uint8_t initSettingPage, const nbgl_genericContents_t *settingContents, const nbgl_contentInfoList_t *infosList, const nbgl_homeAction_t *action, nbgl_callback_t quitCallback)
#define RISKY_OPERATION
This is to use in nbgl_operationType_t when the operation is concerned by an internal warning....
uint8_t nbgl_useCaseGetNbInfosInPage(uint8_t nbInfos, const nbgl_contentInfoList_t *infosList, uint8_t startIndex, bool withNav)
void(* nbgl_choiceCallback_t)(bool confirm)
prototype of choice callback function
uint8_t nbgl_useCaseGetNbBarsInPage(uint8_t nbBars, const nbgl_contentBarsList_t *barsList, uint8_t startIndex, bool withNav)
void nbgl_useCaseNavigableContent(const char *title, uint8_t initPage, uint8_t nbPages, nbgl_callback_t quitCallback, nbgl_navCallback_t navCallback, nbgl_layoutTouchCallback_t controlsCallback)
void nbgl_useCaseReviewStreamingFinish(const char *finishTitle, nbgl_choiceCallback_t choiceCallback)
#define NO_THREAT_OPERATION
This is to use in nbgl_operationType_t when the operation is concerned by an internal information....
void nbgl_useCaseChoiceWithDetails(const nbgl_icon_details_t *icon, const char *message, const char *subMessage, const char *confirmText, const char *cancelText, nbgl_warningDetails_t *details, nbgl_choiceCallback_t callback)
void nbgl_useCaseAdvancedChoiceWithDetails(const nbgl_icon_details_t *centerIcon, const nbgl_icon_details_t *headerIcon, const char *title, const char *message, const char *subMessage, const char *confirmText, const char *cancelText, nbgl_warningDetails_t *details, nbgl_choiceCallback_t callback)
void nbgl_useCaseSpinner(const char *text)
void nbgl_useCaseConfirm(const char *message, const char *subMessage, const char *confirmText, const char *rejectText, nbgl_callback_t callback)
void nbgl_useCaseStatus(const char *message, bool isSuccess, nbgl_callback_t quitCallback)
@ BLIND_SIGNING_WARN
Blind signing.
@ W3C_NO_THREAT_WARN
Web3 Checks: No Threat detected.
void nbgl_useCaseGenericConfiguration(const char *title, uint8_t initPage, const nbgl_genericContents_t *contents, nbgl_callback_t quitCallback)
#define INIT_HOME_PAGE
Value to pass to nbgl_useCaseHomeAndSettings() initSettingPage parameter to initialize the use case o...
void nbgl_useCaseKeypad(const char *title, uint8_t minDigits, uint8_t maxDigits, bool shuffled, bool hidden, nbgl_pinValidCallback_t validatePinCallback, nbgl_callback_t backCallback)
void nbgl_useCaseReviewStreamingContinueExt(const nbgl_contentTagValueList_t *tagValueList, nbgl_choiceCallback_t choiceCallback, nbgl_callback_t skipCallback)
void nbgl_useCaseReviewBlindSigning(nbgl_operationType_t operationType, const nbgl_contentTagValueList_t *tagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *finishTitle, const nbgl_tipBox_t *tipBox, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseChoice(const nbgl_icon_details_t *icon, const char *message, const char *subMessage, const char *confirmText, const char *rejectString, nbgl_choiceCallback_t callback)
void nbgl_useCaseGenericReview(const nbgl_genericContents_t *contents, const char *rejectText, nbgl_callback_t rejectCallback)
#define STATUS_SCREEN_DURATION
void nbgl_useCaseKeyboard(const nbgl_keyboardParams_t *params, nbgl_callback_t backCallback)
void nbgl_useCaseReviewStreamingBlindSigningStart(nbgl_operationType_t operationType, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseReviewStreamingContinue(const nbgl_contentTagValueList_t *tagValueList, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseReviewLight(nbgl_operationType_t operationType, const nbgl_contentTagValueList_t *tagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *finishTitle, nbgl_choiceCallback_t choiceCallback)
uint8_t nbgl_useCaseGetNbChoicesInPage(uint8_t nbChoices, const nbgl_contentRadioChoice_t *choicesList, uint8_t startIndex, bool withNav)
void(* nbgl_keyboardButtonsCallback_t)(nbgl_layoutKeyboardContent_t *content, uint32_t *mask)
prototype of keyboard buttons callback function
#define REAL_TYPE_MASK
Mask to apply on nbgl_operationType_t to extract the base nbgl_opType_t. Bits 0-3 are reserved for th...
void nbgl_useCaseReviewStatus(nbgl_reviewStatusType_t reviewStatusType, nbgl_callback_t quitCallback)
#define ADDRESS_BOOK_OPERATION
This is to use in nbgl_operationType_t when the operation is related to "Address Book" to adapt wordi...
nbgl_reviewStatusType_t
The different types of review status.
@ STATUS_TYPE_TRANSACTION_REJECTED
@ STATUS_TYPE_ADDRESS_REJECTED
@ STATUS_TYPE_TRANSACTION_SIGNED
@ STATUS_TYPE_OPERATION_REJECTED
@ STATUS_TYPE_OPERATION_SIGNED
@ STATUS_TYPE_ADDRESS_VERIFIED
@ STATUS_TYPE_MESSAGE_SIGNED
@ STATUS_TYPE_MESSAGE_REJECTED
bool(* nbgl_navCallback_t)(uint8_t page, nbgl_pageContent_t *content)
prototype of navigation callback function
#define HAS_INITIAL_WARNING(_warning)
void nbgl_useCaseAddressReview(const char *address, const nbgl_contentTagValueList_t *additionalTagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, nbgl_choiceCallback_t choiceCallback)
@ TYPE_TRANSACTION
For operations transferring a coin or taken from an account to another.
void nbgl_useCaseAdvancedReviewStreamingStart(nbgl_operationType_t operationType, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const nbgl_warning_t *warning, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseAdvancedReview(nbgl_operationType_t operationType, const nbgl_contentTagValueList_t *tagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *finishTitle, const nbgl_tipBox_t *tipBox, const nbgl_warning_t *warning, nbgl_choiceCallback_t choiceCallback)
uint8_t nbgl_useCaseGetNbSwitchesInPage(uint8_t nbSwitches, const nbgl_contentSwitchesList_t *switchesList, uint8_t startIndex, bool withNav)
This structure contains data to build a BARS_LIST content.
const uint8_t * tokens
array of tokens, one for each bar (nbBars items)
const char *const * barTexts
array of texts for each bar (nbBars items, in black/bold)
const char * title
Nano only and used in the horizontal flow: per-content header text. Same semantics as nbgl_contentRad...
uint8_t nbBars
number of elements in barTexts and tokens array
const nbgl_icon_details_t * icon
the icon (can be null)
const char * title
title in black large (can be null)
const char * description
description in black small regular case (can be null)
This structure contains info to build a centered (vertically and horizontally) area,...
const char * text2
second text (can be null)
const char * text1
first text (can be null)
nbgl_contentCenteredInfoStyle_t style
style to apply to this info
const nbgl_icon_details_t * icon
a buffer containing the 1BPP icon
const char * buttonText
text of the long press button
const nbgl_icon_details_t * icon
a buffer containing the 1BPP icon
const char * text
centered text in large case
This structure contains data to build a INFOS_LIST content.
const char *const * infoContents
array of contents of infos (in black)
const char *const * infoTypes
array of types of infos (in black/bold)
uint8_t nbInfos
number of elements in infoTypes and infoContents array
This structure contains a list of names to build a list of radio buttons (on the right part of screen...
uint8_t token
the token that will be used as argument of the callback
uint8_t initChoice
index of the current choice
const char *const * names
array of strings giving the choices (nbChoices)
const nbgl_icon_details_t * selectionIcon
uint8_t nbChoices
number of choices
const char * title
Nano only and used in the horizontal flow (i.e. vertical is false): per-content header text shown abo...
This structure contains info to build a switch (on the right) with a description (on the left),...
const char * text
main text for the switch
uint8_t token
the token that will be used as argument of the callback (unused on Nano)
nbgl_state_t initState
initial state of the switch
const char * subText
description under main text (NULL terminated, single line, may be null)
const char * confirmationText
text of the confirmation button, if NULL "It matches" is used
uint8_t confirmationToken
the token used as argument of the onActionCallback
nbgl_contentTagValueList_t tagValueList
list of tag/value pairs
This structure contains a list of [tag,value] pairs.
const nbgl_contentTagValue_t * pairs
array of [tag,value] pairs (nbPairs items). If NULL, callback is used instead
nbgl_contentTagValueCallback_t callback
function to call to retrieve a given pair
This structure contains a [tag,value] pair and possible extensions.
const nbgl_contentValueExt_t * extension
if not NULL, gives additional info on value field
const nbgl_icon_details_t * valueIcon
const char * value
string giving the value name
const char * item
string giving the tag name
uint8_t centeredInfo
if set to 1, the tag will be displayed as a centered info
This structure contains additions to a tag/value pair, to be able to build a screen to display these ...
This structure contains data to build a content.
nbgl_contentActionCallback_t contentActionCallback
callback to be called when an action on an object occurs
nbgl_contentType_t type
type of page content in the content union
const struct nbgl_genericDetails_s * details
array of nbBars structures giving what to display when each bar is touched.
uint8_t nbBars
number of touchable bars
uint8_t nbContents
number of contents
const nbgl_content_t * contentsList
array of nbgl_content_t (nbContents items).
nbgl_contentCallback_t contentGetterCallback
function to call to retrieve a given content
The necessary parameters to build the page(s) displayed when the top-right button is touched in intro...
nbgl_genericBarList_t barList
touchable bars list, if type == BAR_LIST_WARNING
nbgl_genericDetailsType_t type
type of content in the page, determining what to use in the following union
nbgl_contentCenter_t centeredInfo
centered info, if type == CENTERED_INFO_WARNING
Structure describing the action button in Home Screen.
nbgl_keyboardButtonsCallback_t updateButtonsCallback
callback to call when a key is pressed to update suggestions
nbgl_layoutTouchCallback_t onButtonCallback
callback to call when one of the buttons is pressed
const char ** buttons
array of strings for buttons (last ones can be NULL)
int firstButtonToken
first token used for buttons, provided in onButtonCallback
Structure containing all parameters for keyboard use case.
keyboardMode_t mode
keyboard mode to start with
nbgl_kbdSuggestParams_t suggestionParams
nbgl_kbdButtonParams_t confirmationParams
used if type is KEYBOARD_WITH_SUGGESTIONS
bool lettersOnly
if true, only display letter keys and Backspace
uint8_t entryMaxLen
maximum length of text that can be entered
nbgl_layoutKeyboardContentType_t type
type of content
const char * title
centered title explaining the screen
char * entryBuffer
already entered text
Structure containing all information when creating a layout. This structure must be passed as argumen...
This structure contains info to build a keyboard with nbgl_layoutAddKeyboard()
keyboardCallback_t callback
function called when an active key is pressed
This structure contains info to build a keyboard content (controls that are linked to keyboard)
This structure contains info to build a navigation bar at the bottom of the screen.
nbgl_layoutNavDirection_t direction
vertical or horizontal navigation
This structure contains data to build a page in multi-pages mode (nbgl_pageDrawGenericContent)
nbgl_contentRadioChoice_t choicesList
CHOICES_LIST type
nbgl_contentSwitchesList_t switchesList
SWITCHES_LIST type
nbgl_contentBarsList_t barsList
BARS_LIST type
nbgl_contentInfoButton_t infoButton
INFO_BUTTON type
nbgl_contentInfoList_t infosList
INFOS_LIST type
nbgl_contentTagValueList_t tagValueList
TAG_VALUE_LIST type
nbgl_contentType_t type
type of page content in the following union
nbgl_contentCenteredInfo_t centeredInfo
CENTERED_INFO type
nbgl_contentTagValueConfirm_t tagValueConfirm
TAG_VALUE_CONFIRM type
This structure contains data to build a SWITCHES_LIST content.
uint8_t nbSwitches
number of elements in switches and tokens array
const nbgl_contentSwitch_t * switches
array of switches (nbSwitches items)
The necessary parameters to build a tip-box in first review page and the modal if this tip box is tou...
The necessary parameters to build a warning page preceding a review. One can either use predefinedSet...
const nbgl_preludeDetails_t * prelude
if not null, means that the review can start by a prelude
const nbgl_warningDetails_t * reviewDetails
const nbgl_contentCenter_t * info
parameters to build the intro warning page, if not using pre-defined
nbgl_contentInfoList_t infosList
INFOS_LIST type
nbgl_contentTagValueConfirm_t tagValueConfirm
TAG_VALUE_CONFIRM type
nbgl_contentTagValueList_t tagValueList
TAG_VALUE_LIST type
nbgl_contentCenteredInfo_t centeredInfo
CENTERED_INFO type
nbgl_contentBarsList_t barsList
BARS_LIST type
nbgl_contentSwitchesList_t switchesList
SWITCHES_LIST type
nbgl_contentInfoButton_t infoButton
INFO_BUTTON type
nbgl_contentRadioChoice_t choicesList
CHOICES_LIST type