From 76c14a5f47b11ec8142935b08b342d4b2cc42ca5 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Sun, 24 Nov 2024 22:16:43 +0100 Subject: [PATCH] Sort apps on Desktop and Settings (#87) - Sort apps by name - Make manifest IDs consistent - Updated screenshots - Renamed Screenshot app so it always renders at the bottom of the app list --- Documentation/ideas.md | 7 ++----- Documentation/pics/screenshot-Desktop.png | Bin 4415 -> 3999 bytes Documentation/pics/screenshot-Settings.png | Bin 3616 -> 3862 bytes Tactility/Source/AppManifest.h | 4 ++++ Tactility/Source/AppManifestRegistry.cpp | 18 +++++------------ Tactility/Source/AppManifestRegistry.h | 6 ++---- Tactility/Source/Apps/Desktop/Desktop.cpp | 19 +++++++++++++++--- Tactility/Source/Apps/Display/Display.cpp | 2 +- Tactility/Source/Apps/Files/Files.cpp | 2 +- Tactility/Source/Apps/Gpio/Gpio.cpp | 2 +- Tactility/Source/Apps/Power/Power.cpp | 2 +- .../Source/Apps/Screenshot/Screenshot.cpp | 4 ++-- Tactility/Source/Apps/Settings/Settings.cpp | 13 +++++++++--- .../Source/Apps/SystemInfo/SystemInfo.cpp | 2 +- .../Source/Apps/WifiConnect/WifiConnect.cpp | 2 +- .../Source/Apps/WifiManager/WifiManage.cpp | 2 +- Tactility/Source/Tactility.cpp | 18 +++++++---------- .../Source/Services/Wifi/WifiEsp.cpp | 2 +- .../Source/Services/Wifi/WifiMock.cpp | 2 +- 19 files changed, 57 insertions(+), 50 deletions(-) diff --git a/Documentation/ideas.md b/Documentation/ideas.md index 2a75eadf..ebfdeee2 100644 --- a/Documentation/ideas.md +++ b/Documentation/ideas.md @@ -21,20 +21,17 @@ - Refactor hardware configuration init methods to return esp_err_t instead of bool # Core Ideas -- Make a HAL? It would mainly be there to support PC development. It's a lot of effort for supporting what's effectively a dev-only feature. - Support for displays with different DPI. Consider the layer-based system like on Android. - If present, use LED to show boot status - 2 wire speaker support -- tt_app_start() and similar functions as proxies for Loader app start/stop/etc. -- tt_app_set_result() for apps that need to return data to other apps (e.g. file selection) +- tt::startApp() and similar functions as proxies for Loader app start/stop/etc. +- tt::setAppResult() for apps that need to return data to other apps (e.g. file selection) - Wi-Fi using dispatcher to dispatch its main functionality to the dedicated Wi-Fi CPU core (to avoid main loop hack) # App Improvement Ideas -- Sort desktop apps by name. - Light/dark mode selection in Display settings app. # App Ideas -- File viewer (images, text... binary?) - BlueTooth keyboard app - Chip 8 emulator - BadUSB diff --git a/Documentation/pics/screenshot-Desktop.png b/Documentation/pics/screenshot-Desktop.png index f76598df70fac1397b8fd321e3add6b7a5eed6ea..2da8a0b993a576cdc012db464d1df614bbf750ac 100644 GIT binary patch literal 3999 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 Ao&W#< diff --git a/Documentation/pics/screenshot-Settings.png b/Documentation/pics/screenshot-Settings.png index a776921671c9fd8c830314fd89af1572c254ddf1..855bdbdfd427d9c995299a91134e84df894755ea 100644 GIT binary patch delta 3460 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 H#K?aEB7|ek delta 3211 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 diff --git a/Tactility/Source/AppManifest.h b/Tactility/Source/AppManifest.h index 8663bba8..d9e4f8ac 100644 --- a/Tactility/Source/AppManifest.h +++ b/Tactility/Source/AppManifest.h @@ -70,4 +70,8 @@ typedef struct AppManifest { const AppOnHide _Nullable on_hide = nullptr; } AppManifest; +struct { + bool operator()(const AppManifest* a, const AppManifest* b) const { return a->name < b->name; } +} SortAppManifestByName; + } // namespace diff --git a/Tactility/Source/AppManifestRegistry.cpp b/Tactility/Source/AppManifestRegistry.cpp index b9ab56f2..16ceb773 100644 --- a/Tactility/Source/AppManifestRegistry.cpp +++ b/Tactility/Source/AppManifestRegistry.cpp @@ -42,22 +42,14 @@ _Nullable const AppManifest * app_manifest_registry_find_by_id(const std::string return result; } -void app_manifest_registry_for_each_of_type(AppType type, void* _Nullable context, AppManifestCallback callback) { +std::vector app_manifest_registry_get() { + std::vector manifests; app_registry_lock(); - for (auto& it : app_manifest_map) { - if (it.second->type == type) { - callback(it.second, context); - } - } - app_registry_unlock(); -} - -void app_manifest_registry_for_each(AppManifestCallback callback, void* _Nullable context) { - app_registry_lock(); - for (auto& it : app_manifest_map) { - callback(it.second, context); + for (const auto& item: app_manifest_map) { + manifests.push_back(item.second); } app_registry_unlock(); + return manifests; } } // namespace diff --git a/Tactility/Source/AppManifestRegistry.h b/Tactility/Source/AppManifestRegistry.h index 9864552a..693f3528 100644 --- a/Tactility/Source/AppManifestRegistry.h +++ b/Tactility/Source/AppManifestRegistry.h @@ -2,16 +2,14 @@ #include "AppManifest.h" #include +#include namespace tt { -typedef void (*AppManifestCallback)(const AppManifest*, void* context); - void app_manifest_registry_init(); void app_manifest_registry_add(const AppManifest* manifest); void app_manifest_registry_remove(const AppManifest* manifest); const AppManifest _Nullable* app_manifest_registry_find_by_id(const std::string& id); -void app_manifest_registry_for_each(AppManifestCallback callback, void* _Nullable context); -void app_manifest_registry_for_each_of_type(AppType type, void* _Nullable context, AppManifestCallback callback); +std::vector app_manifest_registry_get(); } // namespace diff --git a/Tactility/Source/Apps/Desktop/Desktop.cpp b/Tactility/Source/Apps/Desktop/Desktop.cpp index 553892d7..71874b8e 100644 --- a/Tactility/Source/Apps/Desktop/Desktop.cpp +++ b/Tactility/Source/Apps/Desktop/Desktop.cpp @@ -2,6 +2,7 @@ #include "Assets.h" #include "Check.h" #include "lvgl.h" +#include #include "Services/Loader/Loader.h" namespace tt::app::desktop { @@ -27,14 +28,26 @@ static void desktop_show(TT_UNUSED App app, lv_obj_t* parent) { lv_obj_set_size(list, LV_PCT(100), LV_PCT(100)); lv_obj_center(list); + auto manifests = app_manifest_registry_get(); + std::sort(manifests.begin(), manifests.end(), SortAppManifestByName); + lv_list_add_text(list, "User"); - app_manifest_registry_for_each_of_type(AppTypeUser, list, create_app_widget); + for (const auto& manifest: manifests) { + if (manifest->type == AppTypeUser) { + create_app_widget(manifest, list); + } + } + lv_list_add_text(list, "System"); - app_manifest_registry_for_each_of_type(AppTypeSystem, list, create_app_widget); + for (const auto& manifest: manifests) { + if (manifest->type == AppTypeSystem) { + create_app_widget(manifest, list); + } + } } extern const AppManifest manifest = { - .id = "desktop", + .id = "Desktop", .name = "Desktop", .type = AppTypeDesktop, .on_show = &desktop_show, diff --git a/Tactility/Source/Apps/Display/Display.cpp b/Tactility/Source/Apps/Display/Display.cpp index 1523588d..09823d94 100644 --- a/Tactility/Source/Apps/Display/Display.cpp +++ b/Tactility/Source/Apps/Display/Display.cpp @@ -121,7 +121,7 @@ static void app_hide(TT_UNUSED App app) { } extern const AppManifest manifest = { - .id = "display", + .id = "Display", .name = "Display", .icon = TT_ASSETS_APP_ICON_DISPLAY_SETTINGS, .type = AppTypeSettings, diff --git a/Tactility/Source/Apps/Files/Files.cpp b/Tactility/Source/Apps/Files/Files.cpp index 773e781f..449d22dc 100644 --- a/Tactility/Source/Apps/Files/Files.cpp +++ b/Tactility/Source/Apps/Files/Files.cpp @@ -222,7 +222,7 @@ static void on_stop(App app) { // endregion Lifecycle extern const AppManifest manifest = { - .id = "files", + .id = "Files", .name = "Files", .icon = TT_ASSETS_APP_ICON_FILES, .type = AppTypeSystem, diff --git a/Tactility/Source/Apps/Gpio/Gpio.cpp b/Tactility/Source/Apps/Gpio/Gpio.cpp index 6bf75be6..5781525f 100644 --- a/Tactility/Source/Apps/Gpio/Gpio.cpp +++ b/Tactility/Source/Apps/Gpio/Gpio.cpp @@ -201,7 +201,7 @@ static void on_stop(App app) { // endregion App lifecycle extern const AppManifest manifest = { - .id = "gpio", + .id = "Gpio", .name = "GPIO", .type = AppTypeSystem, .on_start = &on_start, diff --git a/Tactility/Source/Apps/Power/Power.cpp b/Tactility/Source/Apps/Power/Power.cpp index 92c2eee1..18956d91 100644 --- a/Tactility/Source/Apps/Power/Power.cpp +++ b/Tactility/Source/Apps/Power/Power.cpp @@ -110,7 +110,7 @@ static void app_stop(App app) { } extern const AppManifest manifest = { - .id = "power", + .id = "Power", .name = "Power", .icon = TT_ASSETS_APP_ICON_POWER_SETTINGS, .type = AppTypeSettings, diff --git a/Tactility/Source/Apps/Screenshot/Screenshot.cpp b/Tactility/Source/Apps/Screenshot/Screenshot.cpp index 5d4d45e2..9cd5d081 100644 --- a/Tactility/Source/Apps/Screenshot/Screenshot.cpp +++ b/Tactility/Source/Apps/Screenshot/Screenshot.cpp @@ -18,8 +18,8 @@ static void on_stop(App app) { } extern const AppManifest manifest = { - .id = "screenshot", - .name = "Screenshot", + .id = "Screenshot", + .name = "_Screenshot", // So it gets put at the bottom of the desktop and becomes less visible on small screen devices .icon = LV_SYMBOL_IMAGE, .type = AppTypeSystem, .on_start = &on_start, diff --git a/Tactility/Source/Apps/Settings/Settings.cpp b/Tactility/Source/Apps/Settings/Settings.cpp index 4e58c64e..cfc743b5 100644 --- a/Tactility/Source/Apps/Settings/Settings.cpp +++ b/Tactility/Source/Apps/Settings/Settings.cpp @@ -1,9 +1,10 @@ #include "AppManifestRegistry.h" #include "Assets.h" #include "Check.h" -#include "lvgl.h" #include "Services/Loader/Loader.h" #include "Ui/Toolbar.h" +#include "lvgl.h" +#include namespace tt::app::settings { @@ -32,11 +33,17 @@ static void on_show(App app, lv_obj_t* parent) { lv_obj_set_width(list, LV_PCT(100)); lv_obj_set_flex_grow(list, 1); - app_manifest_registry_for_each_of_type(AppTypeSettings, list, create_app_widget); + auto manifests = app_manifest_registry_get(); + std::sort(manifests.begin(), manifests.end(), SortAppManifestByName); + for (const auto& manifest: manifests) { + if (manifest->type == AppTypeSettings) { + create_app_widget(manifest, list); + } + } } extern const AppManifest manifest = { - .id = "settings", + .id = "Settings", .name = "Settings", .icon = TT_ASSETS_APP_ICON_SETTINGS, .type = AppTypeSystem, diff --git a/Tactility/Source/Apps/SystemInfo/SystemInfo.cpp b/Tactility/Source/Apps/SystemInfo/SystemInfo.cpp index 57fcb4c5..fb390e04 100644 --- a/Tactility/Source/Apps/SystemInfo/SystemInfo.cpp +++ b/Tactility/Source/Apps/SystemInfo/SystemInfo.cpp @@ -102,7 +102,7 @@ static void on_show(App app, lv_obj_t* parent) { } extern const AppManifest manifest = { - .id = "systeminfo", + .id = "SystemInfo", .name = "System Info", .icon = TT_ASSETS_APP_ICON_SYSTEM_INFO, .type = AppTypeSystem, diff --git a/Tactility/Source/Apps/WifiConnect/WifiConnect.cpp b/Tactility/Source/Apps/WifiConnect/WifiConnect.cpp index fd5b0686..1457d7f8 100644 --- a/Tactility/Source/Apps/WifiConnect/WifiConnect.cpp +++ b/Tactility/Source/Apps/WifiConnect/WifiConnect.cpp @@ -133,7 +133,7 @@ static void app_stop(App app) { } extern const AppManifest manifest = { - .id = "wifi_connect", + .id = "WifiConnect", .name = "Wi-Fi Connect", .icon = LV_SYMBOL_WIFI, .type = AppTypeSettings, diff --git a/Tactility/Source/Apps/WifiManager/WifiManage.cpp b/Tactility/Source/Apps/WifiManager/WifiManage.cpp index 1b72033d..ea15a39e 100644 --- a/Tactility/Source/Apps/WifiManager/WifiManage.cpp +++ b/Tactility/Source/Apps/WifiManager/WifiManage.cpp @@ -26,7 +26,7 @@ static void on_connect(const char* ssid) { Bundle bundle; bundle.putString(WIFI_CONNECT_PARAM_SSID, ssid); bundle.putString(WIFI_CONNECT_PARAM_PASSWORD, ""); - service::loader::start_app("wifi_connect", false, bundle); + service::loader::start_app("WifiConnect", false, bundle); } } diff --git a/Tactility/Source/Tactility.cpp b/Tactility/Source/Tactility.cpp index b6b0cc84..765f14c3 100644 --- a/Tactility/Source/Tactility.cpp +++ b/Tactility/Source/Tactility.cpp @@ -21,7 +21,7 @@ namespace service { namespace statusbar { extern const ServiceManifest manifest; } } -static const ServiceManifest* const system_services[] = { +static const std::vector system_services = { &service::loader::manifest, &service::gui::manifest, // depends on loader service #ifndef ESP_PLATFORM // Screenshots don't work yet on ESP32 @@ -54,7 +54,7 @@ namespace app { extern const AppManifest screenshot_app; #endif -static const AppManifest* const system_apps[] = { +static const std::vector system_apps = { &app::desktop::manifest, &app::files::manifest, &app::gpio::manifest, @@ -75,10 +75,8 @@ static const AppManifest* const system_apps[] = { static void register_system_apps() { TT_LOG_I(TAG, "Registering default apps"); - - int app_count = sizeof(system_apps) / sizeof(AppManifest*); - for (int i = 0; i < app_count; ++i) { - app_manifest_registry_add(system_apps[i]); + for (const auto& app_manifest: system_apps) { + app_manifest_registry_add(app_manifest); } if (getConfiguration()->hardware->power != nullptr) { @@ -101,10 +99,9 @@ static void register_user_apps(const AppManifest* const apps[TT_CONFIG_APPS_LIMI static void register_and_start_system_services() { TT_LOG_I(TAG, "Registering and starting system services"); - int app_count = sizeof(system_services) / sizeof(ServiceManifest*); - for (int i = 0; i < app_count; ++i) { - service_registry_add(system_services[i]); - tt_check(service_registry_start(system_services[i]->id)); + for (const auto& service_manifest: system_services) { + service_registry_add(service_manifest); + tt_check(service_registry_start(service_manifest->id)); } } @@ -125,7 +122,6 @@ static void register_and_start_user_services(const ServiceManifest* const servic void init(const Configuration* config) { TT_LOG_I(TAG, "init started"); - // Assign early so starting services can use it config_instance = config; diff --git a/TactilityHeadless/Source/Services/Wifi/WifiEsp.cpp b/TactilityHeadless/Source/Services/Wifi/WifiEsp.cpp index c7a4fad9..cad9bcee 100644 --- a/TactilityHeadless/Source/Services/Wifi/WifiEsp.cpp +++ b/TactilityHeadless/Source/Services/Wifi/WifiEsp.cpp @@ -745,7 +745,7 @@ static void service_stop(Service& service) { } extern const ServiceManifest manifest = { - .id = "wifi", + .id = "Wifi", .on_start = &service_start, .on_stop = &service_stop }; diff --git a/TactilityHeadless/Source/Services/Wifi/WifiMock.cpp b/TactilityHeadless/Source/Services/Wifi/WifiMock.cpp index 1e1bc8e0..601e39c5 100644 --- a/TactilityHeadless/Source/Services/Wifi/WifiMock.cpp +++ b/TactilityHeadless/Source/Services/Wifi/WifiMock.cpp @@ -177,7 +177,7 @@ static void service_stop(TT_UNUSED Service& service) { } extern const ServiceManifest manifest = { - .id = "wifi", + .id = "Wifi", .on_start = &service_start, .on_stop = &service_stop };