Fügt CLI-Toolverwaltung und erweiterte UI-Funktionen hinzu

Ermöglicht die Verwaltung (Erstellen, Auflisten, Ausführen) von Tools über eine Befehlszeilenschnittstelle für Automatisierung und Integration. Die Benutzeroberfläche wurde mit dedizierten Ansichten für Toolerstellung und -bearbeitung, In-App-Lua-Hilfe sowie kontextsensitiven Menüs erweitert. Neue Abhängigkeiten (CLI11, rang) wurden integriert und eine umfassende Testsuite hinzugefügt. Die Lizenzierung wurde auf AGPL-3.0 umgestellt und ein Kontributionsleitfaden bereitgestellt.
This commit is contained in:
2026-07-17 17:22:15 +02:00
parent 074fa73992
commit c611b008af
45 changed files with 5501 additions and 709 deletions

29
inc/luaHelpWindow.h Normal file
View File

@@ -0,0 +1,29 @@
#pragma once
#include "modules/hwnd_module.h"
#include <saucer/app.hpp>
#include <saucer/smartview.hpp>
#include <memory>
class LuaHelpWindow {
public:
explicit LuaHelpWindow(std::shared_ptr<saucer::application> app);
void initialize();
void show();
private:
std::shared_ptr<saucer::application> m_app;
saucer::smartview m_webview;
std::unique_ptr<hwnd_module> m_hwndModule;
HWND m_hwnd{};
void configureWindow();
void loadResources();
void exposeToJs();
void injectDocumentationToolbar();
void showCheatsheet();
void showOfficialDocumentation();
};

View File

@@ -5,23 +5,54 @@
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <unordered_map>
#include <vector>
class LuaRunner {
public:
using CompletionCallback = std::function<void()>;
using CompletionCallback = std::function<void(bool)>;
void run(int id, const std::filesystem::path& scriptPath, int timeoutSeconds, CompletionCallback onComplete);
void cancel(int id);
struct RunResult {
bool started = false;
bool singleInstance = false;
};
struct TaskStatus {
bool singleInstance = false;
bool running = false;
};
RunResult run(const std::string& taskId, const std::filesystem::path& scriptPath,
int timeoutSeconds, CompletionCallback onComplete);
TaskStatus status(const std::string& taskId, const std::filesystem::path& scriptPath) const;
void cancel(const std::string& taskId) const;
void shutdown() const;
~LuaRunner();
private:
struct LuaTask {
std::shared_ptr<std::atomic_bool> cancel;
std::shared_ptr<std::atomic_bool> executionFinished;
std::shared_ptr<std::atomic_bool> callbackFinished;
bool singleInstance = false;
std::jthread worker;
LuaTask(std::shared_ptr<std::atomic_bool> cancelFlag,
std::shared_ptr<std::atomic_bool> executionFinishedFlag,
std::shared_ptr<std::atomic_bool> callbackFinishedFlag,
bool isSingleInstance)
: cancel(std::move(cancelFlag)),
executionFinished(std::move(executionFinishedFlag)),
callbackFinished(std::move(callbackFinishedFlag)),
singleInstance(isSingleInstance) {}
};
struct State {
std::mutex tasksMutex;
std::unordered_map<int, LuaTask> tasks;
std::unordered_map<std::string, std::vector<LuaTask>> tasks;
};
std::shared_ptr<State> m_state = std::make_shared<State>();

View File

@@ -13,15 +13,16 @@ class optionWindow {
public:
// Konstruktor erhält das Application-Objekt als Parameter
optionWindow(std::shared_ptr<saucer::application>& app,
std::function<int()> getLuaTimeoutSeconds,
std::function<void(int)> setLuaTimeoutSeconds,
std::function<std::string()> getActiveToolName,
std::function<std::string()> getToolConfigIni,
std::function<void(const std::string &)> setToolConfigIni,
std::function<std::string()> getToolDetails,
std::function<std::string(const std::string &)> saveToolDetails,
std::function<std::string()> openToolFolder,
std::function<std::string(const std::string &)> createTool,
std::function<void()> openLuaHelp,
std::function<void()> openIndex);
// Methode zum Anzeigen des Fensters
void show();
void showCreateTool();
// Für die Fensterinitialisierung
void initialize();
@@ -33,11 +34,11 @@ private:
saucer::smartview m_webview;
std::unique_ptr<hwnd_module> m_hwnd_module;
HWND m_hwnd;
std::function<int()> m_getLuaTimeoutSeconds;
std::function<void(int)> m_setLuaTimeoutSeconds;
std::function<std::string()> m_getActiveToolName;
std::function<std::string()> m_getToolConfigIni;
std::function<void(const std::string &)> m_setToolConfigIni;
std::function<std::string()> m_getToolDetails;
std::function<std::string(const std::string &)> m_saveToolDetails;
std::function<std::string()> m_openToolFolder;
std::function<std::string(const std::string &)> m_createTool;
std::function<void()> m_openLuaHelp;
std::function<void()> m_openIndex;
void configureWindow();

11
inc/toolLaunchBridge.h Normal file
View File

@@ -0,0 +1,11 @@
#pragma once
namespace sol {
class state;
}
namespace ToolLaunchBridge {
void registerFunctions(sol::state& lua);
} // namespace ToolLaunchBridge

View File

@@ -1,6 +1,7 @@
#pragma once
#include <filesystem>
#include <optional>
#include <string>
#include <vector>
@@ -18,11 +19,73 @@ struct ToolboxItem {
std::string license;
};
struct ToolDraft {
std::string name;
std::string description;
std::string luaScript;
std::string iconBase64;
int timeoutSeconds = 30;
std::string templateType = "lua";
std::string templateTarget;
};
struct ToolDetails {
std::filesystem::path path;
std::string name;
std::string description;
std::string luaScript;
std::string iconBase64;
int timeoutSeconds = 30;
std::string templateType = "lua";
std::string templateTarget;
};
struct ToolDetailsResult {
bool success = false;
std::string message;
ToolDetails details;
};
struct ToolUpdateDraft {
std::string name;
std::string description;
std::string luaScript;
std::optional<std::string> iconBase64;
int timeoutSeconds = 30;
std::string templateType = "lua";
std::string templateTarget;
};
struct ToolUpdateResult {
bool success = false;
std::string message;
std::filesystem::path toolPath;
};
struct ToolCreationResult {
bool success = false;
std::string message;
};
struct ToolDeletionResult {
bool success = false;
std::string message;
};
class ToolRegistry {
public:
static std::filesystem::path toolboxDirectory(const std::filesystem::path& userPath);
static bool ensureToolboxDirectory(const std::filesystem::path& userPath);
static std::vector<ToolboxItem> loadTools(const std::filesystem::path& userPath);
static ToolCreationResult createTool(const std::filesystem::path& userPath,
const ToolDraft& draft);
static ToolDetailsResult getToolDetails(const std::filesystem::path& userPath,
const std::filesystem::path& toolPath);
static ToolUpdateResult updateTool(const std::filesystem::path& userPath,
const std::filesystem::path& toolPath,
const ToolUpdateDraft& draft);
static ToolDeletionResult deleteTool(const std::filesystem::path& userPath,
const std::filesystem::path& toolPath);
private:
static void encodeIcon(const std::filesystem::path& imagePath, ToolboxItem& item);

27
inc/toolTemplates.h Normal file
View File

@@ -0,0 +1,27 @@
#pragma once
#include <filesystem>
#include <string>
#include <string_view>
struct ToolTemplateDraft {
std::string name;
std::string description;
std::string luaScript;
std::string templateType;
std::string templateTarget;
};
struct ToolTemplateResult {
bool success = false;
std::string message;
ToolTemplateDraft draft;
};
class ToolTemplates {
public:
static std::string defaultLuaScript(std::string_view toolName);
static ToolTemplateResult programLauncher(const std::filesystem::path& executable);
static ToolTemplateResult folderLauncher(const std::filesystem::path& folder);
static ToolTemplateResult websiteLauncher(const std::string& url);
};

4
inc/toolboxCli.h Normal file
View File

@@ -0,0 +1,4 @@
#pragma once
#include <string>
#include <vector>
int runCli(std::vector<std::string> args);

View File

@@ -9,19 +9,18 @@ class ToolboxJsBridge {
public:
struct Bindings {
std::function<std::string()> getToolboxItems;
std::function<void(int)> runLua;
std::function<void(int)> cancelLua;
std::function<std::string(const std::string&)> runLua;
std::function<void(const std::string&)> cancelLua;
std::function<void()> debugPrint;
std::function<void()> openFileSystem;
std::function<void()> openCommandPrompt;
std::function<void(int)> openSettings;
std::function<void()> openAddTool;
std::function<void(const std::string&)> openSettings;
std::function<std::string(const std::string&)> deleteTool;
std::function<void(int)> setOpacity;
std::function<int()> getOpacity;
std::function<void()> openIndex;
std::function<void()> getNewContent;
std::function<int()> getLuaTimeoutSeconds;
std::function<void(int)> setLuaTimeoutSeconds;
std::function<std::string()> getActiveToolName;
std::function<std::string()> getToolConfigIni;
std::function<void(const std::string&)> setToolConfigIni;
};
static void registerBindings(saucer::smartview& webview, Bindings bindings);

View File

@@ -5,6 +5,7 @@
#include <saucer/webview.hpp>
#include <chrono>
#include "luaRunner.h"
#include "luaHelpWindow.h"
#include "optionWindow.h"
#include "resourceLoader.h"
#include "toolConfig.h"
@@ -18,19 +19,16 @@ public:
explicit ToolboxWindow(std::shared_ptr<saucer::application>& app);
~ToolboxWindow();
bool m_bShow = false;
// Methode zum Anzeigen des Fensters
void show();
void hide();
[[nodiscard]] bool isVisible() const noexcept;
// Für die Fensterinitialisierung
void initialize();
void setupToolboxWindow();
void toggleDevTools();
std::atomic_bool isIndex = true;
std::vector<ToolboxItem> m_toolboxItems;
saucer::smartview m_webview;
@@ -40,20 +38,23 @@ private:
HWND m_hwnd{};
std::shared_ptr<saucer::application> m_app;
std::unique_ptr<optionWindow> m_optionWindow;
std::unique_ptr<LuaHelpWindow> m_luaHelpWindow;
std::thread m_threadMonitor;
std::jthread m_repositionThread;
std::atomic_bool m_isVisible = false;
std::atomic_bool m_isIndex = true;
std::atomic<bool> m_runningMonitor = true;
std::chrono::steady_clock::time_point m_lastShowTime{};
bool m_seenFocusSinceShow = false;
std::atomic_bool m_seenFocusSinceShow = false;
std::shared_ptr<std::atomic_bool> m_alive = std::make_shared<std::atomic_bool>(true);
std::string jsonString;
#ifdef _WIN32
std::filesystem::path userPath = std::getenv("USERPROFILE"); // Windows
#else
std::filesystem::path userPath = std::getenv("HOME"); // Unix/Linux/MacOS
#endif
std::filesystem::path userPath = userDirectory();
static std::filesystem::path userDirectory();
void startThreadMonitor();
void scheduleDelayedReposition();
bool serveHtmlFile(const std::string &htmlPath, bool setDecorations);
@@ -69,8 +70,9 @@ private:
void debug_print();
void run_lua(int id);
void cancel_lua(int id);
LuaRunner::RunResult run_lua(int id);
std::string run_lua_path(const std::string& toolPath);
void cancel_lua(const std::string& toolPath);
void monitor_focus();
@@ -78,10 +80,15 @@ private:
void open_cmd();
void setWindowOpacity(int percent);
int getWindowOpacity() const;
void SetJsonItems();
void openEinst();
void openEinst(int id);
void openEinst(const std::string& toolPath);
void openAddTool();
void openLuaHelp();
void centerWindow();
void resizeWindow(int width, int height);
void resizeWindow(double widthPercent, double heightPercent);
@@ -89,17 +96,19 @@ private:
void openIndex();
void getNewContent();
int getLuaTimeoutSeconds();
void setLuaTimeoutSeconds(int seconds);
std::string getActiveToolName();
std::string getActiveToolDetails() const;
std::string saveActiveToolDetails(const std::string &payload);
std::string openActiveToolFolder() const;
int m_activeToolId = -1;
std::filesystem::path m_activeToolPath;
LuaRunner m_luaRunner;
ToolConfigStore m_configStore;
int m_lastOpacity = 100;
std::filesystem::path getToolConfigPath(int id) const;
void ensureConfigExists(int id) const;
int getLuaTimeoutSecondsForId(int id) const;
std::string getToolConfigIni() const;
void setToolConfigIni(const std::string &content);
std::string createTool(const std::string &payload);
std::string deleteTool(const std::string& toolPath);
optionWindow& optionWindowInstance();
LuaHelpWindow& luaHelpWindowInstance();
};