feat: Implement Discord app UI and settings management
- Added MainUI class for displaying voice state, status icon, and buttons. - Introduced MainUIHandler to manage UI interactions and bridge communication. - Created SettingsUI for displaying QR code and configuration instructions. - Implemented SettingsUIHandler to manage settings and web server interactions. - Developed WebHandler for handling HTTP requests for settings configuration. - Updated AppRegistry to initialize with the new Discord app descriptor. - Enhanced InteractionHandler to support keyboard interactions across app switches. - Updated UIHandler to manage app switching and rendering of app icons. - Enabled QR code support in LVGL configuration.
This commit is contained in:
@@ -1,8 +1,14 @@
|
||||
#include "ui/ui_handler.h"
|
||||
#include "ui/apps/registry.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#define TAG "UIHandler"
|
||||
|
||||
struct AppClickUserData {
|
||||
UIHandler* ui_handler;
|
||||
std::string app_name;
|
||||
};
|
||||
|
||||
UIHandler::~UIHandler() {
|
||||
deinit();
|
||||
}
|
||||
@@ -18,7 +24,9 @@ esp_err_t UIHandler::init(void) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = interaction_handler_.init(root_layout_.get_app_container());
|
||||
// Initialize InteractionHandler with screen as parent (not app_container)
|
||||
// so keyboard survives app switches
|
||||
ret = interaction_handler_.init(screen);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize InteractionHandler");
|
||||
return ret;
|
||||
@@ -61,7 +69,7 @@ esp_err_t UIHandler::deinit(void) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t UIHandler::switch_app(std::shared_ptr<AppDescriptor> app_descriptor) {
|
||||
esp_err_t UIHandler::switch_app(AppDescriptor* app_descriptor) {
|
||||
if (!app_descriptor) {
|
||||
ESP_LOGE(TAG, "Invalid app descriptor");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@@ -100,7 +108,7 @@ esp_err_t UIHandler::switch_app(std::shared_ptr<AppDescriptor> app_descriptor) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
ret = new_app->init(app_container);
|
||||
ret = new_app->init(app_container, &interaction_handler_);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize app: %s", new_app->get_name().c_str());
|
||||
active_descriptor_ = nullptr;
|
||||
@@ -239,6 +247,45 @@ esp_err_t UIHandler::create_main_screen_(lv_obj_t* parent) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// render all apps
|
||||
|
||||
for (const auto& [name, descriptor] : AppRegistry::instance()) {
|
||||
lv_obj_t* app_icon_container = lv_obj_create(root_layout_.get_app_container());
|
||||
lv_obj_set_size(app_icon_container, 100, 100);
|
||||
lv_obj_set_style_pad_all(app_icon_container, 10, 0);
|
||||
lv_obj_set_flex_flow(app_icon_container, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(app_icon_container, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
|
||||
// Draw the app icon
|
||||
descriptor->draw_icon(app_icon_container);
|
||||
|
||||
// App name label
|
||||
lv_obj_t* label = lv_label_create(app_icon_container);
|
||||
lv_label_set_text(label, name.c_str());
|
||||
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0);
|
||||
|
||||
// Center the icon container
|
||||
lv_obj_center(app_icon_container);
|
||||
|
||||
// Register click event to switch to the app
|
||||
lv_obj_add_event_cb(app_icon_container,
|
||||
[](lv_event_t* e) {
|
||||
AppClickUserData* user_data = static_cast<AppClickUserData*>(lv_event_get_user_data(e));
|
||||
UIHandler* ui_handler = user_data->ui_handler;
|
||||
std::string app_name = user_data->app_name;
|
||||
|
||||
AppDescriptor* descriptor = AppRegistry::instance()[app_name];
|
||||
if (descriptor) {
|
||||
ui_handler->switch_app(descriptor);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "App descriptor not found for app: %s", app_name.c_str());
|
||||
}
|
||||
},
|
||||
LV_EVENT_CLICKED,
|
||||
new AppClickUserData { this, name }
|
||||
);
|
||||
}
|
||||
|
||||
// Register back button callback
|
||||
lv_event_dsc_t* back_event_dsc = nullptr;
|
||||
ret = root_layout_.register_back_button_callback(
|
||||
|
||||
Reference in New Issue
Block a user