17#include "os_helpers.h"
23#define WITH_HORIZONTAL_CHOICES_LIST
24#define WITH_HORIZONTAL_BARS_LIST
31#define RISKY_OPERATION (1 << 6)
38#define NO_THREAT_OPERATION (1 << 7)
44typedef struct ReviewContext_s {
48 const char *reviewTitle;
49 const char *reviewSubTitle;
50 const char *finishTitle;
55 uint8_t dataDirection;
56 uint8_t currentTagValueIndex;
57 uint8_t currentExtensionPage;
58 uint8_t nbExtensionPages;
64typedef struct ChoiceContext_s {
67 const char *subMessage;
68 const char *confirmText;
69 const char *cancelText;
74typedef struct ConfirmContext_s {
76 const char *subMessage;
77 const char *confirmText;
78 const char *cancelText;
83typedef struct ContentContext_s {
86 const char *rejectText;
92typedef struct HomeContext_s {
102typedef struct ActionContext_s {
107typedef struct KeypadContext_s {
110 uint8_t pinMinDigits;
111 uint8_t pinMaxDigits;
124 GENERIC_REVIEW_USE_CASE,
125 ADDRESS_REVIEW_USE_CASE,
126 STREAMING_START_REVIEW_USE_CASE,
127 STREAMING_CONTINUE_REVIEW_USE_CASE,
128 STREAMING_FINISH_REVIEW_USE_CASE,
141typedef struct UseCaseContext_s {
146 int8_t firstPairPage;
151 ReviewContext_t review;
152 ChoiceContext_t choice;
153 ConfirmContext_t confirm;
155 ContentContext_t content;
157 KeypadContext_t keypad;
159 ActionContext_t action;
163typedef struct PageContent_s {
174typedef struct ReviewWithWarningContext_s {
179 const char *reviewTitle;
180 const char *reviewSubTitle;
181 const char *finishTitle;
184 uint8_t securityReportLevel;
187 uint8_t nbWarningPages;
188 uint8_t firstWarningPage;
189} ReviewWithWarningContext_t;
200static UseCaseContext_t context;
202static ReviewWithWarningContext_t reviewWithWarnCtx;
220static void displaySpinner(
const char *text);
222static void startUseCaseHome(
void);
223static void startUseCaseInfo(
void);
224static void startUseCaseSettings(
void);
225static void startUseCaseSettingsAtPage(uint8_t initSettingPage);
226static void startUseCaseContent(
void);
228static void statusTickerCallback(
void);
231static void displayWarningStep(
void);
236 switch (content->
type) {
266 if (contentIdx < 0 || contentIdx >= genericContents->
nbContents) {
272 if (content == NULL) {
278 if (context.content.navCallback) {
279 if (context.content.navCallback(contentIdx, &pageContent) ==
true) {
282 switch (content->
type) {
331 uint8_t *elemContentIdx,
337 uint8_t elemNbPages = 0;
339 switch (context.type) {
340 case SETTINGS_USE_CASE:
342 case GENERIC_SETTINGS:
343 genericContents = context.home.settingContents;
345 case CONTENT_USE_CASE:
346 case GENERIC_REVIEW_USE_CASE:
347 genericContents = &context.content.genericContents;
352 for (
int i = 0; i < genericContents->
nbContents; i++) {
353 p_content = getContentAtIdx(genericContents, i, content);
354 elemNbPages = getContentNbElement(p_content);
355 if (nbPages + elemNbPages > elemIdx) {
356 *elemContentIdx = context.currentPage - nbPages;
359 nbPages += elemNbPages;
365static const char *getChoiceName(uint8_t choiceIndex)
375 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
376 if (p_content == NULL) {
379 switch (p_content->
type) {
382 names = (
char **) PIC(contentChoices->
names);
387 names = (
char **) PIC(contentBars->
barTexts);
388 nbValues = contentBars->
nbBars;
394 if (choiceIndex >= nbValues) {
398 return (
const char *) PIC(names[choiceIndex]);
401static void onChoiceSelected(uint8_t choiceIndex)
410 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
411 if (p_content == NULL) {
414 switch (p_content->
type) {
417 if (choiceIndex < contentChoices->nbChoices) {
418 token = contentChoices->
token;
423 if (choiceIndex < contentBars->nbBars) {
424 token = contentBars->
tokens[choiceIndex];
431 if ((token != 255) && (context.content.controlsCallback != NULL)) {
432 context.content.controlsCallback(token, 0);
434 else if (context.content.quitCallback != NULL) {
435 context.content.quitCallback();
445 bool *isCenteredInfo)
449 if (tagValueList->
pairs != NULL) {
450 pair = PIC(&tagValueList->
pairs[index]);
453 pair = PIC(tagValueList->
callback(index));
456 *value = pair->
value;
461 *isCenteredInfo =
true;
469static void onReviewAccept(
void)
471 if (context.review.onChoice) {
472 context.review.onChoice(
true);
476static void onReviewReject(
void)
478 if (context.review.onChoice) {
479 context.review.onChoice(
false);
483static void onChoiceAccept(
void)
485 if (context.choice.onChoice) {
486 context.choice.onChoice(
true);
490static void onChoiceReject(
void)
492 if (context.choice.onChoice) {
493 context.choice.onChoice(
false);
497static void onConfirmAccept(
void)
499 if (context.confirm.currentStep) {
502 if (context.confirm.onConfirm) {
503 context.confirm.onConfirm();
507static void onConfirmReject(
void)
509 if (context.confirm.currentStep) {
516static void onSwitchAction(
void)
523 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
529 switch (context.type) {
530 case SETTINGS_USE_CASE:
532 case GENERIC_SETTINGS:
535 case CONTENT_USE_CASE:
536 case GENERIC_REVIEW_USE_CASE:
544 actionCallback(contentSwitch->
token,
546 context.currentPage);
548 else if (context.content.controlsCallback != NULL) {
549 context.content.controlsCallback(contentSwitch->
token, 0);
559 ForcedType_t forcedType)
570 .tickerIntervale = 0,
576 if ((context.type == STREAMING_CONTINUE_REVIEW_USE_CASE)
577 && (context.review.skipCallback != NULL) && (context.review.nbDataSets > 1)) {
580 if ((context.type == STATUS_USE_CASE) || (context.type == SPINNER_USE_CASE)) {
583 if ((context.type == CONFIRM_USE_CASE) && (context.confirm.currentStep != NULL)) {
588 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
590 switch (p_content->
type) {
612 else if ((icon == NULL) && (forcedType != FORCE_CENTERED_INFO)) {
614 if (subTxt != NULL) {
615 style = (forcedType == FORCE_BUTTON) ? BUTTON_INFO : BOLD_TEXT1_INFO;
618 style = REGULAR_INFO;
620 newStep =
nbgl_stepDrawText(pos, onActionCallback, p_ticker, txt, subTxt, style, modal);
628 if ((subTxt != NULL) || (context.stepCallback != NULL) || context.forceAction) {
629 info.
style = BOLD_TEXT1_INFO;
632 info.
style = REGULAR_INFO;
636 if (context.type == CONFIRM_USE_CASE) {
637 context.confirm.currentStep = newStep;
643 const char *description,
652 switchInfo.
text = title;
653 switchInfo.
subText = description;
666 if (context.currentPage > 0) {
667 context.currentPage--;
671 else if ((context.type != STREAMING_CONTINUE_REVIEW_USE_CASE)
672 || (context.review.skipCallback == NULL) || (context.review.nbDataSets == 1)) {
679 if (context.currentPage < (
int) (context.nbPages - 1)) {
680 context.currentPage++;
690 if (context.stepCallback != NULL) {
691 context.stepCallback();
693 else if ((context.type == CONTENT_USE_CASE) || (context.type == SETTINGS_USE_CASE)
694 || (context.type == GENERIC_SETTINGS)
695 || (context.type == GENERIC_REVIEW_USE_CASE)) {
696 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
697 if (p_content != NULL) {
698 switch (p_content->
type) {
713 index = context.currentPage;
718 if (elemIdx < p_content->content.tagValueConfirm.tagValueList.nbPairs) {
730 else if (context.content.controlsCallback != NULL) {
731 context.content.controlsCallback(token, index);
746 if (!buttonGenericCallback(event, &pos)) {
751 context.review.dataDirection = pos;
753 displayReviewPage(pos);
765 && (context.currentPage > context.firstPairPage)) {
766 context.currentPage--;
773 && (context.currentPage < (
int) (context.nbPages - 1))
774 && (context.currentPage > context.firstPairPage)) {
775 context.currentPage++;
781 if (context.firstPairPage == 0) {
783 context.review.skipCallback();
787 context.currentPage = context.nbPages - 2;
796 if (context.firstPairPage == 0) {
797 displayStreamingReviewPage(pos);
800 displayReviewPage(pos);
810 context.action.actionCallback();
819 if (!buttonGenericCallback(event, &pos)) {
824 context.review.dataDirection = pos;
827 displayStreamingReviewPage(pos);
835 if (!buttonGenericCallback(event, &pos)) {
839 displaySettingsPage(pos,
false);
847 if (!buttonGenericCallback(event, &pos)) {
851 displayInfoPage(pos);
859 if (!buttonGenericCallback(event, &pos)) {
863 displayHomePage(pos);
871 if (!buttonGenericCallback(event, &pos)) {
875 displayChoicePage(pos);
883 if (!buttonGenericCallback(event, &pos)) {
896 if (context.stepCallback != NULL) {
897 context.stepCallback();
907 if (!buttonGenericCallback(event, &pos)) {
911 displayContent(pos,
false);
915static void statusTickerCallback(
void)
917 if (context.stepCallback != NULL) {
918 context.stepCallback();
930 if (context.review.currentExtensionPage > 0) {
931 context.review.currentExtensionPage--;
937 if (context.review.currentExtensionPage < (context.review.nbExtensionPages - 1)) {
938 context.review.currentExtensionPage++;
944 if (context.review.currentExtensionPage == (context.review.nbExtensionPages - 1)) {
954 displayExtensionStep(pos);
963 const char *text = NULL;
964 const char *subText = NULL;
966 if (context.review.extensionStepCtx != NULL) {
969 if (context.review.currentExtensionPage < (context.review.nbExtensionPages - 1)) {
970 if (context.review.currentExtensionPage == 0) {
977 switch (context.review.extension->aliasType) {
979 text = context.review.extension->title;
980 subText = context.review.extension->fullValue;
983 infoList = context.review.extension->infolist;
984 text = PIC(infoList->
infoTypes[context.review.currentExtensionPage]);
985 subText = PIC(infoList->
infoContents[context.review.currentExtensionPage]);
988 tagValueList = context.review.extension->tagValuelist;
989 text = PIC(tagValueList->
pairs[context.review.currentExtensionPage].
item);
990 subText = PIC(tagValueList->
pairs[context.review.currentExtensionPage].
value);
997 pos, extensionNavigate, NULL, text, subText, BOLD_TEXT1_INFO,
true);
1000 else if (context.review.currentExtensionPage == (context.review.nbExtensionPages - 1)) {
1002 info.
icon = &C_icon_back_x;
1003 info.
text1 =
"Back";
1004 info.
style = BOLD_TEXT1_INFO;
1006 context.review.extensionStepCtx
1012static void displayAliasFullValue(
void)
1014 const char *text = NULL;
1015 const char *subText = NULL;
1017 bool isCenteredInfo;
1019 getPairData(context.review.tagValueList,
1020 context.review.currentTagValueIndex,
1023 &context.review.extension,
1026 if (context.review.extension == NULL) {
1029 "displayAliasFullValue: extension nor found for pair %d\n",
1030 context.review.currentTagValueIndex);
1033 context.review.currentExtensionPage = 0;
1034 context.review.extensionStepCtx = NULL;
1036 switch (context.review.extension->aliasType) {
1038 context.review.nbExtensionPages = 2;
1041 context.review.nbExtensionPages = context.review.extension->infolist->nbInfos + 1;
1044 context.review.nbExtensionPages = context.review.extension->tagValuelist->nbPairs + 1;
1048 "displayAliasFullValue: unsupported alias type %d\n",
1049 context.review.extension->aliasType);
1055static void getLastPageInfo(
bool approve,
const nbgl_icon_details_t **icon,
const char **text)
1059 *icon = &C_icon_validate_14;
1060 if (context.type == ADDRESS_REVIEW_USE_CASE) {
1065 if (context.review.finishTitle != NULL) {
1066 *text = context.review.finishTitle;
1071 if (context.operationType & RISKY_OPERATION) {
1072 *text =
"Accept risk and sign transaction";
1075 *text =
"Sign transaction";
1079 if (context.operationType & RISKY_OPERATION) {
1080 *text =
"Accept risk and sign message";
1083 *text =
"Sign message";
1087 if (context.operationType & RISKY_OPERATION) {
1088 *text =
"Accept risk and sign operation";
1091 *text =
"Sign operation";
1097 context.stepCallback = onReviewAccept;
1101 *icon = &C_icon_crossmark;
1102 if (context.type == ADDRESS_REVIEW_USE_CASE) {
1106 *text =
"Reject transaction";
1109 *text =
"Reject message";
1112 *text =
"Reject operation";
1114 context.stepCallback = onReviewReject;
1121 uint8_t reviewPages = 0;
1122 uint8_t finalPages = 0;
1123 uint8_t pairIndex = 0;
1124 const char *text = NULL;
1125 const char *subText = NULL;
1127 uint8_t currentIndex = 0;
1128 uint8_t titleIndex = 255;
1129 uint8_t subIndex = 255;
1130 uint8_t approveIndex = 255;
1131 uint8_t rejectIndex = 255;
1133 ForcedType_t forcedType = NO_FORCED_TYPE;
1135 context.stepCallback = NULL;
1139 titleIndex = currentIndex++;
1141 if (context.review.reviewSubTitle) {
1143 subIndex = currentIndex++;
1146 approveIndex = context.nbPages - 2;
1147 rejectIndex = context.nbPages - 1;
1148 finalPages = approveIndex;
1151 if (context.currentPage >= finalPages) {
1152 if (context.currentPage == approveIndex) {
1154 getLastPageInfo(
true, &icon, &text);
1156 else if (context.currentPage == rejectIndex) {
1158 getLastPageInfo(
false, &icon, &text);
1161 else if (context.currentPage < reviewPages) {
1162 if (context.currentPage == titleIndex) {
1164 icon = context.review.icon;
1165 text = context.review.reviewTitle;
1167 else if (context.currentPage == subIndex) {
1169 text = context.review.reviewSubTitle;
1172 else if ((context.review.address != NULL) && (context.currentPage == reviewPages)) {
1175 subText = context.review.address;
1181 if ((context.operationType &
SKIPPABLE_OPERATION) && (context.review.skipDisplay ==
false)
1182 && ((context.currentPage > reviewPages)
1186 if ((context.review.nbDataSets == 1) || (context.currentPage > 0)) {
1189 info.
icon = &C_Information_circle_14px;
1190 info.
text1 =
"Press right button to continue message or \bpress both to skip\b";
1193 context.review.skipDisplay =
true;
1194 context.firstPairPage = reviewPages;
1197 context.review.skipDisplay =
false;
1198 bool isCenteredInfo =
false;
1199 pairIndex = context.currentPage - reviewPages;
1200 if (context.review.address != NULL) {
1203 getPairData(context.review.tagValueList,
1210 if (extension != NULL) {
1211 context.stepCallback = displayAliasFullValue;
1212 context.review.currentTagValueIndex = pairIndex;
1213 forcedType = FORCE_BUTTON;
1216 if (isCenteredInfo) {
1217 forcedType = FORCE_CENTERED_INFO;
1222 drawStep(pos, icon, text, subText, reviewCallback,
false, forcedType);
1229 const char *text = NULL;
1230 const char *subText = NULL;
1232 uint8_t reviewPages = 0;
1233 uint8_t titleIndex = 255;
1234 uint8_t subIndex = 255;
1236 ForcedType_t forcedType = NO_FORCED_TYPE;
1238 context.stepCallback = NULL;
1239 switch (context.type) {
1240 case STREAMING_START_REVIEW_USE_CASE:
1242 titleIndex = reviewPages++;
1243 if (context.review.reviewSubTitle) {
1245 subIndex = reviewPages++;
1248 if (context.currentPage >= reviewPages) {
1253 if (context.currentPage == titleIndex) {
1255 icon = context.review.icon;
1256 text = context.review.reviewTitle;
1258 else if (context.currentPage == subIndex) {
1260 text = context.review.reviewSubTitle;
1264 case STREAMING_CONTINUE_REVIEW_USE_CASE:
1265 if (context.currentPage >= context.review.tagValueList->nbPairs) {
1272 if ((context.review.skipCallback != NULL) && (context.review.skipDisplay ==
false)
1273 && ((context.review.nbDataSets > 1) || (context.currentPage > 0)
1277 if ((context.review.nbDataSets == 1) || (context.currentPage > 0)) {
1280 info.
icon = &C_Information_circle_14px;
1281 info.
text1 =
"Press right button to continue message or \bpress both to skip\b";
1284 context.review.skipDisplay =
true;
1287 context.review.skipDisplay =
false;
1288 bool isCenteredInfo =
false;
1289 getPairData(context.review.tagValueList,
1290 context.currentPage,
1296 if (extension != NULL) {
1297 forcedType = FORCE_BUTTON;
1300 if (isCenteredInfo) {
1301 forcedType = FORCE_CENTERED_INFO;
1306 case STREAMING_FINISH_REVIEW_USE_CASE:
1308 if (context.currentPage == 0) {
1310 getLastPageInfo(
true, &icon, &text);
1314 getLastPageInfo(
false, &icon, &text);
1319 drawStep(pos, icon, text, subText, streamingReviewCallback,
false, forcedType);
1326 const char *text = NULL;
1327 const char *subText = NULL;
1330 context.stepCallback = NULL;
1332 if (context.currentPage < (context.nbPages - 1)) {
1334 ((
const char *
const *) PIC(context.home.infosList->infoTypes))[context.currentPage]);
1336 ((
const char *
const *) PIC(context.home.infosList->infoContents))[context.currentPage]);
1339 icon = &C_icon_back_x;
1341 context.stepCallback = startUseCaseHome;
1344 drawStep(pos, icon, text, subText, infoCallback,
false, FORCE_CENTERED_INFO);
1349static void getContentPage(
bool toogle_state, PageContent_t *contentPage)
1351 uint8_t elemIdx = 0;
1355#ifdef WITH_HORIZONTAL_CHOICES_LIST
1357 char **names = NULL;
1359#ifdef WITH_HORIZONTAL_BARS_LIST
1361 char **texts = NULL;
1363 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
1364 if (p_content == NULL) {
1367 switch (p_content->
type) {
1381 &contentPage->subText,
1382 &contentPage->extension,
1384 &contentPage->isCenteredInfo);
1387 if (elemIdx < p_content->content.tagValueConfirm.tagValueList.nbPairs) {
1391 &contentPage->subText,
1392 &contentPage->extension,
1394 &contentPage->isCenteredInfo);
1398 contentPage->icon = &C_icon_validate_14;
1399 contentPage->isAction =
true;
1403 contentPage->isSwitch =
true;
1406 contentPage->
text = contentSwitch->
text;
1407 contentPage->state = contentSwitch->
initState;
1411 context.stepCallback = onSwitchAction;
1412 contentPage->subText = contentSwitch->
subText;
1417 contentPage->subText
1421#ifdef WITH_HORIZONTAL_CHOICES_LIST
1423 names = (
char **) PIC(contentChoices->
names);
1424 if ((context.type == CONTENT_USE_CASE) && (context.content.title != NULL)) {
1425 contentPage->text = PIC(context.content.title);
1426 contentPage->subText = (
const char *) PIC(names[elemIdx]);
1428 else if ((context.type == GENERIC_SETTINGS) && (context.home.appName != NULL)) {
1429 contentPage->text = PIC(context.home.appName);
1430 contentPage->subText = (
const char *) PIC(names[elemIdx]);
1433 contentPage->text = (
const char *) PIC(names[elemIdx]);
1438#ifdef WITH_HORIZONTAL_BARS_LIST
1440 texts = (
char **) PIC(contentBars->
barTexts);
1441 if ((context.type == CONTENT_USE_CASE) && (context.content.title != NULL)) {
1442 contentPage->text = PIC(context.content.title);
1443 contentPage->subText = PIC(texts[elemIdx]);
1445 else if ((context.type == GENERIC_SETTINGS) && (context.home.appName != NULL)) {
1446 contentPage->text = PIC(context.home.appName);
1447 contentPage->subText = PIC(texts[elemIdx]);
1450 contentPage->text = PIC(texts[elemIdx]);
1462 PageContent_t contentPage = {0};
1464 context.stepCallback = NULL;
1466 if (context.currentPage < (context.nbPages - 1)) {
1467 getContentPage(toogle_state, &contentPage);
1470 contentPage.icon = &C_icon_back_x;
1471 contentPage.text =
"Back";
1472 if (context.type == GENERIC_SETTINGS) {
1473 context.stepCallback = context.home.quitCallback;
1476 context.stepCallback = startUseCaseHome;
1480 if (contentPage.isSwitch) {
1482 pos, contentPage.text, contentPage.subText, contentPage.state, settingsCallback,
false);
1488 contentPage.subText,
1497static void startUseCaseHome(
void)
1499 switch (context.type) {
1500 case SETTINGS_USE_CASE:
1502 context.currentPage = 1;
1503 if (context.home.homeAction) {
1505 context.currentPage++;
1510 context.currentPage = 1;
1511 if (context.home.homeAction) {
1513 context.currentPage++;
1515 if (context.home.settingContents) {
1517 context.currentPage++;
1522 context.currentPage = 0;
1526 context.type = HOME_USE_CASE;
1527 context.nbPages = 2;
1528 if (context.home.settingContents) {
1531 if (context.home.infosList) {
1534 if (context.home.homeAction) {
1540static void startUseCaseInfo(
void)
1542 context.type = INFO_USE_CASE;
1543 context.nbPages = context.home.infosList->nbInfos + 1;
1544 context.currentPage = 0;
1549static void startUseCaseSettingsAtPage(uint8_t initSettingPage)
1555 if (context.type != GENERIC_SETTINGS) {
1556 context.
type = SETTINGS_USE_CASE;
1559 context.nbPages = 1;
1560 for (
int i = 0; i < context.home.settingContents->nbContents; i++) {
1561 p_content = getContentAtIdx(context.home.settingContents, i, &content);
1562 context.nbPages += getContentNbElement(p_content);
1564 context.currentPage = initSettingPage;
1569static void startUseCaseSettings(
void)
1571 startUseCaseSettingsAtPage(0);
1574static void startUseCaseContent(
void)
1576 uint8_t contentIdx = 0;
1580 context.nbPages = 1;
1582 for (contentIdx = 0; contentIdx < context.content.genericContents.nbContents; contentIdx++) {
1583 p_content = getContentAtIdx(&context.content.genericContents, contentIdx, &content);
1584 context.nbPages += getContentNbElement(p_content);
1588 if (context.currentPage >= context.nbPages) {
1598 const char *text = NULL;
1599 const char *subText = NULL;
1601 uint8_t currentIndex = 0;
1602 uint8_t homeIndex = 255;
1603 uint8_t actionIndex = 255;
1604 uint8_t settingsIndex = 255;
1605 uint8_t infoIndex = 255;
1607 context.stepCallback = NULL;
1610 homeIndex = currentIndex++;
1611 if (context.home.homeAction) {
1612 actionIndex = currentIndex++;
1614 if (context.home.settingContents) {
1615 settingsIndex = currentIndex++;
1617 if (context.home.infosList) {
1618 infoIndex = currentIndex++;
1621 if (context.currentPage == homeIndex) {
1623 icon = context.home.appIcon;
1624 if (context.home.tagline != NULL) {
1625 text = context.home.tagline;
1628 text = context.home.appName;
1629 subText =
"app is ready";
1632 else if (context.currentPage == actionIndex) {
1634 icon = context.home.homeAction->icon;
1635 text = PIC(context.home.homeAction->text);
1636 context.stepCallback = context.home.homeAction->callback;
1638 else if (context.currentPage == settingsIndex) {
1640 icon = &C_icon_coggle;
1641 text =
"App settings";
1642 context.stepCallback = startUseCaseSettings;
1644 else if (context.currentPage == infoIndex) {
1646 icon = &C_Information_circle_14px;
1648 context.stepCallback = startUseCaseInfo;
1651 icon = &C_Quit_14px;
1653 context.stepCallback = context.home.quitCallback;
1656 drawStep(pos, icon, text, subText, homeCallback,
false, NO_FORCED_TYPE);
1663 const char *text = NULL;
1664 const char *subText = NULL;
1667 uint8_t acceptPage = 0;
1669 if (context.choice.message != NULL) {
1670 if ((context.choice.icon == NULL) || (context.choice.subMessage == NULL)) {
1677 context.stepCallback = NULL;
1679 if (context.currentPage < acceptPage) {
1680 if (context.currentPage == 0) {
1681 text = context.choice.message;
1682 if (context.choice.icon != NULL) {
1683 icon = context.choice.icon;
1686 subText = context.choice.subMessage;
1689 else if ((acceptPage == 2) && (context.currentPage == 1)) {
1691 text = context.choice.message;
1692 subText = context.choice.subMessage;
1695 else if (context.currentPage == acceptPage) {
1696 icon = &C_icon_validate_14;
1697 text = context.choice.confirmText;
1698 context.stepCallback = onChoiceAccept;
1700 else if (context.currentPage == (acceptPage + 1)) {
1701 icon = &C_icon_crossmark;
1702 text = context.choice.cancelText;
1703 context.stepCallback = onChoiceReject;
1705 else if (context.choice.details != NULL) {
1708 text = context.choice.details->barList.texts[context.currentPage - (acceptPage + 2)];
1710 = context.choice.details->barList.subTexts[context.currentPage - (acceptPage + 2)];
1714 drawStep(pos, icon, text, subText, genericChoiceCallback,
false, NO_FORCED_TYPE);
1721 const char *text = NULL;
1722 const char *subText = NULL;
1725 context.stepCallback = NULL;
1726 switch (context.currentPage) {
1729 text = context.confirm.message;
1730 subText = context.confirm.subMessage;
1734 icon = &C_icon_validate_14;
1735 text = context.confirm.confirmText;
1736 context.stepCallback = onConfirmAccept;
1740 icon = &C_icon_crossmark;
1741 text = context.confirm.cancelText;
1742 context.stepCallback = onConfirmReject;
1746 drawStep(pos, icon, text, subText, genericConfirmCallback,
true, NO_FORCED_TYPE);
1753 PageContent_t contentPage = {0};
1754 ForcedType_t forcedType = NO_FORCED_TYPE;
1756 context.stepCallback = NULL;
1758 if (context.currentPage < (context.nbPages - 1)) {
1759 getContentPage(toogle_state, &contentPage);
1760 if (contentPage.isCenteredInfo) {
1761 forcedType = FORCE_CENTERED_INFO;
1763 context.forceAction = contentPage.isAction;
1766 if (context.content.rejectText) {
1767 contentPage.text = context.content.rejectText;
1770 contentPage.text =
"Back";
1772 if (context.type == GENERIC_REVIEW_USE_CASE) {
1773 contentPage.icon = &C_icon_crossmark;
1776 contentPage.icon = &C_icon_back_x;
1778 context.stepCallback = context.content.quitCallback;
1781 if (contentPage.isSwitch) {
1783 pos, contentPage.text, contentPage.subText, contentPage.state, contentCallback,
false);
1789 contentPage.subText,
1794 context.forceAction =
false;
1798static void displaySpinner(
const char *text)
1800 drawStep(
SINGLE_STEP, &C_icon_processing, text, NULL, NULL,
false,
false);
1805static void useCaseReview(ContextType_t type,
1809 const char *reviewTitle,
1810 const char *reviewSubTitle,
1811 const char *finishTitle,
1814 memset(&context, 0,
sizeof(UseCaseContext_t));
1815 context.type = type;
1816 context.operationType = operationType;
1817 context.review.tagValueList = tagValueList;
1818 context.review.reviewTitle = reviewTitle;
1819 context.review.reviewSubTitle = reviewSubTitle;
1820 context.review.finishTitle = finishTitle;
1821 context.review.icon = icon;
1822 context.review.onChoice = choiceCallback;
1823 context.currentPage = 0;
1825 context.nbPages = tagValueList->
nbPairs + 3;
1826 if (reviewSubTitle) {
1834static void setPinCodeText(
void)
1836 bool enableValidate =
false;
1837 bool enableBackspace =
true;
1840 enableValidate = (context.keypad.pinLen >= context.keypad.pinMinDigits);
1842 enableBackspace = (context.keypad.pinLen > 0) || (context.keypad.backCallback != NULL);
1844 context.keypad.hidden,
1845 context.keypad.pinLen,
1846 (
const char *) context.keypad.pinEntry);
1848 context.keypad.layoutCtx, context.keypad.keypadIndex, enableValidate, enableBackspace);
1854static void keypadCallback(
char touchedKey)
1856 switch (touchedKey) {
1858 if (context.keypad.pinLen > 0) {
1859 context.keypad.pinLen--;
1860 context.keypad.pinEntry[context.keypad.pinLen] = 0;
1862 else if (context.keypad.backCallback != NULL) {
1863 context.keypad.backCallback();
1870 context.keypad.validatePin(context.keypad.pinEntry, context.keypad.pinLen);
1874 if ((touchedKey >= 0x30) && (touchedKey < 0x40)) {
1875 if (context.keypad.pinLen < context.keypad.pinMaxDigits) {
1876 context.keypad.pinEntry[context.keypad.pinLen] = touchedKey;
1877 context.keypad.pinLen++;
1887static void launchReviewAfterWarning(
void)
1889 if (reviewWithWarnCtx.type == REVIEW_USE_CASE) {
1890 useCaseReview(reviewWithWarnCtx.type,
1891 reviewWithWarnCtx.operationType,
1892 reviewWithWarnCtx.tagValueList,
1893 reviewWithWarnCtx.icon,
1894 reviewWithWarnCtx.reviewTitle,
1895 reviewWithWarnCtx.reviewSubTitle,
1896 reviewWithWarnCtx.finishTitle,
1897 reviewWithWarnCtx.choiceCallback);
1899 else if (reviewWithWarnCtx.type == STREAMING_START_REVIEW_USE_CASE) {
1911 if (reviewWithWarnCtx.warningPage > 0) {
1912 reviewWithWarnCtx.warningPage--;
1917 if (reviewWithWarnCtx.warningPage < (reviewWithWarnCtx.nbWarningPages - 1)) {
1918 reviewWithWarnCtx.warningPage++;
1920 else if ((reviewWithWarnCtx.warning->predefinedSet == 0)
1921 && (reviewWithWarnCtx.warning->info != NULL)) {
1922 launchReviewAfterWarning();
1929 if (reviewWithWarnCtx.warningPage == reviewWithWarnCtx.firstWarningPage) {
1930 launchReviewAfterWarning();
1933 else if (reviewWithWarnCtx.warningPage == (reviewWithWarnCtx.nbWarningPages - 1)) {
1934 reviewWithWarnCtx.choiceCallback(
false);
1941 displayWarningStep();
1945static void displayWarningStep(
void)
1949 if ((reviewWithWarnCtx.warning->prelude) && (reviewWithWarnCtx.warningPage == 0)) {
1954 reviewWithWarnCtx.warning->prelude->title,
1955 reviewWithWarnCtx.warning->prelude->description,
1962 if (reviewWithWarnCtx.warningPage == reviewWithWarnCtx.firstWarningPage) {
1964 info.
icon = &C_icon_warning;
1965 info.
text1 =
"Blind signing ahead";
1966 info.
text2 =
"To accept risk, press both buttons";
1967 pos = (reviewWithWarnCtx.firstWarningPage == 0) ?
FIRST_STEP
1971 else if (reviewWithWarnCtx.warningPage == (reviewWithWarnCtx.nbWarningPages - 1)) {
1972 getLastPageInfo(
false, &info.
icon, &info.
text1);
1976 else if ((reviewWithWarnCtx.warning->predefinedSet == 0)
1977 && (reviewWithWarnCtx.warning->info != NULL)) {
1978 if (reviewWithWarnCtx.warningPage == reviewWithWarnCtx.firstWarningPage) {
1979 info.
icon = reviewWithWarnCtx.warning->info->icon;
1980 info.
text1 = reviewWithWarnCtx.warning->info->title;
1981 info.
text2 = reviewWithWarnCtx.warning->info->description;
1982 pos = (reviewWithWarnCtx.firstWarningPage == 0) ?
FIRST_STEP
1986 else if (reviewWithWarnCtx.warningPage == (reviewWithWarnCtx.nbWarningPages - 1)) {
1988 info.
icon = reviewWithWarnCtx.warning->introDetails->centeredInfo.icon;
1989 info.
text1 = reviewWithWarnCtx.warning->introDetails->centeredInfo.title;
1990 info.
text2 = reviewWithWarnCtx.warning->introDetails->centeredInfo.description;
2003 info.
style = BOLD_TEXT1_INFO;
2009static void displayInitialWarning(
void)
2012 reviewWithWarnCtx.warningPage = 0;
2014 || ((reviewWithWarnCtx.warning->introDetails)
2016 reviewWithWarnCtx.nbWarningPages = 2;
2020 reviewWithWarnCtx.nbWarningPages = 1;
2023 reviewWithWarnCtx.firstWarningPage = 0;
2024 displayWarningStep();
2028static void displayPrelude(
void)
2031 reviewWithWarnCtx.warningPage = 0;
2033 || ((reviewWithWarnCtx.warning->introDetails)
2035 reviewWithWarnCtx.nbWarningPages = 3;
2039 reviewWithWarnCtx.nbWarningPages = 2;
2041 reviewWithWarnCtx.firstWarningPage = 1;
2042 displayWarningStep();
2063 bool *requireSpecificDisplay)
2066 UNUSED(tagValueList);
2068 *requireSpecificDisplay =
true;
2088 bool *requireSpecificDisplay)
2091 UNUSED(tagValueList);
2093 UNUSED(isSkippable);
2094 *requireSpecificDisplay =
true;
2132 UNUSED(switchesList);
2172 UNUSED(choicesList);
2186 uint8_t nbPages = 0;
2187 uint8_t nbPairs = tagValueList->
nbPairs;
2188 uint8_t nbPairsInPage;
2192 while (i < tagValueList->nbPairs) {
2196 nbPairs -= nbPairsInPage;
2222 memset(&context, 0,
sizeof(UseCaseContext_t));
2223 context.type = CONTENT_USE_CASE;
2224 context.currentPage = initPage;
2225 context.content.title = title;
2226 context.content.quitCallback = quitCallback;
2227 context.content.navCallback = navCallback;
2228 context.content.controlsCallback = controlsCallback;
2229 context.content.genericContents.callbackCallNeeded =
true;
2230 context.content.genericContents.nbContents = nbPages;
2232 startUseCaseContent();
2251 const char *tagline,
2252 const uint8_t initSettingPage,
2258 memset(&context, 0,
sizeof(UseCaseContext_t));
2259 context.home.appName = appName;
2260 context.home.appIcon = appIcon;
2261 context.home.tagline = tagline;
2262 context.home.settingContents = PIC(settingContents);
2263 context.home.infosList = PIC(infosList);
2264 context.home.homeAction = action;
2265 context.home.quitCallback = quitCallback;
2267 if ((initSettingPage !=
INIT_HOME_PAGE) && (settingContents != NULL)) {
2268 startUseCaseSettingsAtPage(initSettingPage);
2293 memset(&context, 0,
sizeof(UseCaseContext_t));
2294 context.type = GENERIC_SETTINGS;
2295 context.home.appName = appName;
2296 context.home.settingContents = PIC(settingContents);
2297 context.home.infosList = PIC(infosList);
2298 context.home.quitCallback = quitCallback;
2300 startUseCaseSettingsAtPage(initPage);
2339 const char *reviewTitle,
2340 const char *reviewSubTitle,
2341 const char *finishTitle,
2344 useCaseReview(REVIEW_USE_CASE,
2379 const char *reviewTitle,
2380 const char *reviewSubTitle,
2381 const char *finishTitle,
2387 ContextType_t type = REVIEW_USE_CASE;
2390 if ((warning == NULL)
2404 operationType |= NO_THREAT_OPERATION;
2407 operationType |= RISKY_OPERATION;
2410 memset(&reviewWithWarnCtx, 0,
sizeof(reviewWithWarnCtx));
2411 reviewWithWarnCtx.type = type;
2412 reviewWithWarnCtx.operationType = operationType;
2413 reviewWithWarnCtx.tagValueList = tagValueList;
2414 reviewWithWarnCtx.icon = icon;
2415 reviewWithWarnCtx.reviewTitle = reviewTitle;
2416 reviewWithWarnCtx.reviewSubTitle = reviewSubTitle;
2417 reviewWithWarnCtx.finishTitle = finishTitle;
2418 reviewWithWarnCtx.warning = warning;
2419 reviewWithWarnCtx.choiceCallback = choiceCallback;
2422 if (reviewWithWarnCtx.warning->prelude) {
2427 displayInitialWarning();
2463 const char *reviewTitle,
2464 const char *reviewSubTitle,
2465 const char *finishTitle,
2476 &blindSigningWarning,
2497 const char *reviewTitle,
2498 const char *reviewSubTitle,
2499 const char *finishTitle,
2530 const char *reviewTitle,
2531 const char *reviewSubTitle,
2534 memset(&context, 0,
sizeof(UseCaseContext_t));
2535 context.type = ADDRESS_REVIEW_USE_CASE;
2536 context.review.address = address;
2537 context.review.reviewTitle = reviewTitle;
2538 context.review.reviewSubTitle = reviewSubTitle;
2539 context.review.icon = icon;
2540 context.review.onChoice = choiceCallback;
2541 context.currentPage = 0;
2544 context.nbPages = reviewSubTitle ? 5 : 4;
2545 if (additionalTagValueList) {
2546 context.review.tagValueList = PIC(additionalTagValueList);
2547 context.nbPages += additionalTagValueList->
nbPairs;
2562 const char *rejectText,
2565 memset(&context, 0,
sizeof(UseCaseContext_t));
2566 context.type = GENERIC_REVIEW_USE_CASE;
2567 context.content.rejectText = rejectText;
2568 context.content.quitCallback = rejectCallback;
2569 context.content.genericContents.nbContents = contents->
nbContents;
2575 context.content.genericContents.contentsList = PIC(contents->
contentsList);
2578 startUseCaseContent();
2592 memset(&context, 0,
sizeof(UseCaseContext_t));
2593 context.type = STATUS_USE_CASE;
2594 context.stepCallback = quitCallback;
2595 context.currentPage = 0;
2596 context.nbPages = 1;
2602 statusButtonCallback,
2618 switch (reviewStatusType) {
2620 msg =
"Operation signed";
2624 msg =
"Operation rejected";
2628 msg =
"Transaction signed";
2632 msg =
"Transaction rejected";
2636 msg =
"Message signed";
2640 msg =
"Message rejected";
2644 msg =
"Address verified";
2648 msg =
"Address verification cancelled";
2671 const char *reviewTitle,
2672 const char *reviewSubTitle,
2676 streamingOpType = operationType;
2678 memset(&context, 0,
sizeof(UseCaseContext_t));
2679 context.type = STREAMING_START_REVIEW_USE_CASE;
2680 context.operationType = operationType;
2681 context.review.reviewTitle = reviewTitle;
2682 context.review.reviewSubTitle = reviewSubTitle;
2683 context.review.icon = icon;
2684 context.review.onChoice = choiceCallback;
2685 context.currentPage = 0;
2686 context.nbPages = reviewSubTitle ? 3 : 2;
2706 const char *reviewTitle,
2707 const char *reviewSubTitle,
2711 operationType, icon, reviewTitle, reviewSubTitle, &blindSigningWarning, choiceCallback);
2731 const char *reviewTitle,
2732 const char *reviewSubTitle,
2736 memset(&context, 0,
sizeof(UseCaseContext_t));
2737 context.type = STREAMING_START_REVIEW_USE_CASE;
2738 context.operationType = operationType;
2739 context.review.reviewTitle = reviewTitle;
2740 context.review.reviewSubTitle = reviewSubTitle;
2741 context.review.icon = icon;
2742 context.review.onChoice = choiceCallback;
2743 context.currentPage = 0;
2744 context.nbPages = reviewSubTitle ? 3 : 2;
2747 streamingOpType = operationType;
2750 if ((warning == NULL)
2757 operationType |= NO_THREAT_OPERATION;
2760 operationType |= RISKY_OPERATION;
2762 memset(&reviewWithWarnCtx, 0,
sizeof(reviewWithWarnCtx));
2764 reviewWithWarnCtx.type = context.type;
2765 reviewWithWarnCtx.operationType = operationType;
2766 reviewWithWarnCtx.icon = icon;
2767 reviewWithWarnCtx.reviewTitle = reviewTitle;
2768 reviewWithWarnCtx.reviewSubTitle = reviewSubTitle;
2769 reviewWithWarnCtx.choiceCallback = choiceCallback;
2770 reviewWithWarnCtx.warning = warning;
2773 if (reviewWithWarnCtx.warning->prelude) {
2778 displayInitialWarning();
2802 uint8_t curNbDataSets = context.review.nbDataSets;
2804 memset(&context, 0,
sizeof(UseCaseContext_t));
2805 context.type = STREAMING_CONTINUE_REVIEW_USE_CASE;
2806 context.operationType = streamingOpType;
2807 context.review.tagValueList = tagValueList;
2808 context.review.onChoice = choiceCallback;
2809 context.currentPage = 0;
2810 context.nbPages = tagValueList->
nbPairs + 1;
2811 context.review.skipCallback = skipCallback;
2812 context.review.nbDataSets = curNbDataSets + 1;
2836 memset(&context, 0,
sizeof(UseCaseContext_t));
2837 context.type = STREAMING_FINISH_REVIEW_USE_CASE;
2838 context.operationType = streamingOpType;
2839 context.review.onChoice = choiceCallback;
2840 context.review.finishTitle = finishTitle;
2841 context.currentPage = 0;
2842 context.nbPages = 2;
2854 memset(&context, 0,
sizeof(UseCaseContext_t));
2855 context.type = SPINNER_USE_CASE;
2856 context.currentPage = 0;
2857 context.nbPages = 1;
2859 displaySpinner(text);
2875 const char *message,
2876 const char *subMessage,
2877 const char *confirmText,
2878 const char *cancelText,
2882 icon, message, subMessage, confirmText, cancelText, NULL, callback);
2900 const char *message,
2901 const char *subMessage,
2902 const char *confirmText,
2903 const char *cancelText,
2907 memset(&context, 0,
sizeof(UseCaseContext_t));
2908 context.type = CHOICE_USE_CASE;
2909 context.choice.icon = icon;
2910 context.choice.message = message;
2911 context.choice.subMessage = subMessage;
2912 context.choice.confirmText = confirmText;
2913 context.choice.cancelText = cancelText;
2914 context.choice.onChoice = callback;
2915 context.choice.details = details;
2916 context.currentPage = 0;
2917 context.nbPages = 2;
2918 if (message != NULL) {
2921 if ((icon != NULL) && (subMessage != NULL)) {
2925 if (details != NULL) {
2949 const char *subMessage,
2950 const char *confirmText,
2951 const char *cancelText,
2954 memset(&context, 0,
sizeof(UseCaseContext_t));
2955 context.type = CONFIRM_USE_CASE;
2956 context.confirm.message = message;
2957 context.confirm.subMessage = subMessage;
2958 context.confirm.confirmText = confirmText;
2959 context.confirm.cancelText = cancelText;
2960 context.confirm.onConfirm = callback;
2961 context.currentPage = 0;
2962 context.nbPages = 1 + 2;
2977 const char *message,
2978 const char *actionText,
2986 memset(&context, 0,
sizeof(UseCaseContext_t));
2987 context.type = ACTION_USE_CASE;
2988 context.action.actionCallback = callback;
2990 centeredInfo.
icon = icon;
2991 centeredInfo.
text1 = message;
2992 centeredInfo.
style = BOLD_TEXT1_INFO;
3027 memset(&context, 0,
sizeof(KeypadContext_t));
3028 context.type = KEYPAD_USE_CASE;
3029 context.currentPage = 0;
3030 context.nbPages = 1;
3031 context.keypad.validatePin = validatePinCallback;
3032 context.keypad.backCallback = backCallback;
3033 context.keypad.pinMinDigits = minDigits;
3034 context.keypad.pinMaxDigits = maxDigits;
3035 context.keypad.hidden = hidden;
3043 context.keypad.keypadIndex = status;
3051 if (context.keypad.backCallback != NULL) {
nbgl_contentCenteredInfoStyle_t
possible styles for Centered Info Area
@ 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
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,...)
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_layoutUpdateKeypad(nbgl_layout_t *layout, uint8_t index, bool enableValidate, bool enableBackspace, bool enableDigits)
Updates an existing keypad on bottom of the screen, with the given configuration.
int nbgl_layoutDraw(nbgl_layout_t *layout)
Applies given layout. The screen will be redrawn.
void * nbgl_layout_t
type shared externally
int nbgl_layoutAddKeypadContent(nbgl_layout_t *layout, const char *title, 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_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, bool shuffled)
Adds a keypad on bottom of the screen, with the associated callback.
@ 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)
void * nbgl_step_t
type shared externally
uint8_t nbgl_stepPosition_t
this type is a bitfield containing:
nbgl_step_t nbgl_stepDrawMenuList(nbgl_stepMenuListCallback_t onActionCallback, nbgl_screenTickerConfiguration_t *ticker, nbgl_layoutMenuList_t *list, bool modal)
#define ACTION_ON_ANY_BUTTON
When action callback applies only on both button press.
@ 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
int nbgl_stepRelease(nbgl_step_t step)
#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)
nbgl_step_t nbgl_stepDrawCenteredInfo(nbgl_stepPosition_t pos, nbgl_stepButtonCallback_t onActionCallback, nbgl_screenTickerConfiguration_t *ticker, nbgl_layoutCenteredInfo_t *info, bool modal)
#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.
@ 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.
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)
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)
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_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_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)
#define REAL_TYPE_MASK
This is the mask to apply on nbgl_operationType_t to get the real type provided by app.
void nbgl_useCaseReviewStatus(nbgl_reviewStatusType_t reviewStatusType, nbgl_callback_t quitCallback)
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)
uint8_t nbBars
number of elements in barTexts and tokens array
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)
bool onTop
if set to true, align only horizontally
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)
uint8_t nbChoices
number of choices
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
int8_t centeredInfo
if set to 1, the tag will be displayed as a centered info
const char * value
string giving the value name
const char * item
string giving the tag name
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
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
Structure describing the action button in Home Screen.
Structure containing all information when creating a layout. This structure must be passed as argumen...
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