From 75d83071d03fc6070849baa58301305f16c21d07 Mon Sep 17 00:00:00 2001 From: Nicolas Roggeman Date: Fri, 24 May 2024 14:49:44 +0200 Subject: [PATCH] Add possibilty to use alias for value in tag/value pair, with automatic creation of "detailled" view --- lib_nbgl/glyphs/32px/Mini_Push_32px.png | Bin 0 -> 1530 bytes lib_nbgl/glyphs/40px/Mini_Push_40px.png | Bin 0 -> 1008 bytes lib_nbgl/include/nbgl_content.h | 50 +++++++-- lib_nbgl/include/nbgl_layout.h | 4 + lib_nbgl/include/nbgl_obj.h | 7 ++ lib_nbgl/src/nbgl_layout.c | 124 ++++++++++++++++++---- lib_nbgl/src/nbgl_use_case.c | 132 ++++++++++++++++++++---- 7 files changed, 267 insertions(+), 50 deletions(-) create mode 100755 lib_nbgl/glyphs/32px/Mini_Push_32px.png create mode 100755 lib_nbgl/glyphs/40px/Mini_Push_40px.png diff --git a/lib_nbgl/glyphs/32px/Mini_Push_32px.png b/lib_nbgl/glyphs/32px/Mini_Push_32px.png new file mode 100755 index 0000000000000000000000000000000000000000..9d3fc747edf16a6566f72629cb69b269e72f43b6 GIT binary patch literal 1530 zcmVbL{6o z|9>xZ;LADZ_dDmgpXWTsIcrHtNiH)pGZ>#ed)6&3F1q32VK+KDx`C0Akt6CG#>U3J zQ9q;pp|Gy;tom;C=Y-18`hW(sph<%VyrQ<++FCa|I~!~kkpvMwp#HS_pY`o;jVFaZ z;YZ;+q1(ni!kE^qY3;DaA8A~oJ`GwkGcy70|1>X6d3m{OX=!njlap?Id>rQa!h6C` zBDkvlx(GE3Rl?IkCIXta8JZUe$AkuRa#KyH^BFXu|_uwD|aV=Q1)ff=N?T zlUrY3cm4hSXrHIeog%z~W}2TI930G_n3zbKo}PBFO-(ti%@I?CxuX4R!nYci zLK`0NqNS#$KDI(#U0opEz`y{^v$Ww4+jv2Q0)H+oExFsbZ@aFpE|;C1?Q(K*f<8Rv zA8VGEmjf$W3^kY{vsefo@Y--keSN({D>k6H77hv18oxa>G?b1;w{G2Xot>R7FE7t+ z*I2{a-rnB8BBsEL7B_>UdjMW@b93&*i4)E(EGz^8C+ydP&(K`sGm<{d`|aq_qZ!qb4}>gp;-6d^8JJRJ7vbwz!ne4dD;g@uJK zAt51_n~#NrSRswX5&~M#?Ca|b;!3<;mC{S%`xfSJ)dzf1#j)w==-6qjA;g#ov1*n` zinRgS@Zc!gX}E~_uW8aN6cH?Br&vcVqE&^2h#3>mgfkg&MdLznT0ky#ET<&PRh?Cz(c#$5|ECRx`!4S69>0i1Z}fGoX{pba(170 z`zv#g0u%^0OaSogHUb2(M^eHZe@TcRg!DbS0Or?>@tSZ&NRQ?M1c-FOO$~a4f;|M` zk&xz`g!4jLtRRGkcxKsE-Q$npxKi*-R6@HrhA{6AX%6$89Uj91bNd%eDy2O)U;|0w z&Ye3uNkox8zYJ{TG%j7bw2_L%>q99` z$yVZT!w)o>p<>}~AZ5n5jH=AvF?}B1TTxLFXm6ErmUvL~Tov|v3mg{u_2Vn9Os-CX zg{yQ6Az=8f&=$+*;p>>lhbC9Oc(mGWcuMmGM^T^;NmQ>SCH#UAY@#msKME3PK~v0M zw}Rv4ri+NWF4RgiCXr7wh?zTztZw7H&Z$2yyextT)MpE+cB`?LASS&&Wl5&Zj@qA^ zU-!qGcxY~J-uyI+Y}M7(Zhn5=KPY(r)seRa(HL9cttjwpyI@x;r{`mV-2T0-d7$;I zc|&~~uE6Kej@ppMztsp1{D>*7lHDg_)Q)c=jK2M1Px420oiC~HH$i!dJtqZn)W>tw gpydM&9%0S@0ds2(8^^O!XaE2J07*qoM6N<$f`4+{zW@LL literal 0 HcmV?d00001 diff --git a/lib_nbgl/glyphs/40px/Mini_Push_40px.png b/lib_nbgl/glyphs/40px/Mini_Push_40px.png new file mode 100755 index 0000000000000000000000000000000000000000..6d105ff428b288e9b84fe0c4cabf77fd3286ccc2 GIT binary patch literal 1008 zcmV&QY*uPA9t;L2NY#ckXrX3d%jNQyruAqvs-=SlDGw{uuqcX4 zt@J8@iIvrlsb61TZxzDq$tbM@-n@}j%QRZYsqZ48inf>a#Ye(fzL*sbLYZ3jv8+b> zm=2MhfM`}(O&cDrkv$3B1$7XzWZfIuXkvByg?`C5SvBi%-~JXW3?R1JQ0u)8TdW8k zGVBw=K4;}039W=WaSsMgQ=5R8=QIK2G_lVaHT0jAe~5^-D$x z-ZN^COwm`-pBBc z^1b(jh+H5=6vCyX#xe7mu>Z@3)p0lvV(03;$U{@CETJCy!a;2t=Wr#dSV4(HwZzM+ zeU_eZ46$6GJj8AM?`uGMF+5rIopz#yre*x+j}zs_TFlcvn%adv7)RMVTyQ47+YTnR z#%6SgZ-+jt><7+=Jd9dnj5*$Zrgb-?Q0P+_mH4`+#6B4%^f`LY$SQKyy43zP{H9layer); + textArea->textColor = BLACK; + textArea->text = PIC(title); + textArea->textAlignment = MID_LEFT; + textArea->fontId = LARGE_MEDIUM_FONT; + textArea->style = NO_STYLE; + textArea->wrapping = true; + textArea->obj.alignment = NO_ALIGNMENT; + textArea->obj.alignmentMarginX = BORDER_MARGIN; + textArea->obj.alignmentMarginY = 16; + textArea->obj.area.width = AVAILABLE_WIDTH; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + // set this new obj as child of main container + layoutAddObject(layoutInt, (nbgl_obj_t *) textArea); + + // create description + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + textArea->textColor = BLACK; + textArea->text = PIC(description); + textArea->fontId = SMALL_REGULAR_FONT; + textArea->style = NO_STYLE; + textArea->wrapping = true; + textArea->obj.area.width = AVAILABLE_WIDTH; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + textArea->textAlignment = MID_LEFT; + textArea->obj.alignment = NO_ALIGNMENT; + textArea->obj.alignmentMarginX = BORDER_MARGIN; + textArea->obj.alignmentMarginY = 24; + // set this new obj as child of main container + layoutAddObject(layoutInt, (nbgl_obj_t *) textArea); + + // create info on the bottom + textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); + textArea->textColor = DARK_GRAY; + textArea->text = PIC(info); + textArea->fontId = SMALL_REGULAR_FONT; + textArea->style = NO_STYLE; + textArea->wrapping = true; + textArea->obj.area.width = AVAILABLE_WIDTH; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); + textArea->textAlignment = MID_LEFT; + textArea->obj.alignment = BOTTOM_LEFT; + textArea->obj.alignmentMarginX = BORDER_MARGIN; + textArea->obj.alignmentMarginY = 40; + // set this new obj as child of main container + layoutAddObject(layoutInt, (nbgl_obj_t *) textArea); + + return layoutInt->container->obj.area.height; +} + /** * @brief Creates a list of radio buttons (on the right) * @@ -1699,7 +1778,8 @@ int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueL for (i = 0; i < list->nbPairs; i++) { const nbgl_layoutTagValue_t *pair; - uint16_t fullHeight = 0, usableWidth; + uint16_t fullHeight = 0; + const nbgl_icon_details_t *valueIcon = NULL; if (list->pairs != NULL) { pair = &list->pairs[i]; @@ -1707,8 +1787,6 @@ int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueL else { pair = list->callback(list->startIndex + i); } - // width that can be used for item and text - usableWidth = AVAILABLE_WIDTH; container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); @@ -1725,9 +1803,9 @@ int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueL itemTextArea->textAlignment = MID_LEFT; itemTextArea->fontId = SMALL_REGULAR_FONT; itemTextArea->wrapping = true; - itemTextArea->obj.area.width = usableWidth; + itemTextArea->obj.area.width = AVAILABLE_WIDTH; itemTextArea->obj.area.height = nbgl_getTextHeightInWidth( - itemTextArea->fontId, itemTextArea->text, usableWidth, itemTextArea->wrapping); + itemTextArea->fontId, itemTextArea->text, AVAILABLE_WIDTH, itemTextArea->wrapping); itemTextArea->style = NO_STYLE; itemTextArea->obj.alignment = NO_ALIGNMENT; itemTextArea->obj.alignmentMarginX = 0; @@ -1748,19 +1826,28 @@ int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueL else { valueTextArea->fontId = LARGE_MEDIUM_FONT; } - if (pair->valueIcon == NULL) { - valueTextArea->obj.area.width = usableWidth; + if ((pair->aliasValue == 0) && (pair->valueIcon == NULL)) { + valueTextArea->obj.area.width = AVAILABLE_WIDTH; } else { - // we assume that value is single line - valueTextArea->obj.area.width - = nbgl_getTextWidth(valueTextArea->fontId, valueTextArea->text); + if (pair->aliasValue) { + // if the value is an alias, we automatically display a (>) icon + valueIcon = &MINI_PUSH_ICON; + } + else { + // otherwise use the provided icon + valueIcon = PIC(pair->valueIcon); + } + // decrease the available width for value text + valueTextArea->obj.area.width = AVAILABLE_WIDTH - valueIcon->width - 12; } // handle the nbMaxLinesForValue parameter, used to automatically keep only // nbMaxLinesForValue lines - uint16_t nbLines = nbgl_getTextNbLinesInWidth( - valueTextArea->fontId, valueTextArea->text, usableWidth, list->wrapping); + uint16_t nbLines = nbgl_getTextNbLinesInWidth(valueTextArea->fontId, + valueTextArea->text, + valueTextArea->obj.area.width, + list->wrapping); // use this nbMaxLinesForValue parameter only if >0 if ((list->nbMaxLinesForValue > 0) && (nbLines > list->nbMaxLinesForValue)) { nbLines = list->nbMaxLinesForValue; @@ -1777,23 +1864,24 @@ int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueL container->nbChildren++; fullHeight += valueTextArea->obj.area.height + valueTextArea->obj.alignmentMarginY; - if (pair->valueIcon != NULL) { + if (valueIcon != NULL) { nbgl_image_t *image = (nbgl_image_t *) nbgl_objPoolGet(IMAGE, layoutInt->layer); layoutObj_t *obj = layoutAddCallbackObj( layoutInt, (nbgl_obj_t *) image, list->token, TUNE_TAP_CASUAL); obj->index = i; image->foregroundColor = BLACK; - image->buffer = PIC(pair->valueIcon); - image->obj.alignment = MID_RIGHT; - image->obj.alignmentMarginX = 4; + image->buffer = valueIcon; + image->obj.alignment = RIGHT_TOP; + image->obj.alignmentMarginX = 12; image->obj.alignTo = (nbgl_obj_t *) valueTextArea; image->obj.touchMask = (1 << TOUCHED); + image->obj.touchId = VALUE_BUTTON_1_ID + i; container->children[container->nbChildren] = (nbgl_obj_t *) image; container->nbChildren++; } - container->obj.area.width = usableWidth; + container->obj.area.width = AVAILABLE_WIDTH; container->obj.area.height = fullHeight; container->layout = VERTICAL; container->obj.alignmentMarginX = BORDER_MARGIN; @@ -2372,7 +2460,7 @@ int nbgl_layoutAddHeader(nbgl_layout_t *layout, const nbgl_layoutHeader_t *heade textArea->fontId = SMALL_BOLD_FONT; textArea->textAlignment = CENTER; textArea->obj.touchMask = (1 << TOUCHED); - textArea->obj.touchId = RIGHT_BUTTON_ID; + textArea->obj.touchId = TOP_RIGHT_BUTTON_ID; // add to bottom container layoutInt->headerContainer->children[layoutInt->headerContainer->nbChildren] = (nbgl_obj_t *) textArea; diff --git a/lib_nbgl/src/nbgl_use_case.c b/lib_nbgl/src/nbgl_use_case.c index e239f0358..121d4c7fd 100644 --- a/lib_nbgl/src/nbgl_use_case.c +++ b/lib_nbgl/src/nbgl_use_case.c @@ -62,7 +62,8 @@ enum { CHOICE_TOKEN, DETAILS_BUTTON_TOKEN, CONFIRM_TOKEN, - REJECT_TOKEN + REJECT_TOKEN, + VALUE_ALIAS_TOKEN }; typedef enum { @@ -107,6 +108,12 @@ typedef struct { const char *detailsItem; const char *detailsvalue; bool detailsWrapping; + const nbgl_contentTagValue_t + *currentPairs; // to be used to retrieve the pairs with value alias + nbgl_contentTagValueCallback_t + currentCallback; // to be used to retrieve the pairs with value alias + + nbgl_layout_t modalLayout; } GenericContext_t; typedef struct { @@ -226,6 +233,7 @@ static char reducedAddress[QRCODE_REDUCED_ADDR_LEN]; **********************/ static void displayReviewPage(uint8_t page, bool forceFullRefresh); static void displayDetailsPage(uint8_t page, bool forceFullRefresh); +static void displayFullValuePage(const nbgl_contentTagValue_t *pair); static void displaySettingsPage(uint8_t page, bool forceFullRefresh); static void displayGenericContextPage(uint8_t pageIdx, bool forceFullRefresh); static void pageCallback(int token, uint8_t index); @@ -233,6 +241,7 @@ static void pageCallback(int token, uint8_t index); static void displayAddressQRCode(void); static void addressLayoutTouchCallbackQR(int token, uint8_t index); #endif // NBGL_QRCODE +static void modalLayoutTouchCallback(int token, uint8_t index); static void displaySkipWarning(void); static void bundleNavStartHome(void); @@ -543,6 +552,17 @@ static void pageCallback(int token, uint8_t index) // display a modal warning to confirm skip displaySkipWarning(); } + else if (token == VALUE_ALIAS_TOKEN) { + // the icon next to value alias has been touched + const nbgl_contentTagValue_t *pair; + if (genericContext.currentPairs != NULL) { + pair = &genericContext.currentPairs[genericContext.currentElementIdx + index]; + } + else { + pair = genericContext.currentCallback(genericContext.currentElementIdx + index); + } + displayFullValuePage(pair); + } else { // probably a control provided by caller if (onContentAction != NULL) { onContentAction(token, index, navInfo.activePage); @@ -797,6 +817,10 @@ static bool genericContextPreparePageContent(const nbgl_content_t *p_content, case TAG_VALUE_LIST: { nbgl_contentTagValueList_t *p_tagValueList = &pageContent->tagValueList; + // memorize pairs (or callback) for usage when alias is used + genericContext.currentPairs = p_content->content.tagValueList.pairs; + genericContext.currentCallback = p_content->content.tagValueList.callback; + if (flag) { // Flag can be set if the pair is too long to fit or because it needs // to be displayed as centered info. @@ -805,12 +829,10 @@ static bool genericContextPreparePageContent(const nbgl_content_t *p_content, const nbgl_layoutTagValue_t *pair; if (p_content->content.tagValueList.pairs != NULL) { - pair = PIC( - &p_content->content.tagValueList.pairs[genericContext.currentElementIdx]); + pair = PIC(&p_content->content.tagValueList.pairs[nextElementIdx]); } else { - pair = PIC( - p_content->content.tagValueList.callback(genericContext.currentElementIdx)); + pair = PIC(p_content->content.tagValueList.callback(nextElementIdx)); } if (pair->centeredInfo) { @@ -843,14 +865,31 @@ static bool genericContextPreparePageContent(const nbgl_content_t *p_content, if (p_tagValueList != NULL) { p_tagValueList->nbPairs = nbElementsInPage; + p_tagValueList->token = p_content->content.tagValueList.token; if (p_content->content.tagValueList.pairs != NULL) { p_tagValueList->pairs = PIC(&p_content->content.tagValueList.pairs[nextElementIdx]); + // parse pairs to check if any contains an alias for value + for (uint8_t i = 0; i < nbElementsInPage; i++) { + if (p_tagValueList->pairs[i].aliasValue) { + p_tagValueList->token = VALUE_ALIAS_TOKEN; + break; + } + } } else { p_tagValueList->pairs = NULL; p_tagValueList->callback = p_content->content.tagValueList.callback; p_tagValueList->startIndex = nextElementIdx; + // parse pairs to check if any contains an alias for value + for (uint8_t i = 0; i < nbElementsInPage; i++) { + const nbgl_layoutTagValue_t *pair + = PIC(p_content->content.tagValueList.callback(nextElementIdx + i)); + if (pair->aliasValue) { + p_tagValueList->token = VALUE_ALIAS_TOKEN; + break; + } + } } p_tagValueList->smallCaseForValue = false; p_tagValueList->nbMaxLinesForValue = NB_MAX_LINES_IN_REVIEW; @@ -1080,6 +1119,45 @@ static void displayDetailsPage(uint8_t detailsPage, bool forceFullRefresh) } } +// function used to display the content of a full value, when touching an alias of a tag/value pair +static void displayFullValuePage(const nbgl_contentTagValue_t *pair) +{ + nbgl_layoutDescription_t layoutDescription = {.modal = true, + .withLeftBorder = true, + .onActionCallback = &modalLayoutTouchCallback, + .tapActionText = NULL}; + nbgl_layoutHeader_t headerDesc = {.type = HEADER_BACK_AND_TEXT, + .separationLine = false, + .backAndText.token = 0, + .backAndText.tuneId = TUNE_TAP_CASUAL, + .backAndText.text = PIC(pair->item)}; + const char *info; + genericContext.modalLayout = nbgl_layoutGet(&layoutDescription); + // add header with the tag part of the pair, to go back + nbgl_layoutAddHeader(genericContext.modalLayout, &headerDesc); + // add full value text + if (pair->extension->explanation == NULL) { + if (pair->extension->aliasType == ENS_ALIAS) { + info = "ENS names are resolved by Ledger backend."; + } + else if (pair->extension->aliasType == ADDRESS_BOOK_ALIAS) { + info = "This account label comes from your Address Book in Ledger Live."; + } + else { + info = ""; + } + } + else { + info = pair->extension->explanation; + } + nbgl_layoutAddTextContent( + genericContext.modalLayout, pair->value, pair->extension->fullValue, info); + + // draw & refresh + nbgl_layoutDraw(genericContext.modalLayout); + nbgl_refresh(); +} + #ifdef NBGL_QRCODE static void displayAddressQRCode(void) { @@ -1141,6 +1219,18 @@ static void addressLayoutTouchCallbackQR(int token, uint8_t index) } #endif // NBGL_QRCODE +// called when header is touched on modal page, to dismiss it +static void modalLayoutTouchCallback(int token, uint8_t index) +{ + UNUSED(token); + UNUSED(index); + + // dismiss modal + nbgl_layoutRelease(genericContext.modalLayout); + nbgl_screenRedraw(); + nbgl_refresh(); +} + // called when skip button is touched in footer, during forward only review static void displaySkipWarning(void) { @@ -1503,7 +1593,7 @@ static void bundleNavReviewStreamingChoice(bool confirm) { if (confirm) { // Display a spinner if it wasn't the finish step - if (localContentsList[0].type != INFO_LONG_PRESS) { + if (STARTING_CONTENT.type != INFO_LONG_PRESS) { nbgl_useCaseSpinner("Processing"); } bundleNavContext.reviewStreaming.choiceCallback(true); @@ -2446,15 +2536,16 @@ void nbgl_useCaseReview(nbgl_operationType_t operationType, memset(localContentsList, 0, 3 * sizeof(nbgl_content_t)); // First a centered info - localContentsList[0].type = CENTERED_INFO; + STARTING_CONTENT.type = CENTERED_INFO; prepareReviewFirstPage( - &localContentsList[0].content.centeredInfo, icon, reviewTitle, reviewSubTitle); + &STARTING_CONTENT.content.centeredInfo, icon, reviewTitle, reviewSubTitle); // Then the tag/value pairs localContentsList[1].type = TAG_VALUE_LIST; memcpy(&localContentsList[1].content.tagValueList, tagValueList, sizeof(nbgl_contentTagValueList_t)); + localContentsList[1].contentActionCallback = tagValueList->actionCallback; // Eventually the long press page localContentsList[2].type = INFO_LONG_PRESS; @@ -2508,9 +2599,9 @@ void nbgl_useCaseReviewLight(nbgl_operationType_t operationType, memset(localContentsList, 0, 3 * sizeof(nbgl_content_t)); // First a centered info - localContentsList[0].type = CENTERED_INFO; + STARTING_CONTENT.type = CENTERED_INFO; prepareReviewFirstPage( - &localContentsList[0].content.centeredInfo, icon, reviewTitle, reviewSubTitle); + &STARTING_CONTENT.content.centeredInfo, icon, reviewTitle, reviewSubTitle); // Then the tag/value pairs localContentsList[1].type = TAG_VALUE_LIST; @@ -2599,9 +2690,9 @@ void nbgl_useCaseReviewStreamingStart(nbgl_operationType_t operationType, memset(localContentsList, 0, 1 * sizeof(nbgl_content_t)); // First a centered info - localContentsList[0].type = CENTERED_INFO; + STARTING_CONTENT.type = CENTERED_INFO; prepareReviewFirstPage( - &localContentsList[0].content.centeredInfo, icon, reviewTitle, reviewSubTitle); + &STARTING_CONTENT.content.centeredInfo, icon, reviewTitle, reviewSubTitle); // compute number of pages & fill navigation structure bundleNavContext.reviewStreaming.stepPageNb @@ -2653,10 +2744,9 @@ void nbgl_useCaseReviewStreamingContinueExt(const nbgl_contentTagValueList_t *ta memset(localContentsList, 0, 1 * sizeof(nbgl_content_t)); // Then the tag/value pairs - localContentsList[0].type = TAG_VALUE_LIST; - memcpy(&localContentsList[0].content.tagValueList, - tagValueList, - sizeof(nbgl_contentTagValueList_t)); + STARTING_CONTENT.type = TAG_VALUE_LIST; + memcpy( + &STARTING_CONTENT.content.tagValueList, tagValueList, sizeof(nbgl_contentTagValueList_t)); // compute number of pages & fill navigation structure bundleNavContext.reviewStreaming.stepPageNb @@ -2721,8 +2811,8 @@ void nbgl_useCaseReviewStreamingFinish(const char *finishTitle, memset(localContentsList, 0, 1 * sizeof(nbgl_content_t)); // Eventually the long press page - localContentsList[0].type = INFO_LONG_PRESS; - prepareReviewLastPage(&localContentsList[0].content.infoLongPress, + STARTING_CONTENT.type = INFO_LONG_PRESS; + prepareReviewLastPage(&STARTING_CONTENT.content.infoLongPress, bundleNavContext.reviewStreaming.icon, finishTitle); @@ -2816,7 +2906,7 @@ void nbgl_useCaseAddressConfirmationExt(const char *addres genericContext.genericContents.nbContents = (tagValueList == NULL) ? 1 : 2; memset(localContentsList, 0, 2 * sizeof(nbgl_content_t)); prepareAddressConfirmationPages( - address, tagValueList, &localContentsList[0], &localContentsList[1]); + address, tagValueList, &STARTING_CONTENT, &localContentsList[1]); // fill navigation structure, common to all pages uint8_t nbPages = nbgl_useCaseGetNbPagesForGenericContents(&genericContext.genericContents, 0); @@ -2867,9 +2957,9 @@ void nbgl_useCaseAddressReview(const char *address, memset(localContentsList, 0, 3 * sizeof(nbgl_content_t)); // First a centered info - localContentsList[0].type = CENTERED_INFO; + STARTING_CONTENT.type = CENTERED_INFO; prepareReviewFirstPage( - &localContentsList[0].content.centeredInfo, icon, reviewTitle, reviewSubTitle); + &STARTING_CONTENT.content.centeredInfo, icon, reviewTitle, reviewSubTitle); // Then the address confirmation pages prepareAddressConfirmationPages(