From 60fd32f329df800f1cb198e8aed9cf8b4be5bd7c Mon Sep 17 00:00:00 2001 From: demonkiller Date: Sun, 9 Nov 2025 19:55:40 +0000 Subject: [PATCH 01/71] build script for alg-app-store --- build.sh | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100755 build.sh diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..34e8e84 --- /dev/null +++ b/build.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# Build script for ALG App Store Qt6 version + +set -e + +echo "===================================" +echo "ALG App Store - Qt6 Build Script" +echo "===================================" +echo "" + +# Check for required dependencies +echo "Checking dependencies..." + +command -v cmake >/dev/null 2>&1 || { + echo "Error: cmake is not installed. Install with: sudo pacman -S cmake" + exit 1 +} + +command -v qmake6 >/dev/null 2>&1 || command -v qmake >/dev/null 2>&1 || { + echo "Error: Qt6 is not installed. Install with: sudo pacman -S qt6-base" + exit 1 +} + +pkg-config --exists libalpm || { + echo "Error: libalpm is not installed. Install with: sudo pacman -S pacman" + exit 1 +} + +echo "All dependencies found!" +echo "" + +# Clean previous build +if [ -d "build" ]; then + echo "Cleaning previous build..." + rm -rf build +fi + +# Create build directory +echo "Creating build directory..." +mkdir -p build +cd build + +# Configure with CMake +echo "" +echo "Configuring with CMake..." +cmake .. -DCMAKE_BUILD_TYPE=Release + +# Build +echo "" +echo "Building..." +make -j$(nproc) + +echo "" +echo "===================================" +echo "Build completed successfully!" +echo "===================================" +echo "" +echo "To run the application:" +echo " ./build/alg-app-store" +echo "" +echo "To install system-wide:" +echo " sudo make install (from build directory)" +echo "" From 19a52bb624d965806cccfebc74ddbceb05407027 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 08:31:05 +0000 Subject: [PATCH 02/71] initialise qt6 app --- src/main.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main.cpp diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..a3f35bd --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,29 @@ +#include "gui/mainwindow.h" +#include "utils/logger.h" +#include +#include + +int main(int argc, char *argv[]) { + QApplication app(argc, argv); + + // Set application metadata + app.setApplicationName("ALG App Store"); + app.setApplicationVersion("2.0.0"); + app.setOrganizationName("Arch Linux GUI"); + + // Set application style + app.setStyle(QStyleFactory::create("Fusion")); + + Logger::info("Starting ALG App Store"); + Logger::info(QString("Qt version: %1").arg(qVersion())); + + MainWindow window; + window.show(); + + Logger::info("Application window shown"); + + int result = app.exec(); + + Logger::info("Application exiting"); + return result; +} From e97858788cd5af2ab6ea7a20d836db4b5551200a Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 08:32:57 +0000 Subject: [PATCH 03/71] project cmake --- CMakeLists.txt | 115 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..6268a7c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,115 @@ +cmake_minimum_required(VERSION 3.16) + +project(alg-app-store VERSION 2.0.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +# Find Qt6 packages +find_package(Qt6 REQUIRED COMPONENTS + Core + Gui + Widgets + Network + Concurrent +) + +# Find libalpm +find_package(PkgConfig REQUIRED) +pkg_check_modules(ALPM REQUIRED libalpm) + +# Include directories +include_directories( + ${CMAKE_SOURCE_DIR}/src + ${ALPM_INCLUDE_DIRS} +) + +# Source files +set(SOURCES + src/main.cpp + + # Core + src/core/alpm_wrapper.cpp + src/core/aur_helper.cpp + src/core/package_manager.cpp + + # GUI + src/gui/mainwindow.cpp + src/gui/home_widget.cpp + src/gui/search_widget.cpp + src/gui/installed_widget.cpp + src/gui/updates_widget.cpp + src/gui/package_card.cpp + src/gui/package_details_dialog.cpp +) + +# Header files +set(HEADERS + src/utils/logger.h + src/utils/types.h + + # Core + src/core/alpm_wrapper.h + src/core/aur_helper.h + src/core/package_manager.h + + # GUI + src/gui/mainwindow.h + src/gui/home_widget.h + src/gui/search_widget.h + src/gui/installed_widget.h + src/gui/updates_widget.h + src/gui/package_card.h + src/gui/package_details_dialog.h +) + +# Create executable +add_executable(${PROJECT_NAME} + ${SOURCES} + ${HEADERS} +) + +# Link libraries +target_link_libraries(${PROJECT_NAME} PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets + Qt6::Network + Qt6::Concurrent + ${ALPM_LIBRARIES} +) + +# Link directories +link_directories(${ALPM_LIBRARY_DIRS}) + +# Compiler flags +target_compile_options(${PROJECT_NAME} PRIVATE + -Wall + -Wextra + -Wpedantic +) + +# Install target +install(TARGETS ${PROJECT_NAME} + RUNTIME DESTINATION bin +) + +# Install desktop file +install(FILES assets/alg-app-store.desktop + DESTINATION share/applications +) + +# Copy stylesheet to build directory +configure_file( + ${CMAKE_SOURCE_DIR}/stylesheet.qss + ${CMAKE_BINARY_DIR}/stylesheet.qss + COPYONLY +) + +# Install stylesheet +install(FILES stylesheet.qss + DESTINATION share/alg-app-store +) From 244a93092144c3cdd8c58d3a2e0c4d53766ae616 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 08:33:31 +0000 Subject: [PATCH 04/71] ignore build files --- .gitignore | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b202a2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,52 @@ +# Qt/C++ Build artifacts +build/ +*.o +*.so +*.a +*.user +*.autosave +moc_*.cpp +qrc_*.cpp +ui_*.h + +# CMake +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake +Makefile + +# Qt Creator +*.pro.user +*.pro.user.* + +# Executable +alg-app-store + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Compiled Object files +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# OS specific +.DS_Store +Thumbs.db + +# Backup files +*~ +*.bak +*.backup From c08c24ac0cf9a015adf1df99742a7aff90c64375 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 08:34:31 +0000 Subject: [PATCH 05/71] add verbose logger --- src/utils/logger.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/utils/logger.h diff --git a/src/utils/logger.h b/src/utils/logger.h new file mode 100644 index 0000000..a8be860 --- /dev/null +++ b/src/utils/logger.h @@ -0,0 +1,25 @@ +#ifndef LOGGER_H +#define LOGGER_H + +#include +#include + +namespace Logger { + inline void info(const QString &message) { + qDebug() << "[INFO]" << message; + } + + inline void warning(const QString &message) { + qWarning() << "[WARNING]" << message; + } + + inline void error(const QString &message) { + qCritical() << "[ERROR]" << message; + } + + inline void debug(const QString &message) { + qDebug() << "[DEBUG]" << message; + } +} + +#endif // LOGGER_H From d8c81bd0fdef6549ad5a371682e4e6c0bf6c22ec Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:14:44 +0000 Subject: [PATCH 06/71] create mainwindow --- src/gui/mainwindow.cpp | 116 +++++++++++++++++++++++++++++++++++++++++ src/gui/mainwindow.h | 33 ++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 src/gui/mainwindow.cpp create mode 100644 src/gui/mainwindow.h diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp new file mode 100644 index 0000000..0eefeeb --- /dev/null +++ b/src/gui/mainwindow.cpp @@ -0,0 +1,116 @@ +#include "mainwindow.h" +#include "home_widget.h" +#include "search_widget.h" +#include "installed_widget.h" +#include "updates_widget.h" +#include "../utils/logger.h" +#include "../core/alpm_wrapper.h" +#include +#include +#include +#include +#include +#include + +MainWindow::MainWindow(QWidget* parent) + : QMainWindow(parent) + , m_tabWidget(std::make_unique(this)) { + + setupUi(); + loadStyleSheet(); + + // Initialize ALPM + if (!AlpmWrapper::instance().initialize()) { + QMessageBox::critical(this, "Error", + "Failed to initialize package manager. Please check your system configuration."); + Logger::error("Failed to initialize ALPM in MainWindow"); + } + + Logger::info("MainWindow created successfully"); +} + +MainWindow::~MainWindow() { + AlpmWrapper::instance().release(); + Logger::info("MainWindow destroyed"); +} + +void MainWindow::setupUi() { + setWindowTitle("ALG App Store (Beta)"); + setMinimumSize(1024, 768); + resize(1124, 868); + + // Create widgets + m_homeWidget = new HomeWidget(this); + m_searchWidget = new SearchWidget(this); + m_installedWidget = new InstalledWidget(this); + m_updatesWidget = new UpdatesWidget(this); + + // Add tabs + m_tabWidget->addTab(m_homeWidget, "Home"); + m_tabWidget->addTab(m_searchWidget, "Search"); + m_tabWidget->addTab(m_installedWidget, "Installed"); + m_tabWidget->addTab(m_updatesWidget, "Updates"); + + m_tabWidget->setTabPosition(QTabWidget::North); + m_tabWidget->setMovable(false); + + setCentralWidget(m_tabWidget.get()); + createMenuBar(); +} + +void MainWindow::createMenuBar() { + auto* fileMenu = menuBar()->addMenu("&File"); + + auto* refreshAction = new QAction("&Refresh", this); + refreshAction->setShortcut(QKeySequence::Refresh); + connect(refreshAction, &QAction::triggered, [this]() { + int currentIndex = m_tabWidget->currentIndex(); + if (currentIndex == 0) { + // Home widget refresh + } else if (currentIndex == 1) { + // Search widget refresh + } else if (currentIndex == 2) { + m_installedWidget->refreshPackages(); + } else if (currentIndex == 3) { + m_updatesWidget->checkForUpdates(); + } + }); + fileMenu->addAction(refreshAction); + + fileMenu->addSeparator(); + + auto* quitAction = new QAction("&Quit", this); + quitAction->setShortcut(QKeySequence::Quit); + connect(quitAction, &QAction::triggered, this, &QMainWindow::close); + fileMenu->addAction(quitAction); + + auto* helpMenu = menuBar()->addMenu("&Help"); + + auto* aboutAction = new QAction("&About", this); + connect(aboutAction, &QAction::triggered, [this]() { + QMessageBox::about(this, "About ALG App Store", + "ALG App Store (Beta)\n\n" + "A modern package manager for Arch Linux\n" + "Built with Qt6 and C++17\n\n" + "© 2025 Arch Linux GUI"); + }); + helpMenu->addAction(aboutAction); +} + +void MainWindow::loadStyleSheet() { + QFile styleFile(":/stylesheet.qss"); + + if (!styleFile.exists()) { + // Try loading from file system + styleFile.setFileName("stylesheet.qss"); + } + + if (styleFile.open(QFile::ReadOnly)) { + QString styleSheet = QLatin1String(styleFile.readAll()); + qApp->setStyleSheet(styleSheet); + styleFile.close(); + Logger::info("Stylesheet loaded successfully"); + } else { + Logger::warning("Could not load stylesheet"); + } +} diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h new file mode 100644 index 0000000..2d1cb4c --- /dev/null +++ b/src/gui/mainwindow.h @@ -0,0 +1,33 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include + +class HomeWidget; +class SearchWidget; +class InstalledWidget; +class UpdatesWidget; + +class MainWindow : public QMainWindow { + Q_OBJECT + +public: + explicit MainWindow(QWidget* parent = nullptr); + ~MainWindow() override; + +private: + void setupUi(); + void createMenuBar(); + void loadStyleSheet(); + + std::unique_ptr m_tabWidget; + HomeWidget* m_homeWidget; + SearchWidget* m_searchWidget; + InstalledWidget* m_installedWidget; + UpdatesWidget* m_updatesWidget; +}; + +#endif // MAINWINDOW_H From 4d8cd1b1842b5eeba690c0ed4418385202e34ba6 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:15:19 +0000 Subject: [PATCH 07/71] wrapper around alpm --- src/core/alpm_wrapper.cpp | 279 ++++++++++++++++++++++++++++++++++++++ src/core/alpm_wrapper.h | 46 +++++++ 2 files changed, 325 insertions(+) create mode 100644 src/core/alpm_wrapper.cpp create mode 100644 src/core/alpm_wrapper.h diff --git a/src/core/alpm_wrapper.cpp b/src/core/alpm_wrapper.cpp new file mode 100644 index 0000000..10c8c46 --- /dev/null +++ b/src/core/alpm_wrapper.cpp @@ -0,0 +1,279 @@ +#include "alpm_wrapper.h" +#include "../utils/logger.h" +#include +#include + +AlpmWrapper& AlpmWrapper::instance() { + static AlpmWrapper instance; + return instance; +} + +AlpmWrapper::AlpmWrapper() + : m_handle(nullptr), m_syncDbs(nullptr), m_initialized(false) { +} + +AlpmWrapper::~AlpmWrapper() { + release(); +} + +bool AlpmWrapper::initialize() { + std::lock_guard lock(m_mutex); + + if (m_initialized) { + return true; + } + + alpm_errno_t err; + m_handle = alpm_initialize("/", "/var/lib/pacman", &err); + + if (!m_handle) { + Logger::error(QString("Failed to initialize ALPM: %1") + .arg(alpm_strerror(err))); + return false; + } + + // Register sync databases + QStringList repos = {"core", "extra"}; + for (const auto& repo : repos) { + alpm_db_t* db = alpm_register_syncdb(m_handle, + repo.toStdString().c_str(), + ALPM_SIG_USE_DEFAULT); + if (!db) { + Logger::warning(QString("Failed to register sync db: %1").arg(repo)); + } + } + + m_syncDbs = alpm_get_syncdbs(m_handle); + m_initialized = true; + + Logger::info("ALPM initialized successfully"); + return true; +} + +void AlpmWrapper::release() { + std::lock_guard lock(m_mutex); + + if (m_handle) { + alpm_release(m_handle); + m_handle = nullptr; + m_syncDbs = nullptr; + m_initialized = false; + Logger::info("ALPM released"); + } +} + +QVector AlpmWrapper::searchPackages(const QString& query) { + std::lock_guard lock(m_mutex); + + if (!m_initialized) { + Logger::error("ALPM not initialized"); + return {}; + } + + QVector results; + + // Search in sync databases + for (alpm_list_t* i = m_syncDbs; i; i = i->next) { + auto* db = static_cast(i->data); + searchInDatabase(db, query, results); + } + + return results; +} + +void AlpmWrapper::searchInDatabase(alpm_db_t* db, const QString& query, + QVector& results) { + if (!db) return; + + alpm_list_t* pkgs = alpm_db_get_pkgcache(db); + QString lowerQuery = query.toLower(); + + for (alpm_list_t* i = pkgs; i; i = i->next) { + auto* pkg = static_cast(i->data); + QString pkgName = QString::fromUtf8(alpm_pkg_get_name(pkg)); + + if (pkgName.toLower().contains(lowerQuery)) { + PackageInfo info; + info.name = pkgName; + info.version = QString::fromUtf8(alpm_pkg_get_version(pkg)); + info.description = QString::fromUtf8(alpm_pkg_get_desc(pkg)); + info.repository = QString::fromUtf8(alpm_db_get_name(db)); + info.maintainer = QString::fromUtf8(alpm_pkg_get_packager(pkg)); + info.upstreamUrl = QString::fromUtf8(alpm_pkg_get_url(pkg)); + info.dependList = convertDependList(alpm_pkg_get_depends(pkg)); + + alpm_time_t buildDate = alpm_pkg_get_builddate(pkg); + info.lastUpdated = QDateTime::fromSecsSinceEpoch(buildDate); + + results.push_back(std::move(info)); + } + } +} + +QVector AlpmWrapper::getInstalledPackages() { + std::lock_guard lock(m_mutex); + + if (!m_initialized) { + Logger::error("ALPM not initialized"); + return {}; + } + + QVector packages; + alpm_db_t* localDb = alpm_get_localdb(m_handle); + + if (!localDb) { + Logger::error("Failed to get local database"); + return {}; + } + + alpm_list_t* pkgs = alpm_db_get_pkgcache(localDb); + + for (alpm_list_t* i = pkgs; i; i = i->next) { + auto* pkg = static_cast(i->data); + + PackageInfo info; + info.name = QString::fromUtf8(alpm_pkg_get_name(pkg)); + info.version = QString::fromUtf8(alpm_pkg_get_version(pkg)); + info.description = QString::fromUtf8(alpm_pkg_get_desc(pkg)); + info.repository = QString::fromUtf8(alpm_db_get_name(alpm_pkg_get_db(pkg))); + info.maintainer = QString::fromUtf8(alpm_pkg_get_packager(pkg)); + info.upstreamUrl = QString::fromUtf8(alpm_pkg_get_url(pkg)); + info.dependList = convertDependList(alpm_pkg_get_depends(pkg)); + + alpm_time_t buildDate = alpm_pkg_get_builddate(pkg); + info.lastUpdated = QDateTime::fromSecsSinceEpoch(buildDate); + + packages.push_back(std::move(info)); + } + + Logger::info(QString("Found %1 installed packages").arg(packages.size())); + return packages; +} + +bool AlpmWrapper::isPackageInstalled(const QString& packageName) { + std::lock_guard lock(m_mutex); + + if (!m_initialized) { + return false; + } + + alpm_db_t* localDb = alpm_get_localdb(m_handle); + if (!localDb) { + return false; + } + + alpm_pkg_t* pkg = alpm_db_get_pkg(localDb, packageName.toStdString().c_str()); + return pkg != nullptr; +} + +PackageInfo AlpmWrapper::getPackageInfo(const QString& packageName) { + std::lock_guard lock(m_mutex); + + PackageInfo info; + if (!m_initialized) { + return info; + } + + // First check local database + alpm_db_t* localDb = alpm_get_localdb(m_handle); + if (localDb) { + alpm_pkg_t* pkg = alpm_db_get_pkg(localDb, packageName.toStdString().c_str()); + if (pkg) { + info.name = QString::fromUtf8(alpm_pkg_get_name(pkg)); + info.version = QString::fromUtf8(alpm_pkg_get_version(pkg)); + info.description = QString::fromUtf8(alpm_pkg_get_desc(pkg)); + info.repository = QString::fromUtf8(alpm_db_get_name(alpm_pkg_get_db(pkg))); + info.maintainer = QString::fromUtf8(alpm_pkg_get_packager(pkg)); + info.upstreamUrl = QString::fromUtf8(alpm_pkg_get_url(pkg)); + info.dependList = convertDependList(alpm_pkg_get_depends(pkg)); + + alpm_time_t buildDate = alpm_pkg_get_builddate(pkg); + info.lastUpdated = QDateTime::fromSecsSinceEpoch(buildDate); + + return info; + } + } + + // Check sync databases + for (alpm_list_t* i = m_syncDbs; i; i = i->next) { + auto* db = static_cast(i->data); + alpm_pkg_t* pkg = alpm_db_get_pkg(db, packageName.toStdString().c_str()); + + if (pkg) { + info.name = QString::fromUtf8(alpm_pkg_get_name(pkg)); + info.version = QString::fromUtf8(alpm_pkg_get_version(pkg)); + info.description = QString::fromUtf8(alpm_pkg_get_desc(pkg)); + info.repository = QString::fromUtf8(alpm_db_get_name(db)); + info.maintainer = QString::fromUtf8(alpm_pkg_get_packager(pkg)); + info.upstreamUrl = QString::fromUtf8(alpm_pkg_get_url(pkg)); + info.dependList = convertDependList(alpm_pkg_get_depends(pkg)); + + alpm_time_t buildDate = alpm_pkg_get_builddate(pkg); + info.lastUpdated = QDateTime::fromSecsSinceEpoch(buildDate); + + return info; + } + } + + return info; +} + +QVector AlpmWrapper::getAvailableUpdates() { + std::lock_guard lock(m_mutex); + + QVector updates; + + if (!m_initialized) { + Logger::error("ALPM not initialized"); + return updates; + } + + alpm_db_t* localDb = alpm_get_localdb(m_handle); + if (!localDb) { + return updates; + } + + alpm_list_t* pkgs = alpm_db_get_pkgcache(localDb); + + for (alpm_list_t* i = pkgs; i; i = i->next) { + auto* localPkg = static_cast(i->data); + const char* pkgName = alpm_pkg_get_name(localPkg); + + // Check each sync database for newer version + for (alpm_list_t* j = m_syncDbs; j; j = j->next) { + auto* syncDb = static_cast(j->data); + alpm_pkg_t* syncPkg = alpm_db_get_pkg(syncDb, pkgName); + + if (syncPkg) { + int cmp = alpm_pkg_vercmp(alpm_pkg_get_version(syncPkg), + alpm_pkg_get_version(localPkg)); + + if (cmp > 0) { + UpdateInfo update; + update.name = QString::fromUtf8(pkgName); + update.oldVersion = QString::fromUtf8(alpm_pkg_get_version(localPkg)); + update.newVersion = QString::fromUtf8(alpm_pkg_get_version(syncPkg)); + update.repository = QString::fromUtf8(alpm_db_get_name(syncDb)); + update.downloadSize = alpm_pkg_get_size(syncPkg); + + updates.push_back(std::move(update)); + break; + } + } + } + } + + Logger::info(QString("Found %1 available updates").arg(updates.size())); + return updates; +} + +QStringList AlpmWrapper::convertDependList(alpm_list_t* deps) { + QStringList result; + + for (alpm_list_t* i = deps; i; i = i->next) { + auto* dep = static_cast(i->data); + result.append(QString::fromUtf8(dep->name)); + } + + return result; +} diff --git a/src/core/alpm_wrapper.h b/src/core/alpm_wrapper.h new file mode 100644 index 0000000..010e960 --- /dev/null +++ b/src/core/alpm_wrapper.h @@ -0,0 +1,46 @@ +#ifndef ALPM_WRAPPER_H +#define ALPM_WRAPPER_H + +#include +#include +#include +#include +#include +#include +#include "../utils/types.h" + +class AlpmWrapper { +public: + static AlpmWrapper& instance(); + + ~AlpmWrapper(); + + // Disable copy and move + AlpmWrapper(const AlpmWrapper&) = delete; + AlpmWrapper& operator=(const AlpmWrapper&) = delete; + AlpmWrapper(AlpmWrapper&&) = delete; + AlpmWrapper& operator=(AlpmWrapper&&) = delete; + + bool initialize(); + void release(); + + QVector searchPackages(const QString& query); + QVector getInstalledPackages(); + bool isPackageInstalled(const QString& packageName); + PackageInfo getPackageInfo(const QString& packageName); + QVector getAvailableUpdates(); + +private: + AlpmWrapper(); + + alpm_handle_t* m_handle; + alpm_list_t* m_syncDbs; + std::mutex m_mutex; + bool m_initialized; + + QStringList convertDependList(alpm_list_t* deps); + void searchInDatabase(alpm_db_t* db, const QString& query, + QVector& results); +}; + +#endif // ALPM_WRAPPER_H From 5d78f920a925c3bb04b20bd76d9c5d005a3d770f Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:15:52 +0000 Subject: [PATCH 08/71] key backend operations --- src/core/package_manager.cpp | 186 +++++++++++++++++++++++++++++++++++ src/core/package_manager.h | 60 +++++++++++ 2 files changed, 246 insertions(+) create mode 100644 src/core/package_manager.cpp create mode 100644 src/core/package_manager.h diff --git a/src/core/package_manager.cpp b/src/core/package_manager.cpp new file mode 100644 index 0000000..2ec606b --- /dev/null +++ b/src/core/package_manager.cpp @@ -0,0 +1,186 @@ +#include "package_manager.h" +#include "../utils/logger.h" +#include + +PackageManager& PackageManager::instance() { + static PackageManager instance; + return instance; +} + +PackageManager::PackageManager() + : QObject(nullptr) + , m_helper(Helper::Pacman) + , m_process(std::make_unique()) { + + detectHelper(); + + connect(m_process.get(), &QProcess::finished, + this, &PackageManager::onProcessFinished); + connect(m_process.get(), &QProcess::errorOccurred, + this, &PackageManager::onProcessError); + connect(m_process.get(), &QProcess::readyReadStandardOutput, + this, &PackageManager::onProcessOutput); + connect(m_process.get(), &QProcess::readyReadStandardError, + this, &PackageManager::onProcessOutput); +} + +PackageManager::~PackageManager() { + if (m_process && m_process->state() != QProcess::NotRunning) { + m_process->terminate(); + m_process->waitForFinished(3000); + } +} + +void PackageManager::detectHelper() { + // Check for yay first + QString yayPath = QStandardPaths::findExecutable("yay"); + if (!yayPath.isEmpty()) { + m_helper = Helper::Yay; + Logger::info("Using yay as package helper"); + return; + } + + // Check for paru + QString paruPath = QStandardPaths::findExecutable("paru"); + if (!paruPath.isEmpty()) { + m_helper = Helper::Paru; + Logger::info("Using paru as package helper"); + return; + } + + // Default to pacman + m_helper = Helper::Pacman; + Logger::info("Using pacman as package helper"); +} + +QString PackageManager::getHelperName() const { + switch (m_helper) { + case Helper::Yay: return "yay"; + case Helper::Paru: return "paru"; + case Helper::Pacman: return "pacman"; + default: return "pacman"; + } +} + +void PackageManager::installPackage(const QString& packageName, const QString& repository) { + std::lock_guard lock(m_mutex); + + Logger::info(QString("Installing package: %1 from %2").arg(packageName, repository.isEmpty() ? "default" : repository)); + emit operationStarted(QString("Installing %1...").arg(packageName)); + + // AUR packages should not use pkexec (must run as regular user) + bool isAUR = repository.toLower() == "aur"; + QString helper = getHelperName(); + + QString command; + if (isAUR && (m_helper == Helper::Yay || m_helper == Helper::Paru)) { + // AUR helpers run as regular user + command = QString("%1 -S %2 --noconfirm").arg(helper, packageName); + } else { + // Official repos need root access + command = QString("pkexec pacman -S %1 --noconfirm").arg(packageName); + } + + executeCommand("sh", QStringList() << "-c" << command); +} + +void PackageManager::uninstallPackage(const QString& packageName, const QString& repository) { + std::lock_guard lock(m_mutex); + + Logger::info(QString("Uninstalling package: %1 from %2").arg(packageName, repository.isEmpty() ? "default" : repository)); + emit operationStarted(QString("Uninstalling %1...").arg(packageName)); + + // Uninstall always needs root (even for AUR packages, they're in the system db once installed) + QString command = QString("pkexec pacman -Rdd %1 --noconfirm").arg(packageName); + + executeCommand("sh", QStringList() << "-c" << command); +} + +void PackageManager::updatePackage(const QString& packageName, const QString& repository) { + std::lock_guard lock(m_mutex); + + Logger::info(QString("Updating package: %1 from %2").arg(packageName, repository.isEmpty() ? "default" : repository)); + emit operationStarted(QString("Updating %1...").arg(packageName)); + + // AUR packages should not use pkexec (must run as regular user) + bool isAUR = repository.toLower() == "aur"; + QString helper = getHelperName(); + + QString command; + if (isAUR && (m_helper == Helper::Yay || m_helper == Helper::Paru)) { + // AUR helpers run as regular user + command = QString("%1 -S %2 --noconfirm").arg(helper, packageName); + } else { + // Official repos need root access + command = QString("pkexec pacman -S %1 --noconfirm").arg(packageName); + } + + executeCommand("sh", QStringList() << "-c" << command); +} + +void PackageManager::updateAllPackages() { + std::lock_guard lock(m_mutex); + + Logger::info("Updating all packages"); + emit operationStarted("Updating all packages..."); + + QString command = QString("pkexec %1 -Syu --noconfirm") + .arg(getHelperName()); + + executeCommand("sh", QStringList() << "-c" << command); +} + +void PackageManager::executeCommand(const QString& command, const QStringList& args) { + if (m_process->state() != QProcess::NotRunning) { + Logger::warning("Another operation is already running"); + emit operationError("Another operation is already in progress"); + return; + } + + // Merge stdout and stderr so we capture all output + m_process->setProcessChannelMode(QProcess::MergedChannels); + + Logger::debug(QString("Executing: %1 %2").arg(command, args.join(" "))); + + // Emit the actual command being executed to the UI for visibility + QString fullCommand = command + " " + args.join(" "); + emit operationOutput(QString(">> Executing: %1\n").arg(fullCommand)); + + m_process->start(command, args); + + // Check if process started successfully + if (!m_process->waitForStarted(3000)) { + QString error = QString("Failed to start process: %1").arg(m_process->errorString()); + Logger::error(error); + emit operationError(error); + } +} + +void PackageManager::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) { + QString output = m_process->readAllStandardOutput(); + QString error = m_process->readAllStandardError(); + + if (exitStatus == QProcess::NormalExit && exitCode == 0) { + Logger::info("Operation completed successfully"); + emit operationCompleted(true, "Operation completed successfully"); + } else { + Logger::error(QString("Operation failed with exit code %1").arg(exitCode)); + Logger::error(QString("Error output: %1").arg(error)); + emit operationCompleted(false, QString("Operation failed: %1").arg(error)); + } +} + +void PackageManager::onProcessError(QProcess::ProcessError /*error*/) { + QString errorString = m_process->errorString(); + Logger::error(QString("Process error: %1").arg(errorString)); + emit operationError(errorString); +} + +void PackageManager::onProcessOutput() { + // Since we merged channels, only read stdout (which includes stderr) + QString output = m_process->readAll(); + if (!output.isEmpty()) { + Logger::debug(QString("Process output: %1").arg(output.trimmed())); + emit operationOutput(output); + } +} diff --git a/src/core/package_manager.h b/src/core/package_manager.h new file mode 100644 index 0000000..ad77fc2 --- /dev/null +++ b/src/core/package_manager.h @@ -0,0 +1,60 @@ +#ifndef PACKAGE_MANAGER_H +#define PACKAGE_MANAGER_H + +#include +#include +#include +#include +#include + +class PackageManager : public QObject { + Q_OBJECT + +public: + enum class Helper { + Pacman, + Yay, + Paru + }; + + static PackageManager& instance(); + + ~PackageManager() override; + + // Disable copy and move + PackageManager(const PackageManager&) = delete; + PackageManager& operator=(const PackageManager&) = delete; + PackageManager(PackageManager&&) = delete; + PackageManager& operator=(PackageManager&&) = delete; + + void installPackage(const QString& packageName, const QString& repository = QString()); + void uninstallPackage(const QString& packageName, const QString& repository = QString()); + void updatePackage(const QString& packageName, const QString& repository = QString()); + void updateAllPackages(); + + Helper getHelper() const { return m_helper; } + QString getHelperName() const; + +signals: + void operationStarted(const QString& message); + void operationOutput(const QString& output); + void operationCompleted(bool success, const QString& message); + void operationError(const QString& error); + +private: + PackageManager(); + + void detectHelper(); + void executeCommand(const QString& command, const QStringList& args); + + Helper m_helper; + std::unique_ptr m_process; + std::mutex m_mutex; + +private slots: + void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + void onProcessError(QProcess::ProcessError error); + void onProcessOutput(); +}; + +#endif // PACKAGE_MANAGER_H From 1925b37fc44b41e0842c6f37699008c39ae44858 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:17:00 +0000 Subject: [PATCH 09/71] create app store homepage --- src/gui/home_widget.cpp | 145 ++++++++++++++++++++++++++++++++++++++++ src/gui/home_widget.h | 38 +++++++++++ 2 files changed, 183 insertions(+) create mode 100644 src/gui/home_widget.cpp create mode 100644 src/gui/home_widget.h diff --git a/src/gui/home_widget.cpp b/src/gui/home_widget.cpp new file mode 100644 index 0000000..197281e --- /dev/null +++ b/src/gui/home_widget.cpp @@ -0,0 +1,145 @@ +#include "home_widget.h" +#include "package_card.h" +#include "package_details_dialog.h" +#include "../core/alpm_wrapper.h" +#include "../core/aur_helper.h" +#include "../utils/logger.h" +#include +#include +#include + +HomeWidget::HomeWidget(QWidget* parent) + : QWidget(parent) + , m_scrollArea(new QScrollArea(this)) + , m_contentWidget(new QWidget()) + , m_gridLayout(new QGridLayout(m_contentWidget)) + , m_updateTimer(new QTimer(this)) { + + setupUi(); + loadFeaturedPackages(); + createPackageCards(); + + // Setup timer to periodically check installation status + connect(m_updateTimer, &QTimer::timeout, this, &HomeWidget::onUpdateTimer); + m_updateTimer->start(3000); // Check every 3 seconds + + // Initial check + checkInstalledPackages(); +} + +void HomeWidget::setupUi() { + auto* mainLayout = new QVBoxLayout(this); + + auto* titleLabel = new QLabel("Featured Packages", this); + auto titleFont = titleLabel->font(); + titleFont.setPointSize(24); + titleFont.setBold(true); + titleLabel->setFont(titleFont); + mainLayout->addWidget(titleLabel); + + m_scrollArea->setWidget(m_contentWidget); + m_scrollArea->setWidgetResizable(true); + m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + m_gridLayout->setSpacing(15); + m_gridLayout->setContentsMargins(10, 10, 10, 10); + + mainLayout->addWidget(m_scrollArea); + setLayout(mainLayout); +} + +void HomeWidget::loadFeaturedPackages() { + // Featured packages list + m_featuredPackages = { + {"firefox", "Latest", "Fast, Private & Safe Web Browser", "extra"}, + {"gimp", "Latest", "GNU Image Manipulation Program", "extra"}, + {"vlc", "Latest", "Multi-platform MPEG, VCD/DVD, and DivX player", "extra"}, + {"visual-studio-code-bin", "Latest", "Visual Studio Code (official binary version)", "AUR"}, + {"libreoffice-still", "Latest", "LibreOffice maintenance branch", "extra"}, + {"blender", "Latest", "A fully integrated 3D graphics creation suite", "extra"}, + {"zed", "Latest", "A high-performance, multiplayer code editor", "extra"}, + {"git", "Latest", "The fast distributed version control system", "extra"}, + {"google-chrome", "Latest", "The popular web browser by Google", "AUR"} + }; + + Logger::info(QString("Loaded %1 featured packages").arg(m_featuredPackages.size())); +} + +void HomeWidget::createPackageCards() { + int row = 0; + int col = 0; + const int columns = 3; + + for (const auto& pkg : m_featuredPackages) { + auto* card = new PackageCard(pkg, m_contentWidget); + connect(card, &PackageCard::clicked, this, &HomeWidget::onPackageClicked); + + m_gridLayout->addWidget(card, row, col); + m_packageCards.append(card); + + col++; + if (col >= columns) { + col = 0; + row++; + } + } + + // Add stretch to push cards to the top + m_gridLayout->setRowStretch(row + 1, 1); +} + +void HomeWidget::checkInstalledPackages() { + for (auto* card : m_packageCards) { + card->checkInstallStatus(); + } +} + +void HomeWidget::onUpdateTimer() { + checkInstalledPackages(); +} + +void HomeWidget::onPackageClicked(const PackageInfo& info) { + Logger::info(QString("Package clicked: %1").arg(info.name)); + + // Fetch full package details including dependencies + PackageInfo fullInfo; + + if (info.repository.toLower() == "aur") { + // For AUR packages, query AUR API for full details + AurHelper aurHelper; + QEventLoop loop; + + connect(&aurHelper, &AurHelper::packageInfoReceived, [&fullInfo, &loop](const PackageInfo& aurInfo) { + fullInfo = aurInfo; + loop.quit(); + }); + + connect(&aurHelper, &AurHelper::error, [&fullInfo, &info, &loop](const QString& error) { + Logger::warning(QString("Failed to fetch AUR package info: %1").arg(error)); + fullInfo = info; // Fallback to basic info + loop.quit(); + }); + + aurHelper.getPackageInfo(info.name); + loop.exec(); // Wait for response + + // If we didn't get full info, use the basic info + if (fullInfo.name.isEmpty()) { + fullInfo = info; + } + } else { + // For official repos, fetch full details from ALPM + fullInfo = AlpmWrapper::instance().getPackageInfo(info.name); + // If not found, use the basic info + if (fullInfo.name.isEmpty()) { + fullInfo = info; + } + } + + auto* dialog = new PackageDetailsDialog(fullInfo, this); + dialog->exec(); + dialog->deleteLater(); + + // Update installation status after dialog closes + checkInstalledPackages(); +} diff --git a/src/gui/home_widget.h b/src/gui/home_widget.h new file mode 100644 index 0000000..5882b8f --- /dev/null +++ b/src/gui/home_widget.h @@ -0,0 +1,38 @@ +#ifndef HOME_WIDGET_H +#define HOME_WIDGET_H + +#include +#include +#include +#include +#include +#include "../utils/types.h" + +class PackageCard; + +class HomeWidget : public QWidget { + Q_OBJECT + +public: + explicit HomeWidget(QWidget* parent = nullptr); + ~HomeWidget() override = default; + +private: + void setupUi(); + void loadFeaturedPackages(); + void createPackageCards(); + void checkInstalledPackages(); + + QVector m_featuredPackages; + QVector m_packageCards; + QScrollArea* m_scrollArea; + QWidget* m_contentWidget; + QGridLayout* m_gridLayout; + QTimer* m_updateTimer; + +private slots: + void onPackageClicked(const PackageInfo& info); + void onUpdateTimer(); +}; + +#endif // HOME_WIDGET_H From ae7902b5dc7c416c4706efb8f5fe4ccfed70990b Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:17:16 +0000 Subject: [PATCH 10/71] style app --- stylesheet.qss | 338 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 338 insertions(+) create mode 100644 stylesheet.qss diff --git a/stylesheet.qss b/stylesheet.qss new file mode 100644 index 0000000..2ec70f9 --- /dev/null +++ b/stylesheet.qss @@ -0,0 +1,338 @@ +/* ALG App Store - Qt Stylesheet */ +/* Based on the original Tailwind CSS dark theme */ + +* { + font-family: "Geist Sans", "Segoe UI", Roboto, Arial, sans-serif; +} + +QMainWindow { + background-color: #09090b; + color: #fafafa; +} + +QWidget { + background-color: #09090b; + color: #fafafa; +} + +/* Tab Widget */ +QTabWidget::pane { + border: 1px solid #27272a; + background-color: #09090b; +} + +QTabBar::tab { + background-color: #18181b; + color: #a1a1aa; + padding: 10px 20px; + margin-right: 2px; + border: 1px solid #27272a; + border-bottom: none; + min-width: 100px; +} + +QTabBar::tab:selected { + background-color: #27272a; + color: #fafafa; +} + +QTabBar::tab:hover { + background-color: #27272a; +} + +/* Buttons */ +QPushButton { + background-color: #fafafa; + color: #18181b; + border: none; + border-radius: 6px; + padding: 8px 16px; + font-weight: 500; +} + +QPushButton:hover { + background-color: #e4e4e7; +} + +QPushButton:pressed { + background-color: #d4d4d8; +} + +QPushButton:disabled { + background-color: #3f3f46; + color: #71717a; +} + +/* Line Edit / Input */ +QLineEdit { + background-color: #18181b; + color: #fafafa; + border: 1px solid #27272a; + border-radius: 6px; + padding: 8px 12px; + selection-background-color: #3f3f46; +} + +QLineEdit:focus { + border: 1px solid #52525b; +} + +QLineEdit::placeholder { + color: #71717a; +} + +/* Combo Box */ +QComboBox { + background-color: #18181b; + color: #fafafa; + border: 1px solid #27272a; + border-radius: 6px; + padding: 8px 12px; + min-width: 120px; +} + +QComboBox:hover { + border: 1px solid #3f3f46; +} + +QComboBox::drop-down { + border: none; + width: 20px; +} + +QComboBox::down-arrow { + width: 10px; + height: 10px; +} + +QComboBox QAbstractItemView { + background-color: #18181b; + color: #fafafa; + border: 1px solid #27272a; + selection-background-color: #27272a; +} + +/* Scroll Area */ +QScrollArea { + border: none; + background-color: transparent; +} + +/* Scroll Bar */ +QScrollBar:vertical { + background-color: #18181b; + width: 12px; + margin: 0px; +} + +QScrollBar::handle:vertical { + background-color: #3f3f46; + border-radius: 6px; + min-height: 30px; +} + +QScrollBar::handle:vertical:hover { + background-color: #52525b; +} + +QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { + height: 0px; +} + +QScrollBar:horizontal { + background-color: #18181b; + height: 12px; + margin: 0px; +} + +QScrollBar::handle:horizontal { + background-color: #3f3f46; + border-radius: 6px; + min-width: 30px; +} + +QScrollBar::handle:horizontal:hover { + background-color: #52525b; +} + +QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal { + width: 0px; +} + +/* Package Card */ +QWidget[class="package-card"] { + background-color: #18181b; + border: 1px solid #27272a; + border-radius: 8px; +} + +QWidget[class="package-card"][hovered="true"] { + background-color: #27272a; + border: 1px solid #3f3f46; +} + +/* Labels / Badges */ +QLabel[class="status-badge"] { + background-color: #27272a; + color: #fafafa; + border-radius: 4px; + padding: 4px 8px; + font-size: 11px; +} + +QLabel[class="repo-badge"] { + background-color: #27272a; + color: #a1a1aa; + border-radius: 4px; + padding: 4px 8px; + font-size: 11px; +} + +/* Update Item */ +QWidget[class="update-item"] { + background-color: #18181b; + border: 1px solid #27272a; + border-radius: 6px; + margin: 2px 0px; +} + +/* Group Box */ +QGroupBox { + background-color: #18181b; + border: 1px solid #27272a; + border-radius: 8px; + margin-top: 10px; + padding-top: 10px; + font-weight: bold; +} + +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + padding: 0px 10px; + color: #fafafa; +} + +/* Text Edit */ +QTextEdit { + background-color: #18181b; + color: #fafafa; + border: 1px solid #27272a; + border-radius: 6px; + padding: 8px; + selection-background-color: #3f3f46; +} + +QTextEdit:focus { + border: 1px solid #52525b; +} + +/* Dialog */ +QDialog { + background-color: #09090b; + color: #fafafa; +} + +/* Menu Bar */ +QMenuBar { + background-color: #18181b; + color: #fafafa; + border-bottom: 1px solid #27272a; +} + +QMenuBar::item { + padding: 5px 10px; + background-color: transparent; +} + +QMenuBar::item:selected { + background-color: #27272a; +} + +QMenuBar::item:pressed { + background-color: #3f3f46; +} + +/* Menu */ +QMenu { + background-color: #18181b; + color: #fafafa; + border: 1px solid #27272a; + border-radius: 6px; + padding: 5px; +} + +QMenu::item { + padding: 8px 25px; + border-radius: 4px; +} + +QMenu::item:selected { + background-color: #27272a; +} + +QMenu::separator { + height: 1px; + background-color: #27272a; + margin: 5px 0px; +} + +/* Message Box */ +QMessageBox { + background-color: #18181b; + color: #fafafa; +} + +QMessageBox QLabel { + color: #fafafa; +} + +QMessageBox QPushButton { + min-width: 80px; + background-color: #3b82f6; + color: #fafafa; + border: none; + border-radius: 6px; + padding: 8px 16px; + font-weight: 500; +} + +QMessageBox QPushButton:hover { + background-color: #2563eb; +} + +QMessageBox QPushButton:pressed { + background-color: #1d4ed8; +} + +QMessageBox QPushButton:default { + background-color: #3b82f6; + color: #fafafa; +} + +QMessageBox QPushButton:default:hover { + background-color: #2563eb; +} + +QMessageBox QPushButton:!default { + background-color: #27272a; + color: #fafafa; +} + +QMessageBox QPushButton:!default:hover { + background-color: #3f3f46; +} + +/* Progress Bar (if needed in future) */ +QProgressBar { + background-color: #27272a; + border: 1px solid #3f3f46; + border-radius: 4px; + text-align: center; + color: #fafafa; +} + +QProgressBar::chunk { + background-color: #3b82f6; + border-radius: 4px; +} From 4cbe082756c86dc9c54bbf61ddcffdb1db4b5e0c Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:18:18 +0000 Subject: [PATCH 11/71] manage aur packages --- frontend/.gitignore | 36 - frontend/components.json | 16 - frontend/index.html | 13 - frontend/package-lock.json | 4574 ----------------- frontend/package.json | 45 - frontend/package.json.md5 | 1 - frontend/postcss.config.js | 6 - frontend/src/App.tsx | 40 - frontend/src/assets/fonts/OFL.txt | 93 - .../fonts/nunito-v16-latin-regular.woff2 | Bin 18972 -> 0 bytes frontend/src/assets/icon/appicon.png | Bin 183818 -> 0 bytes frontend/src/assets/images/logo-universal.png | Bin 139695 -> 0 bytes frontend/src/components/ErrorBoundary.tsx | 33 - frontend/src/components/Home.tsx | 536 -- frontend/src/components/Installed.tsx | 214 - frontend/src/components/Navbar.tsx | 55 - frontend/src/components/PackageDetails.tsx | 399 -- frontend/src/components/Search.tsx | 348 -- frontend/src/components/Updates.tsx | 298 -- frontend/src/components/ui/alert.tsx | 59 - frontend/src/components/ui/badge.tsx | 36 - frontend/src/components/ui/button.tsx | 56 - frontend/src/components/ui/card.tsx | 86 - frontend/src/components/ui/checkbox.tsx | 27 - .../src/components/ui/circular-progress.tsx | 51 - frontend/src/components/ui/dropdown-menu.tsx | 198 - frontend/src/components/ui/input.tsx | 25 - frontend/src/components/ui/label.tsx | 24 - frontend/src/components/ui/progress.tsx | 26 - frontend/src/components/ui/scroll-area.tsx | 46 - frontend/src/components/ui/separator.tsx | 29 - frontend/src/components/ui/skeleton.tsx | 15 - frontend/src/components/ui/tabs.tsx | 53 - frontend/src/components/ui/theme-provider.tsx | 73 - frontend/src/components/ui/toast.tsx | 127 - frontend/src/components/ui/toaster.tsx | 33 - frontend/src/components/ui/tooltip.tsx | 28 - frontend/src/components/ui/use-toast.ts | 192 - frontend/src/globals.css | 101 - frontend/src/lib/utils.ts | 6 - frontend/src/main.tsx | 14 - frontend/src/vite-env.d.ts | 1 - frontend/tailwind.config.cjs | 77 - frontend/tsconfig.json | 37 - frontend/tsconfig.node.json | 11 - frontend/vite.config.ts | 12 - frontend/wailsjs/go/main/App.d.ts | 25 - frontend/wailsjs/go/main/App.js | 47 - frontend/wailsjs/go/models.ts | 51 - frontend/wailsjs/runtime/package.json | 24 - frontend/wailsjs/runtime/runtime.d.ts | 249 - frontend/wailsjs/runtime/runtime.js | 238 - src/core/aur_helper.cpp | 206 + src/core/aur_helper.h | 38 + 54 files changed, 244 insertions(+), 8784 deletions(-) delete mode 100644 frontend/.gitignore delete mode 100644 frontend/components.json delete mode 100644 frontend/index.html delete mode 100644 frontend/package-lock.json delete mode 100644 frontend/package.json delete mode 100755 frontend/package.json.md5 delete mode 100644 frontend/postcss.config.js delete mode 100644 frontend/src/App.tsx delete mode 100644 frontend/src/assets/fonts/OFL.txt delete mode 100644 frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 delete mode 100644 frontend/src/assets/icon/appicon.png delete mode 100644 frontend/src/assets/images/logo-universal.png delete mode 100644 frontend/src/components/ErrorBoundary.tsx delete mode 100644 frontend/src/components/Home.tsx delete mode 100644 frontend/src/components/Installed.tsx delete mode 100644 frontend/src/components/Navbar.tsx delete mode 100644 frontend/src/components/PackageDetails.tsx delete mode 100644 frontend/src/components/Search.tsx delete mode 100644 frontend/src/components/Updates.tsx delete mode 100644 frontend/src/components/ui/alert.tsx delete mode 100644 frontend/src/components/ui/badge.tsx delete mode 100644 frontend/src/components/ui/button.tsx delete mode 100644 frontend/src/components/ui/card.tsx delete mode 100644 frontend/src/components/ui/checkbox.tsx delete mode 100644 frontend/src/components/ui/circular-progress.tsx delete mode 100644 frontend/src/components/ui/dropdown-menu.tsx delete mode 100644 frontend/src/components/ui/input.tsx delete mode 100644 frontend/src/components/ui/label.tsx delete mode 100644 frontend/src/components/ui/progress.tsx delete mode 100644 frontend/src/components/ui/scroll-area.tsx delete mode 100644 frontend/src/components/ui/separator.tsx delete mode 100644 frontend/src/components/ui/skeleton.tsx delete mode 100644 frontend/src/components/ui/tabs.tsx delete mode 100644 frontend/src/components/ui/theme-provider.tsx delete mode 100644 frontend/src/components/ui/toast.tsx delete mode 100644 frontend/src/components/ui/toaster.tsx delete mode 100644 frontend/src/components/ui/tooltip.tsx delete mode 100644 frontend/src/components/ui/use-toast.ts delete mode 100644 frontend/src/globals.css delete mode 100644 frontend/src/lib/utils.ts delete mode 100644 frontend/src/main.tsx delete mode 100644 frontend/src/vite-env.d.ts delete mode 100644 frontend/tailwind.config.cjs delete mode 100644 frontend/tsconfig.json delete mode 100644 frontend/tsconfig.node.json delete mode 100644 frontend/vite.config.ts delete mode 100755 frontend/wailsjs/go/main/App.d.ts delete mode 100755 frontend/wailsjs/go/main/App.js delete mode 100755 frontend/wailsjs/go/models.ts delete mode 100644 frontend/wailsjs/runtime/package.json delete mode 100644 frontend/wailsjs/runtime/runtime.d.ts delete mode 100644 frontend/wailsjs/runtime/runtime.js create mode 100644 src/core/aur_helper.cpp create mode 100644 src/core/aur_helper.h diff --git a/frontend/.gitignore b/frontend/.gitignore deleted file mode 100644 index ae34bd3..0000000 --- a/frontend/.gitignore +++ /dev/null @@ -1,36 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# next.js -/.next/ - - -# production -/build -/dist - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* -.pnpm-debug.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo \ No newline at end of file diff --git a/frontend/components.json b/frontend/components.json deleted file mode 100644 index 7c79d38..0000000 --- a/frontend/components.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://ui.shadcn.com/schema.json", - "style": "new-york", - "rsc": false, - "tsx": true, - "tailwind": { - "config": "tailwind.config.js", - "css": "src/globals.css", - "baseColor": "slate", - "cssVariables": true - }, - "aliases": { - "components": "@/components", - "utils": "@/lib/utils" - } -} diff --git a/frontend/index.html b/frontend/index.html deleted file mode 100644 index edbc62d..0000000 --- a/frontend/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - myproject - - -
- - - - diff --git a/frontend/package-lock.json b/frontend/package-lock.json deleted file mode 100644 index 2293397..0000000 --- a/frontend/package-lock.json +++ /dev/null @@ -1,4574 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "frontend", - "version": "0.0.0", - "dependencies": { - "@radix-ui/react-checkbox": "^1.1.4", - "@radix-ui/react-dropdown-menu": "^2.1.6", - "@radix-ui/react-icons": "^1.3.2", - "@radix-ui/react-label": "^2.1.0", - "@radix-ui/react-progress": "^1.1.0", - "@radix-ui/react-scroll-area": "^1.1.0", - "@radix-ui/react-separator": "^1.1.0", - "@radix-ui/react-slot": "^1.0.2", - "@radix-ui/react-tabs": "^1.1.0", - "@radix-ui/react-toast": "^1.2.1", - "@radix-ui/react-tooltip": "^1.1.2", - "@types/react-window": "^1.8.8", - "class-variance-authority": "^0.7.0", - "clsx": "^2.0.0", - "lucide-react": "^0.290.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-virtualized-auto-sizer": "^1.0.24", - "react-window": "^1.8.10", - "tailwind-merge": "^1.14.0", - "tailwindcss-animate": "^1.0.7" - }, - "devDependencies": { - "@types/node": "^20.8.9", - "@types/react": "^18.0.17", - "@types/react-dom": "^18.0.6", - "@vitejs/plugin-react": "^2.0.1", - "autoprefixer": "^10.4.16", - "postcss": "^8.4.31", - "tailwindcss": "^3.3.5", - "typescript": "^4.6.4", - "vite": "^3.0.7" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", - "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", - "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.9", - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-module-transforms": "^7.24.9", - "@babel/helpers": "^7.24.8", - "@babel/parser": "^7.24.8", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.9", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.24.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz", - "integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.9", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", - "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.24.8", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", - "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", - "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", - "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", - "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", - "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", - "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", - "dev": true, - "license": "MIT", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", - "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-jsx": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", - "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", - "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", - "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", - "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", - "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.8", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.8", - "@babel/types": "^7.24.8", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", - "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", - "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", - "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@floating-ui/core": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.5.tgz", - "integrity": "sha512-8GrTWmoFhm5BsMZOTHeGD2/0FLKLQQHvO/ZmQga4tKempYRLz8aqJGqXVuQgisnMObq2YZ2SgkwctN1LOOxcqA==", - "license": "MIT", - "dependencies": { - "@floating-ui/utils": "^0.2.5" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.8.tgz", - "integrity": "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q==", - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.5" - } - }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", - "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", - "license": "MIT", - "dependencies": { - "@floating-ui/dom": "^1.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.5.tgz", - "integrity": "sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ==", - "license": "MIT" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@radix-ui/number": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", - "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==", - "license": "MIT" - }, - "node_modules/@radix-ui/primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", - "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==", - "license": "MIT" - }, - "node_modules/@radix-ui/react-arrow": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", - "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.0.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-checkbox": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.4.tgz", - "integrity": "sha512-wP0CPAHq+P5I4INKe3hJrIa1WoNqqrejzW+zoU0rOvo1b9gDEJJFl2rYfO1PYJUQCc2H1WZxIJmyv9BS8i5fLw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-use-size": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", - "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==", - "license": "MIT" - }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-presence": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", - "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-primitive": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", - "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-collection": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", - "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-slot": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-context": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", - "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-direction": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", - "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz", - "integrity": "sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-escape-keydown": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.6.tgz", - "integrity": "sha512-no3X7V5fD487wab/ZYSHXq3H37u4NVeLDKI/Ks724X/eEFSSEFYZxWgsIlr1UBeEyDaM29HM5x9p1Nv8DuTYPA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-menu": "2.1.6", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-controllable-state": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", - "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==", - "license": "MIT" - }, - "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-primitive": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", - "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", - "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz", - "integrity": "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-scope/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-scope/node_modules/@radix-ui/react-primitive": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", - "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-scope/node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-icons": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.2.tgz", - "integrity": "sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==", - "license": "MIT", - "peerDependencies": { - "react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc" - } - }, - "node_modules/@radix-ui/react-id": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", - "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-label": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz", - "integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.0.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.6.tgz", - "integrity": "sha512-tBBb5CXDJW3t2mo9WlO7r6GTmWV0F0uzHZVFmlRmYpiSK1CDU5IKojP1pm7oknpBOrFZx/YgBRW9oorPO2S/Lg==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.5", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.2", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.2", - "@radix-ui/react-portal": "1.1.4", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-roving-focus": "1.1.2", - "@radix-ui/react-slot": "1.1.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", - "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==", - "license": "MIT" - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-arrow": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.2.tgz", - "integrity": "sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.0.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-collection": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.2.tgz", - "integrity": "sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-slot": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz", - "integrity": "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-escape-keydown": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-popper": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.2.tgz", - "integrity": "sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA==", - "license": "MIT", - "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-rect": "1.1.0", - "@radix-ui/react-use-size": "1.1.0", - "@radix-ui/rect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-portal": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.4.tgz", - "integrity": "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-presence": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", - "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-primitive": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", - "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.1.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.2.tgz", - "integrity": "sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popper": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", - "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", - "license": "MIT", - "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-rect": "1.1.0", - "@radix-ui/react-use-size": "1.1.0", - "@radix-ui/rect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-portal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.1.tgz", - "integrity": "sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-presence": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz", - "integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", - "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-progress": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.0.tgz", - "integrity": "sha512-aSzvnYpP725CROcxAOEBVZZSIQVQdHgBr2QQFKySsaD14u8dNT0batuXI+AAGDdAHfXH8rbnHmjYFqVJ21KkRg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-primitive": "2.0.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz", - "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-collection": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-scroll-area": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.1.0.tgz", - "integrity": "sha512-9ArIZ9HWhsrfqS765h+GZuLoxaRHD/j0ZWOWilsCvYTpYJp8XwCqNG7Dt9Nu/TItKOdgLGkOPCodQvDc+UMwYg==", - "license": "MIT", - "dependencies": { - "@radix-ui/number": "1.1.0", - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-presence": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.0.tgz", - "integrity": "sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.0.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", - "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tabs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.0.tgz", - "integrity": "sha512-bZgOKB/LtZIij75FSuPzyEti/XBhJH52ExgtdVqjCIh+Nx/FW+LhnbXtbCzIi34ccyMsyOja8T0thCzoHFXNKA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-presence": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-roving-focus": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-toast": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.1.tgz", - "integrity": "sha512-5trl7piMXcZiCq7MW6r8YYmu0bK5qDpTWz+FdEPdKyft2UixkspheYbjbrLXVN5NGKHFbOP7lm8eD0biiSqZqg==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-collection": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.0", - "@radix-ui/react-portal": "1.1.1", - "@radix-ui/react-presence": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-visually-hidden": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tooltip": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.2.tgz", - "integrity": "sha512-9XRsLwe6Yb9B/tlnYCPVUd/TFS4J7HuOZW345DCeC6vKIxQGMZdx21RK4VoZauPD5frgkXTYVS5y90L+3YBn4w==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.0", - "@radix-ui/react-portal": "1.1.1", - "@radix-ui/react-presence": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-slot": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-visually-hidden": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", - "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", - "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-previous": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", - "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", - "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/rect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-size": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", - "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz", - "integrity": "sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.0.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", - "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==", - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.14.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz", - "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", - "license": "MIT", - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/react-window": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz", - "integrity": "sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==", - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-2.2.0.tgz", - "integrity": "sha512-FFpefhvExd1toVRlokZgxgy2JtnBOdp4ZDsq7ldCWaqGSGn9UhWMAVm/1lxPL14JfNS5yGz+s9yFrQY6shoStA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.19.6", - "@babel/plugin-transform-react-jsx": "^7.19.0", - "@babel/plugin-transform-react-jsx-development": "^7.18.6", - "@babel/plugin-transform-react-jsx-self": "^7.18.6", - "@babel/plugin-transform-react-jsx-source": "^7.19.6", - "magic-string": "^0.26.7", - "react-refresh": "^0.14.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^3.0.0" - } - }, - "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, - "license": "MIT" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true, - "license": "MIT" - }, - "node_modules/aria-hidden": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", - "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/autoprefixer": { - "version": "10.4.19", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", - "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "browserslist": "^4.23.0", - "caniuse-lite": "^1.0.30001599", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.23.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", - "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001640", - "electron-to-chromium": "^1.4.820", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.1.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001700", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz", - "integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/class-variance-authority": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz", - "integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==", - "license": "Apache-2.0", - "dependencies": { - "clsx": "2.0.0" - }, - "funding": { - "url": "https://joebell.co.uk" - } - }, - "node_modules/class-variance-authority/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/detect-node-es": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", - "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", - "license": "MIT" - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true, - "license": "MIT" - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.0.tgz", - "integrity": "sha512-Vb3xHHYnLseK8vlMJQKJYXJ++t4u1/qJ3vykuVrVjvdiOEhYyT1AuP4x03G8EnPmYvYOhe9T+dADTmthjRQMkA==", - "dev": true, - "license": "ISC" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", - "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.15.18", - "@esbuild/linux-loong64": "0.15.18", - "esbuild-android-64": "0.15.18", - "esbuild-android-arm64": "0.15.18", - "esbuild-darwin-64": "0.15.18", - "esbuild-darwin-arm64": "0.15.18", - "esbuild-freebsd-64": "0.15.18", - "esbuild-freebsd-arm64": "0.15.18", - "esbuild-linux-32": "0.15.18", - "esbuild-linux-64": "0.15.18", - "esbuild-linux-arm": "0.15.18", - "esbuild-linux-arm64": "0.15.18", - "esbuild-linux-mips64le": "0.15.18", - "esbuild-linux-ppc64le": "0.15.18", - "esbuild-linux-riscv64": "0.15.18", - "esbuild-linux-s390x": "0.15.18", - "esbuild-netbsd-64": "0.15.18", - "esbuild-openbsd-64": "0.15.18", - "esbuild-sunos-64": "0.15.18", - "esbuild-windows-32": "0.15.18", - "esbuild-windows-64": "0.15.18", - "esbuild-windows-arm64": "0.15.18" - } - }, - "node_modules/esbuild-android-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", - "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", - "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", - "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", - "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", - "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", - "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", - "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", - "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", - "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", - "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", - "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", - "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", - "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", - "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", - "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", - "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", - "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", - "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", - "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", - "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/foreground-child": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", - "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-nonce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", - "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", - "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jiti": { - "version": "1.21.6", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", - "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lucide-react": { - "version": "0.290.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.290.0.tgz", - "integrity": "sha512-CBDPRLOPjdo+bVlxhaa7FVWaB8OrZZQ34mwm0Fsz9ut6JltN/Td55640ur8bRWSJuz6+nX2klKrpBpV7ktwD3Q==", - "license": "ISC", - "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/magic-string": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", - "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", - "dev": true, - "license": "MIT", - "dependencies": { - "sourcemap-codec": "^1.4.8" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/memoize-one": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", - "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/postcss": { - "version": "8.4.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", - "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "postcss-selector-parser": "^6.1.1" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", - "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-remove-scroll": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz", - "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==", - "license": "MIT", - "dependencies": { - "react-remove-scroll-bar": "^2.3.7", - "react-style-singleton": "^2.2.3", - "tslib": "^2.1.0", - "use-callback-ref": "^1.3.3", - "use-sidecar": "^1.1.3" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-remove-scroll-bar": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", - "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", - "license": "MIT", - "dependencies": { - "react-style-singleton": "^2.2.2", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-style-singleton": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", - "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", - "license": "MIT", - "dependencies": { - "get-nonce": "^1.0.0", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/react-virtualized-auto-sizer": { - "version": "1.0.24", - "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.24.tgz", - "integrity": "sha512-3kCn7N9NEb3FlvJrSHWGQ4iVl+ydQObq2fHMn12i5wbtm74zHOPhz/i64OL3c1S1vi9i2GXtZqNqUJTQ+BnNfg==", - "license": "MIT", - "peerDependencies": { - "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0", - "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/react-window": { - "version": "1.8.10", - "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.10.tgz", - "integrity": "sha512-Y0Cx+dnU6NLa5/EvoHukUD0BklJ8qITCtVEPY1C/nL8wwoZ0b5aEw8Ff1dOVHw7fCzMt55XfJDd8S8W8LCaUCg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.0.0", - "memoize-one": ">=3.1.1 <6" - }, - "engines": { - "node": ">8.0.0" - }, - "peerDependencies": { - "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", - "dev": true, - "license": "MIT", - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead", - "dev": true, - "license": "MIT" - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/sucrase": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", - "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "^10.3.10", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tailwind-merge": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.14.0.tgz", - "integrity": "sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/dcastil" - } - }, - "node_modules/tailwindcss": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.6.tgz", - "integrity": "sha512-1uRHzPB+Vzu57ocybfZ4jh5Q3SdlH7XW23J5sQoM9LhE9eIOlzxer/3XPSsycvih3rboRsvt0QCmzSrqyOYUIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.0", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.0", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tailwindcss-animate": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", - "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", - "license": "MIT", - "peerDependencies": { - "tailwindcss": ">=3.0.0 || insiders" - } - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true, - "license": "MIT" - }, - "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/use-callback-ref": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", - "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/use-sidecar": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", - "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", - "license": "MIT", - "dependencies": { - "detect-node-es": "^1.1.0", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/vite": { - "version": "3.2.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.10.tgz", - "integrity": "sha512-Dx3olBo/ODNiMVk/cA5Yft9Ws+snLOXrhLtrI3F4XLt4syz2Yg8fayZMWScPKoz12v5BUv7VEmQHnsfpY80fYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.15.9", - "postcss": "^8.4.18", - "resolve": "^1.22.1", - "rollup": "^2.79.1" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/yaml": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", - "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - } - } -} diff --git a/frontend/package.json b/frontend/package.json deleted file mode 100644 index 10affba..0000000 --- a/frontend/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc && vite build", - "preview": "vite preview" - }, - "dependencies": { - "@radix-ui/react-checkbox": "^1.1.4", - "@radix-ui/react-dropdown-menu": "^2.1.6", - "@radix-ui/react-icons": "^1.3.2", - "@radix-ui/react-label": "^2.1.0", - "@radix-ui/react-progress": "^1.1.0", - "@radix-ui/react-scroll-area": "^1.1.0", - "@radix-ui/react-separator": "^1.1.0", - "@radix-ui/react-slot": "^1.0.2", - "@radix-ui/react-tabs": "^1.1.0", - "@radix-ui/react-toast": "^1.2.1", - "@radix-ui/react-tooltip": "^1.1.2", - "@types/react-window": "^1.8.8", - "class-variance-authority": "^0.7.0", - "clsx": "^2.0.0", - "lucide-react": "^0.290.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-virtualized-auto-sizer": "^1.0.24", - "react-window": "^1.8.10", - "tailwind-merge": "^1.14.0", - "tailwindcss-animate": "^1.0.7" - }, - "devDependencies": { - "@types/node": "^20.8.9", - "@types/react": "^18.0.17", - "@types/react-dom": "^18.0.6", - "@vitejs/plugin-react": "^2.0.1", - "autoprefixer": "^10.4.16", - "postcss": "^8.4.31", - "tailwindcss": "^3.3.5", - "typescript": "^4.6.4", - "vite": "^3.0.7" - } -} diff --git a/frontend/package.json.md5 b/frontend/package.json.md5 deleted file mode 100755 index 44dddfb..0000000 --- a/frontend/package.json.md5 +++ /dev/null @@ -1 +0,0 @@ -dba055dd0a545865cffe1a57e682c54b \ No newline at end of file diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js deleted file mode 100644 index 2e7af2b..0000000 --- a/frontend/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx deleted file mode 100644 index 6ebebc9..0000000 --- a/frontend/src/App.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React, { useState } from "react"; -import { ThemeProvider } from "./components/ui/theme-provider"; -import Navbar from "./components/Navbar"; -import Home from "./components/Home"; -import Search from "./components/Search"; -import Install from "./components/Installed"; -import { Toaster } from "./components/ui/toaster"; -import Updates from "./components/Updates"; - -type PageType = "home" | "search" | "install" | "updates"; - -const App: React.FC = () => { - const [currentPage, setCurrentPage] = useState("home"); - const renderPage = () => { - switch (currentPage) { - case "home": - return ; - case "search": - return ; - case "install": - return ; - case "updates": - return ; - default: - return ; - } - }; - - return ( - -
- -
{renderPage()}
- -
-
- ); -}; - -export default App; diff --git a/frontend/src/assets/fonts/OFL.txt b/frontend/src/assets/fonts/OFL.txt deleted file mode 100644 index 9cac04c..0000000 --- a/frontend/src/assets/fonts/OFL.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2016 The Nunito Project Authors (contact@sansoxygen.com), - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 b/frontend/src/assets/fonts/nunito-v16-latin-regular.woff2 deleted file mode 100644 index 2f9cc5964455b8f5ca989db989250dbebb1a5f66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18972 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 diff --git a/frontend/src/assets/images/logo-universal.png b/frontend/src/assets/images/logo-universal.png deleted file mode 100644 index 99ac71f5a38d0b2350d101f7dea65694c10671a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 139695 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

``Cl35~rb|Fd`a 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�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 { - public state: State = { - hasError: false, - }; - - public static getDerivedStateFromError(_: Error): State { - return { hasError: true }; - } - - public componentDidCatch(error: Error, errorInfo: ErrorInfo) { - console.error("Uncaught error:", error, errorInfo); - } - - public render() { - if (this.state.hasError) { - return

Sorry, there was an error

; - } - - return this.props.children; - } -} - -export default ErrorBoundary; diff --git a/frontend/src/components/Home.tsx b/frontend/src/components/Home.tsx deleted file mode 100644 index 621de13..0000000 --- a/frontend/src/components/Home.tsx +++ /dev/null @@ -1,536 +0,0 @@ -import { useCallback, useEffect, useState } from "react"; -import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "../components/ui/card"; -import { Badge } from "../components/ui/badge"; -import { ScrollArea } from "../components/ui/scroll-area"; -import PackageDetails from "./PackageDetails"; -import ErrorBoundary from "./ErrorBoundary"; -import { CheckPackageInstalled } from "../../wailsjs/go/main/App"; - -interface AppInfo { - name: string; - version: string; - description: string; - repository: string; - maintainer: string; - upstreamurl: string; - dependlist: string[]; - lastupdated: string; -} - -const featuredApps: AppInfo[] = [ - { - name: "firefox", - version: "128.0.2-1", - description: "Fast, Private \u0026 Safe Web Browser", - repository: "extra", - maintainer: - "Jan Alexander Steffens (heftig) \u003cheftig@archlinux.org\u003e", - upstreamurl: "https://www.mozilla.org/firefox/", - dependlist: [ - "alsa-lib", - "at-spi2-core", - "bash", - "cairo", - "dbus", - "ffmpeg", - "fontconfig", - "freetype2", - "gcc-libs", - "gdk-pixbuf2", - "glib2", - "glibc", - "gtk3", - "hicolor-icon-theme", - "libpulse", - "libx11", - "libxcb", - "libxcomposite", - "libxdamage", - "libxext", - "libxfixes", - "libxrandr", - "libxss", - "libxt", - "mime-types", - "nspr", - "nss", - "pango", - "ttf-font", - ], - lastupdated: "Jul. 23, 2024, 4 p.m. UTC", - }, - { - name: "gimp", - description: "GNU Image Manipulation Program", - repository: "extra", - version: "2.10.38-1", - maintainer: "Christian Hesse, Christian Heusel", - lastupdated: "May 3, 2024, 9:48 a.m. UTC", - dependlist: [ - "aalib", - "babl", - "bzip2", - "cairo", - "fontconfig", - "freetype2", - "gcc-libs", - "gdk-pixbuf2", - "gegl", - "glib2", - "glibc", - "gtk2", - "harfbuzz", - "hicolor-icon-theme", - "iso-codes", - "json-glib", - "lcms2", - "libgexiv2", - "libgudev", - "libheif", - "libjpeg-turbo", - "libjxl", - "libmng", - "libmypaint", - "libpng", - "librsvg", - "libtiff", - "libunwind", - "libwebp", - "libwmf", - "libx11", - "libxcursor", - "libxext", - "libxfixes", - "libxmu", - "libxpm", - "mypaint-brushes1", - "openexr", - "openjpeg2", - "pango", - "poppler-data", - "poppler-glib", - "xz", - "zlib", - ], - upstreamurl: "https://www.gimp.org/", - }, - { - name: "vlc", - version: "3.0.21-1", - description: "Multi-platform MPEG, VCD/DVD, and DivX player", - repository: "extra", - maintainer: "Antonio Rojas \u003carojas@archlinux.org\u003e", - upstreamurl: "https://www.videolan.org/vlc/", - dependlist: [ - "a52dec", - "abseil-cpp", - "aribb24", - "bash", - "cairo", - "dbus", - "faad2", - "ffmpeg4.4", - "fontconfig", - "freetype2", - "fribidi", - "gcc-libs", - "gdk-pixbuf2", - "glib2", - "glibc", - "gnutls", - "harfbuzz", - "hicolor-icon-theme", - "libarchive", - "libdca", - "libdvbpsi", - "libglvnd", - "libidn", - "libmad", - "libmatroska", - "libmpcdec", - "libmpeg2", - "libproxy", - "libsecret", - "libtar", - "libupnp", - "libixml.so", - "libupnp.so", - "libva", - "libx11", - "libxcb", - "libxinerama", - "libxml2", - "libxpm", - "lua", - "qt5-base", - "qt5-svg", - "qt5-x11extras", - "taglib", - "wayland", - "xcb-util-keysyms", - "zlib", - ], - lastupdated: "Jun. 16, 2024, 8 p.m. UTC", - }, - { - name: "visual-studio-code-bin", - description: - "Visual Studio Code (vscode): Editor for building and debugging modern web and cloud applications (official binary version)", - repository: "AUR", - version: "1.57.0", - maintainer: "Microsoft", - lastupdated: "2023-06-10", - dependlist: [ - "libxkbfile", - "gnupg", - "gtk3", - "libsecret", - "nss", - "gcc-libs", - "libnotify", - "libxss", - "glibc", - "lsof", - "shared-mime-info", - "xdg-utils", - "alsa-lib", - ], - upstreamurl: "", - }, - { - name: "libreoffice-still", - version: "7.6.7-1", - description: "LibreOffice maintenance branch", - repository: "extra", - maintainer: "Andreas Radke \u003candyrtr@archlinux.org\u003e", - upstreamurl: "https://www.libreoffice.org/", - dependlist: [ - "curl", - "hunspell", - "python", - "libwpd", - "libwps", - "neon", - "pango", - "nspr", - "libjpeg", - "libxrandr", - "libgl", - "redland", - "hyphen", - "lpsolve", - "gcc-libs", - "sh", - "graphite", - "icu", - "libxslt", - "lcms2", - "libvisio", - "libetonyek", - "libodfgen", - "libcdr", - "libmspub", - "harfbuzz-icu", - "nss", - "clucene", - "hicolor-icon-theme", - "desktop-file-utils", - "shared-mime-info", - "libpagemaker", - "libxinerama", - "libabw", - "libmwaw", - "libe-book", - "libcups", - "liblangtag", - "libexttextcat", - "liborcus", - "libwebp", - "libcmis", - "libtommath", - "libzmf", - "libatomic_ops", - "libnumbertext", - "gpgme", - "libfreehand", - "libstaroffice", - "libepubgen", - "libqxp", - "libepoxy", - "box2d", - "zxing-cpp", - "xdg-utils", - "libldap", - "fontconfig", - "zlib", - "libpng", - "freetype2", - "raptor", - "libxml2", - "cairo", - "libx11", - "expat", - "glib2", - "boost-libs", - "libtiff", - "dbus", - "glibc", - "librevenge", - "libxext", - "openjpeg2", - ], - lastupdated: "May. 19, 2024, 7 p.m. UTC", - }, - { - name: "blender", - version: "17:4.2.0-3", - description: "A fully integrated 3D graphics creation suite", - repository: "extra", - maintainer: "Sven-Hendrik Haase \u003csvenstaro@archlinux.org\u003e", - upstreamurl: "https://www.blender.org", - dependlist: [ - "alembic", - "bash", - "boost-libs", - "draco", - "embree", - "expat", - "ffmpeg", - "fftw", - "freetype2", - "gcc-libs", - "glew", - "glibc", - "gmp", - "hicolor-icon-theme", - "imath", - "intel-oneapi-compiler-dpcpp-cpp-runtime-libs", - "intel-oneapi-compiler-shared-runtime-libs", - "jack", - "jemalloc", - "level-zero-loader", - "libepoxy", - "libharu", - "libjpeg-turbo", - "libpng", - "libsndfile", - "libspnav", - "libtiff", - "libwebp", - "libx11", - "libxfixes", - "libxi", - "libxkbcommon", - "libxml2", - "libxrender", - "libxxf86vm", - "llvm-libs", - "materialx", - "onetbb", - "openal", - "opencollada", - "opencolorio", - "openexr", - "openimagedenoise", - "openimageio", - "openjpeg2", - "openpgl", - "openshadinglanguage", - "opensubdiv", - "openvdb", - "openxr", - "potrace", - "pugixml", - "pystring", - "python", - "python-numpy", - "python-requests", - "sdl2", - "shared-mime-info", - "usd", - "xdg-utils", - "yaml-cpp", - "zlib", - "zstd", - ], - lastupdated: "Jul. 17, 2024, 12 p.m. UTC", - }, - { - name: "zed", - version: "0.144.4-1", - description: - "A high-performance, multiplayer code editor from the creators of Atom and Tree-sitter", - repository: "extra", - maintainer: "Caleb Maclennan \u003calerque@archlinux.org\u003e", - upstreamurl: "https://zed.dev", - dependlist: [ - "alsa-lib", - "libasound.so", - "fontconfig", - "gcc-libs", - "glibc", - "libxcb", - "libxkbcommon", - "libxkbcommon-x11", - "openssl", - "libcrypto.so", - "libssl.so", - "sqlite", - "vulkan-driver", - "vulkan-icd-loader", - "vulkan-tools", - "wayland", - "zlib", - "libz.so", - ], - lastupdated: "Jul. 19, 2024, 9 p.m. UTC", - }, - { - name: "git", - version: "2.45.2-1", - description: "the fast distributed version control system", - repository: "extra", - maintainer: "Christian Hesse \u003ceworm@archlinux.org\u003e", - upstreamurl: "https://git-scm.com/", - dependlist: [ - "curl", - "expat", - "perl", - "perl-error", - "perl-mailtools", - "openssl", - "pcre2", - "grep", - "shadow", - "zlib", - ], - lastupdated: "Jun. 1, 2024, 9 p.m. UTC", - }, - { - name: "google-chrome", - version: "127.0.6533.72-1", - description: "The popular web browser by Google (Stable Channel)", - repository: "AUR", - maintainer: "gromit", - upstreamurl: "https://www.google.com/chrome", - dependlist: [ - "alsa-lib", - "gtk3", - "libcups", - "libxss", - "libxtst", - "nss", - "ttf-liberation", - "xdg-utils", - ], - lastupdated: "23-07-2024", - }, -]; - -const Home = () => { - const [selectedApp, setSelectedApp] = useState(null); - const [installedApps, setInstalledApps] = useState>(new Set()); - - const checkInstalledApps = useCallback(async () => { - try { - const installedSet = new Set(); - for (const app of featuredApps) { - try { - const isInstalled = await CheckPackageInstalled(app.name); - if (isInstalled) { - installedSet.add(app.name); - } - } catch (error) { - console.error(`Error checking if ${app.name} is installed:`, error); - } - } - setInstalledApps(installedSet); - } catch (error) { - console.error("Error fetching package information:", error); - } - }, []); - - useEffect(() => { - checkInstalledApps(); - const interval = setInterval(checkInstalledApps, 3000); - return () => clearInterval(interval); - }, [checkInstalledApps]); - - const handleInstallStateChange = useCallback(() => { - checkInstalledApps(); - }, [checkInstalledApps]); - - const handleBack = useCallback(() => { - setSelectedApp(null); - }, []); - - const handleSelectApp = useCallback((app: AppInfo) => { - setSelectedApp({ ...app }); - }, []); - - if (selectedApp) { - return ( - - - - ); - } - - return ( - -
-

Mentioned Packages

- -
- {featuredApps.map((app, index) => ( - handleSelectApp(app)} - > - -
- {app.name} - {installedApps.has(app.name) && ( - - Installed - - )} -
-
- - - {app.description && app.description.length > 70 - ? `${app.description.substring(0, 80)}...` - : app.description} - -

- Version: {app.version} -

-
- - - {app.repository} - - -
- ))} -
-
-
-
- ); -}; - -export default Home; diff --git a/frontend/src/components/Installed.tsx b/frontend/src/components/Installed.tsx deleted file mode 100644 index 3e78d9b..0000000 --- a/frontend/src/components/Installed.tsx +++ /dev/null @@ -1,214 +0,0 @@ -import React, { useState, useEffect, useCallback, useMemo } from "react"; -import { FixedSizeGrid as Grid } from "react-window"; -import AutoSizer from "react-virtualized-auto-sizer"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@/components/ui/card"; -import { GetInstalledPackages } from "../../wailsjs/go/main/App"; -import { main } from "wailsjs/go/models"; -import { Badge } from "./ui/badge"; -import { Skeleton } from "./ui/skeleton"; -import PackageDetails from "./PackageDetails"; -import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; -import { AlertCircle } from "lucide-react"; - -const Installed = () => { - const [installedPackages, setInstalledPackages] = useState< - main.PackageInfo[] - >([]); - const [isLoading, setIsLoading] = useState(true); - const [error, setError] = useState(null); - const [searchTerm, setSearchTerm] = useState(""); - const [selectedPackage, setSelectedPackage] = - useState(null); - - const fetchInstalledPackages = useCallback(async () => { - setIsLoading(true); - try { - const packages = await GetInstalledPackages(); - setInstalledPackages(packages); - setError(null); - } catch (err) { - console.error("Error fetching installed packages:", err); - setError("Failed to fetch installed packages. Please try again."); - } finally { - setIsLoading(false); - } - }, []); - - useEffect(() => { - fetchInstalledPackages(); - const intervalId = setInterval(fetchInstalledPackages, 5000); - return () => clearInterval(intervalId); - }, [fetchInstalledPackages]); - - const filteredPackages = useMemo(() => { - return installedPackages.filter((pkg) => - pkg.name.toLowerCase().includes(searchTerm.toLowerCase()) - ); - }, [installedPackages, searchTerm]); - - const PackageItem = useCallback( - ({ - columnIndex, - rowIndex, - style, - }: { - columnIndex: number; - rowIndex: number; - style: React.CSSProperties; - }) => { - const index = rowIndex * 3 + columnIndex; - const pkg = filteredPackages[index]; - if (!pkg) return null; - - return ( -
- setSelectedPackage(pkg)} - > - - {pkg.name} - - - - {pkg.description && pkg.description.length > 70 - ? `${pkg.description.substring(0, 80)}...` - : pkg.description} - -

- Last Updated: {pkg.lastupdated} -

-
- - - {pkg.version} - - -
-
- ); - }, - [filteredPackages] - ); - - const renderContent = useMemo(() => { - if (isLoading && installedPackages.length === 0) { - return ( -
- {Array.from({ length: 9 }, (_, i) => ( - - - - - - - - - - - - - ))} -
- ); - } - - if (error) { - return ( - - - Error - {error} - - ); - } - - if (filteredPackages.length === 0) { - return ( -
- - - No packages found - - - {searchTerm - ? "No packages match your search." - : "No installed packages found."} - - -
- ); - } - - return ( -
- - {({ height, width }: { height: number; width: number }) => { - const columnCount = width >= 1024 ? 3 : width >= 768 ? 2 : 1; - const columnWidth = width / columnCount; - const rowCount = Math.ceil(filteredPackages.length / columnCount); - return ( - - {PackageItem} - - ); - }} - -
- ); - }, [ - isLoading, - error, - filteredPackages, - PackageItem, - installedPackages.length, - searchTerm, - ]); - - return ( -
- {selectedPackage ? ( - setSelectedPackage(null)} - onInstallStateChange={fetchInstalledPackages} - /> - ) : ( - <> -

Installed Packages

-
- ) => - setSearchTerm(e.target.value) - } - className="flex-grow" - aria-label="Search installed packages" - /> -
- {renderContent} - - )} -
- ); -}; - -export default React.memo(Installed); diff --git a/frontend/src/components/Navbar.tsx b/frontend/src/components/Navbar.tsx deleted file mode 100644 index 0e0da85..0000000 --- a/frontend/src/components/Navbar.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import React from "react"; -import { Search, Package, PackagePlus, Home, Moon, Sun } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { useTheme } from "@/components/ui/theme-provider"; - -type PageType = "home" | "search" | "install" | "updates"; - -interface NavbarProps { - setCurrentPage: (page: PageType) => void; -} - -const Navbar: React.FC = ({ setCurrentPage }) => { - const { setTheme, theme } = useTheme(); - - return ( - - ); -}; - -export default Navbar; diff --git a/frontend/src/components/PackageDetails.tsx b/frontend/src/components/PackageDetails.tsx deleted file mode 100644 index 53c1135..0000000 --- a/frontend/src/components/PackageDetails.tsx +++ /dev/null @@ -1,399 +0,0 @@ -import React, { - useEffect, - useState, - useCallback, - useMemo, - useRef, -} from "react"; -import { Button } from "@/components/ui/button"; -import { ArrowLeft, Download, Check, Copy, Trash2 } from "lucide-react"; -import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@/components/ui/card"; -import { Badge } from "@/components/ui/badge"; -import { Separator } from "@/components/ui/separator"; -import { ScrollArea } from "@/components/ui/scroll-area"; -import { main } from "wailsjs/go/models"; -import { - CheckPackageInstalled, - Install, - Uninstall, -} from "../../wailsjs/go/main/App"; -import ErrorBoundary from "./ErrorBoundary"; -import { Skeleton } from "./ui/skeleton"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs"; -import CircularProgress from "./ui/circular-progress"; - -interface PackageDetailsProps { - app: main.PackageInfo | null; - onBack: () => void; - onInstallStateChange: () => void; -} - -const PackageDetails: React.FC = ({ - app, - onBack, - onInstallStateChange, -}) => { - const [isInstalled, setIsInstalled] = useState(false); - const [isCheckingInstall, setIsCheckingInstall] = useState(false); - const [isInstalling, setIsInstalling] = useState(false); - const [installProgress, setInstallProgress] = useState(0); - const [error, setError] = useState(null); - const [isLoading, setIsLoading] = useState(true); - const installInstructionsRef = useRef(null); - const [copiedCommand, setCopiedCommand] = useState(null); - - const handleCopyCommand = (command: string) => { - navigator.clipboard.writeText(command).then(() => { - setCopiedCommand(command); - setTimeout(() => setCopiedCommand(null), 2000); - }); - }; - - const checkIfInstalled = useCallback(async (appName: string) => { - try { - setIsCheckingInstall(true); - setError(null); - const isExist = await CheckPackageInstalled(appName); - setIsInstalled(isExist); - } catch (err) { - console.error("Error checking package installation:", err); - } finally { - setIsCheckingInstall(false); - } - }, []); - - useEffect(() => { - if (app?.name) { - setIsLoading(true); - checkIfInstalled(app.name).finally(() => setIsLoading(false)); - } - }, [app, checkIfInstalled]); - - const handleInstall = useCallback(async () => { - if (!app?.name) return; - - try { - setIsInstalling(true); - setInstallProgress(0); - setError(null); - - const installationInterval = setInterval(() => { - setInstallProgress((prev) => Math.min(prev + 10, 90)); - }, 500); - - await Install(app.name); - - clearInterval(installationInterval); - setInstallProgress(100); - await checkIfInstalled(app.name); - onInstallStateChange(); - } catch (err) { - setError("Failed to install package"); - console.error("Error installing package:", err); - } finally { - const isExist = await CheckPackageInstalled(app.name); - setIsInstalled(isExist); - setIsInstalling(false); - } - }, [app, onInstallStateChange]); - - const handleUninstall = async () => { - if (!app?.name) return; - - try { - setIsInstalling(true); - setInstallProgress(0); - setError(null); - - const installationInterval = setInterval(() => { - setInstallProgress((prev) => Math.min(prev + 10, 90)); - }, 500); - - await Uninstall(app.name); - - clearInterval(installationInterval); - setInstallProgress(100); - await checkIfInstalled(app.name); - onInstallStateChange(); - } catch (err) { - setError("Failed to install package"); - console.error("Error installing package:", err); - } finally { - const isExist = await CheckPackageInstalled(app.name); - setIsInstalled(isExist); - setIsInstalling(false); - } - }; - - const renderDependencies = useMemo(() => { - const dependencies = app?.dependlist; - if (!dependencies || dependencies.length === 0) { - return

No dependencies listed.

; - } - return ( -
    - {dependencies.map((dependency) => ( -
  • {dependency}
  • - ))} -
- ); - }, [app?.dependlist]); - - const renderInstallButton = useMemo(() => { - if (isInstalled) { - return ( - - ); - } - - if (isInstalling) { - return ( - - ); - } - return ( - - ); - }, [ - isCheckingInstall, - isInstalled, - isInstalling, - installProgress, - handleInstall, - ]); - - if (!app) { - return
No package information available
; - } - - if (isLoading) { - return ( -
- {Array.from({ length: 9 }, (_, i) => ( - - - - - - - - - - - - - ))} -
- ); - } - - const renderInstallationInstructions = () => { - const isOfficialRepo = - app.repository.includes("core") || - app.repository.includes("extra") || - app.repository.includes("local"); - const installCommand = `${isOfficialRepo ? "sudo pacman" : "yay"} -S ${ - app.name - }`; - - const uninstallCommand = `sudo pacman -Rdd ${app.name}`; - - return ( -
- - - {isOfficialRepo ? ( - pacman - ) : ( - <> - yay - paru - - )} - - {isOfficialRepo ? ( -
- -
-                  
-                    {app.repository.includes("local")
-                      ? uninstallCommand
-                      : installCommand}
-                  
-                
- -
-
- ) : ( -
- -
-                  {installCommand}
-                
- -
- -
-                  {`paru -S ${app.name}`}
-                
- -
- {/* - - - - - -

Install {app.name}

-
-
-
*/} -
- )} -
-
- ); - }; - - return ( - - -
-
- - {renderInstallButton} -
- {error && ( -
- Error: - {error} -
- )} - - -
-
- - {app.name || "N/A"} - - - {app.description || "No description available."} - -
- - {app.repository || "Unknown"} - -
-
- -
- {[ - { label: "Version", value: app.version }, - { label: "Maintainer", value: app.maintainer }, - { label: "Last Updated", value: app.lastupdated }, - { label: "Upstream URL", value: app.upstreamurl }, - ].map(({ label, value }) => ( -
-

{label}

-

{value || "N/A"}

-
- ))} -
-
-
- - - Details - - -

{app.description || "No description available."}

- -

Dependencies

- {renderDependencies} - -

Command

- {renderInstallationInstructions()} -
- -

- Please ensure your system meets the minimum requirements before - installation. -

-
-
-
-
-
- ); -}; - -interface CopyButtonProps { - command: string; - copiedCommand: string | null; - onCopy: (command: string) => void; -} - -const CopyButton: React.FC = ({ - command, - copiedCommand, - onCopy, -}) => ( - -); - -export default PackageDetails; diff --git a/frontend/src/components/Search.tsx b/frontend/src/components/Search.tsx deleted file mode 100644 index f1b9564..0000000 --- a/frontend/src/components/Search.tsx +++ /dev/null @@ -1,348 +0,0 @@ -import React, { useState, useCallback, useRef, useEffect } from "react"; -import { FixedSizeGrid as Grid } from "react-window"; -import AutoSizer from "react-virtualized-auto-sizer"; -import { Input } from "@/components/ui/input"; -import { Button } from "@/components/ui/button"; -import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@/components/ui/card"; -import { Badge } from "./ui/badge"; -import { SearchPackage, SearchLocalPackage } from "../../wailsjs/go/main/App"; -import { main } from "wailsjs/go/models"; -import PackageDetails from "./PackageDetails"; -import ErrorBoundary from "./ErrorBoundary"; -import { Skeleton } from "./ui/skeleton"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuTrigger, - DropdownMenuItem, - DropdownMenuSeparator, -} from "./ui/dropdown-menu"; -import { Checkbox } from "@/components/ui/checkbox"; - -const Search: React.FC = () => { - const [searchTerm, setSearchTerm] = useState(""); - const [searchResults, setSearchResults] = useState([]); - const [allResults, setAllResults] = useState([]); - const [isLoading, setIsLoading] = useState(false); - const [selectedApp, setSelectedApp] = useState(null); - const [error, setError] = useState(null); - const [installedApps, setInstalledApps] = useState>(new Set()); - const [activeFilters, setActiveFilters] = useState([]); - - const handleSearch = async (): Promise => { - if (!searchTerm.trim()) { - setError("Please enter a search term"); - return; - } - - setSearchResults([]); - setAllResults([]); - setSelectedApp(null); - setIsLoading(true); - setError(null); - - try { - const res = await SearchPackage( - searchTerm.toLowerCase().trim().replace(/\s+/g, "-") - ); - setAllResults(res); - - if (activeFilters.length > 0) { - const filtered = res.filter((pkg) => - activeFilters.includes(pkg.repository) - ); - setSearchResults(filtered); - if (filtered.length === 0) { - setError("No results found for selected filters!"); - } - } else { - setSearchResults(res); - } - - if (res.length === 0) { - setError("No results found"); - } else { - checkInstalledApps(res); - } - } catch (error) { - console.error("Error searching packages:", error); - setError("An error occurred while searching. Please try again."); - } finally { - setIsLoading(false); - } - }; - - const checkInstalledApps = useCallback(async (apps: main.PackageInfo[]) => { - const installedSet = new Set(); - for (const app of apps) { - try { - const isInstalled = await SearchLocalPackage(app.name); - if (isInstalled) { - installedSet.add(app.name); - } - } catch (error) { - console.error(`Error checking if ${app.name} is installed:`, error); - } - } - setInstalledApps(installedSet); - }, []); - - const handleKeyPress = (event: React.KeyboardEvent) => { - if (event.key === "Enter") { - handleSearch(); - } - }; - - const updateFilters = (filter: string, checked: boolean) => { - let newFilters: string[]; - - if (filter === "CLEAR_ALL") { - newFilters = []; - } else { - newFilters = checked - ? [...activeFilters, filter] - : activeFilters.filter((f) => f !== filter); - } - - setActiveFilters(newFilters); - - if (newFilters.length === 0) { - setSearchResults(allResults); - setError(null); - } else { - const filteredResults = allResults.filter((pkg) => - newFilters.includes(pkg.repository) - ); - - if (filteredResults.length === 0) { - setError("No results found for selected filters!"); - } else { - setError(null); - setSearchResults(filteredResults); - } - } - }; - - const handleInstallStateChange = useCallback(() => { - if (selectedApp) { - checkInstalledApps([selectedApp]); - } - }, [selectedApp, checkInstalledApps]); - - const CardItem = useCallback( - ({ - columnIndex, - rowIndex, - style, - }: { - columnIndex: number; - rowIndex: number; - style: React.CSSProperties; - }) => { - const index = rowIndex * 3 + columnIndex; - const result = searchResults[index]; - if (!result) return null; - - const isInstalled = installedApps.has(result.name); - - return ( -
- setSelectedApp({ ...result })} - > - -
- {result.name} - {isInstalled && ( - - Installed - - )} -
-
- - - {result.description && result.description.length > 70 - ? `${result.description.substring(0, 80)}...` - : result.description} - -

- Version: {result.version} -

-
- - - {result.repository} - - -
-
- ); - }, - [installedApps, searchResults] - ); - - const renderContent = () => { - if (isLoading) { - return ( -
- {Array.from({ length: 9 }, (_, i) => ( - - - - - - - - - - - - - ))} -
- ); - } - - if (error) { - return
{error}
; - } - - return ( -
- - {({ height, width }: { height: number; width: number }) => { - const columnCount = width >= 1024 ? 3 : width >= 768 ? 2 : 1; - const columnWidth = width / columnCount; - const rowCount = Math.ceil(searchResults.length / columnCount); - return ( - - {CardItem} - - ); - }} - -
- ); - }; - - return ( - -
- {selectedApp ? ( - setSelectedApp(null)} - onInstallStateChange={handleInstallStateChange} - /> - ) : ( - <> -

Search Packages

-
- ) => - setSearchTerm(e.target.value) - } - onKeyDown={handleKeyPress} - className="flex-grow" - /> - - -
- {renderContent()} - - )} -
-
- ); -}; - -type FilterDropdownProps = { - activeFilters: string[]; - onFilterChange: (filter: string, checked: boolean) => void; -}; - -const FilterDropdown: React.FC = ({ - activeFilters, - onFilterChange, -}) => { - const repositories = ["core", "extra", "AUR"]; - - return ( - - - - - - {repositories.map((repo) => ( - { - e.preventDefault(); - }} - className="flex items-center justify-between cursor-pointer" - > - - onFilterChange(repo, checked === true) - } - aria-label={`Filter by ${repo}`} - /> - {repo} - - ))} - {activeFilters.length > 0 && ( - <> - - { - activeFilters.forEach((filter) => - onFilterChange("CLEAR_ALL", false) - ); - }} - className="text-center text-xs cursor-pointer text-gray-500 hover:text-gray-700" - > - Clear all - - - )} - - - ); -}; - -export default Search; diff --git a/frontend/src/components/Updates.tsx b/frontend/src/components/Updates.tsx deleted file mode 100644 index 9448c68..0000000 --- a/frontend/src/components/Updates.tsx +++ /dev/null @@ -1,298 +0,0 @@ -import React, { useState, useEffect, useCallback, useMemo } from "react"; -import { FixedSizeGrid as Grid } from "react-window"; -import AutoSizer from "react-virtualized-auto-sizer"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@/components/ui/card"; -import { - GetAvailableUpdates, - HumanReadableSize, - UpdateAllPkg, - UpdateSinglePkg, -} from "../../wailsjs/go/main/App"; -import { main } from "wailsjs/go/models"; -import { Badge } from "./ui/badge"; -import { Skeleton } from "./ui/skeleton"; -import { ArrowUpCircle, AlertCircle } from "lucide-react"; -import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; - -const useAvailableUpdates = () => { - const [availableUpdates, setAvailableUpdates] = useState( - [] - ); - const [isLoading, setIsLoading] = useState(true); - const [error, setError] = useState(null); - const [totalDownloadSize, setTotalDownloadSize] = useState(""); - - const fetchAvailableUpdates = useCallback(async () => { - setIsLoading(true); - try { - const updates = await GetAvailableUpdates(); - setAvailableUpdates(updates); - const totalSize = updates.reduce( - (acc, update) => acc + update.downloadSize, - 0 - ); - const readableSize = await HumanReadableSize(totalSize); - setTotalDownloadSize(readableSize); - setError(null); - } catch (err) { - console.error("Error fetching available updates:", err); - setError("Failed to fetch available updates. Please try again."); - } finally { - setIsLoading(false); - } - }, []); - - useEffect(() => { - fetchAvailableUpdates(); - const intervalId = setInterval(fetchAvailableUpdates, 5000); - return () => clearInterval(intervalId); - }, [fetchAvailableUpdates]); - - return { - availableUpdates, - isLoading, - error, - totalDownloadSize, - fetchAvailableUpdates, - }; -}; - -const useReadableSizes = (availableUpdates: main.UpdateInfo[]) => { - const [readableSizes, setReadableSizes] = useState<{ [key: string]: string }>( - {} - ); - - useEffect(() => { - const fetchSizes = async () => { - const sizes: { [key: string]: string } = {}; - for (const update of availableUpdates) { - sizes[update.name] = await HumanReadableSize(update.downloadSize); - } - setReadableSizes(sizes); - }; - fetchSizes(); - }, [availableUpdates]); - - return readableSizes; -}; - -const Updates: React.FC = () => { - const { - availableUpdates, - isLoading, - error, - totalDownloadSize, - fetchAvailableUpdates, - } = useAvailableUpdates(); - const readableSizes = useReadableSizes(availableUpdates); - const [searchTerm, setSearchTerm] = useState(""); - const [updatingAll, setUpdatingAll] = useState(false); - const [updatingPackages, setUpdatingPackages] = useState>( - new Set() - ); - - const filteredUpdates = useMemo(() => { - return availableUpdates.filter((update) => - update.name.toLowerCase().includes(searchTerm.toLowerCase()) - ); - }, [availableUpdates, searchTerm]); - - const handleSinglePackageUpdate = async (pkg: string) => { - setUpdatingPackages((prev) => new Set(prev).add(pkg)); - try { - await UpdateSinglePkg(pkg); - } catch (err) { - console.error(`Error updating package ${pkg}:`, err); - } finally { - setUpdatingPackages((prev) => { - const newSet = new Set(prev); - newSet.delete(pkg); - return newSet; - }); - fetchAvailableUpdates(); - } - }; - - const handleAllPackageUpdate = async () => { - setUpdatingAll(true); - try { - await UpdateAllPkg(); - } catch (err) { - console.error("Error updating all packages:", err); - } finally { - setUpdatingAll(false); - fetchAvailableUpdates(); - } - }; - - const UpdateItem = useCallback( - ({ - columnIndex, - rowIndex, - style, - }: { - columnIndex: number; - rowIndex: number; - style: React.CSSProperties; - }) => { - const index = rowIndex * 3 + columnIndex; - const update = filteredUpdates[index]; - if (!update) return null; - const isUpdating = updatingPackages.has(update.name) || updatingAll; - return ( -
- - - {update.name} - - - - Update available: {update.oldVersion} → {update.newVersion} - -

- Repository: {update.repository} -

-
- - - {readableSizes[update.name] || "Calculating..."} - - - -
-
- ); - }, - [filteredUpdates, readableSizes, updatingPackages, updatingAll] - ); - - const renderContent = useMemo(() => { - if (isLoading && availableUpdates.length === 0) { - return ( -
- {Array.from({ length: 9 }, (_, i) => ( - - - - - - - - - - - - - - ))} -
- ); - } - - if (error) { - return ( - - - Error - {error} - - ); - } - - if (filteredUpdates.length === 0) { - return ( - - - No updates available - - - {searchTerm - ? "No packages match your search." - : "All packages are up to date!"} - - - ); - } - - return ( -
- - {({ height, width }: { height: number; width: number }) => { - const columnCount = width >= 1024 ? 3 : width >= 768 ? 2 : 1; - const columnWidth = width / columnCount; - const rowCount = Math.ceil(filteredUpdates.length / columnCount); - return ( - - {UpdateItem} - - ); - }} - -
- ); - }, [ - isLoading, - error, - filteredUpdates, - UpdateItem, - availableUpdates.length, - searchTerm, - ]); - - return ( -
-

Available Updates

-
- ) => - setSearchTerm(e.target.value) - } - className="flex-grow" - aria-label="Search available updates" - /> - -
- {totalDownloadSize && ( -

- Total download size: {totalDownloadSize} -

- )} - {renderContent} -
- ); -}; - -export default React.memo(Updates); diff --git a/frontend/src/components/ui/alert.tsx b/frontend/src/components/ui/alert.tsx deleted file mode 100644 index 5afd41d..0000000 --- a/frontend/src/components/ui/alert.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" - -import { cn } from "@/lib/utils" - -const alertVariants = cva( - "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7", - { - variants: { - variant: { - default: "bg-background text-foreground", - destructive: - "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", - }, - }, - defaultVariants: { - variant: "default", - }, - } -) - -const Alert = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes & VariantProps ->(({ className, variant, ...props }, ref) => ( -
-)) -Alert.displayName = "Alert" - -const AlertTitle = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -AlertTitle.displayName = "AlertTitle" - -const AlertDescription = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)) -AlertDescription.displayName = "AlertDescription" - -export { Alert, AlertTitle, AlertDescription } diff --git a/frontend/src/components/ui/badge.tsx b/frontend/src/components/ui/badge.tsx deleted file mode 100644 index f000e3e..0000000 --- a/frontend/src/components/ui/badge.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" - -import { cn } from "@/lib/utils" - -const badgeVariants = cva( - "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", - { - variants: { - variant: { - default: - "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", - secondary: - "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", - destructive: - "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", - outline: "text-foreground", - }, - }, - defaultVariants: { - variant: "default", - }, - } -) - -export interface BadgeProps - extends React.HTMLAttributes, - VariantProps {} - -function Badge({ className, variant, ...props }: BadgeProps) { - return ( -
- ) -} - -export { Badge, badgeVariants } diff --git a/frontend/src/components/ui/button.tsx b/frontend/src/components/ui/button.tsx deleted file mode 100644 index 0ba4277..0000000 --- a/frontend/src/components/ui/button.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { cva, type VariantProps } from "class-variance-authority" - -import { cn } from "@/lib/utils" - -const buttonVariants = cva( - "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", - { - variants: { - variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90", - destructive: - "bg-destructive text-destructive-foreground hover:bg-destructive/90", - outline: - "border border-input bg-background hover:bg-accent hover:text-accent-foreground", - secondary: - "bg-secondary text-secondary-foreground hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground", - link: "text-primary underline-offset-4 hover:underline", - }, - size: { - default: "h-10 px-4 py-2", - sm: "h-9 rounded-md px-3", - lg: "h-11 rounded-md px-8", - icon: "h-10 w-10", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - } -) - -export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { - asChild?: boolean -} - -const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button" - return ( - - ) - } -) -Button.displayName = "Button" - -export { Button, buttonVariants } diff --git a/frontend/src/components/ui/card.tsx b/frontend/src/components/ui/card.tsx deleted file mode 100644 index 4cb56a6..0000000 --- a/frontend/src/components/ui/card.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import * as React from "react"; - -import { cn } from "@/lib/utils"; - -const Card = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)); -Card.displayName = "Card"; - -const CardHeader = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)); -CardHeader.displayName = "CardHeader"; - -const CardTitle = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -

-)); -CardTitle.displayName = "CardTitle"; - -const CardDescription = React.forwardRef< - HTMLParagraphElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -

-)); -CardDescription.displayName = "CardDescription"; - -const CardContent = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -

-)); -CardContent.displayName = "CardContent"; - -const CardFooter = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)); -CardFooter.displayName = "CardFooter"; - -export { - Card, - CardHeader, - CardFooter, - CardTitle, - CardDescription, - CardContent, -}; diff --git a/frontend/src/components/ui/checkbox.tsx b/frontend/src/components/ui/checkbox.tsx deleted file mode 100644 index 8d02b28..0000000 --- a/frontend/src/components/ui/checkbox.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import * as React from "react" -import * as CheckboxPrimitive from "@radix-ui/react-checkbox" -import { cn } from "@/lib/utils" -import { CheckIcon } from "@radix-ui/react-icons" - -const Checkbox = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - - - -)) -Checkbox.displayName = CheckboxPrimitive.Root.displayName - -export { Checkbox } diff --git a/frontend/src/components/ui/circular-progress.tsx b/frontend/src/components/ui/circular-progress.tsx deleted file mode 100644 index f6f8e5e..0000000 --- a/frontend/src/components/ui/circular-progress.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { cn } from "@/lib/utils"; -import React from "react"; - -interface CircularProgressProps { - size?: number; - strokeWidth?: number; - percentage: number; -} - -const CircularProgress: React.FC = ({ - size = 24, - strokeWidth = 2, - percentage, -}) => { - const radius = (size - strokeWidth) / 2; - const circumference = radius * 2 * Math.PI; - const strokeDashoffset = circumference - (percentage / 100) * circumference; - - return ( - - - - - ); -}; - -export default CircularProgress; diff --git a/frontend/src/components/ui/dropdown-menu.tsx b/frontend/src/components/ui/dropdown-menu.tsx deleted file mode 100644 index d26ae38..0000000 --- a/frontend/src/components/ui/dropdown-menu.tsx +++ /dev/null @@ -1,198 +0,0 @@ -import * as React from "react" -import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" -import { cn } from "@/lib/utils" -import { CheckIcon, ChevronRightIcon, DotFilledIcon } from "@radix-ui/react-icons" - -const DropdownMenu = DropdownMenuPrimitive.Root - -const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger - -const DropdownMenuGroup = DropdownMenuPrimitive.Group - -const DropdownMenuPortal = DropdownMenuPrimitive.Portal - -const DropdownMenuSub = DropdownMenuPrimitive.Sub - -const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup - -const DropdownMenuSubTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, children, ...props }, ref) => ( - - {children} - - -)) -DropdownMenuSubTrigger.displayName = - DropdownMenuPrimitive.SubTrigger.displayName - -const DropdownMenuSubContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DropdownMenuSubContent.displayName = - DropdownMenuPrimitive.SubContent.displayName - -const DropdownMenuContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, sideOffset = 4, ...props }, ref) => ( - - - -)) -DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName - -const DropdownMenuItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, ...props }, ref) => ( - svg]:size-4 [&>svg]:shrink-0", - inset && "pl-8", - className - )} - {...props} - /> -)) -DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName - -const DropdownMenuCheckboxItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, checked, ...props }, ref) => ( - - - - - - - {children} - -)) -DropdownMenuCheckboxItem.displayName = - DropdownMenuPrimitive.CheckboxItem.displayName - -const DropdownMenuRadioItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - - - - - {children} - -)) -DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName - -const DropdownMenuLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, ...props }, ref) => ( - -)) -DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName - -const DropdownMenuSeparator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName - -const DropdownMenuShortcut = ({ - className, - ...props -}: React.HTMLAttributes) => { - return ( - - ) -} -DropdownMenuShortcut.displayName = "DropdownMenuShortcut" - -export { - DropdownMenu, - DropdownMenuTrigger, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuCheckboxItem, - DropdownMenuRadioItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuShortcut, - DropdownMenuGroup, - DropdownMenuPortal, - DropdownMenuSub, - DropdownMenuSubContent, - DropdownMenuSubTrigger, - DropdownMenuRadioGroup, -} diff --git a/frontend/src/components/ui/input.tsx b/frontend/src/components/ui/input.tsx deleted file mode 100644 index 677d05f..0000000 --- a/frontend/src/components/ui/input.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from "react" - -import { cn } from "@/lib/utils" - -export interface InputProps - extends React.InputHTMLAttributes {} - -const Input = React.forwardRef( - ({ className, type, ...props }, ref) => { - return ( - - ) - } -) -Input.displayName = "Input" - -export { Input } diff --git a/frontend/src/components/ui/label.tsx b/frontend/src/components/ui/label.tsx deleted file mode 100644 index 683faa7..0000000 --- a/frontend/src/components/ui/label.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import * as React from "react" -import * as LabelPrimitive from "@radix-ui/react-label" -import { cva, type VariantProps } from "class-variance-authority" - -import { cn } from "@/lib/utils" - -const labelVariants = cva( - "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" -) - -const Label = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & - VariantProps ->(({ className, ...props }, ref) => ( - -)) -Label.displayName = LabelPrimitive.Root.displayName - -export { Label } diff --git a/frontend/src/components/ui/progress.tsx b/frontend/src/components/ui/progress.tsx deleted file mode 100644 index 105fb65..0000000 --- a/frontend/src/components/ui/progress.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import * as React from "react" -import * as ProgressPrimitive from "@radix-ui/react-progress" - -import { cn } from "@/lib/utils" - -const Progress = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, value, ...props }, ref) => ( - - - -)) -Progress.displayName = ProgressPrimitive.Root.displayName - -export { Progress } diff --git a/frontend/src/components/ui/scroll-area.tsx b/frontend/src/components/ui/scroll-area.tsx deleted file mode 100644 index cf253cf..0000000 --- a/frontend/src/components/ui/scroll-area.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import * as React from "react" -import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" - -import { cn } from "@/lib/utils" - -const ScrollArea = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - {children} - - - - -)) -ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName - -const ScrollBar = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, orientation = "vertical", ...props }, ref) => ( - - - -)) -ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName - -export { ScrollArea, ScrollBar } diff --git a/frontend/src/components/ui/separator.tsx b/frontend/src/components/ui/separator.tsx deleted file mode 100644 index 6d7f122..0000000 --- a/frontend/src/components/ui/separator.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import * as React from "react" -import * as SeparatorPrimitive from "@radix-ui/react-separator" - -import { cn } from "@/lib/utils" - -const Separator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->( - ( - { className, orientation = "horizontal", decorative = true, ...props }, - ref - ) => ( - - ) -) -Separator.displayName = SeparatorPrimitive.Root.displayName - -export { Separator } diff --git a/frontend/src/components/ui/skeleton.tsx b/frontend/src/components/ui/skeleton.tsx deleted file mode 100644 index 01b8b6d..0000000 --- a/frontend/src/components/ui/skeleton.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { cn } from "@/lib/utils" - -function Skeleton({ - className, - ...props -}: React.HTMLAttributes) { - return ( -
- ) -} - -export { Skeleton } diff --git a/frontend/src/components/ui/tabs.tsx b/frontend/src/components/ui/tabs.tsx deleted file mode 100644 index 85d83be..0000000 --- a/frontend/src/components/ui/tabs.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import * as React from "react" -import * as TabsPrimitive from "@radix-ui/react-tabs" - -import { cn } from "@/lib/utils" - -const Tabs = TabsPrimitive.Root - -const TabsList = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -TabsList.displayName = TabsPrimitive.List.displayName - -const TabsTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -TabsTrigger.displayName = TabsPrimitive.Trigger.displayName - -const TabsContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -TabsContent.displayName = TabsPrimitive.Content.displayName - -export { Tabs, TabsList, TabsTrigger, TabsContent } diff --git a/frontend/src/components/ui/theme-provider.tsx b/frontend/src/components/ui/theme-provider.tsx deleted file mode 100644 index 7b9eeb2..0000000 --- a/frontend/src/components/ui/theme-provider.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { createContext, useContext, useEffect, useState } from "react"; - -type Theme = "dark" | "light" | "system"; - -type ThemeProviderProps = { - children: React.ReactNode; - defaultTheme?: Theme; - storageKey?: string; -}; - -type ThemeProviderState = { - theme: Theme; - setTheme: (theme: Theme) => void; -}; - -const initialState: ThemeProviderState = { - theme: "system", - setTheme: () => null, -}; - -const ThemeProviderContext = createContext(initialState); - -export function ThemeProvider({ - children, - defaultTheme = "system", - storageKey = "vite-ui-theme", - ...props -}: ThemeProviderProps) { - const [theme, setTheme] = useState( - () => (localStorage.getItem(storageKey) as Theme) || defaultTheme - ); - - useEffect(() => { - const root = window.document.documentElement; - - root.classList.remove("light", "dark"); - - if (theme === "system") { - const systemTheme = window.matchMedia("(prefers-color-scheme: dark)") - .matches - ? "dark" - : "light"; - - root.classList.add(systemTheme); - return; - } - - root.classList.add(theme); - }, [theme]); - - const value = { - theme, - setTheme: (theme: Theme) => { - localStorage.setItem(storageKey, theme); - setTheme(theme); - }, - }; - - return ( - - {children} - - ); -} - -export const useTheme = () => { - const context = useContext(ThemeProviderContext); - - if (context === undefined) - throw new Error("useTheme must be used within a ThemeProvider"); - - return context; -}; diff --git a/frontend/src/components/ui/toast.tsx b/frontend/src/components/ui/toast.tsx deleted file mode 100644 index a822477..0000000 --- a/frontend/src/components/ui/toast.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import * as React from "react" -import * as ToastPrimitives from "@radix-ui/react-toast" -import { cva, type VariantProps } from "class-variance-authority" -import { X } from "lucide-react" - -import { cn } from "@/lib/utils" - -const ToastProvider = ToastPrimitives.Provider - -const ToastViewport = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -ToastViewport.displayName = ToastPrimitives.Viewport.displayName - -const toastVariants = cva( - "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full", - { - variants: { - variant: { - default: "border bg-background text-foreground", - destructive: - "destructive group border-destructive bg-destructive text-destructive-foreground", - }, - }, - defaultVariants: { - variant: "default", - }, - } -) - -const Toast = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & - VariantProps ->(({ className, variant, ...props }, ref) => { - return ( - - ) -}) -Toast.displayName = ToastPrimitives.Root.displayName - -const ToastAction = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -ToastAction.displayName = ToastPrimitives.Action.displayName - -const ToastClose = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - -)) -ToastClose.displayName = ToastPrimitives.Close.displayName - -const ToastTitle = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -ToastTitle.displayName = ToastPrimitives.Title.displayName - -const ToastDescription = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -ToastDescription.displayName = ToastPrimitives.Description.displayName - -type ToastProps = React.ComponentPropsWithoutRef - -type ToastActionElement = React.ReactElement - -export { - type ToastProps, - type ToastActionElement, - ToastProvider, - ToastViewport, - Toast, - ToastTitle, - ToastDescription, - ToastClose, - ToastAction, -} diff --git a/frontend/src/components/ui/toaster.tsx b/frontend/src/components/ui/toaster.tsx deleted file mode 100644 index a2209ba..0000000 --- a/frontend/src/components/ui/toaster.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { - Toast, - ToastClose, - ToastDescription, - ToastProvider, - ToastTitle, - ToastViewport, -} from "@/components/ui/toast" -import { useToast } from "@/components/ui/use-toast" - -export function Toaster() { - const { toasts } = useToast() - - return ( - - {toasts.map(function ({ id, title, description, action, ...props }) { - return ( - -
- {title && {title}} - {description && ( - {description} - )} -
- {action} - -
- ) - })} - -
- ) -} diff --git a/frontend/src/components/ui/tooltip.tsx b/frontend/src/components/ui/tooltip.tsx deleted file mode 100644 index a9c71ba..0000000 --- a/frontend/src/components/ui/tooltip.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import * as React from "react" -import * as TooltipPrimitive from "@radix-ui/react-tooltip" - -import { cn } from "@/lib/utils" - -const TooltipProvider = TooltipPrimitive.Provider - -const Tooltip = TooltipPrimitive.Root - -const TooltipTrigger = TooltipPrimitive.Trigger - -const TooltipContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, sideOffset = 4, ...props }, ref) => ( - -)) -TooltipContent.displayName = TooltipPrimitive.Content.displayName - -export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } diff --git a/frontend/src/components/ui/use-toast.ts b/frontend/src/components/ui/use-toast.ts deleted file mode 100644 index 1671307..0000000 --- a/frontend/src/components/ui/use-toast.ts +++ /dev/null @@ -1,192 +0,0 @@ -// Inspired by react-hot-toast library -import * as React from "react" - -import type { - ToastActionElement, - ToastProps, -} from "@/components/ui/toast" - -const TOAST_LIMIT = 1 -const TOAST_REMOVE_DELAY = 1000000 - -type ToasterToast = ToastProps & { - id: string - title?: React.ReactNode - description?: React.ReactNode - action?: ToastActionElement -} - -const actionTypes = { - ADD_TOAST: "ADD_TOAST", - UPDATE_TOAST: "UPDATE_TOAST", - DISMISS_TOAST: "DISMISS_TOAST", - REMOVE_TOAST: "REMOVE_TOAST", -} as const - -let count = 0 - -function genId() { - count = (count + 1) % Number.MAX_SAFE_INTEGER - return count.toString() -} - -type ActionType = typeof actionTypes - -type Action = - | { - type: ActionType["ADD_TOAST"] - toast: ToasterToast - } - | { - type: ActionType["UPDATE_TOAST"] - toast: Partial - } - | { - type: ActionType["DISMISS_TOAST"] - toastId?: ToasterToast["id"] - } - | { - type: ActionType["REMOVE_TOAST"] - toastId?: ToasterToast["id"] - } - -interface State { - toasts: ToasterToast[] -} - -const toastTimeouts = new Map>() - -const addToRemoveQueue = (toastId: string) => { - if (toastTimeouts.has(toastId)) { - return - } - - const timeout = setTimeout(() => { - toastTimeouts.delete(toastId) - dispatch({ - type: "REMOVE_TOAST", - toastId: toastId, - }) - }, TOAST_REMOVE_DELAY) - - toastTimeouts.set(toastId, timeout) -} - -export const reducer = (state: State, action: Action): State => { - switch (action.type) { - case "ADD_TOAST": - return { - ...state, - toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), - } - - case "UPDATE_TOAST": - return { - ...state, - toasts: state.toasts.map((t) => - t.id === action.toast.id ? { ...t, ...action.toast } : t - ), - } - - case "DISMISS_TOAST": { - const { toastId } = action - - // ! Side effects ! - This could be extracted into a dismissToast() action, - // but I'll keep it here for simplicity - if (toastId) { - addToRemoveQueue(toastId) - } else { - state.toasts.forEach((toast) => { - addToRemoveQueue(toast.id) - }) - } - - return { - ...state, - toasts: state.toasts.map((t) => - t.id === toastId || toastId === undefined - ? { - ...t, - open: false, - } - : t - ), - } - } - case "REMOVE_TOAST": - if (action.toastId === undefined) { - return { - ...state, - toasts: [], - } - } - return { - ...state, - toasts: state.toasts.filter((t) => t.id !== action.toastId), - } - } -} - -const listeners: Array<(state: State) => void> = [] - -let memoryState: State = { toasts: [] } - -function dispatch(action: Action) { - memoryState = reducer(memoryState, action) - listeners.forEach((listener) => { - listener(memoryState) - }) -} - -type Toast = Omit - -function toast({ ...props }: Toast) { - const id = genId() - - const update = (props: ToasterToast) => - dispatch({ - type: "UPDATE_TOAST", - toast: { ...props, id }, - }) - const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id }) - - dispatch({ - type: "ADD_TOAST", - toast: { - ...props, - id, - open: true, - onOpenChange: (open) => { - if (!open) dismiss() - }, - }, - }) - - return { - id: id, - dismiss, - update, - } -} - -function useToast() { - const [state, setState] = React.useState(memoryState) - - React.useEffect(() => { - listeners.push(setState) - return () => { - const index = listeners.indexOf(setState) - if (index > -1) { - listeners.splice(index, 1) - } - } - }, [state]) - - return { - ...state, - toast, - dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }), - } -} - -export { useToast, toast } diff --git a/frontend/src/globals.css b/frontend/src/globals.css deleted file mode 100644 index 3a62e20..0000000 --- a/frontend/src/globals.css +++ /dev/null @@ -1,101 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -body { - font-family: "Geist Sans", sans-serif; -} - -@layer base { - :root { - --background: 0 0% 100%; - --foreground: 222.2 84% 4.9%; - - --card: 0 0% 100%; - --card-foreground: 222.2 84% 4.9%; - - --popover: 0 0% 100%; - --popover-foreground: 222.2 84% 4.9%; - - --primary: 222.2 47.4% 11.2%; - --primary-foreground: 210 40% 98%; - - --secondary: 210 40% 96.1%; - --secondary-foreground: 222.2 47.4% 11.2%; - - --muted: 210 40% 96.1%; - --muted-foreground: 215.4 16.3% 46.9%; - - --accent: 210 40% 96.1%; - --accent-foreground: 222.2 47.4% 11.2%; - - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 210 40% 98%; - - --border: 214.3 31.8% 91.4%; - --input: 214.3 31.8% 91.4%; - --ring: 222.2 84% 4.9%; - - --radius: 0.5rem; - - --chart-1: 12 76% 61%; - --chart-2: 173 58% 39%; - --chart-3: 197 37% 24%; - --chart-4: 43 74% 66%; - --chart-5: 27 87% 67%; - } - - .dark { - --background: 240 14.3% 3.5%; - --foreground: 210 40% 98%; - - --card: 240 14.3% 5.5%; - --card-foreground: 210 40% 98%; - - --popover: 222.2 84% 4.9%; - --popover-foreground: 210 40% 98%; - - --primary: 210 40% 98%; - --primary-foreground: 222.2 47.4% 11.2%; - - --secondary: 217.2 32.6% 17.5%; - --secondary-foreground: 210 40% 98%; - - --muted: 217.2 32.6% 17.5%; - --muted-foreground: 215 20.2% 65.1%; - - --accent: 217.2 32.6% 17.5%; - --accent-foreground: 210 40% 98%; - - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 210 40% 98%; - - --border: 217.2 32.6% 17.5%; - --input: 217.2 32.6% 17.5%; - --ring: 212.7 26.8% 83.9%; - - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; - } -} - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } -} - -html { - height: 100%; - overflow: hidden; -} - -.nodrag { - --wails-draggable: no-drag; -} diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts deleted file mode 100644 index ec79801..0000000 --- a/frontend/src/lib/utils.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { type ClassValue, clsx } from "clsx" -import { twMerge } from "tailwind-merge" - -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) -} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx deleted file mode 100644 index 277011d..0000000 --- a/frontend/src/main.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react' -import {createRoot} from 'react-dom/client' -import './globals.css' -import App from './App' - -const container = document.getElementById('root') - -const root = createRoot(container!) - -root.render( - - - -) diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe..0000000 --- a/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/frontend/tailwind.config.cjs b/frontend/tailwind.config.cjs deleted file mode 100644 index 36a84d5..0000000 --- a/frontend/tailwind.config.cjs +++ /dev/null @@ -1,77 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -module.exports = { - darkMode: ["class"], - content: [ - "./index.html", - './pages/**/*.{ts,tsx}', - './components/**/*.{ts,tsx}', - './app/**/*.{ts,tsx}', - './src/**/*.{ts,tsx}', - ], - theme: { - container: { - center: true, - padding: "2rem", - screens: { - "2xl": "1400px", - }, - }, - extend: { - colors: { - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", - primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", - }, - secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", - }, - destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", - }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, - accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", - }, - popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", - }, - card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", - }, - }, - borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", - }, - keyframes: { - "accordion-down": { - from: { height: 0 }, - to: { height: "var(--radix-accordion-content-height)" }, - }, - "accordion-up": { - from: { height: "var(--radix-accordion-content-height)" }, - to: { height: 0 }, - }, - }, - animation: { - "accordion-down": "accordion-down 0.2s ease-out", - "accordion-up": "accordion-up 0.2s ease-out", - }, - }, - }, - plugins: [require("tailwindcss-animate")], -} \ No newline at end of file diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json deleted file mode 100644 index ffd60f8..0000000 --- a/frontend/tsconfig.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@/*": [ - "./src/*" - ] - }, - "target": "ESNext", - "useDefineForClassFields": true, - "lib": [ - "DOM", - "DOM.Iterable", - "ESNext" - ], - "allowJs": false, - "skipLibCheck": true, - "esModuleInterop": false, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "module": "ESNext", - "moduleResolution": "Node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx" - }, - "include": [ - "src" - ], - "references": [ - { - "path": "./tsconfig.node.json" - } - ] -} diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json deleted file mode 100644 index b8afcc8..0000000 --- a/frontend/tsconfig.node.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "module": "ESNext", - "moduleResolution": "Node", - "allowSyntheticDefaultImports": true - }, - "include": [ - "vite.config.ts" - ] -} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts deleted file mode 100644 index d36c010..0000000 --- a/frontend/vite.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import path from "path" -import react from "@vitejs/plugin-react" -import { defineConfig } from "vite" - -export default defineConfig({ - plugins: [react()], - resolve: { - alias: { - "@": path.resolve(__dirname, "./src"), - }, - }, -}) \ No newline at end of file diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts deleted file mode 100755 index a58abf5..0000000 --- a/frontend/wailsjs/go/main/App.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT -import {main} from '../models'; - -export function CheckPackageInstalled(arg1:string):Promise; - -export function GetAvailableUpdates():Promise>; - -export function GetInstalledPackages():Promise>; - -export function GetMultiplePackageInfo(arg1:Array):Promise>; - -export function HumanReadableSize(arg1:number):Promise; - -export function Install(arg1:string):Promise; - -export function SearchLocalPackage(arg1:string):Promise; - -export function SearchPackage(arg1:string):Promise>; - -export function Uninstall(arg1:string):Promise; - -export function UpdateAllPkg():Promise; - -export function UpdateSinglePkg(arg1:string):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js deleted file mode 100755 index 65ab958..0000000 --- a/frontend/wailsjs/go/main/App.js +++ /dev/null @@ -1,47 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export function CheckPackageInstalled(arg1) { - return window['go']['main']['App']['CheckPackageInstalled'](arg1); -} - -export function GetAvailableUpdates() { - return window['go']['main']['App']['GetAvailableUpdates'](); -} - -export function GetInstalledPackages() { - return window['go']['main']['App']['GetInstalledPackages'](); -} - -export function GetMultiplePackageInfo(arg1) { - return window['go']['main']['App']['GetMultiplePackageInfo'](arg1); -} - -export function HumanReadableSize(arg1) { - return window['go']['main']['App']['HumanReadableSize'](arg1); -} - -export function Install(arg1) { - return window['go']['main']['App']['Install'](arg1); -} - -export function SearchLocalPackage(arg1) { - return window['go']['main']['App']['SearchLocalPackage'](arg1); -} - -export function SearchPackage(arg1) { - return window['go']['main']['App']['SearchPackage'](arg1); -} - -export function Uninstall(arg1) { - return window['go']['main']['App']['Uninstall'](arg1); -} - -export function UpdateAllPkg() { - return window['go']['main']['App']['UpdateAllPkg'](); -} - -export function UpdateSinglePkg(arg1) { - return window['go']['main']['App']['UpdateSinglePkg'](arg1); -} diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts deleted file mode 100755 index 4977036..0000000 --- a/frontend/wailsjs/go/models.ts +++ /dev/null @@ -1,51 +0,0 @@ -export namespace main { - - export class PackageInfo { - name: string; - version: string; - description: string; - repository: string; - maintainer: string; - upstreamurl: string; - dependlist: string[]; - lastupdated: string; - - static createFrom(source: any = {}) { - return new PackageInfo(source); - } - - constructor(source: any = {}) { - if ('string' === typeof source) source = JSON.parse(source); - this.name = source["name"]; - this.version = source["version"]; - this.description = source["description"]; - this.repository = source["repository"]; - this.maintainer = source["maintainer"]; - this.upstreamurl = source["upstreamurl"]; - this.dependlist = source["dependlist"]; - this.lastupdated = source["lastupdated"]; - } - } - export class UpdateInfo { - name: string; - oldVersion: string; - newVersion: string; - repository: string; - downloadSize: number; - - static createFrom(source: any = {}) { - return new UpdateInfo(source); - } - - constructor(source: any = {}) { - if ('string' === typeof source) source = JSON.parse(source); - this.name = source["name"]; - this.oldVersion = source["oldVersion"]; - this.newVersion = source["newVersion"]; - this.repository = source["repository"]; - this.downloadSize = source["downloadSize"]; - } - } - -} - diff --git a/frontend/wailsjs/runtime/package.json b/frontend/wailsjs/runtime/package.json deleted file mode 100644 index 1e7c8a5..0000000 --- a/frontend/wailsjs/runtime/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@wailsapp/runtime", - "version": "2.0.0", - "description": "Wails Javascript runtime library", - "main": "runtime.js", - "types": "runtime.d.ts", - "scripts": { - }, - "repository": { - "type": "git", - "url": "git+https://github.com/wailsapp/wails.git" - }, - "keywords": [ - "Wails", - "Javascript", - "Go" - ], - "author": "Lea Anthony ", - "license": "MIT", - "bugs": { - "url": "https://github.com/wailsapp/wails/issues" - }, - "homepage": "https://github.com/wailsapp/wails#readme" -} diff --git a/frontend/wailsjs/runtime/runtime.d.ts b/frontend/wailsjs/runtime/runtime.d.ts deleted file mode 100644 index 94778df..0000000 --- a/frontend/wailsjs/runtime/runtime.d.ts +++ /dev/null @@ -1,249 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -export interface Position { - x: number; - y: number; -} - -export interface Size { - w: number; - h: number; -} - -export interface Screen { - isCurrent: boolean; - isPrimary: boolean; - width : number - height : number -} - -// Environment information such as platform, buildtype, ... -export interface EnvironmentInfo { - buildType: string; - platform: string; - arch: string; -} - -// [EventsEmit](https://wails.io/docs/reference/runtime/events#eventsemit) -// emits the given event. Optional data may be passed with the event. -// This will trigger any event listeners. -export function EventsEmit(eventName: string, ...data: any): void; - -// [EventsOn](https://wails.io/docs/reference/runtime/events#eventson) sets up a listener for the given event name. -export function EventsOn(eventName: string, callback: (...data: any) => void): () => void; - -// [EventsOnMultiple](https://wails.io/docs/reference/runtime/events#eventsonmultiple) -// sets up a listener for the given event name, but will only trigger a given number times. -export function EventsOnMultiple(eventName: string, callback: (...data: any) => void, maxCallbacks: number): () => void; - -// [EventsOnce](https://wails.io/docs/reference/runtime/events#eventsonce) -// sets up a listener for the given event name, but will only trigger once. -export function EventsOnce(eventName: string, callback: (...data: any) => void): () => void; - -// [EventsOff](https://wails.io/docs/reference/runtime/events#eventsoff) -// unregisters the listener for the given event name. -export function EventsOff(eventName: string, ...additionalEventNames: string[]): void; - -// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) -// unregisters all listeners. -export function EventsOffAll(): void; - -// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) -// logs the given message as a raw message -export function LogPrint(message: string): void; - -// [LogTrace](https://wails.io/docs/reference/runtime/log#logtrace) -// logs the given message at the `trace` log level. -export function LogTrace(message: string): void; - -// [LogDebug](https://wails.io/docs/reference/runtime/log#logdebug) -// logs the given message at the `debug` log level. -export function LogDebug(message: string): void; - -// [LogError](https://wails.io/docs/reference/runtime/log#logerror) -// logs the given message at the `error` log level. -export function LogError(message: string): void; - -// [LogFatal](https://wails.io/docs/reference/runtime/log#logfatal) -// logs the given message at the `fatal` log level. -// The application will quit after calling this method. -export function LogFatal(message: string): void; - -// [LogInfo](https://wails.io/docs/reference/runtime/log#loginfo) -// logs the given message at the `info` log level. -export function LogInfo(message: string): void; - -// [LogWarning](https://wails.io/docs/reference/runtime/log#logwarning) -// logs the given message at the `warning` log level. -export function LogWarning(message: string): void; - -// [WindowReload](https://wails.io/docs/reference/runtime/window#windowreload) -// Forces a reload by the main application as well as connected browsers. -export function WindowReload(): void; - -// [WindowReloadApp](https://wails.io/docs/reference/runtime/window#windowreloadapp) -// Reloads the application frontend. -export function WindowReloadApp(): void; - -// [WindowSetAlwaysOnTop](https://wails.io/docs/reference/runtime/window#windowsetalwaysontop) -// Sets the window AlwaysOnTop or not on top. -export function WindowSetAlwaysOnTop(b: boolean): void; - -// [WindowSetSystemDefaultTheme](https://wails.io/docs/next/reference/runtime/window#windowsetsystemdefaulttheme) -// *Windows only* -// Sets window theme to system default (dark/light). -export function WindowSetSystemDefaultTheme(): void; - -// [WindowSetLightTheme](https://wails.io/docs/next/reference/runtime/window#windowsetlighttheme) -// *Windows only* -// Sets window to light theme. -export function WindowSetLightTheme(): void; - -// [WindowSetDarkTheme](https://wails.io/docs/next/reference/runtime/window#windowsetdarktheme) -// *Windows only* -// Sets window to dark theme. -export function WindowSetDarkTheme(): void; - -// [WindowCenter](https://wails.io/docs/reference/runtime/window#windowcenter) -// Centers the window on the monitor the window is currently on. -export function WindowCenter(): void; - -// [WindowSetTitle](https://wails.io/docs/reference/runtime/window#windowsettitle) -// Sets the text in the window title bar. -export function WindowSetTitle(title: string): void; - -// [WindowFullscreen](https://wails.io/docs/reference/runtime/window#windowfullscreen) -// Makes the window full screen. -export function WindowFullscreen(): void; - -// [WindowUnfullscreen](https://wails.io/docs/reference/runtime/window#windowunfullscreen) -// Restores the previous window dimensions and position prior to full screen. -export function WindowUnfullscreen(): void; - -// [WindowIsFullscreen](https://wails.io/docs/reference/runtime/window#windowisfullscreen) -// Returns the state of the window, i.e. whether the window is in full screen mode or not. -export function WindowIsFullscreen(): Promise; - -// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) -// Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; - -// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) -// Gets the width and height of the window. -export function WindowGetSize(): Promise; - -// [WindowSetMaxSize](https://wails.io/docs/reference/runtime/window#windowsetmaxsize) -// Sets the maximum window size. Will resize the window if the window is currently larger than the given dimensions. -// Setting a size of 0,0 will disable this constraint. -export function WindowSetMaxSize(width: number, height: number): void; - -// [WindowSetMinSize](https://wails.io/docs/reference/runtime/window#windowsetminsize) -// Sets the minimum window size. Will resize the window if the window is currently smaller than the given dimensions. -// Setting a size of 0,0 will disable this constraint. -export function WindowSetMinSize(width: number, height: number): void; - -// [WindowSetPosition](https://wails.io/docs/reference/runtime/window#windowsetposition) -// Sets the window position relative to the monitor the window is currently on. -export function WindowSetPosition(x: number, y: number): void; - -// [WindowGetPosition](https://wails.io/docs/reference/runtime/window#windowgetposition) -// Gets the window position relative to the monitor the window is currently on. -export function WindowGetPosition(): Promise; - -// [WindowHide](https://wails.io/docs/reference/runtime/window#windowhide) -// Hides the window. -export function WindowHide(): void; - -// [WindowShow](https://wails.io/docs/reference/runtime/window#windowshow) -// Shows the window, if it is currently hidden. -export function WindowShow(): void; - -// [WindowMaximise](https://wails.io/docs/reference/runtime/window#windowmaximise) -// Maximises the window to fill the screen. -export function WindowMaximise(): void; - -// [WindowToggleMaximise](https://wails.io/docs/reference/runtime/window#windowtogglemaximise) -// Toggles between Maximised and UnMaximised. -export function WindowToggleMaximise(): void; - -// [WindowUnmaximise](https://wails.io/docs/reference/runtime/window#windowunmaximise) -// Restores the window to the dimensions and position prior to maximising. -export function WindowUnmaximise(): void; - -// [WindowIsMaximised](https://wails.io/docs/reference/runtime/window#windowismaximised) -// Returns the state of the window, i.e. whether the window is maximised or not. -export function WindowIsMaximised(): Promise; - -// [WindowMinimise](https://wails.io/docs/reference/runtime/window#windowminimise) -// Minimises the window. -export function WindowMinimise(): void; - -// [WindowUnminimise](https://wails.io/docs/reference/runtime/window#windowunminimise) -// Restores the window to the dimensions and position prior to minimising. -export function WindowUnminimise(): void; - -// [WindowIsMinimised](https://wails.io/docs/reference/runtime/window#windowisminimised) -// Returns the state of the window, i.e. whether the window is minimised or not. -export function WindowIsMinimised(): Promise; - -// [WindowIsNormal](https://wails.io/docs/reference/runtime/window#windowisnormal) -// Returns the state of the window, i.e. whether the window is normal or not. -export function WindowIsNormal(): Promise; - -// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour) -// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels. -export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void; - -// [ScreenGetAll](https://wails.io/docs/reference/runtime/window#screengetall) -// Gets the all screens. Call this anew each time you want to refresh data from the underlying windowing system. -export function ScreenGetAll(): Promise; - -// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl) -// Opens the given URL in the system browser. -export function BrowserOpenURL(url: string): void; - -// [Environment](https://wails.io/docs/reference/runtime/intro#environment) -// Returns information about the environment -export function Environment(): Promise; - -// [Quit](https://wails.io/docs/reference/runtime/intro#quit) -// Quits the application. -export function Quit(): void; - -// [Hide](https://wails.io/docs/reference/runtime/intro#hide) -// Hides the application. -export function Hide(): void; - -// [Show](https://wails.io/docs/reference/runtime/intro#show) -// Shows the application. -export function Show(): void; - -// [ClipboardGetText](https://wails.io/docs/reference/runtime/clipboard#clipboardgettext) -// Returns the current text stored on clipboard -export function ClipboardGetText(): Promise; - -// [ClipboardSetText](https://wails.io/docs/reference/runtime/clipboard#clipboardsettext) -// Sets a text on the clipboard -export function ClipboardSetText(text: string): Promise; - -// [OnFileDrop](https://wails.io/docs/reference/runtime/draganddrop#onfiledrop) -// OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings. -export function OnFileDrop(callback: (x: number, y: number ,paths: string[]) => void, useDropTarget: boolean) :void - -// [OnFileDropOff](https://wails.io/docs/reference/runtime/draganddrop#dragandddropoff) -// OnFileDropOff removes the drag and drop listeners and handlers. -export function OnFileDropOff() :void - -// Check if the file path resolver is available -export function CanResolveFilePaths(): boolean; - -// Resolves file paths for an array of files -export function ResolveFilePaths(files: File[]): void \ No newline at end of file diff --git a/frontend/wailsjs/runtime/runtime.js b/frontend/wailsjs/runtime/runtime.js deleted file mode 100644 index 623397b..0000000 --- a/frontend/wailsjs/runtime/runtime.js +++ /dev/null @@ -1,238 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -export function LogPrint(message) { - window.runtime.LogPrint(message); -} - -export function LogTrace(message) { - window.runtime.LogTrace(message); -} - -export function LogDebug(message) { - window.runtime.LogDebug(message); -} - -export function LogInfo(message) { - window.runtime.LogInfo(message); -} - -export function LogWarning(message) { - window.runtime.LogWarning(message); -} - -export function LogError(message) { - window.runtime.LogError(message); -} - -export function LogFatal(message) { - window.runtime.LogFatal(message); -} - -export function EventsOnMultiple(eventName, callback, maxCallbacks) { - return window.runtime.EventsOnMultiple(eventName, callback, maxCallbacks); -} - -export function EventsOn(eventName, callback) { - return EventsOnMultiple(eventName, callback, -1); -} - -export function EventsOff(eventName, ...additionalEventNames) { - return window.runtime.EventsOff(eventName, ...additionalEventNames); -} - -export function EventsOnce(eventName, callback) { - return EventsOnMultiple(eventName, callback, 1); -} - -export function EventsEmit(eventName) { - let args = [eventName].slice.call(arguments); - return window.runtime.EventsEmit.apply(null, args); -} - -export function WindowReload() { - window.runtime.WindowReload(); -} - -export function WindowReloadApp() { - window.runtime.WindowReloadApp(); -} - -export function WindowSetAlwaysOnTop(b) { - window.runtime.WindowSetAlwaysOnTop(b); -} - -export function WindowSetSystemDefaultTheme() { - window.runtime.WindowSetSystemDefaultTheme(); -} - -export function WindowSetLightTheme() { - window.runtime.WindowSetLightTheme(); -} - -export function WindowSetDarkTheme() { - window.runtime.WindowSetDarkTheme(); -} - -export function WindowCenter() { - window.runtime.WindowCenter(); -} - -export function WindowSetTitle(title) { - window.runtime.WindowSetTitle(title); -} - -export function WindowFullscreen() { - window.runtime.WindowFullscreen(); -} - -export function WindowUnfullscreen() { - window.runtime.WindowUnfullscreen(); -} - -export function WindowIsFullscreen() { - return window.runtime.WindowIsFullscreen(); -} - -export function WindowGetSize() { - return window.runtime.WindowGetSize(); -} - -export function WindowSetSize(width, height) { - window.runtime.WindowSetSize(width, height); -} - -export function WindowSetMaxSize(width, height) { - window.runtime.WindowSetMaxSize(width, height); -} - -export function WindowSetMinSize(width, height) { - window.runtime.WindowSetMinSize(width, height); -} - -export function WindowSetPosition(x, y) { - window.runtime.WindowSetPosition(x, y); -} - -export function WindowGetPosition() { - return window.runtime.WindowGetPosition(); -} - -export function WindowHide() { - window.runtime.WindowHide(); -} - -export function WindowShow() { - window.runtime.WindowShow(); -} - -export function WindowMaximise() { - window.runtime.WindowMaximise(); -} - -export function WindowToggleMaximise() { - window.runtime.WindowToggleMaximise(); -} - -export function WindowUnmaximise() { - window.runtime.WindowUnmaximise(); -} - -export function WindowIsMaximised() { - return window.runtime.WindowIsMaximised(); -} - -export function WindowMinimise() { - window.runtime.WindowMinimise(); -} - -export function WindowUnminimise() { - window.runtime.WindowUnminimise(); -} - -export function WindowSetBackgroundColour(R, G, B, A) { - window.runtime.WindowSetBackgroundColour(R, G, B, A); -} - -export function ScreenGetAll() { - return window.runtime.ScreenGetAll(); -} - -export function WindowIsMinimised() { - return window.runtime.WindowIsMinimised(); -} - -export function WindowIsNormal() { - return window.runtime.WindowIsNormal(); -} - -export function BrowserOpenURL(url) { - window.runtime.BrowserOpenURL(url); -} - -export function Environment() { - return window.runtime.Environment(); -} - -export function Quit() { - window.runtime.Quit(); -} - -export function Hide() { - window.runtime.Hide(); -} - -export function Show() { - window.runtime.Show(); -} - -export function ClipboardGetText() { - return window.runtime.ClipboardGetText(); -} - -export function ClipboardSetText(text) { - return window.runtime.ClipboardSetText(text); -} - -/** - * Callback for OnFileDrop returns a slice of file path strings when a drop is finished. - * - * @export - * @callback OnFileDropCallback - * @param {number} x - x coordinate of the drop - * @param {number} y - y coordinate of the drop - * @param {string[]} paths - A list of file paths. - */ - -/** - * OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings. - * - * @export - * @param {OnFileDropCallback} callback - Callback for OnFileDrop returns a slice of file path strings when a drop is finished. - * @param {boolean} [useDropTarget=true] - Only call the callback when the drop finished on an element that has the drop target style. (--wails-drop-target) - */ -export function OnFileDrop(callback, useDropTarget) { - return window.runtime.OnFileDrop(callback, useDropTarget); -} - -/** - * OnFileDropOff removes the drag and drop listeners and handlers. - */ -export function OnFileDropOff() { - return window.runtime.OnFileDropOff(); -} - -export function CanResolveFilePaths() { - return window.runtime.CanResolveFilePaths(); -} - -export function ResolveFilePaths(files) { - return window.runtime.ResolveFilePaths(files); -} \ No newline at end of file diff --git a/src/core/aur_helper.cpp b/src/core/aur_helper.cpp new file mode 100644 index 0000000..bdce2a3 --- /dev/null +++ b/src/core/aur_helper.cpp @@ -0,0 +1,206 @@ +#include "aur_helper.h" +#include "../utils/logger.h" +#include +#include +#include +#include +#include +#include +#include +#include + +AurHelper::AurHelper(QObject* parent) + : QObject(parent) + , m_networkManager(std::make_unique(this)) { +} + +AurHelper::~AurHelper() = default; + +void AurHelper::searchPackages(const QString& query) { + Logger::debug(QString("Searching AUR for: %1").arg(query)); + + QUrl url("https://aur.archlinux.org/rpc/"); + QUrlQuery urlQuery; + urlQuery.addQueryItem("v", "5"); + urlQuery.addQueryItem("type", "search"); + urlQuery.addQueryItem("arg", query); + url.setQuery(urlQuery); + + QNetworkRequest request(url); + auto* reply = m_networkManager->get(request); + + connect(reply, &QNetworkReply::finished, this, &AurHelper::onSearchFinished); +} + +void AurHelper::onSearchFinished() { + auto* reply = qobject_cast(sender()); + if (!reply) return; + + reply->deleteLater(); + + if (reply->error() != QNetworkReply::NoError) { + Logger::error(QString("AUR search error: %1").arg(reply->errorString())); + emit error(reply->errorString()); + return; + } + + QByteArray data = reply->readAll(); + QJsonDocument doc = QJsonDocument::fromJson(data); + + if (!doc.isObject()) { + Logger::error("Invalid AUR response format"); + emit error("Invalid response from AUR"); + return; + } + + QJsonObject root = doc.object(); + QJsonArray results = root["results"].toArray(); + + QVector packages; + for (const auto& result : results) { + packages.push_back(parseAurPackage(result.toObject())); + } + + Logger::info(QString("Found %1 AUR packages").arg(packages.size())); + emit searchCompleted(packages); +} + +void AurHelper::getPackageInfo(const QString& packageName) { + Logger::debug(QString("Getting AUR package info for: %1").arg(packageName)); + + QUrl url("https://aur.archlinux.org/rpc/"); + QUrlQuery urlQuery; + urlQuery.addQueryItem("v", "5"); + urlQuery.addQueryItem("type", "info"); + urlQuery.addQueryItem("arg", packageName); + url.setQuery(urlQuery); + + QNetworkRequest request(url); + auto* reply = m_networkManager->get(request); + + connect(reply, &QNetworkReply::finished, this, &AurHelper::onPackageInfoFinished); +} + +void AurHelper::onPackageInfoFinished() { + auto* reply = qobject_cast(sender()); + if (!reply) return; + + reply->deleteLater(); + + if (reply->error() != QNetworkReply::NoError) { + Logger::error(QString("AUR package info error: %1").arg(reply->errorString())); + emit error(reply->errorString()); + return; + } + + QByteArray data = reply->readAll(); + QJsonDocument doc = QJsonDocument::fromJson(data); + + if (!doc.isObject()) { + emit error("Invalid response from AUR"); + return; + } + + QJsonObject root = doc.object(); + QJsonArray results = root["results"].toArray(); + + if (results.isEmpty()) { + emit error("Package not found in AUR"); + return; + } + + PackageInfo info = parseAurPackage(results[0].toObject()); + emit packageInfoReceived(info); +} + +PackageInfo AurHelper::parseAurPackage(const QJsonObject& obj) { + PackageInfo info; + info.name = obj["Name"].toString(); + info.version = obj["Version"].toString(); + info.description = obj["Description"].toString(); + info.repository = "AUR"; + info.maintainer = obj["Maintainer"].toString(); + info.upstreamUrl = obj["URL"].toString(); + + qint64 lastModified = obj["LastModified"].toInteger(); + info.lastUpdated = QDateTime::fromSecsSinceEpoch(lastModified); + + // Parse dependencies + QJsonArray depends = obj["Depends"].toArray(); + for (const auto& dep : depends) { + info.dependList.append(dep.toString()); + } + + // Also add make dependencies if available + QJsonArray makeDepends = obj["MakeDepends"].toArray(); + for (const auto& dep : makeDepends) { + QString depStr = dep.toString() + " (make)"; + info.dependList.append(depStr); + } + + return info; +} + +QVector AurHelper::checkAurUpdates() { + QVector updates; + + // Get list of foreign (AUR) packages + QProcess process; + process.start("pacman", QStringList() << "-Qm"); + process.waitForFinished(); + + if (process.exitCode() != 0) { + Logger::warning("Failed to get list of foreign packages"); + return updates; + } + + QString output = process.readAllStandardOutput(); + QStringList lines = output.split('\n', Qt::SkipEmptyParts); + + for (const auto& line : lines) { + QStringList parts = line.split(' ', Qt::SkipEmptyParts); + if (parts.size() < 2) continue; + + QString name = parts[0]; + QString version = parts[1]; + + // Query AUR for latest version + QUrl url("https://aur.archlinux.org/rpc/"); + QUrlQuery urlQuery; + urlQuery.addQueryItem("v", "5"); + urlQuery.addQueryItem("type", "info"); + urlQuery.addQueryItem("arg", name); + url.setQuery(urlQuery); + + QNetworkRequest request(url); + auto reply = m_networkManager->get(request); + + QEventLoop loop; + connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + loop.exec(); + + if (reply->error() == QNetworkReply::NoError) { + QByteArray data = reply->readAll(); + QJsonDocument doc = QJsonDocument::fromJson(data); + QJsonObject root = doc.object(); + QJsonArray results = root["results"].toArray(); + + if (!results.isEmpty()) { + QString newVersion = results[0].toObject()["Version"].toString(); + if (newVersion != version) { + UpdateInfo update; + update.name = name; + update.oldVersion = version; + update.newVersion = newVersion; + update.repository = "AUR"; + update.downloadSize = 0; + updates.push_back(std::move(update)); + } + } + } + + reply->deleteLater(); + } + + return updates; +} diff --git a/src/core/aur_helper.h b/src/core/aur_helper.h new file mode 100644 index 0000000..a78bb13 --- /dev/null +++ b/src/core/aur_helper.h @@ -0,0 +1,38 @@ +#ifndef AUR_HELPER_H +#define AUR_HELPER_H + +#include +#include +#include +#include +#include +#include +#include "../utils/types.h" + +class AurHelper : public QObject { + Q_OBJECT + +public: + explicit AurHelper(QObject* parent = nullptr); + ~AurHelper() override; + + void searchPackages(const QString& query); + void getPackageInfo(const QString& packageName); + QVector checkAurUpdates(); + +signals: + void searchCompleted(const QVector& results); + void packageInfoReceived(const PackageInfo& info); + void error(const QString& message); + +private slots: + void onSearchFinished(); + void onPackageInfoFinished(); + +private: + std::unique_ptr m_networkManager; + + PackageInfo parseAurPackage(const QJsonObject& obj); +}; + +#endif // AUR_HELPER_H From 9bdf29c5f7eebe030d2551579581469094bbfc4e Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:19:51 +0000 Subject: [PATCH 12/71] remove go files --- GetPackage/get.go | 184 ------------- app.go | 647 ---------------------------------------------- go.mod | 41 --- go.sum | 98 ------- main.go | 96 ------- 5 files changed, 1066 deletions(-) delete mode 100644 GetPackage/get.go delete mode 100644 app.go delete mode 100644 go.mod delete mode 100644 go.sum delete mode 100644 main.go diff --git a/GetPackage/get.go b/GetPackage/get.go deleted file mode 100644 index 96ba5f5..0000000 --- a/GetPackage/get.go +++ /dev/null @@ -1,184 +0,0 @@ -package getpackage - -import ( - "encoding/json" - "fmt" - "os" - "os/exec" - "strings" - "sync" - "time" - - "github.com/Jguer/go-alpm/v2" -) - -type PackageInfo struct { - Name string `json:"name"` - Version string `json:"version"` - Description string `json:"description"` - Repository string `json:"repository"` - Maintainer string `json:"maintainer"` - UpstreamURL string `json:"upstreamurl"` - DependList []string `json:"dependlist"` - LastUpdated string `json:"lastupdated"` -} - -func SavePackageInfoToFile(pkgName, fileName string) error { - pkgs := SearchPackage(pkgName) - if len(pkgs) == 0 { - return fmt.Errorf("package %s not found", pkgName) - } - - // Assume the first result is the most relevant one - pkgInfo := pkgs - - file, err := os.Create(fileName) - if err != nil { - return fmt.Errorf("failed to create file: %w", err) - } - defer file.Close() - - encoder := json.NewEncoder(file) - encoder.SetIndent("", " ") - err = encoder.Encode(pkgInfo) - if err != nil { - return fmt.Errorf("failed to encode package info to JSON: %w", err) - } - - fmt.Printf("Package information for %s saved to %s\n", pkgName, fileName) - return nil -} - -func SearchPackage(query string) []PackageInfo { - var h *alpm.Handle - - // var dbs []alpm.IDB - var dbs []alpm.IDB - var err error - h, err = alpm.Initialize("/", "/var/lib/pacman") - if err != nil { - fmt.Fprintf(os.Stderr, "failed to initialize alpm: %v\n", err) - os.Exit(1) - } - - // Register and sync repositories - repos := []string{"core", "extra"} - for _, repo := range repos { - db, err := h.RegisterSyncDB(repo, 0) - if err != nil { - fmt.Printf("Error getting sync db for %s: %v\n", repo, err) - } - dbs = append(dbs, db) - } - var results []PackageInfo - var wg sync.WaitGroup - resultChan := make(chan PackageInfo, 100) - doneChan := make(chan bool) - - // Start a goroutine to collect results - go func() { - for pkg := range resultChan { - results = append(results, pkg) - } - doneChan <- true - }() - - // Search official repositories concurrently - for _, db := range dbs { - wg.Add(1) - go func(db alpm.IDB) { - defer wg.Done() - searchDB(db, query, resultChan) - }(db) - } - - // Search AUR concurrently - wg.Add(1) - go func() { - defer wg.Done() - searchAUR(query, resultChan) - }() - - // Wait for all searches to complete - wg.Wait() - close(resultChan) - - // Wait for result collection to finish - <-doneChan - - return results -} - -func searchDB(db alpm.IDB, query string, resultChan chan<- PackageInfo) { - db.PkgCache().ForEach(func(pkg alpm.IPackage) error { - if strings.Contains(strings.ToLower(pkg.Name()), strings.ToLower(query)) { - lastUpdated := pkg.BuildDate().UTC().Format("Jan. 2, 2006, 3 p.m. MST") - resultChan <- PackageInfo{ - Name: pkg.Name(), - Version: pkg.Version(), - Description: pkg.Description(), - Repository: db.Name(), - Maintainer: pkg.Packager(), - UpstreamURL: pkg.URL(), - DependList: convertDependList(pkg.Depends()), - LastUpdated: lastUpdated, - } - } - return nil - }) -} - -func searchAUR(query string, resultChan chan<- PackageInfo) { - cmd := exec.Command("curl", "-s", fmt.Sprintf("https://aur.archlinux.org/rpc/?v=5&type=search&arg=%s", query)) - output, err := cmd.Output() - if err != nil { - fmt.Printf("Error searching AUR: %v\n", err) - return - } - - var aurResponse struct { - Results []struct { - Name string `json:"Name"` - Version string `json:"Version"` - Description string `json:"Description"` - Maintainer string `json:"Maintainer"` - URL string `json:"URL"` - LastModified int64 `json:"LastModified"` - } `json:"results"` - } - err = json.Unmarshal(output, &aurResponse) - if err != nil { - fmt.Printf("Error parsing AUR response: %v\n", err) - return - } - - for _, aurPkg := range aurResponse.Results { - lastUpdated := time.Unix(aurPkg.LastModified, 0).UTC().Format("02-01-2006") - resultChan <- PackageInfo{ - Name: aurPkg.Name, - Version: aurPkg.Version, - Description: aurPkg.Description, - Repository: "AUR", - Maintainer: aurPkg.Maintainer, - UpstreamURL: aurPkg.URL, - DependList: nil, - LastUpdated: lastUpdated, - } - } -} - -func convertDependList(depList alpm.IDependList) []string { - var deps []string - depList.ForEach(func(dep *alpm.Depend) error { - deps = append(deps, dep.Name) - return nil - }) - return deps -} - -func main() { - err := SavePackageInfoToFile("google-chrome", "package-info.json") - if err != nil { - fmt.Println("Error:", err) - } -} diff --git a/app.go b/app.go deleted file mode 100644 index 64edd00..0000000 --- a/app.go +++ /dev/null @@ -1,647 +0,0 @@ -package main - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "log" - "os" - "sort" - "strings" - "sync" - "time" - - "os/exec" - - "github.com/Jguer/go-alpm/v2" - paconf "github.com/Morganamilo/go-pacmanconf" -) - -var h *alpm.Handle - -// var dbs []alpm.IDB -var dbs []alpm.IDB - -var DesktopEnv string - -// App struct -type App struct { - ctx context.Context -} - -// NewApp creates a new App application struct -func NewApp() *App { - return &App{} -} - -// startup is called at application startup -func (a *App) startup(ctx context.Context) { - // Perform your setup here - a.ctx = ctx - - DesktopEnv = getDesktopEnvironment() - - var err error - h, err = alpm.Initialize("/", "/var/lib/pacman") - if err != nil { - fmt.Fprintf(os.Stderr, "failed to initialize alpm: %v\n", err) - os.Exit(1) - } - - // Register and sync repositories - repos := []string{"core", "extra"} - for _, repo := range repos { - db, err := h.RegisterSyncDB(repo, 0) - if err != nil { - fmt.Printf("Error getting sync db for %s: %v\n", repo, err) - return - } - dbs = append(dbs, db) - } -} - -// domReady is called after front-end resources have been loaded -func (a App) domReady(ctx context.Context) { - // Add your action here -} - -// beforeClose is called when the application is about to quit, -// either by clicking the window close button or calling runtime.Quit. -// Returning true will cause the application to continue, false will continue shutdown as normal. -func (a *App) beforeClose(ctx context.Context) (prevent bool) { - return false -} - -// shutdown is called at application termination -func (a *App) shutdown(ctx context.Context) { - // Perform your teardown here - if h != nil { - h.Release() - } -} - -type PackageInfo struct { - Name string `json:"name"` - Version string `json:"version"` - Description string `json:"description"` - Repository string `json:"repository"` - Maintainer string `json:"maintainer"` - UpstreamURL string `json:"upstreamurl"` - DependList []string `json:"dependlist"` - LastUpdated string `json:"lastupdated"` -} - -func (a *App) SearchPackage(query string) []PackageInfo { - var results []PackageInfo - var wg sync.WaitGroup - resultChan := make(chan PackageInfo, 100) - doneChan := make(chan bool) - - // Start a goroutine to collect results - go func() { - for pkg := range resultChan { - results = append(results, pkg) - } - doneChan <- true - }() - - // Search official repositories concurrently - for _, db := range dbs { - wg.Add(1) - go func(db alpm.IDB) { - defer wg.Done() - searchDB(db, query, resultChan) - }(db) - } - - // Search AUR concurrently - wg.Add(1) - go func() { - defer wg.Done() - searchAUR(query, resultChan) - }() - - // Wait for all searches to complete - wg.Wait() - close(resultChan) - - // Wait for result collection to finish - <-doneChan - - return results -} - -func searchDB(db alpm.IDB, query string, resultChan chan<- PackageInfo) { - db.PkgCache().ForEach(func(pkg alpm.IPackage) error { - if strings.Contains(strings.ToLower(pkg.Name()), strings.ToLower(query)) { - lastUpdated := pkg.BuildDate().UTC().Format("Jan. 2, 2006, 3 p.m. MST") - resultChan <- PackageInfo{ - Name: pkg.Name(), - Version: pkg.Version(), - Description: pkg.Description(), - Repository: db.Name(), - Maintainer: pkg.Packager(), - UpstreamURL: pkg.URL(), - DependList: convertDependList(pkg.Depends()), - LastUpdated: lastUpdated, - } - } - return nil - }) -} - -func searchAUR(query string, resultChan chan<- PackageInfo) { - cmd := exec.Command("curl", "-s", fmt.Sprintf("https://aur.archlinux.org/rpc/?v=5&type=search&arg=%s", query)) - output, err := cmd.Output() - if err != nil { - fmt.Printf("Error searching AUR: %v\n", err) - return - } - - var aurResponse struct { - Results []struct { - Name string `json:"Name"` - Version string `json:"Version"` - Description string `json:"Description"` - Maintainer string `json:"Maintainer"` - URL string `json:"URL"` - LastModified int64 `json:"LastModified"` - } `json:"results"` - } - err = json.Unmarshal(output, &aurResponse) - if err != nil { - fmt.Printf("Error parsing AUR response: %v\n", err) - return - } - - for _, aurPkg := range aurResponse.Results { - lastUpdated := time.Unix(aurPkg.LastModified, 0).UTC().Format("02-01-2006") - resultChan <- PackageInfo{ - Name: aurPkg.Name, - Version: aurPkg.Version, - Description: aurPkg.Description, - Repository: "AUR", - Maintainer: aurPkg.Maintainer, - UpstreamURL: aurPkg.URL, - DependList: nil, - LastUpdated: lastUpdated, - } - } -} - -func convertDependList(depList alpm.IDependList) []string { - var deps []string - depList.ForEach(func(dep *alpm.Depend) error { - deps = append(deps, dep.Name) - return nil - }) - return deps -} - -func (a *App) GetInstalledPackages() ([]PackageInfo, error) { - h, err := alpm.Initialize("/", "/var/lib/pacman") - if err != nil { - fmt.Fprintf(os.Stderr, "failed to initialize alpm: %v\n", err) - os.Exit(1) - } - - if h == nil { - return nil, fmt.Errorf("ALPM handle is not initialized") - } - - db, err := h.LocalDB() - if err != nil { - return nil, fmt.Errorf("failed to get local DB: %v", err) - } - - var packages []PackageInfo - var mutex sync.Mutex - - err = db.PkgCache().ForEach(func(pkg alpm.IPackage) error { - mutex.Lock() - lastUpdated := pkg.BuildDate().UTC().Format("Jan. 2, 2006, 3 p.m. MST") - packages = append(packages, PackageInfo{ - Name: pkg.Name(), - Version: pkg.Version(), - Description: pkg.Description(), - Repository: pkg.DB().Name(), - Maintainer: pkg.Packager(), - UpstreamURL: pkg.URL(), - DependList: convertDependList(pkg.Depends()), - LastUpdated: lastUpdated, - }) - mutex.Unlock() - return nil - }) - - if err != nil { - return nil, fmt.Errorf("error iterating over packages: %v", err) - } - - if len(packages) == 0 { - return nil, fmt.Errorf("no installed packages found") - } - - return packages, nil -} - -func (a *App) SearchLocalPackage(pkg string) (bool, error) { - if pkg == "" { - return false, fmt.Errorf("empty package name provided") - } - - local, err := searchLocalDB(pkg) - if err != nil { - return false, fmt.Errorf("error searching local DB: %w", err) - } - - if local == nil { - return false, nil - } - - fmt.Println(strings.Contains(strings.ToLower(local.Name()), strings.ToLower(pkg))) - - return strings.Contains(strings.ToLower(local.Name()), strings.ToLower(pkg)), nil -} - -func searchLocalDB(pkg string) (alpm.IPackage, error) { - h, err := alpm.Initialize("/", "/var/lib/pacman") - if err != nil { - fmt.Fprintf(os.Stderr, "failed to initialize alpm: %v\n", err) - os.Exit(1) - } - if h == nil { - return nil, fmt.Errorf("ALPM handle is not initialized") - } - - db, err := h.LocalDB() - if err != nil { - return nil, fmt.Errorf("failed to get local DB: %w", err) - } - - res := db.Pkg(pkg) - return res, nil -} - -func (a *App) CheckPackageInstalled(packageName string) bool { - h, err := alpm.Initialize("/", "/var/lib/pacman") - if err != nil { - fmt.Fprintf(os.Stderr, "failed to initialize alpm: %v\n", err) - os.Exit(1) - } - if h == nil { - log.Fatal("ALPM handle is not initialized") - } - localDB, err := h.LocalDB() - if err != nil { - log.Fatal(err) - } - packageHandle := localDB.Pkg(packageName) - return packageHandle != nil -} - -func (a *App) Install(pkg string) { - cmdStr := fmt.Sprintf("pkexec yay -S %s --noconfirm", pkg) - cmd := exec.Command("sh", "-c", cmdStr) - fmt.Println("Executing command:", cmdStr) - - var outBuffer, errBuffer bytes.Buffer - cmd.Stdout = &outBuffer - cmd.Stderr = &errBuffer - - err := cmd.Run() - if err != nil { - fmt.Println("Error executing command:", err) - fmt.Println("stderr:", errBuffer.String()) - return - } - - fmt.Println("stdout:", outBuffer.String()) - fmt.Println("stderr:", errBuffer.String()) -} - -func (a *App) Uninstall(pkg string) { - cmdStr := fmt.Sprintf("pkexec yay -Rdd %s --noconfirm", pkg) - cmd := exec.Command("sh", "-c", cmdStr) - fmt.Println("Executing command:", cmdStr) - - var outBuffer, errBuffer bytes.Buffer - cmd.Stdout = &outBuffer - cmd.Stderr = &errBuffer - - err := cmd.Run() - if err != nil { - fmt.Println("Error executing command:", err) - fmt.Println("stderr:", errBuffer.String()) - return - } - - fmt.Println("stdout:", outBuffer.String()) - fmt.Println("stderr:", errBuffer.String()) -} - -// func openTerminal(cmd string) { -// var pkexecCmd *exec.Cmd - -// switch DesktopEnv { -// case "xfce": -// pkexecCmd = exec.Command("xfce4-terminal", "-e", cmd) -// case "gnome": -// pkexecCmd = exec.Command("gnome-terminal", "--", "bash", "-c", cmd) -// case "kde": -// pkexecCmd = exec.Command("konsole", "-e", cmd) -// case "mate": -// pkexecCmd = exec.Command("mate-terminal", "-e", cmd) -// case "lxde": -// pkexecCmd = exec.Command("lxterminal", "-e", cmd) -// case "lxqt": -// pkexecCmd = exec.Command("qterminal", "-e", cmd) -// default: -// fmt.Printf("Unsupported desktop environment: %s\n", DesktopEnv) -// return -// } - -// if err := pkexecCmd.Run(); err != nil { -// fmt.Printf("Error executing command: %v\n", err) -// } -// } - -func getDesktopEnvironment() string { - return strings.ToLower(os.Getenv("XDG_CURRENT_DESKTOP")) -} - -func (a *App) GetMultiplePackageInfo(packageNames []string) ([]PackageInfo, error) { - var results []PackageInfo - var wg sync.WaitGroup - resultChan := make(chan PackageInfo, len(packageNames)) - errorChan := make(chan error, len(packageNames)) - - for _, pkgName := range packageNames { - wg.Add(1) - go func(name string) { - defer wg.Done() - - // Search for package info - searchResults := a.SearchPackage(name) - - var pkg PackageInfo - for _, result := range searchResults { - if result.Repository == "core" || result.Repository == "extra" || result.Repository == "AUR" { - pkg = result - pkg.Name = name // Ensure the name matches the search query - resultChan <- pkg - return - } - } - - // If no package was found in core, extra, or AUR, add a placeholder - if pkg.Name == "" { - resultChan <- PackageInfo{ - Name: name, - Description: "Package not found in core, extra, or AUR", - Repository: "unknown", - } - } - }(pkgName) - } - - // Close channels when all goroutines are done - go func() { - wg.Wait() - close(resultChan) - close(errorChan) - }() - - // Collect results and errors - for i := 0; i < len(packageNames); i++ { - select { - case result := <-resultChan: - results = append(results, result) - case err := <-errorChan: - return nil, fmt.Errorf("error processing packages: %w", err) - case <-a.ctx.Done(): - return nil, a.ctx.Err() - } - } - - // Sort results to maintain order of input packageNames - sort.Slice(results, func(i, j int) bool { - iIndex := indexOf(packageNames, results[i].Name) - jIndex := indexOf(packageNames, results[j].Name) - return iIndex < jIndex - }) - - return results, nil -} - -func indexOf(slice []string, item string) int { - for i, s := range slice { - if s == item { - return i - } - } - return -1 -} - -type UpdateInfo struct { - Name string `json:"name"` - OldVersion string `json:"oldVersion"` - NewVersion string `json:"newVersion"` - Repository string `json:"repository"` - DownloadSize int64 `json:"downloadSize"` -} - -// GetAvailableUpdates returns a list of available updates for packages -func (a *App) GetAvailableUpdates() ([]UpdateInfo, error) { - // Initialize ALPM - h, err := alpm.Initialize("/", "/var/lib/pacman") - if err != nil { - return nil, fmt.Errorf("failed to initialize alpm: %v", err) - } - defer h.Release() - - // Parse pacman configuration - pacmanConfig, _, err := paconf.ParseFile("/etc/pacman.conf") - if err != nil { - return nil, fmt.Errorf("failed to parse pacman config: %v", err) - } - - // Register sync databases - for _, repo := range pacmanConfig.Repos { - db, err := h.RegisterSyncDB(repo.Name, 0) - if err != nil { - return nil, fmt.Errorf("failed to register sync db %s: %v", repo.Name, err) - } - db.SetServers(repo.Servers) - } - - // Get local database - localDB, err := h.LocalDB() - if err != nil { - return nil, fmt.Errorf("failed to get local DB: %v", err) - } - - // Get sync databases - syncDBs, err := h.SyncDBs() - if err != nil { - return nil, fmt.Errorf("failed to get sync DBs: %v", err) - } - - var updates []UpdateInfo - var mutex sync.Mutex - var wg sync.WaitGroup - - // Check for updates in official repositories - wg.Add(1) - go func() { - defer wg.Done() - for _, pkg := range localDB.PkgCache().Slice() { - select { - case <-a.ctx.Done(): - return - default: - newPkg := pkg.SyncNewVersion(syncDBs) - if newPkg != nil { - mutex.Lock() - updates = append(updates, UpdateInfo{ - Name: pkg.Name(), - OldVersion: pkg.Version(), - NewVersion: newPkg.Version(), - Repository: newPkg.DB().Name(), - DownloadSize: newPkg.Size(), - }) - mutex.Unlock() - } - } - } - }() - - // Check for AUR updates - wg.Add(1) - go func() { - defer wg.Done() - aurUpdates, err := a.checkAURUpdates() - if err != nil { - log.Printf("Error checking AUR updates: %v", err) - return - } - mutex.Lock() - updates = append(updates, aurUpdates...) - mutex.Unlock() - }() - - wg.Wait() - - return updates, nil -} - -func (a *App) checkAURUpdates() ([]UpdateInfo, error) { - var aurUpdates []UpdateInfo - - // Get list of AUR packages - cmd := exec.CommandContext(a.ctx, "yay", "-Qm") - output, err := cmd.Output() - if err != nil { - return nil, fmt.Errorf("failed to get AUR package list: %v", err) - } - - aurPackages := strings.Split(strings.TrimSpace(string(output)), "\n") - - for _, pkg := range aurPackages { - select { - case <-a.ctx.Done(): - return aurUpdates, a.ctx.Err() - default: - parts := strings.Fields(pkg) - if len(parts) != 2 { - continue - } - name, version := parts[0], parts[1] - - // Check for updates using AUR RPC - cmd := exec.CommandContext(a.ctx, "curl", "-s", fmt.Sprintf("https://aur.archlinux.org/rpc/v5/info/%s", name)) - output, err := cmd.Output() - if err != nil { - log.Printf("Error checking AUR for package %s: %v", name, err) - continue - } - - var aurResponse struct { - Results []struct { - Version string `json:"Version"` - } `json:"results"` - } - err = json.Unmarshal(output, &aurResponse) - if err != nil { - log.Printf("Error parsing AUR response for package %s: %v", name, err) - continue - } - - if len(aurResponse.Results) > 0 && aurResponse.Results[0].Version != version { - aurUpdates = append(aurUpdates, UpdateInfo{ - Name: name, - OldVersion: version, - NewVersion: aurResponse.Results[0].Version, - Repository: "AUR", - DownloadSize: 0, - }) - } - } - } - - return aurUpdates, nil -} - -// HumanReadableSize converts bytes to a human-readable string -func (a *App) HumanReadableSize(size int64) string { - floatsize := float32(size) - units := [...]string{"", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi"} - for _, unit := range units { - if floatsize < 1024 { - return fmt.Sprintf("%.1f %sB", floatsize, unit) - } - floatsize /= 1024 - } - return fmt.Sprintf("%d%s", size, "B") -} - -func (a *App) UpdateSinglePkg(pkg string) { - cmdStr := fmt.Sprintf("pkexec yay -S %s --noconfirm", pkg) - cmd := exec.Command("sh", "-c", cmdStr) - fmt.Println("Executing command:", cmdStr) - - var outBuffer, errBuffer bytes.Buffer - cmd.Stdout = &outBuffer - cmd.Stderr = &errBuffer - - err := cmd.Run() - if err != nil { - fmt.Println("Error executing command:", err) - fmt.Println("stderr:", errBuffer.String()) - return - } - - fmt.Println("stdout:", outBuffer.String()) - fmt.Println("stderr:", errBuffer.String()) -} - -func (a *App) UpdateAllPkg() { - cmdStr := "pkexec yay -Syu --noconfirm" - cmd := exec.Command("sh", "-c", cmdStr) - fmt.Println("Executing command:", cmdStr) - - var outBuffer, errBuffer bytes.Buffer - cmd.Stdout = &outBuffer - cmd.Stderr = &errBuffer - - err := cmd.Run() - if err != nil { - fmt.Println("Error executing command:", err) - fmt.Println("stderr:", errBuffer.String()) - return - } - - fmt.Println("stdout:", outBuffer.String()) - fmt.Println("stderr:", errBuffer.String()) -} diff --git a/go.mod b/go.mod deleted file mode 100644 index 4f7a7fc..0000000 --- a/go.mod +++ /dev/null @@ -1,41 +0,0 @@ -module alg-app-store - -go 1.21 - -require ( - github.com/Jguer/go-alpm/v2 v2.2.2 - github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5 - github.com/wailsapp/wails/v2 v2.10.2 -) - -require ( - github.com/bep/debounce v1.2.1 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect - github.com/labstack/echo/v4 v4.10.2 // indirect - github.com/labstack/gommon v0.4.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.0 // indirect - github.com/leaanthony/gosod v1.0.3 // indirect - github.com/leaanthony/slicer v1.6.0 // indirect - github.com/leaanthony/u v1.1.0 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect - github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - github.com/samber/lo v1.38.1 // indirect - github.com/tkrajina/go-reflector v0.5.6 // indirect - github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasttemplate v1.2.2 // indirect - github.com/wailsapp/go-webview2 v1.0.10 // indirect - github.com/wailsapp/mimetype v1.4.1 // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect -) - -// replace github.com/wailsapp/wails/v2 v2.8.2 => /home/harsh/go/pkg/mod diff --git a/go.sum b/go.sum deleted file mode 100644 index 56f3f23..0000000 --- a/go.sum +++ /dev/null @@ -1,98 +0,0 @@ -github.com/Jguer/go-alpm/v2 v2.2.2 h1:sPwUoZp1X5Tw6K6Ba1lWvVJfcgVNEGVcxARLBttZnC0= -github.com/Jguer/go-alpm/v2 v2.2.2/go.mod h1:lfe8gSe83F/KERaQvEfrSqQ4n+8bES+ZIyKWR/gm3MI= -github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5 h1:TMscPjkb1ThXN32LuFY5bEYIcXZx3YlwzhS1GxNpn/c= -github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5/go.mod h1:Hk55m330jNiwxRodIlMCvw5iEyoRUCIY64W1p9D+tHc= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= -github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M= -github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= -github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= -github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= -github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc= -github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA= -github.com/leaanthony/go-ansi-parser v1.6.0 h1:T8TuMhFB6TUMIUm0oRrSbgJudTFw9csT3ZK09w0t4Pg= -github.com/leaanthony/go-ansi-parser v1.6.0/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ= -github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4= -github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= -github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js= -github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8= -github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI= -github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= -github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQSepKdE= -github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= -github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/wailsapp/go-webview2 v1.0.10 h1:PP5Hug6pnQEAhfRzLCoOh2jJaPdrqeRgJKZhyYyDV/w= -github.com/wailsapp/go-webview2 v1.0.10/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo= -github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= -github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= -github.com/wailsapp/wails/v2 v2.9.1 h1:irsXnoQrCpeKzKTYZ2SUVlRRyeMR6I0vCO9Q1cvlEdc= -github.com/wailsapp/wails/v2 v2.9.1/go.mod h1:7maJV2h+Egl11Ak8QZN/jlGLj2wg05bsQS+ywJPT0gI= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= -golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go deleted file mode 100644 index 09f1ec9..0000000 --- a/main.go +++ /dev/null @@ -1,96 +0,0 @@ -package main - -import ( - "embed" - "log" - - "github.com/wailsapp/wails/v2" - "github.com/wailsapp/wails/v2/pkg/logger" - "github.com/wailsapp/wails/v2/pkg/options" - "github.com/wailsapp/wails/v2/pkg/options/assetserver" - "github.com/wailsapp/wails/v2/pkg/options/linux" - "github.com/wailsapp/wails/v2/pkg/options/mac" - "github.com/wailsapp/wails/v2/pkg/options/windows" -) - -//go:embed all:frontend/dist -var assets embed.FS - -//go:embed frontend/src/assets/icon/appicon.png -var icon []byte - -func main() { - // Create an instance of the app structure - app := NewApp() - - // Create application with options - err := wails.Run(&options.App{ - Title: "ALG App Store (Beta)", - Width: 1124, - Height: 868, - MinWidth: 1024, - MinHeight: 768, - MaxWidth: 0, - MaxHeight: 0, - DisableResize: false, - Fullscreen: true, - Frameless: false, - StartHidden: false, - HideWindowOnClose: false, - BackgroundColour: &options.RGBA{R: 255, G: 255, B: 255, A: 255}, - CSSDragProperty: "none", - AssetServer: &assetserver.Options{ - Assets: assets, - }, - Menu: nil, - Logger: nil, - LogLevel: logger.DEBUG, - OnStartup: app.startup, - OnDomReady: app.domReady, - OnBeforeClose: app.beforeClose, - OnShutdown: app.shutdown, - WindowStartState: options.Maximised, - Bind: []interface{}{ - app, - }, - Debug: options.Debug{ - OpenInspectorOnStartup: true, - }, - // Windows platform specific options - Windows: &windows.Options{ - WebviewIsTransparent: false, - WindowIsTranslucent: false, - DisableWindowIcon: false, - // DisableFramelessWindowDecorations: false, - WebviewUserDataPath: "", - ZoomFactor: 1.0, - }, - // Mac platform specific options - Mac: &mac.Options{ - TitleBar: &mac.TitleBar{ - TitlebarAppearsTransparent: true, - HideTitle: false, - HideTitleBar: false, - FullSizeContent: false, - UseToolbar: false, - HideToolbarSeparator: true, - }, - Appearance: mac.NSAppearanceNameDarkAqua, - WebviewIsTransparent: true, - WindowIsTranslucent: true, - About: &mac.AboutInfo{ - Title: "alg-app-store", - Message: "", - Icon: icon, - }, - }, - Linux: &linux.Options{ - Icon: icon, - WebviewGpuPolicy: linux.WebviewGpuPolicyOnDemand, - }, - }) - - if err != nil { - log.Fatal(err) - } -} From fb1acbc09c09345b02b558d7c20d1add44d6ac18 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:20:57 +0000 Subject: [PATCH 13/71] remove old wails scripts --- scripts/build-macos-arm.sh | 9 --------- scripts/build-macos-intel.sh | 9 --------- scripts/build-macos.sh | 9 --------- scripts/build-windows.sh | 9 --------- scripts/build.sh | 9 --------- scripts/install-wails-cli.sh | 14 -------------- 6 files changed, 59 deletions(-) delete mode 100644 scripts/build-macos-arm.sh delete mode 100644 scripts/build-macos-intel.sh delete mode 100644 scripts/build-macos.sh delete mode 100644 scripts/build-windows.sh delete mode 100644 scripts/build.sh delete mode 100644 scripts/install-wails-cli.sh diff --git a/scripts/build-macos-arm.sh b/scripts/build-macos-arm.sh deleted file mode 100644 index bc6ee0a..0000000 --- a/scripts/build-macos-arm.sh +++ /dev/null @@ -1,9 +0,0 @@ -#! /bin/bash - -echo -e "Start running the script..." -cd ../ - -echo -e "Start building the app for macos platform..." -wails build --clean --platform darwin/arm64 - -echo -e "End running the script!" diff --git a/scripts/build-macos-intel.sh b/scripts/build-macos-intel.sh deleted file mode 100644 index f359f63..0000000 --- a/scripts/build-macos-intel.sh +++ /dev/null @@ -1,9 +0,0 @@ -#! /bin/bash - -echo -e "Start running the script..." -cd ../ - -echo -e "Start building the app for macos platform..." -wails build --clean --platform darwin - -echo -e "End running the script!" diff --git a/scripts/build-macos.sh b/scripts/build-macos.sh deleted file mode 100644 index d61531f..0000000 --- a/scripts/build-macos.sh +++ /dev/null @@ -1,9 +0,0 @@ -#! /bin/bash - -echo -e "Start running the script..." -cd ../ - -echo -e "Start building the app for macos platform..." -wails build --clean --platform darwin/universal - -echo -e "End running the script!" diff --git a/scripts/build-windows.sh b/scripts/build-windows.sh deleted file mode 100644 index 47b7789..0000000 --- a/scripts/build-windows.sh +++ /dev/null @@ -1,9 +0,0 @@ -#! /bin/bash - -echo -e "Start running the script..." -cd ../ - -echo -e "Start building the app for windows platform..." -wails build --clean --platform windows/amd64 - -echo -e "End running the script!" diff --git a/scripts/build.sh b/scripts/build.sh deleted file mode 100644 index 20ab7eb..0000000 --- a/scripts/build.sh +++ /dev/null @@ -1,9 +0,0 @@ -#! /bin/bash - -echo -e "Start running the script..." -cd ../ - -echo -e "Start building the app..." -wails build --clean - -echo -e "End running the script!" diff --git a/scripts/install-wails-cli.sh b/scripts/install-wails-cli.sh deleted file mode 100644 index 7539d8e..0000000 --- a/scripts/install-wails-cli.sh +++ /dev/null @@ -1,14 +0,0 @@ -#! /bin/bash - -echo -e "Start running the script..." -cd ../ - -echo -e "Current Go version: \c" -go version - -echo -e "Install the Wails command line tool..." -go install github.com/wailsapp/wails/v2/cmd/wails@latest - -echo -e "Successful installation!" - -echo -e "End running the script!" From 69afc2de10e32e9df274b0ab9922176f170280ed Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:21:32 +0000 Subject: [PATCH 14/71] remove wails.json --- wails.json | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 wails.json diff --git a/wails.json b/wails.json deleted file mode 100644 index 9b86be0..0000000 --- a/wails.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "https://wails.io/schemas/config.v2.json", - "name": "alg-app-store", - "outputfilename": "alg-app-store", - "frontend:install": "npm install", - "frontend:build": "npm run build", - "frontend:dev:watcher": "npm run dev", - "frontend:dev:serverUrl": "auto", - "author": { - "name": "harshau007", - "email": "amanupadhyay2004@gmail.com" - } -} From 11786e8ffe1b216b2b8a2e505843a134e84a4838 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:22:02 +0000 Subject: [PATCH 15/71] remove wails build folder --- build/README.md | 35 ---- build/appicon.png | Bin 132625 -> 0 bytes build/darwin/Info.dev.plist | 68 ------- build/darwin/Info.plist | 63 ------ build/windows/icon.ico | Bin 21017 -> 0 bytes build/windows/info.json | 15 -- build/windows/installer/project.nsi | 114 ----------- build/windows/installer/wails_tools.nsh | 249 ------------------------ build/windows/wails.exe.manifest | 15 -- 9 files changed, 559 deletions(-) delete mode 100644 build/README.md delete mode 100644 build/appicon.png delete mode 100644 build/darwin/Info.dev.plist delete mode 100644 build/darwin/Info.plist delete mode 100644 build/windows/icon.ico delete mode 100644 build/windows/info.json delete mode 100644 build/windows/installer/project.nsi delete mode 100644 build/windows/installer/wails_tools.nsh delete mode 100644 build/windows/wails.exe.manifest diff --git a/build/README.md b/build/README.md deleted file mode 100644 index 1ae2f67..0000000 --- a/build/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Build Directory - -The build directory is used to house all the build files and assets for your application. - -The structure is: - -* bin - Output directory -* darwin - macOS specific files -* windows - Windows specific files - -## Mac - -The `darwin` directory holds files specific to Mac builds. -These may be customised and used as part of the build. To return these files to the default state, simply delete them -and -build with `wails build`. - -The directory contains the following files: - -- `Info.plist` - the main plist file used for Mac builds. It is used when building using `wails build`. -- `Info.dev.plist` - same as the main plist file but used when building using `wails dev`. - -## Windows - -The `windows` directory contains the manifest and rc files used when building with `wails build`. -These may be customised for your application. To return these files to the default state, simply delete them and -build with `wails build`. - -- `icon.ico` - The icon used for the application. This is used when building using `wails build`. If you wish to - use a different icon, simply replace this file with your own. If it is missing, a new `icon.ico` file - will be created using the `appicon.png` file in the build directory. -- `installer/*` - The files used to create the Windows installer. These are used when building using `wails build`. -- `info.json` - Application details used for Windows builds. The data here will be used by the Windows installer, - as well as the application itself (right click the exe -> properties -> details) -- `wails.exe.manifest` - The main application manifest file. \ No newline at end of file diff --git a/build/appicon.png b/build/appicon.png deleted file mode 100644 index 63617fe4f746b8a878bd5f44725f4f317b9d9850..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132625 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 z 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 DB$9&s diff --git a/build/darwin/Info.dev.plist b/build/darwin/Info.dev.plist deleted file mode 100644 index 04727c2..0000000 --- a/build/darwin/Info.dev.plist +++ /dev/null @@ -1,68 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - {{.Info.ProductName}} - CFBundleExecutable - {{.Name}} - CFBundleIdentifier - com.wails.{{.Name}} - CFBundleVersion - {{.Info.ProductVersion}} - CFBundleGetInfoString - {{.Info.Comments}} - CFBundleShortVersionString - {{.Info.ProductVersion}} - CFBundleIconFile - iconfile - LSMinimumSystemVersion - 10.13.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - {{.Info.Copyright}} - {{if .Info.FileAssociations}} - CFBundleDocumentTypes - - {{range .Info.FileAssociations}} - - CFBundleTypeExtensions - - {{.Ext}} - - CFBundleTypeName - {{.Name}} - CFBundleTypeRole - {{.Role}} - CFBundleTypeIconFile - {{.IconName}} - - {{end}} - - {{end}} - {{if .Info.Protocols}} - CFBundleURLTypes - - {{range .Info.Protocols}} - - CFBundleURLName - com.wails.{{.Scheme}} - CFBundleURLSchemes - - {{.Scheme}} - - CFBundleTypeRole - {{.Role}} - - {{end}} - - {{end}} - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - - diff --git a/build/darwin/Info.plist b/build/darwin/Info.plist deleted file mode 100644 index 19cc937..0000000 --- a/build/darwin/Info.plist +++ /dev/null @@ -1,63 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - {{.Info.ProductName}} - CFBundleExecutable - {{.Name}} - CFBundleIdentifier - com.wails.{{.Name}} - CFBundleVersion - {{.Info.ProductVersion}} - CFBundleGetInfoString - {{.Info.Comments}} - CFBundleShortVersionString - {{.Info.ProductVersion}} - CFBundleIconFile - iconfile - LSMinimumSystemVersion - 10.13.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - {{.Info.Copyright}} - {{if .Info.FileAssociations}} - CFBundleDocumentTypes - - {{range .Info.FileAssociations}} - - CFBundleTypeExtensions - - {{.Ext}} - - CFBundleTypeName - {{.Name}} - CFBundleTypeRole - {{.Role}} - CFBundleTypeIconFile - {{.IconName}} - - {{end}} - - {{end}} - {{if .Info.Protocols}} - CFBundleURLTypes - - {{range .Info.Protocols}} - - CFBundleURLName - com.wails.{{.Scheme}} - CFBundleURLSchemes - - {{.Scheme}} - - CFBundleTypeRole - {{.Role}} - - {{end}} - - {{end}} - - diff --git a/build/windows/icon.ico b/build/windows/icon.ico deleted file mode 100644 index f33479841c61728c8b5ee076ed13771c68e48b40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21017 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 wails build --target windows/amd64 --nsis -## Then you can call makensis on this file with specifying the path to your binary: -## For a AMD64 only installer: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe -## For a ARM64 only installer: -## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe -## For a installer with both architectures: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe -#### -## The following information is taken from the ProjectInfo file, but they can be overwritten here. -#### -## !define INFO_PROJECTNAME "MyProject" # Default "{{.Name}}" -## !define INFO_COMPANYNAME "MyCompany" # Default "{{.Info.CompanyName}}" -## !define INFO_PRODUCTNAME "MyProduct" # Default "{{.Info.ProductName}}" -## !define INFO_PRODUCTVERSION "1.0.0" # Default "{{.Info.ProductVersion}}" -## !define INFO_COPYRIGHT "Copyright" # Default "{{.Info.Copyright}}" -### -## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" -## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -#### -## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html -#### -## Include the wails tools -#### -!include "wails_tools.nsh" - -# The version information for this two must consist of 4 parts -VIProductVersion "${INFO_PRODUCTVERSION}.0" -VIFileVersion "${INFO_PRODUCTVERSION}.0" - -VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" -VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" -VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" -VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" - -# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware -ManifestDPIAware true - -!include "MUI.nsh" - -!define MUI_ICON "..\icon.ico" -!define MUI_UNICON "..\icon.ico" -# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 -!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps -!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. - -!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. -# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer -!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. -!insertmacro MUI_PAGE_INSTFILES # Installing page. -!insertmacro MUI_PAGE_FINISH # Finished installation page. - -!insertmacro MUI_UNPAGE_INSTFILES # Uinstalling page - -!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer - -## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 -#!uninstfinalize 'signtool --file "%1"' -#!finalize 'signtool --file "%1"' - -Name "${INFO_PRODUCTNAME}" -OutFile "..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. -InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). -ShowInstDetails show # This will always show the installation details. - -Function .onInit - !insertmacro wails.checkArchitecture -FunctionEnd - -Section - !insertmacro wails.setShellContext - - !insertmacro wails.webview2runtime - - SetOutPath $INSTDIR - - !insertmacro wails.files - - CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - - !insertmacro wails.associateFiles - !insertmacro wails.associateCustomProtocols - - !insertmacro wails.writeUninstaller -SectionEnd - -Section "uninstall" - !insertmacro wails.setShellContext - - RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath - - RMDir /r $INSTDIR - - Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" - Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" - - !insertmacro wails.unassociateFiles - !insertmacro wails.unassociateCustomProtocols - - !insertmacro wails.deleteUninstaller -SectionEnd diff --git a/build/windows/installer/wails_tools.nsh b/build/windows/installer/wails_tools.nsh deleted file mode 100644 index f9c0f88..0000000 --- a/build/windows/installer/wails_tools.nsh +++ /dev/null @@ -1,249 +0,0 @@ -# DO NOT EDIT - Generated automatically by `wails build` - -!include "x64.nsh" -!include "WinVer.nsh" -!include "FileFunc.nsh" - -!ifndef INFO_PROJECTNAME - !define INFO_PROJECTNAME "{{.Name}}" -!endif -!ifndef INFO_COMPANYNAME - !define INFO_COMPANYNAME "{{.Info.CompanyName}}" -!endif -!ifndef INFO_PRODUCTNAME - !define INFO_PRODUCTNAME "{{.Info.ProductName}}" -!endif -!ifndef INFO_PRODUCTVERSION - !define INFO_PRODUCTVERSION "{{.Info.ProductVersion}}" -!endif -!ifndef INFO_COPYRIGHT - !define INFO_COPYRIGHT "{{.Info.Copyright}}" -!endif -!ifndef PRODUCT_EXECUTABLE - !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" -!endif -!ifndef UNINST_KEY_NAME - !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -!endif -!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" - -!ifndef REQUEST_EXECUTION_LEVEL - !define REQUEST_EXECUTION_LEVEL "admin" -!endif - -RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" - -!ifdef ARG_WAILS_AMD64_BINARY - !define SUPPORTS_AMD64 -!endif - -!ifdef ARG_WAILS_ARM64_BINARY - !define SUPPORTS_ARM64 -!endif - -!ifdef SUPPORTS_AMD64 - !ifdef SUPPORTS_ARM64 - !define ARCH "amd64_arm64" - !else - !define ARCH "amd64" - !endif -!else - !ifdef SUPPORTS_ARM64 - !define ARCH "arm64" - !else - !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" - !endif -!endif - -!macro wails.checkArchitecture - !ifndef WAILS_WIN10_REQUIRED - !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." - !endif - - !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED - !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" - !endif - - ${If} ${AtLeastWin10} - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - Goto ok - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - Goto ok - ${EndIf} - !endif - - IfSilent silentArch notSilentArch - silentArch: - SetErrorLevel 65 - Abort - notSilentArch: - MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" - Quit - ${else} - IfSilent silentWin notSilentWin - silentWin: - SetErrorLevel 64 - Abort - notSilentWin: - MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" - Quit - ${EndIf} - - ok: -!macroend - -!macro wails.files - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" - ${EndIf} - !endif -!macroend - -!macro wails.writeUninstaller - WriteUninstaller "$INSTDIR\uninstall.exe" - - SetRegView 64 - WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" - WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" - WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" - - ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 - IntFmt $0 "0x%08X" $0 - WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" -!macroend - -!macro wails.deleteUninstaller - Delete "$INSTDIR\uninstall.exe" - - SetRegView 64 - DeleteRegKey HKLM "${UNINST_KEY}" -!macroend - -!macro wails.setShellContext - ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" - SetShellVarContext all - ${else} - SetShellVarContext current - ${EndIf} -!macroend - -# Install webview2 by launching the bootstrapper -# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment -!macro wails.webview2runtime - !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT - !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" - !endif - - SetRegView 64 - # If the admin key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - - ${If} ${REQUEST_EXECUTION_LEVEL} == "user" - # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - ${EndIf} - - SetDetailsPrint both - DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" - SetDetailsPrint listonly - - InitPluginsDir - CreateDirectory "$pluginsdir\webview2bootstrapper" - SetOutPath "$pluginsdir\webview2bootstrapper" - File "tmp\MicrosoftEdgeWebview2Setup.exe" - ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' - - SetDetailsPrint both - ok: -!macroend - -# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b -!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" - - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" - - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` -!macroend - -!macro APP_UNASSOCIATE EXT FILECLASS - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" - - DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` -!macroend - -!macro wails.associateFiles - ; Create file associations - {{range .Info.FileAssociations}} - !insertmacro APP_ASSOCIATE "{{.Ext}}" "{{.Name}}" "{{.Description}}" "$INSTDIR\{{.IconName}}.ico" "Open with ${INFO_PRODUCTNAME}" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\"" - - File "..\{{.IconName}}.ico" - {{end}} -!macroend - -!macro wails.unassociateFiles - ; Delete app associations - {{range .Info.FileAssociations}} - !insertmacro APP_UNASSOCIATE "{{.Ext}}" "{{.Name}}" - - Delete "$INSTDIR\{{.IconName}}.ico" - {{end}} -!macroend - -!macro CUSTOM_PROTOCOL_ASSOCIATE PROTOCOL DESCRIPTION ICON COMMAND - DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}" - WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "" "${DESCRIPTION}" - WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "URL Protocol" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\DefaultIcon" "" "${ICON}" - WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell" "" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open" "" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open\command" "" "${COMMAND}" -!macroend - -!macro CUSTOM_PROTOCOL_UNASSOCIATE PROTOCOL - DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}" -!macroend - -!macro wails.associateCustomProtocols - ; Create custom protocols associations - {{range .Info.Protocols}} - !insertmacro CUSTOM_PROTOCOL_ASSOCIATE "{{.Scheme}}" "{{.Description}}" "$INSTDIR\${PRODUCT_EXECUTABLE},0" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\"" - - {{end}} -!macroend - -!macro wails.unassociateCustomProtocols - ; Delete app custom protocol associations - {{range .Info.Protocols}} - !insertmacro CUSTOM_PROTOCOL_UNASSOCIATE "{{.Scheme}}" - {{end}} -!macroend diff --git a/build/windows/wails.exe.manifest b/build/windows/wails.exe.manifest deleted file mode 100644 index 17e1a23..0000000 --- a/build/windows/wails.exe.manifest +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - true/pm - permonitorv2,permonitor - - - \ No newline at end of file From 2fbe9083ea534b9b712276c49c3f09f2644ea176 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:23:31 +0000 Subject: [PATCH 16/71] implement search tab --- src/gui/search_widget.cpp | 221 ++++++++++++++++++++++++++++++++++++++ src/gui/search_widget.h | 48 +++++++++ 2 files changed, 269 insertions(+) create mode 100644 src/gui/search_widget.cpp create mode 100644 src/gui/search_widget.h diff --git a/src/gui/search_widget.cpp b/src/gui/search_widget.cpp new file mode 100644 index 0000000..4a5f12b --- /dev/null +++ b/src/gui/search_widget.cpp @@ -0,0 +1,221 @@ +#include "search_widget.h" +#include "package_card.h" +#include "package_details_dialog.h" +#include "../core/alpm_wrapper.h" +#include "../core/aur_helper.h" +#include "../utils/logger.h" +#include +#include +#include +#include +#include + +SearchWidget::SearchWidget(QWidget* parent) + : QWidget(parent) + , m_searchInput(new QLineEdit(this)) + , m_searchButton(new QPushButton("Search", this)) + , m_filterCombo(new QComboBox(this)) + , m_scrollArea(new QScrollArea(this)) + , m_contentWidget(new QWidget()) + , m_gridLayout(new QGridLayout(m_contentWidget)) + , m_statusLabel(new QLabel(this)) + , m_aurHelper(std::make_unique(this)) { + + setupUi(); + + connect(m_aurHelper.get(), &AurHelper::searchCompleted, + this, &SearchWidget::onAurSearchCompleted); +} + +void SearchWidget::setupUi() { + auto* mainLayout = new QVBoxLayout(this); + + // Title + auto* titleLabel = new QLabel("Search Packages", this); + auto titleFont = titleLabel->font(); + titleFont.setPointSize(24); + titleFont.setBold(true); + titleLabel->setFont(titleFont); + mainLayout->addWidget(titleLabel); + + // Search bar + auto* searchLayout = new QHBoxLayout(); + + m_searchInput->setPlaceholderText("Search for packages..."); + m_searchInput->setMinimumHeight(35); + connect(m_searchInput, &QLineEdit::returnPressed, this, &SearchWidget::onSearchClicked); + searchLayout->addWidget(m_searchInput, 1); + + // Filter combo + m_filterCombo->addItem("All", "all"); + m_filterCombo->addItem("Core", "core"); + m_filterCombo->addItem("Extra", "extra"); + m_filterCombo->addItem("AUR", "AUR"); + m_filterCombo->setMinimumHeight(35); + connect(m_filterCombo, QOverload::of(&QComboBox::currentIndexChanged), + this, &SearchWidget::onFilterChanged); + searchLayout->addWidget(m_filterCombo); + + m_searchButton->setMinimumHeight(35); + m_searchButton->setMinimumWidth(100); + connect(m_searchButton, &QPushButton::clicked, this, &SearchWidget::onSearchClicked); + searchLayout->addWidget(m_searchButton); + + mainLayout->addLayout(searchLayout); + + // Status label + m_statusLabel->setAlignment(Qt::AlignCenter); + m_statusLabel->hide(); + mainLayout->addWidget(m_statusLabel); + + // Results area + m_scrollArea->setWidget(m_contentWidget); + m_scrollArea->setWidgetResizable(true); + m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + m_gridLayout->setSpacing(15); + m_gridLayout->setContentsMargins(10, 10, 10, 10); + + mainLayout->addWidget(m_scrollArea); + setLayout(mainLayout); +} + +void SearchWidget::onSearchClicked() { + QString query = m_searchInput->text().trimmed(); + + if (query.isEmpty()) { + m_statusLabel->setText("Please enter a search term"); + m_statusLabel->show(); + return; + } + + m_searchButton->setEnabled(false); + m_searchButton->setText("Searching..."); + m_statusLabel->setText("Searching..."); + m_statusLabel->show(); + + clearResults(); + performSearch(); +} + +void SearchWidget::performSearch() { + QString query = m_searchInput->text().trimmed().toLower().replace(' ', '-'); + + // Search in official repos using ALPM + (void)QtConcurrent::run([this, query]() { + auto results = AlpmWrapper::instance().searchPackages(query); + + QMetaObject::invokeMethod(this, [this, results]() { + m_allResults = results; + + // Also search AUR + m_aurHelper->searchPackages(m_searchInput->text().trimmed()); + }, Qt::QueuedConnection); + }); +} + +void SearchWidget::onAurSearchCompleted(const QVector& results) { + // Combine with official repo results + m_allResults.append(results); + + m_searchButton->setEnabled(true); + m_searchButton->setText("Search"); + + if (m_allResults.isEmpty()) { + m_statusLabel->setText("No results found"); + return; + } + + m_statusLabel->hide(); + + // Apply filter + onFilterChanged(m_filterCombo->currentIndex()); + + Logger::info(QString("Search completed: %1 results").arg(m_allResults.size())); +} + +void SearchWidget::onFilterChanged(int index) { + QString filter = m_filterCombo->itemData(index).toString(); + + if (filter == "all") { + displayResults(m_allResults); + } else { + QVector filtered; + for (const auto& pkg : m_allResults) { + if (pkg.repository == filter) { + filtered.append(pkg); + } + } + displayResults(filtered); + } +} + +void SearchWidget::displayResults(const QVector& results) { + clearResults(); + m_currentResults = results; + + if (results.isEmpty()) { + m_statusLabel->setText("No results found for selected filter"); + m_statusLabel->show(); + return; + } + + int row = 0; + int col = 0; + const int columns = 3; + + for (const auto& pkg : results) { + auto* card = new PackageCard(pkg, m_contentWidget); + connect(card, &PackageCard::clicked, this, &SearchWidget::onPackageClicked); + + m_gridLayout->addWidget(card, row, col); + + col++; + if (col >= columns) { + col = 0; + row++; + } + } + + m_gridLayout->setRowStretch(row + 1, 1); +} + +void SearchWidget::clearResults() { + while (auto* item = m_gridLayout->takeAt(0)) { + if (auto* widget = item->widget()) { + widget->deleteLater(); + } + delete item; + } +} + +void SearchWidget::onPackageClicked(const PackageInfo& info) { + Logger::info(QString("Package clicked: %1").arg(info.name)); + + PackageInfo fullInfo = info; + + // For AUR packages, fetch complete details including maintainer, URL, dependencies + if (info.repository.toLower() == "aur") { + auto* aurHelper = new AurHelper(this); + QEventLoop loop; + + connect(aurHelper, &AurHelper::packageInfoReceived, [&](const PackageInfo& detailedInfo) { + fullInfo = detailedInfo; + loop.quit(); + }); + + connect(aurHelper, &AurHelper::error, [&](const QString& errorMsg) { + Logger::warning(QString("Failed to fetch AUR details for %1: %2").arg(info.name, errorMsg)); + loop.quit(); + }); + + aurHelper->getPackageInfo(info.name); + loop.exec(); + + aurHelper->deleteLater(); + } + + auto* dialog = new PackageDetailsDialog(fullInfo, this); + dialog->exec(); + dialog->deleteLater(); +} diff --git a/src/gui/search_widget.h b/src/gui/search_widget.h new file mode 100644 index 0000000..5da3a89 --- /dev/null +++ b/src/gui/search_widget.h @@ -0,0 +1,48 @@ +#ifndef SEARCH_WIDGET_H +#define SEARCH_WIDGET_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../utils/types.h" +#include "../core/aur_helper.h" + +class SearchWidget : public QWidget { + Q_OBJECT + +public: + explicit SearchWidget(QWidget* parent = nullptr); + ~SearchWidget() override = default; + +private: + void setupUi(); + void performSearch(); + void displayResults(const QVector& results); + void clearResults(); + + QLineEdit* m_searchInput; + QPushButton* m_searchButton; + QComboBox* m_filterCombo; + QScrollArea* m_scrollArea; + QWidget* m_contentWidget; + QGridLayout* m_gridLayout; + QLabel* m_statusLabel; + + std::unique_ptr m_aurHelper; + QVector m_currentResults; + QVector m_allResults; + +private slots: + void onSearchClicked(); + void onAurSearchCompleted(const QVector& results); + void onFilterChanged(int index); + void onPackageClicked(const PackageInfo& info); +}; + +#endif // SEARCH_WIDGET_H From 82a584d6b69de75c098721ebd77a8ba437ae9bc2 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:24:55 +0000 Subject: [PATCH 17/71] package card on home tab --- src/gui/package_card.cpp | 112 +++++++++++++++++++++++++++++++++++++++ src/gui/package_card.h | 40 ++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 src/gui/package_card.cpp create mode 100644 src/gui/package_card.h diff --git a/src/gui/package_card.cpp b/src/gui/package_card.cpp new file mode 100644 index 0000000..864e26b --- /dev/null +++ b/src/gui/package_card.cpp @@ -0,0 +1,112 @@ +#include "package_card.h" +#include "../core/alpm_wrapper.h" +#include +#include +#include +#include + +PackageCard::PackageCard(const PackageInfo& info, QWidget* parent) + : QWidget(parent) + , m_info(info) + , m_nameLabel(new QLabel(this)) + , m_descriptionLabel(new QLabel(this)) + , m_versionLabel(new QLabel(this)) + , m_repositoryLabel(new QLabel(this)) + , m_statusLabel(new QLabel(this)) + , m_isInstalled(false) { + + setupUi(); + checkInstallStatus(); +} + +void PackageCard::setupUi() { + setMinimumHeight(180); + setMaximumHeight(220); + setMinimumWidth(280); + setCursor(Qt::PointingHandCursor); + + setProperty("class", "package-card"); + + auto* mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(15, 15, 15, 15); + mainLayout->setSpacing(10); + + // Header with name and status + auto* headerLayout = new QHBoxLayout(); + + m_nameLabel->setText(m_info.name); + m_nameLabel->setWordWrap(false); + m_nameLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + auto nameFont = m_nameLabel->font(); + nameFont.setPointSize(14); + nameFont.setBold(true); + m_nameLabel->setFont(nameFont); + headerLayout->addWidget(m_nameLabel, 1); + + m_statusLabel->setProperty("class", "status-badge"); + m_statusLabel->hide(); + headerLayout->addWidget(m_statusLabel, 0); + + mainLayout->addLayout(headerLayout); + + // Description - with word wrap and proper sizing + m_descriptionLabel->setText(m_info.description); + m_descriptionLabel->setWordWrap(true); + m_descriptionLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_descriptionLabel->setMinimumHeight(40); + m_descriptionLabel->setMaximumHeight(70); + mainLayout->addWidget(m_descriptionLabel, 1); + + // Version + m_versionLabel->setText(QString("Version: %1").arg(m_info.version)); + auto versionFont = m_versionLabel->font(); + versionFont.setPointSize(9); + m_versionLabel->setFont(versionFont); + m_versionLabel->setStyleSheet("color: #888;"); + mainLayout->addWidget(m_versionLabel, 0); + + // Repository badge + m_repositoryLabel->setText(m_info.repository); + m_repositoryLabel->setProperty("class", "repo-badge"); + m_repositoryLabel->setAlignment(Qt::AlignLeft); + mainLayout->addWidget(m_repositoryLabel, 0); + + setLayout(mainLayout); +} + +void PackageCard::checkInstallStatus() { + m_isInstalled = AlpmWrapper::instance().isPackageInstalled(m_info.name); + updateInstallStatus(m_isInstalled); +} + +void PackageCard::updateInstallStatus(bool installed) { + m_isInstalled = installed; + + if (m_isInstalled) { + m_statusLabel->setText("Installed"); + m_statusLabel->show(); + } else { + m_statusLabel->hide(); + } +} + +void PackageCard::mousePressEvent(QMouseEvent* event) { + if (event->button() == Qt::LeftButton) { + emit clicked(m_info); + } + QWidget::mousePressEvent(event); +} + +void PackageCard::enterEvent(QEnterEvent* event) { + setProperty("hovered", true); + style()->unpolish(this); + style()->polish(this); + QWidget::enterEvent(event); +} + +void PackageCard::leaveEvent(QEvent* event) { + setProperty("hovered", false); + style()->unpolish(this); + style()->polish(this); + QWidget::leaveEvent(event); +} diff --git a/src/gui/package_card.h b/src/gui/package_card.h new file mode 100644 index 0000000..aaf38f6 --- /dev/null +++ b/src/gui/package_card.h @@ -0,0 +1,40 @@ +#ifndef PACKAGE_CARD_H +#define PACKAGE_CARD_H + +#include +#include +#include +#include "../utils/types.h" + +class PackageCard : public QWidget { + Q_OBJECT + +public: + explicit PackageCard(const PackageInfo& info, QWidget* parent = nullptr); + ~PackageCard() override = default; + + const PackageInfo& packageInfo() const { return m_info; } + void updateInstallStatus(bool installed); + void checkInstallStatus(); + +signals: + void clicked(const PackageInfo& info); + +protected: + void mousePressEvent(QMouseEvent* event) override; + void enterEvent(QEnterEvent* event) override; + void leaveEvent(QEvent* event) override; + +private: + void setupUi(); + + PackageInfo m_info; + QLabel* m_nameLabel; + QLabel* m_descriptionLabel; + QLabel* m_versionLabel; + QLabel* m_repositoryLabel; + QLabel* m_statusLabel; + bool m_isInstalled; +}; + +#endif // PACKAGE_CARD_H From c7daf11f050c74366ebe517268de9b0bde2335c2 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:25:27 +0000 Subject: [PATCH 18/71] show detailed information for any package and install/uninstall that package --- src/gui/package_details_dialog.cpp | 585 +++++++++++++++++++++++++++++ src/gui/package_details_dialog.h | 69 ++++ 2 files changed, 654 insertions(+) create mode 100644 src/gui/package_details_dialog.cpp create mode 100644 src/gui/package_details_dialog.h diff --git a/src/gui/package_details_dialog.cpp b/src/gui/package_details_dialog.cpp new file mode 100644 index 0000000..2d19346 --- /dev/null +++ b/src/gui/package_details_dialog.cpp @@ -0,0 +1,585 @@ +#include "package_details_dialog.h" +#include "../core/alpm_wrapper.h" +#include "../core/package_manager.h" +#include "../utils/logger.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +PackageDetailsDialog::PackageDetailsDialog(const PackageInfo& info, QWidget* parent) + : QDialog(parent) + , m_info(info) + , m_isInstalled(false) + , m_nameLabel(new QLabel(this)) + , m_versionLabel(new QLabel(this)) + , m_repositoryLabel(new QLabel(this)) + , m_maintainerLabel(new QLabel(this)) + , m_urlLabel(new QLabel(this)) + , m_descriptionText(new QTextEdit(this)) + , m_dependenciesText(new QTextEdit(this)) + , m_lastUpdatedLabel(new QLabel(this)) + , m_installButton(new QPushButton("Install", this)) + , m_uninstallButton(new QPushButton("Uninstall", this)) + , m_closeButton(new QPushButton("Close", this)) + , m_statusBadge(new QLabel(this)) + , m_progressBar(new QProgressBar(this)) + , m_progressLabel(new QLabel(this)) + , m_progressWidget(new QWidget(this)) + , m_logViewer(new QTextEdit(this)) + , m_toggleLogButton(new QPushButton("Show Logs", this)) + , m_logWidget(new QWidget(this)) + , m_logVisible(false) + , m_totalPackages(0) + , m_currentPackage(0) { + + setupUi(); + checkInstallStatus(); + updateButtonStates(); + + // Connect to PackageManager signals + connect(&PackageManager::instance(), &PackageManager::operationStarted, + this, &PackageDetailsDialog::onOperationStarted); + connect(&PackageManager::instance(), &PackageManager::operationOutput, + this, &PackageDetailsDialog::onOperationOutput); + connect(&PackageManager::instance(), &PackageManager::operationCompleted, + this, &PackageDetailsDialog::onOperationCompleted); + connect(&PackageManager::instance(), &PackageManager::operationError, + this, &PackageDetailsDialog::onOperationError); +} + +void PackageDetailsDialog::setupUi() { + setWindowTitle("Package Details"); + setMinimumSize(700, 600); + setModal(true); + + // Remove window icon + setWindowIcon(QIcon()); + + auto* dialogLayout = new QVBoxLayout(this); + dialogLayout->setContentsMargins(0, 0, 0, 0); + dialogLayout->setSpacing(0); + + // Create scroll area for content + auto* scrollArea = new QScrollArea(this); + scrollArea->setWidgetResizable(true); + scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea->setFrameShape(QFrame::NoFrame); + + // Content widget + auto* contentWidget = new QWidget(); + auto* mainLayout = new QVBoxLayout(contentWidget); + mainLayout->setContentsMargins(20, 30, 20, 20); + mainLayout->setSpacing(20); + + // Header with name and repository badge + auto* headerLayout = new QHBoxLayout(); + + m_nameLabel->setText(m_info.name); + m_nameLabel->setContentsMargins(0, 0, 0, 0); + auto nameFont = m_nameLabel->font(); + nameFont.setPointSize(20); + nameFont.setBold(true); + m_nameLabel->setFont(nameFont); + headerLayout->addWidget(m_nameLabel); + + headerLayout->addStretch(); + + // Repository badge (member so we can update it later) + m_repositoryLabel->setText(m_info.repository); + m_repositoryLabel->setProperty("class", "repo-badge"); + m_repositoryLabel->setStyleSheet("background-color: #27272a; color: #a1a1aa; " + "border-radius: 4px; padding: 6px 12px; font-size: 12px;"); + headerLayout->addWidget(m_repositoryLabel); + + // Installed status badge (hidden by default) + m_statusBadge->setText("Installed"); + m_statusBadge->setProperty("class", "status-badge"); + m_statusBadge->setStyleSheet("background-color: #16a34a; color: #ffffff; " + "border-radius: 4px; padding: 6px 10px; font-size: 12px;"); + m_statusBadge->hide(); + headerLayout->addWidget(m_statusBadge); + + mainLayout->addLayout(headerLayout); + + // Description right under the name + auto* descLabel = new QLabel(m_info.description, this); + descLabel->setWordWrap(true); + descLabel->setStyleSheet("color: #a1a1aa; font-size: 13px;"); + mainLayout->addWidget(descLabel); + + // Separator line + auto* line1 = new QFrame(this); + line1->setFrameShape(QFrame::HLine); + line1->setStyleSheet("background-color: #27272a;"); + mainLayout->addWidget(line1); + + // Package Details section - 2x2 grid layout + auto* detailsTitle = new QLabel("Package Details", this); + detailsTitle->setStyleSheet("font-size: 16px; font-weight: bold;"); + mainLayout->addWidget(detailsTitle); + + auto* infoWidget = new QWidget(this); + auto* infoGrid = new QGridLayout(infoWidget); + infoGrid->setSpacing(15); + infoGrid->setContentsMargins(0, 10, 0, 10); + infoGrid->setColumnStretch(1, 1); + infoGrid->setColumnStretch(3, 1); + + // Version (top-left) + auto* versionTitle = new QLabel("Version", this); + versionTitle->setStyleSheet("color: #a1a1aa; font-size: 12px;"); + m_versionLabel->setText(m_info.version); + m_versionLabel->setStyleSheet("font-size: 13px;"); + infoGrid->addWidget(versionTitle, 0, 0, Qt::AlignTop); + infoGrid->addWidget(m_versionLabel, 0, 1); + + // Maintainer (top-right) + if (!m_info.maintainer.isEmpty()) { + auto* maintainerTitle = new QLabel("Maintainer", this); + maintainerTitle->setStyleSheet("color: #a1a1aa; font-size: 12px;"); + m_maintainerLabel->setText(m_info.maintainer); + m_maintainerLabel->setStyleSheet("font-size: 13px;"); + infoGrid->addWidget(maintainerTitle, 0, 2, Qt::AlignTop); + infoGrid->addWidget(m_maintainerLabel, 0, 3); + } + + // Upstream URL (bottom-left) + if (!m_info.upstreamUrl.isEmpty()) { + auto* urlTitle = new QLabel("Upstream URL", this); + urlTitle->setStyleSheet("color: #a1a1aa; font-size: 12px;"); + m_urlLabel->setText(QString("%1") + .arg(m_info.upstreamUrl)); + m_urlLabel->setOpenExternalLinks(true); + m_urlLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); + m_urlLabel->setWordWrap(true); + m_urlLabel->setStyleSheet("font-size: 13px;"); + infoGrid->addWidget(urlTitle, 1, 0, Qt::AlignTop); + infoGrid->addWidget(m_urlLabel, 1, 1); + } + + // Last Updated (bottom-right) + if (!m_info.lastUpdated.isNull()) { + auto* updatedTitle = new QLabel("Last Updated", this); + updatedTitle->setStyleSheet("color: #a1a1aa; font-size: 12px;"); + m_lastUpdatedLabel->setText(m_info.lastUpdated.toString("MMM. d, yyyy, h a")); + m_lastUpdatedLabel->setStyleSheet("font-size: 13px;"); + infoGrid->addWidget(updatedTitle, 1, 2, Qt::AlignTop); + infoGrid->addWidget(m_lastUpdatedLabel, 1, 3); + } + + mainLayout->addWidget(infoWidget); + + // Separator line + auto* line2 = new QFrame(this); + line2->setFrameShape(QFrame::HLine); + line2->setStyleSheet("background-color: #27272a;"); + mainLayout->addWidget(line2); + + // Dependencies section + if (!m_info.dependList.isEmpty()) { + auto* depsTitle = new QLabel("Dependencies", this); + depsTitle->setStyleSheet("font-size: 16px; font-weight: bold;"); + mainLayout->addWidget(depsTitle); + + m_dependenciesText->setPlainText(m_info.dependList.join("\n")); + m_dependenciesText->setReadOnly(true); + m_dependenciesText->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_dependenciesText->setStyleSheet("background-color: #18181b; border: 1px solid #27272a; " + "border-radius: 6px; padding: 8px; font-size: 12px;"); + + // Adjust height to fit all dependencies without scrolling + QFontMetrics fm(m_dependenciesText->font()); + int lineHeight = fm.lineSpacing(); + int numLines = m_info.dependList.size(); + int contentHeight = (numLines * lineHeight) + 20; // +20 for padding + m_dependenciesText->setMinimumHeight(contentHeight); + m_dependenciesText->setMaximumHeight(contentHeight); + + mainLayout->addWidget(m_dependenciesText); + + // Separator line + auto* line3 = new QFrame(this); + line3->setFrameShape(QFrame::HLine); + line3->setStyleSheet("background-color: #27272a;"); + mainLayout->addWidget(line3); + } + + // Command section + auto* commandTitle = new QLabel("Command", this); + commandTitle->setStyleSheet("font-size: 16px; font-weight: bold;"); + mainLayout->addWidget(commandTitle); + + // Command buttons and text + auto* commandWidget = new QWidget(this); + auto* commandLayout = new QVBoxLayout(commandWidget); + commandLayout->setContentsMargins(0, 0, 0, 0); + commandLayout->setSpacing(10); + + // Determine which package managers to show + bool isAUR = (m_info.repository.toLower() == "aur"); + QString command; + + if (isAUR) { + // Show yay and paru for AUR + auto* buttonLayout = new QHBoxLayout(); + + auto* yayButton = new QPushButton("yay", this); + yayButton->setCheckable(true); + yayButton->setChecked(true); + yayButton->setStyleSheet("QPushButton { background-color: #27272a; color: #fafafa; " + "border: none; border-radius: 4px; padding: 6px 16px; }" + "QPushButton:checked { background-color: #3b82f6; }"); + + auto* paruButton = new QPushButton("paru", this); + paruButton->setCheckable(true); + paruButton->setStyleSheet("QPushButton { background-color: #27272a; color: #fafafa; " + "border: none; border-radius: 4px; padding: 6px 16px; }" + "QPushButton:checked { background-color: #3b82f6; }"); + + buttonLayout->addWidget(yayButton); + buttonLayout->addWidget(paruButton); + buttonLayout->addStretch(); + + commandLayout->addLayout(buttonLayout); + + command = QString("yay -S %1").arg(m_info.name); + auto* commandText = new QLabel(this); + commandText->setText(command); + commandText->setStyleSheet("background-color: #27272a; color: #fafafa; " + "border-radius: 6px; padding: 12px; font-family: monospace; font-size: 13px;"); + commandText->setTextInteractionFlags(Qt::TextSelectableByMouse); + commandLayout->addWidget(commandText); + + // Connect buttons to update command + connect(yayButton, &QPushButton::clicked, [yayButton, paruButton, commandText, this]() { + yayButton->setChecked(true); + paruButton->setChecked(false); + commandText->setText(QString("yay -S %1").arg(m_info.name)); + }); + + connect(paruButton, &QPushButton::clicked, [yayButton, paruButton, commandText, this]() { + paruButton->setChecked(true); + yayButton->setChecked(false); + commandText->setText(QString("paru -S %1").arg(m_info.name)); + }); + + } else { + // Show pacman for official repos + auto* pacmanButton = new QPushButton("pacman", this); + pacmanButton->setCheckable(true); + pacmanButton->setChecked(true); + pacmanButton->setStyleSheet("QPushButton { background-color: #3b82f6; color: #fafafa; " + "border: none; border-radius: 4px; padding: 6px 16px; }"); + commandLayout->addWidget(pacmanButton, 0, Qt::AlignLeft); + + command = QString("sudo pacman -S %1").arg(m_info.name); + auto* commandText = new QLabel(command, this); + commandText->setStyleSheet("background-color: #27272a; color: #fafafa; " + "border-radius: 6px; padding: 12px; font-family: monospace; font-size: 13px;"); + commandText->setTextInteractionFlags(Qt::TextSelectableByMouse); + commandLayout->addWidget(commandText); + } + + mainLayout->addWidget(commandWidget); + + auto* noteLabel = new QLabel("Please ensure your system meets the minimum requirements before installation.", contentWidget); + noteLabel->setStyleSheet("color: #71717a; font-size: 11px; font-style: italic;"); + noteLabel->setWordWrap(true); + mainLayout->addWidget(noteLabel); + + mainLayout->addStretch(); + + // Set content widget to scroll area + contentWidget->setLayout(mainLayout); + scrollArea->setWidget(contentWidget); + dialogLayout->addWidget(scrollArea, 1); + + // Buttons at the bottom (not scrollable) + auto* buttonWidget = new QWidget(this); + auto* buttonLayout = new QHBoxLayout(buttonWidget); + buttonLayout->setContentsMargins(20, 10, 20, 20); + buttonLayout->addStretch(); + + m_installButton->setMinimumWidth(100); + m_installButton->setMinimumHeight(35); + connect(m_installButton, &QPushButton::clicked, this, &PackageDetailsDialog::onInstall); + buttonLayout->addWidget(m_installButton); + + m_uninstallButton->setMinimumWidth(100); + m_uninstallButton->setMinimumHeight(35); + connect(m_uninstallButton, &QPushButton::clicked, this, &PackageDetailsDialog::onUninstall); + buttonLayout->addWidget(m_uninstallButton); + + m_closeButton->setMinimumWidth(100); + m_closeButton->setMinimumHeight(35); + connect(m_closeButton, &QPushButton::clicked, this, &QDialog::accept); + buttonLayout->addWidget(m_closeButton); + + dialogLayout->addWidget(buttonWidget, 0); + + // Progress bar section (hidden by default) + auto* progressLayout = new QVBoxLayout(m_progressWidget); + progressLayout->setContentsMargins(20, 0, 20, 20); + progressLayout->setSpacing(8); + + m_progressLabel->setStyleSheet("color: #a1a1aa; font-size: 12px;"); + m_progressLabel->setAlignment(Qt::AlignCenter); + progressLayout->addWidget(m_progressLabel); + + m_progressBar->setMinimumHeight(20); + m_progressBar->setMaximumHeight(20); + m_progressBar->setTextVisible(true); + m_progressBar->setFormat("%p%"); + m_progressBar->setStyleSheet( + "QProgressBar {" + " border: none;" + " border-radius: 4px;" + " background-color: #27272a;" + " color: #fafafa;" + " text-align: center;" + " font-size: 11px;" + "}" + "QProgressBar::chunk {" + " border-radius: 4px;" + " background-color: #3b82f6;" + "}" + ); + progressLayout->addWidget(m_progressBar); + + // Toggle log button + m_toggleLogButton->setStyleSheet( + "QPushButton {" + " background: none;" + " border: none;" + " color: #3b82f6;" + " text-decoration: underline;" + " font-size: 11px;" + " padding: 4px;" + "}" + "QPushButton:hover {" + " color: #60a5fa;" + "}" + ); + connect(m_toggleLogButton, &QPushButton::clicked, this, &PackageDetailsDialog::toggleLogViewer); + progressLayout->addWidget(m_toggleLogButton, 0, Qt::AlignCenter); + + m_progressWidget->hide(); + dialogLayout->addWidget(m_progressWidget, 0); + + // Log viewer section (hidden by default) + auto* logLayout = new QVBoxLayout(m_logWidget); + logLayout->setContentsMargins(20, 0, 20, 20); + logLayout->setSpacing(8); + + m_logViewer->setReadOnly(true); + m_logViewer->setMaximumHeight(200); + m_logViewer->setStyleSheet( + "QTextEdit {" + " background-color: #18181b;" + " border: 1px solid #27272a;" + " border-radius: 6px;" + " padding: 8px;" + " font-family: monospace;" + " font-size: 11px;" + " color: #a1a1aa;" + "}" + ); + logLayout->addWidget(m_logViewer); + + m_logWidget->hide(); + dialogLayout->addWidget(m_logWidget, 0); + + setLayout(dialogLayout); +} + +void PackageDetailsDialog::checkInstallStatus() { + m_isInstalled = AlpmWrapper::instance().isPackageInstalled(m_info.name); + // Update the installed badge in the header + if (m_isInstalled) { + m_statusBadge->show(); + } else { + m_statusBadge->hide(); + } +} + +void PackageDetailsDialog::updateButtonStates() { + m_installButton->setEnabled(!m_isInstalled); + m_uninstallButton->setEnabled(m_isInstalled); +} + +void PackageDetailsDialog::onInstall() { + auto reply = QMessageBox::question(this, "Install Package", + QString("Are you sure you want to install %1?").arg(m_info.name), + QMessageBox::Yes | QMessageBox::No); + + if (reply == QMessageBox::Yes) { + Logger::info(QString("Installing package: %1").arg(m_info.name)); + + // Disable buttons during operation + m_installButton->setEnabled(false); + m_uninstallButton->setEnabled(false); + m_closeButton->setEnabled(false); + + PackageManager::instance().installPackage(m_info.name, m_info.repository); + } +} + +void PackageDetailsDialog::onUninstall() { + auto reply = QMessageBox::question(this, "Uninstall Package", + QString("Are you sure you want to uninstall %1?\n\n" + "This will remove the package and skip dependency checks.") + .arg(m_info.name), + QMessageBox::Yes | QMessageBox::No); + + if (reply == QMessageBox::Yes) { + Logger::info(QString("Uninstalling package: %1").arg(m_info.name)); + + // Disable buttons during operation + m_installButton->setEnabled(false); + m_uninstallButton->setEnabled(false); + m_closeButton->setEnabled(false); + + PackageManager::instance().uninstallPackage(m_info.name, m_info.repository); + } +} + +void PackageDetailsDialog::showProgress(const QString& message) { + m_progressLabel->setText(message); + m_progressBar->setRange(0, 100); + m_progressBar->setValue(0); + m_progressWidget->show(); + m_logViewer->clear(); + m_currentOperation = message; + m_totalPackages = 0; + m_currentPackage = 0; +} + +void PackageDetailsDialog::hideProgress() { + m_progressWidget->hide(); + m_logWidget->hide(); + m_logVisible = false; + m_toggleLogButton->setText("Show Logs"); +} + +void PackageDetailsDialog::toggleLogViewer() { + m_logVisible = !m_logVisible; + if (m_logVisible) { + m_logWidget->show(); + m_toggleLogButton->setText("Hide Logs"); + } else { + m_logWidget->hide(); + m_toggleLogButton->setText("Show Logs"); + } +} + +void PackageDetailsDialog::parseProgressOutput(const QString& output) { + // Parse pacman/yay/paru output for progress information + + // Pattern: "downloading..." or "installing..." + if (output.contains("downloading", Qt::CaseInsensitive)) { + m_progressLabel->setText("Downloading packages..."); + } else if (output.contains("installing", Qt::CaseInsensitive)) { + m_progressLabel->setText("Installing packages..."); + } else if (output.contains("building", Qt::CaseInsensitive)) { + m_progressLabel->setText("Building packages..."); + } else if (output.contains("checking", Qt::CaseInsensitive)) { + m_progressLabel->setText("Checking dependencies..."); + } else if (output.contains("resolving", Qt::CaseInsensitive)) { + m_progressLabel->setText("Resolving dependencies..."); + } + + // Pattern: "(1/5)" or "( 1/5)" to track package progress + QRegularExpression packagePattern(R"(\(\s*(\d+)/(\d+)\))"); + auto match = packagePattern.match(output); + if (match.hasMatch()) { + m_currentPackage = match.captured(1).toInt(); + m_totalPackages = match.captured(2).toInt(); + + if (m_totalPackages > 0) { + int percentage = (m_currentPackage * 100) / m_totalPackages; + m_progressBar->setValue(percentage); + } + } + + // Pattern: "[##########] 100%" for download progress + QRegularExpression percentPattern(R"(\s+(\d+)%\s*)"); + auto percentMatch = percentPattern.match(output); + if (percentMatch.hasMatch()) { + int percentage = percentMatch.captured(1).toInt(); + m_progressBar->setValue(percentage); + } +} + +void PackageDetailsDialog::onOperationStarted(const QString& message) { + showProgress(message); +} + +void PackageDetailsDialog::onOperationOutput(const QString& output) { + if (output.trimmed().isEmpty()) { + return; + } + + // Add to log viewer + m_logViewer->append(output.trimmed()); + + // Auto-scroll to bottom + QTextCursor cursor = m_logViewer->textCursor(); + cursor.movePosition(QTextCursor::End); + m_logViewer->setTextCursor(cursor); + + // Parse output for progress information + parseProgressOutput(output); + + // Force UI update + m_progressLabel->repaint(); + m_progressBar->repaint(); + QCoreApplication::processEvents(); +} + +void PackageDetailsDialog::onOperationCompleted(bool success, const QString& message) { + // Refresh ALPM state so subsequent queries reflect the change + AlpmWrapper::instance().release(); + AlpmWrapper::instance().initialize(); + + // Update status and UI + checkInstallStatus(); + updateButtonStates(); + + hideProgress(); + + // Re-enable close button + m_closeButton->setEnabled(true); + + if (success) { + QMessageBox::information(this, "Success", message); + } else { + QMessageBox::warning(this, "Operation Failed", message); + } +} + +void PackageDetailsDialog::onOperationError(const QString& error) { + // Refresh ALPM state (best-effort) + AlpmWrapper::instance().release(); + AlpmWrapper::instance().initialize(); + + // Update status and UI + checkInstallStatus(); + updateButtonStates(); + + hideProgress(); + + // Re-enable close button + m_closeButton->setEnabled(true); + + QMessageBox::critical(this, "Error", error); +} diff --git a/src/gui/package_details_dialog.h b/src/gui/package_details_dialog.h new file mode 100644 index 0000000..d11ce01 --- /dev/null +++ b/src/gui/package_details_dialog.h @@ -0,0 +1,69 @@ +#ifndef PACKAGE_DETAILS_DIALOG_H +#define PACKAGE_DETAILS_DIALOG_H + +#include +#include +#include +#include +#include +#include "../utils/types.h" + +class PackageDetailsDialog : public QDialog { + Q_OBJECT + +public: + explicit PackageDetailsDialog(const PackageInfo& info, QWidget* parent = nullptr); + ~PackageDetailsDialog() override = default; + +private: + void setupUi(); + void updateButtonStates(); + void checkInstallStatus(); + void showProgress(const QString& message); + void hideProgress(); + void toggleLogViewer(); + void parseProgressOutput(const QString& output); + + PackageInfo m_info; + bool m_isInstalled; + + QLabel* m_nameLabel; + QLabel* m_versionLabel; + QLabel* m_repositoryLabel; + QLabel* m_maintainerLabel; + QLabel* m_urlLabel; + QTextEdit* m_descriptionText; + QTextEdit* m_dependenciesText; + QLabel* m_lastUpdatedLabel; + + QPushButton* m_installButton; + QPushButton* m_uninstallButton; + QPushButton* m_closeButton; + + QLabel* m_statusBadge; + + QProgressBar* m_progressBar; + QLabel* m_progressLabel; + QWidget* m_progressWidget; + + // Log viewer + QTextEdit* m_logViewer; + QPushButton* m_toggleLogButton; + QWidget* m_logWidget; + bool m_logVisible; + + // Progress tracking + QString m_currentOperation; + int m_totalPackages; + int m_currentPackage; + +private slots: + void onInstall(); + void onUninstall(); + void onOperationStarted(const QString& message); + void onOperationOutput(const QString& output); + void onOperationCompleted(bool success, const QString& message); + void onOperationError(const QString& error); +}; + +#endif // PACKAGE_DETAILS_DIALOG_H From 52d85fe9cf401ffb087849a26bca58d0a8d829e7 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:25:50 +0000 Subject: [PATCH 19/71] update all system apps --- src/gui/updates_widget.cpp | 248 +++++++++++++++++++++++++++++++++++++ src/gui/updates_widget.h | 44 +++++++ 2 files changed, 292 insertions(+) create mode 100644 src/gui/updates_widget.cpp create mode 100644 src/gui/updates_widget.h diff --git a/src/gui/updates_widget.cpp b/src/gui/updates_widget.cpp new file mode 100644 index 0000000..407af01 --- /dev/null +++ b/src/gui/updates_widget.cpp @@ -0,0 +1,248 @@ +#include "updates_widget.h" +#include "../core/alpm_wrapper.h" +#include "../core/aur_helper.h" +#include "../core/package_manager.h" +#include "../utils/logger.h" +#include +#include +#include +#include + +class UpdateItem : public QWidget { + Q_OBJECT + +public: + UpdateItem(const UpdateInfo& info, QWidget* parent = nullptr) + : QWidget(parent), m_info(info) { + + auto* layout = new QHBoxLayout(this); + layout->setContentsMargins(10, 10, 10, 10); + + auto* infoLayout = new QVBoxLayout(); + + auto* nameLabel = new QLabel(m_info.name, this); + auto nameFont = nameLabel->font(); + nameFont.setBold(true); + nameFont.setPointSize(12); + nameLabel->setFont(nameFont); + infoLayout->addWidget(nameLabel); + + auto* versionLabel = new QLabel( + QString("%1 → %2").arg(m_info.oldVersion, m_info.newVersion), this); + versionLabel->setStyleSheet("color: #888;"); + infoLayout->addWidget(versionLabel); + + auto* repoLabel = new QLabel(m_info.repository, this); + repoLabel->setStyleSheet("color: #666; font-size: 10px;"); + infoLayout->addWidget(repoLabel); + + layout->addLayout(infoLayout); + layout->addStretch(); + + if (m_info.downloadSize > 0) { + auto* sizeLabel = new QLabel(formatSize(m_info.downloadSize), this); + sizeLabel->setStyleSheet("color: #888;"); + layout->addWidget(sizeLabel); + } + + auto* updateButton = new QPushButton("Update", this); + updateButton->setMinimumWidth(100); + connect(updateButton, &QPushButton::clicked, [this]() { + emit updateRequested(m_info.name); + }); + layout->addWidget(updateButton); + + setLayout(layout); + setProperty("class", "update-item"); + } + +signals: + void updateRequested(const QString& packageName); + +private: + UpdateInfo m_info; + + QString formatSize(qint64 bytes) { + const qint64 KB = 1024; + const qint64 MB = KB * 1024; + const qint64 GB = MB * 1024; + + if (bytes >= GB) { + return QString("%1 GB").arg(bytes / static_cast(GB), 0, 'f', 2); + } else if (bytes >= MB) { + return QString("%1 MB").arg(bytes / static_cast(MB), 0, 'f', 1); + } else if (bytes >= KB) { + return QString("%1 KB").arg(bytes / static_cast(KB), 0, 'f', 0); + } + return QString("%1 B").arg(bytes); + } +}; + +UpdatesWidget::UpdatesWidget(QWidget* parent) + : QWidget(parent) + , m_scrollArea(new QScrollArea(this)) + , m_contentWidget(new QWidget()) + , m_contentLayout(new QVBoxLayout(m_contentWidget)) + , m_statusLabel(new QLabel(this)) + , m_countLabel(new QLabel(this)) + , m_updateAllButton(new QPushButton("Update All", this)) + , m_checkButton(new QPushButton("Check for Updates", this)) { + + setupUi(); + + connect(&PackageManager::instance(), &PackageManager::operationCompleted, + this, [this](bool success, const QString& message) { + if (success) { + QMessageBox::information(this, "Success", message); + checkForUpdates(); + } else { + QMessageBox::warning(this, "Error", message); + } + }); +} + +void UpdatesWidget::setupUi() { + auto* mainLayout = new QVBoxLayout(this); + + // Header + auto* headerLayout = new QHBoxLayout(); + + auto* titleLabel = new QLabel("Available Updates", this); + auto titleFont = titleLabel->font(); + titleFont.setPointSize(24); + titleFont.setBold(true); + titleLabel->setFont(titleFont); + headerLayout->addWidget(titleLabel); + + headerLayout->addStretch(); + + m_countLabel->setStyleSheet("font-size: 14px; color: #888;"); + headerLayout->addWidget(m_countLabel); + + m_checkButton->setMinimumHeight(35); + connect(m_checkButton, &QPushButton::clicked, this, &UpdatesWidget::checkForUpdates); + headerLayout->addWidget(m_checkButton); + + m_updateAllButton->setMinimumHeight(35); + m_updateAllButton->setMinimumWidth(120); + m_updateAllButton->setEnabled(false); + connect(m_updateAllButton, &QPushButton::clicked, this, &UpdatesWidget::onUpdateAll); + headerLayout->addWidget(m_updateAllButton); + + mainLayout->addLayout(headerLayout); + + // Status label + m_statusLabel->setAlignment(Qt::AlignCenter); + m_statusLabel->setText("Click 'Check for Updates' to scan for available updates"); + mainLayout->addWidget(m_statusLabel); + + // Updates area + m_scrollArea->setWidget(m_contentWidget); + m_scrollArea->setWidgetResizable(true); + m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + m_contentLayout->setSpacing(5); + m_contentLayout->setContentsMargins(10, 10, 10, 10); + m_contentLayout->addStretch(); + + mainLayout->addWidget(m_scrollArea); + setLayout(mainLayout); +} + +void UpdatesWidget::checkForUpdates() { + m_statusLabel->setText("Checking for updates..."); + m_statusLabel->show(); + m_checkButton->setEnabled(false); + m_checkButton->setText("Checking..."); + m_updateAllButton->setEnabled(false); + + clearUpdates(); + + (void)QtConcurrent::run([this]() { + auto updates = AlpmWrapper::instance().getAvailableUpdates(); + + // Also check AUR updates + AurHelper aurHelper; + auto aurUpdates = aurHelper.checkAurUpdates(); + updates.append(aurUpdates); + + QMetaObject::invokeMethod(this, [this, updates]() { + m_updates = updates; + + m_checkButton->setEnabled(true); + m_checkButton->setText("Check for Updates"); + + if (updates.isEmpty()) { + m_statusLabel->setText("Your system is up to date!"); + m_countLabel->clear(); + } else { + m_statusLabel->hide(); + m_countLabel->setText(QString("%1 updates available") + .arg(updates.size())); + m_updateAllButton->setEnabled(true); + displayUpdates(updates); + } + + Logger::info(QString("Found %1 updates").arg(updates.size())); + }, Qt::QueuedConnection); + }); +} + +void UpdatesWidget::displayUpdates(const QVector& updates) { + clearUpdates(); + + for (const auto& update : updates) { + auto* item = new UpdateItem(update, m_contentWidget); + connect(item, &UpdateItem::updateRequested, + this, &UpdatesWidget::onUpdateSingle); + m_contentLayout->insertWidget(m_contentLayout->count() - 1, item); + } +} + +void UpdatesWidget::clearUpdates() { + while (m_contentLayout->count() > 1) { + auto* item = m_contentLayout->takeAt(0); + if (auto* widget = item->widget()) { + widget->deleteLater(); + } + delete item; + } +} + +void UpdatesWidget::onUpdateAll() { + auto reply = QMessageBox::question(this, "Update All", + QString("Are you sure you want to update all %1 packages?") + .arg(m_updates.size()), + QMessageBox::Yes | QMessageBox::No); + + if (reply == QMessageBox::Yes) { + PackageManager::instance().updateAllPackages(); + } +} + +void UpdatesWidget::onUpdateSingle(const QString& packageName) { + auto reply = QMessageBox::question(this, "Update Package", + QString("Are you sure you want to update %1?").arg(packageName), + QMessageBox::Yes | QMessageBox::No); + + if (reply == QMessageBox::Yes) { + PackageManager::instance().updatePackage(packageName); + } +} + +QString UpdatesWidget::formatSize(qint64 bytes) { + const qint64 KB = 1024; + const qint64 MB = KB * 1024; + const qint64 GB = MB * 1024; + + if (bytes >= GB) { + return QString("%1 GB").arg(bytes / static_cast(GB), 0, 'f', 2); + } else if (bytes >= MB) { + return QString("%1 MB").arg(bytes / static_cast(MB), 0, 'f', 1); + } else if (bytes >= KB) { + return QString("%1 KB").arg(bytes / static_cast(KB), 0, 'f', 0); + } + return QString("%1 B").arg(bytes); +} + +#include "updates_widget.moc" diff --git a/src/gui/updates_widget.h b/src/gui/updates_widget.h new file mode 100644 index 0000000..389fc77 --- /dev/null +++ b/src/gui/updates_widget.h @@ -0,0 +1,44 @@ +#ifndef UPDATES_WIDGET_H +#define UPDATES_WIDGET_H + +#include +#include +#include +#include +#include +#include +#include "../utils/types.h" + +class UpdateItem; + +class UpdatesWidget : public QWidget { + Q_OBJECT + +public: + explicit UpdatesWidget(QWidget* parent = nullptr); + ~UpdatesWidget() override = default; + + void checkForUpdates(); + +private: + void setupUi(); + void displayUpdates(const QVector& updates); + void clearUpdates(); + QString formatSize(qint64 bytes); + + QScrollArea* m_scrollArea; + QWidget* m_contentWidget; + QVBoxLayout* m_contentLayout; + QLabel* m_statusLabel; + QLabel* m_countLabel; + QPushButton* m_updateAllButton; + QPushButton* m_checkButton; + + QVector m_updates; + +private slots: + void onUpdateAll(); + void onUpdateSingle(const QString& packageName); +}; + +#endif // UPDATES_WIDGET_H From b11315231135acf61a1f4c3a8b11649d9b054664 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:26:23 +0000 Subject: [PATCH 20/71] show installed packages tab --- src/gui/installed_widget.cpp | 173 +++++++++++++++++++++++++++++++++++ src/gui/installed_widget.h | 43 +++++++++ 2 files changed, 216 insertions(+) create mode 100644 src/gui/installed_widget.cpp create mode 100644 src/gui/installed_widget.h diff --git a/src/gui/installed_widget.cpp b/src/gui/installed_widget.cpp new file mode 100644 index 0000000..3fe8329 --- /dev/null +++ b/src/gui/installed_widget.cpp @@ -0,0 +1,173 @@ +#include "installed_widget.h" +#include "package_card.h" +#include "package_details_dialog.h" +#include "../core/alpm_wrapper.h" +#include "../utils/logger.h" +#include +#include +#include +#include + +InstalledWidget::InstalledWidget(QWidget* parent) + : QWidget(parent) + , m_filterInput(new QLineEdit(this)) + , m_scrollArea(new QScrollArea(this)) + , m_contentWidget(new QWidget()) + , m_gridLayout(new QGridLayout(m_contentWidget)) + , m_statusLabel(new QLabel(this)) + , m_countLabel(new QLabel(this)) { + + setupUi(); + loadInstalledPackages(); +} + +void InstalledWidget::setupUi() { + auto* mainLayout = new QVBoxLayout(this); + + // Header + auto* headerLayout = new QHBoxLayout(); + + auto* titleLabel = new QLabel("Installed Packages", this); + auto titleFont = titleLabel->font(); + titleFont.setPointSize(24); + titleFont.setBold(true); + titleLabel->setFont(titleFont); + headerLayout->addWidget(titleLabel); + + headerLayout->addStretch(); + + m_countLabel->setStyleSheet("font-size: 14px; color: #888;"); + headerLayout->addWidget(m_countLabel); + + auto* refreshButton = new QPushButton("Refresh", this); + connect(refreshButton, &QPushButton::clicked, this, &InstalledWidget::refreshPackages); + headerLayout->addWidget(refreshButton); + + mainLayout->addLayout(headerLayout); + + // Filter + m_filterInput->setPlaceholderText("Filter installed packages..."); + m_filterInput->setMinimumHeight(35); + connect(m_filterInput, &QLineEdit::textChanged, + this, &InstalledWidget::onFilterTextChanged); + mainLayout->addWidget(m_filterInput); + + // Status label + m_statusLabel->setAlignment(Qt::AlignCenter); + m_statusLabel->setText("Loading installed packages..."); + mainLayout->addWidget(m_statusLabel); + + // Results area + m_scrollArea->setWidget(m_contentWidget); + m_scrollArea->setWidgetResizable(true); + m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + m_gridLayout->setSpacing(15); + m_gridLayout->setContentsMargins(10, 10, 10, 10); + + mainLayout->addWidget(m_scrollArea); + setLayout(mainLayout); +} + +void InstalledWidget::loadInstalledPackages() { + m_statusLabel->setText("Loading installed packages..."); + m_statusLabel->show(); + + (void)QtConcurrent::run([this]() { + auto packages = AlpmWrapper::instance().getInstalledPackages(); + + QMetaObject::invokeMethod(this, [this, packages]() { + m_allPackages = packages; + m_filteredPackages = packages; + + m_statusLabel->hide(); + m_countLabel->setText(QString("%1 packages installed") + .arg(packages.size())); + + displayPackages(packages); + + Logger::info(QString("Loaded %1 installed packages").arg(packages.size())); + }, Qt::QueuedConnection); + }); +} + +void InstalledWidget::refreshPackages() { + clearResults(); + loadInstalledPackages(); +} + +void InstalledWidget::displayPackages(const QVector& packages) { + clearResults(); + + if (packages.isEmpty()) { + m_statusLabel->setText("No packages found"); + m_statusLabel->show(); + return; + } + + int row = 0; + int col = 0; + const int columns = 3; + + for (const auto& pkg : packages) { + auto* card = new PackageCard(pkg, m_contentWidget); + card->updateInstallStatus(true); + connect(card, &PackageCard::clicked, this, &InstalledWidget::onPackageClicked); + + m_gridLayout->addWidget(card, row, col); + + col++; + if (col >= columns) { + col = 0; + row++; + } + } + + m_gridLayout->setRowStretch(row + 1, 1); +} + +void InstalledWidget::clearResults() { + while (auto* item = m_gridLayout->takeAt(0)) { + if (auto* widget = item->widget()) { + widget->deleteLater(); + } + delete item; + } +} + +void InstalledWidget::filterPackages(const QString& query) { + if (query.isEmpty()) { + m_filteredPackages = m_allPackages; + } else { + m_filteredPackages.clear(); + QString lowerQuery = query.toLower(); + + for (const auto& pkg : m_allPackages) { + if (pkg.name.toLower().contains(lowerQuery) || + pkg.description.toLower().contains(lowerQuery)) { + m_filteredPackages.append(pkg); + } + } + } + + m_countLabel->setText(QString("%1 of %2 packages") + .arg(m_filteredPackages.size()) + .arg(m_allPackages.size())); + + displayPackages(m_filteredPackages); +} + +void InstalledWidget::onFilterTextChanged(const QString& text) { + filterPackages(text); +} + +void InstalledWidget::onPackageClicked(const PackageInfo& info) { + Logger::info(QString("Package clicked: %1").arg(info.name)); + + auto* dialog = new PackageDetailsDialog(info, this); + dialog->exec(); + dialog->deleteLater(); + + // Refresh after dialog closes in case package was uninstalled + refreshPackages(); +} diff --git a/src/gui/installed_widget.h b/src/gui/installed_widget.h new file mode 100644 index 0000000..1e2bc67 --- /dev/null +++ b/src/gui/installed_widget.h @@ -0,0 +1,43 @@ +#ifndef INSTALLED_WIDGET_H +#define INSTALLED_WIDGET_H + +#include +#include +#include +#include +#include +#include +#include "../utils/types.h" + +class InstalledWidget : public QWidget { + Q_OBJECT + +public: + explicit InstalledWidget(QWidget* parent = nullptr); + ~InstalledWidget() override = default; + + void refreshPackages(); + +private: + void setupUi(); + void loadInstalledPackages(); + void displayPackages(const QVector& packages); + void filterPackages(const QString& query); + void clearResults(); + + QLineEdit* m_filterInput; + QScrollArea* m_scrollArea; + QWidget* m_contentWidget; + QGridLayout* m_gridLayout; + QLabel* m_statusLabel; + QLabel* m_countLabel; + + QVector m_allPackages; + QVector m_filteredPackages; + +private slots: + void onPackageClicked(const PackageInfo& info); + void onFilterTextChanged(const QString& text); +}; + +#endif // INSTALLED_WIDGET_H From a36288e46b35ecd6952229bf27331b1e87868c54 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:27:04 +0000 Subject: [PATCH 21/71] data types for packages --- src/utils/types.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/utils/types.h diff --git a/src/utils/types.h b/src/utils/types.h new file mode 100644 index 0000000..d4907f8 --- /dev/null +++ b/src/utils/types.h @@ -0,0 +1,43 @@ +#ifndef TYPES_H +#define TYPES_H + +#include +#include +#include +#include + +struct PackageInfo { + QString name; + QString version; + QString description; + QString repository; + QString maintainer; + QString upstreamUrl; + QStringList dependList; + QDateTime lastUpdated; + + PackageInfo() = default; + + PackageInfo(const QString& name, const QString& version, + const QString& description, const QString& repository) + : name(name), version(version), description(description), + repository(repository) {} +}; + +struct UpdateInfo { + QString name; + QString oldVersion; + QString newVersion; + QString repository; + qint64 downloadSize; + + UpdateInfo() : downloadSize(0) {} + + UpdateInfo(const QString& name, const QString& oldVersion, + const QString& newVersion, const QString& repository, + qint64 downloadSize = 0) + : name(name), oldVersion(oldVersion), newVersion(newVersion), + repository(repository), downloadSize(downloadSize) {} +}; + +#endif // TYPES_H From 8be5b1f55050b065407c3cb93fffefa3fa561234 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:28:17 +0000 Subject: [PATCH 22/71] rewrite readme for qt6 version --- README.md | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 251 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ed259fc..2001077 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,258 @@ -# README +# ALG App Store - Qt6/C++ Version -## About +A modern, native package manager for Arch Linux built with Qt6 and C++17. This is a complete rewrite of the original Wails-based application. -About your template +## Features -## Live Development +- **Search Packages**: Search through official Arch repositories (core, extra) and AUR +- **View Installed Packages**: Browse and manage installed packages +- **Check for Updates**: View available updates for both official and AUR packages +- **Package Management**: Install, uninstall, and update packages +- **Modern UI**: Clean, dark-themed interface with responsive design +- **Smart Helper Detection**: Automatically detects and uses yay, paru, or falls back to pacman +- **Thread-Safe**: Uses modern C++ threading features for safe concurrent operations +- **Comprehensive Logging**: Built-in logger for debugging and monitoring -To run in live development mode, run `wails dev` in the project directory. In another terminal, go into the `frontend` -directory and run `npm run dev`. The frontend dev server will run on http://localhost:34115. Connect to this in your -browser and connect to your application. +## Technology Stack + +- **Language**: C++17 +- **GUI Framework**: Qt6 (Widgets) +- **Package Management**: libalpm (Arch Linux Package Manager library) +- **AUR Integration**: AUR RPC API via Qt Network +- **Build System**: CMake +- **Threading**: Qt Concurrent & STL threading + +## Prerequisites + +### Build Dependencies + +```bash +sudo pacman -S base-devel cmake qt6-base qt6-svg pkgconf +``` + +### Runtime Dependencies + +```bash +sudo pacman -S qt6-base libalpm polkit curl +# Optional but recommended: +sudo pacman -S yay # or paru +``` ## Building -To build a redistributable, production mode package, use `wails build`. +1. Clone the repository: +```bash +git clone https://github.com/arch-linux-gui/alg-app-store.git +cd alg-app-store +``` + +2. Create build directory: +```bash +mkdir build +cd build +``` + +3. Configure with CMake: +```bash +cmake .. +``` + +4. Build: +```bash +make -j$(nproc) +``` + +5. Install (optional): +```bash +sudo make install +``` + +## Running + +### From Build Directory + +```bash +./build/alg-app-store +``` + +### From System Installation + +```bash +alg-app-store +``` + +## Architecture + +### Directory Structure + +``` +src/ +├── core/ # Backend logic +│ ├── alpm_wrapper.cpp/h # libalpm wrapper +│ ├── aur_helper.cpp/h # AUR search/integration +│ └── package_manager.cpp/h # Package operations +├── gui/ # Qt Widgets UI +│ ├── mainwindow.cpp/h +│ ├── home_widget.cpp/h +│ ├── search_widget.cpp/h +│ ├── installed_widget.cpp/h +│ ├── updates_widget.cpp/h +│ ├── package_card.cpp/h +│ └── package_details_dialog.cpp/h +├── utils/ # Utilities +│ ├── logger.h # Logging system +│ └── types.h # Data structures +└── main.cpp # Entry point +``` + +### Key Components + +#### AlpmWrapper (Singleton) +Wraps libalpm functionality with thread-safe operations: +- Package searching +- Installed package enumeration +- Update detection +- Package information retrieval + +#### AurHelper +Handles AUR integration: +- Package search via AUR RPC API +- Package information retrieval +- Update checking for AUR packages + +#### PackageManager (Singleton) +Manages package operations with proper privilege escalation: +- Install/uninstall packages +- Update operations +- Automatic helper detection (yay/paru/pacman) +- Process management with signals + +#### GUI Components +- **MainWindow**: Tabbed interface container +- **HomeWidget**: Featured packages display +- **SearchWidget**: Package search with filtering +- **InstalledWidget**: Installed package browser +- **UpdatesWidget**: Update management +- **PackageCard**: Reusable package display widget +- **PackageDetailsDialog**: Detailed package information + +## Design Decisions + +### Modern C++ Features + +- **Smart Pointers**: `std::unique_ptr` and `std::shared_ptr` for automatic memory management +- **Move Semantics**: `std::move()` for efficient resource transfer +- **Auto Type Deduction**: Cleaner, more maintainable code +- **Range-based Loops**: Cleaner iteration +- **Lambda Functions**: Inline callbacks and signal connections + +### Thread Safety + +- **Mutexes**: `std::mutex` and `std::lock_guard` for critical sections +- **Qt Concurrent**: `QtConcurrent::run()` for background operations +- **Signal/Slot**: Qt's thread-safe communication mechanism + +### Singleton Pattern + +Used for `AlpmWrapper` and `PackageManager` to ensure: +- Single libalpm handle instance +- Centralized package operation management +- Thread-safe access + +## Logging + +The application includes a comprehensive logging system: + +```cpp +Logger::info("Information message"); +Logger::warning("Warning message"); +Logger::error("Error message"); +Logger::debug("Debug message"); +``` + +Logs are output to standard output and can be redirected for persistent logging. + +## Package Helper Detection + +The application automatically detects available package helpers in this order: + +1. **yay** - Preferred for AUR support +2. **paru** - Alternative AUR helper +3. **pacman** - Fallback (official repos only) + +## Privilege Escalation + +Package operations require root privileges. The application uses `pkexec` (PolicyKit) for secure privilege escalation. Ensure PolicyKit is properly configured on your system. + +## Contributing + +Contributions are welcome! Please ensure: + +- Code follows C++17 standards +- Proper error handling and logging +- Thread safety for concurrent operations +- Qt best practices for GUI code +- Comments for complex logic + +## License + +This project is part of the Arch Linux GUI project. + +## Credits + +- **Original Project**: Wails-based ALG App Store +- **Rewrite**: Qt6/C++ implementation +- **Community**: Arch Linux and Qt communities + +## Troubleshooting + +### Build Issues + +**Missing Qt6**: +```bash +sudo pacman -S qt6-base qt6-svg +``` + +**Missing libalpm**: +```bash +sudo pacman -S pacman +``` + +### Runtime Issues + +**Permission Denied**: +Ensure PolicyKit is running: +```bash +systemctl status polkit +``` + +**Package Helper Not Found**: +Install yay or paru: +```bash +sudo pacman -S yay +``` + +**ALPM Initialization Failed**: +Check pacman configuration: +```bash +sudo pacman -Syy +``` + +## Future Enhancements + +- Package categories/tags +- Package ratings and reviews +- Automated testing suite +- Flatpak integration +- AppImage support +- Configuration file support +- Multi-language support +- Package download progress +- Transaction history +- Dependency visualization + +## Contact + +For issues, questions, or contributions, please visit: +- GitHub: https://github.com/arch-linux-gui/alg-app-store +- Website: https://archlinuxgui.in From 4b6c5a8f66fbad35e0af2c22fedc681d80bafefa Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:35:07 +0000 Subject: [PATCH 23/71] clang format --- .clang-format | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..36a3128 --- /dev/null +++ b/.clang-format @@ -0,0 +1,34 @@ +BasedOnStyle: WebKit + +AlignAfterOpenBracket: Align +AlignEscapedNewlines: DontAlign +AllowAllParametersOfDeclarationOnNextLine: "false" +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: "false" +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: "false" +AlwaysBreakAfterReturnType: TopLevelDefinitions +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: "false" +BinPackParameters: "false" +BreakBeforeBraces: Allman +BreakBeforeTernaryOperators: "true" +BreakConstructorInitializers: BeforeComma +ColumnLimit: 120 +Cpp11BracedListStyle: "false" +FixNamespaceComments: "true" +IncludeBlocks: Preserve +IndentWidth: "4" +InsertBraces: "true" +MaxEmptyLinesToKeep: "2" +NamespaceIndentation: None +PointerAlignment: Left +ReflowComments: "false" +SortIncludes: "true" +SpaceAfterCStyleCast: "false" +SpaceInEmptyBlock: "false" +SpacesBeforeTrailingComments: "2" +SpacesInAngles: "true" +SpacesInParentheses: "true" +SpacesInSquareBrackets: "true" +Standard: c++17 \ No newline at end of file From 9d88f1c38052c72a9c814a6948bf1f4e6d5285bb Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 16:38:23 +0000 Subject: [PATCH 24/71] remove dir-struct from readme --- README.md | 46 +++++----------------------------------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 2001077..c622329 100644 --- a/README.md +++ b/README.md @@ -46,26 +46,13 @@ git clone https://github.com/arch-linux-gui/alg-app-store.git cd alg-app-store ``` -2. Create build directory: +2. Run Build Script ```bash -mkdir build -cd build +# This will create a build directory. +./build.sh ``` -3. Configure with CMake: -```bash -cmake .. -``` - -4. Build: -```bash -make -j$(nproc) -``` - -5. Install (optional): -```bash -sudo make install -``` +Binary will be in the build directory. ## Running @@ -75,35 +62,12 @@ sudo make install ./build/alg-app-store ``` -### From System Installation +### From System Installation (if installed) ```bash alg-app-store ``` -## Architecture - -### Directory Structure - -``` -src/ -├── core/ # Backend logic -│ ├── alpm_wrapper.cpp/h # libalpm wrapper -│ ├── aur_helper.cpp/h # AUR search/integration -│ └── package_manager.cpp/h # Package operations -├── gui/ # Qt Widgets UI -│ ├── mainwindow.cpp/h -│ ├── home_widget.cpp/h -│ ├── search_widget.cpp/h -│ ├── installed_widget.cpp/h -│ ├── updates_widget.cpp/h -│ ├── package_card.cpp/h -│ └── package_details_dialog.cpp/h -├── utils/ # Utilities -│ ├── logger.h # Logging system -│ └── types.h # Data structures -└── main.cpp # Entry point -``` ### Key Components From ba5de3be582f37a00cb99c351812273354b4ed5f Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 17:03:22 +0000 Subject: [PATCH 25/71] add settings tab --- CMakeLists.txt | 2 + src/gui/mainwindow.cpp | 10 + src/gui/mainwindow.h | 2 + src/gui/settings_widget.cpp | 397 ++++++++++++++++++++++++++++++++++++ src/gui/settings_widget.h | 54 +++++ 5 files changed, 465 insertions(+) create mode 100644 src/gui/settings_widget.cpp create mode 100644 src/gui/settings_widget.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6268a7c..6148f4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ set(SOURCES src/gui/search_widget.cpp src/gui/installed_widget.cpp src/gui/updates_widget.cpp + src/gui/settings_widget.cpp src/gui/package_card.cpp src/gui/package_details_dialog.cpp ) @@ -62,6 +63,7 @@ set(HEADERS src/gui/search_widget.h src/gui/installed_widget.h src/gui/updates_widget.h + src/gui/settings_widget.h src/gui/package_card.h src/gui/package_details_dialog.h ) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 0eefeeb..d1cf994 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -3,6 +3,7 @@ #include "search_widget.h" #include "installed_widget.h" #include "updates_widget.h" +#include "settings_widget.h" #include "../utils/logger.h" #include "../core/alpm_wrapper.h" #include @@ -44,12 +45,21 @@ void MainWindow::setupUi() { m_searchWidget = new SearchWidget(this); m_installedWidget = new InstalledWidget(this); m_updatesWidget = new UpdatesWidget(this); + m_settingsWidget = new SettingsWidget(this); // Add tabs m_tabWidget->addTab(m_homeWidget, "Home"); m_tabWidget->addTab(m_searchWidget, "Search"); m_tabWidget->addTab(m_installedWidget, "Installed"); m_tabWidget->addTab(m_updatesWidget, "Updates"); + m_tabWidget->addTab(m_settingsWidget, "Settings"); + + // Connect settings signals + connect(m_settingsWidget, &SettingsWidget::multilibStatusChanged, + m_searchWidget, &SearchWidget::updateRepositoryList); + + // Initialize search widget with current multilib state + m_searchWidget->updateRepositoryList(m_settingsWidget->isMultilibEnabled()); m_tabWidget->setTabPosition(QTabWidget::North); m_tabWidget->setMovable(false); diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index 2d1cb4c..3f2b4f7 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -10,6 +10,7 @@ class HomeWidget; class SearchWidget; class InstalledWidget; class UpdatesWidget; +class SettingsWidget; class MainWindow : public QMainWindow { Q_OBJECT @@ -28,6 +29,7 @@ class MainWindow : public QMainWindow { SearchWidget* m_searchWidget; InstalledWidget* m_installedWidget; UpdatesWidget* m_updatesWidget; + SettingsWidget* m_settingsWidget; }; #endif // MAINWINDOW_H diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp new file mode 100644 index 0000000..b48fce0 --- /dev/null +++ b/src/gui/settings_widget.cpp @@ -0,0 +1,397 @@ +#include "settings_widget.h" +#include "../utils/logger.h" +#include +#include +#include +#include +#include +#include + +SettingsWidget::SettingsWidget(QWidget* parent) + : QWidget(parent) + , m_repositoryGroup(nullptr) + , m_coreRepoCheckbox(nullptr) + , m_extraRepoCheckbox(nullptr) + , m_multilibRepoCheckbox(nullptr) + , m_applyButton(nullptr) + , m_revertButton(nullptr) + , m_statusLabel(nullptr) + , m_originalMultilibState(false) { + + setupUi(); + loadCurrentSettings(); + + Logger::info("SettingsWidget created successfully"); +} + +void SettingsWidget::setupUi() { + auto* mainLayout = new QVBoxLayout(this); + mainLayout->setSpacing(20); + + // Title + auto* titleLabel = new QLabel("Settings", this); + auto titleFont = titleLabel->font(); + titleFont.setPointSize(24); + titleFont.setBold(true); + titleLabel->setFont(titleFont); + mainLayout->addWidget(titleLabel); + + // Repository Settings + createRepositorySettings(); + mainLayout->addWidget(m_repositoryGroup); + + // Status label + m_statusLabel = new QLabel(this); + m_statusLabel->setAlignment(Qt::AlignCenter); + m_statusLabel->setStyleSheet("QLabel { color: #0066cc; padding: 10px; }"); + m_statusLabel->hide(); + mainLayout->addWidget(m_statusLabel); + + // Buttons + auto* buttonLayout = new QHBoxLayout(); + buttonLayout->addStretch(); + + m_revertButton = new QPushButton("Revert", this); + m_revertButton->setMinimumWidth(100); + m_revertButton->setEnabled(false); + connect(m_revertButton, &QPushButton::clicked, this, &SettingsWidget::onRevertClicked); + buttonLayout->addWidget(m_revertButton); + + m_applyButton = new QPushButton("Apply", this); + m_applyButton->setMinimumWidth(100); + m_applyButton->setEnabled(false); + connect(m_applyButton, &QPushButton::clicked, this, &SettingsWidget::onApplyClicked); + buttonLayout->addWidget(m_applyButton); + + mainLayout->addLayout(buttonLayout); + + // Add stretch at the bottom + mainLayout->addStretch(); + + setLayout(mainLayout); +} + +void SettingsWidget::createRepositorySettings() { + m_repositoryGroup = new QGroupBox("Package Repositories", this); + auto* repoLayout = new QVBoxLayout(m_repositoryGroup); + + // Description + auto* descLabel = new QLabel( + "Select which package repositories to use for searching and installing packages.\n" + "Core and Extra repositories are required and cannot be disabled.", + this); + descLabel->setWordWrap(true); + descLabel->setStyleSheet("QLabel { color: #666; margin-bottom: 10px; }"); + repoLayout->addWidget(descLabel); + + // Core repository (always enabled, cannot be disabled) + m_coreRepoCheckbox = new QCheckBox("Core - Essential system packages", this); + m_coreRepoCheckbox->setChecked(true); + m_coreRepoCheckbox->setEnabled(false); + m_coreRepoCheckbox->setToolTip("Core repository is required and cannot be disabled"); + repoLayout->addWidget(m_coreRepoCheckbox); + + // Extra repository (always enabled, cannot be disabled) + m_extraRepoCheckbox = new QCheckBox("Extra - Additional official packages", this); + m_extraRepoCheckbox->setChecked(true); + m_extraRepoCheckbox->setEnabled(false); + m_extraRepoCheckbox->setToolTip("Extra repository is required and cannot be disabled"); + repoLayout->addWidget(m_extraRepoCheckbox); + + // Multilib repository (optional, can be enabled/disabled) + m_multilibRepoCheckbox = new QCheckBox("Multilib - 32-bit packages on x86_64", this); + m_multilibRepoCheckbox->setToolTip( + "Enable multilib repository for 32-bit applications on 64-bit systems.\n" + "This modifies /etc/pacman.conf and requires administrator privileges."); + connect(m_multilibRepoCheckbox, &QCheckBox::checkStateChanged, + this, &SettingsWidget::onSettingsChanged); + repoLayout->addWidget(m_multilibRepoCheckbox); + + // Info label + auto* infoLabel = new QLabel( + "Note: Changes to repositories require modifying system configuration files " + "and may require administrator privileges.", + this); + infoLabel->setWordWrap(true); + infoLabel->setStyleSheet("QLabel { color: #888; font-style: italic; margin-top: 10px; }"); + repoLayout->addWidget(infoLabel); + + m_repositoryGroup->setLayout(repoLayout); +} + +void SettingsWidget::loadCurrentSettings() { + // Check if multilib is currently enabled + bool multilibEnabled = isMultilibEnabledInPacmanConf(); + m_multilibRepoCheckbox->setChecked(multilibEnabled); + m_originalMultilibState = multilibEnabled; + + Logger::info(QString("Loaded settings: multilib=%1").arg(multilibEnabled ? "enabled" : "disabled")); +} + +bool SettingsWidget::isMultilibEnabledInPacmanConf() const { + QFile file("/etc/pacman.conf"); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + Logger::error("Failed to open /etc/pacman.conf for reading"); + return false; + } + + QTextStream in(&file); + bool inMultilibSection = false; + + while (!in.atEnd()) { + QString line = in.readLine().trimmed(); + + // Check for [multilib] section header + if (line == "[multilib]") { + inMultilibSection = true; + continue; + } + + // If we found [multilib] section, check if it's not commented + if (inMultilibSection && !line.isEmpty() && !line.startsWith("#")) { + // If we find Include directive, multilib is enabled + if (line.startsWith("Include")) { + file.close(); + return true; + } + } + + // If we hit another section, stop + if (inMultilibSection && line.startsWith("[") && line != "[multilib]") { + break; + } + } + + file.close(); + return false; +} + +bool SettingsWidget::enableMultilibInPacmanConf() { + QFile file("/etc/pacman.conf"); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + Logger::error("Failed to open /etc/pacman.conf for reading"); + return false; + } + + QStringList lines; + QTextStream in(&file); + bool multilibSectionFound = false; + + while (!in.atEnd()) { + QString line = in.readLine(); + + // Check if this is a commented [multilib] section + if (line.trimmed() == "#[multilib]") { + lines.append("[multilib]"); + multilibSectionFound = true; + } + // Check if the Include line in multilib section is commented + else if (multilibSectionFound && line.trimmed().startsWith("#Include") && + line.contains("mirrorlist")) { + lines.append(line.mid(1)); // Remove the # comment character + multilibSectionFound = false; // Reset flag after processing + } + else { + lines.append(line); + } + } + file.close(); + + // Write back to file using pkexec for elevated privileges + QString tempFile = "/tmp/pacman.conf.tmp"; + QFile temp(tempFile); + if (!temp.open(QIODevice::WriteOnly | QIODevice::Text)) { + Logger::error("Failed to create temporary file"); + return false; + } + + QTextStream out(&temp); + for (const QString& line : lines) { + out << line << "\n"; + } + temp.close(); + + // Use pkexec to copy the file with elevated privileges + QProcess process; + process.start("pkexec", QStringList() << "cp" << tempFile << "/etc/pacman.conf"); + process.waitForFinished(30000); // 30 second timeout + + if (process.exitCode() != 0) { + Logger::error("Failed to update pacman.conf with elevated privileges"); + QFile::remove(tempFile); + return false; + } + + QFile::remove(tempFile); + Logger::info("Successfully enabled multilib repository"); + return true; +} + +bool SettingsWidget::disableMultilibInPacmanConf() { + QFile file("/etc/pacman.conf"); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + Logger::error("Failed to open /etc/pacman.conf for reading"); + return false; + } + + QStringList lines; + QTextStream in(&file); + bool inMultilibSection = false; + + while (!in.atEnd()) { + QString line = in.readLine(); + QString trimmedLine = line.trimmed(); + + // Check if this is [multilib] section + if (trimmedLine == "[multilib]") { + lines.append("#[multilib]"); + inMultilibSection = true; + } + // Check if we're in multilib section and this is the Include line + else if (inMultilibSection && trimmedLine.startsWith("Include") && + trimmedLine.contains("mirrorlist")) { + lines.append("#" + line); + inMultilibSection = false; + } + // Check if we hit another section + else if (trimmedLine.startsWith("[") && trimmedLine != "[multilib]") { + lines.append(line); + inMultilibSection = false; + } + else { + lines.append(line); + } + } + file.close(); + + // Write back to file using pkexec for elevated privileges + QString tempFile = "/tmp/pacman.conf.tmp"; + QFile temp(tempFile); + if (!temp.open(QIODevice::WriteOnly | QIODevice::Text)) { + Logger::error("Failed to create temporary file"); + return false; + } + + QTextStream out(&temp); + for (const QString& line : lines) { + out << line << "\n"; + } + temp.close(); + + // Use pkexec to copy the file with elevated privileges + QProcess process; + process.start("pkexec", QStringList() << "cp" << tempFile << "/etc/pacman.conf"); + process.waitForFinished(30000); // 30 second timeout + + if (process.exitCode() != 0) { + Logger::error("Failed to update pacman.conf with elevated privileges"); + QFile::remove(tempFile); + return false; + } + + QFile::remove(tempFile); + Logger::info("Successfully disabled multilib repository"); + return true; +} + +void SettingsWidget::onSettingsChanged() { + // Enable apply and revert buttons when settings change + bool hasChanges = (m_multilibRepoCheckbox->isChecked() != m_originalMultilibState); + m_applyButton->setEnabled(hasChanges); + m_revertButton->setEnabled(hasChanges); + m_statusLabel->hide(); +} + +void SettingsWidget::onApplyClicked() { + bool currentMultilibState = m_multilibRepoCheckbox->isChecked(); + bool success = false; + + if (currentMultilibState != m_originalMultilibState) { + // Show confirmation dialog + QString message; + if (currentMultilibState) { + message = "This will enable the multilib repository by modifying /etc/pacman.conf.\n" + "You will be prompted for administrator privileges.\n\n" + "After enabling, you should run 'sudo pacman -Sy' to sync the databases.\n\n" + "Do you want to continue?"; + } else { + message = "This will disable the multilib repository by modifying /etc/pacman.conf.\n" + "You will be prompted for administrator privileges.\n\n" + "Do you want to continue?"; + } + + auto reply = QMessageBox::question(this, "Confirm Repository Change", + message, + QMessageBox::Yes | QMessageBox::No); + + if (reply != QMessageBox::Yes) { + return; + } + + // Apply the change + if (currentMultilibState) { + success = enableMultilibInPacmanConf(); + } else { + success = disableMultilibInPacmanConf(); + } + + if (success) { + m_originalMultilibState = currentMultilibState; + m_statusLabel->setText("Settings applied successfully! Please sync package databases."); + m_statusLabel->setStyleSheet("QLabel { color: #00aa00; padding: 10px; font-weight: bold; }"); + m_statusLabel->show(); + + m_applyButton->setEnabled(false); + m_revertButton->setEnabled(false); + + // Emit signal to notify other widgets + emit multilibStatusChanged(currentMultilibState); + + // Suggest database sync + auto reply = QMessageBox::question(this, "Sync Package Database", + "Would you like to sync the package database now?\n" + "(This will run 'pkexec pacman -Sy')", + QMessageBox::Yes | QMessageBox::No); + + if (reply == QMessageBox::Yes) { + QProcess process; + m_statusLabel->setText("Syncing package databases..."); + process.start("pkexec", QStringList() << "pacman" << "-Sy"); + process.waitForFinished(60000); // 60 second timeout + + if (process.exitCode() == 0) { + m_statusLabel->setText("Package databases synced successfully!"); + Logger::info("Package databases synced after repository change"); + } else { + m_statusLabel->setText("Failed to sync package databases. Please run 'sudo pacman -Sy' manually."); + m_statusLabel->setStyleSheet("QLabel { color: #aa0000; padding: 10px; }"); + } + } + } else { + m_statusLabel->setText("Failed to apply settings. Please check permissions."); + m_statusLabel->setStyleSheet("QLabel { color: #aa0000; padding: 10px; }"); + m_statusLabel->show(); + } + } +} + +void SettingsWidget::onRevertClicked() { + // Revert to original state + m_multilibRepoCheckbox->setChecked(m_originalMultilibState); + m_applyButton->setEnabled(false); + m_revertButton->setEnabled(false); + m_statusLabel->setText("Changes reverted"); + m_statusLabel->setStyleSheet("QLabel { color: #0066cc; padding: 10px; }"); + m_statusLabel->show(); + + Logger::info("Settings reverted to original state"); +} + +bool SettingsWidget::isMultilibEnabled() const { + return m_multilibRepoCheckbox->isChecked() && + (m_multilibRepoCheckbox->isChecked() == m_originalMultilibState); +} + +void SettingsWidget::applySettings() { + onApplyClicked(); +} diff --git a/src/gui/settings_widget.h b/src/gui/settings_widget.h new file mode 100644 index 0000000..f200a3c --- /dev/null +++ b/src/gui/settings_widget.h @@ -0,0 +1,54 @@ +#ifndef SETTINGS_WIDGET_H +#define SETTINGS_WIDGET_H + +#include +#include +#include +#include +#include +#include + +class SettingsWidget : public QWidget { + Q_OBJECT + +public: + explicit SettingsWidget(QWidget* parent = nullptr); + ~SettingsWidget() override = default; + + bool isMultilibEnabled() const; + +signals: + void multilibStatusChanged(bool enabled); + +private: + void setupUi(); + void loadCurrentSettings(); + void createRepositorySettings(); + bool isMultilibEnabledInPacmanConf() const; + bool enableMultilibInPacmanConf(); + bool disableMultilibInPacmanConf(); + void applySettings(); + + // Repository settings + QGroupBox* m_repositoryGroup; + QCheckBox* m_coreRepoCheckbox; + QCheckBox* m_extraRepoCheckbox; + QCheckBox* m_multilibRepoCheckbox; + + // Control buttons + QPushButton* m_applyButton; + QPushButton* m_revertButton; + + // Status + QLabel* m_statusLabel; + + // Track original state + bool m_originalMultilibState; + +private slots: + void onApplyClicked(); + void onRevertClicked(); + void onSettingsChanged(); +}; + +#endif // SETTINGS_WIDGET_H From 4207065f87d3552ac00851cfeac884b169ab3109 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 17:29:37 +0000 Subject: [PATCH 26/71] show logs regardless of operation success --- src/core/alpm_wrapper.cpp | 73 +++++++++++++++++++++++++++++- src/core/alpm_wrapper.h | 2 + src/gui/package_details_dialog.cpp | 12 +++-- src/gui/search_widget.cpp | 42 +++++++++++++++++ src/gui/search_widget.h | 3 ++ src/gui/settings_widget.cpp | 7 +++ 6 files changed, 133 insertions(+), 6 deletions(-) diff --git a/src/core/alpm_wrapper.cpp b/src/core/alpm_wrapper.cpp index 10c8c46..2d19d83 100644 --- a/src/core/alpm_wrapper.cpp +++ b/src/core/alpm_wrapper.cpp @@ -1,6 +1,8 @@ #include "alpm_wrapper.h" #include "../utils/logger.h" #include +#include +#include #include AlpmWrapper& AlpmWrapper::instance() { @@ -32,14 +34,16 @@ bool AlpmWrapper::initialize() { return false; } - // Register sync databases - QStringList repos = {"core", "extra"}; + // Register sync databases - read from enabled repositories + QStringList repos = getEnabledRepositories(); for (const auto& repo : repos) { alpm_db_t* db = alpm_register_syncdb(m_handle, repo.toStdString().c_str(), ALPM_SIG_USE_DEFAULT); if (!db) { Logger::warning(QString("Failed to register sync db: %1").arg(repo)); + } else { + Logger::info(QString("Registered sync db: %1").arg(repo)); } } @@ -277,3 +281,68 @@ QStringList AlpmWrapper::convertDependList(alpm_list_t* deps) { return result; } + +QStringList AlpmWrapper::getEnabledRepositories() const { + QStringList repos; + + // Read /etc/pacman.conf to find enabled repositories + QFile file("/etc/pacman.conf"); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + Logger::error("Failed to open /etc/pacman.conf"); + // Return default repositories + return {"core", "extra"}; + } + + QTextStream in(&file); + while (!in.atEnd()) { + QString line = in.readLine().trimmed(); + + // Check for repository sections (not commented out) + if (line.startsWith("[") && line.endsWith("]") && !line.startsWith("#")) { + QString repo = line.mid(1, line.length() - 2); + + // Filter out non-repository sections + if (repo != "options" && repo != "testing" && repo != "core-testing" && + repo != "extra-testing" && repo != "multilib-testing") { + repos.append(repo); + } + } + } + + file.close(); + + // Ensure core and extra are always present + if (!repos.contains("core")) { + repos.prepend("core"); + } + if (!repos.contains("extra")) { + repos.insert(1, "extra"); + } + + Logger::info(QString("Enabled repositories: %1").arg(repos.join(", "))); + return repos; +} + +void AlpmWrapper::refreshDatabases() { + std::lock_guard lock(m_mutex); + + if (!m_initialized) { + Logger::error("ALPM not initialized"); + return; + } + + // Release current handle + if (m_handle) { + alpm_release(m_handle); + m_handle = nullptr; + m_syncDbs = nullptr; + m_initialized = false; + } + + // Re-initialize to pick up new repositories + m_mutex.unlock(); + initialize(); + m_mutex.lock(); + + Logger::info("ALPM databases refreshed"); +} diff --git a/src/core/alpm_wrapper.h b/src/core/alpm_wrapper.h index 010e960..e0894b9 100644 --- a/src/core/alpm_wrapper.h +++ b/src/core/alpm_wrapper.h @@ -23,6 +23,7 @@ class AlpmWrapper { bool initialize(); void release(); + void refreshDatabases(); QVector searchPackages(const QString& query); QVector getInstalledPackages(); @@ -41,6 +42,7 @@ class AlpmWrapper { QStringList convertDependList(alpm_list_t* deps); void searchInDatabase(alpm_db_t* db, const QString& query, QVector& results); + QStringList getEnabledRepositories() const; }; #endif // ALPM_WRAPPER_H diff --git a/src/gui/package_details_dialog.cpp b/src/gui/package_details_dialog.cpp index 2d19346..b97f664 100644 --- a/src/gui/package_details_dialog.cpp +++ b/src/gui/package_details_dialog.cpp @@ -458,6 +458,8 @@ void PackageDetailsDialog::showProgress(const QString& message) { m_progressBar->setRange(0, 100); m_progressBar->setValue(0); m_progressWidget->show(); + m_progressBar->show(); + m_progressLabel->show(); m_logViewer->clear(); m_currentOperation = message; m_totalPackages = 0; @@ -465,10 +467,12 @@ void PackageDetailsDialog::showProgress(const QString& message) { } void PackageDetailsDialog::hideProgress() { - m_progressWidget->hide(); - m_logWidget->hide(); - m_logVisible = false; - m_toggleLogButton->setText("Show Logs"); + // Hide the progress bar and label, but keep the widget and toggle button visible + m_progressBar->hide(); + m_progressLabel->hide(); + // Don't hide m_progressWidget - keeps the toggle button visible + // Don't hide the log widget or reset log visibility + // This allows users to review logs after operation completes } void PackageDetailsDialog::toggleLogViewer() { diff --git a/src/gui/search_widget.cpp b/src/gui/search_widget.cpp index 4a5f12b..2f0063e 100644 --- a/src/gui/search_widget.cpp +++ b/src/gui/search_widget.cpp @@ -219,3 +219,45 @@ void SearchWidget::onPackageClicked(const PackageInfo& info) { dialog->exec(); dialog->deleteLater(); } + +void SearchWidget::updateRepositoryList(bool multilibEnabled) { + // Save the current selection + int currentIndex = m_filterCombo->currentIndex(); + QString currentFilter = m_filterCombo->itemData(currentIndex).toString(); + + // Check if multilib already exists in the list + bool multilibExists = false; + for (int i = 0; i < m_filterCombo->count(); ++i) { + if (m_filterCombo->itemData(i).toString() == "multilib") { + multilibExists = true; + break; + } + } + + if (multilibEnabled && !multilibExists) { + // Add multilib to the dropdown (insert before AUR) + int aurIndex = m_filterCombo->findData("AUR"); + if (aurIndex != -1) { + m_filterCombo->insertItem(aurIndex, "Multilib", "multilib"); + } else { + m_filterCombo->addItem("Multilib", "multilib"); + } + Logger::info("Added multilib repository to search filter"); + } else if (!multilibEnabled && multilibExists) { + // Remove multilib from the dropdown + int multilibIndex = m_filterCombo->findData("multilib"); + if (multilibIndex != -1) { + m_filterCombo->removeItem(multilibIndex); + Logger::info("Removed multilib repository from search filter"); + } + } + + // Restore previous selection if it still exists + int newIndex = m_filterCombo->findData(currentFilter); + if (newIndex != -1) { + m_filterCombo->setCurrentIndex(newIndex); + } else { + // If previous selection was multilib and it's now removed, select "All" + m_filterCombo->setCurrentIndex(0); + } +} diff --git a/src/gui/search_widget.h b/src/gui/search_widget.h index 5da3a89..6db8d17 100644 --- a/src/gui/search_widget.h +++ b/src/gui/search_widget.h @@ -20,6 +20,9 @@ class SearchWidget : public QWidget { explicit SearchWidget(QWidget* parent = nullptr); ~SearchWidget() override = default; +public slots: + void updateRepositoryList(bool multilibEnabled); + private: void setupUi(); void performSearch(); diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp index b48fce0..5e3fae5 100644 --- a/src/gui/settings_widget.cpp +++ b/src/gui/settings_widget.cpp @@ -1,5 +1,6 @@ #include "settings_widget.h" #include "../utils/logger.h" +#include "../core/alpm_wrapper.h" #include #include #include @@ -362,10 +363,16 @@ void SettingsWidget::onApplyClicked() { if (process.exitCode() == 0) { m_statusLabel->setText("Package databases synced successfully!"); Logger::info("Package databases synced after repository change"); + + // Refresh ALPM databases to pick up the new repository + AlpmWrapper::instance().refreshDatabases(); } else { m_statusLabel->setText("Failed to sync package databases. Please run 'sudo pacman -Sy' manually."); m_statusLabel->setStyleSheet("QLabel { color: #aa0000; padding: 10px; }"); } + } else { + // Even if they don't sync now, refresh ALPM to detect the new repo configuration + AlpmWrapper::instance().refreshDatabases(); } } else { m_statusLabel->setText("Failed to apply settings. Please check permissions."); From 3f4cdb17e8bf2ddd5f2628f460acb514891245de Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 17:40:20 +0000 Subject: [PATCH 27/71] show logs and progress bar in updates page --- src/gui/updates_widget.cpp | 204 +++++++++++++++++++++++++++++++++++-- src/gui/updates_widget.h | 18 ++++ 2 files changed, 213 insertions(+), 9 deletions(-) diff --git a/src/gui/updates_widget.cpp b/src/gui/updates_widget.cpp index 407af01..7ced7b6 100644 --- a/src/gui/updates_widget.cpp +++ b/src/gui/updates_widget.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include class UpdateItem : public QWidget { @@ -86,19 +87,26 @@ UpdatesWidget::UpdatesWidget(QWidget* parent) , m_statusLabel(new QLabel(this)) , m_countLabel(new QLabel(this)) , m_updateAllButton(new QPushButton("Update All", this)) - , m_checkButton(new QPushButton("Check for Updates", this)) { + , m_checkButton(new QPushButton("Check for Updates", this)) + , m_progressWidget(new QWidget(this)) + , m_progressBar(new QProgressBar(this)) + , m_progressLabel(new QLabel(this)) + , m_toggleLogButton(new QPushButton("Show Logs", this)) + , m_logWidget(new QWidget(this)) + , m_logViewer(new QTextEdit(this)) + , m_logVisible(false) { setupUi(); + // Connect to PackageManager signals + connect(&PackageManager::instance(), &PackageManager::operationStarted, + this, &UpdatesWidget::onOperationStarted); + connect(&PackageManager::instance(), &PackageManager::operationOutput, + this, &UpdatesWidget::onOperationOutput); connect(&PackageManager::instance(), &PackageManager::operationCompleted, - this, [this](bool success, const QString& message) { - if (success) { - QMessageBox::information(this, "Success", message); - checkForUpdates(); - } else { - QMessageBox::warning(this, "Error", message); - } - }); + this, &UpdatesWidget::onOperationCompleted); + connect(&PackageManager::instance(), &PackageManager::operationError, + this, &UpdatesWidget::onOperationError); } void UpdatesWidget::setupUi() { @@ -146,6 +154,79 @@ void UpdatesWidget::setupUi() { m_contentLayout->addStretch(); mainLayout->addWidget(m_scrollArea); + + // Progress bar section (hidden by default) + auto* progressLayout = new QVBoxLayout(m_progressWidget); + progressLayout->setContentsMargins(20, 0, 20, 20); + progressLayout->setSpacing(8); + + m_progressLabel->setStyleSheet("color: #a1a1aa; font-size: 12px;"); + m_progressLabel->setAlignment(Qt::AlignCenter); + progressLayout->addWidget(m_progressLabel); + + m_progressBar->setMinimumHeight(20); + m_progressBar->setMaximumHeight(20); + m_progressBar->setTextVisible(true); + m_progressBar->setFormat("%p%"); + m_progressBar->setStyleSheet( + "QProgressBar {" + " border: none;" + " border-radius: 4px;" + " background-color: #27272a;" + " color: #fafafa;" + " text-align: center;" + " font-size: 11px;" + "}" + "QProgressBar::chunk {" + " border-radius: 4px;" + " background-color: #3b82f6;" + "}" + ); + progressLayout->addWidget(m_progressBar); + + // Toggle log button + m_toggleLogButton->setStyleSheet( + "QPushButton {" + " background: none;" + " border: none;" + " color: #3b82f6;" + " text-decoration: underline;" + " font-size: 11px;" + " padding: 4px;" + "}" + "QPushButton:hover {" + " color: #60a5fa;" + "}" + ); + connect(m_toggleLogButton, &QPushButton::clicked, this, &UpdatesWidget::toggleLogViewer); + progressLayout->addWidget(m_toggleLogButton, 0, Qt::AlignCenter); + + m_progressWidget->hide(); + mainLayout->addWidget(m_progressWidget, 0); + + // Log viewer section (hidden by default) + auto* logLayout = new QVBoxLayout(m_logWidget); + logLayout->setContentsMargins(20, 0, 20, 20); + logLayout->setSpacing(8); + + m_logViewer->setReadOnly(true); + m_logViewer->setMaximumHeight(200); + m_logViewer->setStyleSheet( + "QTextEdit {" + " background-color: #18181b;" + " border: 1px solid #27272a;" + " border-radius: 6px;" + " color: #d4d4d8;" + " font-family: 'Consolas', 'Monaco', monospace;" + " font-size: 11px;" + " padding: 8px;" + "}" + ); + logLayout->addWidget(m_logViewer); + + m_logWidget->hide(); + mainLayout->addWidget(m_logWidget, 0); + setLayout(mainLayout); } @@ -245,4 +326,109 @@ QString UpdatesWidget::formatSize(qint64 bytes) { return QString("%1 B").arg(bytes); } +void UpdatesWidget::showProgress(const QString& message) { + m_progressLabel->setText(message); + m_progressBar->setRange(0, 100); + m_progressBar->setValue(0); + m_progressWidget->show(); + m_progressBar->show(); + m_progressLabel->show(); + m_logViewer->clear(); +} + +void UpdatesWidget::hideProgress() { + // Hide the progress bar and label, but keep the widget and toggle button visible + m_progressBar->hide(); + m_progressLabel->hide(); + // Don't hide m_progressWidget - keeps the toggle button visible + // Don't hide the log widget or reset log visibility + // This allows users to review logs after operation completes +} + +void UpdatesWidget::toggleLogViewer() { + m_logVisible = !m_logVisible; + if (m_logVisible) { + m_logWidget->show(); + m_toggleLogButton->setText("Hide Logs"); + } else { + m_logWidget->hide(); + m_toggleLogButton->setText("Show Logs"); + } +} + +void UpdatesWidget::onOperationStarted(const QString& message) { + showProgress(message); + m_updateAllButton->setEnabled(false); + m_checkButton->setEnabled(false); + + // Disable all individual update buttons + for (int i = 0; i < m_contentLayout->count() - 1; ++i) { + if (auto* item = m_contentLayout->itemAt(i)) { + if (auto* widget = item->widget()) { + widget->setEnabled(false); + } + } + } +} + +void UpdatesWidget::onOperationOutput(const QString& output) { + m_logViewer->append(output); + + // Auto-scroll to bottom + auto cursor = m_logViewer->textCursor(); + cursor.movePosition(QTextCursor::End); + m_logViewer->setTextCursor(cursor); + + // Try to parse progress information from output + // This is a simple implementation - could be enhanced + if (output.contains("downloading", Qt::CaseInsensitive)) { + m_progressLabel->setText("Downloading packages..."); + m_progressBar->setRange(0, 0); // Indeterminate + } else if (output.contains("installing", Qt::CaseInsensitive)) { + m_progressLabel->setText("Installing packages..."); + m_progressBar->setRange(0, 0); // Indeterminate + } +} + +void UpdatesWidget::onOperationCompleted(bool success, const QString& message) { + hideProgress(); + + m_updateAllButton->setEnabled(!m_updates.isEmpty()); + m_checkButton->setEnabled(true); + + // Re-enable all individual update buttons + for (int i = 0; i < m_contentLayout->count() - 1; ++i) { + if (auto* item = m_contentLayout->itemAt(i)) { + if (auto* widget = item->widget()) { + widget->setEnabled(true); + } + } + } + + if (success) { + QMessageBox::information(this, "Success", message); + checkForUpdates(); + } else { + QMessageBox::warning(this, "Operation Failed", message); + } +} + +void UpdatesWidget::onOperationError(const QString& error) { + hideProgress(); + + m_updateAllButton->setEnabled(!m_updates.isEmpty()); + m_checkButton->setEnabled(true); + + // Re-enable all individual update buttons + for (int i = 0; i < m_contentLayout->count() - 1; ++i) { + if (auto* item = m_contentLayout->itemAt(i)) { + if (auto* widget = item->widget()) { + widget->setEnabled(true); + } + } + } + + QMessageBox::critical(this, "Error", error); +} + #include "updates_widget.moc" diff --git a/src/gui/updates_widget.h b/src/gui/updates_widget.h index 389fc77..c8cdb8d 100644 --- a/src/gui/updates_widget.h +++ b/src/gui/updates_widget.h @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include "../utils/types.h" class UpdateItem; @@ -25,6 +27,9 @@ class UpdatesWidget : public QWidget { void displayUpdates(const QVector& updates); void clearUpdates(); QString formatSize(qint64 bytes); + void showProgress(const QString& message); + void hideProgress(); + void toggleLogViewer(); QScrollArea* m_scrollArea; QWidget* m_contentWidget; @@ -34,11 +39,24 @@ class UpdatesWidget : public QWidget { QPushButton* m_updateAllButton; QPushButton* m_checkButton; + // Progress bar and log viewer + QWidget* m_progressWidget; + QProgressBar* m_progressBar; + QLabel* m_progressLabel; + QPushButton* m_toggleLogButton; + QWidget* m_logWidget; + QTextEdit* m_logViewer; + bool m_logVisible; + QVector m_updates; private slots: void onUpdateAll(); void onUpdateSingle(const QString& packageName); + void onOperationStarted(const QString& message); + void onOperationOutput(const QString& output); + void onOperationCompleted(bool success, const QString& message); + void onOperationError(const QString& error); }; #endif // UPDATES_WIDGET_H From 577e2ec1595db4feaf12eceb3be275b341e8f117 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 17:48:58 +0000 Subject: [PATCH 28/71] refresh updates list after successful update --- src/gui/updates_widget.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/gui/updates_widget.cpp b/src/gui/updates_widget.cpp index 7ced7b6..547d2f0 100644 --- a/src/gui/updates_widget.cpp +++ b/src/gui/updates_widget.cpp @@ -391,6 +391,10 @@ void UpdatesWidget::onOperationOutput(const QString& output) { } void UpdatesWidget::onOperationCompleted(bool success, const QString& message) { + // Refresh ALPM state so subsequent queries reflect the changes + AlpmWrapper::instance().release(); + AlpmWrapper::instance().initialize(); + hideProgress(); m_updateAllButton->setEnabled(!m_updates.isEmpty()); @@ -414,6 +418,10 @@ void UpdatesWidget::onOperationCompleted(bool success, const QString& message) { } void UpdatesWidget::onOperationError(const QString& error) { + // Refresh ALPM state (best-effort) + AlpmWrapper::instance().release(); + AlpmWrapper::instance().initialize(); + hideProgress(); m_updateAllButton->setEnabled(!m_updates.isEmpty()); From 86b1fb5771e7fcb6f5e49c42f9febbba559ce3da Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 18:06:26 +0000 Subject: [PATCH 29/71] add search bar in updates tab --- src/gui/updates_widget.cpp | 52 +++++++++++++++++++++++++++++++++++++- src/gui/updates_widget.h | 5 ++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/gui/updates_widget.cpp b/src/gui/updates_widget.cpp index 547d2f0..347803b 100644 --- a/src/gui/updates_widget.cpp +++ b/src/gui/updates_widget.cpp @@ -81,6 +81,7 @@ class UpdateItem : public QWidget { UpdatesWidget::UpdatesWidget(QWidget* parent) : QWidget(parent) + , m_searchInput(new QLineEdit(this)) , m_scrollArea(new QScrollArea(this)) , m_contentWidget(new QWidget()) , m_contentLayout(new QVBoxLayout(m_contentWidget)) @@ -139,6 +140,14 @@ void UpdatesWidget::setupUi() { mainLayout->addLayout(headerLayout); + // Search bar + m_searchInput->setPlaceholderText("Search updates..."); + m_searchInput->setMinimumHeight(35); + m_searchInput->setClearButtonEnabled(true); + m_searchInput->setEnabled(false); // Disabled until updates are loaded + connect(m_searchInput, &QLineEdit::textChanged, this, &UpdatesWidget::onSearchTextChanged); + mainLayout->addWidget(m_searchInput); + // Status label m_statusLabel->setAlignment(Qt::AlignCenter); m_statusLabel->setText("Click 'Check for Updates' to scan for available updates"); @@ -249,6 +258,7 @@ void UpdatesWidget::checkForUpdates() { QMetaObject::invokeMethod(this, [this, updates]() { m_updates = updates; + m_filteredUpdates = updates; m_checkButton->setEnabled(true); m_checkButton->setText("Check for Updates"); @@ -256,12 +266,21 @@ void UpdatesWidget::checkForUpdates() { if (updates.isEmpty()) { m_statusLabel->setText("Your system is up to date!"); m_countLabel->clear(); + m_searchInput->setEnabled(false); } else { m_statusLabel->hide(); m_countLabel->setText(QString("%1 updates available") .arg(updates.size())); m_updateAllButton->setEnabled(true); - displayUpdates(updates); + m_searchInput->setEnabled(true); + + // Apply any existing search filter + QString searchText = m_searchInput->text(); + if (!searchText.isEmpty()) { + filterUpdates(searchText); + } else { + displayUpdates(updates); + } } Logger::info(QString("Found %1 updates").arg(updates.size())); @@ -290,6 +309,37 @@ void UpdatesWidget::clearUpdates() { } } +void UpdatesWidget::filterUpdates(const QString& searchText) { + if (searchText.isEmpty()) { + m_filteredUpdates = m_updates; + displayUpdates(m_filteredUpdates); + m_countLabel->setText(QString("%1 updates available").arg(m_updates.size())); + return; + } + + QString lowerSearch = searchText.toLower(); + m_filteredUpdates.clear(); + + for (const auto& update : m_updates) { + if (update.name.toLower().contains(lowerSearch)) { + m_filteredUpdates.append(update); + } + } + + displayUpdates(m_filteredUpdates); + + // Update count label to show filtered count + if (m_filteredUpdates.size() == m_updates.size()) { + m_countLabel->setText(QString("%1 updates available").arg(m_updates.size())); + } else { + m_countLabel->setText(QString("%1 of %2 updates").arg(m_filteredUpdates.size()).arg(m_updates.size())); + } +} + +void UpdatesWidget::onSearchTextChanged(const QString& text) { + filterUpdates(text); +} + void UpdatesWidget::onUpdateAll() { auto reply = QMessageBox::question(this, "Update All", QString("Are you sure you want to update all %1 packages?") diff --git a/src/gui/updates_widget.h b/src/gui/updates_widget.h index c8cdb8d..bf045e4 100644 --- a/src/gui/updates_widget.h +++ b/src/gui/updates_widget.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "../utils/types.h" class UpdateItem; @@ -26,11 +27,13 @@ class UpdatesWidget : public QWidget { void setupUi(); void displayUpdates(const QVector& updates); void clearUpdates(); + void filterUpdates(const QString& searchText); QString formatSize(qint64 bytes); void showProgress(const QString& message); void hideProgress(); void toggleLogViewer(); + QLineEdit* m_searchInput; QScrollArea* m_scrollArea; QWidget* m_contentWidget; QVBoxLayout* m_contentLayout; @@ -49,10 +52,12 @@ class UpdatesWidget : public QWidget { bool m_logVisible; QVector m_updates; + QVector m_filteredUpdates; private slots: void onUpdateAll(); void onUpdateSingle(const QString& packageName); + void onSearchTextChanged(const QString& text); void onOperationStarted(const QString& message); void onOperationOutput(const QString& output); void onOperationCompleted(bool success, const QString& message); From a29f5e43b706f86bbaa8e4d85ceaad7a72afb33d Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 18:06:45 +0000 Subject: [PATCH 30/71] remove pacman lock file --- src/gui/settings_widget.cpp | 111 ++++++++++++++++++++++++++++++++++++ src/gui/settings_widget.h | 6 ++ 2 files changed, 117 insertions(+) diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp index 5e3fae5..ab64a17 100644 --- a/src/gui/settings_widget.cpp +++ b/src/gui/settings_widget.cpp @@ -41,6 +41,10 @@ void SettingsWidget::setupUi() { createRepositorySettings(); mainLayout->addWidget(m_repositoryGroup); + // Maintenance Settings + createMaintenanceSettings(); + mainLayout->addWidget(m_maintenanceGroup); + // Status label m_statusLabel = new QLabel(this); m_statusLabel->setAlignment(Qt::AlignCenter); @@ -120,6 +124,51 @@ void SettingsWidget::createRepositorySettings() { m_repositoryGroup->setLayout(repoLayout); } +void SettingsWidget::createMaintenanceSettings() { + m_maintenanceGroup = new QGroupBox("Maintenance", this); + auto* maintenanceLayout = new QVBoxLayout(m_maintenanceGroup); + + // Description + auto* descLabel = new QLabel( + "System maintenance and troubleshooting tools.", + this); + descLabel->setWordWrap(true); + descLabel->setStyleSheet("QLabel { color: #666; margin-bottom: 10px; }"); + maintenanceLayout->addWidget(descLabel); + + // Lock file section + auto* lockFileLayout = new QHBoxLayout(); + + auto* lockFileLabel = new QLabel( + "Pacman Database Lock:", + this); + lockFileLabel->setStyleSheet("QLabel { font-weight: bold; }"); + lockFileLayout->addWidget(lockFileLabel); + + lockFileLayout->addStretch(); + + m_removeLockButton = new QPushButton("Remove Lock File", this); + m_removeLockButton->setMinimumWidth(150); + m_removeLockButton->setToolTip( + "Remove /var/lib/pacman/db.lck if pacman is stuck.\n" + "Only use this if you're sure no other pacman process is running."); + connect(m_removeLockButton, &QPushButton::clicked, this, &SettingsWidget::onRemoveLockClicked); + lockFileLayout->addWidget(m_removeLockButton); + + maintenanceLayout->addLayout(lockFileLayout); + + // Lock file info + auto* lockInfoLabel = new QLabel( + "If pacman was interrupted, it may leave a lock file that prevents other operations.\n" + "Remove it only if you're certain no package manager is currently running.", + this); + lockInfoLabel->setWordWrap(true); + lockInfoLabel->setStyleSheet("QLabel { color: #888; font-size: 11px; margin-top: 5px; margin-left: 10px; }"); + maintenanceLayout->addWidget(lockInfoLabel); + + m_maintenanceGroup->setLayout(maintenanceLayout); +} + void SettingsWidget::loadCurrentSettings() { // Check if multilib is currently enabled bool multilibEnabled = isMultilibEnabledInPacmanConf(); @@ -402,3 +451,65 @@ bool SettingsWidget::isMultilibEnabled() const { void SettingsWidget::applySettings() { onApplyClicked(); } + +void SettingsWidget::onRemoveLockClicked() { + QString lockFilePath = "/var/lib/pacman/db.lck"; + + // Check if lock file exists + QFile lockFile(lockFilePath); + if (!lockFile.exists()) { + QMessageBox::information(this, "Lock File Not Found", + "The pacman lock file does not exist.\n" + "No action needed."); + return; + } + + // Show warning dialog with checkbox + QMessageBox msgBox(this); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle("Remove Pacman Lock File"); + msgBox.setText("Are you sure you want to remove the pacman lock file?"); + msgBox.setInformativeText( + "This will remove: /var/lib/pacman/db.lck\n\n" + "WARNING: Only do this if you are certain that no other package manager " + "(pacman, yay, paru, etc.) is currently running.\n\n" + "Removing the lock file while a package operation is in progress can " + "corrupt your package database!"); + + QCheckBox* confirmCheckbox = new QCheckBox("I understand the risks and confirm no package manager is running"); + msgBox.setCheckBox(confirmCheckbox); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + + int ret = msgBox.exec(); + + if (ret == QMessageBox::Yes && confirmCheckbox->isChecked()) { + // Use pkexec to remove the lock file with elevated privileges + QProcess process; + process.start("pkexec", QStringList() << "rm" << "-f" << lockFilePath); + process.waitForFinished(30000); // 30 second timeout + + if (process.exitCode() == 0) { + m_statusLabel->setText("Lock file removed successfully!"); + m_statusLabel->setStyleSheet("QLabel { color: #00aa00; padding: 10px; font-weight: bold; }"); + m_statusLabel->show(); + Logger::info("Pacman lock file removed successfully"); + + QMessageBox::information(this, "Success", + "The pacman lock file has been removed successfully.\n" + "You can now run package operations."); + } else { + m_statusLabel->setText("Failed to remove lock file. Check permissions."); + m_statusLabel->setStyleSheet("QLabel { color: #aa0000; padding: 10px; }"); + m_statusLabel->show(); + Logger::error("Failed to remove pacman lock file"); + + QMessageBox::critical(this, "Error", + "Failed to remove the lock file.\n" + "You may need to run: sudo rm /var/lib/pacman/db.lck"); + } + } else if (ret == QMessageBox::Yes && !confirmCheckbox->isChecked()) { + QMessageBox::warning(this, "Confirmation Required", + "You must check the confirmation box to proceed."); + } +} diff --git a/src/gui/settings_widget.h b/src/gui/settings_widget.h index f200a3c..1ea9f80 100644 --- a/src/gui/settings_widget.h +++ b/src/gui/settings_widget.h @@ -24,6 +24,7 @@ class SettingsWidget : public QWidget { void setupUi(); void loadCurrentSettings(); void createRepositorySettings(); + void createMaintenanceSettings(); bool isMultilibEnabledInPacmanConf() const; bool enableMultilibInPacmanConf(); bool disableMultilibInPacmanConf(); @@ -35,6 +36,10 @@ class SettingsWidget : public QWidget { QCheckBox* m_extraRepoCheckbox; QCheckBox* m_multilibRepoCheckbox; + // Maintenance settings + QGroupBox* m_maintenanceGroup; + QPushButton* m_removeLockButton; + // Control buttons QPushButton* m_applyButton; QPushButton* m_revertButton; @@ -49,6 +54,7 @@ private slots: void onApplyClicked(); void onRevertClicked(); void onSettingsChanged(); + void onRemoveLockClicked(); }; #endif // SETTINGS_WIDGET_H From a2ad535bc05f8c0b65e2e617dedec35f61cbc3f8 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 18:24:34 +0000 Subject: [PATCH 31/71] add clear button to the search bar of installed and search tabs --- src/gui/installed_widget.cpp | 1 + src/gui/search_widget.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/gui/installed_widget.cpp b/src/gui/installed_widget.cpp index 3fe8329..075b404 100644 --- a/src/gui/installed_widget.cpp +++ b/src/gui/installed_widget.cpp @@ -48,6 +48,7 @@ void InstalledWidget::setupUi() { // Filter m_filterInput->setPlaceholderText("Filter installed packages..."); m_filterInput->setMinimumHeight(35); + m_filterInput->setClearButtonEnabled(true); connect(m_filterInput, &QLineEdit::textChanged, this, &InstalledWidget::onFilterTextChanged); mainLayout->addWidget(m_filterInput); diff --git a/src/gui/search_widget.cpp b/src/gui/search_widget.cpp index 2f0063e..00be66f 100644 --- a/src/gui/search_widget.cpp +++ b/src/gui/search_widget.cpp @@ -43,6 +43,7 @@ void SearchWidget::setupUi() { m_searchInput->setPlaceholderText("Search for packages..."); m_searchInput->setMinimumHeight(35); + m_searchInput->setClearButtonEnabled(true); connect(m_searchInput, &QLineEdit::returnPressed, this, &SearchWidget::onSearchClicked); searchLayout->addWidget(m_searchInput, 1); From f449ba667075842f1a48d23bdca0d78c1e07433a Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 19:59:53 +0000 Subject: [PATCH 32/71] add chaotic aur options in settings tab --- src/gui/settings_widget.cpp | 482 ++++++++++++++++++++++++++++++++++-- src/gui/settings_widget.h | 13 + 2 files changed, 478 insertions(+), 17 deletions(-) diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp index ab64a17..f749e6e 100644 --- a/src/gui/settings_widget.cpp +++ b/src/gui/settings_widget.cpp @@ -14,10 +14,15 @@ SettingsWidget::SettingsWidget(QWidget* parent) , m_coreRepoCheckbox(nullptr) , m_extraRepoCheckbox(nullptr) , m_multilibRepoCheckbox(nullptr) + , m_chaoticAurCheckbox(nullptr) + , m_chaoticAurGroup(nullptr) + , m_setupChaoticButton(nullptr) + , m_removeChaoticButton(nullptr) , m_applyButton(nullptr) , m_revertButton(nullptr) , m_statusLabel(nullptr) - , m_originalMultilibState(false) { + , m_originalMultilibState(false) + , m_originalChaoticAurState(false) { setupUi(); loadCurrentSettings(); @@ -41,6 +46,10 @@ void SettingsWidget::setupUi() { createRepositorySettings(); mainLayout->addWidget(m_repositoryGroup); + // Chaotic-AUR Setup + createChaoticAurSettings(); + mainLayout->addWidget(m_chaoticAurGroup); + // Maintenance Settings createMaintenanceSettings(); mainLayout->addWidget(m_maintenanceGroup); @@ -112,6 +121,16 @@ void SettingsWidget::createRepositorySettings() { this, &SettingsWidget::onSettingsChanged); repoLayout->addWidget(m_multilibRepoCheckbox); + // Chaotic-AUR repository (optional, can be enabled/disabled) + m_chaoticAurCheckbox = new QCheckBox("Chaotic-AUR - Pre-built AUR packages", this); + m_chaoticAurCheckbox->setToolTip( + "Enable chaotic-aur repository for pre-built AUR packages.\n" + "This modifies /etc/pacman.conf and requires administrator privileges.\n" + "Note: chaotic-keyring and chaotic-mirrorlist must be installed first."); + connect(m_chaoticAurCheckbox, &QCheckBox::checkStateChanged, + this, &SettingsWidget::onSettingsChanged); + repoLayout->addWidget(m_chaoticAurCheckbox); + // Info label auto* infoLabel = new QLabel( "Note: Changes to repositories require modifying system configuration files " @@ -124,6 +143,79 @@ void SettingsWidget::createRepositorySettings() { m_repositoryGroup->setLayout(repoLayout); } +void SettingsWidget::createChaoticAurSettings() { + m_chaoticAurGroup = new QGroupBox("Chaotic-AUR Setup", this); + auto* chaoticLayout = new QVBoxLayout(m_chaoticAurGroup); + + // Description + auto* descLabel = new QLabel( + "Chaotic-AUR provides pre-built AUR packages, making installation faster and easier.\n" + "Setup requires installing the keyring and mirrorlist packages.", + this); + descLabel->setWordWrap(true); + descLabel->setStyleSheet("QLabel { color: #666; margin-bottom: 10px; }"); + chaoticLayout->addWidget(descLabel); + + // Setup button section + auto* setupLayout = new QHBoxLayout(); + + auto* setupLabel = new QLabel("Install Chaotic-AUR:", this); + setupLabel->setStyleSheet("QLabel { font-weight: bold; }"); + setupLayout->addWidget(setupLabel); + + setupLayout->addStretch(); + + m_setupChaoticButton = new QPushButton("Setup Chaotic-AUR", this); + m_setupChaoticButton->setMinimumWidth(150); + m_setupChaoticButton->setToolTip( + "Install chaotic-keyring and chaotic-mirrorlist packages.\n" + "This will enable access to pre-built AUR packages."); + connect(m_setupChaoticButton, &QPushButton::clicked, this, &SettingsWidget::onSetupChaoticClicked); + setupLayout->addWidget(m_setupChaoticButton); + + chaoticLayout->addLayout(setupLayout); + + // Setup info + auto* setupInfoLabel = new QLabel( + "This will install chaotic-keyring and chaotic-mirrorlist from the official Chaotic-AUR repository.", + this); + setupInfoLabel->setWordWrap(true); + setupInfoLabel->setStyleSheet("QLabel { color: #888; font-size: 11px; margin-top: 5px; margin-left: 10px; }"); + chaoticLayout->addWidget(setupInfoLabel); + + // Spacer + chaoticLayout->addSpacing(10); + + // Remove button section + auto* removeLayout = new QHBoxLayout(); + + auto* removeLabel = new QLabel("Remove Chaotic-AUR:", this); + removeLabel->setStyleSheet("QLabel { font-weight: bold; }"); + removeLayout->addWidget(removeLabel); + + removeLayout->addStretch(); + + m_removeChaoticButton = new QPushButton("Remove Chaotic-AUR", this); + m_removeChaoticButton->setMinimumWidth(150); + m_removeChaoticButton->setToolTip( + "Remove chaotic-keyring and chaotic-mirrorlist packages.\n" + "You may need to manually remove the repository from /etc/pacman.conf"); + connect(m_removeChaoticButton, &QPushButton::clicked, this, &SettingsWidget::onRemoveChaoticClicked); + removeLayout->addWidget(m_removeChaoticButton); + + chaoticLayout->addLayout(removeLayout); + + // Remove info + auto* removeInfoLabel = new QLabel( + "This will remove the Chaotic-AUR packages. You need to uncheck the Chaotic-AUR option above or manually edit /etc/pacman.conf to remove the repository configuration.", + this); + removeInfoLabel->setWordWrap(true); + removeInfoLabel->setStyleSheet("QLabel { color: #888; font-size: 11px; margin-top: 5px; margin-left: 10px; }"); + chaoticLayout->addWidget(removeInfoLabel); + + m_chaoticAurGroup->setLayout(chaoticLayout); +} + void SettingsWidget::createMaintenanceSettings() { m_maintenanceGroup = new QGroupBox("Maintenance", this); auto* maintenanceLayout = new QVBoxLayout(m_maintenanceGroup); @@ -175,7 +267,14 @@ void SettingsWidget::loadCurrentSettings() { m_multilibRepoCheckbox->setChecked(multilibEnabled); m_originalMultilibState = multilibEnabled; - Logger::info(QString("Loaded settings: multilib=%1").arg(multilibEnabled ? "enabled" : "disabled")); + // Check if chaotic-aur is enabled + bool chaoticAurEnabled = isChaoticAurEnabledInPacmanConf(); + m_chaoticAurCheckbox->setChecked(chaoticAurEnabled); + m_originalChaoticAurState = chaoticAurEnabled; + + Logger::info(QString("Loaded settings: multilib=%1, chaotic-aur=%2") + .arg(multilibEnabled ? "enabled" : "disabled") + .arg(chaoticAurEnabled ? "enabled" : "disabled")); } bool SettingsWidget::isMultilibEnabledInPacmanConf() const { @@ -216,6 +315,44 @@ bool SettingsWidget::isMultilibEnabledInPacmanConf() const { return false; } +bool SettingsWidget::isChaoticAurEnabledInPacmanConf() const { + QFile file("/etc/pacman.conf"); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + Logger::error("Failed to open /etc/pacman.conf for reading"); + return false; + } + + QTextStream in(&file); + bool inChaoticAurSection = false; + + while (!in.atEnd()) { + QString line = in.readLine().trimmed(); + + // Check for [chaotic-aur] section header + if (line == "[chaotic-aur]") { + inChaoticAurSection = true; + continue; + } + + // If we found [chaotic-aur] section, check if it's not commented + if (inChaoticAurSection && !line.isEmpty() && !line.startsWith("#")) { + // If we find Include or Server directive, chaotic-aur is enabled + if (line.startsWith("Include") || line.startsWith("Server")) { + file.close(); + return true; + } + } + + // If we hit another section, stop + if (inChaoticAurSection && line.startsWith("[") && line != "[chaotic-aur]") { + break; + } + } + + file.close(); + return false; +} + bool SettingsWidget::enableMultilibInPacmanConf() { QFile file("/etc/pacman.conf"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -344,9 +481,150 @@ bool SettingsWidget::disableMultilibInPacmanConf() { return true; } +bool SettingsWidget::enableChaoticAurInPacmanConf() { + QFile file("/etc/pacman.conf"); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + Logger::error("Failed to open /etc/pacman.conf for reading"); + return false; + } + + QStringList lines; + QTextStream in(&file); + bool chaoticAurSectionFound = false; + bool chaoticAurExists = false; + + while (!in.atEnd()) { + QString line = in.readLine(); + + // Check if chaotic-aur section already exists (uncommented) + if (line.trimmed() == "[chaotic-aur]") { + chaoticAurExists = true; + } + + // Check if this is a commented [chaotic-aur] section + if (line.trimmed() == "#[chaotic-aur]") { + lines.append("[chaotic-aur]"); + chaoticAurSectionFound = true; + } + // Check if the Include/Server line in chaotic-aur section is commented + else if (chaoticAurSectionFound && line.trimmed().startsWith("#") && + (line.contains("Include") || line.contains("Server"))) { + lines.append(line.mid(line.indexOf('#') + 1)); // Remove the # comment character + chaoticAurSectionFound = false; // Reset flag after processing + } + else { + lines.append(line); + } + } + file.close(); + + // If chaotic-aur section doesn't exist at all, add it + if (!chaoticAurExists && !chaoticAurSectionFound) { + lines.append(""); + lines.append("[chaotic-aur]"); + lines.append("Include = /etc/pacman.d/chaotic-mirrorlist"); + } + + // Write back to file using pkexec for elevated privileges + QString tempFile = "/tmp/pacman.conf.tmp"; + QFile temp(tempFile); + if (!temp.open(QIODevice::WriteOnly | QIODevice::Text)) { + Logger::error("Failed to create temporary file"); + return false; + } + + QTextStream out(&temp); + for (const QString& line : lines) { + out << line << "\n"; + } + temp.close(); + + // Use pkexec to copy the file with elevated privileges + QProcess process; + process.start("pkexec", QStringList() << "cp" << tempFile << "/etc/pacman.conf"); + process.waitForFinished(30000); // 30 second timeout + + if (process.exitCode() != 0) { + Logger::error("Failed to update pacman.conf with elevated privileges"); + QFile::remove(tempFile); + return false; + } + + QFile::remove(tempFile); + Logger::info("Successfully enabled chaotic-aur repository"); + return true; +} + +bool SettingsWidget::disableChaoticAurInPacmanConf() { + QFile file("/etc/pacman.conf"); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + Logger::error("Failed to open /etc/pacman.conf for reading"); + return false; + } + + QStringList lines; + QTextStream in(&file); + bool inChaoticAurSection = false; + + while (!in.atEnd()) { + QString line = in.readLine(); + QString trimmedLine = line.trimmed(); + + // Check if this is [chaotic-aur] section + if (trimmedLine == "[chaotic-aur]") { + lines.append("#[chaotic-aur]"); + inChaoticAurSection = true; + } + // Check if we're in chaotic-aur section and this is the Include/Server line + else if (inChaoticAurSection && !trimmedLine.startsWith("#") && + (trimmedLine.startsWith("Include") || trimmedLine.startsWith("Server"))) { + lines.append("#" + line); + } + // Check if we hit another section + else if (trimmedLine.startsWith("[") && trimmedLine != "[chaotic-aur]") { + lines.append(line); + inChaoticAurSection = false; + } + else { + lines.append(line); + } + } + file.close(); + + // Write back to file using pkexec for elevated privileges + QString tempFile = "/tmp/pacman.conf.tmp"; + QFile temp(tempFile); + if (!temp.open(QIODevice::WriteOnly | QIODevice::Text)) { + Logger::error("Failed to create temporary file"); + return false; + } + + QTextStream out(&temp); + for (const QString& line : lines) { + out << line << "\n"; + } + temp.close(); + + // Use pkexec to copy the file with elevated privileges + QProcess process; + process.start("pkexec", QStringList() << "cp" << tempFile << "/etc/pacman.conf"); + process.waitForFinished(30000); // 30 second timeout + + if (process.exitCode() != 0) { + Logger::error("Failed to update pacman.conf with elevated privileges"); + QFile::remove(tempFile); + return false; + } + + QFile::remove(tempFile); + Logger::info("Successfully disabled chaotic-aur repository"); + return true; +} + void SettingsWidget::onSettingsChanged() { // Enable apply and revert buttons when settings change - bool hasChanges = (m_multilibRepoCheckbox->isChecked() != m_originalMultilibState); + bool hasChanges = (m_multilibRepoCheckbox->isChecked() != m_originalMultilibState) || + (m_chaoticAurCheckbox->isChecked() != m_originalChaoticAurState); m_applyButton->setEnabled(hasChanges); m_revertButton->setEnabled(hasChanges); m_statusLabel->hide(); @@ -354,8 +632,11 @@ void SettingsWidget::onSettingsChanged() { void SettingsWidget::onApplyClicked() { bool currentMultilibState = m_multilibRepoCheckbox->isChecked(); - bool success = false; + bool currentChaoticAurState = m_chaoticAurCheckbox->isChecked(); + bool success = true; + bool changesApplied = false; + // Handle multilib changes if (currentMultilibState != m_originalMultilibState) { // Show confirmation dialog QString message; @@ -387,17 +668,65 @@ void SettingsWidget::onApplyClicked() { if (success) { m_originalMultilibState = currentMultilibState; - m_statusLabel->setText("Settings applied successfully! Please sync package databases."); - m_statusLabel->setStyleSheet("QLabel { color: #00aa00; padding: 10px; font-weight: bold; }"); - m_statusLabel->show(); - - m_applyButton->setEnabled(false); - m_revertButton->setEnabled(false); + changesApplied = true; // Emit signal to notify other widgets emit multilibStatusChanged(currentMultilibState); - - // Suggest database sync + } else { + success = false; + } + } + + // Handle chaotic-aur changes + if (currentChaoticAurState != m_originalChaoticAurState) { + // Show confirmation dialog + QString message; + if (currentChaoticAurState) { + message = "This will enable the chaotic-aur repository by modifying /etc/pacman.conf.\n" + "You will be prompted for administrator privileges.\n\n" + "Note: Make sure chaotic-keyring and chaotic-mirrorlist are installed first.\n\n" + "After enabling, you should run 'sudo pacman -Sy' to sync the databases.\n\n" + "Do you want to continue?"; + } else { + message = "This will disable the chaotic-aur repository by modifying /etc/pacman.conf.\n" + "You will be prompted for administrator privileges.\n\n" + "Do you want to continue?"; + } + + auto reply = QMessageBox::question(this, "Confirm Repository Change", + message, + QMessageBox::Yes | QMessageBox::No); + + if (reply != QMessageBox::Yes) { + return; + } + + // Apply the change + bool chaoticSuccess = false; + if (currentChaoticAurState) { + chaoticSuccess = enableChaoticAurInPacmanConf(); + } else { + chaoticSuccess = disableChaoticAurInPacmanConf(); + } + + if (chaoticSuccess) { + m_originalChaoticAurState = currentChaoticAurState; + changesApplied = true; + } else { + success = false; + } + } + + // Show results and offer database sync if changes were applied + if (changesApplied && success) { + m_statusLabel->setText("Settings applied successfully! Please sync package databases."); + m_statusLabel->setStyleSheet("QLabel { color: #00aa00; padding: 10px; font-weight: bold; }"); + m_statusLabel->show(); + + m_applyButton->setEnabled(false); + m_revertButton->setEnabled(false); + + // Suggest database sync auto reply = QMessageBox::question(this, "Sync Package Database", "Would you like to sync the package database now?\n" "(This will run 'pkexec pacman -Sy')", @@ -423,17 +752,17 @@ void SettingsWidget::onApplyClicked() { // Even if they don't sync now, refresh ALPM to detect the new repo configuration AlpmWrapper::instance().refreshDatabases(); } - } else { - m_statusLabel->setText("Failed to apply settings. Please check permissions."); - m_statusLabel->setStyleSheet("QLabel { color: #aa0000; padding: 10px; }"); - m_statusLabel->show(); - } + } else if (!success) { + m_statusLabel->setText("Failed to apply settings. Please check permissions."); + m_statusLabel->setStyleSheet("QLabel { color: #aa0000; padding: 10px; }"); + m_statusLabel->show(); } } void SettingsWidget::onRevertClicked() { // Revert to original state m_multilibRepoCheckbox->setChecked(m_originalMultilibState); + m_chaoticAurCheckbox->setChecked(m_originalChaoticAurState); m_applyButton->setEnabled(false); m_revertButton->setEnabled(false); m_statusLabel->setText("Changes reverted"); @@ -513,3 +842,122 @@ void SettingsWidget::onRemoveLockClicked() { "You must check the confirmation box to proceed."); } } + +void SettingsWidget::onSetupChaoticClicked() { + QMessageBox msgBox(this); + msgBox.setIcon(QMessageBox::Question); + msgBox.setWindowTitle("Setup Chaotic-AUR"); + msgBox.setText("Install Chaotic-AUR repository?"); + msgBox.setInformativeText( + "This will install:\n" + "• chaotic-keyring\n" + "• chaotic-mirrorlist\n\n" + "These packages are required to use the Chaotic-AUR repository.\n" + "You may need to manually add the repository to /etc/pacman.conf if not already configured."); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + + if (msgBox.exec() != QMessageBox::Yes) { + return; + } + + m_statusLabel->setText("Installing Chaotic-AUR packages..."); + m_statusLabel->setStyleSheet("QLabel { color: #0066cc; padding: 10px; }"); + m_statusLabel->show(); + m_setupChaoticButton->setEnabled(false); + + // Install chaotic-keyring and chaotic-mirrorlist + QProcess* process = new QProcess(this); + connect(process, QOverload::of(&QProcess::finished), + this, [this, process](int exitCode, QProcess::ExitStatus exitStatus) { + process->deleteLater(); + m_setupChaoticButton->setEnabled(true); + + if (exitCode == 0 && exitStatus == QProcess::NormalExit) { + m_statusLabel->setText("Chaotic-AUR packages installed successfully!"); + m_statusLabel->setStyleSheet("QLabel { color: #00aa00; padding: 10px; font-weight: bold; }"); + m_statusLabel->show(); + Logger::info("Chaotic-AUR packages installed successfully"); + + // Refresh the chaotic-aur checkbox status + loadCurrentSettings(); + + QMessageBox::information(this, "Success", + "Chaotic-AUR packages installed successfully!\n\n" + "If the repository is not yet configured, you may need to add it to /etc/pacman.conf:\n\n" + "[chaotic-aur]\n" + "Include = /etc/pacman.d/chaotic-mirrorlist"); + } else { + m_statusLabel->setText("Failed to install Chaotic-AUR packages."); + m_statusLabel->setStyleSheet("QLabel { color: #aa0000; padding: 10px; }"); + m_statusLabel->show(); + Logger::error("Failed to install Chaotic-AUR packages"); + + QMessageBox::critical(this, "Error", + "Failed to install Chaotic-AUR packages.\n" + "Please check the logs for details."); + } + }); + + process->start("pkexec", QStringList() << "pacman" << "-S" << "--noconfirm" + << "chaotic-keyring" << "chaotic-mirrorlist"); +} + +void SettingsWidget::onRemoveChaoticClicked() { + QMessageBox msgBox(this); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle("Remove Chaotic-AUR"); + msgBox.setText("Remove Chaotic-AUR repository?"); + msgBox.setInformativeText( + "This will remove:\n" + "• chaotic-keyring\n" + "• chaotic-mirrorlist\n\n" + "Note: You may need to manually remove the [chaotic-aur] section " + "from /etc/pacman.conf to fully disable the repository."); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + + if (msgBox.exec() != QMessageBox::Yes) { + return; + } + + m_statusLabel->setText("Removing Chaotic-AUR packages..."); + m_statusLabel->setStyleSheet("QLabel { color: #0066cc; padding: 10px; }"); + m_statusLabel->show(); + m_removeChaoticButton->setEnabled(false); + + // Remove chaotic-keyring and chaotic-mirrorlist + QProcess* process = new QProcess(this); + connect(process, QOverload::of(&QProcess::finished), + this, [this, process](int exitCode, QProcess::ExitStatus exitStatus) { + process->deleteLater(); + m_removeChaoticButton->setEnabled(true); + + if (exitCode == 0 && exitStatus == QProcess::NormalExit) { + m_statusLabel->setText("Chaotic-AUR packages removed successfully!"); + m_statusLabel->setStyleSheet("QLabel { color: #00aa00; padding: 10px; font-weight: bold; }"); + m_statusLabel->show(); + Logger::info("Chaotic-AUR packages removed successfully"); + + // Refresh the chaotic-aur checkbox status + loadCurrentSettings(); + + QMessageBox::information(this, "Success", + "Chaotic-AUR packages removed successfully!\n\n" + "To fully disable the repository, you may need to remove or comment out " + "the [chaotic-aur] section in /etc/pacman.conf"); + } else { + m_statusLabel->setText("Failed to remove Chaotic-AUR packages."); + m_statusLabel->setStyleSheet("QLabel { color: #aa0000; padding: 10px; }"); + m_statusLabel->show(); + Logger::error("Failed to remove Chaotic-AUR packages"); + + QMessageBox::critical(this, "Error", + "Failed to remove Chaotic-AUR packages.\n" + "Please check the logs for details."); + } + }); + + process->start("pkexec", QStringList() << "pacman" << "-Rns" << "--noconfirm" + << "chaotic-keyring" << "chaotic-mirrorlist"); +} diff --git a/src/gui/settings_widget.h b/src/gui/settings_widget.h index 1ea9f80..a225a57 100644 --- a/src/gui/settings_widget.h +++ b/src/gui/settings_widget.h @@ -24,10 +24,14 @@ class SettingsWidget : public QWidget { void setupUi(); void loadCurrentSettings(); void createRepositorySettings(); + void createChaoticAurSettings(); void createMaintenanceSettings(); bool isMultilibEnabledInPacmanConf() const; + bool isChaoticAurEnabledInPacmanConf() const; bool enableMultilibInPacmanConf(); bool disableMultilibInPacmanConf(); + bool enableChaoticAurInPacmanConf(); + bool disableChaoticAurInPacmanConf(); void applySettings(); // Repository settings @@ -35,6 +39,12 @@ class SettingsWidget : public QWidget { QCheckBox* m_coreRepoCheckbox; QCheckBox* m_extraRepoCheckbox; QCheckBox* m_multilibRepoCheckbox; + QCheckBox* m_chaoticAurCheckbox; + + // Chaotic-AUR setup + QGroupBox* m_chaoticAurGroup; + QPushButton* m_setupChaoticButton; + QPushButton* m_removeChaoticButton; // Maintenance settings QGroupBox* m_maintenanceGroup; @@ -49,11 +59,14 @@ class SettingsWidget : public QWidget { // Track original state bool m_originalMultilibState; + bool m_originalChaoticAurState; private slots: void onApplyClicked(); void onRevertClicked(); void onSettingsChanged(); + void onSetupChaoticClicked(); + void onRemoveChaoticClicked(); void onRemoveLockClicked(); }; From 7e21ad32ebb906975044e992737a9fd27dca6107 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Mon, 10 Nov 2025 20:01:06 +0000 Subject: [PATCH 33/71] make sure AUR packages do not run as root --- src/core/package_manager.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/core/package_manager.cpp b/src/core/package_manager.cpp index 2ec606b..ccb23d5 100644 --- a/src/core/package_manager.cpp +++ b/src/core/package_manager.cpp @@ -1,6 +1,7 @@ #include "package_manager.h" #include "../utils/logger.h" #include +#include PackageManager& PackageManager::instance() { static PackageManager instance; @@ -68,13 +69,13 @@ void PackageManager::installPackage(const QString& packageName, const QString& r Logger::info(QString("Installing package: %1 from %2").arg(packageName, repository.isEmpty() ? "default" : repository)); emit operationStarted(QString("Installing %1...").arg(packageName)); - // AUR packages should not use pkexec (must run as regular user) + // Determine if this is an AUR package bool isAUR = repository.toLower() == "aur"; QString helper = getHelperName(); QString command; if (isAUR && (m_helper == Helper::Yay || m_helper == Helper::Paru)) { - // AUR helpers run as regular user + // AUR packages - run helper as regular user (no pkexec) command = QString("%1 -S %2 --noconfirm").arg(helper, packageName); } else { // Official repos need root access @@ -102,13 +103,13 @@ void PackageManager::updatePackage(const QString& packageName, const QString& re Logger::info(QString("Updating package: %1 from %2").arg(packageName, repository.isEmpty() ? "default" : repository)); emit operationStarted(QString("Updating %1...").arg(packageName)); - // AUR packages should not use pkexec (must run as regular user) + // Determine if this is an AUR package bool isAUR = repository.toLower() == "aur"; QString helper = getHelperName(); QString command; if (isAUR && (m_helper == Helper::Yay || m_helper == Helper::Paru)) { - // AUR helpers run as regular user + // AUR packages - run helper as regular user (no pkexec) command = QString("%1 -S %2 --noconfirm").arg(helper, packageName); } else { // Official repos need root access From 4bd32d036bc6df3ea56a234a20419ff709d57c39 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Tue, 11 Nov 2025 20:19:12 +0000 Subject: [PATCH 34/71] show chaotic-aur in search tab dropdown filter if enabled --- src/gui/mainwindow.cpp | 22 +++++++++++++++++++--- src/gui/search_widget.cpp | 33 +++++++++++++++++++++++++++++++-- src/gui/search_widget.h | 2 +- src/gui/settings_widget.cpp | 8 ++++++++ src/gui/settings_widget.h | 2 ++ 5 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index d1cf994..08e0a09 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -56,10 +56,26 @@ void MainWindow::setupUi() { // Connect settings signals connect(m_settingsWidget, &SettingsWidget::multilibStatusChanged, - m_searchWidget, &SearchWidget::updateRepositoryList); + this, [this]() { + m_searchWidget->updateRepositoryList( + m_settingsWidget->isMultilibEnabled(), + m_settingsWidget->isChaoticAurEnabled() + ); + }); + + connect(m_settingsWidget, &SettingsWidget::chaoticAurStatusChanged, + this, [this]() { + m_searchWidget->updateRepositoryList( + m_settingsWidget->isMultilibEnabled(), + m_settingsWidget->isChaoticAurEnabled() + ); + }); - // Initialize search widget with current multilib state - m_searchWidget->updateRepositoryList(m_settingsWidget->isMultilibEnabled()); + // Initialize search widget with current repository states + m_searchWidget->updateRepositoryList( + m_settingsWidget->isMultilibEnabled(), + m_settingsWidget->isChaoticAurEnabled() + ); m_tabWidget->setTabPosition(QTabWidget::North); m_tabWidget->setMovable(false); diff --git a/src/gui/search_widget.cpp b/src/gui/search_widget.cpp index 00be66f..d4a7e20 100644 --- a/src/gui/search_widget.cpp +++ b/src/gui/search_widget.cpp @@ -221,7 +221,7 @@ void SearchWidget::onPackageClicked(const PackageInfo& info) { dialog->deleteLater(); } -void SearchWidget::updateRepositoryList(bool multilibEnabled) { +void SearchWidget::updateRepositoryList(bool multilibEnabled, bool chaoticAurEnabled) { // Save the current selection int currentIndex = m_filterCombo->currentIndex(); QString currentFilter = m_filterCombo->itemData(currentIndex).toString(); @@ -235,6 +235,16 @@ void SearchWidget::updateRepositoryList(bool multilibEnabled) { } } + // Check if chaotic-aur already exists in the list + bool chaoticAurExists = false; + for (int i = 0; i < m_filterCombo->count(); ++i) { + if (m_filterCombo->itemData(i).toString() == "chaotic-aur") { + chaoticAurExists = true; + break; + } + } + + // Handle multilib if (multilibEnabled && !multilibExists) { // Add multilib to the dropdown (insert before AUR) int aurIndex = m_filterCombo->findData("AUR"); @@ -253,12 +263,31 @@ void SearchWidget::updateRepositoryList(bool multilibEnabled) { } } + // Handle chaotic-aur + if (chaoticAurEnabled && !chaoticAurExists) { + // Add chaotic-aur to the dropdown (insert before AUR) + int aurIndex = m_filterCombo->findData("AUR"); + if (aurIndex != -1) { + m_filterCombo->insertItem(aurIndex, "Chaotic-AUR", "chaotic-aur"); + } else { + m_filterCombo->addItem("Chaotic-AUR", "chaotic-aur"); + } + Logger::info("Added chaotic-aur repository to search filter"); + } else if (!chaoticAurEnabled && chaoticAurExists) { + // Remove chaotic-aur from the dropdown + int chaoticAurIndex = m_filterCombo->findData("chaotic-aur"); + if (chaoticAurIndex != -1) { + m_filterCombo->removeItem(chaoticAurIndex); + Logger::info("Removed chaotic-aur repository from search filter"); + } + } + // Restore previous selection if it still exists int newIndex = m_filterCombo->findData(currentFilter); if (newIndex != -1) { m_filterCombo->setCurrentIndex(newIndex); } else { - // If previous selection was multilib and it's now removed, select "All" + // If previous selection was removed, select "All" m_filterCombo->setCurrentIndex(0); } } diff --git a/src/gui/search_widget.h b/src/gui/search_widget.h index 6db8d17..ed48b8e 100644 --- a/src/gui/search_widget.h +++ b/src/gui/search_widget.h @@ -21,7 +21,7 @@ class SearchWidget : public QWidget { ~SearchWidget() override = default; public slots: - void updateRepositoryList(bool multilibEnabled); + void updateRepositoryList(bool multilibEnabled, bool chaoticAurEnabled = false); private: void setupUi(); diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp index f749e6e..1f51bb3 100644 --- a/src/gui/settings_widget.cpp +++ b/src/gui/settings_widget.cpp @@ -712,6 +712,9 @@ void SettingsWidget::onApplyClicked() { if (chaoticSuccess) { m_originalChaoticAurState = currentChaoticAurState; changesApplied = true; + + // Emit signal to notify other widgets + emit chaoticAurStatusChanged(currentChaoticAurState); } else { success = false; } @@ -777,6 +780,11 @@ bool SettingsWidget::isMultilibEnabled() const { (m_multilibRepoCheckbox->isChecked() == m_originalMultilibState); } +bool SettingsWidget::isChaoticAurEnabled() const { + return m_chaoticAurCheckbox->isChecked() && + (m_chaoticAurCheckbox->isChecked() == m_originalChaoticAurState); +} + void SettingsWidget::applySettings() { onApplyClicked(); } diff --git a/src/gui/settings_widget.h b/src/gui/settings_widget.h index a225a57..bab7df0 100644 --- a/src/gui/settings_widget.h +++ b/src/gui/settings_widget.h @@ -16,9 +16,11 @@ class SettingsWidget : public QWidget { ~SettingsWidget() override = default; bool isMultilibEnabled() const; + bool isChaoticAurEnabled() const; signals: void multilibStatusChanged(bool enabled); + void chaoticAurStatusChanged(bool enabled); private: void setupUi(); From f5d02e9dcae5327e761ef3c85e5a5c28416c4631 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Tue, 11 Nov 2025 20:33:15 +0000 Subject: [PATCH 35/71] add launch button for apps with a .desktop file --- src/gui/mainwindow.cpp | 2 +- src/gui/package_details_dialog.cpp | 109 +++++++++++++++++++++++++++++ src/gui/package_details_dialog.h | 3 + 3 files changed, 113 insertions(+), 1 deletion(-) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 08e0a09..2b05f2c 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -118,7 +118,7 @@ void MainWindow::createMenuBar() { "ALG App Store (Beta)\n\n" "A modern package manager for Arch Linux\n" "Built with Qt6 and C++17\n\n" - "© 2025 Arch Linux GUI"); + "© 2025 Arka Linux GUI"); }); helpMenu->addAction(aboutAction); } diff --git a/src/gui/package_details_dialog.cpp b/src/gui/package_details_dialog.cpp index b97f664..4c04b4e 100644 --- a/src/gui/package_details_dialog.cpp +++ b/src/gui/package_details_dialog.cpp @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include PackageDetailsDialog::PackageDetailsDialog(const PackageInfo& info, QWidget* parent) : QDialog(parent) @@ -30,6 +33,7 @@ PackageDetailsDialog::PackageDetailsDialog(const PackageInfo& info, QWidget* par , m_lastUpdatedLabel(new QLabel(this)) , m_installButton(new QPushButton("Install", this)) , m_uninstallButton(new QPushButton("Uninstall", this)) + , m_launchButton(new QPushButton("Launch", this)) , m_closeButton(new QPushButton("Close", this)) , m_statusBadge(new QLabel(this)) , m_progressBar(new QProgressBar(this)) @@ -320,6 +324,11 @@ void PackageDetailsDialog::setupUi() { connect(m_uninstallButton, &QPushButton::clicked, this, &PackageDetailsDialog::onUninstall); buttonLayout->addWidget(m_uninstallButton); + m_launchButton->setMinimumWidth(100); + m_launchButton->setMinimumHeight(35); + connect(m_launchButton, &QPushButton::clicked, this, &PackageDetailsDialog::launchApplication); + buttonLayout->addWidget(m_launchButton); + m_closeButton->setMinimumWidth(100); m_closeButton->setMinimumHeight(35); connect(m_closeButton, &QPushButton::clicked, this, &QDialog::accept); @@ -415,6 +424,10 @@ void PackageDetailsDialog::checkInstallStatus() { void PackageDetailsDialog::updateButtonStates() { m_installButton->setEnabled(!m_isInstalled); m_uninstallButton->setEnabled(m_isInstalled); + + // Enable launch button only if installed and has a desktop file + QString desktopFile = findDesktopFile(); + m_launchButton->setEnabled(m_isInstalled && !desktopFile.isEmpty()); } void PackageDetailsDialog::onInstall() { @@ -428,6 +441,7 @@ void PackageDetailsDialog::onInstall() { // Disable buttons during operation m_installButton->setEnabled(false); m_uninstallButton->setEnabled(false); + m_launchButton->setEnabled(false); m_closeButton->setEnabled(false); PackageManager::instance().installPackage(m_info.name, m_info.repository); @@ -447,6 +461,7 @@ void PackageDetailsDialog::onUninstall() { // Disable buttons during operation m_installButton->setEnabled(false); m_uninstallButton->setEnabled(false); + m_launchButton->setEnabled(false); m_closeButton->setEnabled(false); PackageManager::instance().uninstallPackage(m_info.name, m_info.repository); @@ -587,3 +602,97 @@ void PackageDetailsDialog::onOperationError(const QString& error) { QMessageBox::critical(this, "Error", error); } + +QString PackageDetailsDialog::findDesktopFile() const { + if (!m_isInstalled) { + return QString(); + } + + // Common locations for .desktop files + QStringList desktopDirs = { + "/usr/share/applications", + "/usr/local/share/applications", + QDir::homePath() + "/.local/share/applications" + }; + + // Try to find desktop file matching the package name + // Common patterns: package.desktop, package-*.desktop + QStringList patterns = { + m_info.name + ".desktop", + m_info.name + "-*.desktop" + }; + + for (const QString& dir : desktopDirs) { + QDir desktopDir(dir); + if (!desktopDir.exists()) { + continue; + } + + for (const QString& pattern : patterns) { + QStringList matches = desktopDir.entryList(QStringList() << pattern, QDir::Files); + if (!matches.isEmpty()) { + QString desktopFile = desktopDir.absoluteFilePath(matches.first()); + Logger::info(QString("Found desktop file for %1: %2").arg(m_info.name, desktopFile)); + return desktopFile; + } + } + } + + Logger::debug(QString("No desktop file found for package: %1").arg(m_info.name)); + return QString(); +} + +void PackageDetailsDialog::launchApplication() { + QString desktopFile = findDesktopFile(); + + if (desktopFile.isEmpty()) { + QMessageBox::warning(this, "Launch Failed", + QString("Could not find a desktop file for %1.\n" + "This application may not have a graphical interface or " + "may need to be launched from the terminal.").arg(m_info.name)); + return; + } + + // Launch the application using gtk-launch or similar + QProcess* process = new QProcess(this); + + // Try gtk-launch first (works on most desktop environments) + QString baseName = QFileInfo(desktopFile).fileName(); + + connect(process, QOverload::of(&QProcess::finished), + this, [this, process, baseName](int exitCode, QProcess::ExitStatus exitStatus) { + process->deleteLater(); + + if (exitCode != 0 || exitStatus != QProcess::NormalExit) { + Logger::error(QString("Failed to launch application: %1").arg(baseName)); + QMessageBox::warning(this, "Launch Failed", + QString("Failed to launch %1.\n" + "Exit code: %2").arg(m_info.name).arg(exitCode)); + } else { + Logger::info(QString("Successfully launched: %1").arg(baseName)); + } + }); + + // Try gtk-launch first + process->start("gtk-launch", QStringList() << baseName); + + // If gtk-launch doesn't start, try alternative methods + if (!process->waitForStarted(1000)) { + // Try dex (Desktop Entry Execution) + process->start("dex", QStringList() << desktopFile); + + if (!process->waitForStarted(1000)) { + // Try exo-open (XFCE) + process->start("exo-open", QStringList() << desktopFile); + + if (!process->waitForStarted(1000)) { + // Last resort: try to parse and execute the Exec line + process->deleteLater(); + QMessageBox::warning(this, "Launch Failed", + "Could not find a suitable desktop file launcher.\n" + "Please install gtk-launch, dex, or exo-open."); + Logger::error("No desktop file launcher available"); + } + } + } +} diff --git a/src/gui/package_details_dialog.h b/src/gui/package_details_dialog.h index d11ce01..3f44d79 100644 --- a/src/gui/package_details_dialog.h +++ b/src/gui/package_details_dialog.h @@ -23,6 +23,8 @@ class PackageDetailsDialog : public QDialog { void hideProgress(); void toggleLogViewer(); void parseProgressOutput(const QString& output); + QString findDesktopFile() const; + void launchApplication(); PackageInfo m_info; bool m_isInstalled; @@ -38,6 +40,7 @@ class PackageDetailsDialog : public QDialog { QPushButton* m_installButton; QPushButton* m_uninstallButton; + QPushButton* m_launchButton; QPushButton* m_closeButton; QLabel* m_statusBadge; From 8797b1e375f9d56679c16daa20a5d16809e07b2d Mon Sep 17 00:00:00 2001 From: demonkiller Date: Tue, 11 Nov 2025 20:58:07 +0000 Subject: [PATCH 36/71] add version number --- src/gui/mainwindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 2b05f2c..1bd1494 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -117,6 +117,7 @@ void MainWindow::createMenuBar() { QMessageBox::about(this, "About ALG App Store", "ALG App Store (Beta)\n\n" "A modern package manager for Arch Linux\n" + "Version: 0.2.15\n" "Built with Qt6 and C++17\n\n" "© 2025 Arka Linux GUI"); }); From 0f5a0451bdb39b258f3d61855088b2d22fac595b Mon Sep 17 00:00:00 2001 From: demonkiller Date: Tue, 11 Nov 2025 20:59:36 +0000 Subject: [PATCH 37/71] README: alpm as dependency --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c622329..ffc8715 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ A modern, native package manager for Arch Linux built with Qt6 and C++17. This i ### Build Dependencies ```bash -sudo pacman -S base-devel cmake qt6-base qt6-svg pkgconf +sudo pacman -S base-devel cmake qt6-base qt6-svg alpm pkgconf ``` ### Runtime Dependencies From 894afab2483a202a88721b80e5231ec78d0e3e84 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Tue, 11 Nov 2025 21:04:19 +0000 Subject: [PATCH 38/71] add contributing document --- CONTRIBUTING.md | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..0fefe26 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,113 @@ +# Contributing to ALG Welcome + +Contributions are welcome and appreciated! To contribute: + +- Code follows C++17 standards +- Proper error handling and logging +- Thread safety for concurrent operations +- Qt best practices for GUI code +- Comments for complex logic + +### How to contribute +1. **Fork the Repository.** +2. **Create a New Branch** for your feature or bug fix: + ```bash + git checkout -b feature/your-feature-name + ``` +3. **Make Your Changes:** + - Follow modern C++17 best practices + - Use Qt6 APIs and conventions + - Ensure code compiles without warnings + - Test on your desktop environment (KDE, GNOME, or Xfce) +4. **Commit Your Changes** and push your branch: + ```bash + git commit -m "Add new feature or fix bug" + git push -u origin feature/your-feature-name + ``` +5. **Open a Pull Request** describing your changes. + + +## Project Structure + +``` + +``` + +## Understanding the code +### Core +#### AlpmWrapper (Singleton) +Wraps libalpm functionality with thread-safe operations: +- Package searching +- Installed package enumeration +- Update detection +- Package information retrieval + +#### AurHelper +Handles AUR integration: +- Package search via AUR RPC API +- Package information retrieval +- Update checking for AUR packages + +#### PackageManager (Singleton) +Manages package operations with proper privilege escalation: +- Install/uninstall packages +- Update operations +- Automatic helper detection (yay/paru/pacman) +- Process management with signals + +### GUI Components +- **MainWindow**: Tabbed interface container +- **HomeWidget**: Featured packages display +- **SearchWidget**: Package search with filtering +- **InstalledWidget**: Installed package browser +- **UpdatesWidget**: Update management +- **PackageCard**: Reusable package display widget +- **PackageDetailsDialog**: Detailed package information + +## Design Decisions + +### Modern C++ Features + +- **Smart Pointers**: `std::unique_ptr` and `std::shared_ptr` for automatic memory management +- **Move Semantics**: `std::move()` for efficient resource transfer +- **Auto Type Deduction**: Cleaner, more maintainable code +- **Range-based Loops**: Cleaner iteration +- **Lambda Functions**: Inline callbacks and signal connections + +### Thread Safety + +- **Mutexes**: `std::mutex` and `std::lock_guard` for critical sections +- **Qt Concurrent**: `QtConcurrent::run()` for background operations +- **Signal/Slot**: Qt's thread-safe communication mechanism + +### Singleton Pattern + +Used for `AlpmWrapper` and `PackageManager` to ensure: +- Single libalpm handle instance +- Centralized package operation management +- Thread-safe access + +## Logging + +The application includes a comprehensive logging system: + +```cpp +Logger::info("Information message"); +Logger::warning("Warning message"); +Logger::error("Error message"); +Logger::debug("Debug message"); +``` + +Logs are output to standard output and can be redirected for persistent logging. + +## Package Helper Detection + +The application automatically detects available package helpers in this order: + +1. **yay** - Preferred for AUR support +2. **paru** - Alternative AUR helper +3. **pacman** - Fallback (official repos only) + +## Privilege Escalation + +Package operations require root privileges. The application uses `pkexec` (PolicyKit) for secure privilege escalation. Ensure PolicyKit is properly configured on your system. \ No newline at end of file From 7ad1f1ebd4c171e5dfa888b80ff6c62f2442aca7 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Tue, 11 Nov 2025 21:08:00 +0000 Subject: [PATCH 39/71] clean up readme --- README.md | 151 +++--------------------------------------------------- 1 file changed, 6 insertions(+), 145 deletions(-) diff --git a/README.md b/README.md index ffc8715..3fe1751 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ A modern, native package manager for Arch Linux built with Qt6 and C++17. This i - **Language**: C++17 - **GUI Framework**: Qt6 (Widgets) - **Package Management**: libalpm (Arch Linux Package Manager library) -- **AUR Integration**: AUR RPC API via Qt Network +- **AUR Integration**: AUR RPC API via Qt Network + Chaotic AUR Support - **Build System**: CMake - **Threading**: Qt Concurrent & STL threading @@ -30,13 +30,7 @@ A modern, native package manager for Arch Linux built with Qt6 and C++17. This i sudo pacman -S base-devel cmake qt6-base qt6-svg alpm pkgconf ``` -### Runtime Dependencies - -```bash -sudo pacman -S qt6-base libalpm polkit curl -# Optional but recommended: -sudo pacman -S yay # or paru -``` +You can optionally also have either either yay or paru if you would like to work with packages from the AUR. ## Building @@ -69,154 +63,21 @@ alg-app-store ``` -### Key Components - -#### AlpmWrapper (Singleton) -Wraps libalpm functionality with thread-safe operations: -- Package searching -- Installed package enumeration -- Update detection -- Package information retrieval - -#### AurHelper -Handles AUR integration: -- Package search via AUR RPC API -- Package information retrieval -- Update checking for AUR packages - -#### PackageManager (Singleton) -Manages package operations with proper privilege escalation: -- Install/uninstall packages -- Update operations -- Automatic helper detection (yay/paru/pacman) -- Process management with signals - -#### GUI Components -- **MainWindow**: Tabbed interface container -- **HomeWidget**: Featured packages display -- **SearchWidget**: Package search with filtering -- **InstalledWidget**: Installed package browser -- **UpdatesWidget**: Update management -- **PackageCard**: Reusable package display widget -- **PackageDetailsDialog**: Detailed package information - -## Design Decisions - -### Modern C++ Features - -- **Smart Pointers**: `std::unique_ptr` and `std::shared_ptr` for automatic memory management -- **Move Semantics**: `std::move()` for efficient resource transfer -- **Auto Type Deduction**: Cleaner, more maintainable code -- **Range-based Loops**: Cleaner iteration -- **Lambda Functions**: Inline callbacks and signal connections - -### Thread Safety - -- **Mutexes**: `std::mutex` and `std::lock_guard` for critical sections -- **Qt Concurrent**: `QtConcurrent::run()` for background operations -- **Signal/Slot**: Qt's thread-safe communication mechanism - -### Singleton Pattern - -Used for `AlpmWrapper` and `PackageManager` to ensure: -- Single libalpm handle instance -- Centralized package operation management -- Thread-safe access - -## Logging - -The application includes a comprehensive logging system: - -```cpp -Logger::info("Information message"); -Logger::warning("Warning message"); -Logger::error("Error message"); -Logger::debug("Debug message"); -``` - -Logs are output to standard output and can be redirected for persistent logging. - -## Package Helper Detection - -The application automatically detects available package helpers in this order: - -1. **yay** - Preferred for AUR support -2. **paru** - Alternative AUR helper -3. **pacman** - Fallback (official repos only) - -## Privilege Escalation - -Package operations require root privileges. The application uses `pkexec` (PolicyKit) for secure privilege escalation. Ensure PolicyKit is properly configured on your system. - -## Contributing - -Contributions are welcome! Please ensure: - -- Code follows C++17 standards -- Proper error handling and logging -- Thread safety for concurrent operations -- Qt best practices for GUI code -- Comments for complex logic - ## License This project is part of the Arch Linux GUI project. +It is distributed under the MIT License. Check LICENSE. ## Credits +- **Author**: DemonKiller - **Original Project**: Wails-based ALG App Store - **Rewrite**: Qt6/C++ implementation - **Community**: Arch Linux and Qt communities -## Troubleshooting - -### Build Issues - -**Missing Qt6**: -```bash -sudo pacman -S qt6-base qt6-svg -``` - -**Missing libalpm**: -```bash -sudo pacman -S pacman -``` - -### Runtime Issues - -**Permission Denied**: -Ensure PolicyKit is running: -```bash -systemctl status polkit -``` - -**Package Helper Not Found**: -Install yay or paru: -```bash -sudo pacman -S yay -``` - -**ALPM Initialization Failed**: -Check pacman configuration: -```bash -sudo pacman -Syy -``` - -## Future Enhancements - -- Package categories/tags -- Package ratings and reviews -- Automated testing suite -- Flatpak integration -- AppImage support -- Configuration file support -- Multi-language support -- Package download progress -- Transaction history -- Dependency visualization - ## Contact For issues, questions, or contributions, please visit: - GitHub: https://github.com/arch-linux-gui/alg-app-store -- Website: https://archlinuxgui.in +- Website: https://arkalinuxgui.org +- Discord: https://discord.com/invite/NgAFEw9Tkf \ No newline at end of file From 9f42cb3a5b517e790aea4272316b5e222fd2d707 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Tue, 11 Nov 2025 21:09:30 +0000 Subject: [PATCH 40/71] add LICENSE --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..33100ba --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 ALG Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file From 22ae227982fbed6f4f89188d1d1f7229e432e10e Mon Sep 17 00:00:00 2001 From: demonkiller Date: Tue, 11 Nov 2025 21:11:37 +0000 Subject: [PATCH 41/71] update todo --- TODO.md | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/TODO.md b/TODO.md index 2555835..7301e79 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,19 @@ -- [x] Search packages from all DB: Core, Extra & AUR -- [x] Search Local DB and display packages in Install screen -- [x] Add Install Func -- [x] Add Uninstall Func -- [x] Do State Management while installing with loader -- [x] Do State Managerment while uninstalling with loader -- [ ] Add Update All for updation of all packages +- [x] Add chaotic aur to search tab if enabled +- [x] Add launch button on package card if package is installed and remove when uninstalled +- [] Add detailed mirrorlist tab to set mirrorlist +- [] Add version information +- [] + + +## Future Enhancements + +- Package categories/tags +- Package ratings and reviews +- Automated testing suite +- Flatpak integration +- AppImage support +- Configuration file support +- Multi-language support +- Package download progress +- Transaction history +- Dependency visualization \ No newline at end of file From a783730811a215c691c054dad106bacff769dc09 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Tue, 11 Nov 2025 21:14:01 +0000 Subject: [PATCH 42/71] add CI --- .github/workflows/build.yml | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..7c33723 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,53 @@ +name: Build ALG App Store + +on: + push: + branches: [ "main", "qt6/c++" ] + pull_request: + branches: [ "main", "qt6/c++" ] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential \ + cmake \ + qt6-base-dev \ + qt6-tools-dev \ + qt6-tools-dev-tools \ + libalpm-dev \ + libarchive-dev \ + libcurl4-openssl-dev \ + pkg-config + + - name: Configure CMake + run: | + mkdir -p build + cd build + cmake .. + + - name: Build + run: | + cd build + make -j$(nproc) + + - name: Check build artifacts + run: | + ls -lh build/alg-app-store + file build/alg-app-store + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: alg-app-store + path: build/alg-app-store + retention-days: 7 From d8058597b9a330c75b2d39129296e53eecd2e6dc Mon Sep 17 00:00:00 2001 From: demonkiller Date: Tue, 11 Nov 2025 21:16:56 +0000 Subject: [PATCH 43/71] directory structure in contributing --- CONTRIBUTING.md | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0fefe26..48ad1ab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,7 +30,49 @@ Contributions are welcome and appreciated! To contribute: ## Project Structure ``` - +├── assets +│ ├── alg-app-store.desktop +│ └── alg-app-store.png +├── build.sh +├── CMakeLists.txt +├── CONTRIBUTING.md +├── DEVELOPER_GUIDE.md +├── LICENSE +├── QT_REWRITE_SUMMARY.md +├── README.md +├── src +│ ├── core +│ │ ├── alpm_wrapper.cpp +│ │ ├── alpm_wrapper.h +│ │ ├── aur_helper.cpp +│ │ ├── aur_helper.h +│ │ ├── package_manager.cpp +│ │ └── package_manager.h +│ ├── gui +│ │ ├── home_widget.cpp +│ │ ├── home_widget.h +│ │ ├── installed_widget.cpp +│ │ ├── installed_widget.h +│ │ ├── mainwindow.cpp +│ │ ├── mainwindow.h +│ │ ├── package_card.cpp +│ │ ├── package_card.h +│ │ ├── package_details_dialog.cpp +│ │ ├── package_details_dialog.h +│ │ ├── search_widget.cpp +│ │ ├── search_widget.h +│ │ ├── settings_widget.cpp +│ │ ├── settings_widget.h +│ │ ├── updates_widget.cpp +│ │ └── updates_widget.h +│ ├── main.cpp +│ └── utils +│ ├── logger.h +│ └── types.h +├── stylesheet.qss +└── TODO.md + +6 directories, 36 files ``` ## Understanding the code From ef0258d83eb0599b43fd0bc56a8020e65ace8d5f Mon Sep 17 00:00:00 2001 From: demonkillerr Date: Wed, 12 Nov 2025 11:51:44 +0000 Subject: [PATCH 44/71] redo home tab featured packages --- src/gui/home_widget.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/gui/home_widget.cpp b/src/gui/home_widget.cpp index 197281e..35f914a 100644 --- a/src/gui/home_widget.cpp +++ b/src/gui/home_widget.cpp @@ -54,12 +54,15 @@ void HomeWidget::loadFeaturedPackages() { {"firefox", "Latest", "Fast, Private & Safe Web Browser", "extra"}, {"gimp", "Latest", "GNU Image Manipulation Program", "extra"}, {"vlc", "Latest", "Multi-platform MPEG, VCD/DVD, and DivX player", "extra"}, - {"visual-studio-code-bin", "Latest", "Visual Studio Code (official binary version)", "AUR"}, - {"libreoffice-still", "Latest", "LibreOffice maintenance branch", "extra"}, + {"telegram-desktop", "Latest", "Official Telegram Desktop client", "extra"}, + {"obs-studio", "Latest", "Free, open source software for live streaming and recording", "extra"}, {"blender", "Latest", "A fully integrated 3D graphics creation suite", "extra"}, - {"zed", "Latest", "A high-performance, multiplayer code editor", "extra"}, - {"git", "Latest", "The fast distributed version control system", "extra"}, - {"google-chrome", "Latest", "The popular web browser by Google", "AUR"} + {"spotify", "Latest", "A proprietary music streaming service", "AUR"}, + {"discord", "Latest", "All-in-one voice and text chat for gamers", "extra"}, + {"google-chrome", "Latest", "The popular web browser by Google", "AUR"}, + {"visual-studio-code-bin", "Latest", "Visual Studio Code (official binary version)", "AUR"}, + {"libreoffice-still", "Latest", "Free and Open Source Office Suite", "extra"}, + {"zoom", "Latest", "Video Conferencing and Web Conferencing Service", "AUR"} }; Logger::info(QString("Loaded %1 featured packages").arg(m_featuredPackages.size())); From eaf763979d0f5dfede93252a3c0de268b73f81cb Mon Sep 17 00:00:00 2001 From: demonkillerr Date: Wed, 12 Nov 2025 11:52:50 +0000 Subject: [PATCH 45/71] regex for searching unsual .desktop files --- src/gui/package_details_dialog.cpp | 93 ++++++++++++++++++++++++++++++ src/gui/package_details_dialog.h | 3 + 2 files changed, 96 insertions(+) diff --git a/src/gui/package_details_dialog.cpp b/src/gui/package_details_dialog.cpp index 4c04b4e..17d7438 100644 --- a/src/gui/package_details_dialog.cpp +++ b/src/gui/package_details_dialog.cpp @@ -628,6 +628,7 @@ QString PackageDetailsDialog::findDesktopFile() const { continue; } + // First try exact patterns for (const QString& pattern : patterns) { QStringList matches = desktopDir.entryList(QStringList() << pattern, QDir::Files); if (!matches.isEmpty()) { @@ -636,12 +637,104 @@ QString PackageDetailsDialog::findDesktopFile() const { return desktopFile; } } + + // If not found, try fuzzy matching with all .desktop files + QStringList allDesktopFiles = desktopDir.entryList(QStringList() << "*.desktop", QDir::Files); + + // Create regex patterns for fuzzy matching + // Match if package name appears in the desktop file name (case-insensitive) + // Handle cases like: com.obsproject.Studio.desktop -> obs + // code.desktop -> visual-studio-code-bin + QString packageNameLower = m_info.name.toLower(); + QStringList nameVariants; + + // Add the full package name + nameVariants << packageNameLower; + + // Extract keywords from package name (split by dash and underscore) + QStringList parts = packageNameLower.split(QRegularExpression("[-_]")); + for (const QString& part : parts) { + if (part.length() > 2) { // Skip very short parts + nameVariants << part; + } + } + + // Special handling for common patterns + if (packageNameLower.contains("visual-studio-code")) { + nameVariants << "code" << "vscode"; + } + if (packageNameLower.contains("obs")) { + nameVariants << "obs" << "obsproject" << "studio"; + } + + // Search through all desktop files + for (const QString& desktopFileName : allDesktopFiles) { + QString fileNameLower = desktopFileName.toLower(); + + // Check if any variant matches in the desktop file name + for (const QString& variant : nameVariants) { + if (fileNameLower.contains(variant)) { + QString desktopFile = desktopDir.absoluteFilePath(desktopFileName); + + // Verify this is the right file by checking the Exec line contains package name + if (verifyDesktopFile(desktopFile, packageNameLower, nameVariants)) { + Logger::info(QString("Found desktop file for %1 via fuzzy match: %2") + .arg(m_info.name, desktopFile)); + return desktopFile; + } + } + } + } } Logger::debug(QString("No desktop file found for package: %1").arg(m_info.name)); return QString(); } +bool PackageDetailsDialog::verifyDesktopFile(const QString& desktopFilePath, + const QString& packageName, + const QStringList& nameVariants) const { + QFile file(desktopFilePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + return false; + } + + QTextStream in(&file); + QString content = in.readAll(); + file.close(); + + // Check if Exec line contains any of our name variants + QRegularExpression execPattern(R"(^Exec=(.*)$)", QRegularExpression::MultilineOption); + auto match = execPattern.match(content); + + if (match.hasMatch()) { + QString execLine = match.captured(1).toLower(); + + // Check if any variant appears in the Exec line + for (const QString& variant : nameVariants) { + if (execLine.contains(variant)) { + return true; + } + } + } + + // Also check Name field as a fallback + QRegularExpression namePattern(R"(^Name=(.*)$)", QRegularExpression::MultilineOption); + match = namePattern.match(content); + + if (match.hasMatch()) { + QString nameField = match.captured(1).toLower(); + + for (const QString& variant : nameVariants) { + if (nameField.contains(variant)) { + return true; + } + } + } + + return false; +} + void PackageDetailsDialog::launchApplication() { QString desktopFile = findDesktopFile(); diff --git a/src/gui/package_details_dialog.h b/src/gui/package_details_dialog.h index 3f44d79..0e2dba9 100644 --- a/src/gui/package_details_dialog.h +++ b/src/gui/package_details_dialog.h @@ -24,6 +24,9 @@ class PackageDetailsDialog : public QDialog { void toggleLogViewer(); void parseProgressOutput(const QString& output); QString findDesktopFile() const; + bool verifyDesktopFile(const QString& desktopFilePath, + const QString& packageName, + const QStringList& nameVariants) const; void launchApplication(); PackageInfo m_info; From fc39e1097a9fb2344845f67b33395a63918087db Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 12:07:07 +0000 Subject: [PATCH 46/71] improve regex for searching desktop files for packages --- src/gui/package_details_dialog.cpp | 68 ++++++++++++++++++++++-------- src/gui/package_details_dialog.h | 5 +-- 2 files changed, 53 insertions(+), 20 deletions(-) diff --git a/src/gui/package_details_dialog.cpp b/src/gui/package_details_dialog.cpp index 17d7438..bbe9dd2 100644 --- a/src/gui/package_details_dialog.cpp +++ b/src/gui/package_details_dialog.cpp @@ -642,9 +642,8 @@ QString PackageDetailsDialog::findDesktopFile() const { QStringList allDesktopFiles = desktopDir.entryList(QStringList() << "*.desktop", QDir::Files); // Create regex patterns for fuzzy matching - // Match if package name appears in the desktop file name (case-insensitive) - // Handle cases like: com.obsproject.Studio.desktop -> obs - // code.desktop -> visual-studio-code-bin + // Handle reverse domain names: com.obsproject.Studio.desktop -> obs-studio + // Handle simple names: code.desktop -> visual-studio-code-bin QString packageNameLower = m_info.name.toLower(); QStringList nameVariants; @@ -653,32 +652,68 @@ QString PackageDetailsDialog::findDesktopFile() const { // Extract keywords from package name (split by dash and underscore) QStringList parts = packageNameLower.split(QRegularExpression("[-_]")); + QStringList significantParts; for (const QString& part : parts) { - if (part.length() > 2) { // Skip very short parts - nameVariants << part; + if (part.length() > 3) { // Skip very short parts to avoid false matches + significantParts << part; } } // Special handling for common patterns + QStringList specialVariants; if (packageNameLower.contains("visual-studio-code")) { - nameVariants << "code" << "vscode"; + specialVariants << "vscode" << "code"; + } else if (packageNameLower == "obs-studio") { + // For obs-studio, look for obsproject specifically + specialVariants << "obsproject"; } - if (packageNameLower.contains("obs")) { - nameVariants << "obs" << "obsproject" << "studio"; + + // Try special variants first (highest priority) + for (const QString& variant : specialVariants) { + for (const QString& desktopFileName : allDesktopFiles) { + QString fileNameLower = desktopFileName.toLower(); + + if (fileNameLower.contains(variant)) { + QString desktopFile = desktopDir.absoluteFilePath(desktopFileName); + + if (verifyDesktopFile(desktopFile, nameVariants + specialVariants + significantParts)) { + Logger::info(QString("Found desktop file for %1 via special match: %2") + .arg(m_info.name, desktopFile)); + return desktopFile; + } + } + } } - // Search through all desktop files + // Try full package name match for (const QString& desktopFileName : allDesktopFiles) { QString fileNameLower = desktopFileName.toLower(); - // Check if any variant matches in the desktop file name - for (const QString& variant : nameVariants) { - if (fileNameLower.contains(variant)) { + if (fileNameLower.contains(packageNameLower)) { + QString desktopFile = desktopDir.absoluteFilePath(desktopFileName); + + if (verifyDesktopFile(desktopFile, nameVariants + specialVariants + significantParts)) { + Logger::info(QString("Found desktop file for %1 via full name match: %2") + .arg(m_info.name, desktopFile)); + return desktopFile; + } + } + } + + // Finally, try matching individual significant parts (but verify carefully) + for (const QString& part : significantParts) { + for (const QString& desktopFileName : allDesktopFiles) { + QString fileNameLower = desktopFileName.toLower(); + + // Use word boundary-like matching: ensure part is not in the middle of another word + // Check if part appears as a separate component (after . or at start, before . or -) + QRegularExpression wordBoundary(QString("(^|[._-])%1([._-]|$)").arg(QRegularExpression::escape(part))); + + if (wordBoundary.match(fileNameLower).hasMatch()) { QString desktopFile = desktopDir.absoluteFilePath(desktopFileName); - // Verify this is the right file by checking the Exec line contains package name - if (verifyDesktopFile(desktopFile, packageNameLower, nameVariants)) { - Logger::info(QString("Found desktop file for %1 via fuzzy match: %2") + if (verifyDesktopFile(desktopFile, nameVariants + specialVariants + significantParts)) { + Logger::info(QString("Found desktop file for %1 via word match: %2") .arg(m_info.name, desktopFile)); return desktopFile; } @@ -691,8 +726,7 @@ QString PackageDetailsDialog::findDesktopFile() const { return QString(); } -bool PackageDetailsDialog::verifyDesktopFile(const QString& desktopFilePath, - const QString& packageName, +bool PackageDetailsDialog::verifyDesktopFile(const QString& desktopFilePath, const QStringList& nameVariants) const { QFile file(desktopFilePath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { diff --git a/src/gui/package_details_dialog.h b/src/gui/package_details_dialog.h index 0e2dba9..dd94aee 100644 --- a/src/gui/package_details_dialog.h +++ b/src/gui/package_details_dialog.h @@ -24,9 +24,8 @@ class PackageDetailsDialog : public QDialog { void toggleLogViewer(); void parseProgressOutput(const QString& output); QString findDesktopFile() const; - bool verifyDesktopFile(const QString& desktopFilePath, - const QString& packageName, - const QStringList& nameVariants) const; + bool verifyDesktopFile(const QString& desktopFilePath, + const QStringList& nameVariants) const; void launchApplication(); PackageInfo m_info; From 35b6b8d4af8138a57f59ea92428eb2fb29457eae Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 12:10:23 +0000 Subject: [PATCH 47/71] bump version -> 0.2.16 --- src/gui/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 1bd1494..b69c7f2 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -117,7 +117,7 @@ void MainWindow::createMenuBar() { QMessageBox::about(this, "About ALG App Store", "ALG App Store (Beta)\n\n" "A modern package manager for Arch Linux\n" - "Version: 0.2.15\n" + "Version: 0.2.16\n" "Built with Qt6 and C++17\n\n" "© 2025 Arka Linux GUI"); }); From c7239d4c8d9cdf19231b00d9ff347794fb772c59 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 14:07:13 +0000 Subject: [PATCH 48/71] use pacman is chaotic is enabled --- src/core/package_manager.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/core/package_manager.cpp b/src/core/package_manager.cpp index ccb23d5..8e2b129 100644 --- a/src/core/package_manager.cpp +++ b/src/core/package_manager.cpp @@ -69,8 +69,9 @@ void PackageManager::installPackage(const QString& packageName, const QString& r Logger::info(QString("Installing package: %1 from %2").arg(packageName, repository.isEmpty() ? "default" : repository)); emit operationStarted(QString("Installing %1...").arg(packageName)); - // Determine if this is an AUR package - bool isAUR = repository.toLower() == "aur"; + // Determine if this is an AUR package (not from official repos or chaotic-aur) + QString repoLower = repository.toLower(); + bool isAUR = repoLower == "aur"; QString helper = getHelperName(); QString command; @@ -78,7 +79,7 @@ void PackageManager::installPackage(const QString& packageName, const QString& r // AUR packages - run helper as regular user (no pkexec) command = QString("%1 -S %2 --noconfirm").arg(helper, packageName); } else { - // Official repos need root access + // Official repos and chaotic-aur need root access and use pacman command = QString("pkexec pacman -S %1 --noconfirm").arg(packageName); } @@ -103,8 +104,9 @@ void PackageManager::updatePackage(const QString& packageName, const QString& re Logger::info(QString("Updating package: %1 from %2").arg(packageName, repository.isEmpty() ? "default" : repository)); emit operationStarted(QString("Updating %1...").arg(packageName)); - // Determine if this is an AUR package - bool isAUR = repository.toLower() == "aur"; + // Determine if this is an AUR package (not from official repos or chaotic-aur) + QString repoLower = repository.toLower(); + bool isAUR = repoLower == "aur"; QString helper = getHelperName(); QString command; @@ -112,7 +114,7 @@ void PackageManager::updatePackage(const QString& packageName, const QString& re // AUR packages - run helper as regular user (no pkexec) command = QString("%1 -S %2 --noconfirm").arg(helper, packageName); } else { - // Official repos need root access + // Official repos and chaotic-aur need root access and use pacman command = QString("pkexec pacman -S %1 --noconfirm").arg(packageName); } From d150dd5528b0137e555e336d9633345e83371583 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 14:14:58 +0000 Subject: [PATCH 49/71] sync repositories manually in settings --- src/gui/settings_widget.cpp | 126 ++++++++++++++++++++++++++++++++++-- src/gui/settings_widget.h | 2 + 2 files changed, 122 insertions(+), 6 deletions(-) diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp index 1f51bb3..6d9fbd5 100644 --- a/src/gui/settings_widget.cpp +++ b/src/gui/settings_widget.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include SettingsWidget::SettingsWidget(QWidget* parent) : QWidget(parent) @@ -18,6 +20,9 @@ SettingsWidget::SettingsWidget(QWidget* parent) , m_chaoticAurGroup(nullptr) , m_setupChaoticButton(nullptr) , m_removeChaoticButton(nullptr) + , m_maintenanceGroup(nullptr) + , m_removeLockButton(nullptr) + , m_syncReposButton(nullptr) , m_applyButton(nullptr) , m_revertButton(nullptr) , m_statusLabel(nullptr) @@ -31,11 +36,25 @@ SettingsWidget::SettingsWidget(QWidget* parent) } void SettingsWidget::setupUi() { - auto* mainLayout = new QVBoxLayout(this); + // Create main layout for the widget + auto* outerLayout = new QVBoxLayout(this); + outerLayout->setContentsMargins(0, 0, 0, 0); + + // Create scroll area + auto* scrollArea = new QScrollArea(this); + scrollArea->setWidgetResizable(true); + scrollArea->setFrameShape(QFrame::NoFrame); + scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + + // Create content widget that will be scrollable + auto* contentWidget = new QWidget(); + auto* mainLayout = new QVBoxLayout(contentWidget); mainLayout->setSpacing(20); + mainLayout->setContentsMargins(10, 10, 10, 10); // Title - auto* titleLabel = new QLabel("Settings", this); + auto* titleLabel = new QLabel("Settings", contentWidget); auto titleFont = titleLabel->font(); titleFont.setPointSize(24); titleFont.setBold(true); @@ -55,7 +74,7 @@ void SettingsWidget::setupUi() { mainLayout->addWidget(m_maintenanceGroup); // Status label - m_statusLabel = new QLabel(this); + m_statusLabel = new QLabel(contentWidget); m_statusLabel->setAlignment(Qt::AlignCenter); m_statusLabel->setStyleSheet("QLabel { color: #0066cc; padding: 10px; }"); m_statusLabel->hide(); @@ -65,13 +84,13 @@ void SettingsWidget::setupUi() { auto* buttonLayout = new QHBoxLayout(); buttonLayout->addStretch(); - m_revertButton = new QPushButton("Revert", this); + m_revertButton = new QPushButton("Revert", contentWidget); m_revertButton->setMinimumWidth(100); m_revertButton->setEnabled(false); connect(m_revertButton, &QPushButton::clicked, this, &SettingsWidget::onRevertClicked); buttonLayout->addWidget(m_revertButton); - m_applyButton = new QPushButton("Apply", this); + m_applyButton = new QPushButton("Apply", contentWidget); m_applyButton->setMinimumWidth(100); m_applyButton->setEnabled(false); connect(m_applyButton, &QPushButton::clicked, this, &SettingsWidget::onApplyClicked); @@ -82,7 +101,13 @@ void SettingsWidget::setupUi() { // Add stretch at the bottom mainLayout->addStretch(); - setLayout(mainLayout); + // Set the content widget to the scroll area + scrollArea->setWidget(contentWidget); + + // Add scroll area to the outer layout + outerLayout->addWidget(scrollArea); + + setLayout(outerLayout); } void SettingsWidget::createRepositorySettings() { @@ -258,6 +283,39 @@ void SettingsWidget::createMaintenanceSettings() { lockInfoLabel->setStyleSheet("QLabel { color: #888; font-size: 11px; margin-top: 5px; margin-left: 10px; }"); maintenanceLayout->addWidget(lockInfoLabel); + // Spacer + maintenanceLayout->addSpacing(15); + + // Sync repositories section + auto* syncReposLayout = new QHBoxLayout(); + + auto* syncReposLabel = new QLabel( + "Synchronize Repositories:", + this); + syncReposLabel->setStyleSheet("QLabel { font-weight: bold; }"); + syncReposLayout->addWidget(syncReposLabel); + + syncReposLayout->addStretch(); + + m_syncReposButton = new QPushButton("Sync Repositories", this); + m_syncReposButton->setMinimumWidth(150); + m_syncReposButton->setToolTip( + "Manually synchronize package databases (pacman -Sy).\n" + "This updates the list of available packages from all enabled repositories."); + connect(m_syncReposButton, &QPushButton::clicked, this, &SettingsWidget::onSyncReposClicked); + syncReposLayout->addWidget(m_syncReposButton); + + maintenanceLayout->addLayout(syncReposLayout); + + // Sync info + auto* syncInfoLabel = new QLabel( + "Use this to manually update your package database. This is useful after enabling/disabling repositories\n" + "or when you want to ensure you have the latest package information.", + this); + syncInfoLabel->setWordWrap(true); + syncInfoLabel->setStyleSheet("QLabel { color: #888; font-size: 11px; margin-top: 5px; margin-left: 10px; }"); + maintenanceLayout->addWidget(syncInfoLabel); + m_maintenanceGroup->setLayout(maintenanceLayout); } @@ -969,3 +1027,59 @@ void SettingsWidget::onRemoveChaoticClicked() { process->start("pkexec", QStringList() << "pacman" << "-Rns" << "--noconfirm" << "chaotic-keyring" << "chaotic-mirrorlist"); } + +void SettingsWidget::onSyncReposClicked() { + QMessageBox msgBox(this); + msgBox.setIcon(QMessageBox::Question); + msgBox.setWindowTitle("Sync Repositories"); + msgBox.setText("Synchronize package databases?"); + msgBox.setInformativeText( + "This will run: pacman -Sy\n\n" + "This updates the list of available packages from all enabled repositories.\n" + "This is useful after enabling/disabling repositories or when you want to " + "ensure you have the latest package information."); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + + if (msgBox.exec() != QMessageBox::Yes) { + return; + } + + m_statusLabel->setText("Synchronizing repositories..."); + m_statusLabel->setStyleSheet("QLabel { color: #0066cc; padding: 10px; }"); + m_statusLabel->show(); + m_syncReposButton->setEnabled(false); + + // Run pacman -Sy with pkexec + QProcess* process = new QProcess(this); + connect(process, QOverload::of(&QProcess::finished), + this, [this, process](int exitCode, QProcess::ExitStatus exitStatus) { + process->deleteLater(); + m_syncReposButton->setEnabled(true); + + if (exitCode == 0 && exitStatus == QProcess::NormalExit) { + m_statusLabel->setText("Repositories synchronized successfully!"); + m_statusLabel->setStyleSheet("QLabel { color: #00aa00; padding: 10px; font-weight: bold; }"); + m_statusLabel->show(); + Logger::info("Repositories synchronized successfully"); + + // Refresh ALPM databases + AlpmWrapper::instance().refreshDatabases(); + + QMessageBox::information(this, "Success", + "Package databases synchronized successfully!\n\n" + "The package list has been updated with the latest available packages."); + } else { + m_statusLabel->setText("Failed to synchronize repositories."); + m_statusLabel->setStyleSheet("QLabel { color: #aa0000; padding: 10px; }"); + m_statusLabel->show(); + Logger::error("Failed to synchronize repositories"); + + QMessageBox::critical(this, "Error", + "Failed to synchronize package databases.\n" + "Please check your internet connection and try again."); + } + }); + + process->start("pkexec", QStringList() << "pacman" << "-Sy"); +} diff --git a/src/gui/settings_widget.h b/src/gui/settings_widget.h index bab7df0..5fd48ae 100644 --- a/src/gui/settings_widget.h +++ b/src/gui/settings_widget.h @@ -51,6 +51,7 @@ class SettingsWidget : public QWidget { // Maintenance settings QGroupBox* m_maintenanceGroup; QPushButton* m_removeLockButton; + QPushButton* m_syncReposButton; // Control buttons QPushButton* m_applyButton; @@ -70,6 +71,7 @@ private slots: void onSetupChaoticClicked(); void onRemoveChaoticClicked(); void onRemoveLockClicked(); + void onSyncReposClicked(); }; #endif // SETTINGS_WIDGET_H From c39795bd5963c9a3627c3fc0c1c513c8543a2cd7 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 15:05:18 +0000 Subject: [PATCH 50/71] pull from chaotic on home tab --- src/gui/home_widget.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/gui/home_widget.cpp b/src/gui/home_widget.cpp index 35f914a..90f8148 100644 --- a/src/gui/home_widget.cpp +++ b/src/gui/home_widget.cpp @@ -49,7 +49,7 @@ void HomeWidget::setupUi() { } void HomeWidget::loadFeaturedPackages() { - // Featured packages list + // Featured packages list with initial repositories m_featuredPackages = { {"firefox", "Latest", "Fast, Private & Safe Web Browser", "extra"}, {"gimp", "Latest", "GNU Image Manipulation Program", "extra"}, @@ -65,6 +65,21 @@ void HomeWidget::loadFeaturedPackages() { {"zoom", "Latest", "Video Conferencing and Web Conferencing Service", "AUR"} }; + // Check if packages marked as AUR are actually available in automated repos (like chaotic-aur) + for (auto& pkg : m_featuredPackages) { + if (pkg.repository.toLower() == "aur") { + PackageInfo repoInfo = AlpmWrapper::instance().getPackageInfo(pkg.name); + if (!repoInfo.name.isEmpty() && !repoInfo.repository.isEmpty()) { + // Package found in automated repos, use that repository instead + pkg.repository = repoInfo.repository; + pkg.version = repoInfo.version; + pkg.description = repoInfo.description; + Logger::info(QString("Package %1 found in %2 repository, using pacman instead of AUR helper") + .arg(pkg.name, pkg.repository)); + } + } + } + Logger::info(QString("Loaded %1 featured packages").arg(m_featuredPackages.size())); } From 467e396a8dde81323f233a0850c415f54bd56afc Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 15:28:47 +0000 Subject: [PATCH 51/71] alpm init before ui setup --- src/gui/home_widget.cpp | 5 ++++- src/gui/mainwindow.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/gui/home_widget.cpp b/src/gui/home_widget.cpp index 90f8148..2939122 100644 --- a/src/gui/home_widget.cpp +++ b/src/gui/home_widget.cpp @@ -68,14 +68,17 @@ void HomeWidget::loadFeaturedPackages() { // Check if packages marked as AUR are actually available in automated repos (like chaotic-aur) for (auto& pkg : m_featuredPackages) { if (pkg.repository.toLower() == "aur") { + Logger::debug(QString("Checking if AUR package %1 is available in official repos...").arg(pkg.name)); PackageInfo repoInfo = AlpmWrapper::instance().getPackageInfo(pkg.name); if (!repoInfo.name.isEmpty() && !repoInfo.repository.isEmpty()) { // Package found in automated repos, use that repository instead pkg.repository = repoInfo.repository; pkg.version = repoInfo.version; pkg.description = repoInfo.description; - Logger::info(QString("Package %1 found in %2 repository, using pacman instead of AUR helper") + Logger::info(QString("✅ Package %1 found in %2 repository, will use pacman instead of AUR helper") .arg(pkg.name, pkg.repository)); + } else { + Logger::debug(QString("Package %1 not found in official repos, will use AUR helper").arg(pkg.name)); } } } diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index b69c7f2..aa0ef94 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -17,16 +17,16 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) , m_tabWidget(std::make_unique(this)) { - setupUi(); - loadStyleSheet(); - - // Initialize ALPM + // Initialize ALPM before creating widgets that might need it if (!AlpmWrapper::instance().initialize()) { QMessageBox::critical(this, "Error", "Failed to initialize package manager. Please check your system configuration."); Logger::error("Failed to initialize ALPM in MainWindow"); } + setupUi(); + loadStyleSheet(); + Logger::info("MainWindow created successfully"); } From b29c52bb23e218048b27c473e2c163bd5841919e Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 16:21:48 +0000 Subject: [PATCH 52/71] bump version -> 0.2.21 --- src/gui/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index aa0ef94..d45c284 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -117,7 +117,7 @@ void MainWindow::createMenuBar() { QMessageBox::about(this, "About ALG App Store", "ALG App Store (Beta)\n\n" "A modern package manager for Arch Linux\n" - "Version: 0.2.16\n" + "Version: 0.2.21\n" "Built with Qt6 and C++17\n\n" "© 2025 Arka Linux GUI"); }); From 460f85f02fef860afb569f9017db448eca711a92 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 16:31:31 +0000 Subject: [PATCH 53/71] update todo --- TODO.md | 2 +- src/gui/home_widget.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index 7301e79..1b5b1cc 100644 --- a/TODO.md +++ b/TODO.md @@ -2,7 +2,7 @@ - [x] Add launch button on package card if package is installed and remove when uninstalled - [] Add detailed mirrorlist tab to set mirrorlist - [] Add version information -- [] +- [] Implement an AUR helper in core to remove dependence on paru and yay ## Future Enhancements diff --git a/src/gui/home_widget.cpp b/src/gui/home_widget.cpp index 2939122..6a3b700 100644 --- a/src/gui/home_widget.cpp +++ b/src/gui/home_widget.cpp @@ -75,7 +75,7 @@ void HomeWidget::loadFeaturedPackages() { pkg.repository = repoInfo.repository; pkg.version = repoInfo.version; pkg.description = repoInfo.description; - Logger::info(QString("✅ Package %1 found in %2 repository, will use pacman instead of AUR helper") + Logger::info(QString("Package %1 found in %2 repository, will use pacman instead of AUR helper") .arg(pkg.name, pkg.repository)); } else { Logger::debug(QString("Package %1 not found in official repos, will use AUR helper").arg(pkg.name)); From b197cfdfd2eae1ccd262fc7756576dd98211ec34 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 16:38:40 +0000 Subject: [PATCH 54/71] show correct version information for all apps --- src/gui/home_widget.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/gui/home_widget.cpp b/src/gui/home_widget.cpp index 6a3b700..4446649 100644 --- a/src/gui/home_widget.cpp +++ b/src/gui/home_widget.cpp @@ -65,21 +65,23 @@ void HomeWidget::loadFeaturedPackages() { {"zoom", "Latest", "Video Conferencing and Web Conferencing Service", "AUR"} }; - // Check if packages marked as AUR are actually available in automated repos (like chaotic-aur) + // Fetch actual package information from repositories for (auto& pkg : m_featuredPackages) { - if (pkg.repository.toLower() == "aur") { - Logger::debug(QString("Checking if AUR package %1 is available in official repos...").arg(pkg.name)); - PackageInfo repoInfo = AlpmWrapper::instance().getPackageInfo(pkg.name); - if (!repoInfo.name.isEmpty() && !repoInfo.repository.isEmpty()) { - // Package found in automated repos, use that repository instead - pkg.repository = repoInfo.repository; - pkg.version = repoInfo.version; - pkg.description = repoInfo.description; - Logger::info(QString("Package %1 found in %2 repository, will use pacman instead of AUR helper") - .arg(pkg.name, pkg.repository)); - } else { - Logger::debug(QString("Package %1 not found in official repos, will use AUR helper").arg(pkg.name)); + PackageInfo repoInfo = AlpmWrapper::instance().getPackageInfo(pkg.name); + + if (!repoInfo.name.isEmpty() && !repoInfo.repository.isEmpty()) { + // Package found in official repos, update with actual information + pkg.repository = repoInfo.repository; + pkg.version = repoInfo.version; + pkg.description = repoInfo.description; + + if (pkg.repository.toLower() != "aur") { + Logger::debug(QString("Package %1 found in %2 repository with version %3") + .arg(pkg.name, pkg.repository, pkg.version)); } + } else if (pkg.repository.toLower() == "aur") { + // Package not found in official repos, will use AUR helper + Logger::debug(QString("Package %1 not found in official repos, will use AUR helper").arg(pkg.name)); } } From 4b0727ee520905ab530608b84c66c9ef523cb5df Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 18:08:29 +0000 Subject: [PATCH 55/71] remove paru support and default to yay --- src/core/package_manager.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/core/package_manager.cpp b/src/core/package_manager.cpp index 8e2b129..f3588f3 100644 --- a/src/core/package_manager.cpp +++ b/src/core/package_manager.cpp @@ -41,13 +41,13 @@ void PackageManager::detectHelper() { return; } - // Check for paru - QString paruPath = QStandardPaths::findExecutable("paru"); - if (!paruPath.isEmpty()) { - m_helper = Helper::Paru; - Logger::info("Using paru as package helper"); - return; - } + // Check for paru - deprecate because paru doesn't allow running with pkexec + // QString paruPath = QStandardPaths::findExecutable("paru"); + // if (!paruPath.isEmpty()) { + // m_helper = Helper::Paru; + // Logger::info("Using paru as package helper"); + // return; + // } // Default to pacman m_helper = Helper::Pacman; @@ -57,7 +57,6 @@ void PackageManager::detectHelper() { QString PackageManager::getHelperName() const { switch (m_helper) { case Helper::Yay: return "yay"; - case Helper::Paru: return "paru"; case Helper::Pacman: return "pacman"; default: return "pacman"; } @@ -75,9 +74,10 @@ void PackageManager::installPackage(const QString& packageName, const QString& r QString helper = getHelperName(); QString command; - if (isAUR && (m_helper == Helper::Yay || m_helper == Helper::Paru)) { - // AUR packages - run helper as regular user (no pkexec) - command = QString("%1 -S %2 --noconfirm").arg(helper, packageName); + if (isAUR && (m_helper == Helper::Yay)) { + // AUR packages - use pkexec to get userpassword before hand + // Paru has a problem here, so default to yay + command = QString("pkexec %1 -S %2 --noconfirm").arg(helper, packageName); } else { // Official repos and chaotic-aur need root access and use pacman command = QString("pkexec pacman -S %1 --noconfirm").arg(packageName); @@ -110,7 +110,7 @@ void PackageManager::updatePackage(const QString& packageName, const QString& re QString helper = getHelperName(); QString command; - if (isAUR && (m_helper == Helper::Yay || m_helper == Helper::Paru)) { + if (isAUR && (m_helper == Helper::Yay)) { // AUR packages - run helper as regular user (no pkexec) command = QString("%1 -S %2 --noconfirm").arg(helper, packageName); } else { From c1a53832af10597ee56d319f38ec7eaaa457f6b4 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 18:46:58 +0000 Subject: [PATCH 56/71] add cancel operation button; remove revert button --- src/core/package_manager.cpp | 27 ++++++++ src/core/package_manager.h | 2 + src/gui/settings_widget.cpp | 129 +++++++++++++++++++++++++---------- src/gui/settings_widget.h | 4 +- 4 files changed, 125 insertions(+), 37 deletions(-) diff --git a/src/core/package_manager.cpp b/src/core/package_manager.cpp index f3588f3..c85901c 100644 --- a/src/core/package_manager.cpp +++ b/src/core/package_manager.cpp @@ -187,3 +187,30 @@ void PackageManager::onProcessOutput() { emit operationOutput(output); } } + +void PackageManager::cancelRunningOperation() { + if (m_process && m_process->state() != QProcess::NotRunning) { + Logger::warning("Cancelling running operation..."); + emit operationOutput("\n>>> Operation cancelled by user <<<\n"); + + // First try to terminate gracefully + m_process->terminate(); + + // Wait up to 5 seconds for graceful termination + if (!m_process->waitForFinished(5000)) { + // If it doesn't terminate gracefully, force kill + Logger::warning("Process did not terminate gracefully, forcing kill..."); + m_process->kill(); + m_process->waitForFinished(1000); + } + + emit operationCompleted(false, "Operation cancelled by user"); + Logger::info("Operation cancelled successfully"); + } else { + Logger::warning("No operation is currently running"); + } +} + +bool PackageManager::isOperationRunning() const { + return m_process && m_process->state() != QProcess::NotRunning; +} diff --git a/src/core/package_manager.h b/src/core/package_manager.h index ad77fc2..5cf1cc8 100644 --- a/src/core/package_manager.h +++ b/src/core/package_manager.h @@ -31,6 +31,8 @@ class PackageManager : public QObject { void uninstallPackage(const QString& packageName, const QString& repository = QString()); void updatePackage(const QString& packageName, const QString& repository = QString()); void updateAllPackages(); + void cancelRunningOperation(); + bool isOperationRunning() const; Helper getHelper() const { return m_helper; } QString getHelperName() const; diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp index 6d9fbd5..e245581 100644 --- a/src/gui/settings_widget.cpp +++ b/src/gui/settings_widget.cpp @@ -1,6 +1,7 @@ #include "settings_widget.h" #include "../utils/logger.h" #include "../core/alpm_wrapper.h" +#include "../core/package_manager.h" #include #include #include @@ -23,8 +24,8 @@ SettingsWidget::SettingsWidget(QWidget* parent) , m_maintenanceGroup(nullptr) , m_removeLockButton(nullptr) , m_syncReposButton(nullptr) + , m_cancelProcessButton(nullptr) , m_applyButton(nullptr) - , m_revertButton(nullptr) , m_statusLabel(nullptr) , m_originalMultilibState(false) , m_originalChaoticAurState(false) { @@ -80,24 +81,6 @@ void SettingsWidget::setupUi() { m_statusLabel->hide(); mainLayout->addWidget(m_statusLabel); - // Buttons - auto* buttonLayout = new QHBoxLayout(); - buttonLayout->addStretch(); - - m_revertButton = new QPushButton("Revert", contentWidget); - m_revertButton->setMinimumWidth(100); - m_revertButton->setEnabled(false); - connect(m_revertButton, &QPushButton::clicked, this, &SettingsWidget::onRevertClicked); - buttonLayout->addWidget(m_revertButton); - - m_applyButton = new QPushButton("Apply", contentWidget); - m_applyButton->setMinimumWidth(100); - m_applyButton->setEnabled(false); - connect(m_applyButton, &QPushButton::clicked, this, &SettingsWidget::onApplyClicked); - buttonLayout->addWidget(m_applyButton); - - mainLayout->addLayout(buttonLayout); - // Add stretch at the bottom mainLayout->addStretch(); @@ -165,6 +148,18 @@ void SettingsWidget::createRepositorySettings() { infoLabel->setStyleSheet("QLabel { color: #888; font-style: italic; margin-top: 10px; }"); repoLayout->addWidget(infoLabel); + // Apply button + auto* applyLayout = new QHBoxLayout(); + applyLayout->addStretch(); + + m_applyButton = new QPushButton("Apply Changes", this); + m_applyButton->setMinimumWidth(150); + m_applyButton->setEnabled(false); + connect(m_applyButton, &QPushButton::clicked, this, &SettingsWidget::onApplyClicked); + applyLayout->addWidget(m_applyButton); + + repoLayout->addLayout(applyLayout); + m_repositoryGroup->setLayout(repoLayout); } @@ -316,6 +311,40 @@ void SettingsWidget::createMaintenanceSettings() { syncInfoLabel->setStyleSheet("QLabel { color: #888; font-size: 11px; margin-top: 5px; margin-left: 10px; }"); maintenanceLayout->addWidget(syncInfoLabel); + // Spacer + maintenanceLayout->addSpacing(15); + + // Cancel running process section + auto* cancelProcessLayout = new QHBoxLayout(); + + auto* cancelProcessLabel = new QLabel( + "Cancel Running Process:", + this); + cancelProcessLabel->setStyleSheet("QLabel { font-weight: bold; }"); + cancelProcessLayout->addWidget(cancelProcessLabel); + + cancelProcessLayout->addStretch(); + + m_cancelProcessButton = new QPushButton("Cancel Process", this); + m_cancelProcessButton->setMinimumWidth(150); + m_cancelProcessButton->setToolTip( + "Cancel any running package operation (install, uninstall, update).\n" + "Use this if an operation is stuck or taking too long.\n" + "This is different from removing the lock file - it actually stops the running process."); + connect(m_cancelProcessButton, &QPushButton::clicked, this, &SettingsWidget::onCancelProcessClicked); + cancelProcessLayout->addWidget(m_cancelProcessButton); + + maintenanceLayout->addLayout(cancelProcessLayout); + + // Cancel process info + auto* cancelInfoLabel = new QLabel( + "Use this to cancel a stuck installation, uninstallation, or update process.\n" + "This is useful when you see 'Another operation is already in progress' and want to stop it.", + this); + cancelInfoLabel->setWordWrap(true); + cancelInfoLabel->setStyleSheet("QLabel { color: #888; font-size: 11px; margin-top: 5px; margin-left: 10px; }"); + maintenanceLayout->addWidget(cancelInfoLabel); + m_maintenanceGroup->setLayout(maintenanceLayout); } @@ -680,11 +709,10 @@ bool SettingsWidget::disableChaoticAurInPacmanConf() { } void SettingsWidget::onSettingsChanged() { - // Enable apply and revert buttons when settings change + // Enable apply button when settings change bool hasChanges = (m_multilibRepoCheckbox->isChecked() != m_originalMultilibState) || (m_chaoticAurCheckbox->isChecked() != m_originalChaoticAurState); m_applyButton->setEnabled(hasChanges); - m_revertButton->setEnabled(hasChanges); m_statusLabel->hide(); } @@ -785,7 +813,6 @@ void SettingsWidget::onApplyClicked() { m_statusLabel->show(); m_applyButton->setEnabled(false); - m_revertButton->setEnabled(false); // Suggest database sync auto reply = QMessageBox::question(this, "Sync Package Database", @@ -820,19 +847,6 @@ void SettingsWidget::onApplyClicked() { } } -void SettingsWidget::onRevertClicked() { - // Revert to original state - m_multilibRepoCheckbox->setChecked(m_originalMultilibState); - m_chaoticAurCheckbox->setChecked(m_originalChaoticAurState); - m_applyButton->setEnabled(false); - m_revertButton->setEnabled(false); - m_statusLabel->setText("Changes reverted"); - m_statusLabel->setStyleSheet("QLabel { color: #0066cc; padding: 10px; }"); - m_statusLabel->show(); - - Logger::info("Settings reverted to original state"); -} - bool SettingsWidget::isMultilibEnabled() const { return m_multilibRepoCheckbox->isChecked() && (m_multilibRepoCheckbox->isChecked() == m_originalMultilibState); @@ -1083,3 +1097,48 @@ void SettingsWidget::onSyncReposClicked() { process->start("pkexec", QStringList() << "pacman" << "-Sy"); } + +void SettingsWidget::onCancelProcessClicked() { + // Check if there's actually a process running + if (!PackageManager::instance().isOperationRunning()) { + QMessageBox::information(this, "No Process Running", + "There is no package operation currently running.\n" + "Nothing to cancel."); + return; + } + + // Show confirmation dialog + QMessageBox msgBox(this); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle("Cancel Running Process"); + msgBox.setText("Are you sure you want to cancel the running package operation?"); + msgBox.setInformativeText( + "This will stop the current installation, uninstallation, or update process.\n\n" + "WARNING: Cancelling a package operation may leave your system in an inconsistent state.\n" + "You may need to run the operation again to complete it properly.\n\n" + "It's recommended to only cancel if the process is truly stuck or unresponsive."); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + + if (msgBox.exec() != QMessageBox::Yes) { + return; + } + + m_statusLabel->setText("Cancelling running process..."); + m_statusLabel->setStyleSheet("QLabel { color: #0066cc; padding: 10px; }"); + m_statusLabel->show(); + + // Cancel the operation + PackageManager::instance().cancelRunningOperation(); + + m_statusLabel->setText("Process cancelled successfully!"); + m_statusLabel->setStyleSheet("QLabel { color: #00aa00; padding: 10px; font-weight: bold; }"); + m_statusLabel->show(); + + Logger::info("User cancelled running package operation from settings"); + + QMessageBox::information(this, "Process Cancelled", + "The running package operation has been cancelled.\n\n" + "If you were in the middle of installing or updating a package, " + "you may need to run the operation again to complete it."); +} diff --git a/src/gui/settings_widget.h b/src/gui/settings_widget.h index 5fd48ae..6985381 100644 --- a/src/gui/settings_widget.h +++ b/src/gui/settings_widget.h @@ -52,10 +52,10 @@ class SettingsWidget : public QWidget { QGroupBox* m_maintenanceGroup; QPushButton* m_removeLockButton; QPushButton* m_syncReposButton; + QPushButton* m_cancelProcessButton; // Control buttons QPushButton* m_applyButton; - QPushButton* m_revertButton; // Status QLabel* m_statusLabel; @@ -66,12 +66,12 @@ class SettingsWidget : public QWidget { private slots: void onApplyClicked(); - void onRevertClicked(); void onSettingsChanged(); void onSetupChaoticClicked(); void onRemoveChaoticClicked(); void onRemoveLockClicked(); void onSyncReposClicked(); + void onCancelProcessClicked(); }; #endif // SETTINGS_WIDGET_H From 63befddc4559f06147546a07a48a1f9b0cf8b4bd Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 18:48:34 +0000 Subject: [PATCH 57/71] bump version -> 0.2.25 --- src/gui/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index d45c284..0e63344 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -117,7 +117,7 @@ void MainWindow::createMenuBar() { QMessageBox::about(this, "About ALG App Store", "ALG App Store (Beta)\n\n" "A modern package manager for Arch Linux\n" - "Version: 0.2.21\n" + "Version: 0.2.25\n" "Built with Qt6 and C++17\n\n" "© 2025 Arka Linux GUI"); }); From ff121318ab89215c106ab8e8e2932efe2fa56b49 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 19:00:12 +0000 Subject: [PATCH 58/71] home_tab should default to yay if chaotic is disabled --- src/gui/home_widget.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/gui/home_widget.cpp b/src/gui/home_widget.cpp index 4446649..cba1315 100644 --- a/src/gui/home_widget.cpp +++ b/src/gui/home_widget.cpp @@ -70,7 +70,7 @@ void HomeWidget::loadFeaturedPackages() { PackageInfo repoInfo = AlpmWrapper::instance().getPackageInfo(pkg.name); if (!repoInfo.name.isEmpty() && !repoInfo.repository.isEmpty()) { - // Package found in official repos, update with actual information + // Package found in official repos (including chaotic-aur), update with actual information pkg.repository = repoInfo.repository; pkg.version = repoInfo.version; pkg.description = repoInfo.description; @@ -80,8 +80,10 @@ void HomeWidget::loadFeaturedPackages() { .arg(pkg.name, pkg.repository, pkg.version)); } } else if (pkg.repository.toLower() == "aur") { - // Package not found in official repos, will use AUR helper - Logger::debug(QString("Package %1 not found in official repos, will use AUR helper").arg(pkg.name)); + // Package not found in official repos (including chaotic-aur) + // Default to AUR helper (yay/paru) since chaotic-aur is not enabled or doesn't have this package + pkg.repository = "aur"; + Logger::debug(QString("Package %1 not found in enabled repositories, defaulting to AUR helper").arg(pkg.name)); } } From 890d35b841ea1145a0eb20ed7684162d70d0da4a Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 19:13:33 +0000 Subject: [PATCH 59/71] ensure chaotic is not added multiple times in pacman.conf --- src/gui/settings_widget.cpp | 54 ++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp index e245581..a5db25e 100644 --- a/src/gui/settings_widget.cpp +++ b/src/gui/settings_widget.cpp @@ -577,27 +577,37 @@ bool SettingsWidget::enableChaoticAurInPacmanConf() { QStringList lines; QTextStream in(&file); - bool chaoticAurSectionFound = false; - bool chaoticAurExists = false; + bool inCommentedChaoticAurSection = false; + bool chaoticAurSectionExists = false; while (!in.atEnd()) { QString line = in.readLine(); + QString trimmedLine = line.trimmed(); - // Check if chaotic-aur section already exists (uncommented) - if (line.trimmed() == "[chaotic-aur]") { - chaoticAurExists = true; - } - - // Check if this is a commented [chaotic-aur] section - if (line.trimmed() == "#[chaotic-aur]") { - lines.append("[chaotic-aur]"); - chaoticAurSectionFound = true; + // Check if chaotic-aur section already exists (uncommented or commented) + if (trimmedLine == "[chaotic-aur]" || trimmedLine == "#[chaotic-aur]") { + chaoticAurSectionExists = true; + + // If it's commented, uncomment it + if (trimmedLine == "#[chaotic-aur]") { + lines.append("[chaotic-aur]"); + inCommentedChaoticAurSection = true; + } else { + // Already uncommented, keep as is + lines.append(line); + } } // Check if the Include/Server line in chaotic-aur section is commented - else if (chaoticAurSectionFound && line.trimmed().startsWith("#") && - (line.contains("Include") || line.contains("Server"))) { - lines.append(line.mid(line.indexOf('#') + 1)); // Remove the # comment character - chaoticAurSectionFound = false; // Reset flag after processing + else if (inCommentedChaoticAurSection && trimmedLine.startsWith("#") && + (trimmedLine.contains("Include") || trimmedLine.contains("Server"))) { + // Remove the # comment character + lines.append(line.mid(line.indexOf('#') + 1)); + inCommentedChaoticAurSection = false; + } + // Check if we hit another section, reset flag + else if (trimmedLine.startsWith("[") && trimmedLine != "[chaotic-aur]" && trimmedLine != "#[chaotic-aur]") { + lines.append(line); + inCommentedChaoticAurSection = false; } else { lines.append(line); @@ -606,7 +616,7 @@ bool SettingsWidget::enableChaoticAurInPacmanConf() { file.close(); // If chaotic-aur section doesn't exist at all, add it - if (!chaoticAurExists && !chaoticAurSectionFound) { + if (!chaoticAurSectionExists) { lines.append(""); lines.append("[chaotic-aur]"); lines.append("Include = /etc/pacman.d/chaotic-mirrorlist"); @@ -657,18 +667,24 @@ bool SettingsWidget::disableChaoticAurInPacmanConf() { QString line = in.readLine(); QString trimmedLine = line.trimmed(); - // Check if this is [chaotic-aur] section + // Check if this is [chaotic-aur] section (uncommented or already commented) if (trimmedLine == "[chaotic-aur]") { lines.append("#[chaotic-aur]"); inChaoticAurSection = true; } - // Check if we're in chaotic-aur section and this is the Include/Server line + else if (trimmedLine == "#[chaotic-aur]") { + // Already commented, keep as is + lines.append(line); + inChaoticAurSection = false; + } + // Check if we're in chaotic-aur section and this is the Include/Server line (not already commented) else if (inChaoticAurSection && !trimmedLine.startsWith("#") && (trimmedLine.startsWith("Include") || trimmedLine.startsWith("Server"))) { lines.append("#" + line); + inChaoticAurSection = false; } // Check if we hit another section - else if (trimmedLine.startsWith("[") && trimmedLine != "[chaotic-aur]") { + else if (trimmedLine.startsWith("[") && trimmedLine != "[chaotic-aur]" && trimmedLine != "#[chaotic-aur]") { lines.append(line); inChaoticAurSection = false; } From 02f3cf43b71e43244b9bad62a14040ad21a11301 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 20:22:05 +0000 Subject: [PATCH 60/71] add postinstall stylesheet path --- src/gui/mainwindow.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 0e63344..4a0d6d9 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -128,15 +128,20 @@ void MainWindow::loadStyleSheet() { QFile styleFile(":/stylesheet.qss"); if (!styleFile.exists()) { - // Try loading from file system + // Try loading from current directory (for development) styleFile.setFileName("stylesheet.qss"); } + if (!styleFile.exists()) { + // Try loading from system installation path + styleFile.setFileName("/usr/share/alg-app-store/stylesheet.qss"); + } + if (styleFile.open(QFile::ReadOnly)) { QString styleSheet = QLatin1String(styleFile.readAll()); qApp->setStyleSheet(styleSheet); styleFile.close(); - Logger::info("Stylesheet loaded successfully"); + Logger::info(QString("Stylesheet loaded successfully from: %1").arg(styleFile.fileName())); } else { Logger::warning("Could not load stylesheet"); } From 948a2c93c1dd10f6d72c0e30d812f1129697d538 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 20:33:28 +0000 Subject: [PATCH 61/71] update desktop entry --- assets/alg-app-store.desktop | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/alg-app-store.desktop b/assets/alg-app-store.desktop index c7449b1..9844259 100644 --- a/assets/alg-app-store.desktop +++ b/assets/alg-app-store.desktop @@ -2,12 +2,12 @@ Type=Application Version=1.0 Name=App Store -GenericName=ALG - App Store -Keywords=utility;system;welcome; +GenericName=ALG App Store +Keywords=app;store;software;install;system; Encoding=UTF-8 Terminal=false Exec=alg-app-store -Icon=/usr/share/pixmaps/alg-app-store.png -Comment=ALG - App Store -Categories=System;Go; +Icon=alg-app-store +Comment=Install all your favourite apps +Categories=System;Apps; StartupNotify=true From acc639a31ca5dc599f28bfd35bfad497245e733a Mon Sep 17 00:00:00 2001 From: demonkiller Date: Fri, 14 Nov 2025 22:08:07 +0000 Subject: [PATCH 62/71] fixed chaotic-setup button --- src/gui/settings_widget.cpp | 60 +++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp index a5db25e..0e3bac2 100644 --- a/src/gui/settings_widget.cpp +++ b/src/gui/settings_widget.cpp @@ -945,11 +945,11 @@ void SettingsWidget::onSetupChaoticClicked() { msgBox.setWindowTitle("Setup Chaotic-AUR"); msgBox.setText("Install Chaotic-AUR repository?"); msgBox.setInformativeText( - "This will install:\n" - "• chaotic-keyring\n" - "• chaotic-mirrorlist\n\n" - "These packages are required to use the Chaotic-AUR repository.\n" - "You may need to manually add the repository to /etc/pacman.conf if not already configured."); + "This will:\n" + "1. Download chaotic-keyring and chaotic-mirrorlist packages\n" + "2. Install them using pacman\n" + "3. Add the repository to /etc/pacman.conf\n\n" + "This requires internet connection and administrator privileges."); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::Yes); @@ -957,15 +957,37 @@ void SettingsWidget::onSetupChaoticClicked() { return; } - m_statusLabel->setText("Installing Chaotic-AUR packages..."); + m_statusLabel->setText("Setting up Chaotic-AUR repository..."); m_statusLabel->setStyleSheet("QLabel { color: #0066cc; padding: 10px; }"); m_statusLabel->show(); m_setupChaoticButton->setEnabled(false); - // Install chaotic-keyring and chaotic-mirrorlist + // Use a shell script to download and install chaotic-aur packages + // This follows the official installation guide from aur.chaotic.cx + QString script = + "cd /tmp && " + "rm -f chaotic-keyring.pkg.tar.zst chaotic-mirrorlist.pkg.tar.zst && " + "curl -L -O https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-keyring.pkg.tar.zst && " + "curl -L -O https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-mirrorlist.pkg.tar.zst && " + "pacman -U --noconfirm chaotic-keyring.pkg.tar.zst chaotic-mirrorlist.pkg.tar.zst"; + QProcess* process = new QProcess(this); + + // Capture both stdout and stderr for debugging + process->setProcessChannelMode(QProcess::MergedChannels); + connect(process, QOverload::of(&QProcess::finished), this, [this, process](int exitCode, QProcess::ExitStatus exitStatus) { + QString output = process->readAll(); + + Logger::info(QString("Chaotic-AUR setup exit code: %1, status: %2") + .arg(exitCode) + .arg(exitStatus == QProcess::NormalExit ? "Normal" : "Crashed")); + + if (!output.isEmpty()) { + Logger::debug(QString("Chaotic-AUR setup output:\n%1").arg(output)); + } + process->deleteLater(); m_setupChaoticButton->setEnabled(true); @@ -980,23 +1002,31 @@ void SettingsWidget::onSetupChaoticClicked() { QMessageBox::information(this, "Success", "Chaotic-AUR packages installed successfully!\n\n" - "If the repository is not yet configured, you may need to add it to /etc/pacman.conf:\n\n" - "[chaotic-aur]\n" - "Include = /etc/pacman.d/chaotic-mirrorlist"); + "You can now enable the Chaotic-AUR repository using the checkbox above.\n" + "After enabling, remember to sync the package databases."); } else { m_statusLabel->setText("Failed to install Chaotic-AUR packages."); m_statusLabel->setStyleSheet("QLabel { color: #aa0000; padding: 10px; }"); m_statusLabel->show(); - Logger::error("Failed to install Chaotic-AUR packages"); + Logger::error(QString("Failed to install Chaotic-AUR packages. Exit code: %1").arg(exitCode)); + + // Show output in error message if available + QString errorDetails = "Possible reasons:\n" + "• No internet connection\n" + "• Download failed\n" + "• Installation cancelled\n" + "• User denied authentication\n\n"; + + if (!output.isEmpty() && output.length() < 500) { + errorDetails += "Error output:\n" + output; + } QMessageBox::critical(this, "Error", - "Failed to install Chaotic-AUR packages.\n" - "Please check the logs for details."); + "Failed to install Chaotic-AUR packages.\n\n" + errorDetails); } }); - process->start("pkexec", QStringList() << "pacman" << "-S" << "--noconfirm" - << "chaotic-keyring" << "chaotic-mirrorlist"); + process->start("pkexec", QStringList() << "bash" << "-c" << script); } void SettingsWidget::onRemoveChaoticClicked() { From d9731e61ad5ddcbc282ab884e91298e13bf6aa73 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Fri, 14 Nov 2025 22:57:14 +0000 Subject: [PATCH 63/71] cancel button now kills processes --- src/core/package_manager.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/core/package_manager.cpp b/src/core/package_manager.cpp index c85901c..58e0c4c 100644 --- a/src/core/package_manager.cpp +++ b/src/core/package_manager.cpp @@ -193,13 +193,24 @@ void PackageManager::cancelRunningOperation() { Logger::warning("Cancelling running operation..."); emit operationOutput("\n>>> Operation cancelled by user <<<\n"); - // First try to terminate gracefully + // When using pkexec, we need to kill the actual pacman/yay/paru process + // not just the pkexec wrapper. Use pkill to terminate all package manager processes. + QProcess killProcess; + killProcess.start("pkexec", QStringList() << "bash" << "-c" + << "pkill -TERM pacman; pkill -TERM yay; pkill -TERM paru"); + killProcess.waitForFinished(2000); + + // Also terminate the QProcess wrapper m_process->terminate(); - // Wait up to 5 seconds for graceful termination - if (!m_process->waitForFinished(5000)) { - // If it doesn't terminate gracefully, force kill + // Wait up to 3 seconds for graceful termination + if (!m_process->waitForFinished(3000)) { + // Force kill if still running Logger::warning("Process did not terminate gracefully, forcing kill..."); + killProcess.start("pkexec", QStringList() << "bash" << "-c" + << "pkill -KILL pacman; pkill -KILL yay; pkill -KILL paru"); + killProcess.waitForFinished(2000); + m_process->kill(); m_process->waitForFinished(1000); } From 0f1b6f980d796adb709d009b6098c9f9208e8c8e Mon Sep 17 00:00:00 2001 From: demonkiller Date: Fri, 14 Nov 2025 23:00:02 +0000 Subject: [PATCH 64/71] bump version -> 0.2.26 --- src/gui/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 4a0d6d9..8282b08 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -117,7 +117,7 @@ void MainWindow::createMenuBar() { QMessageBox::about(this, "About ALG App Store", "ALG App Store (Beta)\n\n" "A modern package manager for Arch Linux\n" - "Version: 0.2.25\n" + "Version: 0.2.26\n" "Built with Qt6 and C++17\n\n" "© 2025 Arka Linux GUI"); }); From 3e258a0a2fb929c384bde1c4b9d345017375e61e Mon Sep 17 00:00:00 2001 From: demonkillerr Date: Wed, 17 Dec 2025 22:30:13 +0000 Subject: [PATCH 65/71] [refactor] strictly follow RAII, standardize ownership & cleanup redundant initializers --- src/core/alpm_wrapper.cpp | 4 +-- src/core/alpm_wrapper.h | 17 +++++++-- src/core/aur_helper.h | 7 ++++ src/core/package_manager.cpp | 1 - src/core/package_manager.h | 11 ++++-- src/gui/home_widget.h | 19 ++++++++--- src/gui/installed_widget.h | 20 +++++++---- src/gui/mainwindow.h | 20 ++++++++--- src/gui/package_card.cpp | 3 +- src/gui/package_card.h | 21 ++++++++---- src/gui/package_details_dialog.cpp | 6 +--- src/gui/package_details_dialog.h | 55 +++++++++++++++++------------- src/gui/search_widget.h | 25 ++++++++++---- src/gui/settings_widget.cpp | 18 +--------- src/gui/settings_widget.h | 48 ++++++++++++++------------ src/gui/updates_widget.cpp | 3 +- src/gui/updates_widget.h | 40 +++++++++++++--------- 17 files changed, 194 insertions(+), 124 deletions(-) diff --git a/src/core/alpm_wrapper.cpp b/src/core/alpm_wrapper.cpp index 2d19d83..3fc92b7 100644 --- a/src/core/alpm_wrapper.cpp +++ b/src/core/alpm_wrapper.cpp @@ -10,8 +10,8 @@ AlpmWrapper& AlpmWrapper::instance() { return instance; } -AlpmWrapper::AlpmWrapper() - : m_handle(nullptr), m_syncDbs(nullptr), m_initialized(false) { +AlpmWrapper::AlpmWrapper() { + // Member initialization is done in header file } AlpmWrapper::~AlpmWrapper() { diff --git a/src/core/alpm_wrapper.h b/src/core/alpm_wrapper.h index e0894b9..b1f8906 100644 --- a/src/core/alpm_wrapper.h +++ b/src/core/alpm_wrapper.h @@ -9,6 +9,17 @@ #include #include "../utils/types.h" +/** + * @brief Singleton wrapper for libalpm (Arch Linux Package Manager library). + * + * Memory Management: + * - m_handle: Raw pointer to libalpm handle, manually managed via initialize()/release() + * - m_syncDbs: Raw pointer to libalpm list, managed by libalpm internally + * - Thread-safe via m_mutex + * + * Note: libalpm uses C-style memory management, so smart pointers are not + * directly applicable to the alpm types. + */ class AlpmWrapper { public: static AlpmWrapper& instance(); @@ -34,10 +45,10 @@ class AlpmWrapper { private: AlpmWrapper(); - alpm_handle_t* m_handle; - alpm_list_t* m_syncDbs; + alpm_handle_t* m_handle = nullptr; + alpm_list_t* m_syncDbs = nullptr; std::mutex m_mutex; - bool m_initialized; + bool m_initialized = false; QStringList convertDependList(alpm_list_t* deps); void searchInDatabase(alpm_db_t* db, const QString& query, diff --git a/src/core/aur_helper.h b/src/core/aur_helper.h index a78bb13..e29321f 100644 --- a/src/core/aur_helper.h +++ b/src/core/aur_helper.h @@ -9,6 +9,13 @@ #include #include "../utils/types.h" +/** + * @brief Helper class for interacting with the Arch User Repository (AUR). + * + * Memory Management: + * - m_networkManager: Owned by std::unique_ptr for RAII-style cleanup + * - Network replies are managed via Qt parent-child and deleteLater() + */ class AurHelper : public QObject { Q_OBJECT diff --git a/src/core/package_manager.cpp b/src/core/package_manager.cpp index 58e0c4c..5b50364 100644 --- a/src/core/package_manager.cpp +++ b/src/core/package_manager.cpp @@ -10,7 +10,6 @@ PackageManager& PackageManager::instance() { PackageManager::PackageManager() : QObject(nullptr) - , m_helper(Helper::Pacman) , m_process(std::make_unique()) { detectHelper(); diff --git a/src/core/package_manager.h b/src/core/package_manager.h index 5cf1cc8..0e86a9b 100644 --- a/src/core/package_manager.h +++ b/src/core/package_manager.h @@ -7,6 +7,13 @@ #include #include +/** + * @brief Singleton class for managing package operations (install, uninstall, update). + * + * Memory Management: + * - m_process: Owned by std::unique_ptr for RAII-style cleanup and clear ownership + * - Thread-safe via m_mutex for operation serialization + */ class PackageManager : public QObject { Q_OBJECT @@ -49,9 +56,9 @@ class PackageManager : public QObject { void detectHelper(); void executeCommand(const QString& command, const QStringList& args); - Helper m_helper; + Helper m_helper = Helper::Pacman; std::unique_ptr m_process; - std::mutex m_mutex; + mutable std::mutex m_mutex; private slots: void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); diff --git a/src/gui/home_widget.h b/src/gui/home_widget.h index 5882b8f..08684a2 100644 --- a/src/gui/home_widget.h +++ b/src/gui/home_widget.h @@ -10,6 +10,13 @@ class PackageCard; +/** + * @brief Widget displaying featured packages on the home screen. + * + * Memory Management: + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + * - m_packageCards contains non-owning pointers to cards owned by m_contentWidget + */ class HomeWidget : public QWidget { Q_OBJECT @@ -24,11 +31,13 @@ class HomeWidget : public QWidget { void checkInstalledPackages(); QVector m_featuredPackages; - QVector m_packageCards; - QScrollArea* m_scrollArea; - QWidget* m_contentWidget; - QGridLayout* m_gridLayout; - QTimer* m_updateTimer; + QVector m_packageCards; // Non-owning pointers, owned by m_contentWidget + + // Qt parent-child managed widgets (non-owning pointers) + QScrollArea* m_scrollArea = nullptr; + QWidget* m_contentWidget = nullptr; + QGridLayout* m_gridLayout = nullptr; + QTimer* m_updateTimer = nullptr; private slots: void onPackageClicked(const PackageInfo& info); diff --git a/src/gui/installed_widget.h b/src/gui/installed_widget.h index 1e2bc67..d4cbe0b 100644 --- a/src/gui/installed_widget.h +++ b/src/gui/installed_widget.h @@ -9,6 +9,13 @@ #include #include "../utils/types.h" +/** + * @brief Widget displaying installed packages. + * + * Memory Management: + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + * - Package cards are dynamically created/destroyed in displayPackages/clearResults + */ class InstalledWidget : public QWidget { Q_OBJECT @@ -25,12 +32,13 @@ class InstalledWidget : public QWidget { void filterPackages(const QString& query); void clearResults(); - QLineEdit* m_filterInput; - QScrollArea* m_scrollArea; - QWidget* m_contentWidget; - QGridLayout* m_gridLayout; - QLabel* m_statusLabel; - QLabel* m_countLabel; + // Qt parent-child managed widgets (non-owning pointers) + QLineEdit* m_filterInput = nullptr; + QScrollArea* m_scrollArea = nullptr; + QWidget* m_contentWidget = nullptr; + QGridLayout* m_gridLayout = nullptr; + QLabel* m_statusLabel = nullptr; + QLabel* m_countLabel = nullptr; QVector m_allPackages; QVector m_filteredPackages; diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index 3f2b4f7..cf6d531 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -12,6 +12,14 @@ class InstalledWidget; class UpdatesWidget; class SettingsWidget; +/** + * @brief Main application window for ALG App Store. + * + * Memory Management: + * - m_tabWidget: Owned by std::unique_ptr (central widget) + * - Child widgets (m_homeWidget, etc.): Owned by Qt parent-child hierarchy + * through m_tabWidget. Raw pointers are used as non-owning references. + */ class MainWindow : public QMainWindow { Q_OBJECT @@ -25,11 +33,13 @@ class MainWindow : public QMainWindow { void loadStyleSheet(); std::unique_ptr m_tabWidget; - HomeWidget* m_homeWidget; - SearchWidget* m_searchWidget; - InstalledWidget* m_installedWidget; - UpdatesWidget* m_updatesWidget; - SettingsWidget* m_settingsWidget; + + // Non-owning pointers - owned by m_tabWidget via Qt parent-child hierarchy + HomeWidget* m_homeWidget = nullptr; + SearchWidget* m_searchWidget = nullptr; + InstalledWidget* m_installedWidget = nullptr; + UpdatesWidget* m_updatesWidget = nullptr; + SettingsWidget* m_settingsWidget = nullptr; }; #endif // MAINWINDOW_H diff --git a/src/gui/package_card.cpp b/src/gui/package_card.cpp index 864e26b..62cdee8 100644 --- a/src/gui/package_card.cpp +++ b/src/gui/package_card.cpp @@ -12,8 +12,7 @@ PackageCard::PackageCard(const PackageInfo& info, QWidget* parent) , m_descriptionLabel(new QLabel(this)) , m_versionLabel(new QLabel(this)) , m_repositoryLabel(new QLabel(this)) - , m_statusLabel(new QLabel(this)) - , m_isInstalled(false) { + , m_statusLabel(new QLabel(this)) { setupUi(); checkInstallStatus(); diff --git a/src/gui/package_card.h b/src/gui/package_card.h index aaf38f6..bdb6f86 100644 --- a/src/gui/package_card.h +++ b/src/gui/package_card.h @@ -6,6 +6,12 @@ #include #include "../utils/types.h" +/** + * @brief A clickable card widget displaying package information. + * + * Memory Management: + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + */ class PackageCard : public QWidget { Q_OBJECT @@ -29,12 +35,15 @@ class PackageCard : public QWidget { void setupUi(); PackageInfo m_info; - QLabel* m_nameLabel; - QLabel* m_descriptionLabel; - QLabel* m_versionLabel; - QLabel* m_repositoryLabel; - QLabel* m_statusLabel; - bool m_isInstalled; + + // Qt parent-child managed widgets (non-owning pointers) + QLabel* m_nameLabel = nullptr; + QLabel* m_descriptionLabel = nullptr; + QLabel* m_versionLabel = nullptr; + QLabel* m_repositoryLabel = nullptr; + QLabel* m_statusLabel = nullptr; + + bool m_isInstalled = false; }; #endif // PACKAGE_CARD_H diff --git a/src/gui/package_details_dialog.cpp b/src/gui/package_details_dialog.cpp index bbe9dd2..cacebce 100644 --- a/src/gui/package_details_dialog.cpp +++ b/src/gui/package_details_dialog.cpp @@ -22,7 +22,6 @@ PackageDetailsDialog::PackageDetailsDialog(const PackageInfo& info, QWidget* parent) : QDialog(parent) , m_info(info) - , m_isInstalled(false) , m_nameLabel(new QLabel(this)) , m_versionLabel(new QLabel(this)) , m_repositoryLabel(new QLabel(this)) @@ -41,10 +40,7 @@ PackageDetailsDialog::PackageDetailsDialog(const PackageInfo& info, QWidget* par , m_progressWidget(new QWidget(this)) , m_logViewer(new QTextEdit(this)) , m_toggleLogButton(new QPushButton("Show Logs", this)) - , m_logWidget(new QWidget(this)) - , m_logVisible(false) - , m_totalPackages(0) - , m_currentPackage(0) { + , m_logWidget(new QWidget(this)) { setupUi(); checkInstallStatus(); diff --git a/src/gui/package_details_dialog.h b/src/gui/package_details_dialog.h index dd94aee..4a8a324 100644 --- a/src/gui/package_details_dialog.h +++ b/src/gui/package_details_dialog.h @@ -8,6 +8,12 @@ #include #include "../utils/types.h" +/** + * @brief Dialog showing detailed package information and actions. + * + * Memory Management: + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + */ class PackageDetailsDialog : public QDialog { Q_OBJECT @@ -29,38 +35,39 @@ class PackageDetailsDialog : public QDialog { void launchApplication(); PackageInfo m_info; - bool m_isInstalled; + bool m_isInstalled = false; - QLabel* m_nameLabel; - QLabel* m_versionLabel; - QLabel* m_repositoryLabel; - QLabel* m_maintainerLabel; - QLabel* m_urlLabel; - QTextEdit* m_descriptionText; - QTextEdit* m_dependenciesText; - QLabel* m_lastUpdatedLabel; + // Qt parent-child managed widgets (non-owning pointers) + QLabel* m_nameLabel = nullptr; + QLabel* m_versionLabel = nullptr; + QLabel* m_repositoryLabel = nullptr; + QLabel* m_maintainerLabel = nullptr; + QLabel* m_urlLabel = nullptr; + QTextEdit* m_descriptionText = nullptr; + QTextEdit* m_dependenciesText = nullptr; + QLabel* m_lastUpdatedLabel = nullptr; - QPushButton* m_installButton; - QPushButton* m_uninstallButton; - QPushButton* m_launchButton; - QPushButton* m_closeButton; + QPushButton* m_installButton = nullptr; + QPushButton* m_uninstallButton = nullptr; + QPushButton* m_launchButton = nullptr; + QPushButton* m_closeButton = nullptr; - QLabel* m_statusBadge; + QLabel* m_statusBadge = nullptr; - QProgressBar* m_progressBar; - QLabel* m_progressLabel; - QWidget* m_progressWidget; + QProgressBar* m_progressBar = nullptr; + QLabel* m_progressLabel = nullptr; + QWidget* m_progressWidget = nullptr; - // Log viewer - QTextEdit* m_logViewer; - QPushButton* m_toggleLogButton; - QWidget* m_logWidget; - bool m_logVisible; + // Log viewer (Qt parent-child managed) + QTextEdit* m_logViewer = nullptr; + QPushButton* m_toggleLogButton = nullptr; + QWidget* m_logWidget = nullptr; + bool m_logVisible = false; // Progress tracking QString m_currentOperation; - int m_totalPackages; - int m_currentPackage; + int m_totalPackages = 0; + int m_currentPackage = 0; private slots: void onInstall(); diff --git a/src/gui/search_widget.h b/src/gui/search_widget.h index ed48b8e..5767dcf 100644 --- a/src/gui/search_widget.h +++ b/src/gui/search_widget.h @@ -13,6 +13,14 @@ #include "../utils/types.h" #include "../core/aur_helper.h" +/** + * @brief Widget for searching packages across repositories. + * + * Memory Management: + * - m_aurHelper: Owned by std::unique_ptr for explicit lifetime management + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + * - Package cards are dynamically created/destroyed in displayResults/clearResults + */ class SearchWidget : public QWidget { Q_OBJECT @@ -29,15 +37,18 @@ public slots: void displayResults(const QVector& results); void clearResults(); - QLineEdit* m_searchInput; - QPushButton* m_searchButton; - QComboBox* m_filterCombo; - QScrollArea* m_scrollArea; - QWidget* m_contentWidget; - QGridLayout* m_gridLayout; - QLabel* m_statusLabel; + // Qt parent-child managed widgets (non-owning pointers) + QLineEdit* m_searchInput = nullptr; + QPushButton* m_searchButton = nullptr; + QComboBox* m_filterCombo = nullptr; + QScrollArea* m_scrollArea = nullptr; + QWidget* m_contentWidget = nullptr; + QGridLayout* m_gridLayout = nullptr; + QLabel* m_statusLabel = nullptr; + // Owned resources std::unique_ptr m_aurHelper; + QVector m_currentResults; QVector m_allResults; diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp index 0e3bac2..6d31e71 100644 --- a/src/gui/settings_widget.cpp +++ b/src/gui/settings_widget.cpp @@ -12,23 +12,7 @@ #include SettingsWidget::SettingsWidget(QWidget* parent) - : QWidget(parent) - , m_repositoryGroup(nullptr) - , m_coreRepoCheckbox(nullptr) - , m_extraRepoCheckbox(nullptr) - , m_multilibRepoCheckbox(nullptr) - , m_chaoticAurCheckbox(nullptr) - , m_chaoticAurGroup(nullptr) - , m_setupChaoticButton(nullptr) - , m_removeChaoticButton(nullptr) - , m_maintenanceGroup(nullptr) - , m_removeLockButton(nullptr) - , m_syncReposButton(nullptr) - , m_cancelProcessButton(nullptr) - , m_applyButton(nullptr) - , m_statusLabel(nullptr) - , m_originalMultilibState(false) - , m_originalChaoticAurState(false) { + : QWidget(parent) { setupUi(); loadCurrentSettings(); diff --git a/src/gui/settings_widget.h b/src/gui/settings_widget.h index 6985381..064f2f8 100644 --- a/src/gui/settings_widget.h +++ b/src/gui/settings_widget.h @@ -8,6 +8,12 @@ #include #include +/** + * @brief Widget for application and repository settings. + * + * Memory Management: + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + */ class SettingsWidget : public QWidget { Q_OBJECT @@ -36,33 +42,33 @@ class SettingsWidget : public QWidget { bool disableChaoticAurInPacmanConf(); void applySettings(); - // Repository settings - QGroupBox* m_repositoryGroup; - QCheckBox* m_coreRepoCheckbox; - QCheckBox* m_extraRepoCheckbox; - QCheckBox* m_multilibRepoCheckbox; - QCheckBox* m_chaoticAurCheckbox; + // Repository settings (Qt parent-child managed, non-owning pointers) + QGroupBox* m_repositoryGroup = nullptr; + QCheckBox* m_coreRepoCheckbox = nullptr; + QCheckBox* m_extraRepoCheckbox = nullptr; + QCheckBox* m_multilibRepoCheckbox = nullptr; + QCheckBox* m_chaoticAurCheckbox = nullptr; - // Chaotic-AUR setup - QGroupBox* m_chaoticAurGroup; - QPushButton* m_setupChaoticButton; - QPushButton* m_removeChaoticButton; + // Chaotic-AUR setup (Qt parent-child managed) + QGroupBox* m_chaoticAurGroup = nullptr; + QPushButton* m_setupChaoticButton = nullptr; + QPushButton* m_removeChaoticButton = nullptr; - // Maintenance settings - QGroupBox* m_maintenanceGroup; - QPushButton* m_removeLockButton; - QPushButton* m_syncReposButton; - QPushButton* m_cancelProcessButton; + // Maintenance settings (Qt parent-child managed) + QGroupBox* m_maintenanceGroup = nullptr; + QPushButton* m_removeLockButton = nullptr; + QPushButton* m_syncReposButton = nullptr; + QPushButton* m_cancelProcessButton = nullptr; - // Control buttons - QPushButton* m_applyButton; + // Control buttons (Qt parent-child managed) + QPushButton* m_applyButton = nullptr; - // Status - QLabel* m_statusLabel; + // Status (Qt parent-child managed) + QLabel* m_statusLabel = nullptr; // Track original state - bool m_originalMultilibState; - bool m_originalChaoticAurState; + bool m_originalMultilibState = false; + bool m_originalChaoticAurState = false; private slots: void onApplyClicked(); diff --git a/src/gui/updates_widget.cpp b/src/gui/updates_widget.cpp index 347803b..f191a46 100644 --- a/src/gui/updates_widget.cpp +++ b/src/gui/updates_widget.cpp @@ -94,8 +94,7 @@ UpdatesWidget::UpdatesWidget(QWidget* parent) , m_progressLabel(new QLabel(this)) , m_toggleLogButton(new QPushButton("Show Logs", this)) , m_logWidget(new QWidget(this)) - , m_logViewer(new QTextEdit(this)) - , m_logVisible(false) { + , m_logViewer(new QTextEdit(this)) { setupUi(); diff --git a/src/gui/updates_widget.h b/src/gui/updates_widget.h index bf045e4..4742f2e 100644 --- a/src/gui/updates_widget.h +++ b/src/gui/updates_widget.h @@ -14,6 +14,13 @@ class UpdateItem; +/** + * @brief Widget for displaying and managing package updates. + * + * Memory Management: + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + * - UpdateItem widgets are dynamically created/destroyed in displayUpdates/clearUpdates + */ class UpdatesWidget : public QWidget { Q_OBJECT @@ -33,23 +40,24 @@ class UpdatesWidget : public QWidget { void hideProgress(); void toggleLogViewer(); - QLineEdit* m_searchInput; - QScrollArea* m_scrollArea; - QWidget* m_contentWidget; - QVBoxLayout* m_contentLayout; - QLabel* m_statusLabel; - QLabel* m_countLabel; - QPushButton* m_updateAllButton; - QPushButton* m_checkButton; + // Qt parent-child managed widgets (non-owning pointers) + QLineEdit* m_searchInput = nullptr; + QScrollArea* m_scrollArea = nullptr; + QWidget* m_contentWidget = nullptr; + QVBoxLayout* m_contentLayout = nullptr; + QLabel* m_statusLabel = nullptr; + QLabel* m_countLabel = nullptr; + QPushButton* m_updateAllButton = nullptr; + QPushButton* m_checkButton = nullptr; - // Progress bar and log viewer - QWidget* m_progressWidget; - QProgressBar* m_progressBar; - QLabel* m_progressLabel; - QPushButton* m_toggleLogButton; - QWidget* m_logWidget; - QTextEdit* m_logViewer; - bool m_logVisible; + // Progress bar and log viewer (Qt parent-child managed) + QWidget* m_progressWidget = nullptr; + QProgressBar* m_progressBar = nullptr; + QLabel* m_progressLabel = nullptr; + QPushButton* m_toggleLogButton = nullptr; + QWidget* m_logWidget = nullptr; + QTextEdit* m_logViewer = nullptr; + bool m_logVisible = false; QVector m_updates; QVector m_filteredUpdates; From 337414068bfb3634cec86561ced284da18c5e9ee Mon Sep 17 00:00:00 2001 From: demonkillerr Date: Wed, 17 Dec 2025 22:48:44 +0000 Subject: [PATCH 66/71] update TODO --- TODO.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index 1b5b1cc..047078a 100644 --- a/TODO.md +++ b/TODO.md @@ -1,9 +1,13 @@ - [x] Add chaotic aur to search tab if enabled - [x] Add launch button on package card if package is installed and remove when uninstalled - [] Add detailed mirrorlist tab to set mirrorlist -- [] Add version information +- [x] Add version information - [] Implement an AUR helper in core to remove dependence on paru and yay - +- [] Ask password only once on startup - startup_auth +- [] Improve settings page - settings_tab +- [] Move all styles to single stylesheet - style_and_theme +- [] Clean up UI; make UI look more modern (check gnome's styling options) - style_and_theme +- [] Set a light/dark theme toggle, or follow system's theme - style_and_theme ## Future Enhancements From 4ed6c9991a8b952c37e54b25b193223e1ce81c59 Mon Sep 17 00:00:00 2001 From: demonkillerr Date: Sun, 21 Dec 2025 13:01:12 +0000 Subject: [PATCH 67/71] update todo --- TODO.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO.md b/TODO.md index 047078a..6998488 100644 --- a/TODO.md +++ b/TODO.md @@ -8,6 +8,8 @@ - [] Move all styles to single stylesheet - style_and_theme - [] Clean up UI; make UI look more modern (check gnome's styling options) - style_and_theme - [] Set a light/dark theme toggle, or follow system's theme - style_and_theme +- [] Look into spdlog for logging +- [] Look into CppUTest or Google Test (gtest) for test ## Future Enhancements From 701e0f5db5fde599e644d0848b46c0354e203d32 Mon Sep 17 00:00:00 2001 From: demonkillerr Date: Sun, 21 Dec 2025 13:18:31 +0000 Subject: [PATCH 68/71] [CI] extract version info from cmake and publish only on main branch; build on rest --- .github/workflows/release.yml | 137 ++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..6cdbe33 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,137 @@ +name: Build and Release ALG App Store + +on: + push: + branches: [ "main", "devel", "qt6/c++" ] + paths: + - '**.cpp' + - '**.h' + - 'CMakeLists.txt' + - '.github/workflows/**' + pull_request: + branches: [ "main", "devel", "qt6/c++" ] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.get_version.outputs.version }} + should_release: ${{ steps.check_release.outputs.should_release }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 2 # Need history to check changed files + + - name: Extract version from CMakeLists.txt + id: get_version + run: | + VERSION=$(grep -oP 'project\(alg-app-store VERSION \K[0-9]+\.[0-9]+\.[0-9]+' CMakeLists.txt) + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Detected version: $VERSION" + + - name: Check if this should trigger a release + id: check_release + run: | + # Only release on main branch when CMakeLists.txt was modified + if [[ "${{ github.ref }}" == "refs/heads/main" && "${{ github.event_name }}" == "push" ]]; then + # Check if CMakeLists.txt was changed in this push + if git diff --name-only HEAD~1 HEAD | grep -q "CMakeLists.txt"; then + echo "should_release=true" >> $GITHUB_OUTPUT + echo "Release triggered: CMakeLists.txt changed on main branch" + else + echo "should_release=false" >> $GITHUB_OUTPUT + echo "No release: CMakeLists.txt not changed" + fi + else + echo "should_release=false" >> $GITHUB_OUTPUT + echo "No release: not on main branch or not a push event" + fi + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + build-essential \ + cmake \ + qt6-base-dev \ + qt6-tools-dev \ + qt6-tools-dev-tools \ + libalpm-dev \ + libarchive-dev \ + libcurl4-openssl-dev \ + pkg-config + + - name: Configure CMake + run: | + mkdir -p build + cd build + cmake .. + + - name: Build + run: | + cd build + make -j$(nproc) + + - name: Check build artifacts + run: | + ls -lh build/alg-app-store + file build/alg-app-store + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: alg-app-store-${{ github.ref_name }}-${{ steps.get_version.outputs.version }} + path: build/alg-app-store + retention-days: 30 + + release: + needs: build + runs-on: ubuntu-latest + if: needs.build.outputs.should_release == 'true' + permissions: + contents: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Download build artifact + uses: actions/download-artifact@v4 + with: + name: alg-app-store-${{ github.ref_name }}-${{ needs.build.outputs.version }} + path: ./release + + - name: Prepare release assets + run: | + chmod +x ./release/alg-app-store + tar -czvf alg-app-store-${{ needs.build.outputs.version }}-linux-x86_64.tar.gz -C ./release alg-app-store + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + with: + tag_name: v${{ needs.build.outputs.version }} + name: ALG App Store v${{ needs.build.outputs.version }} + body: | + ## ALG App Store v${{ needs.build.outputs.version }} + + A modern package manager GUI for Arch Linux. + + ### Installation + ```bash + tar -xzvf alg-app-store-${{ needs.build.outputs.version }}-linux-x86_64.tar.gz + sudo mv alg-app-store /usr/local/bin/ + ``` + + ### Requirements + - Qt6 (Core, Gui, Widgets, Network, Concurrent) + - libalpm (pacman library) + - yay or paru (for AUR support) + files: | + alg-app-store-${{ needs.build.outputs.version }}-linux-x86_64.tar.gz + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 1c56ebf5ba187429e1ce00f947d4530c8c65d348 Mon Sep 17 00:00:00 2001 From: demonkillerr Date: Sun, 21 Dec 2025 13:19:36 +0000 Subject: [PATCH 69/71] bump version --- .github/workflows/build.yml | 53 ------------------------------------- CMakeLists.txt | 2 +- src/gui/mainwindow.cpp | 2 +- 3 files changed, 2 insertions(+), 55 deletions(-) delete mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 7c33723..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Build ALG App Store - -on: - push: - branches: [ "main", "qt6/c++" ] - pull_request: - branches: [ "main", "qt6/c++" ] - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - build-essential \ - cmake \ - qt6-base-dev \ - qt6-tools-dev \ - qt6-tools-dev-tools \ - libalpm-dev \ - libarchive-dev \ - libcurl4-openssl-dev \ - pkg-config - - - name: Configure CMake - run: | - mkdir -p build - cd build - cmake .. - - - name: Build - run: | - cd build - make -j$(nproc) - - - name: Check build artifacts - run: | - ls -lh build/alg-app-store - file build/alg-app-store - - - name: Upload build artifact - uses: actions/upload-artifact@v4 - with: - name: alg-app-store - path: build/alg-app-store - retention-days: 7 diff --git a/CMakeLists.txt b/CMakeLists.txt index 6148f4a..e990cd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.16) -project(alg-app-store VERSION 2.0.0 LANGUAGES CXX) +project(alg-app-store VERSION 0.2.28 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 8282b08..dd71d18 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -117,7 +117,7 @@ void MainWindow::createMenuBar() { QMessageBox::about(this, "About ALG App Store", "ALG App Store (Beta)\n\n" "A modern package manager for Arch Linux\n" - "Version: 0.2.26\n" + "Version: 0.2.28\n" "Built with Qt6 and C++17\n\n" "© 2025 Arka Linux GUI"); }); From 1381be3f1c9025d4ad1dfde64028ad60c9f3c5d1 Mon Sep 17 00:00:00 2001 From: demonkillerr Date: Sun, 21 Dec 2025 13:30:11 +0000 Subject: [PATCH 70/71] ci: use Arch Linux container for native libalpm support --- .github/workflows/release.yml | 37 ++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6cdbe33..590c4ca 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,28 +2,47 @@ name: Build and Release ALG App Store on: push: - branches: [ "main", "devel", "qt6/c++" ] + branches: [ "main", "devel", "qt6" ] paths: - '**.cpp' - '**.h' - 'CMakeLists.txt' - '.github/workflows/**' pull_request: - branches: [ "main", "devel", "qt6/c++" ] + branches: [ "main", "devel", "qt6" ] workflow_dispatch: jobs: build: runs-on: ubuntu-latest + container: + image: archlinux:latest outputs: version: ${{ steps.get_version.outputs.version }} should_release: ${{ steps.check_release.outputs.should_release }} steps: + - name: Install base dependencies + run: | + pacman -Syu --noconfirm + pacman -S --noconfirm --needed \ + base-devel \ + git \ + cmake \ + qt6-base \ + qt6-tools \ + pacman \ + libarchive \ + curl \ + pkgconf + - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 2 # Need history to check changed files + + - name: Mark git directory as safe + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - name: Extract version from CMakeLists.txt id: get_version @@ -49,20 +68,6 @@ jobs: echo "should_release=false" >> $GITHUB_OUTPUT echo "No release: not on main branch or not a push event" fi - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y \ - build-essential \ - cmake \ - qt6-base-dev \ - qt6-tools-dev \ - qt6-tools-dev-tools \ - libalpm-dev \ - libarchive-dev \ - libcurl4-openssl-dev \ - pkg-config - name: Configure CMake run: | From 1c157fe373b1675b3a094fc8f5338a9f0cef5c51 Mon Sep 17 00:00:00 2001 From: demonkillerr Date: Sun, 21 Dec 2025 13:40:02 +0000 Subject: [PATCH 71/71] ci: fix artifact name for PR refs by replacing slashes with dashes --- .github/workflows/release.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 590c4ca..9ccbd91 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,6 +20,7 @@ jobs: outputs: version: ${{ steps.get_version.outputs.version }} should_release: ${{ steps.check_release.outputs.should_release }} + artifact_name: ${{ steps.artifact.outputs.name }} steps: - name: Install base dependencies @@ -85,10 +86,19 @@ jobs: ls -lh build/alg-app-store file build/alg-app-store + - name: Set artifact name + id: artifact + run: | + # Replace forward slashes with dashes to handle PR refs like "12/merge" + ARTIFACT_NAME="alg-app-store-${{ github.ref_name }}-${{ steps.get_version.outputs.version }}" + ARTIFACT_NAME="${ARTIFACT_NAME//\//-}" + echo "name=$ARTIFACT_NAME" >> $GITHUB_OUTPUT + echo "Artifact name: $ARTIFACT_NAME" + - name: Upload build artifact uses: actions/upload-artifact@v4 with: - name: alg-app-store-${{ github.ref_name }}-${{ steps.get_version.outputs.version }} + name: ${{ steps.artifact.outputs.name }} path: build/alg-app-store retention-days: 30 @@ -106,7 +116,7 @@ jobs: - name: Download build artifact uses: actions/download-artifact@v4 with: - name: alg-app-store-${{ github.ref_name }}-${{ needs.build.outputs.version }} + name: ${{ needs.build.outputs.artifact_name }} path: ./release - name: Prepare release assets