Created app settings and app details applications (#364)

This commit is contained in:
Ken Van Hoeylandt 2025-10-07 22:13:01 +02:00 committed by GitHub
parent 45a8379426
commit 17b4fc6a47
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 193 additions and 0 deletions

View File

@ -0,0 +1,9 @@
#pragma once
#include <string>
namespace tt::app::appdetails {
void start(const std::string& appId);
} // namespace

View File

@ -57,7 +57,9 @@ namespace service {
namespace app { namespace app {
namespace addgps { extern const AppManifest manifest; } namespace addgps { extern const AppManifest manifest; }
namespace alertdialog { extern const AppManifest manifest; } namespace alertdialog { extern const AppManifest manifest; }
namespace appdetails { extern const AppManifest manifest; }
namespace applist { extern const AppManifest manifest; } namespace applist { extern const AppManifest manifest; }
namespace appsettings { extern const AppManifest manifest; }
namespace boot { extern const AppManifest manifest; } namespace boot { extern const AppManifest manifest; }
namespace chat { extern const AppManifest manifest; } namespace chat { extern const AppManifest manifest; }
namespace development { extern const AppManifest manifest; } namespace development { extern const AppManifest manifest; }
@ -99,7 +101,9 @@ namespace app {
// List of all apps excluding Boot app (as Boot app calls this function indirectly) // List of all apps excluding Boot app (as Boot app calls this function indirectly)
static void registerInternalApps() { static void registerInternalApps() {
addApp(app::alertdialog::manifest); addApp(app::alertdialog::manifest);
addApp(app::appdetails::manifest);
addApp(app::applist::manifest); addApp(app::applist::manifest);
addApp(app::appsettings::manifest);
addApp(app::display::manifest); addApp(app::display::manifest);
addApp(app::files::manifest); addApp(app::files::manifest);
addApp(app::fileselection::manifest); addApp(app::fileselection::manifest);

View File

@ -0,0 +1,114 @@
#include "Tactility/lvgl/LvglSync.h"
#include <Tactility/app/App.h>
#include <Tactility/app/AppContext.h>
#include <Tactility/app/AppManifest.h>
#include <Tactility/app/alertdialog/AlertDialog.h>
#include <Tactility/lvgl/Style.h>
#include <Tactility/lvgl/Toolbar.h>
#include <Tactility/TactilityCore.h>
#include <lvgl.h>
#include <format>
#include <Tactility/StringUtils.h>
#include <Tactility/file/File.h>
namespace tt::app::appdetails {
extern const AppManifest manifest;
void start(const std::string& appId) {
auto bundle = std::make_shared<Bundle>();
bundle->putString("appId", appId);
app::start(manifest.appId, bundle);
}
class AppDetailsApp : public App {
std::shared_ptr<AppManifest> manifest;
static void onPressUninstall(TT_UNUSED lv_event_t* event) {
auto* self = static_cast<AppDetailsApp*>(lv_event_get_user_data(event));
std::vector<std::string> choices = {
"Yes",
"No"
};
alertdialog::start("Confirmation", std::format("Uninstall {}?", self->manifest->appName), choices);
}
public:
void onCreate(AppContext& app) override {
const auto parameters = app.getParameters();
tt_check(parameters != nullptr, "Parameters missing");
auto app_id = parameters->getString("appId");
manifest = findAppById(app_id);
assert(manifest != nullptr);
}
void onShow(AppContext& app, lv_obj_t* parent) override {
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
lv_obj_set_style_pad_row(parent, 0, LV_STATE_DEFAULT);
auto title = std::format("{} details", manifest->appName);
lvgl::toolbar_create(parent, title);
auto* wrapper = lv_obj_create(parent);
lv_obj_set_width(wrapper, LV_PCT(100));
lv_obj_set_flex_grow(wrapper, 1);
lv_obj_set_flex_flow(wrapper, LV_FLEX_FLOW_COLUMN);
lv_obj_set_style_border_width(wrapper, 0, LV_STATE_DEFAULT);
lvgl::obj_set_style_bg_invisible(wrapper);
auto identifier = std::format("Identifier: {}", manifest->appId);
auto* identifier_label = lv_label_create(wrapper);
lv_label_set_text(identifier_label, identifier.c_str());
auto* location_label = lv_label_create(wrapper);
std::string location;
if (manifest->appLocation.isInternal()) {
location = "internal";
} else {
if (!string::getPathParent(manifest->appLocation.getPath(), location)) {
location = "external";
}
}
std::string location_label_text = std::format("Location: {}", location);
lv_label_set_text(location_label, location_label_text.c_str());
if (manifest->appLocation.isExternal()) {
auto* uninstall_button = lv_button_create(wrapper);
lv_obj_set_width(uninstall_button, LV_PCT(100));
lv_obj_add_event_cb(uninstall_button, onPressUninstall, LV_EVENT_SHORT_CLICKED, this);
auto* uninstall_label = lv_label_create(uninstall_button);
lv_obj_align(uninstall_label, LV_ALIGN_CENTER, 0, 0);
lv_label_set_text(uninstall_label, "Uninstall");
}
}
void onResult(TT_UNUSED AppContext& appContext, TT_UNUSED LaunchId launchId, TT_UNUSED Result result, std::unique_ptr<Bundle> bundle) override {
if (result != Result::Ok || bundle == nullptr) {
return;
}
if (alertdialog::getResultIndex(*bundle) != 0) { // 0 = Yes
return;
}
uninstall(manifest->appId);
// Stop app
stop();
}
};
extern const AppManifest manifest = {
.appId = "AppDetails",
.appName = "App Details",
.appCategory = Category::System,
.appFlags = AppManifest::Flags::Hidden,
.createApp = create<AppDetailsApp>
};
} // namespace

View File

@ -0,0 +1,66 @@
#include <Tactility/app/appdetails/AppDetails.h>
#include <Tactility/app/AppRegistration.h>
#include <Tactility/service/loader/Loader.h>
#include <Tactility/lvgl/Toolbar.h>
#include <Tactility/Assets.h>
#include <lvgl.h>
#include <algorithm>
namespace tt::app::appsettings {
class AppSettingsApp final : public App {
static void onAppPressed(lv_event_t* e) {
const auto* manifest = static_cast<const AppManifest*>(lv_event_get_user_data(e));
appdetails::start(manifest->appId);
}
static void createAppWidget(const std::shared_ptr<AppManifest>& manifest, lv_obj_t* list) {
const void* icon = !manifest->appIcon.empty() ? manifest->appIcon.c_str() : TT_ASSETS_APP_ICON_FALLBACK;
lv_obj_t* btn = lv_list_add_button(list, icon, manifest->appName.c_str());
lv_obj_add_event_cb(btn, &onAppPressed, LV_EVENT_SHORT_CLICKED, manifest.get());
}
public:
void onShow(TT_UNUSED AppContext& app, lv_obj_t* parent) override {
auto* toolbar = lvgl::toolbar_create(parent, "External Apps");
lv_obj_align(toolbar, LV_ALIGN_TOP_MID, 0, 0);
lv_obj_t* list = lv_list_create(parent);
lv_obj_set_width(list, LV_PCT(100));
lv_obj_align_to(list, toolbar, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
auto toolbar_height = lv_obj_get_height(toolbar);
auto parent_content_height = lv_obj_get_content_height(parent);
lv_obj_set_height(list, parent_content_height - toolbar_height);
auto manifests = getApps();
std::ranges::sort(manifests, SortAppManifestByName);
size_t app_count = 0;
for (const auto& manifest: manifests) {
if (manifest->appLocation.isExternal()) {
app_count++;
createAppWidget(manifest, list);
}
}
if (app_count == 0) {
auto* no_apps_label = lv_label_create(parent);
lv_label_set_text(no_apps_label, "No apps installed");
lv_obj_align(no_apps_label, LV_ALIGN_CENTER, 0, 0);
}
}
};
extern const AppManifest manifest = {
.appId = "AppSettings",
.appName = "Apps",
.appCategory = Category::Settings,
.createApp = create<AppSettingsApp>,
};
} // namespace