Refactor RootLayout and UIHandler for improved structure and functionality

- Updated RootLayout to manage layout initialization and deinitialization more effectively.
- Removed unnecessary dependencies and streamlined event handling for keyboard events.
- Enhanced UIHandler to utilize shared pointers for app descriptors, improving memory management.
- Added methods for showing and hiding navigation elements in RootLayout.
- Introduced textarea widget with instant response by disabling animations.
- Improved error handling and logging throughout the UI components.
This commit is contained in:
GW_MC
2026-02-01 13:03:56 +08:00
parent 237a3a96c5
commit 06e81301b2
22 changed files with 880 additions and 2198 deletions

View File

@@ -0,0 +1,159 @@
#include "ui/interaction_handler.h"
#include "ui/events.h"
#include "esp_err.h"
#include "esp_log.h"
#define TAG "InteractionHandler"
InteractionHandler::~InteractionHandler() {
esp_err_t err = deinit();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error during InteractionHandler deinit: %s", esp_err_to_name(err));
}
}
esp_err_t InteractionHandler::init(lv_obj_t* app_container) {
if (!app_container) {
ESP_LOGE(TAG, "Invalid argument: app_container is nullptr");
return ESP_ERR_INVALID_ARG;
}
app_container_ = app_container;
keyboard_ = lv_keyboard_create(app_container_);
lv_obj_add_flag(keyboard_, LV_OBJ_FLAG_HIDDEN); // start hidden
lv_obj_add_event_cb(
keyboard_,
[](lv_event_t* e) {
InteractionHandler* handler = static_cast<InteractionHandler*>(lv_event_get_user_data(e));
handler->on_keyboard_event_(e);
}
, LV_EVENT_ALL, this);
return ESP_OK;
}
esp_err_t InteractionHandler::deinit(void) {
if (keyboard_) {
lv_obj_del(keyboard_);
keyboard_ = nullptr;
}
return ESP_OK;
}
esp_err_t InteractionHandler::register_text_area_keyboard_support(lv_obj_t* text_area) {
if (!text_area) {
ESP_LOGE(TAG, "Invalid argument: text_area is nullptr");
return ESP_ERR_INVALID_ARG;
}
lv_obj_add_event_cb(
text_area,
[](lv_event_t* e) {
lv_event_code_t code = lv_event_get_code(e);
if (code != LV_EVENT_FOCUSED) {
return;
}
InteractionHandler* handler = static_cast<InteractionHandler*>(lv_event_get_user_data(e));
esp_err_t err = handler->show_keyboard_for_textarea_(static_cast<lv_obj_t*>(lv_event_get_target(e)));
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to show keyboard: %s", esp_err_to_name(err));
}
}
, LV_EVENT_FOCUSED, this);
lv_obj_add_event_cb(
text_area,
[](lv_event_t* e) {
lv_event_code_t code = lv_event_get_code(e);
if (code != LV_EVENT_DEFOCUSED) {
return;
}
InteractionHandler* handler = static_cast<InteractionHandler*>(lv_event_get_user_data(e));
esp_err_t err = handler->hide_keyboard_();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to hide keyboard: %s", esp_err_to_name(err));
}
}
, LV_EVENT_DEFOCUSED, this);
return ESP_OK;
}
//
// Private methods
//
void InteractionHandler::on_keyboard_event_(lv_event_t* e) {
lv_event_code_t code = lv_event_get_code(e);
if (code == LV_EVENT_READY || code == LV_EVENT_CANCEL) {
// Keyboard is cancelled
esp_err_t err = hide_keyboard_();
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to hide keyboard: %s", esp_err_to_name(err));
}
if (focused_textarea_) {
lv_obj_clear_state(focused_textarea_, LV_STATE_FOCUSED);
lv_keyboard_set_textarea(keyboard_, nullptr);
focused_textarea_ = nullptr;
}
}
}
esp_err_t InteractionHandler::show_keyboard_for_textarea_(lv_obj_t* textarea) {
if (!keyboard_ || !textarea) {
ESP_LOGE(TAG, "Invalid state or argument in show_keyboard_for_textarea_");
return ESP_ERR_INVALID_ARG;
}
focused_textarea_ = textarea;
lv_keyboard_set_textarea(keyboard_, textarea);
lv_obj_clear_flag(keyboard_, LV_OBJ_FLAG_HIDDEN);
// emit keyboard shown event
KeyboardEventData event_data = {
.textarea = textarea
};
esp_err_t err = esp_event_post_to(
NULL,
UI_EVENT_BASE,
UI_EVENT_KEYBOARD_SHOWN,
&event_data,
sizeof(event_data),
portMAX_DELAY
);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to post keyboard shown event: %s", esp_err_to_name(err));
}
return ESP_OK;
}
esp_err_t InteractionHandler::hide_keyboard_(void) {
if (!keyboard_) {
return ESP_ERR_INVALID_STATE;
}
lv_obj_add_flag(keyboard_, LV_OBJ_FLAG_HIDDEN);
// emit keyboard hidden event
KeyboardEventData event_data = {
.textarea = nullptr
};
esp_err_t err = esp_event_post_to(
NULL,
UI_EVENT_BASE,
UI_EVENT_KEYBOARD_HIDDEN,
&event_data,
sizeof(event_data),
portMAX_DELAY
);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to post keyboard hidden event: %s", esp_err_to_name(err));
}
return ESP_OK;
}