Merge develop into main (#327)

## New features
- Implemented support for app packaging in firmware and `tactility.py`: load `.app` files instead of `.elf` files. Install apps remotely or via `FileBrowser`.
- Ensure headless mode works: all services that require LVGL can deal with the absence of a display
- Service `onStart()` is now allowed to fail (return `bool` result)
- Added and improved various file-related helper functions

## Improvements
- Completely revamped the SystemInfo app UI
- Improved Calculator UI of internal and external variant
- Fix Chat UI and removed the emoji buttons for now
- Fix for toolbar bottom padding issue in all apps

## Fixes
- Fix for allowing recursive locking for certain SPI SD cards
& more
This commit is contained in:
Ken Van Hoeylandt
2025-09-12 16:24:22 +02:00
committed by GitHub
parent 068600f98c
commit 84049658db
87 changed files with 1490 additions and 537 deletions
+16 -5
View File
@@ -86,11 +86,12 @@ void View::viewFile(const std::string& path, const std::string& filename) {
TT_LOG_I(TAG, "Clicked %s", file_path.c_str());
if (isSupportedExecutableFile(filename)) {
if (isSupportedAppFile(filename)) {
#ifdef ESP_PLATFORM
registerElfApp(processed_filepath);
auto app_id = getElfAppId(processed_filepath);
service::loader::startApp(app_id);
// install(filename);
auto message = std::format("Do you want to install {}?", filename);
installAppPath = processed_filepath;
installAppLaunchId = alertdialog::start("Install?", message, { "Yes", "No" });
#endif
} else if (isSupportedImageFile(filename)) {
imageviewer::start(processed_filepath);
@@ -253,6 +254,7 @@ void View::update() {
void View::init(lv_obj_t* parent) {
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT);
auto* toolbar = lvgl::toolbar_create(parent, "Files");
navigate_up_button = lvgl::toolbar_add_button_action(toolbar, LV_SYMBOL_UP, &onNavigateUpPressedCallback, this);
@@ -292,11 +294,20 @@ void View::onNavigate() {
}
}
void View::onResult(Result result, std::unique_ptr<Bundle> bundle) {
void View::onResult(LaunchId launchId, Result result, std::unique_ptr<Bundle> bundle) {
if (result != Result::Ok || bundle == nullptr) {
return;
}
if (
launchId == installAppLaunchId &&
result == Result::Ok &&
alertdialog::getResultIndex(*bundle) == 0
) {
install(installAppPath);
return;
}
std::string filepath = state->getSelectedChildPath();
TT_LOG_I(TAG, "Result for %s", filepath.c_str());