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:
committed by
GitHub
parent
068600f98c
commit
84049658db
@@ -3,6 +3,7 @@
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <unistd.h>
|
||||
#include <Tactility/StringUtils.h>
|
||||
|
||||
namespace tt::hal::sdcard {
|
||||
class SdCardDevice;
|
||||
@@ -35,6 +36,28 @@ bool direntSortAlphaAndType(const dirent& left, const dirent& right) {
|
||||
}
|
||||
}
|
||||
|
||||
bool listDirectory(
|
||||
const std::string& path,
|
||||
std::function<void(const dirent&)> onEntry
|
||||
) {
|
||||
TT_LOG_I(TAG, "listDir start %s", path.c_str());
|
||||
DIR* dir = opendir(path.c_str());
|
||||
if (dir == nullptr) {
|
||||
TT_LOG_E(TAG, "Failed to open dir %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
dirent* current_entry;
|
||||
while ((current_entry = readdir(dir)) != nullptr) {
|
||||
onEntry(*current_entry);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
TT_LOG_I(TAG, "listDir stop %s", path.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
int scandir(
|
||||
const std::string& path,
|
||||
std::vector<dirent>& outList,
|
||||
@@ -50,7 +73,7 @@ int scandir(
|
||||
|
||||
dirent* current_entry;
|
||||
while ((current_entry = readdir(dir)) != nullptr) {
|
||||
if (filterMethod(current_entry) == 0) {
|
||||
if (filterMethod == nullptr || filterMethod(current_entry) == 0) {
|
||||
outList.push_back(*current_entry);
|
||||
}
|
||||
}
|
||||
@@ -184,7 +207,16 @@ static bool findOrCreateDirectoryInternal(std::string path, mode_t mode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool findOrCreateDirectory(std::string path, mode_t mode) {
|
||||
std::string getLastPathSegment(const std::string& path) {
|
||||
auto index = path.find_last_of('/');
|
||||
if (index != std::string::npos) {
|
||||
return path.substr(index + 1);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
bool findOrCreateDirectory(const std::string& path, mode_t mode) {
|
||||
if (path.empty()) {
|
||||
return true;
|
||||
}
|
||||
@@ -213,6 +245,45 @@ bool findOrCreateDirectory(std::string path, mode_t mode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool findOrCreateParentDirectory(const std::string& path, mode_t mode) {
|
||||
std::string parent;
|
||||
if (!string::getPathParent(path, parent)) {
|
||||
return false;
|
||||
}
|
||||
return findOrCreateDirectory(parent, mode);
|
||||
}
|
||||
|
||||
bool deleteRecursively(const std::string& path) {
|
||||
if (path.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isDirectory(path)) {
|
||||
std::vector<dirent> entries;
|
||||
if (scandir(path, entries) < 0) {
|
||||
TT_LOG_E(TAG, "Failed to scan directory %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
for (const auto& entry : entries) {
|
||||
auto child_path = path + "/" + entry.d_name;
|
||||
if (!deleteRecursively(child_path)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
TT_LOG_I(TAG, "Deleting %s", path.c_str());
|
||||
return rmdir(path.c_str()) == 0;
|
||||
} else if (isFile(path)) {
|
||||
TT_LOG_I(TAG, "Deleting %s", path.c_str());
|
||||
return remove(path.c_str()) == 0;
|
||||
} else if (path == "/" || path == "." || path == "..") {
|
||||
// No-op
|
||||
return true;
|
||||
} else {
|
||||
TT_LOG_E(TAG, "Failed to delete \"%s\": unknown type", path.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool isFile(const std::string& path) {
|
||||
return access(path.c_str(), F_OK) == 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user