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;
150 ReviewContext_t review;
151 ChoiceContext_t choice;
152 ConfirmContext_t confirm;
154 ContentContext_t content;
156 KeypadContext_t keypad;
158 ActionContext_t action;
162typedef struct PageContent_s {
172typedef struct ReviewWithWarningContext_s {
177 const char *reviewTitle;
178 const char *reviewSubTitle;
179 const char *finishTitle;
182 uint8_t securityReportLevel;
185 uint8_t nbWarningPages;
186 uint8_t firstWarningPage;
187} ReviewWithWarningContext_t;
198static UseCaseContext_t context;
200static ReviewWithWarningContext_t reviewWithWarnCtx;
218static void displaySpinner(
const char *text);
220static void startUseCaseHome(
void);
221static void startUseCaseInfo(
void);
222static void startUseCaseSettings(
void);
223static void startUseCaseSettingsAtPage(uint8_t initSettingPage);
224static void startUseCaseContent(
void);
226static void statusTickerCallback(
void);
229static void displayWarningStep(
void);
234 switch (content->
type) {
261 if (contentIdx < 0 || contentIdx >= genericContents->
nbContents) {
267 if (content == NULL) {
273 if (context.content.navCallback) {
274 if (context.content.navCallback(contentIdx, &pageContent) ==
true) {
277 switch (content->
type) {
323 uint8_t *elemContentIdx,
329 uint8_t elemNbPages = 0;
331 switch (context.type) {
332 case SETTINGS_USE_CASE:
334 case GENERIC_SETTINGS:
335 genericContents = context.home.settingContents;
337 case CONTENT_USE_CASE:
338 case GENERIC_REVIEW_USE_CASE:
339 genericContents = &context.content.genericContents;
344 for (
int i = 0; i < genericContents->
nbContents; i++) {
345 p_content = getContentAtIdx(genericContents, i, content);
346 elemNbPages = getContentNbElement(p_content);
347 if (nbPages + elemNbPages > elemIdx) {
348 *elemContentIdx = context.currentPage - nbPages;
351 nbPages += elemNbPages;
357static const char *getChoiceName(uint8_t choiceIndex)
367 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
368 if (p_content == NULL) {
371 switch (p_content->
type) {
374 names = (
char **) PIC(contentChoices->
names);
379 names = (
char **) PIC(contentBars->
barTexts);
380 nbValues = contentBars->
nbBars;
386 if (choiceIndex >= nbValues) {
390 return (
const char *) PIC(names[choiceIndex]);
393static void onChoiceSelected(uint8_t choiceIndex)
402 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
403 if (p_content == NULL) {
406 switch (p_content->
type) {
409 if (choiceIndex < contentChoices->nbChoices) {
410 token = contentChoices->
token;
415 if (choiceIndex < contentBars->nbBars) {
416 token = contentBars->
tokens[choiceIndex];
423 if ((token != 255) && (context.content.controlsCallback != NULL)) {
424 context.content.controlsCallback(token, 0);
426 else if (context.content.quitCallback != NULL) {
427 context.content.quitCallback();
437 bool *isCenteredInfo)
441 if (tagValueList->
pairs != NULL) {
442 pair = PIC(&tagValueList->
pairs[index]);
445 pair = PIC(tagValueList->
callback(index));
448 *value = pair->
value;
453 *isCenteredInfo =
true;
461static void onReviewAccept(
void)
463 if (context.review.onChoice) {
464 context.review.onChoice(
true);
468static void onReviewReject(
void)
470 if (context.review.onChoice) {
471 context.review.onChoice(
false);
475static void onChoiceAccept(
void)
477 if (context.choice.onChoice) {
478 context.choice.onChoice(
true);
482static void onChoiceReject(
void)
484 if (context.choice.onChoice) {
485 context.choice.onChoice(
false);
489static void onConfirmAccept(
void)
491 if (context.confirm.currentStep) {
494 if (context.confirm.onConfirm) {
495 context.confirm.onConfirm();
499static void onConfirmReject(
void)
501 if (context.confirm.currentStep) {
508static void onSwitchAction(
void)
515 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
521 switch (context.type) {
522 case SETTINGS_USE_CASE:
524 case GENERIC_SETTINGS:
527 case CONTENT_USE_CASE:
528 case GENERIC_REVIEW_USE_CASE:
536 actionCallback(contentSwitch->
token,
538 context.currentPage);
540 else if (context.content.controlsCallback != NULL) {
541 context.content.controlsCallback(contentSwitch->
token, 0);
551 ForcedType_t forcedType)
562 .tickerIntervale = 0,
568 if ((context.type == STREAMING_CONTINUE_REVIEW_USE_CASE)
569 && (context.review.skipCallback != NULL) && (context.review.nbDataSets > 1)) {
572 if ((context.type == STATUS_USE_CASE) || (context.type == SPINNER_USE_CASE)) {
575 if ((context.type == CONFIRM_USE_CASE) && (context.confirm.currentStep != NULL)) {
580 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
582 switch (p_content->
type) {
604 else if ((icon == NULL) && (forcedType != FORCE_CENTERED_INFO)) {
606 if (subTxt != NULL) {
607 style = (forcedType == FORCE_BUTTON) ? BUTTON_INFO : BOLD_TEXT1_INFO;
610 style = REGULAR_INFO;
612 newStep =
nbgl_stepDrawText(pos, onActionCallback, p_ticker, txt, subTxt, style, modal);
620 if ((subTxt != NULL) || (context.stepCallback != NULL)) {
621 info.
style = BOLD_TEXT1_INFO;
624 info.
style = REGULAR_INFO;
628 if (context.type == CONFIRM_USE_CASE) {
629 context.confirm.currentStep = newStep;
635 const char *description,
644 switchInfo.
text = title;
645 switchInfo.
subText = description;
658 if (context.currentPage > 0) {
659 context.currentPage--;
663 else if ((context.type != STREAMING_CONTINUE_REVIEW_USE_CASE)
664 || (context.review.skipCallback == NULL) || (context.review.nbDataSets == 1)) {
671 if (context.currentPage < (
int) (context.nbPages - 1)) {
672 context.currentPage++;
682 if (context.stepCallback != NULL) {
683 context.stepCallback();
685 else if ((context.type == CONTENT_USE_CASE) || (context.type == SETTINGS_USE_CASE)
686 || (context.type == GENERIC_SETTINGS)
687 || (context.type == GENERIC_REVIEW_USE_CASE)) {
688 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
689 if (p_content != NULL) {
690 switch (p_content->
type) {
705 index = context.currentPage;
714 else if (context.content.controlsCallback != NULL) {
715 context.content.controlsCallback(token, index);
730 if (!buttonGenericCallback(event, &pos)) {
735 context.review.dataDirection = pos;
737 displayReviewPage(pos);
749 && (context.currentPage > context.firstPairPage)) {
750 context.currentPage--;
757 && (context.currentPage < (
int) (context.nbPages - 1))
758 && (context.currentPage > context.firstPairPage)) {
759 context.currentPage++;
765 if (context.firstPairPage == 0) {
767 context.review.skipCallback();
771 context.currentPage = context.nbPages - 2;
780 if (context.firstPairPage == 0) {
781 displayStreamingReviewPage(pos);
784 displayReviewPage(pos);
794 context.action.actionCallback();
803 if (!buttonGenericCallback(event, &pos)) {
808 context.review.dataDirection = pos;
811 displayStreamingReviewPage(pos);
819 if (!buttonGenericCallback(event, &pos)) {
823 displaySettingsPage(pos,
false);
831 if (!buttonGenericCallback(event, &pos)) {
835 displayInfoPage(pos);
843 if (!buttonGenericCallback(event, &pos)) {
847 displayHomePage(pos);
855 if (!buttonGenericCallback(event, &pos)) {
859 displayChoicePage(pos);
867 if (!buttonGenericCallback(event, &pos)) {
880 if (context.stepCallback != NULL) {
881 context.stepCallback();
891 if (!buttonGenericCallback(event, &pos)) {
895 displayContent(pos,
false);
899static void statusTickerCallback(
void)
901 if (context.stepCallback != NULL) {
902 context.stepCallback();
914 if (context.review.currentExtensionPage > 0) {
915 context.review.currentExtensionPage--;
921 if (context.review.currentExtensionPage < (context.review.nbExtensionPages - 1)) {
922 context.review.currentExtensionPage++;
928 if (context.review.currentExtensionPage == (context.review.nbExtensionPages - 1)) {
938 displayExtensionStep(pos);
947 const char *text = NULL;
948 const char *subText = NULL;
950 if (context.review.extensionStepCtx != NULL) {
953 if (context.review.currentExtensionPage < (context.review.nbExtensionPages - 1)) {
954 if (context.review.currentExtensionPage == 0) {
961 switch (context.review.extension->aliasType) {
963 text = context.review.extension->title;
964 subText = context.review.extension->fullValue;
967 infoList = context.review.extension->infolist;
968 text = PIC(infoList->
infoTypes[context.review.currentExtensionPage]);
969 subText = PIC(infoList->
infoContents[context.review.currentExtensionPage]);
972 tagValueList = context.review.extension->tagValuelist;
973 text = PIC(tagValueList->
pairs[context.review.currentExtensionPage].
item);
974 subText = PIC(tagValueList->
pairs[context.review.currentExtensionPage].
value);
981 pos, extensionNavigate, NULL, text, subText, BOLD_TEXT1_INFO,
true);
984 else if (context.review.currentExtensionPage == (context.review.nbExtensionPages - 1)) {
986 info.
icon = &C_icon_back_x;
988 info.
style = BOLD_TEXT1_INFO;
990 context.review.extensionStepCtx
996static void displayAliasFullValue(
void)
998 const char *text = NULL;
999 const char *subText = NULL;
1001 bool isCenteredInfo;
1003 getPairData(context.review.tagValueList,
1004 context.review.currentTagValueIndex,
1007 &context.review.extension,
1010 if (context.review.extension == NULL) {
1013 "displayAliasFullValue: extension nor found for pair %d\n",
1014 context.review.currentTagValueIndex);
1017 context.review.currentExtensionPage = 0;
1018 context.review.extensionStepCtx = NULL;
1020 switch (context.review.extension->aliasType) {
1022 context.review.nbExtensionPages = 2;
1025 context.review.nbExtensionPages = context.review.extension->infolist->nbInfos + 1;
1028 context.review.nbExtensionPages = context.review.extension->tagValuelist->nbPairs + 1;
1032 "displayAliasFullValue: unsupported alias type %d\n",
1033 context.review.extension->aliasType);
1039static void getLastPageInfo(
bool approve,
const nbgl_icon_details_t **icon,
const char **text)
1043 *icon = &C_icon_validate_14;
1044 if (context.type == ADDRESS_REVIEW_USE_CASE) {
1049 if (context.review.finishTitle != NULL) {
1050 *text = context.review.finishTitle;
1055 if (context.operationType & RISKY_OPERATION) {
1056 *text =
"Accept risk and sign transaction";
1059 *text =
"Sign transaction";
1063 if (context.operationType & RISKY_OPERATION) {
1064 *text =
"Accept risk and sign message";
1067 *text =
"Sign message";
1071 if (context.operationType & RISKY_OPERATION) {
1072 *text =
"Accept risk and sign operation";
1075 *text =
"Sign operation";
1081 context.stepCallback = onReviewAccept;
1085 *icon = &C_icon_crossmark;
1086 if (context.type == ADDRESS_REVIEW_USE_CASE) {
1090 *text =
"Reject transaction";
1093 *text =
"Reject message";
1096 *text =
"Reject operation";
1098 context.stepCallback = onReviewReject;
1105 uint8_t reviewPages = 0;
1106 uint8_t finalPages = 0;
1107 uint8_t pairIndex = 0;
1108 const char *text = NULL;
1109 const char *subText = NULL;
1111 uint8_t currentIndex = 0;
1112 uint8_t titleIndex = 255;
1113 uint8_t subIndex = 255;
1114 uint8_t approveIndex = 255;
1115 uint8_t rejectIndex = 255;
1117 ForcedType_t forcedType = NO_FORCED_TYPE;
1119 context.stepCallback = NULL;
1123 titleIndex = currentIndex++;
1125 if (context.review.reviewSubTitle) {
1127 subIndex = currentIndex++;
1130 approveIndex = context.nbPages - 2;
1131 rejectIndex = context.nbPages - 1;
1132 finalPages = approveIndex;
1135 if (context.currentPage >= finalPages) {
1136 if (context.currentPage == approveIndex) {
1138 getLastPageInfo(
true, &icon, &text);
1140 else if (context.currentPage == rejectIndex) {
1142 getLastPageInfo(
false, &icon, &text);
1145 else if (context.currentPage < reviewPages) {
1146 if (context.currentPage == titleIndex) {
1148 icon = context.review.icon;
1149 text = context.review.reviewTitle;
1151 else if (context.currentPage == subIndex) {
1153 text = context.review.reviewSubTitle;
1156 else if ((context.review.address != NULL) && (context.currentPage == reviewPages)) {
1159 subText = context.review.address;
1165 if ((context.operationType &
SKIPPABLE_OPERATION) && (context.review.skipDisplay ==
false)
1166 && ((context.currentPage > reviewPages)
1170 if ((context.review.nbDataSets == 1) || (context.currentPage > 0)) {
1173 info.
icon = &C_Information_circle_14px;
1174 info.
text1 =
"Press right button to continue message or \bpress both to skip\b";
1177 context.review.skipDisplay =
true;
1178 context.firstPairPage = reviewPages;
1181 context.review.skipDisplay =
false;
1182 bool isCenteredInfo =
false;
1183 pairIndex = context.currentPage - reviewPages;
1184 if (context.review.address != NULL) {
1187 getPairData(context.review.tagValueList,
1194 if (extension != NULL) {
1195 context.stepCallback = displayAliasFullValue;
1196 context.review.currentTagValueIndex = pairIndex;
1197 forcedType = FORCE_BUTTON;
1200 if (isCenteredInfo) {
1201 forcedType = FORCE_CENTERED_INFO;
1206 drawStep(pos, icon, text, subText, reviewCallback,
false, forcedType);
1213 const char *text = NULL;
1214 const char *subText = NULL;
1216 uint8_t reviewPages = 0;
1217 uint8_t titleIndex = 255;
1218 uint8_t subIndex = 255;
1220 ForcedType_t forcedType = NO_FORCED_TYPE;
1222 context.stepCallback = NULL;
1223 switch (context.type) {
1224 case STREAMING_START_REVIEW_USE_CASE:
1226 titleIndex = reviewPages++;
1227 if (context.review.reviewSubTitle) {
1229 subIndex = reviewPages++;
1232 if (context.currentPage >= reviewPages) {
1237 if (context.currentPage == titleIndex) {
1239 icon = context.review.icon;
1240 text = context.review.reviewTitle;
1242 else if (context.currentPage == subIndex) {
1244 text = context.review.reviewSubTitle;
1248 case STREAMING_CONTINUE_REVIEW_USE_CASE:
1249 if (context.currentPage >= context.review.tagValueList->nbPairs) {
1256 if ((context.review.skipCallback != NULL) && (context.review.skipDisplay ==
false)
1257 && ((context.review.nbDataSets > 1) || (context.currentPage > 0)
1261 if ((context.review.nbDataSets == 1) || (context.currentPage > 0)) {
1264 info.
icon = &C_Information_circle_14px;
1265 info.
text1 =
"Press right button to continue message or \bpress both to skip\b";
1268 context.review.skipDisplay =
true;
1271 context.review.skipDisplay =
false;
1272 bool isCenteredInfo =
false;
1273 getPairData(context.review.tagValueList,
1274 context.currentPage,
1280 if (extension != NULL) {
1281 forcedType = FORCE_BUTTON;
1284 if (isCenteredInfo) {
1285 forcedType = FORCE_CENTERED_INFO;
1290 case STREAMING_FINISH_REVIEW_USE_CASE:
1292 if (context.currentPage == 0) {
1294 getLastPageInfo(
true, &icon, &text);
1298 getLastPageInfo(
false, &icon, &text);
1303 drawStep(pos, icon, text, subText, streamingReviewCallback,
false, forcedType);
1310 const char *text = NULL;
1311 const char *subText = NULL;
1314 context.stepCallback = NULL;
1316 if (context.currentPage < (context.nbPages - 1)) {
1318 ((
const char *
const *) PIC(context.home.infosList->infoTypes))[context.currentPage]);
1320 ((
const char *
const *) PIC(context.home.infosList->infoContents))[context.currentPage]);
1323 icon = &C_icon_back_x;
1325 context.stepCallback = startUseCaseHome;
1328 drawStep(pos, icon, text, subText, infoCallback,
false, FORCE_CENTERED_INFO);
1333static void getContentPage(
bool toogle_state, PageContent_t *contentPage)
1335 uint8_t elemIdx = 0;
1339#ifdef WITH_HORIZONTAL_CHOICES_LIST
1341 char **names = NULL;
1343#ifdef WITH_HORIZONTAL_BARS_LIST
1345 char **texts = NULL;
1347 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
1348 if (p_content == NULL) {
1351 switch (p_content->
type) {
1365 &contentPage->subText,
1366 &contentPage->extension,
1368 &contentPage->isCenteredInfo);
1371 contentPage->isSwitch =
true;
1374 contentPage->
text = contentSwitch->
text;
1375 contentPage->state = contentSwitch->
initState;
1379 context.stepCallback = onSwitchAction;
1380 contentPage->subText = contentSwitch->
subText;
1385 contentPage->subText
1389#ifdef WITH_HORIZONTAL_CHOICES_LIST
1391 names = (
char **) PIC(contentChoices->
names);
1392 if ((context.type == CONTENT_USE_CASE) && (context.content.title != NULL)) {
1393 contentPage->text = PIC(context.content.title);
1394 contentPage->subText = (
const char *) PIC(names[elemIdx]);
1396 else if ((context.type == GENERIC_SETTINGS) && (context.home.appName != NULL)) {
1397 contentPage->text = PIC(context.home.appName);
1398 contentPage->subText = (
const char *) PIC(names[elemIdx]);
1401 contentPage->text = (
const char *) PIC(names[elemIdx]);
1406#ifdef WITH_HORIZONTAL_BARS_LIST
1408 texts = (
char **) PIC(contentBars->
barTexts);
1409 if ((context.type == CONTENT_USE_CASE) && (context.content.title != NULL)) {
1410 contentPage->text = PIC(context.content.title);
1411 contentPage->subText = PIC(texts[elemIdx]);
1413 else if ((context.type == GENERIC_SETTINGS) && (context.home.appName != NULL)) {
1414 contentPage->text = PIC(context.home.appName);
1415 contentPage->subText = PIC(texts[elemIdx]);
1418 contentPage->text = PIC(texts[elemIdx]);
1430 PageContent_t contentPage = {0};
1432 context.stepCallback = NULL;
1434 if (context.currentPage < (context.nbPages - 1)) {
1435 getContentPage(toogle_state, &contentPage);
1438 contentPage.icon = &C_icon_back_x;
1439 contentPage.text =
"Back";
1440 if (context.type == GENERIC_SETTINGS) {
1441 context.stepCallback = context.home.quitCallback;
1444 context.stepCallback = startUseCaseHome;
1448 if (contentPage.isSwitch) {
1450 pos, contentPage.text, contentPage.subText, contentPage.state, settingsCallback,
false);
1456 contentPage.subText,
1465static void startUseCaseHome(
void)
1467 switch (context.type) {
1468 case SETTINGS_USE_CASE:
1470 context.currentPage = 1;
1471 if (context.home.homeAction) {
1473 context.currentPage++;
1478 context.currentPage = 1;
1479 if (context.home.homeAction) {
1481 context.currentPage++;
1483 if (context.home.settingContents) {
1485 context.currentPage++;
1490 context.currentPage = 0;
1494 context.type = HOME_USE_CASE;
1495 context.nbPages = 2;
1496 if (context.home.settingContents) {
1499 if (context.home.infosList) {
1502 if (context.home.homeAction) {
1508static void startUseCaseInfo(
void)
1510 context.type = INFO_USE_CASE;
1511 context.nbPages = context.home.infosList->nbInfos + 1;
1512 context.currentPage = 0;
1517static void startUseCaseSettingsAtPage(uint8_t initSettingPage)
1523 if (context.type != GENERIC_SETTINGS) {
1524 context.
type = SETTINGS_USE_CASE;
1527 context.nbPages = 1;
1528 for (
int i = 0; i < context.home.settingContents->nbContents; i++) {
1529 p_content = getContentAtIdx(context.home.settingContents, i, &content);
1530 context.nbPages += getContentNbElement(p_content);
1532 context.currentPage = initSettingPage;
1537static void startUseCaseSettings(
void)
1539 startUseCaseSettingsAtPage(0);
1542static void startUseCaseContent(
void)
1544 uint8_t contentIdx = 0;
1548 context.nbPages = 1;
1550 for (contentIdx = 0; contentIdx < context.content.genericContents.nbContents; contentIdx++) {
1551 p_content = getContentAtIdx(&context.content.genericContents, contentIdx, &content);
1552 context.nbPages += getContentNbElement(p_content);
1556 if (context.currentPage >= context.nbPages) {
1566 const char *text = NULL;
1567 const char *subText = NULL;
1569 uint8_t currentIndex = 0;
1570 uint8_t homeIndex = 255;
1571 uint8_t actionIndex = 255;
1572 uint8_t settingsIndex = 255;
1573 uint8_t infoIndex = 255;
1575 context.stepCallback = NULL;
1578 homeIndex = currentIndex++;
1579 if (context.home.homeAction) {
1580 actionIndex = currentIndex++;
1582 if (context.home.settingContents) {
1583 settingsIndex = currentIndex++;
1585 if (context.home.infosList) {
1586 infoIndex = currentIndex++;
1589 if (context.currentPage == homeIndex) {
1591 icon = context.home.appIcon;
1592 if (context.home.tagline != NULL) {
1593 text = context.home.tagline;
1596 text = context.home.appName;
1597 subText =
"app is ready";
1600 else if (context.currentPage == actionIndex) {
1602 icon = context.home.homeAction->icon;
1603 text = PIC(context.home.homeAction->text);
1604 context.stepCallback = context.home.homeAction->callback;
1606 else if (context.currentPage == settingsIndex) {
1608 icon = &C_icon_coggle;
1609 text =
"App settings";
1610 context.stepCallback = startUseCaseSettings;
1612 else if (context.currentPage == infoIndex) {
1614 icon = &C_Information_circle_14px;
1616 context.stepCallback = startUseCaseInfo;
1619 icon = &C_Quit_14px;
1621 context.stepCallback = context.home.quitCallback;
1624 drawStep(pos, icon, text, subText, homeCallback,
false, NO_FORCED_TYPE);
1631 const char *text = NULL;
1632 const char *subText = NULL;
1635 uint8_t acceptPage = 0;
1637 if (context.choice.message != NULL) {
1638 if ((context.choice.icon == NULL) || (context.choice.subMessage == NULL)) {
1645 context.stepCallback = NULL;
1647 if (context.currentPage < acceptPage) {
1648 if (context.currentPage == 0) {
1649 text = context.choice.message;
1650 if (context.choice.icon != NULL) {
1651 icon = context.choice.icon;
1654 subText = context.choice.subMessage;
1657 else if ((acceptPage == 2) && (context.currentPage == 1)) {
1659 text = context.choice.message;
1660 subText = context.choice.subMessage;
1663 else if (context.currentPage == acceptPage) {
1664 icon = &C_icon_validate_14;
1665 text = context.choice.confirmText;
1666 context.stepCallback = onChoiceAccept;
1668 else if (context.currentPage == (acceptPage + 1)) {
1669 icon = &C_icon_crossmark;
1670 text = context.choice.cancelText;
1671 context.stepCallback = onChoiceReject;
1673 else if (context.choice.details != NULL) {
1676 text = context.choice.details->barList.texts[context.currentPage - (acceptPage + 2)];
1678 = context.choice.details->barList.subTexts[context.currentPage - (acceptPage + 2)];
1682 drawStep(pos, icon, text, subText, genericChoiceCallback,
false, NO_FORCED_TYPE);
1689 const char *text = NULL;
1690 const char *subText = NULL;
1693 context.stepCallback = NULL;
1694 switch (context.currentPage) {
1697 text = context.confirm.message;
1698 subText = context.confirm.subMessage;
1702 icon = &C_icon_validate_14;
1703 text = context.confirm.confirmText;
1704 context.stepCallback = onConfirmAccept;
1708 icon = &C_icon_crossmark;
1709 text = context.confirm.cancelText;
1710 context.stepCallback = onConfirmReject;
1714 drawStep(pos, icon, text, subText, genericConfirmCallback,
true, NO_FORCED_TYPE);
1721 PageContent_t contentPage = {0};
1722 ForcedType_t forcedType = NO_FORCED_TYPE;
1724 context.stepCallback = NULL;
1726 if (context.currentPage < (context.nbPages - 1)) {
1727 getContentPage(toogle_state, &contentPage);
1728 if (contentPage.isCenteredInfo) {
1729 forcedType = FORCE_CENTERED_INFO;
1733 if (context.content.rejectText) {
1734 contentPage.text = context.content.rejectText;
1737 contentPage.text =
"Back";
1739 if (context.type == GENERIC_REVIEW_USE_CASE) {
1740 contentPage.icon = &C_icon_crossmark;
1743 contentPage.icon = &C_icon_back_x;
1745 context.stepCallback = context.content.quitCallback;
1748 if (contentPage.isSwitch) {
1750 pos, contentPage.text, contentPage.subText, contentPage.state, contentCallback,
false);
1756 contentPage.subText,
1765static void displaySpinner(
const char *text)
1767 drawStep(
SINGLE_STEP, &C_icon_processing, text, NULL, NULL,
false,
false);
1772static void useCaseReview(ContextType_t type,
1776 const char *reviewTitle,
1777 const char *reviewSubTitle,
1778 const char *finishTitle,
1781 memset(&context, 0,
sizeof(UseCaseContext_t));
1782 context.type = type;
1783 context.operationType = operationType;
1784 context.review.tagValueList = tagValueList;
1785 context.review.reviewTitle = reviewTitle;
1786 context.review.reviewSubTitle = reviewSubTitle;
1787 context.review.finishTitle = finishTitle;
1788 context.review.icon = icon;
1789 context.review.onChoice = choiceCallback;
1790 context.currentPage = 0;
1792 context.nbPages = tagValueList->
nbPairs + 3;
1793 if (reviewSubTitle) {
1801static void setPinCodeText(
void)
1803 bool enableValidate =
false;
1804 bool enableBackspace =
true;
1807 enableValidate = (context.keypad.pinLen >= context.keypad.pinMinDigits);
1809 enableBackspace = (context.keypad.pinLen > 0) || (context.keypad.backCallback != NULL);
1811 context.keypad.hidden,
1812 context.keypad.pinLen,
1813 (
const char *) context.keypad.pinEntry);
1815 context.keypad.layoutCtx, context.keypad.keypadIndex, enableValidate, enableBackspace);
1821static void keypadCallback(
char touchedKey)
1823 switch (touchedKey) {
1825 if (context.keypad.pinLen > 0) {
1826 context.keypad.pinLen--;
1827 context.keypad.pinEntry[context.keypad.pinLen] = 0;
1829 else if (context.keypad.backCallback != NULL) {
1830 context.keypad.backCallback();
1837 context.keypad.validatePin(context.keypad.pinEntry, context.keypad.pinLen);
1841 if ((touchedKey >= 0x30) && (touchedKey < 0x40)) {
1842 if (context.keypad.pinLen < context.keypad.pinMaxDigits) {
1843 context.keypad.pinEntry[context.keypad.pinLen] = touchedKey;
1844 context.keypad.pinLen++;
1854static void launchReviewAfterWarning(
void)
1856 if (reviewWithWarnCtx.type == REVIEW_USE_CASE) {
1857 useCaseReview(reviewWithWarnCtx.type,
1858 reviewWithWarnCtx.operationType,
1859 reviewWithWarnCtx.tagValueList,
1860 reviewWithWarnCtx.icon,
1861 reviewWithWarnCtx.reviewTitle,
1862 reviewWithWarnCtx.reviewSubTitle,
1863 reviewWithWarnCtx.finishTitle,
1864 reviewWithWarnCtx.choiceCallback);
1866 else if (reviewWithWarnCtx.type == STREAMING_START_REVIEW_USE_CASE) {
1878 if (reviewWithWarnCtx.warningPage > 0) {
1879 reviewWithWarnCtx.warningPage--;
1884 if (reviewWithWarnCtx.warningPage < (reviewWithWarnCtx.nbWarningPages - 1)) {
1885 reviewWithWarnCtx.warningPage++;
1887 else if ((reviewWithWarnCtx.warning->predefinedSet == 0)
1888 && (reviewWithWarnCtx.warning->info != NULL)) {
1889 launchReviewAfterWarning();
1896 if (reviewWithWarnCtx.warningPage == reviewWithWarnCtx.firstWarningPage) {
1897 launchReviewAfterWarning();
1900 else if (reviewWithWarnCtx.warningPage == (reviewWithWarnCtx.nbWarningPages - 1)) {
1901 reviewWithWarnCtx.choiceCallback(
false);
1908 displayWarningStep();
1912static void displayWarningStep(
void)
1916 if ((reviewWithWarnCtx.warning->prelude) && (reviewWithWarnCtx.warningPage == 0)) {
1921 reviewWithWarnCtx.warning->prelude->title,
1929 if (reviewWithWarnCtx.warningPage == reviewWithWarnCtx.firstWarningPage) {
1931 info.
icon = &C_icon_warning;
1932 info.
text1 =
"Blind signing ahead";
1933 info.
text2 =
"To accept risk, press both buttons";
1934 pos = (reviewWithWarnCtx.firstWarningPage == 0) ?
FIRST_STEP
1938 else if (reviewWithWarnCtx.warningPage == (reviewWithWarnCtx.nbWarningPages - 1)) {
1939 getLastPageInfo(
false, &info.
icon, &info.
text1);
1943 else if ((reviewWithWarnCtx.warning->predefinedSet == 0)
1944 && (reviewWithWarnCtx.warning->info != NULL)) {
1945 if (reviewWithWarnCtx.warningPage == reviewWithWarnCtx.firstWarningPage) {
1946 info.
icon = reviewWithWarnCtx.warning->info->icon;
1947 info.
text1 = reviewWithWarnCtx.warning->info->title;
1948 info.
text2 = reviewWithWarnCtx.warning->info->description;
1949 pos = (reviewWithWarnCtx.firstWarningPage == 0) ?
FIRST_STEP
1953 else if (reviewWithWarnCtx.warningPage == (reviewWithWarnCtx.nbWarningPages - 1)) {
1955 info.
icon = reviewWithWarnCtx.warning->introDetails->centeredInfo.icon;
1956 info.
text1 = reviewWithWarnCtx.warning->introDetails->centeredInfo.title;
1957 info.
text2 = reviewWithWarnCtx.warning->introDetails->centeredInfo.description;
1970 info.
style = BOLD_TEXT1_INFO;
1976static void displayInitialWarning(
void)
1979 reviewWithWarnCtx.warningPage = 0;
1980 reviewWithWarnCtx.nbWarningPages = 2;
1981 reviewWithWarnCtx.firstWarningPage = 0;
1982 displayWarningStep();
1986static void displayPrelude(
void)
1989 reviewWithWarnCtx.warningPage = 0;
1990 reviewWithWarnCtx.nbWarningPages = 3;
1991 reviewWithWarnCtx.firstWarningPage = 1;
1992 displayWarningStep();
2013 bool *requireSpecificDisplay)
2016 UNUSED(tagValueList);
2018 *requireSpecificDisplay =
true;
2038 bool *requireSpecificDisplay)
2041 UNUSED(tagValueList);
2043 UNUSED(isSkippable);
2044 *requireSpecificDisplay =
true;
2082 UNUSED(switchesList);
2122 UNUSED(choicesList);
2136 uint8_t nbPages = 0;
2137 uint8_t nbPairs = tagValueList->
nbPairs;
2138 uint8_t nbPairsInPage;
2142 while (i < tagValueList->nbPairs) {
2146 nbPairs -= nbPairsInPage;
2172 memset(&context, 0,
sizeof(UseCaseContext_t));
2173 context.type = CONTENT_USE_CASE;
2174 context.currentPage = initPage;
2175 context.content.title = title;
2176 context.content.quitCallback = quitCallback;
2177 context.content.navCallback = navCallback;
2178 context.content.controlsCallback = controlsCallback;
2179 context.content.genericContents.callbackCallNeeded =
true;
2180 context.content.genericContents.nbContents = nbPages;
2182 startUseCaseContent();
2201 const char *tagline,
2202 const uint8_t initSettingPage,
2208 memset(&context, 0,
sizeof(UseCaseContext_t));
2209 context.home.appName = appName;
2210 context.home.appIcon = appIcon;
2211 context.home.tagline = tagline;
2212 context.home.settingContents = PIC(settingContents);
2213 context.home.infosList = PIC(infosList);
2214 context.home.homeAction = action;
2215 context.home.quitCallback = quitCallback;
2217 if ((initSettingPage !=
INIT_HOME_PAGE) && (settingContents != NULL)) {
2218 startUseCaseSettingsAtPage(initSettingPage);
2243 memset(&context, 0,
sizeof(UseCaseContext_t));
2244 context.type = GENERIC_SETTINGS;
2245 context.home.appName = appName;
2246 context.home.settingContents = PIC(settingContents);
2247 context.home.infosList = PIC(infosList);
2248 context.home.quitCallback = quitCallback;
2250 startUseCaseSettingsAtPage(initPage);
2289 const char *reviewTitle,
2290 const char *reviewSubTitle,
2291 const char *finishTitle,
2294 useCaseReview(REVIEW_USE_CASE,
2329 const char *reviewTitle,
2330 const char *reviewSubTitle,
2331 const char *finishTitle,
2337 ContextType_t type = REVIEW_USE_CASE;
2340 if ((warning == NULL)
2354 operationType |= NO_THREAT_OPERATION;
2357 operationType |= RISKY_OPERATION;
2360 memset(&reviewWithWarnCtx, 0,
sizeof(reviewWithWarnCtx));
2361 reviewWithWarnCtx.type = type;
2362 reviewWithWarnCtx.operationType = operationType;
2363 reviewWithWarnCtx.tagValueList = tagValueList;
2364 reviewWithWarnCtx.icon = icon;
2365 reviewWithWarnCtx.reviewTitle = reviewTitle;
2366 reviewWithWarnCtx.reviewSubTitle = reviewSubTitle;
2367 reviewWithWarnCtx.finishTitle = finishTitle;
2368 reviewWithWarnCtx.warning = warning;
2369 reviewWithWarnCtx.choiceCallback = choiceCallback;
2372 if (reviewWithWarnCtx.warning->prelude) {
2377 displayInitialWarning();
2413 const char *reviewTitle,
2414 const char *reviewSubTitle,
2415 const char *finishTitle,
2426 &blindSigningWarning,
2447 const char *reviewTitle,
2448 const char *reviewSubTitle,
2449 const char *finishTitle,
2480 const char *reviewTitle,
2481 const char *reviewSubTitle,
2484 memset(&context, 0,
sizeof(UseCaseContext_t));
2485 context.type = ADDRESS_REVIEW_USE_CASE;
2486 context.review.address = address;
2487 context.review.reviewTitle = reviewTitle;
2488 context.review.reviewSubTitle = reviewSubTitle;
2489 context.review.icon = icon;
2490 context.review.onChoice = choiceCallback;
2491 context.currentPage = 0;
2494 context.nbPages = reviewSubTitle ? 5 : 4;
2495 if (additionalTagValueList) {
2496 context.review.tagValueList = PIC(additionalTagValueList);
2497 context.nbPages += additionalTagValueList->
nbPairs;
2512 const char *rejectText,
2515 memset(&context, 0,
sizeof(UseCaseContext_t));
2516 context.type = GENERIC_REVIEW_USE_CASE;
2517 context.content.rejectText = rejectText;
2518 context.content.quitCallback = rejectCallback;
2519 context.content.genericContents.nbContents = contents->
nbContents;
2525 context.content.genericContents.contentsList = PIC(contents->
contentsList);
2528 startUseCaseContent();
2542 memset(&context, 0,
sizeof(UseCaseContext_t));
2543 context.type = STATUS_USE_CASE;
2544 context.stepCallback = quitCallback;
2545 context.currentPage = 0;
2546 context.nbPages = 1;
2552 statusButtonCallback,
2568 switch (reviewStatusType) {
2570 msg =
"Operation signed";
2574 msg =
"Operation rejected";
2578 msg =
"Transaction signed";
2582 msg =
"Transaction rejected";
2586 msg =
"Message signed";
2590 msg =
"Message rejected";
2594 msg =
"Address verified";
2598 msg =
"Address verification cancelled";
2621 const char *reviewTitle,
2622 const char *reviewSubTitle,
2626 streamingOpType = operationType;
2628 memset(&context, 0,
sizeof(UseCaseContext_t));
2629 context.type = STREAMING_START_REVIEW_USE_CASE;
2630 context.operationType = operationType;
2631 context.review.reviewTitle = reviewTitle;
2632 context.review.reviewSubTitle = reviewSubTitle;
2633 context.review.icon = icon;
2634 context.review.onChoice = choiceCallback;
2635 context.currentPage = 0;
2636 context.nbPages = reviewSubTitle ? 3 : 2;
2656 const char *reviewTitle,
2657 const char *reviewSubTitle,
2661 operationType, icon, reviewTitle, reviewSubTitle, &blindSigningWarning, choiceCallback);
2681 const char *reviewTitle,
2682 const char *reviewSubTitle,
2686 memset(&context, 0,
sizeof(UseCaseContext_t));
2687 context.type = STREAMING_START_REVIEW_USE_CASE;
2688 context.operationType = operationType;
2689 context.review.reviewTitle = reviewTitle;
2690 context.review.reviewSubTitle = reviewSubTitle;
2691 context.review.icon = icon;
2692 context.review.onChoice = choiceCallback;
2693 context.currentPage = 0;
2694 context.nbPages = reviewSubTitle ? 3 : 2;
2697 streamingOpType = operationType;
2700 if ((warning == NULL)
2707 operationType |= NO_THREAT_OPERATION;
2710 operationType |= RISKY_OPERATION;
2712 memset(&reviewWithWarnCtx, 0,
sizeof(reviewWithWarnCtx));
2714 reviewWithWarnCtx.type = context.type;
2715 reviewWithWarnCtx.operationType = operationType;
2716 reviewWithWarnCtx.icon = icon;
2717 reviewWithWarnCtx.reviewTitle = reviewTitle;
2718 reviewWithWarnCtx.reviewSubTitle = reviewSubTitle;
2719 reviewWithWarnCtx.choiceCallback = choiceCallback;
2720 reviewWithWarnCtx.warning = warning;
2723 if (reviewWithWarnCtx.warning->prelude) {
2728 displayInitialWarning();
2752 uint8_t curNbDataSets = context.review.nbDataSets;
2754 memset(&context, 0,
sizeof(UseCaseContext_t));
2755 context.type = STREAMING_CONTINUE_REVIEW_USE_CASE;
2756 context.operationType = streamingOpType;
2757 context.review.tagValueList = tagValueList;
2758 context.review.onChoice = choiceCallback;
2759 context.currentPage = 0;
2760 context.nbPages = tagValueList->
nbPairs + 1;
2761 context.review.skipCallback = skipCallback;
2762 context.review.nbDataSets = curNbDataSets + 1;
2786 memset(&context, 0,
sizeof(UseCaseContext_t));
2787 context.type = STREAMING_FINISH_REVIEW_USE_CASE;
2788 context.operationType = streamingOpType;
2789 context.review.onChoice = choiceCallback;
2790 context.review.finishTitle = finishTitle;
2791 context.currentPage = 0;
2792 context.nbPages = 2;
2804 memset(&context, 0,
sizeof(UseCaseContext_t));
2805 context.type = SPINNER_USE_CASE;
2806 context.currentPage = 0;
2807 context.nbPages = 1;
2809 displaySpinner(text);
2825 const char *message,
2826 const char *subMessage,
2827 const char *confirmText,
2828 const char *cancelText,
2832 icon, message, subMessage, confirmText, cancelText, NULL, callback);
2850 const char *message,
2851 const char *subMessage,
2852 const char *confirmText,
2853 const char *cancelText,
2857 memset(&context, 0,
sizeof(UseCaseContext_t));
2858 context.type = CHOICE_USE_CASE;
2859 context.choice.icon = icon;
2860 context.choice.message = message;
2861 context.choice.subMessage = subMessage;
2862 context.choice.confirmText = confirmText;
2863 context.choice.cancelText = cancelText;
2864 context.choice.onChoice = callback;
2865 context.choice.details = details;
2866 context.currentPage = 0;
2867 context.nbPages = 2;
2868 if (message != NULL) {
2871 if ((icon != NULL) && (subMessage != NULL)) {
2875 if (details != NULL) {
2899 const char *subMessage,
2900 const char *confirmText,
2901 const char *cancelText,
2904 memset(&context, 0,
sizeof(UseCaseContext_t));
2905 context.type = CONFIRM_USE_CASE;
2906 context.confirm.message = message;
2907 context.confirm.subMessage = subMessage;
2908 context.confirm.confirmText = confirmText;
2909 context.confirm.cancelText = cancelText;
2910 context.confirm.onConfirm = callback;
2911 context.currentPage = 0;
2912 context.nbPages = 1 + 2;
2927 const char *message,
2928 const char *actionText,
2936 memset(&context, 0,
sizeof(UseCaseContext_t));
2937 context.type = ACTION_USE_CASE;
2938 context.action.actionCallback = callback;
2940 centeredInfo.
icon = icon;
2941 centeredInfo.
text1 = message;
2942 centeredInfo.
style = BOLD_TEXT1_INFO;
2977 memset(&context, 0,
sizeof(KeypadContext_t));
2978 context.type = KEYPAD_USE_CASE;
2979 context.currentPage = 0;
2980 context.nbPages = 1;
2981 context.keypad.validatePin = validatePinCallback;
2982 context.keypad.backCallback = backCallback;
2983 context.keypad.pinMinDigits = minDigits;
2984 context.keypad.pinMaxDigits = maxDigits;
2985 context.keypad.hidden = hidden;
2993 context.keypad.keypadIndex = status;
3001 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_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.
void nbgl_refresh(void)
This functions refreshes the actual screen on display with what has changed since the last refresh.
@ 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)
This function redraws the whole screen on top of stack and its children.
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)
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
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 * introDetails
const nbgl_warningDetails_t * reviewDetails
nbgl_contentInfoList_t infosList
INFOS_LIST 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