Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incrementing spinner Use Case when called multiple times #849

Merged
merged 1 commit into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion lib_nbgl/include/nbgl_layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ extern "C" {

#endif // HAVE_SE_TOUCH

#define SPINNER_FIXED 0xFF ///< position to use for a "fixed" spinner

/**********************
* TYPEDEFS
**********************/
Expand Down Expand Up @@ -655,7 +657,14 @@ int nbgl_layoutAddProgressIndicator(nbgl_layout_t *layout,
bool withBack,
uint8_t backToken,
tune_index_e tuneId);
int nbgl_layoutAddSpinner(nbgl_layout_t *layout, const char *text, const char *subText, bool fixed);
int nbgl_layoutAddSpinner(nbgl_layout_t *layout,
const char *text,
const char *subText,
uint8_t initPosition);
int nbgl_layoutUpdateSpinner(nbgl_layout_t *layout,
const char *text,
const char *subText,
uint8_t position);
int nbgl_layoutAddSwipe(nbgl_layout_t *layout,
uint16_t swipesMask,
const char *text,
Expand Down
3 changes: 3 additions & 0 deletions lib_nbgl/include/nbgl_obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ extern "C" {
// max number of pages when nbgl_page_indicator_t uses dashes (above, it uses n / nb_pages)
#define NB_MAX_PAGES_WITH_DASHES 6

// number of spinner positions
#define NB_SPINNER_POSITIONS 4

/**********************
* TYPEDEFS
**********************/
Expand Down
2 changes: 1 addition & 1 deletion lib_nbgl/include/nbgl_page.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ nbgl_page_t *nbgl_pageDrawLedgerInfo(nbgl_layoutTouchCallback_t onA
const nbgl_screenTickerConfiguration_t *ticker,
const char *text,
int tapActionToken);
nbgl_page_t *nbgl_pageDrawSpinner(nbgl_layoutTouchCallback_t onActionCallback, const char *text);
nbgl_page_t *nbgl_pageDrawSpinner(const char *text, uint8_t initPosition);
nbgl_page_t *nbgl_pageDrawInfo(nbgl_layoutTouchCallback_t onActionCallback,
const nbgl_screenTickerConfiguration_t *ticker,
const nbgl_pageInfoDescription_t *info);
Expand Down
100 changes: 94 additions & 6 deletions lib_nbgl/src/nbgl_layout.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,10 +450,13 @@ static void spinnerTickerCallback(void)
while (i < layout->container->nbChildren) {
if (layout->container->children[i]->type == CONTAINER) {
nbgl_container_t *container = (nbgl_container_t *) layout->container->children[i];
if (container->children[0]->type == SPINNER) {
if (container->nbChildren && (container->children[0]->type == SPINNER)) {
spinner = (nbgl_spinner_t *) container->children[0];
spinner->position++;
spinner->position &= 3; // modulo 4
// there are only NB_SPINNER_POSITIONS positions
if (spinner->position == NB_SPINNER_POSITIONS) {
spinner->position = 0;
}
nbgl_objDraw((nbgl_obj_t *) spinner);
nbgl_refreshSpecial(BLACK_AND_WHITE_FAST_REFRESH);
return;
Expand Down Expand Up @@ -3487,10 +3490,14 @@ int nbgl_layoutAddProgressIndicator(nbgl_layout_t *layout,
* @param layout the current layout
* @param text text to draw under the spinner
* @param subText text to draw under the text (can be NULL)
* @param fixed if set to true, the spinner won't spin and be entirely black
* @param initPosition if set to any value expect @ref SPINNER_FIXED, it will be used as the init
* position of the spinner
* @return >= 0 if OK
*/
int nbgl_layoutAddSpinner(nbgl_layout_t *layout, const char *text, const char *subText, bool fixed)
int nbgl_layoutAddSpinner(nbgl_layout_t *layout,
const char *text,
const char *subText,
uint8_t initPosition)
{
nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
nbgl_container_t *container;
Expand All @@ -3513,7 +3520,7 @@ int nbgl_layoutAddSpinner(nbgl_layout_t *layout, const char *text, const char *s

// create spinner
spinner = (nbgl_spinner_t *) nbgl_objPoolGet(SPINNER, layoutInt->layer);
spinner->position = fixed ? 0xFF : 0;
spinner->position = initPosition;
spinner->obj.alignment = TOP_MIDDLE;
// set this new spinner as child of the container
container->children[0] = (nbgl_obj_t *) spinner;
Expand Down Expand Up @@ -3578,7 +3585,7 @@ int nbgl_layoutAddSpinner(nbgl_layout_t *layout, const char *text, const char *s
}
layoutAddObject(layoutInt, (nbgl_obj_t *) container);

if (!fixed) {
if (initPosition != SPINNER_FIXED) {
// update ticker to update the spinner periodically
nbgl_screenTickerConfiguration_t tickerCfg;

Expand All @@ -3591,6 +3598,87 @@ int nbgl_layoutAddSpinner(nbgl_layout_t *layout, const char *text, const char *s
return 0;
}

/**
* @brief Update an existing spinner (must be the only object of the layout)
*
* @param layout the current layout
* @param text text to draw under the spinner
* @param subText text to draw under the text (can be NULL)
* @param initPosition position of the spinner (cannot be fixed)
* @return - 0 if no refresh needed
* - 1 if partial B&W refresh needed
* - 2 if partial color refresh needed
*/
int nbgl_layoutUpdateSpinner(nbgl_layout_t *layout,
const char *text,
const char *subText,
uint8_t position)
{
nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
nbgl_container_t *container;
nbgl_text_area_t *textArea;
nbgl_spinner_t *spinner;
int ret = 0;

LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateSpinner():\n");
if ((layout == NULL) || (layoutInt->container->nbChildren == 0)) {
return -1;
}

container = (nbgl_container_t *) layoutInt->container->children[0];
if ((container->obj.type != CONTAINER) || (container->nbChildren < 2)) {
return -1;
}

spinner = (nbgl_spinner_t *) container->children[0];
if (spinner->obj.type != SPINNER) {
return -1;
}
// if position is different, redraw
if (spinner->position != position) {
spinner->position = position;
nbgl_objDraw((nbgl_obj_t *) spinner);
ret = 1;
}

// update text area if necessary
textArea = (nbgl_text_area_t *) container->children[1];
if (textArea->obj.type != TEXT_AREA) {
return -1;
}
const char *newText = PIC(text);
size_t newTextLen = strlen(newText);
// if text is different, redraw (don't use strcmp because it crashes with Rust SDK)
if ((newTextLen != strlen(textArea->text)) || memcmp(textArea->text, newText, newTextLen)) {
textArea->text = newText;
nbgl_objDraw((nbgl_obj_t *) textArea);
ret = 2;
}

if (subText != NULL) {
nbgl_text_area_t *subTextArea;

if (container->nbChildren != 3) {
return -1;
}
subTextArea = (nbgl_text_area_t *) container->children[2];
if (subTextArea->obj.type != TEXT_AREA) {
return -1;
}
const char *newSubText = PIC(subText);
size_t newSubTextLen = strlen(newSubText);
// if text is different, redraw
if ((newSubTextLen != strlen(subTextArea->text))
|| memcmp(subTextArea->text, newSubText, newSubTextLen)) {
subTextArea->text = newSubText;
nbgl_objDraw((nbgl_obj_t *) subTextArea);
ret = 2;
}
}

return ret;
}

/**
* @brief Applies given layout. The screen will be redrawn
*
Expand Down
16 changes: 6 additions & 10 deletions lib_nbgl/src/nbgl_page.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,25 +292,21 @@ nbgl_page_t *nbgl_pageDrawLedgerInfo(nbgl_layoutTouchCallback_t onA
* @brief draw a spinner page with the given parameters. The spinner will "rotate" automatically
* every 800 ms
*
* @param onActionCallback common callback for all actions on this page (unused, so set to NULL)
* @param text text to use under spinner
* @param initPosition if set to any value expect @ref SPINNER_FIXED, it will be used as the init
* position of the spinner
* @return the page context (or NULL if error)
*/
nbgl_page_t *nbgl_pageDrawSpinner(nbgl_layoutTouchCallback_t onActionCallback, const char *text)
nbgl_page_t *nbgl_pageDrawSpinner(const char *text, uint8_t initPosition)
{
nbgl_layoutDescription_t layoutDescription;
nbgl_layoutDescription_t layoutDescription = {0};
nbgl_layout_t *layout;

layoutDescription.modal = false;
layoutDescription.withLeftBorder = true;

layoutDescription.onActionCallback = onActionCallback;
layoutDescription.tapActionText = NULL;

layoutDescription.ticker.tickerCallback = NULL;
layout = nbgl_layoutGet(&layoutDescription);
layout = nbgl_layoutGet(&layoutDescription);

nbgl_layoutAddSpinner(layout, text, NULL, false);
nbgl_layoutAddSpinner(layout, text, NULL, initPosition);

nbgl_layoutDraw(layout);

Expand Down
49 changes: 44 additions & 5 deletions lib_nbgl/src/nbgl_use_case.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,14 @@ typedef union {
ReviewWithWarningContext_t reviewWithWarning;
} SharedContext_t;

typedef enum {
USE_CASE_GENERIC = 0,
USE_CASE_SPINNER
} GenericContextType_t;

typedef struct {
GenericContextType_t type; // type of Generic context usage
uint8_t spinnerPosition;
nbgl_genericContents_t genericContents;
int8_t currentContentIdx;
uint8_t currentContentElementNb;
Expand All @@ -160,9 +167,9 @@ typedef struct {
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;
currentCallback; // to be used to retrieve the pairs with value alias
nbgl_layout_t modalLayout;
nbgl_layout_t backgroundLayout;
} GenericContext_t;

typedef struct {
Expand Down Expand Up @@ -3859,13 +3866,45 @@ void nbgl_useCaseAddressReview(const char *address,
/**
* @brief draw a spinner page with the given parameters. The spinner will "turn" automatically every
* 800 ms
* @note If called several time in a raw, it can be used to "turn" the corner, for example when
* used in a long mono-process, preventing the automatic update.
*
* @param text text to use under spinner
*/
void nbgl_useCaseSpinner(const char *text)
{
pageContext = nbgl_pageDrawSpinner(NULL, (const char *) text);
nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH);
// if the previous Use Case was not Spinner, fresh start
if (genericContext.type != USE_CASE_SPINNER) {
memset(&genericContext, 0, sizeof(genericContext));
genericContext.type = USE_CASE_SPINNER;
nbgl_layoutDescription_t layoutDescription = {0};

layoutDescription.withLeftBorder = true;

genericContext.backgroundLayout = nbgl_layoutGet(&layoutDescription);

nbgl_layoutAddSpinner(
genericContext.backgroundLayout, text, NULL, genericContext.spinnerPosition);

nbgl_layoutDraw(genericContext.backgroundLayout);
nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH);
}
else {
// otherwise increment spinner
genericContext.spinnerPosition++;
// there are only NB_SPINNER_POSITIONSpositions
if (genericContext.spinnerPosition == NB_SPINNER_POSITIONS) {
genericContext.spinnerPosition = 0;
}
int ret = nbgl_layoutUpdateSpinner(
genericContext.backgroundLayout, text, NULL, genericContext.spinnerPosition);
if (ret == 1) {
nbgl_refreshSpecial(BLACK_AND_WHITE_FAST_REFRESH);
}
else if (ret == 2) {
nbgl_refreshSpecial(FULL_COLOR_PARTIAL_REFRESH);
}
}
}

#ifdef NBGL_KEYPAD
Expand Down