#include "os_app.h" #include "os_gfx.h" #include "os_status.h" #include "os_event.h" #include #include "esp_log.h" static const char *TAG = "SYS_APP"; #define MAX_APPS 16 static const sys_app_t *s_registry[MAX_APPS]; static size_t s_app_count = 0; static const sys_app_t *s_current_app = NULL; static bool s_in_launcher = true; static size_t s_launcher_selected = 0; static void launcher_update(uint32_t delta_ms) { sys_status_t status; sys_status_get(&status); sys_gfx_draw_status_bar(&status); sys_gfx_draw_str_3x5(2, 9, "--- APPS ---", COLOR_WHITE); const char *names[MAX_APPS]; for (size_t i = 0; i < s_app_count; i++) { names[i] = s_registry[i]->name; } sys_gfx_draw_menu(15, names, s_app_count, s_launcher_selected); } static void launcher_handle_input(input_action_t action) { if (s_app_count == 0) return; if (action == INPUT_ACTION_CLICK) { s_launcher_selected = (s_launcher_selected + 1) % s_app_count; } else if (action == INPUT_ACTION_DOUBLE_CLICK) { if (s_launcher_selected == 0) { s_launcher_selected = s_app_count - 1; } else { s_launcher_selected--; } } else if (action == INPUT_ACTION_LONG_PRESS) { sys_app_launch_by_index(s_launcher_selected); } } esp_err_t sys_app_init(void) { s_app_count = 0; s_current_app = NULL; s_in_launcher = true; s_launcher_selected = 0; sys_status_set_active_app_name("Launcher"); ESP_LOGI(TAG, "App Manager initialized"); return ESP_OK; } esp_err_t sys_app_register(const sys_app_t *app) { if (!app || !app->id || !app->name) return ESP_ERR_INVALID_ARG; if (s_app_count >= MAX_APPS) return ESP_ERR_NO_MEM; s_registry[s_app_count++] = app; if (app->init) { app->init(); } ESP_LOGI(TAG, "Registered app: [%s] '%s'", app->id, app->name); return ESP_OK; } esp_err_t sys_app_launch_by_id(const char *id) { if (!id) return ESP_ERR_INVALID_ARG; for (size_t i = 0; i < s_app_count; i++) { if (strcmp(s_registry[i]->id, id) == 0) { return sys_app_launch_by_index(i); } } ESP_LOGW(TAG, "App not found: %s", id); return ESP_ERR_NOT_FOUND; } esp_err_t sys_app_launch_by_index(size_t index) { if (index >= s_app_count) return ESP_ERR_INVALID_ARG; if (s_current_app && s_current_app->exit) { s_current_app->exit(); } s_current_app = s_registry[index]; s_in_launcher = false; sys_status_set_active_app_name(s_current_app->name); if (s_current_app->enter) { s_current_app->enter(); } sys_event_post(SYS_EVENT_APP_SWITCH, (int32_t)index, (void *)s_current_app->id); sys_gfx_show_toast(s_current_app->name, 800); ESP_LOGI(TAG, "Switched to app: %s", s_current_app->name); return ESP_OK; } void sys_app_launch_launcher(void) { if (s_current_app && s_current_app->exit) { s_current_app->exit(); } s_current_app = NULL; s_in_launcher = true; sys_status_set_active_app_name("Launcher"); sys_gfx_show_toast("Launcher", 600); ESP_LOGI(TAG, "Returned to App Launcher"); } const sys_app_t *sys_app_get_current(void) { return s_current_app; } void sys_app_update(uint32_t delta_ms) { if (s_in_launcher) { launcher_update(delta_ms); } else if (s_current_app && s_current_app->update) { s_current_app->update(delta_ms); } } void sys_app_dispatch_input(input_action_t action) { if (action == INPUT_ACTION_HOLD_HOME) { sys_app_launch_launcher(); return; } if (s_in_launcher) { launcher_handle_input(action); } else if (s_current_app && s_current_app->handle_input) { s_current_app->handle_input(action); } } size_t sys_app_get_count(void) { return s_app_count; } const sys_app_t *sys_app_get_by_index(size_t index) { if (index >= s_app_count) return NULL; return s_registry[index]; }