|
|
|
@@ -13,10 +13,15 @@
|
|
|
|
#include "ili9341.h"
|
|
|
|
#include "ili9341.h"
|
|
|
|
#include "lvgl.h"
|
|
|
|
#include "lvgl.h"
|
|
|
|
#include "mnemonic.h"
|
|
|
|
#include "mnemonic.h"
|
|
|
|
|
|
|
|
#include "secure_mem.h"
|
|
|
|
#include "touch.h"
|
|
|
|
#include "touch.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define UI_TICK_MS 2
|
|
|
|
#define UI_TICK_MS 2
|
|
|
|
#define UI_DRAW_LINES 20
|
|
|
|
#define UI_DRAW_LINES 20
|
|
|
|
|
|
|
|
#define UI_MNEMONIC_WORDS 12
|
|
|
|
|
|
|
|
#define UI_BIP39_WORD_MAX 9
|
|
|
|
|
|
|
|
#define UI_SUGGESTION_STORE_MAX 64
|
|
|
|
|
|
|
|
#define UI_SUGGESTION_VISIBLE_MAX 32
|
|
|
|
|
|
|
|
|
|
|
|
static const char *TAG = "ui_lvgl";
|
|
|
|
static const char *TAG = "ui_lvgl";
|
|
|
|
|
|
|
|
|
|
|
|
@@ -30,7 +35,21 @@ static bool s_done = false;
|
|
|
|
static bool s_have_mnemonic = false;
|
|
|
|
static bool s_have_mnemonic = false;
|
|
|
|
static char s_selected_mnemonic[256];
|
|
|
|
static char s_selected_mnemonic[256];
|
|
|
|
static lv_obj_t *s_status_label = NULL;
|
|
|
|
static lv_obj_t *s_status_label = NULL;
|
|
|
|
static lv_obj_t *s_entry_ta = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
static char s_committed_words[UI_MNEMONIC_WORDS][UI_BIP39_WORD_MAX];
|
|
|
|
|
|
|
|
static size_t s_word_count = 0;
|
|
|
|
|
|
|
|
static char s_prefix[UI_BIP39_WORD_MAX];
|
|
|
|
|
|
|
|
static size_t s_prefix_len = 0;
|
|
|
|
|
|
|
|
static bool s_checksum_override = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static lv_obj_t *s_entry_words_label = NULL;
|
|
|
|
|
|
|
|
static lv_obj_t *s_entry_prefix_label = NULL;
|
|
|
|
|
|
|
|
static lv_obj_t *s_suggestion_row = NULL;
|
|
|
|
|
|
|
|
static lv_obj_t *s_key_matrix = NULL;
|
|
|
|
|
|
|
|
static lv_obj_t *s_checksum_panel = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint16_t s_match_indices[UI_SUGGESTION_STORE_MAX];
|
|
|
|
|
|
|
|
static size_t s_match_total = 0;
|
|
|
|
|
|
|
|
|
|
|
|
static ui_approval_decision_t s_approval_decision = UI_APPROVAL_TIMEOUT;
|
|
|
|
static ui_approval_decision_t s_approval_decision = UI_APPROVAL_TIMEOUT;
|
|
|
|
static lv_obj_t *s_approval_countdown = NULL;
|
|
|
|
static lv_obj_t *s_approval_countdown = NULL;
|
|
|
|
@@ -41,6 +60,18 @@ static int64_t s_approval_deadline_us = 0;
|
|
|
|
static char s_event_lines[UI_EVENT_LOG_MAX][UI_EVENT_LINE_MAX];
|
|
|
|
static char s_event_lines[UI_EVENT_LOG_MAX][UI_EVENT_LINE_MAX];
|
|
|
|
static int s_event_count = 0;
|
|
|
|
static int s_event_count = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void reset_screen_widget_refs(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
s_status_label = NULL;
|
|
|
|
|
|
|
|
s_entry_words_label = NULL;
|
|
|
|
|
|
|
|
s_entry_prefix_label = NULL;
|
|
|
|
|
|
|
|
s_suggestion_row = NULL;
|
|
|
|
|
|
|
|
s_key_matrix = NULL;
|
|
|
|
|
|
|
|
s_checksum_panel = NULL;
|
|
|
|
|
|
|
|
s_approval_countdown = NULL;
|
|
|
|
|
|
|
|
s_match_total = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void style_screen(lv_obj_t *scr)
|
|
|
|
static void style_screen(lv_obj_t *scr)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);
|
|
|
|
lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);
|
|
|
|
@@ -62,31 +93,24 @@ static void style_button(lv_obj_t *btn)
|
|
|
|
lv_obj_set_style_text_color(btn, lv_color_hex(0xFF0000), LV_STATE_FOCUSED);
|
|
|
|
lv_obj_set_style_text_color(btn, lv_color_hex(0xFF0000), LV_STATE_FOCUSED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void style_text_area(lv_obj_t *ta)
|
|
|
|
static void style_key_matrix(lv_obj_t *km)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
lv_obj_set_style_bg_opa(ta, LV_OPA_COVER, 0);
|
|
|
|
lv_obj_set_style_bg_opa(km, LV_OPA_COVER, 0);
|
|
|
|
lv_obj_set_style_bg_color(ta, lv_color_hex(0x000000), 0);
|
|
|
|
lv_obj_set_style_bg_color(km, lv_color_hex(0x000000), 0);
|
|
|
|
lv_obj_set_style_border_width(ta, 2, 0);
|
|
|
|
lv_obj_set_style_border_width(km, 1, 0);
|
|
|
|
lv_obj_set_style_border_color(ta, lv_color_hex(0xFFFFFF), 0);
|
|
|
|
lv_obj_set_style_border_color(km, lv_color_hex(0xFFFFFF), 0);
|
|
|
|
lv_obj_set_style_text_color(ta, lv_color_hex(0xFFFFFF), 0);
|
|
|
|
|
|
|
|
lv_obj_set_style_text_color(ta, lv_color_hex(0xFF0000), LV_PART_CURSOR);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void style_keyboard(lv_obj_t *kb)
|
|
|
|
lv_obj_set_style_bg_opa(km, LV_OPA_COVER, LV_PART_ITEMS);
|
|
|
|
{
|
|
|
|
lv_obj_set_style_bg_color(km, lv_color_hex(0x000000), LV_PART_ITEMS);
|
|
|
|
lv_obj_set_style_bg_opa(kb, LV_OPA_COVER, 0);
|
|
|
|
lv_obj_set_style_border_color(km, lv_color_hex(0xFFFFFF), LV_PART_ITEMS);
|
|
|
|
lv_obj_set_style_bg_color(kb, lv_color_hex(0x000000), 0);
|
|
|
|
lv_obj_set_style_border_width(km, 1, LV_PART_ITEMS);
|
|
|
|
lv_obj_set_style_border_width(kb, 1, 0);
|
|
|
|
lv_obj_set_style_text_color(km, lv_color_hex(0xFFFFFF), LV_PART_ITEMS);
|
|
|
|
lv_obj_set_style_border_color(kb, lv_color_hex(0xFFFFFF), 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lv_obj_set_style_bg_opa(kb, LV_OPA_COVER, LV_PART_ITEMS);
|
|
|
|
lv_obj_set_style_border_color(km, lv_color_hex(0xFF0000), LV_PART_ITEMS | LV_STATE_PRESSED);
|
|
|
|
lv_obj_set_style_bg_color(kb, lv_color_hex(0x000000), LV_PART_ITEMS);
|
|
|
|
lv_obj_set_style_text_color(km, lv_color_hex(0xFF0000), LV_PART_ITEMS | LV_STATE_PRESSED);
|
|
|
|
lv_obj_set_style_border_color(kb, lv_color_hex(0xFFFFFF), LV_PART_ITEMS);
|
|
|
|
|
|
|
|
lv_obj_set_style_border_width(kb, 1, LV_PART_ITEMS);
|
|
|
|
|
|
|
|
lv_obj_set_style_text_color(kb, lv_color_hex(0xFFFFFF), LV_PART_ITEMS);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lv_obj_set_style_border_color(kb, lv_color_hex(0xFF0000), LV_PART_ITEMS | LV_STATE_PRESSED);
|
|
|
|
lv_obj_set_style_text_color(km, lv_color_hex(0x505050), LV_PART_ITEMS | LV_STATE_DISABLED);
|
|
|
|
lv_obj_set_style_text_color(kb, lv_color_hex(0xFF0000), LV_PART_ITEMS | LV_STATE_PRESSED);
|
|
|
|
lv_obj_set_style_border_color(km, lv_color_hex(0x303030), LV_PART_ITEMS | LV_STATE_DISABLED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void lvgl_tick_cb(void *arg)
|
|
|
|
static void lvgl_tick_cb(void *arg)
|
|
|
|
@@ -198,85 +222,443 @@ static void on_generate(lv_event_t *e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void build_main_menu(void);
|
|
|
|
static void build_main_menu(void);
|
|
|
|
|
|
|
|
static void refresh_entry_ui(void);
|
|
|
|
|
|
|
|
static bool verify_or_prompt_checksum(void);
|
|
|
|
|
|
|
|
|
|
|
|
static void on_back_to_menu(lv_event_t *e)
|
|
|
|
static const char *s_key_map[] = {
|
|
|
|
|
|
|
|
"q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "\n",
|
|
|
|
|
|
|
|
"a", "s", "d", "f", "g", "h", "j", "k", "l", "\n",
|
|
|
|
|
|
|
|
"z", "x", "c", "v", "b", "n", "m", "<", "",
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void clear_entry_state(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
(void)e;
|
|
|
|
secure_memzero(s_committed_words, sizeof(s_committed_words));
|
|
|
|
build_main_menu();
|
|
|
|
secure_memzero(s_prefix, sizeof(s_prefix));
|
|
|
|
|
|
|
|
s_word_count = 0;
|
|
|
|
|
|
|
|
s_prefix_len = 0;
|
|
|
|
|
|
|
|
s_checksum_override = false;
|
|
|
|
|
|
|
|
s_match_total = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void on_use_entry(lv_event_t *e)
|
|
|
|
static bool join_committed_words(char *out, size_t out_len)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
size_t cursor = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (out == NULL || out_len == 0) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
out[0] = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < s_word_count; ++i) {
|
|
|
|
|
|
|
|
size_t wl = strlen(s_committed_words[i]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (cursor != 0) {
|
|
|
|
|
|
|
|
if (cursor + 1 >= out_len) {
|
|
|
|
|
|
|
|
out[0] = '\0';
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
out[cursor++] = ' ';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (cursor + wl >= out_len) {
|
|
|
|
|
|
|
|
out[0] = '\0';
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(out + cursor, s_committed_words[i], wl);
|
|
|
|
|
|
|
|
cursor += wl;
|
|
|
|
|
|
|
|
out[cursor] = '\0';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void commit_word(const char *word)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (word == NULL || s_word_count >= UI_MNEMONIC_WORDS) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset(s_committed_words[s_word_count], 0, UI_BIP39_WORD_MAX);
|
|
|
|
|
|
|
|
strncpy(s_committed_words[s_word_count], word, UI_BIP39_WORD_MAX - 1);
|
|
|
|
|
|
|
|
s_word_count++;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
secure_memzero(s_prefix, sizeof(s_prefix));
|
|
|
|
|
|
|
|
s_prefix_len = 0;
|
|
|
|
|
|
|
|
s_checksum_override = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void on_checksum_use_anyway(lv_event_t *e)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
(void)e;
|
|
|
|
(void)e;
|
|
|
|
|
|
|
|
|
|
|
|
if (s_entry_ta == NULL) {
|
|
|
|
char joined[256];
|
|
|
|
return;
|
|
|
|
memset(joined, 0, sizeof(joined));
|
|
|
|
}
|
|
|
|
if (!join_committed_words(joined, sizeof(joined))) {
|
|
|
|
|
|
|
|
set_status("Mnemonic buffer error");
|
|
|
|
const char *txt = lv_textarea_get_text(s_entry_ta);
|
|
|
|
secure_memzero(joined, sizeof(joined));
|
|
|
|
if (txt == NULL || txt[0] == '\0') {
|
|
|
|
|
|
|
|
set_status("Mnemonic is empty");
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mnemonic_validate(txt) != 0) {
|
|
|
|
|
|
|
|
set_status("Invalid mnemonic");
|
|
|
|
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
memset(s_selected_mnemonic, 0, sizeof(s_selected_mnemonic));
|
|
|
|
memset(s_selected_mnemonic, 0, sizeof(s_selected_mnemonic));
|
|
|
|
strncpy(s_selected_mnemonic, txt, sizeof(s_selected_mnemonic) - 1);
|
|
|
|
strncpy(s_selected_mnemonic, joined, sizeof(s_selected_mnemonic) - 1);
|
|
|
|
s_have_mnemonic = true;
|
|
|
|
s_have_mnemonic = true;
|
|
|
|
s_done = true;
|
|
|
|
s_done = true;
|
|
|
|
|
|
|
|
s_checksum_override = true;
|
|
|
|
|
|
|
|
secure_memzero(joined, sizeof(joined));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void on_checksum_edit_words(lv_event_t *e)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void)e;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_checksum_panel != NULL) {
|
|
|
|
|
|
|
|
lv_obj_del(s_checksum_panel);
|
|
|
|
|
|
|
|
s_checksum_panel = NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
set_status("Checksum mismatch: edit or use anyway");
|
|
|
|
|
|
|
|
refresh_entry_ui();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool verify_or_prompt_checksum(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
char joined[256];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_key_matrix == NULL || s_entry_words_label == NULL || s_entry_prefix_label == NULL) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_word_count != UI_MNEMONIC_WORDS || s_prefix_len != 0) {
|
|
|
|
|
|
|
|
set_status("Need exactly 12 complete words");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset(joined, 0, sizeof(joined));
|
|
|
|
|
|
|
|
if (!join_committed_words(joined, sizeof(joined))) {
|
|
|
|
|
|
|
|
set_status("Mnemonic buffer error");
|
|
|
|
|
|
|
|
secure_memzero(joined, sizeof(joined));
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mnemonic_validate(joined) == 0) {
|
|
|
|
|
|
|
|
if (s_checksum_panel != NULL) {
|
|
|
|
|
|
|
|
lv_obj_del(s_checksum_panel);
|
|
|
|
|
|
|
|
s_checksum_panel = NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
set_status("Checksum valid");
|
|
|
|
|
|
|
|
memset(s_selected_mnemonic, 0, sizeof(s_selected_mnemonic));
|
|
|
|
|
|
|
|
strncpy(s_selected_mnemonic, joined, sizeof(s_selected_mnemonic) - 1);
|
|
|
|
|
|
|
|
s_have_mnemonic = true;
|
|
|
|
|
|
|
|
s_done = true;
|
|
|
|
|
|
|
|
secure_memzero(joined, sizeof(joined));
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_checksum_panel != NULL) {
|
|
|
|
|
|
|
|
lv_obj_del(s_checksum_panel);
|
|
|
|
|
|
|
|
s_checksum_panel = NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s_checksum_panel = lv_obj_create(lv_scr_act());
|
|
|
|
|
|
|
|
lv_obj_set_size(s_checksum_panel, DISPLAY_WIDTH - 20, 82);
|
|
|
|
|
|
|
|
lv_obj_align(s_checksum_panel, LV_ALIGN_TOP_MID, 0, 78);
|
|
|
|
|
|
|
|
lv_obj_set_style_bg_color(s_checksum_panel, lv_color_hex(0x000000), 0);
|
|
|
|
|
|
|
|
lv_obj_set_style_border_color(s_checksum_panel, lv_color_hex(0xFFFFFF), 0);
|
|
|
|
|
|
|
|
lv_obj_set_style_border_width(s_checksum_panel, 2, 0);
|
|
|
|
|
|
|
|
lv_obj_set_style_radius(s_checksum_panel, 6, 0);
|
|
|
|
|
|
|
|
lv_obj_set_style_pad_all(s_checksum_panel, 6, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lv_obj_t *txt = lv_label_create(s_checksum_panel);
|
|
|
|
|
|
|
|
lv_label_set_text(txt, "Checksum invalid. Use anyway?");
|
|
|
|
|
|
|
|
lv_obj_set_style_text_color(txt, lv_color_hex(0xFF0000), 0);
|
|
|
|
|
|
|
|
lv_obj_align(txt, LV_ALIGN_TOP_MID, 0, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lv_obj_t *use_btn = lv_btn_create(s_checksum_panel);
|
|
|
|
|
|
|
|
lv_obj_set_size(use_btn, 128, 30);
|
|
|
|
|
|
|
|
lv_obj_align(use_btn, LV_ALIGN_BOTTOM_LEFT, 4, -2);
|
|
|
|
|
|
|
|
style_button(use_btn);
|
|
|
|
|
|
|
|
lv_obj_set_style_border_color(use_btn, lv_color_hex(0xFF0000), 0);
|
|
|
|
|
|
|
|
lv_obj_add_event_cb(use_btn, on_checksum_use_anyway, LV_EVENT_RELEASED, NULL);
|
|
|
|
|
|
|
|
lv_obj_t *use_lbl = lv_label_create(use_btn);
|
|
|
|
|
|
|
|
lv_label_set_text(use_lbl, "Use Anyway");
|
|
|
|
|
|
|
|
lv_obj_center(use_lbl);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lv_obj_t *edit_btn = lv_btn_create(s_checksum_panel);
|
|
|
|
|
|
|
|
lv_obj_set_size(edit_btn, 128, 30);
|
|
|
|
|
|
|
|
lv_obj_align(edit_btn, LV_ALIGN_BOTTOM_RIGHT, -4, -2);
|
|
|
|
|
|
|
|
style_button(edit_btn);
|
|
|
|
|
|
|
|
lv_obj_add_event_cb(edit_btn, on_checksum_edit_words, LV_EVENT_RELEASED, NULL);
|
|
|
|
|
|
|
|
lv_obj_t *edit_lbl = lv_label_create(edit_btn);
|
|
|
|
|
|
|
|
lv_label_set_text(edit_lbl, "Edit Words");
|
|
|
|
|
|
|
|
lv_obj_center(edit_lbl);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set_status("Checksum invalid");
|
|
|
|
|
|
|
|
secure_memzero(joined, sizeof(joined));
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void on_back_to_menu(lv_event_t *e)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void)e;
|
|
|
|
|
|
|
|
if (s_checksum_panel != NULL) {
|
|
|
|
|
|
|
|
lv_obj_del(s_checksum_panel);
|
|
|
|
|
|
|
|
s_checksum_panel = NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
clear_entry_state();
|
|
|
|
|
|
|
|
build_main_menu();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void on_suggestion_tap(lv_event_t *e)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const char *word = (const char *)lv_event_get_user_data(e);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_suggestion_row == NULL || word == NULL || s_word_count >= UI_MNEMONIC_WORDS) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
commit_word(word);
|
|
|
|
|
|
|
|
refresh_entry_ui();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_word_count == UI_MNEMONIC_WORDS) {
|
|
|
|
|
|
|
|
(void)verify_or_prompt_checksum();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void entry_backspace_step(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (s_prefix_len > 0) {
|
|
|
|
|
|
|
|
s_prefix_len--;
|
|
|
|
|
|
|
|
s_prefix[s_prefix_len] = '\0';
|
|
|
|
|
|
|
|
} else if (s_word_count > 0) {
|
|
|
|
|
|
|
|
s_word_count--;
|
|
|
|
|
|
|
|
memset(s_prefix, 0, sizeof(s_prefix));
|
|
|
|
|
|
|
|
strncpy(s_prefix, s_committed_words[s_word_count], sizeof(s_prefix) - 1);
|
|
|
|
|
|
|
|
s_prefix_len = strlen(s_prefix);
|
|
|
|
|
|
|
|
secure_memzero(s_committed_words[s_word_count], sizeof(s_committed_words[s_word_count]));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s_checksum_override = false;
|
|
|
|
|
|
|
|
if (s_checksum_panel != NULL) {
|
|
|
|
|
|
|
|
lv_obj_del(s_checksum_panel);
|
|
|
|
|
|
|
|
s_checksum_panel = NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
refresh_entry_ui();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void on_key_matrix(lv_event_t *e)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
lv_obj_t *obj = lv_event_get_target(e);
|
|
|
|
|
|
|
|
if (s_key_matrix == NULL || obj != s_key_matrix) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t idx = lv_btnmatrix_get_selected_btn(obj);
|
|
|
|
|
|
|
|
const char *txt = lv_btnmatrix_get_btn_text(obj, idx);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (txt == NULL || txt[0] == '\0' || txt[1] != '\0') {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (txt[0] == '<') {
|
|
|
|
|
|
|
|
entry_backspace_step();
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_word_count >= UI_MNEMONIC_WORDS) {
|
|
|
|
|
|
|
|
set_status("Already have 12 words");
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_prefix_len + 1 >= sizeof(s_prefix)) {
|
|
|
|
|
|
|
|
set_status("Word too long");
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s_prefix[s_prefix_len++] = txt[0];
|
|
|
|
|
|
|
|
s_prefix[s_prefix_len] = '\0';
|
|
|
|
|
|
|
|
s_checksum_override = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
refresh_entry_ui();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_match_total == 1) {
|
|
|
|
|
|
|
|
const char *word = mnemonic_word_at(s_match_indices[0]);
|
|
|
|
|
|
|
|
if (word != NULL) {
|
|
|
|
|
|
|
|
commit_word(word);
|
|
|
|
|
|
|
|
refresh_entry_ui();
|
|
|
|
|
|
|
|
if (s_word_count == UI_MNEMONIC_WORDS) {
|
|
|
|
|
|
|
|
(void)verify_or_prompt_checksum();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void refresh_entry_ui(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
size_t shown = 0;
|
|
|
|
|
|
|
|
char words_line[256];
|
|
|
|
|
|
|
|
char prefix_line[64];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_checksum_panel != NULL) {
|
|
|
|
|
|
|
|
lv_obj_del(s_checksum_panel);
|
|
|
|
|
|
|
|
s_checksum_panel = NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset(words_line, 0, sizeof(words_line));
|
|
|
|
|
|
|
|
(void)join_committed_words(words_line, sizeof(words_line));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_entry_words_label != NULL) {
|
|
|
|
|
|
|
|
if (s_word_count == 0) {
|
|
|
|
|
|
|
|
lv_label_set_text(s_entry_words_label, "(no words selected)");
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
lv_label_set_text(s_entry_words_label, words_line);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
snprintf(prefix_line, sizeof(prefix_line), "Word %u/12 prefix: %s",
|
|
|
|
|
|
|
|
(unsigned)(s_word_count + 1),
|
|
|
|
|
|
|
|
(s_prefix_len > 0) ? s_prefix : "-");
|
|
|
|
|
|
|
|
if (s_entry_prefix_label != NULL) {
|
|
|
|
|
|
|
|
lv_label_set_text(s_entry_prefix_label, prefix_line);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_suggestion_row != NULL) {
|
|
|
|
|
|
|
|
lv_obj_clean(s_suggestion_row);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_prefix_len > 0 && s_word_count < UI_MNEMONIC_WORDS) {
|
|
|
|
|
|
|
|
s_match_total = mnemonic_words_with_prefix(s_prefix, s_match_indices, UI_SUGGESTION_STORE_MAX);
|
|
|
|
|
|
|
|
shown = (s_match_total > UI_SUGGESTION_VISIBLE_MAX) ? UI_SUGGESTION_VISIBLE_MAX : s_match_total;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < shown; ++i) {
|
|
|
|
|
|
|
|
const char *word = mnemonic_word_at(s_match_indices[i]);
|
|
|
|
|
|
|
|
lv_obj_t *btn;
|
|
|
|
|
|
|
|
lv_obj_t *lbl;
|
|
|
|
|
|
|
|
if (word == NULL) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
btn = lv_btn_create(s_suggestion_row);
|
|
|
|
|
|
|
|
lv_obj_set_size(btn, 84, 26);
|
|
|
|
|
|
|
|
style_button(btn);
|
|
|
|
|
|
|
|
lv_obj_add_event_cb(btn, on_suggestion_tap, LV_EVENT_RELEASED, (void *)word);
|
|
|
|
|
|
|
|
lbl = lv_label_create(btn);
|
|
|
|
|
|
|
|
lv_label_set_text(lbl, word);
|
|
|
|
|
|
|
|
lv_obj_center(lbl);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_match_total > shown) {
|
|
|
|
|
|
|
|
char more[24];
|
|
|
|
|
|
|
|
lv_obj_t *m = lv_label_create(s_suggestion_row);
|
|
|
|
|
|
|
|
snprintf(more, sizeof(more), "+%u more", (unsigned)(s_match_total - shown));
|
|
|
|
|
|
|
|
lv_label_set_text(m, more);
|
|
|
|
|
|
|
|
lv_obj_set_style_text_color(m, lv_color_hex(0xFFFFFF), 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_match_total == 0) {
|
|
|
|
|
|
|
|
set_status("No matches");
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
set_status("");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
s_match_total = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_key_matrix != NULL) {
|
|
|
|
|
|
|
|
const uint16_t matrix_btn_count = 27;
|
|
|
|
|
|
|
|
for (uint16_t i = 0; i < matrix_btn_count; ++i) {
|
|
|
|
|
|
|
|
const char *txt = lv_btnmatrix_get_btn_text(s_key_matrix, i);
|
|
|
|
|
|
|
|
bool enabled = false;
|
|
|
|
|
|
|
|
if (txt == NULL || txt[0] == '\0' || txt[1] != '\0') {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (txt[0] == '<') {
|
|
|
|
|
|
|
|
enabled = (s_prefix_len > 0 || s_word_count > 0);
|
|
|
|
|
|
|
|
} else if (s_word_count >= UI_MNEMONIC_WORDS) {
|
|
|
|
|
|
|
|
enabled = false;
|
|
|
|
|
|
|
|
} else if (s_prefix_len == 0) {
|
|
|
|
|
|
|
|
size_t start = 0;
|
|
|
|
|
|
|
|
enabled = (mnemonic_words_for_letter(txt[0], &start) > 0);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
enabled = mnemonic_letter_extends_prefix(s_prefix, s_prefix_len, txt[0]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (enabled) {
|
|
|
|
|
|
|
|
lv_btnmatrix_clear_btn_ctrl(s_key_matrix, i, LV_BTNMATRIX_CTRL_DISABLED);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
lv_btnmatrix_set_btn_ctrl(s_key_matrix, i, LV_BTNMATRIX_CTRL_DISABLED);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void build_entry_screen(void)
|
|
|
|
static void build_entry_screen(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
lv_obj_t *scr = lv_scr_act();
|
|
|
|
lv_obj_t *scr = lv_scr_act();
|
|
|
|
|
|
|
|
lv_obj_t *title;
|
|
|
|
|
|
|
|
lv_obj_t *close_btn;
|
|
|
|
|
|
|
|
lv_obj_t *close_lbl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
reset_screen_widget_refs();
|
|
|
|
lv_obj_clean(scr);
|
|
|
|
lv_obj_clean(scr);
|
|
|
|
style_screen(scr);
|
|
|
|
style_screen(scr);
|
|
|
|
|
|
|
|
clear_entry_state();
|
|
|
|
|
|
|
|
|
|
|
|
lv_obj_t *title = lv_label_create(scr);
|
|
|
|
title = lv_label_create(scr);
|
|
|
|
lv_label_set_text(title, "Enter Mnemonic");
|
|
|
|
lv_label_set_text(title, "Enter Mnemonic");
|
|
|
|
lv_obj_set_style_text_font(title, &lv_font_montserrat_14, 0);
|
|
|
|
lv_obj_set_style_text_font(title, &lv_font_montserrat_14, 0);
|
|
|
|
lv_obj_set_style_text_color(title, lv_color_hex(0xFFFFFF), 0);
|
|
|
|
lv_obj_set_style_text_color(title, lv_color_hex(0xFFFFFF), 0);
|
|
|
|
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 6);
|
|
|
|
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 4);
|
|
|
|
|
|
|
|
|
|
|
|
s_entry_ta = lv_textarea_create(scr);
|
|
|
|
s_entry_words_label = lv_label_create(scr);
|
|
|
|
lv_obj_set_size(s_entry_ta, DISPLAY_WIDTH - 16, 70);
|
|
|
|
lv_obj_set_width(s_entry_words_label, DISPLAY_WIDTH - 16);
|
|
|
|
lv_obj_align(s_entry_ta, LV_ALIGN_TOP_MID, 0, 32);
|
|
|
|
lv_label_set_long_mode(s_entry_words_label, LV_LABEL_LONG_WRAP);
|
|
|
|
lv_textarea_set_placeholder_text(s_entry_ta, "12 words separated by spaces");
|
|
|
|
lv_label_set_text(s_entry_words_label, "(no words selected)");
|
|
|
|
lv_textarea_set_one_line(s_entry_ta, false);
|
|
|
|
lv_obj_set_style_text_color(s_entry_words_label, lv_color_hex(0xFFFFFF), 0);
|
|
|
|
style_text_area(s_entry_ta);
|
|
|
|
lv_obj_align(s_entry_words_label, LV_ALIGN_TOP_LEFT, 8, 26);
|
|
|
|
|
|
|
|
|
|
|
|
lv_obj_t *kb = lv_keyboard_create(scr);
|
|
|
|
s_entry_prefix_label = lv_label_create(scr);
|
|
|
|
lv_obj_set_size(kb, DISPLAY_WIDTH, 110);
|
|
|
|
lv_label_set_text(s_entry_prefix_label, "Word 1/12 prefix: -");
|
|
|
|
lv_obj_align(kb, LV_ALIGN_BOTTOM_MID, 0, 0);
|
|
|
|
lv_obj_set_style_text_color(s_entry_prefix_label, lv_color_hex(0xFFFFFF), 0);
|
|
|
|
lv_keyboard_set_textarea(kb, s_entry_ta);
|
|
|
|
lv_obj_align(s_entry_prefix_label, LV_ALIGN_TOP_LEFT, 8, 66);
|
|
|
|
style_keyboard(kb);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lv_obj_t *use_btn = lv_btn_create(scr);
|
|
|
|
|
|
|
|
lv_obj_set_size(use_btn, 150, 30);
|
|
|
|
|
|
|
|
lv_obj_align(use_btn, LV_ALIGN_TOP_LEFT, 8, 110);
|
|
|
|
|
|
|
|
lv_obj_add_event_cb(use_btn, on_use_entry, LV_EVENT_RELEASED, NULL);
|
|
|
|
|
|
|
|
style_button(use_btn);
|
|
|
|
|
|
|
|
lv_obj_t *use_lbl = lv_label_create(use_btn);
|
|
|
|
|
|
|
|
lv_label_set_text(use_lbl, "Use Mnemonic");
|
|
|
|
|
|
|
|
lv_obj_center(use_lbl);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lv_obj_t *back_btn = lv_btn_create(scr);
|
|
|
|
|
|
|
|
lv_obj_set_size(back_btn, 150, 30);
|
|
|
|
|
|
|
|
lv_obj_align(back_btn, LV_ALIGN_TOP_RIGHT, -8, 110);
|
|
|
|
|
|
|
|
lv_obj_add_event_cb(back_btn, on_back_to_menu, LV_EVENT_RELEASED, NULL);
|
|
|
|
|
|
|
|
style_button(back_btn);
|
|
|
|
|
|
|
|
lv_obj_t *back_lbl = lv_label_create(back_btn);
|
|
|
|
|
|
|
|
lv_label_set_text(back_lbl, "Back");
|
|
|
|
|
|
|
|
lv_obj_center(back_lbl);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s_status_label = lv_label_create(scr);
|
|
|
|
s_status_label = lv_label_create(scr);
|
|
|
|
lv_label_set_text(s_status_label, "");
|
|
|
|
lv_label_set_text(s_status_label, "");
|
|
|
|
lv_obj_set_style_text_color(s_status_label, lv_color_hex(0xFF0000), 0);
|
|
|
|
lv_obj_set_style_text_color(s_status_label, lv_color_hex(0xFF0000), 0);
|
|
|
|
lv_obj_align(s_status_label, LV_ALIGN_TOP_LEFT, 8, 144);
|
|
|
|
lv_obj_align(s_status_label, LV_ALIGN_TOP_LEFT, 8, 82);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s_suggestion_row = lv_obj_create(scr);
|
|
|
|
|
|
|
|
lv_obj_set_size(s_suggestion_row, DISPLAY_WIDTH - 12, 30);
|
|
|
|
|
|
|
|
lv_obj_align(s_suggestion_row, LV_ALIGN_TOP_MID, 0, 96);
|
|
|
|
|
|
|
|
lv_obj_set_style_bg_color(s_suggestion_row, lv_color_hex(0x000000), 0);
|
|
|
|
|
|
|
|
lv_obj_set_style_border_color(s_suggestion_row, lv_color_hex(0xFFFFFF), 0);
|
|
|
|
|
|
|
|
lv_obj_set_style_border_width(s_suggestion_row, 1, 0);
|
|
|
|
|
|
|
|
lv_obj_set_style_pad_all(s_suggestion_row, 2, 0);
|
|
|
|
|
|
|
|
lv_obj_set_scroll_dir(s_suggestion_row, LV_DIR_HOR);
|
|
|
|
|
|
|
|
lv_obj_set_flex_flow(s_suggestion_row, LV_FLEX_FLOW_ROW);
|
|
|
|
|
|
|
|
lv_obj_set_flex_align(s_suggestion_row, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
close_btn = lv_btn_create(scr);
|
|
|
|
|
|
|
|
lv_obj_set_size(close_btn, 42, 30);
|
|
|
|
|
|
|
|
lv_obj_align(close_btn, LV_ALIGN_TOP_RIGHT, -4, 2);
|
|
|
|
|
|
|
|
style_button(close_btn);
|
|
|
|
|
|
|
|
lv_obj_add_event_cb(close_btn, on_back_to_menu, LV_EVENT_CLICKED, NULL);
|
|
|
|
|
|
|
|
close_lbl = lv_label_create(close_btn);
|
|
|
|
|
|
|
|
lv_label_set_text(close_lbl, "X");
|
|
|
|
|
|
|
|
lv_obj_center(close_lbl);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s_key_matrix = lv_btnmatrix_create(scr);
|
|
|
|
|
|
|
|
lv_obj_set_size(s_key_matrix, DISPLAY_WIDTH - 16, 100);
|
|
|
|
|
|
|
|
lv_obj_align(s_key_matrix, LV_ALIGN_TOP_MID, 0, 132);
|
|
|
|
|
|
|
|
lv_btnmatrix_set_map(s_key_matrix, s_key_map);
|
|
|
|
|
|
|
|
lv_obj_add_event_cb(s_key_matrix, on_key_matrix, LV_EVENT_VALUE_CHANGED, NULL);
|
|
|
|
|
|
|
|
style_key_matrix(s_key_matrix);
|
|
|
|
|
|
|
|
lv_obj_set_style_pad_all(s_key_matrix, 0, 0);
|
|
|
|
|
|
|
|
lv_obj_set_style_pad_gap(s_key_matrix, 0, LV_PART_ITEMS);
|
|
|
|
|
|
|
|
lv_obj_set_style_border_width(s_key_matrix, 1, LV_PART_ITEMS);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
refresh_entry_ui();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void on_enter(lv_event_t *e)
|
|
|
|
static void on_enter(lv_event_t *e)
|
|
|
|
@@ -316,6 +698,7 @@ static void on_use_viewed(lv_event_t *e)
|
|
|
|
static void build_view_screen(void)
|
|
|
|
static void build_view_screen(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
lv_obj_t *scr = lv_scr_act();
|
|
|
|
lv_obj_t *scr = lv_scr_act();
|
|
|
|
|
|
|
|
reset_screen_widget_refs();
|
|
|
|
lv_obj_clean(scr);
|
|
|
|
lv_obj_clean(scr);
|
|
|
|
style_screen(scr);
|
|
|
|
style_screen(scr);
|
|
|
|
|
|
|
|
|
|
|
|
@@ -370,6 +753,7 @@ static void on_view(lv_event_t *e)
|
|
|
|
static void build_main_menu(void)
|
|
|
|
static void build_main_menu(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
lv_obj_t *scr = lv_scr_act();
|
|
|
|
lv_obj_t *scr = lv_scr_act();
|
|
|
|
|
|
|
|
reset_screen_widget_refs();
|
|
|
|
lv_obj_clean(scr);
|
|
|
|
lv_obj_clean(scr);
|
|
|
|
style_screen(scr);
|
|
|
|
style_screen(scr);
|
|
|
|
|
|
|
|
|
|
|
|
@@ -424,6 +808,7 @@ void ui_show_approval_prompt(const char *caller_pubkey_hex, int kind, const char
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
lv_obj_t *scr = lv_scr_act();
|
|
|
|
lv_obj_t *scr = lv_scr_act();
|
|
|
|
|
|
|
|
reset_screen_widget_refs();
|
|
|
|
lv_obj_clean(scr);
|
|
|
|
lv_obj_clean(scr);
|
|
|
|
style_screen(scr);
|
|
|
|
style_screen(scr);
|
|
|
|
|
|
|
|
|
|
|
|
@@ -535,6 +920,7 @@ ui_approval_decision_t ui_wait_for_approval(uint32_t timeout_ms)
|
|
|
|
static void show_event_log_screen(void)
|
|
|
|
static void show_event_log_screen(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
lv_obj_t *scr = lv_scr_act();
|
|
|
|
lv_obj_t *scr = lv_scr_act();
|
|
|
|
|
|
|
|
reset_screen_widget_refs();
|
|
|
|
lv_obj_clean(scr);
|
|
|
|
lv_obj_clean(scr);
|
|
|
|
style_screen(scr);
|
|
|
|
style_screen(scr);
|
|
|
|
|
|
|
|
|
|
|
|
@@ -579,6 +965,7 @@ void ui_show_idle(const char *npub_full, const char *mnemonic_full, const char *
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
lv_obj_t *scr = lv_scr_act();
|
|
|
|
lv_obj_t *scr = lv_scr_act();
|
|
|
|
|
|
|
|
reset_screen_widget_refs();
|
|
|
|
lv_obj_clean(scr);
|
|
|
|
lv_obj_clean(scr);
|
|
|
|
style_screen(scr);
|
|
|
|
style_screen(scr);
|
|
|
|
|
|
|
|
|
|
|
|
|