Use callback to get tag/value pairs
This commit is contained in:
committed by
Clement Bouvet
parent
631f295a51
commit
1f6cb4cb37
+133
-112
@@ -6,13 +6,23 @@
|
||||
#include "network.h"
|
||||
#include "plugins.h"
|
||||
|
||||
#define MAX_PLUGIN_ITEMS_PER_SCREEN 3
|
||||
// 1 more than actually displayed on screen, because of calculations in StaticReview
|
||||
#define MAX_PLUGIN_ITEMS_PER_SCREEN 4
|
||||
#define TAG_MAX_LEN 43
|
||||
#define VALUE_MAX_LEN 79
|
||||
enum {
|
||||
REJECT_TOKEN,
|
||||
START_REVIEW_TOKEN,
|
||||
};
|
||||
|
||||
static nbgl_layoutTagValue_t tlv[MAX_PLUGIN_ITEMS_PER_SCREEN];
|
||||
static char title_buffer[MAX_PLUGIN_ITEMS_PER_SCREEN][43];
|
||||
static char msg_buffer[MAX_PLUGIN_ITEMS_PER_SCREEN][79];
|
||||
static nbgl_layoutTagValue_t tlv;
|
||||
// these buffers are used as circular
|
||||
static char title_buffer[MAX_PLUGIN_ITEMS_PER_SCREEN][TAG_MAX_LEN];
|
||||
static char msg_buffer[MAX_PLUGIN_ITEMS_PER_SCREEN][VALUE_MAX_LEN];
|
||||
|
||||
static nbgl_layoutTagValueList_t useCaseTagValueList;
|
||||
static nbgl_pageInfoLongPress_t infoLongPress;
|
||||
|
||||
static uint8_t pageCount = 0;
|
||||
struct tx_approval_context_t {
|
||||
bool fromPlugin;
|
||||
bool blindSigning;
|
||||
@@ -21,6 +31,8 @@ struct tx_approval_context_t {
|
||||
|
||||
static struct tx_approval_context_t tx_approval_context;
|
||||
|
||||
static void reviewContinueCommon(void);
|
||||
|
||||
|
||||
static void reviewReject(void) {
|
||||
io_seproxyhal_touch_tx_cancel(NULL);
|
||||
@@ -40,133 +52,142 @@ static void reviewChoice(bool confirm) {
|
||||
}
|
||||
}
|
||||
|
||||
static void buildBlindSignWarningPage(nbgl_pageContent_t *content) {
|
||||
content->type = CENTERED_INFO;
|
||||
content->centeredInfo.icon = &C_icon_warning;
|
||||
content->centeredInfo.text1 = "Blind Signing";
|
||||
content->centeredInfo.style = LARGE_CASE_INFO;
|
||||
}
|
||||
|
||||
static void buildRegularTransactionInfoAmountPage(nbgl_pageContent_t *content) {
|
||||
tlv[0].item = "Amount";
|
||||
tlv[1].item = "Address";
|
||||
tlv[2].item = "Nonce";
|
||||
|
||||
tlv[0].value = strings.common.fullAmount;
|
||||
tlv[1].value = strings.common.fullAddress;
|
||||
tlv[2].value = strings.common.nonce;
|
||||
|
||||
content->type = TAG_VALUE_LIST;
|
||||
content->tagValueList.nbPairs = N_storage.displayNonce ? 3 : 2;
|
||||
content->tagValueList.pairs = (nbgl_layoutTagValue_t *)tlv;
|
||||
}
|
||||
|
||||
static void buildRegularTransactionInfoAddressPage(nbgl_pageContent_t *content) {
|
||||
tlv[0].item = "Max fees";
|
||||
tlv[1].item = "Network";
|
||||
|
||||
tlv[0].value = strings.common.maxFee;
|
||||
tlv[1].value = strings.common.network_name;
|
||||
|
||||
content->type = TAG_VALUE_LIST;
|
||||
content->tagValueList.nbPairs = tx_approval_context.displayNetwork ? 2 : 1;
|
||||
content->tagValueList.pairs = (nbgl_layoutTagValue_t *)tlv;
|
||||
}
|
||||
|
||||
static void buildRegularTransactionInfoConfirm(nbgl_pageContent_t *content) {
|
||||
content->type = INFO_LONG_PRESS,
|
||||
content->infoLongPress.icon = &C_badge_transaction_56;
|
||||
content->infoLongPress.text = "Review transaction";
|
||||
content->infoLongPress.longPressText = "Hold to confirm";
|
||||
}
|
||||
|
||||
static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) {
|
||||
if (tx_approval_context.blindSigning) {
|
||||
if (page == 0) {
|
||||
buildBlindSignWarningPage(content);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
page++;
|
||||
}
|
||||
// called by NBGL to get the tag/value pair corresponding to pairIndex
|
||||
static nbgl_layoutTagValue_t* getTagValuePair(uint8_t pairIndex) {
|
||||
static int counter = 0;
|
||||
|
||||
if (tx_approval_context.fromPlugin) {
|
||||
if (page == 1) {
|
||||
if (pairIndex == 0) {
|
||||
// the first page is an exception because the first tag/value pair is the id
|
||||
plugin_ui_get_id();
|
||||
tlv[0].item = strings.common.fullAddress;
|
||||
tlv[0].value = strings.common.fullAmount;
|
||||
|
||||
content->type = TAG_VALUE_LIST;
|
||||
content->tagValueList.nbPairs = 1;
|
||||
content->tagValueList.pairs = (nbgl_layoutTagValue_t *)tlv;
|
||||
|
||||
return true;
|
||||
tlv.item = strings.common.fullAddress;
|
||||
tlv.value = strings.common.fullAmount;
|
||||
}
|
||||
else if (page < pageCount - 1) {
|
||||
uint8_t count = 0;
|
||||
for (
|
||||
dataContext.tokenContext.pluginUiCurrentItem = (page - 2) * MAX_PLUGIN_ITEMS_PER_SCREEN;
|
||||
dataContext.tokenContext.pluginUiCurrentItem < (page - 1) * MAX_PLUGIN_ITEMS_PER_SCREEN && dataContext.tokenContext.pluginUiCurrentItem < dataContext.tokenContext.pluginUiMaxItems;
|
||||
dataContext.tokenContext.pluginUiCurrentItem++, count++
|
||||
) {
|
||||
plugin_ui_get_item_internal(
|
||||
title_buffer[count],
|
||||
sizeof(title_buffer[0]),
|
||||
msg_buffer[count],
|
||||
sizeof(msg_buffer[0])
|
||||
);
|
||||
tlv[count].item = title_buffer[count];
|
||||
tlv[count].value = msg_buffer[count];
|
||||
else if (pairIndex <= dataContext.tokenContext.pluginUiMaxItems) {
|
||||
// for the next dataContext.tokenContext.pluginUiMaxItems items, get tag/value from plugin_ui_get_item_internal()
|
||||
dataContext.tokenContext.pluginUiCurrentItem = pairIndex-1;
|
||||
plugin_ui_get_item_internal(
|
||||
(uint8_t *)title_buffer[counter],
|
||||
TAG_MAX_LEN,
|
||||
(uint8_t *)msg_buffer[counter],
|
||||
VALUE_MAX_LEN
|
||||
);
|
||||
tlv.item = title_buffer[counter];
|
||||
tlv.value = msg_buffer[counter];
|
||||
}
|
||||
else {
|
||||
// for the last 1 (or 2), tags are fixed
|
||||
if (tx_approval_context.displayNetwork && (pairIndex == (dataContext.tokenContext.pluginUiMaxItems+2))) {
|
||||
tlv.item = "Network";
|
||||
tlv.value = strings.common.network_name;
|
||||
}
|
||||
else {
|
||||
tlv.item = "Max fees";
|
||||
tlv.value = strings.common.maxFee;
|
||||
}
|
||||
content->type = TAG_VALUE_LIST;
|
||||
content->tagValueList.pairs = (nbgl_layoutTagValue_t *)tlv;
|
||||
content->tagValueList.nbPairs = count;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (page == pageCount - 1) {
|
||||
buildRegularTransactionInfoAddressPage(content);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
buildRegularTransactionInfoConfirm(content);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (page == 1) {
|
||||
buildRegularTransactionInfoAmountPage(content);
|
||||
return true;
|
||||
// if displayNonce is false, we skip index 2
|
||||
if ((pairIndex > 1) && (!N_storage.displayNonce)) {
|
||||
pairIndex++;
|
||||
}
|
||||
if (page == 2) {
|
||||
buildRegularTransactionInfoAddressPage(content);
|
||||
return true;
|
||||
}
|
||||
if (page == 3) {
|
||||
buildRegularTransactionInfoConfirm(content);
|
||||
return true;
|
||||
switch (pairIndex) {
|
||||
case 0:
|
||||
tlv.item = "Amount";
|
||||
tlv.value = strings.common.fullAmount;
|
||||
break;
|
||||
case 1:
|
||||
tlv.item = "Address";
|
||||
tlv.value = strings.common.fullAddress;
|
||||
break;
|
||||
case 2:
|
||||
tlv.item = "Nonce";
|
||||
tlv.value = strings.common.nonce;
|
||||
break;
|
||||
case 3:
|
||||
tlv.item = "Max fees";
|
||||
tlv.value = strings.common.maxFee;
|
||||
break;
|
||||
case 4:
|
||||
tlv.item = "Network";
|
||||
tlv.value = strings.common.network_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
// counter is used as index to circular buffer
|
||||
counter++;
|
||||
if (counter == MAX_PLUGIN_ITEMS_PER_SCREEN) {
|
||||
counter = 0;
|
||||
}
|
||||
return &tlv;
|
||||
}
|
||||
|
||||
static void pageCallback(int token, uint8_t index) {
|
||||
(void)index;
|
||||
nbgl_pageRelease(pageContext);
|
||||
if (token == REJECT_TOKEN) {
|
||||
reviewReject();
|
||||
}
|
||||
else if (token == START_REVIEW_TOKEN) {
|
||||
reviewContinueCommon();
|
||||
}
|
||||
}
|
||||
|
||||
static void reviewContinue(void) {
|
||||
pageCount = 0;
|
||||
|
||||
if (tx_approval_context.blindSigning) {
|
||||
pageCount++;
|
||||
nbgl_pageInfoDescription_t info = {
|
||||
.centeredInfo.icon = &C_icon_warning,
|
||||
.centeredInfo.text1 = "Blind Signing",
|
||||
.centeredInfo.text2 = NULL,
|
||||
.centeredInfo.text3 = NULL,
|
||||
.centeredInfo.style = LARGE_CASE_INFO,
|
||||
.centeredInfo.offsetY = -32,
|
||||
.footerText = "Reject transaction",
|
||||
.footerToken = REJECT_TOKEN,
|
||||
.tapActionText = "Tap to continue",
|
||||
.tapActionToken = START_REVIEW_TOKEN,
|
||||
.topRightStyle = NO_BUTTON_STYLE,
|
||||
.actionButtonText = NULL,
|
||||
.tuneId = TUNE_TAP_CASUAL
|
||||
};
|
||||
|
||||
if (pageContext != NULL) {
|
||||
nbgl_pageRelease(pageContext);
|
||||
pageContext = NULL;
|
||||
}
|
||||
pageContext = nbgl_pageDrawInfo(&pageCallback, NULL, &info);
|
||||
}
|
||||
else {
|
||||
reviewContinueCommon();
|
||||
}
|
||||
}
|
||||
|
||||
static void reviewContinueCommon(void) {
|
||||
uint8_t nbPairs = 0;
|
||||
|
||||
if (tx_approval_context.fromPlugin) {
|
||||
// plugin id + max items + fees + confirm
|
||||
pageCount += 1 + (dataContext.tokenContext.pluginUiMaxItems/MAX_PLUGIN_ITEMS_PER_SCREEN) + 1 + 1;
|
||||
if (dataContext.tokenContext.pluginUiMaxItems%MAX_PLUGIN_ITEMS_PER_SCREEN) {
|
||||
pageCount++;
|
||||
// plugin id + max items + fees
|
||||
nbPairs += 1 + dataContext.tokenContext.pluginUiMaxItems + 1;
|
||||
if (tx_approval_context.displayNetwork) {
|
||||
nbPairs ++;
|
||||
}
|
||||
} else {
|
||||
pageCount += 3;
|
||||
nbPairs += 4;
|
||||
if (N_storage.displayNonce) {
|
||||
nbPairs ++;
|
||||
}
|
||||
}
|
||||
nbgl_useCaseRegularReview(0, pageCount, "Reject", NULL, displayTransactionPage, reviewChoice);
|
||||
|
||||
useCaseTagValueList.pairs = NULL;
|
||||
useCaseTagValueList.callback = getTagValuePair;
|
||||
useCaseTagValueList.startIndex = 0;
|
||||
useCaseTagValueList.nbPairs = nbPairs; ///< number of pairs in pairs array
|
||||
useCaseTagValueList.smallCaseForValue = false;
|
||||
useCaseTagValueList.wrapping = false;
|
||||
infoLongPress.icon = &C_badge_transaction_56;
|
||||
infoLongPress.text = "Review transaction";
|
||||
infoLongPress.longPressText = "Hold to confirm";
|
||||
nbgl_useCaseStaticReview(&useCaseTagValueList, &infoLongPress, "Reject", reviewChoice);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ void ui_warning_contract_data(void) {
|
||||
},
|
||||
.footerText = NULL,
|
||||
.bottomButtonStyle = QUIT_ICON,
|
||||
.bottomButtonToken = OK_TOKEN,
|
||||
.bottomButtonsToken = OK_TOKEN,
|
||||
.tapActionText = NULL,
|
||||
.topRightStyle = NO_BUTTON_STYLE,
|
||||
.topRightToken = 0,
|
||||
|
||||
Reference in New Issue
Block a user