Merge develop into main (#343)

- Refactor `AppManifest`: add new fields and rename existing ones
- Parse and validate the manifest from an app that is being installed.
- Remove deprecated `scoped()` from `Lock`
- Create `Tactility/Paths.h`
- App loading at boot now properly parses the manifest files of external apps
- Properly lock both source and destination locations during app install
- Remove LVGL path variants from `AppPaths` and `ServicePaths`
- Removed `xPath` base classes for apps and services. There's now `AppPaths` and `ServicePaths`.
- Renamed app and service paths: "data" and "system" paths are now "user data" and "assets"
This commit is contained in:
Ken Van Hoeylandt
2025-09-22 08:03:21 +02:00
committed by GitHub
parent a4d15b2a1e
commit bab3eb19bc
108 changed files with 817 additions and 757 deletions
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include <string>
namespace tt {
bool findFirstMountedSdCardPath(std::string& path);
std::string getSystemRootPath();
std::string getTempPath();
std::string getAppInstallPath();
std::string getAppInstallPath(const std::string& appId);
std::string getUserPath();
std::string getAppUserPath(const std::string& appId);
}
-4
View File
@@ -94,10 +94,6 @@ std::shared_ptr<AppContext> _Nullable getCurrentAppContext();
/** @return the currently running app (it is only ever null before the splash screen is shown) */
std::shared_ptr<App> _Nullable getCurrentApp();
std::string getTempPath();
std::string getInstallPath();
bool install(const std::string& path);
bool uninstall(const std::string& appId);
+2 -62
View File
@@ -7,7 +7,7 @@ namespace tt::app {
// Forward declarations
class App;
class Paths;
class AppPaths;
struct AppManifest;
enum class Result;
@@ -32,70 +32,10 @@ public:
virtual const AppManifest& getManifest() const = 0;
virtual std::shared_ptr<const Bundle> getParameters() const = 0;
virtual std::unique_ptr<Paths> getPaths() const = 0;
virtual std::unique_ptr<AppPaths> getPaths() const = 0;
virtual std::shared_ptr<App> getApp() const = 0;
};
class Paths {
public:
Paths() = default;
virtual ~Paths() = default;
/**
* Returns the directory path for the data location for an app.
* The data directory is intended to survive OS upgrades.
* The path will not end with a "/".
*/
virtual std::string getDataDirectory() const = 0;
/**
* @see getDataDirectory(), but with LVGL prefix.
*/
virtual std::string getDataDirectoryLvgl() const = 0;
/**
* Returns the full path for an entry inside the data location for an app.
* The data directory is intended to survive OS upgrades.
* Configuration data should be stored here.
* @param[in] childPath the path without a "/" prefix
*/
virtual std::string getDataPath(const std::string& childPath) const = 0;
/**
* @see getDataPath(), but with LVGL prefix.
*/
virtual std::string getDataPathLvgl(const std::string& childPath) const = 0;
/**
* Returns the directory path for the system location for an app.
* The system directory is not intended to survive OS upgrades.
* You should not store configuration data here.
* The path will not end with a "/".
* This is mainly used for core apps (system/boot/settings type).
*/
virtual std::string getSystemDirectory() const = 0;
/**
* @see getSystemDirectory(), but with LVGL prefix.
*/
virtual std::string getSystemDirectoryLvgl() const = 0;
/**
* Returns the full path for an entry inside the system location for an app.
* The data directory is not intended to survive OS upgrades.
* You should not store configuration data here.
* This is mainly used for core apps (system/boot/settings type).
* @param[in] childPath the path without a "/" prefix
*/
virtual std::string getSystemPath(const std::string& childPath) const = 0;
/**
* @see getSystemPath(), but with LVGL prefix.
*/
virtual std::string getSystemPathLvgl(const std::string& childPath) const = 0;
};
}
+22 -7
View File
@@ -63,30 +63,45 @@ struct AppManifest {
constexpr static uint32_t Hidden = 1 << 1;
};
/** The version of the manifest file format */
std::string manifestVersion = {};
/** The SDK version that was used to compile this app. (e.g. "0.6.0") */
std::string targetSdk = {};
/** Comma-separated list of platforms, e.g. "esp32,esp32s3" */
std::string targetPlatforms = {};
/** The identifier by which the app is launched by the system and other apps. */
std::string id = {};
std::string appId = {};
/** The user-readable name of the app. Used in UI. */
std::string name = {};
std::string appName = {};
/** Optional icon. */
std::string icon = {};
std::string appIcon = {};
/** The version as it is displayed to the user (e.g. "1.2.0") */
std::string appVersionName = {};
/** The technical version (must be incremented with new releases of the app */
uint64_t appVersionCode = {};
/** App category helps with listing apps in Launcher, app list or settings apps. */
Category category = Category::User;
Category appCategory = Category::User;
/** Where the app is located */
Location location = Location::internal();
Location appLocation = Location::internal();
/** Controls various settings */
uint32_t flags = Flags::None;
uint32_t appFlags = Flags::None;
/** Create the instance of the app */
CreateApp createApp = nullptr;
};
struct {
bool operator()(const std::shared_ptr<AppManifest>& left, const std::shared_ptr<AppManifest>& right) const { return left->name < right->name; }
bool operator()(const std::shared_ptr<AppManifest>& left, const std::shared_ptr<AppManifest>& right) const { return left->appName < right->appName; }
} SortAppManifestByName;
} // namespace
@@ -0,0 +1,47 @@
#pragma once
#include <string>
#include <memory>
namespace tt::app {
// Forward declarations
class AppManifest;
class AppPaths {
const AppManifest& manifest;
public:
explicit AppPaths(const AppManifest& manifest) : manifest(manifest) {}
/**
* The user data directory is intended to survive OS upgrades.
* The path will not end with a "/".
*/
std::string getUserDataPath() const;
/**
* The user data directory is intended to survive OS upgrades.
* Configuration data should be stored here.
* @param[in] childPath the path without a "/" prefix
*/
std::string getUserDataPath(const std::string& childPath) const;
/**
* You should not store configuration data here.
* The path will not end with a "/".
* This is mainly used for core apps (system/boot/settings type).
*/
std::string getAssetsDirectory() const;
/**
* You should not store configuration data here.
* This is mainly used for core apps (system/boot/settings type).
* @param[in] childPath the path without a "/" prefix
*/
std::string getAssetsPath(const std::string& childPath) const;
};
}
@@ -1,14 +1,11 @@
#pragma once
#include "ServiceManifest.h"
#include <Tactility/Mutex.h>
#include <memory>
namespace tt::service {
class Paths;
struct ServiceManifest;
class ServicePaths;
/**
* The public representation of a service instance.
@@ -26,68 +23,8 @@ public:
virtual const ServiceManifest& getManifest() const = 0;
/** Retrieve the paths that are relevant to this service */
virtual std::unique_ptr<Paths> getPaths() const = 0;
virtual std::unique_ptr<ServicePaths> getPaths() const = 0;
};
class Paths {
public:
Paths() = default;
virtual ~Paths() = default;
/**
* Returns the directory path for the data location for a service.
* The data directory is intended to survive OS upgrades.
* The path will not end with a "/".
*/
virtual std::string getDataDirectory() const = 0;
/**
* @see getDataDirectory(), but with LVGL prefix.
*/
virtual std::string getDataDirectoryLvgl() const = 0;
/**
* Returns the full path for an entry inside the data location for a service.
* The data directory is intended to survive OS upgrades.
* Configuration data should be stored here.
* @param[in] childPath the path without a "/" prefix
*/
virtual std::string getDataPath(const std::string& childPath) const = 0;
/**
* @see getDataPath(), but with LVGL prefix.
*/
virtual std::string getDataPathLvgl(const std::string& childPath) const = 0;
/**
* Returns the directory path for the system location for a service.
* The system directory is not intended to survive OS upgrades.
* You should not store configuration data here.
* The path will not end with a "/".
* This is mainly used for core services.
*/
virtual std::string getSystemDirectory() const = 0;
/**
* @see getSystemDirectory(), but with LVGL prefix.
*/
virtual std::string getSystemDirectoryLvgl() const = 0;
/**
* Returns the full path for an entry inside the system location for an app.
* The data directory is not intended to survive OS upgrades.
* You should not store configuration data here.
* This is mainly used for core apps (system/boot/settings type).
* @param[in] childPath the path without a "/" prefix
*/
virtual std::string getSystemPath(const std::string& childPath) const = 0;
/**
* @see getSystemPath(), but with LVGL prefix.
*/
virtual std::string getSystemPathLvgl(const std::string& childPath) const = 0;
};
} // namespace
@@ -1,6 +1,6 @@
#pragma once
#include "Tactility/service/Service.h"
#include <Tactility/service/Service.h>
#include <string>
@@ -0,0 +1,45 @@
#pragma once
#include <string>
#include <memory>
namespace tt::service {
// Forward declarations
class ServiceManifest;
class ServicePaths {
std::shared_ptr<const ServiceManifest> manifest;
public:
explicit ServicePaths(std::shared_ptr<const ServiceManifest> manifest) : manifest(std::move(manifest)) {}
/**
* The user data directory is intended to survive OS upgrades.
* The path will not end with a "/".
*/
std::string getUserDataDirectory() const;
/**
* The user data directory is intended to survive OS upgrades.
* Configuration data should be stored here.
* @param[in] childPath the path without a "/" prefix
*/
std::string getUserDataPath(const std::string& childPath) const;
/**
* You should not store configuration data here.
* The path will not end with a "/".
*/
std::string getAssetsDirectory() const;
/**
* You should not store configuration data here.
* @param[in] childPath the path without a "/" prefix
*/
std::string getAssetsPath(const std::string& childPath) const;
};
}
@@ -24,7 +24,7 @@ class GpsService final : public Service {
Mutex stateMutex;
std::vector<GpsDeviceRecord> deviceRecords;
std::shared_ptr<PubSub<State>> statePubSub = std::make_shared<PubSub<State>>();
std::unique_ptr<Paths> paths;
std::unique_ptr<ServicePaths> paths;
State state = State::Off;
bool startGpsDevice(GpsDeviceRecord& deviceRecord);