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
This commit is contained in:
Ken Van Hoeylandt 2024-11-24 22:16:43 +01:00 committed by GitHub
parent caa8756998
commit 76c14a5f47
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 57 additions and 50 deletions

View File

@ -21,20 +21,17 @@
- Refactor hardware configuration init methods to return esp_err_t instead of bool - Refactor hardware configuration init methods to return esp_err_t instead of bool
# Core Ideas # 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. - Support for displays with different DPI. Consider the layer-based system like on Android.
- If present, use LED to show boot status - If present, use LED to show boot status
- 2 wire speaker support - 2 wire speaker support
- tt_app_start() and similar functions as proxies for Loader app start/stop/etc. - tt::startApp() 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::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) - Wi-Fi using dispatcher to dispatch its main functionality to the dedicated Wi-Fi CPU core (to avoid main loop hack)
# App Improvement Ideas # App Improvement Ideas
- Sort desktop apps by name.
- Light/dark mode selection in Display settings app. - Light/dark mode selection in Display settings app.
# App Ideas # App Ideas
- File viewer (images, text... binary?)
- BlueTooth keyboard app - BlueTooth keyboard app
- Chip 8 emulator - Chip 8 emulator
- BadUSB - BadUSB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -70,4 +70,8 @@ typedef struct AppManifest {
const AppOnHide _Nullable on_hide = nullptr; const AppOnHide _Nullable on_hide = nullptr;
} AppManifest; } AppManifest;
struct {
bool operator()(const AppManifest* a, const AppManifest* b) const { return a->name < b->name; }
} SortAppManifestByName;
} // namespace } // namespace

View File

@ -42,22 +42,14 @@ _Nullable const AppManifest * app_manifest_registry_find_by_id(const std::string
return result; return result;
} }
void app_manifest_registry_for_each_of_type(AppType type, void* _Nullable context, AppManifestCallback callback) { std::vector<const AppManifest*> app_manifest_registry_get() {
std::vector<const AppManifest*> manifests;
app_registry_lock(); app_registry_lock();
for (auto& it : app_manifest_map) { for (const auto& item: app_manifest_map) {
if (it.second->type == type) { manifests.push_back(item.second);
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);
} }
app_registry_unlock(); app_registry_unlock();
return manifests;
} }
} // namespace } // namespace

View File

@ -2,16 +2,14 @@
#include "AppManifest.h" #include "AppManifest.h"
#include <string> #include <string>
#include <vector>
namespace tt { namespace tt {
typedef void (*AppManifestCallback)(const AppManifest*, void* context);
void app_manifest_registry_init(); void app_manifest_registry_init();
void app_manifest_registry_add(const AppManifest* manifest); void app_manifest_registry_add(const AppManifest* manifest);
void app_manifest_registry_remove(const AppManifest* manifest); void app_manifest_registry_remove(const AppManifest* manifest);
const AppManifest _Nullable* app_manifest_registry_find_by_id(const std::string& id); const AppManifest _Nullable* app_manifest_registry_find_by_id(const std::string& id);
void app_manifest_registry_for_each(AppManifestCallback callback, void* _Nullable context); std::vector<const AppManifest*> app_manifest_registry_get();
void app_manifest_registry_for_each_of_type(AppType type, void* _Nullable context, AppManifestCallback callback);
} // namespace } // namespace

View File

@ -2,6 +2,7 @@
#include "Assets.h" #include "Assets.h"
#include "Check.h" #include "Check.h"
#include "lvgl.h" #include "lvgl.h"
#include <algorithm>
#include "Services/Loader/Loader.h" #include "Services/Loader/Loader.h"
namespace tt::app::desktop { 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_set_size(list, LV_PCT(100), LV_PCT(100));
lv_obj_center(list); lv_obj_center(list);
auto manifests = app_manifest_registry_get();
std::sort(manifests.begin(), manifests.end(), SortAppManifestByName);
lv_list_add_text(list, "User"); 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"); 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 = { extern const AppManifest manifest = {
.id = "desktop", .id = "Desktop",
.name = "Desktop", .name = "Desktop",
.type = AppTypeDesktop, .type = AppTypeDesktop,
.on_show = &desktop_show, .on_show = &desktop_show,

View File

@ -121,7 +121,7 @@ static void app_hide(TT_UNUSED App app) {
} }
extern const AppManifest manifest = { extern const AppManifest manifest = {
.id = "display", .id = "Display",
.name = "Display", .name = "Display",
.icon = TT_ASSETS_APP_ICON_DISPLAY_SETTINGS, .icon = TT_ASSETS_APP_ICON_DISPLAY_SETTINGS,
.type = AppTypeSettings, .type = AppTypeSettings,

View File

@ -222,7 +222,7 @@ static void on_stop(App app) {
// endregion Lifecycle // endregion Lifecycle
extern const AppManifest manifest = { extern const AppManifest manifest = {
.id = "files", .id = "Files",
.name = "Files", .name = "Files",
.icon = TT_ASSETS_APP_ICON_FILES, .icon = TT_ASSETS_APP_ICON_FILES,
.type = AppTypeSystem, .type = AppTypeSystem,

View File

@ -201,7 +201,7 @@ static void on_stop(App app) {
// endregion App lifecycle // endregion App lifecycle
extern const AppManifest manifest = { extern const AppManifest manifest = {
.id = "gpio", .id = "Gpio",
.name = "GPIO", .name = "GPIO",
.type = AppTypeSystem, .type = AppTypeSystem,
.on_start = &on_start, .on_start = &on_start,

View File

@ -110,7 +110,7 @@ static void app_stop(App app) {
} }
extern const AppManifest manifest = { extern const AppManifest manifest = {
.id = "power", .id = "Power",
.name = "Power", .name = "Power",
.icon = TT_ASSETS_APP_ICON_POWER_SETTINGS, .icon = TT_ASSETS_APP_ICON_POWER_SETTINGS,
.type = AppTypeSettings, .type = AppTypeSettings,

View File

@ -18,8 +18,8 @@ static void on_stop(App app) {
} }
extern const AppManifest manifest = { extern const AppManifest manifest = {
.id = "screenshot", .id = "Screenshot",
.name = "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, .icon = LV_SYMBOL_IMAGE,
.type = AppTypeSystem, .type = AppTypeSystem,
.on_start = &on_start, .on_start = &on_start,

View File

@ -1,9 +1,10 @@
#include "AppManifestRegistry.h" #include "AppManifestRegistry.h"
#include "Assets.h" #include "Assets.h"
#include "Check.h" #include "Check.h"
#include "lvgl.h"
#include "Services/Loader/Loader.h" #include "Services/Loader/Loader.h"
#include "Ui/Toolbar.h" #include "Ui/Toolbar.h"
#include "lvgl.h"
#include <algorithm>
namespace tt::app::settings { 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_width(list, LV_PCT(100));
lv_obj_set_flex_grow(list, 1); 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 = { extern const AppManifest manifest = {
.id = "settings", .id = "Settings",
.name = "Settings", .name = "Settings",
.icon = TT_ASSETS_APP_ICON_SETTINGS, .icon = TT_ASSETS_APP_ICON_SETTINGS,
.type = AppTypeSystem, .type = AppTypeSystem,

View File

@ -102,7 +102,7 @@ static void on_show(App app, lv_obj_t* parent) {
} }
extern const AppManifest manifest = { extern const AppManifest manifest = {
.id = "systeminfo", .id = "SystemInfo",
.name = "System Info", .name = "System Info",
.icon = TT_ASSETS_APP_ICON_SYSTEM_INFO, .icon = TT_ASSETS_APP_ICON_SYSTEM_INFO,
.type = AppTypeSystem, .type = AppTypeSystem,

View File

@ -133,7 +133,7 @@ static void app_stop(App app) {
} }
extern const AppManifest manifest = { extern const AppManifest manifest = {
.id = "wifi_connect", .id = "WifiConnect",
.name = "Wi-Fi Connect", .name = "Wi-Fi Connect",
.icon = LV_SYMBOL_WIFI, .icon = LV_SYMBOL_WIFI,
.type = AppTypeSettings, .type = AppTypeSettings,

View File

@ -26,7 +26,7 @@ static void on_connect(const char* ssid) {
Bundle bundle; Bundle bundle;
bundle.putString(WIFI_CONNECT_PARAM_SSID, ssid); bundle.putString(WIFI_CONNECT_PARAM_SSID, ssid);
bundle.putString(WIFI_CONNECT_PARAM_PASSWORD, ""); bundle.putString(WIFI_CONNECT_PARAM_PASSWORD, "");
service::loader::start_app("wifi_connect", false, bundle); service::loader::start_app("WifiConnect", false, bundle);
} }
} }

View File

@ -21,7 +21,7 @@ namespace service {
namespace statusbar { extern const ServiceManifest manifest; } namespace statusbar { extern const ServiceManifest manifest; }
} }
static const ServiceManifest* const system_services[] = { static const std::vector<const ServiceManifest*> system_services = {
&service::loader::manifest, &service::loader::manifest,
&service::gui::manifest, // depends on loader service &service::gui::manifest, // depends on loader service
#ifndef ESP_PLATFORM // Screenshots don't work yet on ESP32 #ifndef ESP_PLATFORM // Screenshots don't work yet on ESP32
@ -54,7 +54,7 @@ namespace app {
extern const AppManifest screenshot_app; extern const AppManifest screenshot_app;
#endif #endif
static const AppManifest* const system_apps[] = { static const std::vector<const AppManifest*> system_apps = {
&app::desktop::manifest, &app::desktop::manifest,
&app::files::manifest, &app::files::manifest,
&app::gpio::manifest, &app::gpio::manifest,
@ -75,10 +75,8 @@ static const AppManifest* const system_apps[] = {
static void register_system_apps() { static void register_system_apps() {
TT_LOG_I(TAG, "Registering default apps"); TT_LOG_I(TAG, "Registering default apps");
for (const auto& app_manifest: system_apps) {
int app_count = sizeof(system_apps) / sizeof(AppManifest*); app_manifest_registry_add(app_manifest);
for (int i = 0; i < app_count; ++i) {
app_manifest_registry_add(system_apps[i]);
} }
if (getConfiguration()->hardware->power != nullptr) { 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() { static void register_and_start_system_services() {
TT_LOG_I(TAG, "Registering and starting system services"); TT_LOG_I(TAG, "Registering and starting system services");
int app_count = sizeof(system_services) / sizeof(ServiceManifest*); for (const auto& service_manifest: system_services) {
for (int i = 0; i < app_count; ++i) { service_registry_add(service_manifest);
service_registry_add(system_services[i]); tt_check(service_registry_start(service_manifest->id));
tt_check(service_registry_start(system_services[i]->id));
} }
} }
@ -125,7 +122,6 @@ static void register_and_start_user_services(const ServiceManifest* const servic
void init(const Configuration* config) { void init(const Configuration* config) {
TT_LOG_I(TAG, "init started"); TT_LOG_I(TAG, "init started");
// Assign early so starting services can use it // Assign early so starting services can use it
config_instance = config; config_instance = config;

View File

@ -745,7 +745,7 @@ static void service_stop(Service& service) {
} }
extern const ServiceManifest manifest = { extern const ServiceManifest manifest = {
.id = "wifi", .id = "Wifi",
.on_start = &service_start, .on_start = &service_start,
.on_stop = &service_stop .on_stop = &service_stop
}; };

View File

@ -177,7 +177,7 @@ static void service_stop(TT_UNUSED Service& service) {
} }
extern const ServiceManifest manifest = { extern const ServiceManifest manifest = {
.id = "wifi", .id = "Wifi",
.on_start = &service_start, .on_start = &service_start,
.on_stop = &service_stop .on_stop = &service_stop
}; };