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 {
149 ReviewContext_t review;
150 ChoiceContext_t choice;
151 ConfirmContext_t confirm;
153 ContentContext_t content;
155 KeypadContext_t keypad;
157 ActionContext_t action;
161typedef struct PageContent_s {
171typedef struct ReviewWithWarningContext_s {
176 const char *reviewTitle;
177 const char *reviewSubTitle;
178 const char *finishTitle;
181 uint8_t securityReportLevel;
184 uint8_t nbWarningPages;
185} ReviewWithWarningContext_t;
196static UseCaseContext_t context;
198static ReviewWithWarningContext_t reviewWithWarnCtx;
216static void displaySpinner(
const char *text);
218static void startUseCaseHome(
void);
219static void startUseCaseInfo(
void);
220static void startUseCaseSettings(
void);
221static void startUseCaseSettingsAtPage(uint8_t initSettingPage);
222static void startUseCaseContent(
void);
224static void statusTickerCallback(
void);
227static void displayWarningStep(
void);
232 switch (content->
type) {
259 if (contentIdx < 0 || contentIdx >= genericContents->
nbContents) {
265 if (content == NULL) {
271 if (context.content.navCallback) {
272 if (context.content.navCallback(contentIdx, &pageContent) ==
true) {
275 switch (content->
type) {
321 uint8_t *elemContentIdx,
327 uint8_t elemNbPages = 0;
329 switch (context.type) {
330 case SETTINGS_USE_CASE:
332 case GENERIC_SETTINGS:
333 genericContents = context.home.settingContents;
335 case CONTENT_USE_CASE:
336 case GENERIC_REVIEW_USE_CASE:
337 genericContents = &context.content.genericContents;
342 for (
int i = 0; i < genericContents->
nbContents; i++) {
343 p_content = getContentAtIdx(genericContents, i, content);
344 elemNbPages = getContentNbElement(p_content);
345 if (nbPages + elemNbPages > elemIdx) {
346 *elemContentIdx = context.currentPage - nbPages;
349 nbPages += elemNbPages;
355static const char *getChoiceName(uint8_t choiceIndex)
365 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
366 if (p_content == NULL) {
369 switch (p_content->
type) {
372 names = (
char **) PIC(contentChoices->
names);
377 names = (
char **) PIC(contentBars->
barTexts);
378 nbValues = contentBars->
nbBars;
384 if (choiceIndex >= nbValues) {
388 return (
const char *) PIC(names[choiceIndex]);
391static void onChoiceSelected(uint8_t choiceIndex)
400 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
401 if (p_content == NULL) {
404 switch (p_content->
type) {
407 if (choiceIndex < contentChoices->nbChoices) {
408 token = contentChoices->
token;
413 if (choiceIndex < contentBars->nbBars) {
414 token = contentBars->
tokens[choiceIndex];
421 if ((token != 255) && (context.content.controlsCallback != NULL)) {
422 context.content.controlsCallback(token, 0);
424 else if (context.content.quitCallback != NULL) {
425 context.content.quitCallback();
435 bool *isCenteredInfo)
439 if (tagValueList->
pairs != NULL) {
440 pair = PIC(&tagValueList->
pairs[index]);
443 pair = PIC(tagValueList->
callback(index));
446 *value = pair->
value;
451 *isCenteredInfo =
true;
459static void onReviewAccept(
void)
461 if (context.review.onChoice) {
462 context.review.onChoice(
true);
466static void onReviewReject(
void)
468 if (context.review.onChoice) {
469 context.review.onChoice(
false);
473static void onChoiceAccept(
void)
475 if (context.choice.onChoice) {
476 context.choice.onChoice(
true);
480static void onChoiceReject(
void)
482 if (context.choice.onChoice) {
483 context.choice.onChoice(
false);
487static void onConfirmAccept(
void)
489 if (context.confirm.currentStep) {
492 if (context.confirm.onConfirm) {
493 context.confirm.onConfirm();
497static void onConfirmReject(
void)
499 if (context.confirm.currentStep) {
506static void onSwitchAction(
void)
513 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
519 switch (context.type) {
520 case SETTINGS_USE_CASE:
522 case GENERIC_SETTINGS:
525 case CONTENT_USE_CASE:
526 case GENERIC_REVIEW_USE_CASE:
534 actionCallback(contentSwitch->
token,
536 context.currentPage);
538 else if (context.content.controlsCallback != NULL) {
539 context.content.controlsCallback(contentSwitch->
token, 0);
549 ForcedType_t forcedType)
560 .tickerIntervale = 0,
566 if ((context.type == STREAMING_CONTINUE_REVIEW_USE_CASE)
567 && (context.review.skipCallback != NULL) && (context.review.nbDataSets > 1)) {
570 if ((context.type == STATUS_USE_CASE) || (context.type == SPINNER_USE_CASE)) {
573 if ((context.type == CONFIRM_USE_CASE) && (context.confirm.currentStep != NULL)) {
578 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
580 switch (p_content->
type) {
602 else if ((icon == NULL) && (forcedType != FORCE_CENTERED_INFO)) {
604 if (subTxt != NULL) {
605 style = (forcedType == FORCE_BUTTON) ? BUTTON_INFO : BOLD_TEXT1_INFO;
608 style = REGULAR_INFO;
610 newStep =
nbgl_stepDrawText(pos, onActionCallback, p_ticker, txt, subTxt, style, modal);
618 if ((subTxt != NULL) || (context.stepCallback != NULL)) {
619 info.
style = BOLD_TEXT1_INFO;
622 info.
style = REGULAR_INFO;
626 if (context.type == CONFIRM_USE_CASE) {
627 context.confirm.currentStep = newStep;
633 const char *description,
642 switchInfo.
text = title;
643 switchInfo.
subText = description;
656 if (context.currentPage > 0) {
657 context.currentPage--;
661 else if ((context.type != STREAMING_CONTINUE_REVIEW_USE_CASE)
662 || (context.review.skipCallback == NULL) || (context.review.nbDataSets == 1)) {
669 if (context.currentPage < (
int) (context.nbPages - 1)) {
670 context.currentPage++;
680 if (context.stepCallback != NULL) {
681 context.stepCallback();
683 else if ((context.type == CONTENT_USE_CASE) || (context.type == SETTINGS_USE_CASE)
684 || (context.type == GENERIC_SETTINGS)
685 || (context.type == GENERIC_REVIEW_USE_CASE)) {
686 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
687 if (p_content != NULL) {
688 switch (p_content->
type) {
703 index = context.currentPage;
712 else if (context.content.controlsCallback != NULL) {
713 context.content.controlsCallback(token, index);
728 if (!buttonGenericCallback(event, &pos)) {
732 displayReviewPage(pos);
743 if ((context.review.dataDirection ==
FORWARD_DIRECTION) && (context.currentPage > 0)) {
744 context.currentPage--;
751 && (context.currentPage < (
int) (context.nbPages - 1)) && (context.currentPage > 0)) {
752 context.currentPage++;
757 context.review.skipCallback();
763 displayStreamingReviewPage(pos);
772 context.action.actionCallback();
781 if (!buttonGenericCallback(event, &pos)) {
786 context.review.dataDirection = pos;
789 displayStreamingReviewPage(pos);
797 if (!buttonGenericCallback(event, &pos)) {
801 displaySettingsPage(pos,
false);
809 if (!buttonGenericCallback(event, &pos)) {
813 displayInfoPage(pos);
821 if (!buttonGenericCallback(event, &pos)) {
825 displayHomePage(pos);
833 if (!buttonGenericCallback(event, &pos)) {
837 displayChoicePage(pos);
845 if (!buttonGenericCallback(event, &pos)) {
858 if (context.stepCallback != NULL) {
859 context.stepCallback();
869 if (!buttonGenericCallback(event, &pos)) {
873 displayContent(pos,
false);
877static void statusTickerCallback(
void)
879 if (context.stepCallback != NULL) {
880 context.stepCallback();
892 if (context.review.currentExtensionPage > 0) {
893 context.review.currentExtensionPage--;
899 if (context.review.currentExtensionPage < (context.review.nbExtensionPages - 1)) {
900 context.review.currentExtensionPage++;
906 if (context.review.currentExtensionPage == (context.review.nbExtensionPages - 1)) {
916 displayExtensionStep(pos);
925 const char *text = NULL;
926 const char *subText = NULL;
928 if (context.review.extensionStepCtx != NULL) {
931 if (context.review.currentExtensionPage < (context.review.nbExtensionPages - 1)) {
932 if (context.review.currentExtensionPage == 0) {
939 switch (context.review.extension->aliasType) {
941 text = context.review.extension->title;
942 subText = context.review.extension->fullValue;
945 infoList = context.review.extension->infolist;
946 text = PIC(infoList->
infoTypes[context.review.currentExtensionPage]);
947 subText = PIC(infoList->
infoContents[context.review.currentExtensionPage]);
950 tagValueList = context.review.extension->tagValuelist;
951 text = PIC(tagValueList->
pairs[context.review.currentExtensionPage].
item);
952 subText = PIC(tagValueList->
pairs[context.review.currentExtensionPage].
value);
959 pos, extensionNavigate, NULL, text, subText, BOLD_TEXT1_INFO,
true);
962 else if (context.review.currentExtensionPage == (context.review.nbExtensionPages - 1)) {
964 info.
icon = &C_icon_back_x;
966 info.
style = BOLD_TEXT1_INFO;
968 context.review.extensionStepCtx
974static void displayAliasFullValue(
void)
976 const char *text = NULL;
977 const char *subText = NULL;
981 getPairData(context.review.tagValueList,
982 context.review.currentTagValueIndex,
985 &context.review.extension,
988 if (context.review.extension == NULL) {
991 "displayAliasFullValue: extension nor found for pair %d\n",
992 context.review.currentTagValueIndex);
995 context.review.currentExtensionPage = 0;
996 context.review.extensionStepCtx = NULL;
998 switch (context.review.extension->aliasType) {
1000 context.review.nbExtensionPages = 2;
1003 context.review.nbExtensionPages = context.review.extension->infolist->nbInfos + 1;
1006 context.review.nbExtensionPages = context.review.extension->tagValuelist->nbPairs + 1;
1010 "displayAliasFullValue: unsupported alias type %d\n",
1011 context.review.extension->aliasType);
1017static void getLastPageInfo(
bool approve,
const nbgl_icon_details_t **icon,
const char **text)
1021 *icon = &C_icon_validate_14;
1022 if (context.type == ADDRESS_REVIEW_USE_CASE) {
1027 if (context.review.finishTitle != NULL) {
1028 *text = context.review.finishTitle;
1033 if (context.operationType & RISKY_OPERATION) {
1034 *text =
"Accept risk and sign transaction";
1037 *text =
"Sign transaction";
1041 if (context.operationType & RISKY_OPERATION) {
1042 *text =
"Accept risk and sign message";
1045 *text =
"Sign message";
1049 if (context.operationType & RISKY_OPERATION) {
1050 *text =
"Accept risk and sign operation";
1053 *text =
"Sign operation";
1059 context.stepCallback = onReviewAccept;
1063 *icon = &C_icon_crossmark;
1064 if (context.type == ADDRESS_REVIEW_USE_CASE) {
1068 *text =
"Reject transaction";
1071 *text =
"Reject message";
1074 *text =
"Reject operation";
1076 context.stepCallback = onReviewReject;
1083 uint8_t reviewPages = 0;
1084 uint8_t finalPages = 0;
1085 uint8_t pairIndex = 0;
1086 const char *text = NULL;
1087 const char *subText = NULL;
1089 uint8_t currentIndex = 0;
1090 uint8_t titleIndex = 255;
1091 uint8_t subIndex = 255;
1092 uint8_t approveIndex = 255;
1093 uint8_t rejectIndex = 255;
1095 ForcedType_t forcedType = NO_FORCED_TYPE;
1097 context.stepCallback = NULL;
1101 titleIndex = currentIndex++;
1103 if (context.review.reviewSubTitle) {
1105 subIndex = currentIndex++;
1108 approveIndex = context.nbPages - 2;
1109 rejectIndex = context.nbPages - 1;
1110 finalPages = approveIndex;
1113 if (context.currentPage >= finalPages) {
1114 if (context.currentPage == approveIndex) {
1116 getLastPageInfo(
true, &icon, &text);
1118 else if (context.currentPage == rejectIndex) {
1120 getLastPageInfo(
false, &icon, &text);
1123 else if (context.currentPage < reviewPages) {
1124 if (context.currentPage == titleIndex) {
1126 icon = context.review.icon;
1127 text = context.review.reviewTitle;
1129 else if (context.currentPage == subIndex) {
1131 text = context.review.reviewSubTitle;
1134 else if ((context.review.address != NULL) && (context.currentPage == reviewPages)) {
1137 subText = context.review.address;
1140 bool isCenteredInfo =
false;
1141 pairIndex = context.currentPage - reviewPages;
1142 if (context.review.address != NULL) {
1145 getPairData(context.review.tagValueList,
1152 if (extension != NULL) {
1153 context.stepCallback = displayAliasFullValue;
1154 context.review.currentTagValueIndex = pairIndex;
1155 forcedType = FORCE_BUTTON;
1158 if (isCenteredInfo) {
1159 forcedType = FORCE_CENTERED_INFO;
1164 drawStep(pos, icon, text, subText, reviewCallback,
false, forcedType);
1171 const char *text = NULL;
1172 const char *subText = NULL;
1174 uint8_t reviewPages = 0;
1175 uint8_t titleIndex = 255;
1176 uint8_t subIndex = 255;
1178 ForcedType_t forcedType = NO_FORCED_TYPE;
1180 context.stepCallback = NULL;
1181 switch (context.type) {
1182 case STREAMING_START_REVIEW_USE_CASE:
1184 titleIndex = reviewPages++;
1185 if (context.review.reviewSubTitle) {
1187 subIndex = reviewPages++;
1190 if (context.currentPage >= reviewPages) {
1195 if (context.currentPage == titleIndex) {
1197 icon = context.review.icon;
1198 text = context.review.reviewTitle;
1200 else if (context.currentPage == subIndex) {
1202 text = context.review.reviewSubTitle;
1206 case STREAMING_CONTINUE_REVIEW_USE_CASE:
1207 if (context.currentPage >= context.review.tagValueList->nbPairs) {
1214 if ((context.review.skipCallback != NULL) && (context.review.skipDisplay ==
false)
1215 && ((context.review.nbDataSets > 1) || (context.currentPage > 0)
1219 if ((context.review.nbDataSets == 1) || (context.currentPage > 0)) {
1222 info.
icon = &C_Information_circle_14px;
1223 info.
text1 =
"Press right button to continue message or \bpress both to skip\b";
1226 context.review.skipDisplay =
true;
1229 context.review.skipDisplay =
false;
1230 bool isCenteredInfo =
false;
1231 getPairData(context.review.tagValueList,
1232 context.currentPage,
1238 if (extension != NULL) {
1239 forcedType = FORCE_BUTTON;
1242 if (isCenteredInfo) {
1243 forcedType = FORCE_CENTERED_INFO;
1248 case STREAMING_FINISH_REVIEW_USE_CASE:
1250 if (context.currentPage == 0) {
1252 getLastPageInfo(
true, &icon, &text);
1256 getLastPageInfo(
false, &icon, &text);
1261 drawStep(pos, icon, text, subText, streamingReviewCallback,
false, forcedType);
1268 const char *text = NULL;
1269 const char *subText = NULL;
1272 context.stepCallback = NULL;
1274 if (context.currentPage < (context.nbPages - 1)) {
1276 ((
const char *
const *) PIC(context.home.infosList->infoTypes))[context.currentPage]);
1278 ((
const char *
const *) PIC(context.home.infosList->infoContents))[context.currentPage]);
1281 icon = &C_icon_back_x;
1283 context.stepCallback = startUseCaseHome;
1286 drawStep(pos, icon, text, subText, infoCallback,
false, FORCE_CENTERED_INFO);
1291static void getContentPage(
bool toogle_state, PageContent_t *contentPage)
1293 uint8_t elemIdx = 0;
1297#ifdef WITH_HORIZONTAL_CHOICES_LIST
1299 char **names = NULL;
1301#ifdef WITH_HORIZONTAL_BARS_LIST
1303 char **texts = NULL;
1305 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
1306 if (p_content == NULL) {
1309 switch (p_content->
type) {
1323 &contentPage->subText,
1324 &contentPage->extension,
1326 &contentPage->isCenteredInfo);
1329 contentPage->isSwitch =
true;
1332 contentPage->
text = contentSwitch->
text;
1333 contentPage->state = contentSwitch->
initState;
1337 context.stepCallback = onSwitchAction;
1338 contentPage->subText = contentSwitch->
subText;
1343 contentPage->subText
1347#ifdef WITH_HORIZONTAL_CHOICES_LIST
1349 names = (
char **) PIC(contentChoices->
names);
1350 if ((context.type == CONTENT_USE_CASE) && (context.content.title != NULL)) {
1351 contentPage->text = PIC(context.content.title);
1352 contentPage->subText = (
const char *) PIC(names[elemIdx]);
1354 else if ((context.type == GENERIC_SETTINGS) && (context.home.appName != NULL)) {
1355 contentPage->text = PIC(context.home.appName);
1356 contentPage->subText = (
const char *) PIC(names[elemIdx]);
1359 contentPage->text = (
const char *) PIC(names[elemIdx]);
1364#ifdef WITH_HORIZONTAL_BARS_LIST
1366 texts = (
char **) PIC(contentBars->
barTexts);
1367 if ((context.type == CONTENT_USE_CASE) && (context.content.title != NULL)) {
1368 contentPage->text = PIC(context.content.title);
1369 contentPage->subText = PIC(texts[elemIdx]);
1371 else if ((context.type == GENERIC_SETTINGS) && (context.home.appName != NULL)) {
1372 contentPage->text = PIC(context.home.appName);
1373 contentPage->subText = PIC(texts[elemIdx]);
1376 contentPage->text = PIC(texts[elemIdx]);
1388 PageContent_t contentPage = {0};
1390 context.stepCallback = NULL;
1392 if (context.currentPage < (context.nbPages - 1)) {
1393 getContentPage(toogle_state, &contentPage);
1396 contentPage.icon = &C_icon_back_x;
1397 contentPage.text =
"Back";
1398 if (context.type == GENERIC_SETTINGS) {
1399 context.stepCallback = context.home.quitCallback;
1402 context.stepCallback = startUseCaseHome;
1406 if (contentPage.isSwitch) {
1408 pos, contentPage.text, contentPage.subText, contentPage.state, settingsCallback,
false);
1414 contentPage.subText,
1423static void startUseCaseHome(
void)
1425 switch (context.type) {
1426 case SETTINGS_USE_CASE:
1428 context.currentPage = 1;
1429 if (context.home.homeAction) {
1431 context.currentPage++;
1436 context.currentPage = 1;
1437 if (context.home.homeAction) {
1439 context.currentPage++;
1441 if (context.home.settingContents) {
1443 context.currentPage++;
1448 context.currentPage = 0;
1452 context.type = HOME_USE_CASE;
1453 context.nbPages = 2;
1454 if (context.home.settingContents) {
1457 if (context.home.infosList) {
1460 if (context.home.homeAction) {
1466static void startUseCaseInfo(
void)
1468 context.type = INFO_USE_CASE;
1469 context.nbPages = context.home.infosList->nbInfos + 1;
1470 context.currentPage = 0;
1475static void startUseCaseSettingsAtPage(uint8_t initSettingPage)
1481 if (context.type != GENERIC_SETTINGS) {
1482 context.
type = SETTINGS_USE_CASE;
1485 context.nbPages = 1;
1486 for (
int i = 0; i < context.home.settingContents->nbContents; i++) {
1487 p_content = getContentAtIdx(context.home.settingContents, i, &content);
1488 context.nbPages += getContentNbElement(p_content);
1490 context.currentPage = initSettingPage;
1495static void startUseCaseSettings(
void)
1497 startUseCaseSettingsAtPage(0);
1500static void startUseCaseContent(
void)
1502 uint8_t contentIdx = 0;
1506 context.nbPages = 1;
1508 for (contentIdx = 0; contentIdx < context.content.genericContents.nbContents; contentIdx++) {
1509 p_content = getContentAtIdx(&context.content.genericContents, contentIdx, &content);
1510 context.nbPages += getContentNbElement(p_content);
1514 if (context.currentPage >= context.nbPages) {
1524 const char *text = NULL;
1525 const char *subText = NULL;
1527 uint8_t currentIndex = 0;
1528 uint8_t homeIndex = 255;
1529 uint8_t actionIndex = 255;
1530 uint8_t settingsIndex = 255;
1531 uint8_t infoIndex = 255;
1533 context.stepCallback = NULL;
1536 homeIndex = currentIndex++;
1537 if (context.home.homeAction) {
1538 actionIndex = currentIndex++;
1540 if (context.home.settingContents) {
1541 settingsIndex = currentIndex++;
1543 if (context.home.infosList) {
1544 infoIndex = currentIndex++;
1547 if (context.currentPage == homeIndex) {
1549 icon = context.home.appIcon;
1550 if (context.home.tagline != NULL) {
1551 text = context.home.tagline;
1554 text = context.home.appName;
1555 subText =
"app is ready";
1558 else if (context.currentPage == actionIndex) {
1560 icon = context.home.homeAction->icon;
1561 text = PIC(context.home.homeAction->text);
1562 context.stepCallback = context.home.homeAction->callback;
1564 else if (context.currentPage == settingsIndex) {
1566 icon = &C_icon_coggle;
1567 text =
"App settings";
1568 context.stepCallback = startUseCaseSettings;
1570 else if (context.currentPage == infoIndex) {
1572 icon = &C_Information_circle_14px;
1574 context.stepCallback = startUseCaseInfo;
1577 icon = &C_Quit_14px;
1579 context.stepCallback = context.home.quitCallback;
1582 drawStep(pos, icon, text, subText, homeCallback,
false, NO_FORCED_TYPE);
1589 const char *text = NULL;
1590 const char *subText = NULL;
1593 uint8_t acceptPage = 0;
1595 if (context.choice.message != NULL) {
1596 if ((context.choice.icon == NULL) || (context.choice.subMessage == NULL)) {
1603 context.stepCallback = NULL;
1605 if (context.currentPage < acceptPage) {
1606 if (context.currentPage == 0) {
1607 text = context.choice.message;
1608 if (context.choice.icon != NULL) {
1609 icon = context.choice.icon;
1612 subText = context.choice.subMessage;
1615 else if ((acceptPage == 2) && (context.currentPage == 1)) {
1617 text = context.choice.message;
1618 subText = context.choice.subMessage;
1621 else if (context.currentPage == acceptPage) {
1622 icon = &C_icon_validate_14;
1623 text = context.choice.confirmText;
1624 context.stepCallback = onChoiceAccept;
1626 else if (context.currentPage == (acceptPage + 1)) {
1627 icon = &C_icon_crossmark;
1628 text = context.choice.cancelText;
1629 context.stepCallback = onChoiceReject;
1631 else if (context.choice.details != NULL) {
1634 text = context.choice.details->barList.texts[context.currentPage - (acceptPage + 2)];
1636 = context.choice.details->barList.subTexts[context.currentPage - (acceptPage + 2)];
1640 drawStep(pos, icon, text, subText, genericChoiceCallback,
false, NO_FORCED_TYPE);
1647 const char *text = NULL;
1648 const char *subText = NULL;
1651 context.stepCallback = NULL;
1652 switch (context.currentPage) {
1655 text = context.confirm.message;
1656 subText = context.confirm.subMessage;
1660 icon = &C_icon_validate_14;
1661 text = context.confirm.confirmText;
1662 context.stepCallback = onConfirmAccept;
1666 icon = &C_icon_crossmark;
1667 text = context.confirm.cancelText;
1668 context.stepCallback = onConfirmReject;
1672 drawStep(pos, icon, text, subText, genericConfirmCallback,
true, NO_FORCED_TYPE);
1679 PageContent_t contentPage = {0};
1680 ForcedType_t forcedType = NO_FORCED_TYPE;
1682 context.stepCallback = NULL;
1684 if (context.currentPage < (context.nbPages - 1)) {
1685 getContentPage(toogle_state, &contentPage);
1686 if (contentPage.isCenteredInfo) {
1687 forcedType = FORCE_CENTERED_INFO;
1691 if (context.content.rejectText) {
1692 contentPage.text = context.content.rejectText;
1695 contentPage.text =
"Back";
1697 if (context.type == GENERIC_REVIEW_USE_CASE) {
1698 contentPage.icon = &C_icon_crossmark;
1701 contentPage.icon = &C_icon_back_x;
1703 context.stepCallback = context.content.quitCallback;
1706 if (contentPage.isSwitch) {
1708 pos, contentPage.text, contentPage.subText, contentPage.state, contentCallback,
false);
1714 contentPage.subText,
1723static void displaySpinner(
const char *text)
1725 drawStep(
SINGLE_STEP, &C_icon_processing, text, NULL, NULL,
false,
false);
1730static void useCaseReview(ContextType_t type,
1734 const char *reviewTitle,
1735 const char *reviewSubTitle,
1736 const char *finishTitle,
1739 memset(&context, 0,
sizeof(UseCaseContext_t));
1740 context.type = type;
1741 context.operationType = operationType;
1742 context.review.tagValueList = tagValueList;
1743 context.review.reviewTitle = reviewTitle;
1744 context.review.reviewSubTitle = reviewSubTitle;
1745 context.review.finishTitle = finishTitle;
1746 context.review.icon = icon;
1747 context.review.onChoice = choiceCallback;
1748 context.currentPage = 0;
1750 context.nbPages = tagValueList->
nbPairs + 3;
1751 if (reviewSubTitle) {
1759static void setPinCodeText(
void)
1761 bool enableValidate =
false;
1762 bool enableBackspace =
true;
1765 enableValidate = (context.keypad.pinLen >= context.keypad.pinMinDigits);
1767 enableBackspace = (context.keypad.pinLen > 0) || (context.keypad.backCallback != NULL);
1769 context.keypad.hidden,
1770 context.keypad.pinLen,
1771 (
const char *) context.keypad.pinEntry);
1773 context.keypad.layoutCtx, context.keypad.keypadIndex, enableValidate, enableBackspace);
1779static void keypadCallback(
char touchedKey)
1781 switch (touchedKey) {
1783 if (context.keypad.pinLen > 0) {
1784 context.keypad.pinLen--;
1785 context.keypad.pinEntry[context.keypad.pinLen] = 0;
1787 else if (context.keypad.backCallback != NULL) {
1788 context.keypad.backCallback();
1795 context.keypad.validatePin(context.keypad.pinEntry, context.keypad.pinLen);
1799 if ((touchedKey >= 0x30) && (touchedKey < 0x40)) {
1800 if (context.keypad.pinLen < context.keypad.pinMaxDigits) {
1801 context.keypad.pinEntry[context.keypad.pinLen] = touchedKey;
1802 context.keypad.pinLen++;
1811static void keypadGenericUseCase(
const char *title,
1823 memset(&context, 0,
sizeof(KeypadContext_t));
1824 context.type = KEYPAD_USE_CASE;
1825 context.currentPage = 0;
1826 context.nbPages = 1;
1827 context.keypad.validatePin = validatePinCallback;
1828 context.keypad.backCallback = backCallback;
1829 context.keypad.pinMinDigits = minDigits;
1830 context.keypad.pinMaxDigits = maxDigits;
1831 context.keypad.hidden = hidden;
1839 context.keypad.keypadIndex = status;
1847 if (context.keypad.backCallback != NULL) {
1862 if (reviewWithWarnCtx.warningPage > 0) {
1863 reviewWithWarnCtx.warningPage--;
1868 if (reviewWithWarnCtx.warningPage < (reviewWithWarnCtx.nbWarningPages - 1)) {
1869 reviewWithWarnCtx.warningPage++;
1874 if (reviewWithWarnCtx.warningPage == 0) {
1875 if (reviewWithWarnCtx.type == REVIEW_USE_CASE) {
1876 useCaseReview(reviewWithWarnCtx.type,
1877 reviewWithWarnCtx.operationType,
1878 reviewWithWarnCtx.tagValueList,
1879 reviewWithWarnCtx.icon,
1880 reviewWithWarnCtx.reviewTitle,
1881 reviewWithWarnCtx.reviewSubTitle,
1882 reviewWithWarnCtx.finishTitle,
1883 reviewWithWarnCtx.choiceCallback);
1885 else if (reviewWithWarnCtx.type == STREAMING_START_REVIEW_USE_CASE) {
1890 else if (reviewWithWarnCtx.warningPage == (reviewWithWarnCtx.nbWarningPages - 1)) {
1891 reviewWithWarnCtx.choiceCallback(
false);
1898 displayWarningStep();
1902static void displayWarningStep(
void)
1906 if (reviewWithWarnCtx.warningPage == 0) {
1908 info.
icon = &C_icon_warning;
1909 info.
text1 =
"Blind signing ahead";
1910 info.
text2 =
"To accept risk, press both buttons";
1913 else if (reviewWithWarnCtx.warningPage == (reviewWithWarnCtx.nbWarningPages - 1)) {
1914 getLastPageInfo(
false, &info.
icon, &info.
text1);
1917 info.
style = BOLD_TEXT1_INFO;
1923static void displayInitialWarning(
void)
1926 reviewWithWarnCtx.warningPage = 0;
1927 reviewWithWarnCtx.nbWarningPages = 2;
1928 displayWarningStep();
1949 bool *requireSpecificDisplay)
1952 UNUSED(tagValueList);
1954 *requireSpecificDisplay =
true;
1974 bool *requireSpecificDisplay)
1977 UNUSED(tagValueList);
1979 UNUSED(isSkippable);
1980 *requireSpecificDisplay =
true;
2018 UNUSED(switchesList);
2058 UNUSED(choicesList);
2072 uint8_t nbPages = 0;
2073 uint8_t nbPairs = tagValueList->
nbPairs;
2074 uint8_t nbPairsInPage;
2078 while (i < tagValueList->nbPairs) {
2082 nbPairs -= nbPairsInPage;
2108 memset(&context, 0,
sizeof(UseCaseContext_t));
2109 context.type = CONTENT_USE_CASE;
2110 context.currentPage = initPage;
2111 context.content.title = title;
2112 context.content.quitCallback = quitCallback;
2113 context.content.navCallback = navCallback;
2114 context.content.controlsCallback = controlsCallback;
2115 context.content.genericContents.callbackCallNeeded =
true;
2116 context.content.genericContents.nbContents = nbPages;
2118 startUseCaseContent();
2137 const char *tagline,
2138 const uint8_t initSettingPage,
2144 memset(&context, 0,
sizeof(UseCaseContext_t));
2145 context.home.appName = appName;
2146 context.home.appIcon = appIcon;
2147 context.home.tagline = tagline;
2148 context.home.settingContents = PIC(settingContents);
2149 context.home.infosList = PIC(infosList);
2150 context.home.homeAction = action;
2151 context.home.quitCallback = quitCallback;
2153 if ((initSettingPage !=
INIT_HOME_PAGE) && (settingContents != NULL)) {
2154 startUseCaseSettingsAtPage(initSettingPage);
2179 memset(&context, 0,
sizeof(UseCaseContext_t));
2180 context.type = GENERIC_SETTINGS;
2181 context.home.appName = appName;
2182 context.home.settingContents = PIC(settingContents);
2183 context.home.infosList = PIC(infosList);
2184 context.home.quitCallback = quitCallback;
2186 startUseCaseSettingsAtPage(initPage);
2225 const char *reviewTitle,
2226 const char *reviewSubTitle,
2227 const char *finishTitle,
2230 useCaseReview(REVIEW_USE_CASE,
2265 const char *reviewTitle,
2266 const char *reviewSubTitle,
2267 const char *finishTitle,
2273 ContextType_t type = REVIEW_USE_CASE;
2276 if ((warning == NULL)
2290 operationType |= NO_THREAT_OPERATION;
2293 operationType |= RISKY_OPERATION;
2296 memset(&reviewWithWarnCtx, 0,
sizeof(reviewWithWarnCtx));
2297 reviewWithWarnCtx.type = type;
2298 reviewWithWarnCtx.operationType = operationType;
2299 reviewWithWarnCtx.tagValueList = tagValueList;
2300 reviewWithWarnCtx.icon = icon;
2301 reviewWithWarnCtx.reviewTitle = reviewTitle;
2302 reviewWithWarnCtx.reviewSubTitle = reviewSubTitle;
2303 reviewWithWarnCtx.finishTitle = finishTitle;
2304 reviewWithWarnCtx.warning = warning;
2305 reviewWithWarnCtx.choiceCallback = choiceCallback;
2321 displayInitialWarning();
2346 const char *reviewTitle,
2347 const char *reviewSubTitle,
2348 const char *finishTitle,
2359 &blindSigningWarning,
2380 const char *reviewTitle,
2381 const char *reviewSubTitle,
2382 const char *finishTitle,
2413 const char *reviewTitle,
2414 const char *reviewSubTitle,
2417 memset(&context, 0,
sizeof(UseCaseContext_t));
2418 context.type = ADDRESS_REVIEW_USE_CASE;
2419 context.review.address = address;
2420 context.review.reviewTitle = reviewTitle;
2421 context.review.reviewSubTitle = reviewSubTitle;
2422 context.review.icon = icon;
2423 context.review.onChoice = choiceCallback;
2424 context.currentPage = 0;
2426 context.nbPages = 4;
2427 if (additionalTagValueList) {
2428 context.review.tagValueList = PIC(additionalTagValueList);
2429 context.nbPages += additionalTagValueList->
nbPairs;
2444 const char *rejectText,
2447 memset(&context, 0,
sizeof(UseCaseContext_t));
2448 context.type = GENERIC_REVIEW_USE_CASE;
2449 context.content.rejectText = rejectText;
2450 context.content.quitCallback = rejectCallback;
2451 context.content.genericContents.nbContents = contents->
nbContents;
2457 context.content.genericContents.contentsList = PIC(contents->
contentsList);
2460 startUseCaseContent();
2474 memset(&context, 0,
sizeof(UseCaseContext_t));
2475 context.type = STATUS_USE_CASE;
2476 context.stepCallback = quitCallback;
2477 context.currentPage = 0;
2478 context.nbPages = 1;
2484 statusButtonCallback,
2500 switch (reviewStatusType) {
2502 msg =
"Operation signed";
2506 msg =
"Operation rejected";
2510 msg =
"Transaction signed";
2514 msg =
"Transaction rejected";
2518 msg =
"Message signed";
2522 msg =
"Message rejected";
2526 msg =
"Address verified";
2530 msg =
"Address verification cancelled";
2553 const char *reviewTitle,
2554 const char *reviewSubTitle,
2558 streamingOpType = operationType;
2560 memset(&context, 0,
sizeof(UseCaseContext_t));
2561 context.type = STREAMING_START_REVIEW_USE_CASE;
2562 context.operationType = operationType;
2563 context.review.reviewTitle = reviewTitle;
2564 context.review.reviewSubTitle = reviewSubTitle;
2565 context.review.icon = icon;
2566 context.review.onChoice = choiceCallback;
2567 context.currentPage = 0;
2568 context.nbPages = 2;
2588 const char *reviewTitle,
2589 const char *reviewSubTitle,
2593 operationType, icon, reviewTitle, reviewSubTitle, &blindSigningWarning, choiceCallback);
2613 const char *reviewTitle,
2614 const char *reviewSubTitle,
2618 memset(&context, 0,
sizeof(UseCaseContext_t));
2619 context.type = STREAMING_START_REVIEW_USE_CASE;
2620 context.operationType = operationType;
2621 context.review.reviewTitle = reviewTitle;
2622 context.review.reviewSubTitle = reviewSubTitle;
2623 context.review.icon = icon;
2624 context.review.onChoice = choiceCallback;
2625 context.currentPage = 0;
2626 context.nbPages = 2;
2629 streamingOpType = operationType;
2632 if ((warning == NULL)
2639 operationType |= NO_THREAT_OPERATION;
2642 operationType |= RISKY_OPERATION;
2644 memset(&reviewWithWarnCtx, 0,
sizeof(reviewWithWarnCtx));
2646 reviewWithWarnCtx.type = context.type;
2647 reviewWithWarnCtx.operationType = operationType;
2648 reviewWithWarnCtx.icon = icon;
2649 reviewWithWarnCtx.reviewTitle = reviewTitle;
2650 reviewWithWarnCtx.reviewSubTitle = reviewSubTitle;
2651 reviewWithWarnCtx.choiceCallback = choiceCallback;
2652 reviewWithWarnCtx.warning = warning;
2661 displayInitialWarning();
2681 uint8_t curNbDataSets = context.review.nbDataSets;
2683 memset(&context, 0,
sizeof(UseCaseContext_t));
2684 context.type = STREAMING_CONTINUE_REVIEW_USE_CASE;
2685 context.operationType = streamingOpType;
2686 context.review.tagValueList = tagValueList;
2687 context.review.onChoice = choiceCallback;
2688 context.currentPage = 0;
2689 context.nbPages = tagValueList->
nbPairs + 1;
2690 context.review.skipCallback = skipCallback;
2691 context.review.nbDataSets = curNbDataSets + 1;
2715 memset(&context, 0,
sizeof(UseCaseContext_t));
2716 context.type = STREAMING_FINISH_REVIEW_USE_CASE;
2717 context.operationType = streamingOpType;
2718 context.review.onChoice = choiceCallback;
2719 context.review.finishTitle = finishTitle;
2720 context.currentPage = 0;
2721 context.nbPages = 2;
2733 memset(&context, 0,
sizeof(UseCaseContext_t));
2734 context.type = SPINNER_USE_CASE;
2735 context.currentPage = 0;
2736 context.nbPages = 1;
2738 displaySpinner(text);
2754 const char *message,
2755 const char *subMessage,
2756 const char *confirmText,
2757 const char *cancelText,
2761 icon, message, subMessage, confirmText, cancelText, NULL, callback);
2779 const char *message,
2780 const char *subMessage,
2781 const char *confirmText,
2782 const char *cancelText,
2786 memset(&context, 0,
sizeof(UseCaseContext_t));
2787 context.type = CHOICE_USE_CASE;
2788 context.choice.icon = icon;
2789 context.choice.message = message;
2790 context.choice.subMessage = subMessage;
2791 context.choice.confirmText = confirmText;
2792 context.choice.cancelText = cancelText;
2793 context.choice.onChoice = callback;
2794 context.choice.details = details;
2795 context.currentPage = 0;
2796 context.nbPages = 2;
2797 if (message != NULL) {
2800 if ((icon != NULL) && (subMessage != NULL)) {
2804 if (details != NULL) {
2828 const char *subMessage,
2829 const char *confirmText,
2830 const char *cancelText,
2833 memset(&context, 0,
sizeof(UseCaseContext_t));
2834 context.type = CONFIRM_USE_CASE;
2835 context.confirm.message = message;
2836 context.confirm.subMessage = subMessage;
2837 context.confirm.confirmText = confirmText;
2838 context.confirm.cancelText = cancelText;
2839 context.confirm.onConfirm = callback;
2840 context.currentPage = 0;
2841 context.nbPages = 1 + 2;
2856 const char *message,
2857 const char *actionText,
2865 memset(&context, 0,
sizeof(UseCaseContext_t));
2866 context.type = ACTION_USE_CASE;
2867 context.action.actionCallback = callback;
2869 centeredInfo.
icon = icon;
2870 centeredInfo.
text1 = message;
2871 centeredInfo.
style = BOLD_TEXT1_INFO;
2900 keypadGenericUseCase(
2901 title, minDigits, maxDigits, shuffled,
false, validatePinCallback, backCallback);
2929 keypadGenericUseCase(
2930 title, minDigits, maxDigits, shuffled,
true, validatePinCallback, backCallback);
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.
@ 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
void nbgl_useCaseGenericSettings(const char *appName, uint8_t initPage, const nbgl_genericContents_t *settingContents, const nbgl_contentInfoList_t *infosList, nbgl_callback_t quitCallback)
void nbgl_useCaseKeypadPIN(const char *title, uint8_t minDigits, uint8_t maxDigits, uint8_t backToken, bool shuffled, tune_index_e tuneId, nbgl_pinValidCallback_t validatePinCallback, nbgl_layoutTouchCallback_t actionCallback)
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_useCaseKeypadDigits(const char *title, uint8_t minDigits, uint8_t maxDigits, uint8_t backToken, bool shuffled, tune_index_e tuneId, nbgl_pinValidCallback_t validatePinCallback, nbgl_layoutTouchCallback_t actionCallback)
void nbgl_useCaseStatus(const char *message, bool isSuccess, nbgl_callback_t quitCallback)
@ W3C_THREAT_DETECTED_WARN
Web3 Checks: Threat detected (see reportRisk field)
@ BLIND_SIGNING_WARN
Blind signing.
@ W3C_NO_THREAT_WARN
Web3 Checks: No Threat detected.
@ W3C_RISK_DETECTED_WARN
Web3 Checks: Risk detected (see reportRisk field)
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_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
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_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