From a9df594ac7b435831225bb5a751324f702cf7b2d Mon Sep 17 00:00:00 2001 From: odudex Date: Fri, 24 Apr 2026 10:48:55 -0300 Subject: [PATCH 1/3] fix(display): clear stale framebuffer on warm reset fix graphical bug on splash screen --- main/main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/main/main.c b/main/main.c index c3ebdf8..84ce84d 100644 --- a/main/main.c +++ b/main/main.c @@ -65,6 +65,15 @@ void app_main(void) { bsp_display_start(); ESP_LOGI(TAG, "Display initialized successfully"); + // Paint screen black early to overwrite stale framebuffer on warm reset. + bsp_display_lock(0); + lv_obj_t *screen = lv_screen_active(); + lv_obj_set_style_bg_color(screen, bg_color(), 0); + lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, 0); + lv_obj_invalidate(screen); + lv_refr_now(NULL); + bsp_display_unlock(); + // Initialize PMIC (AXP2101 on wave_35; no-op on wave_4b) esp_err_t pmic_ret = bsp_pmic_init(); if (pmic_ret == ESP_OK) { @@ -77,7 +86,6 @@ void app_main(void) { bsp_display_lock(0); // Set up screen theme background - lv_obj_t *screen = lv_screen_active(); theme_apply_screen(screen); // Force LVGL to render framebuffer lv_refr_now(NULL); From 65c1bec832b6687d57f2989d4dfcf400ca9a3ea8 Mon Sep 17 00:00:00 2001 From: odudex Date: Fri, 24 Apr 2026 11:36:57 -0300 Subject: [PATCH 2/3] fix(wallet_settings): prevent Apply button crop, distribute items evenly --- main/pages/settings/wallet_settings.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/main/pages/settings/wallet_settings.c b/main/pages/settings/wallet_settings.c index fbb6309..04c8081 100644 --- a/main/pages/settings/wallet_settings.c +++ b/main/pages/settings/wallet_settings.c @@ -95,8 +95,8 @@ static void update_derivation_path(void) { static void update_account_display(void) { if (!account_value_label) return; - char buf[12]; - snprintf(buf, sizeof(buf), "%u", selected_account); + char buf[24]; + snprintf(buf, sizeof(buf), "Account: %u", selected_account); lv_label_set_text(account_value_label, buf); } @@ -471,7 +471,6 @@ void wallet_settings_page_create(lv_obj_t *parent, void (*return_cb)(void)) { theme_apply_screen(wallet_settings_screen); lv_obj_clear_flag(wallet_settings_screen, LV_OBJ_FLAG_SCROLLABLE); - int32_t pad = theme_get_default_padding(); int32_t top_h = theme_get_screen_height() * 5 / 36; // 100 @ 720 // Top bar (same as key_confirmation.c) @@ -513,9 +512,8 @@ void wallet_settings_page_create(lv_obj_t *parent, void (*return_cb)(void)) { lv_obj_set_style_pad_all(content, 0, 0); lv_obj_clear_flag(content, LV_OBJ_FLAG_SCROLLABLE); lv_obj_set_flex_flow(content, LV_FLEX_FLOW_COLUMN); - lv_obj_set_flex_align(content, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, - LV_FLEX_ALIGN_CENTER); - lv_obj_set_style_pad_gap(content, theme_get_default_padding(), 0); + lv_obj_set_flex_align(content, LV_FLEX_ALIGN_SPACE_EVENLY, + LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); // Passphrase + Descriptor row container (side by side) lv_obj_t *pp_desc_row = lv_obj_create(content); @@ -524,7 +522,6 @@ void wallet_settings_page_create(lv_obj_t *parent, void (*return_cb)(void)) { lv_obj_set_flex_flow(pp_desc_row, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(pp_desc_row, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); - lv_obj_set_style_margin_top(pp_desc_row, pad, 0); passphrase_btn = lv_btn_create(pp_desc_row); lv_obj_set_size(passphrase_btn, LV_PCT(48), theme_get_min_touch_size()); @@ -557,7 +554,6 @@ void wallet_settings_page_create(lv_obj_t *parent, void (*return_cb)(void)) { lv_obj_set_flex_flow(net_policy_row, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(net_policy_row, LV_FLEX_ALIGN_SPACE_EVENLY, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER); - lv_obj_set_style_margin_top(net_policy_row, pad, 0); // Network column (label + dropdown) lv_obj_t *net_col = lv_obj_create(net_policy_row); @@ -601,22 +597,15 @@ void wallet_settings_page_create(lv_obj_t *parent, void (*return_cb)(void)) { lv_obj_add_event_cb(policy_dropdown, policy_dropdown_cb, LV_EVENT_VALUE_CHANGED, NULL); - // Account label - lv_obj_t *acc_label = lv_label_create(content); - lv_label_set_text(acc_label, "Account"); - lv_obj_set_style_text_font(acc_label, theme_font_small(), 0); - lv_obj_set_style_text_color(acc_label, secondary_color(), 0); - lv_obj_set_style_margin_top(acc_label, pad, 0); - - // Account button + // Account button (label lives on the button itself) account_btn = lv_btn_create(content); lv_obj_set_size(account_btn, LV_PCT(50), theme_get_min_touch_size()); theme_apply_touch_button(account_btn, false); lv_obj_add_event_cb(account_btn, account_btn_cb, LV_EVENT_CLICKED, NULL); account_value_label = lv_label_create(account_btn); - char acc_buf[12]; - snprintf(acc_buf, sizeof(acc_buf), "%u", selected_account); + char acc_buf[24]; + snprintf(acc_buf, sizeof(acc_buf), "Account: %u", selected_account); lv_label_set_text(account_value_label, acc_buf); lv_obj_set_style_text_font(account_value_label, theme_font_medium(), 0); lv_obj_set_style_text_color(account_value_label, main_color(), 0); @@ -625,7 +614,6 @@ void wallet_settings_page_create(lv_obj_t *parent, void (*return_cb)(void)) { // Apply button apply_btn = lv_btn_create(content); lv_obj_set_size(apply_btn, LV_PCT(60), theme_get_min_touch_size()); - lv_obj_set_style_margin_top(apply_btn, pad, 0); theme_apply_touch_button(apply_btn, false); lv_obj_add_event_cb(apply_btn, apply_btn_cb, LV_EVENT_CLICKED, NULL); lv_obj_add_state(apply_btn, LV_STATE_DISABLED); // Disabled until changes made From 7771b97ff4bd9a9bbd7c8da6936e7958136254af Mon Sep 17 00:00:00 2001 From: odudex Date: Fri, 24 Apr 2026 11:38:20 -0300 Subject: [PATCH 3/3] fix(wallet_settings): preserve pending edits across descriptor manager trip Returning from the descriptor manager unconditionally called `refresh_wallet_attributes()`, which re-read `wallet_get_network/policy/account()` and reset `settings_changed = false` wiping any pending user edits and disabling the Apply button even when the user had only opened the descriptor manager without loading anything. Have `descriptor_manager` expose a `descriptor_manager_was_changed()` getter (same pattern as `wallet_settings_were_applied()`), set to true on the two actual load paths: QR validation success and storage (flash/SD) load success. `wallet_settings` only resyncs from the wallet when that signal fires, so a no-op trip preserves pending edits while a real descriptor load correctly overwrites them. --- main/pages/settings/descriptor_manager.c | 12 ++++++++++++ main/pages/settings/descriptor_manager.h | 4 ++++ main/pages/settings/wallet_settings.c | 6 +++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/main/pages/settings/descriptor_manager.c b/main/pages/settings/descriptor_manager.c index 54235fe..5db2c5a 100644 --- a/main/pages/settings/descriptor_manager.c +++ b/main/pages/settings/descriptor_manager.c @@ -61,6 +61,16 @@ static int idx_save_flash = -1; static int idx_save_sd = -1; static int idx_export_qr = -1; +/* Set when a descriptor is loaded; read (and cleared) by callers via + * descriptor_manager_was_changed(). */ +static bool descriptor_changed = false; + +bool descriptor_manager_was_changed(void) { + bool result = descriptor_changed; + descriptor_changed = false; + return result; +} + /* Forward declarations */ static void build_main_menu(void); static void refresh_menu_visibility(void); @@ -291,6 +301,7 @@ static void descriptor_validation_cb(descriptor_validation_result_t result, descriptor_string = NULL; } wallet_get_descriptor_string(&descriptor_string); + descriptor_changed = true; refresh_menu_visibility(); return; } @@ -322,6 +333,7 @@ static void success_from_load_storage(void) { descriptor_string = NULL; } wallet_get_descriptor_string(&descriptor_string); + descriptor_changed = true; descriptor_manager_page_show(); refresh_menu_visibility(); } diff --git a/main/pages/settings/descriptor_manager.h b/main/pages/settings/descriptor_manager.h index b66b88c..27f5e35 100644 --- a/main/pages/settings/descriptor_manager.h +++ b/main/pages/settings/descriptor_manager.h @@ -2,10 +2,14 @@ #define DESCRIPTOR_MANAGER_H #include +#include void descriptor_manager_page_create(lv_obj_t *parent, void (*return_cb)(void)); void descriptor_manager_page_show(void); void descriptor_manager_page_hide(void); void descriptor_manager_page_destroy(void); +// Returns true (and resets) if a descriptor was loaded during the last visit. +bool descriptor_manager_was_changed(void); + #endif // DESCRIPTOR_MANAGER_H diff --git a/main/pages/settings/wallet_settings.c b/main/pages/settings/wallet_settings.c index 04c8081..b04ac87 100644 --- a/main/pages/settings/wallet_settings.c +++ b/main/pages/settings/wallet_settings.c @@ -357,7 +357,11 @@ static void refresh_wallet_attributes(void) { static void descriptor_return_cb(void) { descriptor_manager_page_destroy(); wallet_settings_page_show(); - refresh_wallet_attributes(); + // Descriptor loading can overwrite wallet attributes, in which case pending + // page edits are no longer meaningful and we must resync from the wallet. + if (descriptor_manager_was_changed()) { + refresh_wallet_attributes(); + } } static void descriptor_btn_cb(lv_event_t *e) {