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
# 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

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;
} AppManifest;
struct {
bool operator()(const AppManifest* a, const AppManifest* b) const { return a->name < b->name; }
} SortAppManifestByName;
} // namespace

View File

@ -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<const AppManifest*> app_manifest_registry_get() {
std::vector<const AppManifest*> 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

View File

@ -2,16 +2,14 @@
#include "AppManifest.h"
#include <string>
#include <vector>
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<const AppManifest*> app_manifest_registry_get();
} // namespace

View File

@ -2,6 +2,7 @@
#include "Assets.h"
#include "Check.h"
#include "lvgl.h"
#include <algorithm>
#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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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 <algorithm>
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,

View File

@ -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,

View File

@ -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,

View File

@ -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);
}
}

View File

@ -21,7 +21,7 @@ namespace service {
namespace statusbar { extern const ServiceManifest manifest; }
}
static const ServiceManifest* const system_services[] = {
static const std::vector<const ServiceManifest*> 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<const AppManifest*> 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;

View File

@ -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
};

View File

@ -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
};