From 6e5297c5e1441624571e5cf27fe6e3bdde0d69fa Mon Sep 17 00:00:00 2001 From: Arnaud Date: Tue, 10 Feb 2026 13:27:11 +0400 Subject: [PATCH 1/6] Lot of updates in an ugly state --- .gitignore | 1 + CMakeLists.txt | 4 +- flake.lock | 176 +++++++---- flake.nix | 7 +- src/StorageBackend.cpp | 590 ++++++++++++++++++++++++++++++++++-- src/StorageBackend.h | 60 +++- src/qml/CMakeLists.txt | 1 + src/qml/StorageView.qml | 406 ++++++++++++++++++++++++- vendor/logos-cpp-sdk | 2 +- vendor/logos-liblogos | 2 +- vendor/logos-storage-module | 2 +- 11 files changed, 1136 insertions(+), 115 deletions(-) diff --git a/.gitignore b/.gitignore index b7fb871..1290dfc 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ libs app/build CMakeLists.txt.user generated_code +.cache \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index fe1c452..c4ddce7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,7 +213,7 @@ if(_storage_module_is_source) # Add custom target to run the cpp generator for the storage module add_custom_target(run_cpp_generator_storage_module - COMMAND "${CPP_GENERATOR}" "${PLUGIN_FILE}" --module-only --output-dir "${PLUGINS_OUTPUT_DIR}" + COMMAND "${CPP_GENERATOR}" "${PLUGIN_FILE}" --interface "${LOGOS_STORAGE_ROOT}/storage_module_interface.h" --module-only --output-dir "${PLUGINS_OUTPUT_DIR}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMMENT "Running logos-cpp-generator on ${PLUGIN_FILE} with output-dir ${PLUGINS_OUTPUT_DIR}" VERBATIM @@ -349,6 +349,8 @@ endif() if(_cpp_sdk_is_source) target_include_directories(storage_ui PRIVATE + + #${PLUGINS_OUTPUT_DIR} ${LOGOS_CPP_SDK_ROOT}/cpp ${LOGOS_CPP_SDK_ROOT}/cpp/generated ) diff --git a/flake.lock b/flake.lock index ec81a20..e836e77 100644 --- a/flake.lock +++ b/flake.lock @@ -1,32 +1,38 @@ { "nodes": { - "circom-compat": { + "logos-capability-module": { "inputs": { + "logos-cpp-sdk": [ + "logos-cpp-sdk" + ], + "logos-liblogos": "logos-liblogos", "nixpkgs": [ - "logos-storage-module", - "logos-storage", + "logos-capability-module", + "logos-liblogos", "nixpkgs" ] }, "locked": { - "lastModified": 1736521871, - "narHash": "sha256-d34XNLg9NGPEOARHW+BIOAWalkHdEUAwsv3mpLZQxds=", - "owner": "logos-storage", - "repo": "circom-compat-ffi", - "rev": "8cd4ed44fdafe59d4ec1184420639cae4c4dbab9", + "lastModified": 1767809111, + "narHash": "sha256-jehjsB+BpDJlVu3I7x+vFVOdXmy9MDmFTJtRqzFUONo=", + "owner": "logos-co", + "repo": "logos-capability-module", + "rev": "7b35383e0aa4e28a4633ed18a87efb57636939b1", "type": "github" }, "original": { - "owner": "logos-storage", - "repo": "circom-compat-ffi", + "owner": "logos-co", + "repo": "logos-capability-module", "type": "github" } }, - "logos-capability-module": { + "logos-capability-module_2": { "inputs": { - "logos-cpp-sdk": "logos-cpp-sdk", - "logos-liblogos": "logos-liblogos", + "logos-cpp-sdk": "logos-cpp-sdk_3", + "logos-liblogos": "logos-liblogos_4", "nixpkgs": [ + "logos-storage-module", + "logos-liblogos", "logos-capability-module", "logos-liblogos", "nixpkgs" @@ -68,6 +74,25 @@ "inputs": { "nixpkgs": "nixpkgs_2" }, + "locked": { + "lastModified": 1770703782, + "narHash": "sha256-KloAfjqljpy9Ye/z/WcbwsqkBMph4X6rpWObas1VYH8=", + "owner": "logos-co", + "repo": "logos-cpp-sdk", + "rev": "5a8a6c723f2c50587760f763753c4fa7c11d46bf", + "type": "github" + }, + "original": { + "owner": "logos-co", + "ref": "feat/logos-result", + "repo": "logos-cpp-sdk", + "type": "github" + } + }, + "logos-cpp-sdk_3": { + "inputs": { + "nixpkgs": "nixpkgs_3" + }, "locked": { "lastModified": 1761230734, "narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=", @@ -82,34 +107,16 @@ "type": "github" } }, - "logos-cpp-sdk_3": { - "inputs": { - "nixpkgs": "nixpkgs_3" - }, - "locked": { - "lastModified": 1767724329, - "narHash": "sha256-UPkqxqxbKwU5Dmu00TnjiJVXUmfVylF3p1qziEuYwIE=", - "owner": "logos-co", - "repo": "logos-cpp-sdk", - "rev": "32f1d7080d784ff044d91d076ef2f0c7305d4784", - "type": "github" - }, - "original": { - "owner": "logos-co", - "repo": "logos-cpp-sdk", - "type": "github" - } - }, "logos-cpp-sdk_4": { "inputs": { "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1764699992, - "narHash": "sha256-nCmK9C9F31cHvy6lWKR5WGl99aJbS3kIsROAoZ4OrwI=", + "lastModified": 1761230734, + "narHash": "sha256-CMRUwXH7pJZ1OI6bd/TDDDXKqQ1tQZHQEOOwK8TgYHI=", "owner": "logos-co", "repo": "logos-cpp-sdk", - "rev": "5d0bbd0d1e00aad0532ffa7c8bf2c80f460a4f6d", + "rev": "4b143922c190df00bb3835441c9f0075cb28283b", "type": "github" }, "original": { @@ -141,11 +148,11 @@ "nixpkgs": "nixpkgs_6" }, "locked": { - "lastModified": 1764699992, - "narHash": "sha256-nCmK9C9F31cHvy6lWKR5WGl99aJbS3kIsROAoZ4OrwI=", + "lastModified": 1767724329, + "narHash": "sha256-UPkqxqxbKwU5Dmu00TnjiJVXUmfVylF3p1qziEuYwIE=", "owner": "logos-co", "repo": "logos-cpp-sdk", - "rev": "5d0bbd0d1e00aad0532ffa7c8bf2c80f460a4f6d", + "rev": "32f1d7080d784ff044d91d076ef2f0c7305d4784", "type": "github" }, "original": { @@ -156,7 +163,7 @@ }, "logos-liblogos": { "inputs": { - "logos-cpp-sdk": "logos-cpp-sdk_2", + "logos-cpp-sdk": "logos-cpp-sdk", "nixpkgs": [ "logos-capability-module", "logos-liblogos", @@ -180,7 +187,9 @@ }, "logos-liblogos_2": { "inputs": { - "logos-cpp-sdk": "logos-cpp-sdk_4", + "logos-cpp-sdk": [ + "logos-cpp-sdk" + ], "nixpkgs": [ "logos-liblogos", "logos-cpp-sdk", @@ -204,7 +213,9 @@ }, "logos-liblogos_3": { "inputs": { - "logos-cpp-sdk": "logos-cpp-sdk_6", + "logos-capability-module": "logos-capability-module_2", + "logos-cpp-sdk": "logos-cpp-sdk_5", + "logos-module": "logos-module", "nixpkgs": [ "logos-storage-module", "logos-liblogos", @@ -213,11 +224,11 @@ ] }, "locked": { - "lastModified": 1767722338, - "narHash": "sha256-89RYfnramvJRufy47Kdx662TMHaFVSpS88ouWff3Csw=", + "lastModified": 1770154824, + "narHash": "sha256-WGI+3FkPdeytfLJ3ZJYr1O8esUnQjcmMJEYwB/EBZMs=", "owner": "logos-co", "repo": "logos-liblogos", - "rev": "ca1fda7cabd70027e51d86392f5e29b3fff385f9", + "rev": "901dd86d47216b15b6f1260b7b6bb4ecd88a8f9d", "type": "github" }, "original": { @@ -226,22 +237,73 @@ "type": "github" } }, + "logos-liblogos_4": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_4", + "nixpkgs": [ + "logos-storage-module", + "logos-liblogos", + "logos-capability-module", + "logos-liblogos", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1761845775, + "narHash": "sha256-ulK8xq05ejK6qIgZ7WtWb/MJt2rk5BKfDA2z7mM3wq8=", + "owner": "logos-co", + "repo": "logos-liblogos", + "rev": "a92c2c1268bc70764c8f73c7bce07d21024f5af9", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-liblogos", + "type": "github" + } + }, + "logos-module": { + "inputs": { + "logos-cpp-sdk": "logos-cpp-sdk_6", + "nixpkgs": [ + "logos-storage-module", + "logos-liblogos", + "logos-module", + "logos-cpp-sdk", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770062426, + "narHash": "sha256-zc7ZxDTlqOCYGyEHhrTA/7GS1EWh7+4amdPUKh+gGds=", + "owner": "logos-co", + "repo": "logos-module", + "rev": "f7ee69d9ad9f27c84f04f59896e9194125e951dc", + "type": "github" + }, + "original": { + "owner": "logos-co", + "repo": "logos-module", + "type": "github" + } + }, "logos-storage": { "inputs": { - "circom-compat": "circom-compat", "nixpkgs": "nixpkgs_7" }, "locked": { - "lastModified": 1769016529, - "narHash": "sha256-pzUrdFKSEraZQzO2a9Uj5oDMas+Vtpu6+p4bG+lRnsk=", + "lastModified": 1770408620, + "narHash": "sha256-pMbOn5VoDCnCM3O7XyigYK9A7dhUvoXCWzXlD7ZskMM=", "ref": "refs/heads/master", - "rev": "3c09f008bb5266a669fd19f18368f9e8b861b664", - "revCount": 877, + "rev": "a5ce5e1fb61329884769fc100fb731a913b97dac", + "revCount": 893, "submodules": true, "type": "git", "url": "https://github.com/logos-storage/logos-storage-nim" }, "original": { + "rev": "a5ce5e1fb61329884769fc100fb731a913b97dac", "submodules": true, "type": "git", "url": "https://github.com/logos-storage/logos-storage-nim" @@ -249,7 +311,9 @@ }, "logos-storage-module": { "inputs": { - "logos-cpp-sdk": "logos-cpp-sdk_5", + "logos-cpp-sdk": [ + "logos-cpp-sdk" + ], "logos-liblogos": "logos-liblogos_3", "logos-storage": "logos-storage", "nixpkgs": [ @@ -259,11 +323,11 @@ ] }, "locked": { - "lastModified": 1769611047, - "narHash": "sha256-U8lV4hgntPTMO0wpyIDFKMN1N3jSGnxKDCGHS9WoEb8=", + "lastModified": 1770715398, + "narHash": "sha256-xs/j/5g5tPnKj5uAGJzmUTyzbJkGg3Z4xPDBsw9nF7c=", "owner": "logos-co", "repo": "logos-storage-module", - "rev": "14cc30674980685442e66639c37c587263520147", + "rev": "93c832f981e9e319ea3062e30107b037b965c7ab", "type": "github" }, "original": { @@ -370,11 +434,11 @@ }, "nixpkgs_7": { "locked": { - "lastModified": 1736200483, - "narHash": "sha256-JO+lFN2HsCwSLMUWXHeOad6QUxOuwe9UOAF/iSl1J4I=", + "lastModified": 1751274312, + "narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3f0a8ac25fb674611b98089ca3a5dd6480175751", + "rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674", "type": "github" }, "original": { @@ -387,7 +451,7 @@ "root": { "inputs": { "logos-capability-module": "logos-capability-module", - "logos-cpp-sdk": "logos-cpp-sdk_3", + "logos-cpp-sdk": "logos-cpp-sdk_2", "logos-liblogos": "logos-liblogos_2", "logos-storage-module": "logos-storage-module", "nixpkgs": [ diff --git a/flake.nix b/flake.nix index 85f868d..7e0e1b0 100644 --- a/flake.nix +++ b/flake.nix @@ -4,10 +4,15 @@ inputs = { # Follow the same nixpkgs as logos-liblogos to ensure compatibility nixpkgs.follows = "logos-liblogos/nixpkgs"; - logos-cpp-sdk.url = "github:logos-co/logos-cpp-sdk"; + logos-cpp-sdk.url = "github:logos-co/logos-cpp-sdk?ref=feat/logos-result"; logos-liblogos.url = "github:logos-co/logos-liblogos?ref=fix/logos-cleanup-on-terminate"; logos-storage-module.url = "github:logos-co/logos-storage-module"; + # logos-storage-module.url = "path:/home/arnaud/Work/logos/logos-storage-module"; logos-capability-module.url = "github:logos-co/logos-capability-module"; + + logos-liblogos.inputs.logos-cpp-sdk.follows = "logos-cpp-sdk"; + logos-storage-module.inputs.logos-cpp-sdk.follows = "logos-cpp-sdk"; + logos-capability-module.inputs.logos-cpp-sdk.follows = "logos-cpp-sdk"; }; outputs = { self, nixpkgs, logos-cpp-sdk, logos-liblogos, logos-storage-module, logos-capability-module }: diff --git a/src/StorageBackend.cpp b/src/StorageBackend.cpp index 2cab9dc..690e62c 100644 --- a/src/StorageBackend.cpp +++ b/src/StorageBackend.cpp @@ -1,11 +1,21 @@ #include "StorageBackend.h" #include #include +#include +#include #include #include #include #include +// StorageBackend is responsible for managing the interaction with the storage module. +// It is mocked in the QML. +// There are currently 2 ways to display debug information: +// - the first one is to log only in the console using qDebug/qWarning. This is basically +// for developers: entering a function, sending a command to the storage module... +// - the second one is to use the "debug" helper that logs both in the console and in a +// QString property that can be displayed in the UI. This is more for users to understand +// what is happening. StorageBackend::StorageBackend(LogosAPI* logosAPI, QObject* parent) : QObject(parent), m_status(Destroyed), m_logosAPI(nullptr), m_logos(nullptr) { qDebug() << "Initializing StorageBackend..."; @@ -17,6 +27,7 @@ StorageBackend::StorageBackend(LogosAPI* logosAPI, QObject* parent) } m_logos = new LogosModules(m_logosAPI); + m_showDebug = false; initStorage(); } @@ -30,26 +41,40 @@ StorageBackend::~StorageBackend() void StorageBackend::initStorage() { qDebug() << "StorageBackend::initStorage called"; - bool result = m_logos->storage_module.init("{}"); + QString jsonConfig = "{}"; - qDebug() << "StorageBackend::initStorage: init result =" << result; + QFileInfo info("config.json"); + if (info.exists() && info.isFile()) { + debug("config.json is found, let's try to load it..."); - if (!result) { - qDebug() << "StorageBackend: Failed to initialise Storage module."; - setStatus(Destroyed, "Failed to initialise Storage module."); + QFile file("config.json"); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + jsonConfig = QString::fromUtf8(file.readAll()); + + debug("config.json content is: " + jsonConfig); + } else { + debug("Failed to load config.json"); + } + } + + LogosResult result = m_logos->storage_module.init(jsonConfig); + + qDebug() << "StorageBackend::initStorage: init result =" << result.success; + + if (!result.success) { + setStatus(Destroyed, result.getValue()); return; } setStatus(Stopped, "Storage module ready."); if (!m_logos->storage_module.on("storageStart", [this](const QVariantList& data) { - int code = data[0].toInt(); + bool success = data[0].toBool(); - if (code != RET_OK) { - qDebug() << "StorageBackend: storageStart event failure with code" << code; - setStatus(Stopped, "Failed to start Storage module."); + if (!success) { + QString message = data[1].toString(); + setStatus(Stopped, "Failed to start Storage module:" + message); } else { - qDebug() << "StorageBackend: storageStart event success"; setStatus(Running, "Storage module started."); } })) { @@ -57,13 +82,12 @@ void StorageBackend::initStorage() { } if (!m_logos->storage_module.on("storageStop", [this](const QVariantList& data) { - int code = data[0].toInt(); + bool success = data[0].toBool(); - if (code != RET_OK) { - qDebug() << "StorageBackend: storageStop event failure with code" << code; - setStatus(Running, "Failed to stop Storage module."); + if (!success) { + QString message = data[1].toString(); + setStatus(Running, "Failed to stop Storage module:" + message); } else { - qDebug() << "StorageBackend: storageStop event success"; setStatus(Stopped, "Storage module stopped."); emit stopped(); } @@ -71,35 +95,113 @@ void StorageBackend::initStorage() { qWarning() << "StorageWidget: failed to subscribe to storageStop events"; } + if (!m_logos->storage_module.on("storageConnect", [this](const QVariantList& data) { + bool success = data[0].toBool(); + + if (!success) { + QString message = data[1].toString(); + debug("Failed to connect: " + message); + } else { + // TODO add the peer id + debug("Successfully connected to peer."); + } + })) { + qWarning() << "StorageWidget: failed to subscribe to storageConnect events"; + } + + if (!m_logos->storage_module.on("storageUploadProgress", [this](const QVariantList& data) { + bool success = data[0].toBool(); + + if (!success) { + QString message = data[1].toString(); + debug("Failure during upload progress: " + message); + } else { + QString sessionId = data[1].toString(); + int len = data[2].toInt(); + // debug("Uploaded " + QString::number(len) + " bytes for session " + sessionId); + } + })) { + qWarning() << "StorageWidget: failed to subscribe to storageUploadProgress events"; + } + + if (!m_logos->storage_module.on("storageUploadDone", [this](const QVariantList& data) { + bool success = data[0].toBool(); + + if (!success) { + QString message = data[1].toString(); + debug("Failed to upload: " + message); + } else { + QString sessionId = data[1].toString(); + m_cid = data[2].toString(); + emit cidChanged(); + debug("Upload completed for session " + sessionId + " with CID " + m_cid); + } + })) { + qWarning() << "StorageWidget: failed to subscribe to storageUploadProgress events"; + } + + if (!m_logos->storage_module.on("storageDownloadProgress", [this](const QVariantList& data) { + bool success = data[0].toBool(); + + if (!success) { + QString message = data[1].toString(); + debug("Failure during download progress: " + message); + } else { + QString sessionId = data[1].toString(); + int len = data[2].toInt(); + debug("Downloaded " + QString::number(len) + " bytes for session " + sessionId); + } + })) { + qWarning() << "StorageWidget: failed to subscribe to storageDownloadProgress events"; + } + + if (!m_logos->storage_module.on("storageDownloadDone", [this](const QVariantList& data) { + bool success = data[0].toBool(); + + if (!success) { + QString message = data[1].toString(); + debug("Failed to download: " + message); + } else { + QString sessionId = data[1].toString(); + m_cid = data[2].toString(); + emit cidChanged(); + debug("Download completed for session " + sessionId + " with CID " + m_cid); + } + })) { + qWarning() << "StorageWidget: failed to subscribe to storageDownloadProgress events"; + } + startStop(); } -void StorageBackend::setStatus(StorageStatus newStatus, QString statusText) { +void StorageBackend::setStatus(StorageStatus newStatus, const QString& statusText) { if (m_status != newStatus || m_statusText != statusText) { m_status = newStatus; m_statusText = statusText; emit statusChanged(); - qDebug() << "StorageBackend: Status changed to" << m_status; + + debug(statusText); } } void StorageBackend::startStop() { qDebug() << "StorageBackend: startStop method called"; + // QString s = "hello"; + // emit test(0, s); if (m_status == Destroyed || m_status == Starting || m_status == Stopping) { - qDebug() << "StorageBackend: Cannot start/stop Storage in current state:" << m_status; + // TODO display the m_status properly + debug("StorageBackend: Cannot start/stop Storage in current state:" + m_status); return; } if (m_status != Running) { - qDebug() << "StorageBackend: Starting Storage..."; setStatus(Starting, "Starting Storage module..."); - bool result = m_logos->storage_module.start(); + auto result = m_logos->storage_module.start(); - if (!result) { - qDebug() << "StorageBackend: Failed to start Storage."; - setStatus(Stopped, "Failed to start Storage module."); + if (!result.success) { + setStatus(Stopped, result.getValue()); return; } @@ -110,14 +212,12 @@ void StorageBackend::startStop() { } void StorageBackend::stop() { - qDebug() << "StorageBackend: Stopping Storage..."; setStatus(Stopping, "Stopping Storage module..."); - bool result = m_logos->storage_module.stop(); + auto result = m_logos->storage_module.stop(); - if (!result) { - qDebug() << "StorageBackend: Failed to stop Storage."; - setStatus(Running, "Failed to stop Storage module."); + if (!result.success) { + setStatus(Running, result.getValue()); return; } @@ -128,11 +228,10 @@ void StorageBackend::destroy() { qDebug() << "StorageBackend: destroy method called"; StorageStatus status = m_status; - int result = m_logos->storage_module.destroy(); + auto result = m_logos->storage_module.destroy(); - if (!result) { - qDebug() << "StorageBackend: Failed to destroy Storage module." << result; - setStatus(status, "Failed to destroy Storage module."); + if (!result.success) { + setStatus(status, result.getValue()); return; } @@ -153,4 +252,429 @@ bool StorageBackend::canStartStop() const { return m_status == Running || m_stat bool StorageBackend::isRunning() { return m_status == Running; } -bool StorageBackend::isInitialised() { return m_status != Destroyed; } +QString StorageBackend::peerId() const { return m_peerId; }; + +void StorageBackend::setPeerId(const QString& peerId) { m_peerId = peerId; } + +bool StorageBackend::showDebug() const { return m_showDebug; }; + +void StorageBackend::setShowDebug(const bool showDebug) { + m_showDebug = showDebug; + emit showDebugChanged(); +} + +QString StorageBackend::debugLogs() const { return m_debugLogs; }; + +void StorageBackend::debug(const QString& log) { + if (!m_debugLogs.isEmpty()) { + m_debugLogs += "\n"; + } + + QString timestamp = QDateTime::currentDateTime().toString(Qt::ISODate); + m_debugLogs += timestamp + ": " + log; + emit debugLogsChanged(); + + qDebug() << "StorageBackend: " << log; +} + +bool StorageBackend::isInitialised() const { return m_status != Destroyed; } + +void StorageBackend::tryDebug() { + auto result = m_logos->storage_module.debug(); + + debug("Debug " + result.getValue()); +} +void StorageBackend::tryPeerConnect() { + qDebug().noquote() << "StorageBackend: tryPeerConnect called with peerId=" << m_peerId; + + // LogosResult result2 = m_logos->storage_module.space(); + // QVariantMap space = result2.getValue(); + // int quotaMaxBytes = space["quotaMaxBytes"].toInt(); + // int quotaUsedBytes = space["quotaUsedBytes"].toInt(); + // int quotaReservedBytes = space["quotaReservedBytes"].toInt(); + + // int totalBlocks = result2.getValue("totalBlocks"); + + // debug("totalBlocks " + QString::number(totalBlocks)); + // debug("quotaMaxBytes " + QString::number(quotaMaxBytes)); + // debug("quotaUsedBytes " + QString::number(quotaUsedBytes)); + // debug("quotaReservedBytes " + QString::number(quotaReservedBytes)); + + // LogosResult result = m_logos->storage_module.dataDir(); + // QString myDataDir = result.getValue(); + // qDebug() << "StorageBackend: tryPeerConnect dataDir=" << myDataDir; + + // QString peerId = m_logos->storage_module.peerId(); + + // if (peerId.isEmpty()) { + // qDebug() << "StorageBackend: Peer ID is empty."; + // return; + // } + auto result = m_logos->storage_module.connect(m_peerId, QStringList()); + + qDebug() << "StorageBackend: peerConnect result =" << result.value; + // auto result = m_logos->storage_module.debug(); + + // debug("Debug " + result.getValue()); + // QString filename = "test.txt"; + // QString sessionId = m_logos->storage_module.uploadInit(filename); + + // qDebug() << "StorageBackend: uploadInit sessionId =" << sessionId; + + // bool result = m_logos->storage_module.uploadCancel(sessionId); + + // qDebug() << "StorageBackend: uploadCancel result =" << result; +} + +void StorageBackend::tryUpload() { + qDebug() << "StorageBackend: tryUpload called"; + + // QString filename = "test.txt"; + // m_sessionId = m_logos->storage_module.uploadInit(filename); + + // qDebug() << "StorageBackend: uploadInit sessionId =" << m_sessionId; + + // QByteArray chunk = "Sample data chunk for upload."; + // bool result = m_logos->storage_module.uploadChunk(m_sessionId, chunk); + + // qDebug() << "StorageBackend: uploadChunk result =" << result; +} + +void StorageBackend::tryUploadFinalize() { + qDebug() << "StorageBackend: tryFinalize called"; + + // m_cid = m_logos->storage_module.uploadFinalize(m_sessionId); + + // qDebug() << "StorageBackend: uploadFinalize result =" << m_cid; + + // emit cidChanged(); +} + +void StorageBackend::tryUploadFile(const QUrl& url) { + qDebug() << "StorageBackend: tryUploadFile called"; + qDebug() << " URL toString():" << url.toString(); + qDebug() << " URL toLocalFile():" << url.toLocalFile(); + qDebug() << " URL path():" << url.path(); + + if (!url.isLocalFile()) { + qWarning() << "Not a local file"; + m_statusText = "The provided URL is not a local file."; + emit statusChanged(); + return; + } + + // QString filename = url.toLocalFile(); + + // // QString filename = "/home/arnaud/Work/logos/logos-storage-ui/README.md"; + // QString sessionId = m_logos->storage_module.uploadInit(filename); + + // qDebug() << "StorageBackend: uploadInit sessionId =" << sessionId; + + // QtConcurrent::run([this, url]() { + // LogosResult result = m_logos->storage_module.uploadUrl(url); + + // Go back to the main thread + // // Better to use signal + // QMetaObject::invokeMethod( + // this, + // [this, result]() { + // if (!result.success) { + // setStatus(m_status, result.getValue()); + // return; + // } + + // QString sessionId = result.value.value(); + + // qDebug() << "StorageBackend: uploadFromPath result =" << sessionId; + // }, + // Qt::QueuedConnection); + // }); + // QTimer::singleShot(0, this, [this, url]() { + LogosResult result = m_logos->storage_module.uploadUrl(url); + + if (!result.success) { + setStatus(m_status, result.getValue()); + return; + } + + QString sessionId = result.value.value(); + //}); + qDebug() << "StorageBackend: tryUploadFile result =" << sessionId; +} + +// void StorageBackend::tryUploadFile(const QUrl& url) { +// qDebug() << "StorageBackend:tryUploadFile called"; + +// if (!url.isLocalFile()) { +// qWarning() << "Not a local file"; +// m_statusText = "The provided URL is not a local file."; +// emit statusChanged(); +// return; +// } + +// QString localPath = url.toLocalFile(); +// qDebug() << " Uploading from:" << localPath; + +// QFile file(localPath); +// if (!file.open(QIODevice::ReadOnly)) { +// qWarning() << "Cannot open file for reading:" << localPath; +// m_statusText = "Cannot open file for reading: " + localPath; +// emit statusChanged(); +// return; +// } + +// const qint64 chunkSize = 1024 * 64; // 64KB +// qint64 totalSize = file.size(); +// qint64 bytesRead = 0; + +// QFileInfo fileInfo(localPath); +// QString filename = fileInfo.fileName(); + +// LogosResult result = m_logos->storage_module.uploadInit("test.txt", chunkSize); + +// if (!result.success) { +// debug(result.getValue()); +// file.close(); +// return; +// } + +// QString sessionId = result.getValue(); + +// while (!file.atEnd()) { +// QByteArray chunk = file.read(chunkSize); +// bytesRead += chunk.size(); + +// qDebug() << " Read chunk:" << chunk.size() << "bytes" +// << "Progress:" << bytesRead << "/" << totalSize; + +// result = m_logos->storage_module.uploadChunk(sessionId, chunk); + +// if (!result.success) { +// qWarning("StorageBackend:tryUploadFile failed to send uploadChunk command"); +// file.close(); +// return; +// } + +// // Calculate progress percentage +// int progress = (bytesRead * 100) / totalSize; +// qDebug() << " Progress:" << progress << "%"; +// } + +// file.close(); + +// result = m_logos->storage_module.uploadFinalize(sessionId); + +// if (!result.success) { +// qWarning("StorageBackend:tryUploadFile failed to send uploadFinalize command"); +// file.close(); +// return; +// } + +// qDebug() << "Upload complete, CID:" << result.getValue(); + +// file.close(); +// } + +void StorageBackend::tryDownloadFile(const QString& cid, const QUrl& url) { + qDebug() << "StorageBackend: tryDownloadFile called"; + + if (!url.isLocalFile()) { + qWarning() << "Not a local file"; + m_statusText = "The provided URL is not a local file."; + emit statusChanged(); + return; + } + + // QString filename = url.toLocalFile(); + + // // QString filename = "/home/arnaud/Work/logos/logos-storage-ui/README.md"; + // QString sessionId = m_logos->storage_module.uploadInit(filename); + + // qDebug() << "StorageBackend: uploadInit sessionId =" << sessionId; + + LogosResult result = m_logos->storage_module.downloadToUrl(cid, url, false); + + if (!result.success) { + setStatus(m_status, result.getValue()); + return; + } + + QString sessionId = result.value.value(); + + qDebug() << "StorageBackend: tryDownloadFile result =" << sessionId; +} + +void StorageBackend::exists(const QString& cid) { + qDebug() << "StorageBackend::exists called"; + + LogosResult result = m_logos->storage_module.exists(cid); + + if (!result.success) { + debug("StorageBackend::exists failed with error=" + result.getValue()); + return; + } + + debug("Does " + cid + " exists ? " + QVariant(result.getValue()).toString()); +} + +void StorageBackend::remove(const QString& cid) { + qDebug() << "StorageBackend::remove called"; + + LogosResult result = m_logos->storage_module.remove(cid); + + if (!result.success) { + debug("StorageBackend::remove failed with error=" + result.getValue()); + return; + } + + debug("Cid " + cid + " removed."); +} + +void StorageBackend::fetch(const QString& cid) { + qDebug() << "StorageBackend::fetch called"; + + LogosResult result = m_logos->storage_module.fetch(cid); + + if (!result.success) { + debug("StorageBackend::fetch failed with error=" + result.getValue()); + return; + } + + debug("Cid " + cid + " fetched."); +} + +void StorageBackend::version() { + qDebug() << "StorageBackend::version called"; + + LogosResult result = m_logos->storage_module.version(); + + if (!result.success) { + debug("StorageBackend::version failed with error=" + result.getValue()); + return; + } + + debug("Version: " + result.getValue()); +} + +void StorageBackend::showPeerId() { + qDebug() << "StorageBackend::peerId called"; + + LogosResult result = m_logos->storage_module.peerId(); + + if (!result.success) { + debug("StorageBackend::peerId failed with error=" + result.getValue()); + return; + } + + debug("Peer ID: " + result.getValue()); +} + +void StorageBackend::spr() { + qDebug() << "StorageBackend::spr called"; + + LogosResult result = m_logos->storage_module.spr(); + + if (!result.success) { + debug("StorageBackend::spr failed with error=" + result.getValue()); + return; + } + + debug("SPR: " + result.getValue()); +} + +void StorageBackend::dataDir() { + qDebug() << "StorageBackend::dataDir called"; + + LogosResult result = m_logos->storage_module.dataDir(); + + if (!result.success) { + debug("StorageBackend::dataDir failed with error=" + result.getValue()); + return; + } + + debug("Data dir: " + result.getValue()); +} + +void StorageBackend::downloadManifest(const QString& cid) { + qDebug() << "StorageBackend::downloadManifest called with cid=" << cid; + + LogosResult result = m_logos->storage_module.downloadManifest(cid); + + if (!result.success) { + debug("StorageBackend::downloadManifest failed with error=" + result.getValue()); + return; + } + + debug("Manifest tree cid: " + result.getValue("treeCid")); + debug(QString("Manifest datasetSize %1").arg(result.getValue("datasetSize"))); + debug(QString("Manifest blockSize %1").arg(result.getValue("blockSize"))); + debug("Manifest filename: " + result.getValue("filename")); + debug("Manifest mimetype: " + result.getValue("mimetype")); +} + +void StorageBackend::downloadManifests() { + qDebug() << "StorageBackend::downloadManifests called"; + + LogosResult result = m_logos->storage_module.manifests(); + + if (!result.success) { + debug("StorageBackend::downloadManifests failed with error=" + result.getValue()); + return; + } + + QVariantList manifestsList = result.getValue(); + int count = manifestsList.size(); + + debug(QString("Found %1 manifests").arg(count)); + + // for (const QVariant& manifestVariant : manifestsList) { + // QVariantMap manifest = manifestVariant.toMap(); + + // QString cid = manifest["cid"].toString(); + // QString treeCid = manifest["treeCid"].toString(); + // QString filename = manifest["filename"].toString(); + // qint64 datasetSize = manifest["datasetSize"].toLongLong(); + + // debug(QString("Manifest: %1, treeCid: %2, size: %3") + // .arg(filename) + // .arg(treeCid.isEmpty() ? "EMPTY" : treeCid) + // .arg(datasetSize)); + // } +} + +void StorageBackend::space() { + qDebug() << "StorageBackend::space called"; + + LogosResult result = m_logos->storage_module.space(); + + if (!result.success) { + debug("StorageBackend::space failed with error=" + result.getValue()); + return; + } + + debug(QString("Space datasetSize %1").arg(result.getValue("totalBlocks"))); + debug(QString("Space quotaMaxBytes %1").arg(result.getValue("quotaMaxBytes"))); + debug(QString("Space quotaUsedBytes %1").arg(result.getValue("quotaUsedBytes"))); + debug(QString("Space quotaReservedBytes %1").arg(result.getValue("quotaReservedBytes"))); +} + +void StorageBackend::updateLogLevel(const QString& logLevel) { + qDebug() << "StorageBackend::updateLogLevel called with logLevel=" << logLevel; + + LogosResult result = m_logos->storage_module.updateLogLevel(logLevel); + + if (!result.success) { + debug("StorageBackend::updateLogLevel failed with error=" + result.getValue()); + return; + } + + debug("Log level updated to " + logLevel); +} + +QString StorageBackend::cidText() const { + if (m_cid.isEmpty()) { + return "No CID available."; + } else { + return m_cid; + } +} diff --git a/src/StorageBackend.h b/src/StorageBackend.h index 76d0b7b..cb8370a 100644 --- a/src/StorageBackend.h +++ b/src/StorageBackend.h @@ -8,23 +8,36 @@ #include static const int RET_OK = 0; +static const int RET_PROGRESS = 3; class StorageBackend : public QObject { Q_OBJECT QML_ELEMENT + Q_PROPERTY(bool canStartStop READ canStartStop NOTIFY statusChanged) + Q_PROPERTY(bool isRunning READ isRunning NOTIFY statusChanged) + Q_PROPERTY(bool showDebug READ showDebug WRITE setShowDebug NOTIFY showDebugChanged) + Q_PROPERTY(QString startStopText READ startStopText NOTIFY statusChanged) + Q_PROPERTY(QString statusText READ statusText NOTIFY statusChanged) + Q_PROPERTY(QString cidText READ cidText NOTIFY cidChanged) + Q_PROPERTY(QString peerId READ peerId WRITE setPeerId NOTIFY peerIdChanged) + Q_PROPERTY(QString debugLogs READ debugLogs NOTIFY debugLogsChanged) public: enum StorageStatus { Stopped = 0, Starting, Running, Stopping, Destroyed }; Q_ENUM(StorageStatus) - Q_PROPERTY(bool canStartStop READ canStartStop NOTIFY statusChanged) - bool canStartStop() const; - - Q_PROPERTY(QString startStopText READ startStopText NOTIFY statusChanged) QString startStopText() const; - - Q_PROPERTY(QString statusText READ statusText NOTIFY statusChanged) QString statusText() const; + QString cidText() const; + QString peerId() const; + QString debugLogs() const; + + bool showDebug() const; + bool canStartStop() const; + bool isRunning() const; + + void setPeerId(const QString& peerId); + void setShowDebug(const bool showDebug); explicit StorageBackend(LogosAPI* logosAPI = nullptr, QObject* parent = nullptr); ~StorageBackend(); @@ -33,17 +46,42 @@ class StorageBackend : public QObject { void startStop(); void destroy(); bool isRunning(); - bool isInitialised(); void stop(); + void tryPeerConnect(); + void tryDebug(); + void tryUpload(); + void tryUploadFinalize(); + void exists(const QString& cid); + void remove(const QString& cid); + void fetch(const QString& cid); + void tryUploadFile(const QUrl& url); + void tryDownloadFile(const QString& cid, const QUrl& url); + void dataDir(); + void version(); + void spr(); + void showPeerId(); + void downloadManifest(const QString& cid); + void downloadManifests(); + void space(); + void updateLogLevel(const QString& logLevel); + + bool isInitialised() const; signals: void statusChanged(); + void peerIdChanged(); + void showDebugChanged(); + void debugLogsChanged(); + void cidChanged(); void stopped(); + void test(int code, const QString& msg); private slots: private: - void setStatus(StorageStatus newStatus, QString statusText); + void setStatus(StorageStatus newStatus, const QString& statusText); + void peerConnect(const QString& peerId); + void debug(const QString& log); void initStorage(); StorageStatus m_status; @@ -51,4 +89,10 @@ class StorageBackend : public QObject { LogosModules* m_logos; QString m_statusText; + QString m_cid; + QString m_sessionId; + QString m_peerId; + QString m_debugLogs; + + bool m_showDebug; }; diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt index ecf03e8..1719efd 100644 --- a/src/qml/CMakeLists.txt +++ b/src/qml/CMakeLists.txt @@ -74,6 +74,7 @@ add_library(storage_generated STATIC ${LOGOS_CPP_SDK_ROOT}/cpp/token_manager.cpp ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_consumer.cpp ${LOGOS_CPP_SDK_ROOT}/cpp/logos_api_provider.cpp + ${LOGOS_CPP_SDK_ROOT}/cpp/logos_types.cpp ) # Define the dependencies needed for storage_generated diff --git a/src/qml/StorageView.qml b/src/qml/StorageView.qml index 0cf8f89..5ceefd4 100644 --- a/src/qml/StorageView.qml +++ b/src/qml/StorageView.qml @@ -1,29 +1,40 @@ import QtQuick import QtQuick.Controls +import QtQuick.Dialogs //import QtQuick.Layouts -Item { +Rectangle { property var backend: mockBackend readonly property int stopped: 0 readonly property int starting: 1 readonly property int running: 2 readonly property int stopping: 3 readonly property int destroyed: 4 + property string peerId: "" + property string downloadDestination: "" + property url downloadCid: "" + property string logLevel: "" id: root width: 400 - height: 300 + height: 700 + color: "#000000" QtObject { id: mockBackend + signal test(int code, string msg) + property var status: root.stopped property var statusText: "Destroyed" property var startStopText: "Start" property var canStartStop: true + property bool showDebug: false + property var debugLogs: "" function startStop() { - if (status == root.running) { + console.log("Start") + if (status === root.running) { status = root.stopped statusText = "Stopped" startStopText = "Start" @@ -33,31 +44,400 @@ Item { startStopText = "Stop" } } - } - Rectangle { - anchors.fill: parent - anchors.leftMargin: 0 - anchors.rightMargin: 0 - anchors.topMargin: 0 - anchors.bottomMargin: 0 - color: "#202428" + function tryPeerConnect() { + console.log("Attempting peer connection...") + } + + function tryDebug() { + console.log("Attempting peer connection...") + } + + function spr() {} + + function showPeerId() {} + + function version() {} + + function dataDir() {} + + function tryUploadFinalize() { + console.log("Attempting upload finalize") + } + + function tryUploadFile(file) { + console.log("Attempting upload file") + } + + function tryDownloadFile(cid, file) { + console.log("Attempting download a file", cid, file) + } + + function exists(cid) { + console.log("Attempting exists", cid) + } + + function fetch(cid) { + console.log("Attempting fetch", cid) + } + + function remove(cid) { + console.log("Attempting remove", cid) + } + + function downloadManifest(cid) { + console.log("Attempting downloadManifest", cid) + } + + function downloadManifests() { + console.log("Attempting downloadManifests") + } + + function space() {} + + function updateLogLevel(logLevel) {} } Text { + id: statusTextElement objectName: "status" text: root.backend.statusText color: "white" font.pointSize: 20 - anchors.centerIn: parent - anchors.topMargin: 0 + anchors.top: parent.top + anchors.topMargin: 20 + anchors.horizontalCenter: parent.horizontalCenter } Button { + id: startStopButton objectName: "startStopButton" anchors.leftMargin: 50 text: root.backend.startStopText enabled: root.backend.canStartStop onClicked: root.backend.startStop() + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: statusTextElement.bottom + anchors.topMargin: 10 + } + + TextEdit { + id: cidTextEdit + objectName: "cid" + text: root.backend.cidText + color: "white" + font.pointSize: 14 + readOnly: true + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: startStopButton.bottom + anchors.topMargin: 10 + } + + Button { + id: openFile + text: "Open file" + onClicked: fileDialog.open() + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: cidTextEdit.bottom + anchors.topMargin: 15 + enabled: root.backend.isRunning + } + + TextField { + id: peerIdField + placeholderText: "Enter the peer Id" + placeholderTextColor: "#999999" + color: "#000000" + selectByMouse: true + text: root.peerId + onTextChanged: root.peerId = text + anchors.top: openFile.bottom + anchors.topMargin: 50 + anchors.horizontalCenter: parent.horizontalCenter + } + + Button { + id: peerConnectButton + objectName: "peerConnectButton" + text: "Peer connect" + onClicked: root.backend.tryPeerConnect() + anchors.top: peerIdField.bottom + anchors.horizontalCenter: parent.horizontalCenter + enabled: root.backend.isRunning + anchors.topMargin: 10 + } + + Button { + id: debugButton + objectName: "debugButton" + text: "Debug" + onClicked: root.backend.tryDebug() + anchors.top: peerConnectButton.bottom + anchors.horizontalCenter: parent.horizontalCenter + enabled: root.backend.isRunning + anchors.topMargin: 50 + } + + Button { + id: peerIdButton + objectName: "peerIdButton" + text: "Peer Id" + onClicked: root.backend.showPeerId() + anchors.top: peerConnectButton.bottom + anchors.right: debugButton.left + enabled: root.backend.isRunning + anchors.topMargin: 50 + } + + Button { + id: dataDirButton + objectName: "dataDirButton" + text: "Data dir" + onClicked: root.backend.dataDir() + anchors.top: peerConnectButton.bottom + anchors.right: peerIdButton.left + enabled: root.backend.isRunning + anchors.topMargin: 50 + } + + Button { + id: sprButton + objectName: "sprButton" + text: "SPR" + onClicked: root.backend.spr() + anchors.top: peerConnectButton.bottom + anchors.left: debugButton.right + enabled: root.backend.isRunning + anchors.topMargin: 50 + } + + Button { + id: versionButton + objectName: "versionButton" + text: "Version" + onClicked: root.backend.version() + anchors.top: peerConnectButton.bottom + anchors.left: sprButton.right + enabled: root.backend.isRunning + anchors.topMargin: 50 + } + + TextField { + id: cidDownloadField + placeholderTextColor: "#999999" + placeholderText: "Enter the cid to download" + color: "black" + // text: root.downloadCid + onTextChanged: root.downloadCid = text + anchors.top: debugButton.bottom + anchors.topMargin: 50 + anchors.horizontalCenter: parent.horizontalCenter + } + + Button { + id: openFile2 + text: "Open file" + onClicked: fileDialog2.open() + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: cidDownloadField.bottom + anchors.topMargin: 15 + enabled: root.backend.isRunning + } + + Button { + id: cidDownloadButton + objectName: "cidDownloadButton" + text: "Download" + onClicked: root.backend.tryDownloadFile(root.downloadCid, + root.downloadDestination) + anchors.top: openFile2.bottom + anchors.horizontalCenter: parent.horizontalCenter + enabled: root.backend.isRunning + anchors.topMargin: 10 + } + + Button { + id: existsButton + objectName: "existsButton" + text: "Exists" + onClicked: root.backend.exists(root.downloadCid) + anchors.top: openFile2.bottom + anchors.left: cidDownloadButton.right + enabled: root.backend.isRunning + anchors.topMargin: 10 + } + + Button { + id: fetchButton + objectName: "fetchButton" + text: "Fetch" + onClicked: root.backend.fetch(root.downloadCid) + anchors.top: openFile2.bottom + anchors.left: existsButton.right + enabled: root.backend.isRunning + anchors.topMargin: 10 + } + + Button { + id: removeButton + objectName: "removeButton" + text: "Remove" + onClicked: root.backend.remove(root.downloadCid) + anchors.top: openFile2.bottom + anchors.right: cidDownloadButton.left + enabled: root.backend.isRunning + anchors.topMargin: 10 + } + + Button { + id: downloadManifestButton + objectName: "downloadManifestButton" + text: "Download manifest" + onClicked: root.backend.downloadManifest(root.downloadCid) + anchors.top: openFile2.bottom + anchors.right: removeButton.left + enabled: root.backend.isRunning + anchors.topMargin: 10 + } + + Button { + id: downloadManifestsButton + objectName: "downloadManifestsButton" + text: "Manifests" + onClicked: root.backend.downloadManifests() + anchors.top: cidDownloadButton.bottom + anchors.horizontalCenter: parent.horizontalCenter + enabled: root.backend.isRunning + anchors.topMargin: 10 + } + + Button { + id: spaceButton + objectName: "spaceButton" + text: "Space" + onClicked: root.backend.space() + anchors.top: cidDownloadButton.bottom + anchors.right: downloadManifestsButton.left + enabled: root.backend.isRunning + anchors.topMargin: 10 + } + + TextField { + id: logLevelField + placeholderTextColor: "#999999" + placeholderText: "Enter the log level to download" + color: "black" + // text: root.downloadCid + onTextChanged: root.logLevel = text + anchors.top: downloadManifestsButton.bottom + anchors.topMargin: 50 + anchors.horizontalCenter: parent.horizontalCenter + } + + Button { + id: logLevelButton + objectName: "logLevelButton" + text: "Log level" + onClicked: root.backend.updateLogLevel(root.logLevel) + anchors.top: logLevelField.bottom + anchors.horizontalCenter: parent.horizontalCenter + enabled: root.backend.isRunning + anchors.topMargin: 10 + } + + // TextEdit { + // id: selectableText + // anchors.fill: parent + // anchors.margins: 10 + // text: "This text is selectable. You can copy it, but not edit it." + // readOnly: true // Makes the text non-editable + // selectByMouse: true // Enables selection by mouse drag (often the default for desktop) + // // Optional: Change cursor shape to IBeam when hovering + // MouseArea { + // anchors.fill: parent + // cursorShape: Qt.IBeamCursor + // acceptedButtons: Qt.NoButton // Allows TextEdit to handle mouse events + // } + // } + + // Button { + // anchors.left: parent.left + // anchors.bottom: parent.bottom + // objectName: "uploadButton" + // text: "Upload" + // anchors.bottomMargin: 80 + // onClicked: root.backend.tryUpload() + // } + + // Button { + // anchors.left: parent.left + // anchors.bottom: parent.bottom + // objectName: "finalizeButton" + // text: "Finalize" + // onClicked: root.backend.tryUploadFinalize() + // } + // Button { + // anchors.left: parent.left + // anchors.bottom: parent.bottom + // objectName: "uploadFileButton" + // text: "Upload file" + // onClicked: root.backend.tryUploadFile() + // anchors.bottomMargin: 30 + // } + FileDialog { + id: fileDialog + onAccepted: root.backend.tryUploadFile(fileDialog.selectedFile) + } + + FileDialog { + id: fileDialog2 + fileMode: FileDialog.SaveFile + onAccepted: { + root.downloadDestination = fileDialog2.selectedFile + console.log("Destination selected:", + root.backend.downloadDestination) + } + } + + Rectangle { + id: debugPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + height: 150 + color: "#111111" + visible: root.backend.showDebug // or: visible: showDebug + + Flickable { + id: flick + anchors.fill: parent + clip: true + + contentWidth: width + contentHeight: debugText.paintedHeight + + TextEdit { + id: debugText + width: flick.width + text: root.backend.debugLogs + color: "#dddddd" + font.family: "monospace" + font.pixelSize: 12 + wrapMode: Text.WrapAnywhere + readOnly: true + + // ✅ auto-scroll to bottom on update + onTextChanged: Qt.callLater(function () { + flick.contentY = Math.max( + 0, flick.contentHeight - flick.height) + }) + } + } + + Shortcut { + sequence: "Ctrl+D" + onActivated: root.backend.showDebug = !root.backend.showDebug + // if using local var: onActivated: showDebug = !showDebug + } } } diff --git a/vendor/logos-cpp-sdk b/vendor/logos-cpp-sdk index 32f1d70..b7a5564 160000 --- a/vendor/logos-cpp-sdk +++ b/vendor/logos-cpp-sdk @@ -1 +1 @@ -Subproject commit 32f1d7080d784ff044d91d076ef2f0c7305d4784 +Subproject commit b7a556483a5ac3fa78533105a42c05577a034fb7 diff --git a/vendor/logos-liblogos b/vendor/logos-liblogos index fb7a9d6..1378757 160000 --- a/vendor/logos-liblogos +++ b/vendor/logos-liblogos @@ -1 +1 @@ -Subproject commit fb7a9d6888dc59dd29437e8d3a2d38fc9f0e8696 +Subproject commit 1378757dc8745941ebee79ae484abe62be2f5db4 diff --git a/vendor/logos-storage-module b/vendor/logos-storage-module index e01d9db..c68f855 160000 --- a/vendor/logos-storage-module +++ b/vendor/logos-storage-module @@ -1 +1 @@ -Subproject commit e01d9dbc6159bf6442a670e9432714b024b7698b +Subproject commit c68f855f882002431041de291e2ba7f2f19fa05a From 02c20ae8e5a4b64f5dc1e7590b1d5681062a86da Mon Sep 17 00:00:00 2001 From: Arnaud Date: Fri, 13 Feb 2026 20:15:58 +0400 Subject: [PATCH 2/6] Update dependencies --- flake.lock | 27 +++++++++++++-------------- flake.nix | 3 ++- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index e836e77..d9d524f 100644 --- a/flake.lock +++ b/flake.lock @@ -75,11 +75,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1770703782, - "narHash": "sha256-KloAfjqljpy9Ye/z/WcbwsqkBMph4X6rpWObas1VYH8=", + "lastModified": 1770978598, + "narHash": "sha256-CR5N5v+y2ZInnBocGgjIeLaS9XqNjAKGXE2abC3E110=", "owner": "logos-co", "repo": "logos-cpp-sdk", - "rev": "5a8a6c723f2c50587760f763753c4fa7c11d46bf", + "rev": "c3477d29e32cae5f73ca637fb81e547f8a6cba58", "type": "github" }, "original": { @@ -224,11 +224,11 @@ ] }, "locked": { - "lastModified": 1770154824, - "narHash": "sha256-WGI+3FkPdeytfLJ3ZJYr1O8esUnQjcmMJEYwB/EBZMs=", + "lastModified": 1770837874, + "narHash": "sha256-wr75lv1q4U1FS5+l/6ypwzJFJe06l2RyUvx1npoRS88=", "owner": "logos-co", "repo": "logos-liblogos", - "rev": "901dd86d47216b15b6f1260b7b6bb4ecd88a8f9d", + "rev": "e3741c01fd3abf6b7bd9ff2fa8edf89c41fc0cea", "type": "github" }, "original": { @@ -293,17 +293,16 @@ "nixpkgs": "nixpkgs_7" }, "locked": { - "lastModified": 1770408620, - "narHash": "sha256-pMbOn5VoDCnCM3O7XyigYK9A7dhUvoXCWzXlD7ZskMM=", + "lastModified": 1770798353, + "narHash": "sha256-S7S3stBLrReeHlMqZkVO4h8sG0qWQIbcO+TNH90LCeY=", "ref": "refs/heads/master", - "rev": "a5ce5e1fb61329884769fc100fb731a913b97dac", - "revCount": 893, + "rev": "d02f44ffd64216cc9dd1e8cdc047b583eb074a21", + "revCount": 896, "submodules": true, "type": "git", "url": "https://github.com/logos-storage/logos-storage-nim" }, "original": { - "rev": "a5ce5e1fb61329884769fc100fb731a913b97dac", "submodules": true, "type": "git", "url": "https://github.com/logos-storage/logos-storage-nim" @@ -323,11 +322,11 @@ ] }, "locked": { - "lastModified": 1770715398, - "narHash": "sha256-xs/j/5g5tPnKj5uAGJzmUTyzbJkGg3Z4xPDBsw9nF7c=", + "lastModified": 1770999310, + "narHash": "sha256-0pD6Buni4A2lDyo31xKlGUWnM8Ebs4WRcThF8pKT5Qc=", "owner": "logos-co", "repo": "logos-storage-module", - "rev": "93c832f981e9e319ea3062e30107b037b965c7ab", + "rev": "1943e8cfbee46b800bc8b5f08efb4b4376b286a8", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 7e0e1b0..89a364a 100644 --- a/flake.nix +++ b/flake.nix @@ -4,10 +4,11 @@ inputs = { # Follow the same nixpkgs as logos-liblogos to ensure compatibility nixpkgs.follows = "logos-liblogos/nixpkgs"; + # logos-cpp-sdk.url = "/home/arnaud/Work/logos/logos-cpp-sdk"; logos-cpp-sdk.url = "github:logos-co/logos-cpp-sdk?ref=feat/logos-result"; logos-liblogos.url = "github:logos-co/logos-liblogos?ref=fix/logos-cleanup-on-terminate"; logos-storage-module.url = "github:logos-co/logos-storage-module"; - # logos-storage-module.url = "path:/home/arnaud/Work/logos/logos-storage-module"; + #logos-storage-module.url = "path:/home/arnaud/Work/logos/logos-storage-module"; logos-capability-module.url = "github:logos-co/logos-capability-module"; logos-liblogos.inputs.logos-cpp-sdk.follows = "logos-cpp-sdk"; From 5409e13ea38e24e23b7f628d168580522a2f24bd Mon Sep 17 00:00:00 2001 From: Arnaud Date: Fri, 13 Feb 2026 20:16:27 +0400 Subject: [PATCH 3/6] Did a bunch of refactoring --- src/StorageBackend.cpp | 300 ++++++++++++++++++++++------------------ src/StorageBackend.h | 53 +++---- src/StorageUIPlugin.cpp | 33 ++++- src/qml/StorageView.qml | 245 ++++++++++++++++++++++---------- 4 files changed, 390 insertions(+), 241 deletions(-) diff --git a/src/StorageBackend.cpp b/src/StorageBackend.cpp index 690e62c..3a82bb9 100644 --- a/src/StorageBackend.cpp +++ b/src/StorageBackend.cpp @@ -27,9 +27,6 @@ StorageBackend::StorageBackend(LogosAPI* logosAPI, QObject* parent) } m_logos = new LogosModules(m_logosAPI); - m_showDebug = false; - - initStorage(); } StorageBackend::~StorageBackend() @@ -38,44 +35,31 @@ StorageBackend::~StorageBackend() m_logos = nullptr; } -void StorageBackend::initStorage() { +LogosResult StorageBackend::init(const QString& configJson = "{}") { qDebug() << "StorageBackend::initStorage called"; - QString jsonConfig = "{}"; - - QFileInfo info("config.json"); - if (info.exists() && info.isFile()) { - debug("config.json is found, let's try to load it..."); - - QFile file("config.json"); - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - jsonConfig = QString::fromUtf8(file.readAll()); - - debug("config.json content is: " + jsonConfig); - } else { - debug("Failed to load config.json"); - } - } - - LogosResult result = m_logos->storage_module.init(jsonConfig); + LogosResult result = m_logos->storage_module.init(m_configJson); qDebug() << "StorageBackend::initStorage: init result =" << result.success; if (!result.success) { - setStatus(Destroyed, result.getValue()); - return; + setStatus(Destroyed); + debug(result.getError()); + return result; } - setStatus(Stopped, "Storage module ready."); + setStatus(Stopped); if (!m_logos->storage_module.on("storageStart", [this](const QVariantList& data) { bool success = data[0].toBool(); if (!success) { QString message = data[1].toString(); - setStatus(Stopped, "Failed to start Storage module:" + message); + setStatus(Stopped); + debug("Failed to start Storage module:" + message); } else { - setStatus(Running, "Storage module started."); + setStatus(Running); + debug("Storage module started."); } })) { qWarning() << "StorageWidget: failed to subscribe to storageStart events"; @@ -86,9 +70,11 @@ void StorageBackend::initStorage() { if (!success) { QString message = data[1].toString(); - setStatus(Running, "Failed to stop Storage module:" + message); + setStatus(Running); + debug("Failed to stop Storage module:" + message); } else { - setStatus(Stopped, "Storage module stopped."); + setStatus(Stopped); + debug("Storage module stopped."); emit stopped(); } })) { @@ -171,53 +157,75 @@ void StorageBackend::initStorage() { qWarning() << "StorageWidget: failed to subscribe to storageDownloadProgress events"; } - startStop(); + m_configJson = configJson; + emit configJsonChanged(); + + debug("config.json content is: " + m_configJson); + + return result; } -void StorageBackend::setStatus(StorageStatus newStatus, const QString& statusText) { - if (m_status != newStatus || m_statusText != statusText) { +void StorageBackend::setStatus(StorageStatus newStatus) { + if (m_status != newStatus) { m_status = newStatus; - m_statusText = statusText; emit statusChanged(); - - debug(statusText); } } -void StorageBackend::startStop() { - qDebug() << "StorageBackend: startStop method called"; +LogosResult StorageBackend::start(const QString& newConfigJson) { + qDebug() << "StorageBackend: start method called"; - // QString s = "hello"; - // emit test(0, s); - if (m_status == Destroyed || m_status == Starting || m_status == Stopping) { - // TODO display the m_status properly - debug("StorageBackend: Cannot start/stop Storage in current state:" + m_status); - return; + if (newConfigJson != "") { + reloadIfChanged(newConfigJson); } - if (m_status != Running) { - setStatus(Starting, "Starting Storage module..."); - - auto result = m_logos->storage_module.start(); - - if (!result.success) { - setStatus(Stopped, result.getValue()); - return; - } - - qDebug() << "StorageBackend: start command sent, waiting for events."; - } else { - stop(); + if (m_status != Stopped) { + debug("The Storage Module is not initialised properly."); + return {false, "The Storage Module is not initialised properly."}; } + + if (m_status == Running) { + debug("The Storage Module is already started."); + return {false, "The Storage Module is already started."}; + } + + setStatus(Starting); + debug("Starting Storage module..."); + + auto result = m_logos->storage_module.start(); + + if (!result.success) { + setStatus(Stopped); + debug(result.getError()); + return result; + } + + qDebug() << "StorageBackend: start command sent, waiting for events."; + + return result; } void StorageBackend::stop() { - setStatus(Stopping, "Stopping Storage module..."); + qDebug() << "StorageBackend: stop method called"; + + if (m_status == StorageStatus::Stopping) { + debug("The Storage Module is already stopping."); + return; + } + + if (m_status != StorageStatus::Running) { + debug("The Storage Module is not started."); + return; + } + + setStatus(Stopping); + debug("Stopping Storage module..."); auto result = m_logos->storage_module.stop(); if (!result.success) { - setStatus(Running, result.getValue()); + setStatus(Running); + debug(result.getError()); return; } @@ -231,38 +239,13 @@ void StorageBackend::destroy() { auto result = m_logos->storage_module.destroy(); if (!result.success) { - setStatus(status, result.getValue()); + debug(result.getError()); return; } qDebug() << "StorageBackend: Storage module destroyed."; } -QString StorageBackend::statusText() const { return m_statusText; } - -QString StorageBackend::startStopText() const { - if (m_status != Running) { - return "Start"; - } else { - return "Stop"; - } -} - -bool StorageBackend::canStartStop() const { return m_status == Running || m_status == Stopped; } - -bool StorageBackend::isRunning() { return m_status == Running; } - -QString StorageBackend::peerId() const { return m_peerId; }; - -void StorageBackend::setPeerId(const QString& peerId) { m_peerId = peerId; } - -bool StorageBackend::showDebug() const { return m_showDebug; }; - -void StorageBackend::setShowDebug(const bool showDebug) { - m_showDebug = showDebug; - emit showDebugChanged(); -} - QString StorageBackend::debugLogs() const { return m_debugLogs; }; void StorageBackend::debug(const QString& log) { @@ -277,15 +260,13 @@ void StorageBackend::debug(const QString& log) { qDebug() << "StorageBackend: " << log; } -bool StorageBackend::isInitialised() const { return m_status != Destroyed; } - void StorageBackend::tryDebug() { auto result = m_logos->storage_module.debug(); - debug("Debug " + result.getValue()); + debug("Debug " + result.getString()); } -void StorageBackend::tryPeerConnect() { - qDebug().noquote() << "StorageBackend: tryPeerConnect called with peerId=" << m_peerId; +void StorageBackend::tryPeerConnect(const QString& peerId) { + qDebug().noquote() << "StorageBackend: tryPeerConnect called with peerId=" << peerId; // LogosResult result2 = m_logos->storage_module.space(); // QVariantMap space = result2.getValue(); @@ -301,7 +282,7 @@ void StorageBackend::tryPeerConnect() { // debug("quotaReservedBytes " + QString::number(quotaReservedBytes)); // LogosResult result = m_logos->storage_module.dataDir(); - // QString myDataDir = result.getValue(); + // QString myDataDir = result.getString(); // qDebug() << "StorageBackend: tryPeerConnect dataDir=" << myDataDir; // QString peerId = m_logos->storage_module.peerId(); @@ -310,12 +291,12 @@ void StorageBackend::tryPeerConnect() { // qDebug() << "StorageBackend: Peer ID is empty."; // return; // } - auto result = m_logos->storage_module.connect(m_peerId, QStringList()); + auto result = m_logos->storage_module.connect(peerId, QStringList()); qDebug() << "StorageBackend: peerConnect result =" << result.value; // auto result = m_logos->storage_module.debug(); - // debug("Debug " + result.getValue()); + // debug("Debug " + result.getString()); // QString filename = "test.txt"; // QString sessionId = m_logos->storage_module.uploadInit(filename); @@ -358,8 +339,7 @@ void StorageBackend::tryUploadFile(const QUrl& url) { if (!url.isLocalFile()) { qWarning() << "Not a local file"; - m_statusText = "The provided URL is not a local file."; - emit statusChanged(); + debug("The provided URL is not a local file."); return; } @@ -379,7 +359,7 @@ void StorageBackend::tryUploadFile(const QUrl& url) { // this, // [this, result]() { // if (!result.success) { - // setStatus(m_status, result.getValue()); + // setStatus(m_status, result.getString()); // return; // } @@ -393,7 +373,7 @@ void StorageBackend::tryUploadFile(const QUrl& url) { LogosResult result = m_logos->storage_module.uploadUrl(url); if (!result.success) { - setStatus(m_status, result.getValue()); + debug(result.getError()); return; } @@ -433,12 +413,12 @@ void StorageBackend::tryUploadFile(const QUrl& url) { // LogosResult result = m_logos->storage_module.uploadInit("test.txt", chunkSize); // if (!result.success) { -// debug(result.getValue()); +// debug(result.getString()); // file.close(); // return; // } -// QString sessionId = result.getValue(); +// QString sessionId = result.getString(); // while (!file.atEnd()) { // QByteArray chunk = file.read(chunkSize); @@ -470,7 +450,7 @@ void StorageBackend::tryUploadFile(const QUrl& url) { // return; // } -// qDebug() << "Upload complete, CID:" << result.getValue(); +// qDebug() << "Upload complete, CID:" << result.getString(); // file.close(); // } @@ -480,8 +460,7 @@ void StorageBackend::tryDownloadFile(const QString& cid, const QUrl& url) { if (!url.isLocalFile()) { qWarning() << "Not a local file"; - m_statusText = "The provided URL is not a local file."; - emit statusChanged(); + debug("The provided URL is not a local file."); return; } @@ -495,7 +474,7 @@ void StorageBackend::tryDownloadFile(const QString& cid, const QUrl& url) { LogosResult result = m_logos->storage_module.downloadToUrl(cid, url, false); if (!result.success) { - setStatus(m_status, result.getValue()); + debug(result.getError()); return; } @@ -510,7 +489,7 @@ void StorageBackend::exists(const QString& cid) { LogosResult result = m_logos->storage_module.exists(cid); if (!result.success) { - debug("StorageBackend::exists failed with error=" + result.getValue()); + debug("StorageBackend::exists failed with error=" + result.getError()); return; } @@ -523,7 +502,7 @@ void StorageBackend::remove(const QString& cid) { LogosResult result = m_logos->storage_module.remove(cid); if (!result.success) { - debug("StorageBackend::remove failed with error=" + result.getValue()); + debug("StorageBackend::remove failed with error=" + result.getError()); return; } @@ -536,7 +515,7 @@ void StorageBackend::fetch(const QString& cid) { LogosResult result = m_logos->storage_module.fetch(cid); if (!result.success) { - debug("StorageBackend::fetch failed with error=" + result.getValue()); + debug("StorageBackend::fetch failed with error=" + result.getError()); return; } @@ -549,11 +528,11 @@ void StorageBackend::version() { LogosResult result = m_logos->storage_module.version(); if (!result.success) { - debug("StorageBackend::version failed with error=" + result.getValue()); + debug("StorageBackend::version failed with error=" + result.getError()); return; } - debug("Version: " + result.getValue()); + debug("Version: " + result.getString()); } void StorageBackend::showPeerId() { @@ -562,11 +541,11 @@ void StorageBackend::showPeerId() { LogosResult result = m_logos->storage_module.peerId(); if (!result.success) { - debug("StorageBackend::peerId failed with error=" + result.getValue()); + debug("StorageBackend::peerId failed with error=" + result.getError()); return; } - debug("Peer ID: " + result.getValue()); + debug("Peer ID: " + result.getString()); } void StorageBackend::spr() { @@ -575,11 +554,11 @@ void StorageBackend::spr() { LogosResult result = m_logos->storage_module.spr(); if (!result.success) { - debug("StorageBackend::spr failed with error=" + result.getValue()); + debug("StorageBackend::spr failed with error=" + result.getError()); return; } - debug("SPR: " + result.getValue()); + debug("SPR: " + result.getString()); } void StorageBackend::dataDir() { @@ -588,11 +567,11 @@ void StorageBackend::dataDir() { LogosResult result = m_logos->storage_module.dataDir(); if (!result.success) { - debug("StorageBackend::dataDir failed with error=" + result.getValue()); + debug("StorageBackend::dataDir failed with error=" + result.getError()); return; } - debug("Data dir: " + result.getValue()); + debug("Data dir: " + result.getString()); } void StorageBackend::downloadManifest(const QString& cid) { @@ -601,28 +580,28 @@ void StorageBackend::downloadManifest(const QString& cid) { LogosResult result = m_logos->storage_module.downloadManifest(cid); if (!result.success) { - debug("StorageBackend::downloadManifest failed with error=" + result.getValue()); + debug("StorageBackend::downloadManifest failed with error=" + result.getError()); return; } - debug("Manifest tree cid: " + result.getValue("treeCid")); - debug(QString("Manifest datasetSize %1").arg(result.getValue("datasetSize"))); - debug(QString("Manifest blockSize %1").arg(result.getValue("blockSize"))); - debug("Manifest filename: " + result.getValue("filename")); - debug("Manifest mimetype: " + result.getValue("mimetype")); + debug("Manifest tree cid: " + result.getString("treeCid")); + debug(QString("Manifest datasetSize %1").arg(result.getInt("datasetSize"))); + debug(QString("Manifest blockSize %1").arg(result.getInt("blockSize"))); + debug("Manifest filename: " + result.getString("filename")); + debug("Manifest mimetype: " + result.getString("mimetype")); } void StorageBackend::downloadManifests() { qDebug() << "StorageBackend::downloadManifests called"; LogosResult result = m_logos->storage_module.manifests(); - + QString error = result.getError(); if (!result.success) { - debug("StorageBackend::downloadManifests failed with error=" + result.getValue()); + debug("StorageBackend::downloadManifests failed with error=" + result.getError()); return; } - QVariantList manifestsList = result.getValue(); + QVariantList manifestsList = result.getList(); int count = manifestsList.size(); debug(QString("Found %1 manifests").arg(count)); @@ -648,14 +627,14 @@ void StorageBackend::space() { LogosResult result = m_logos->storage_module.space(); if (!result.success) { - debug("StorageBackend::space failed with error=" + result.getValue()); + debug("StorageBackend::space failed with error=" + result.getError()); return; } - debug(QString("Space datasetSize %1").arg(result.getValue("totalBlocks"))); - debug(QString("Space quotaMaxBytes %1").arg(result.getValue("quotaMaxBytes"))); - debug(QString("Space quotaUsedBytes %1").arg(result.getValue("quotaUsedBytes"))); - debug(QString("Space quotaReservedBytes %1").arg(result.getValue("quotaReservedBytes"))); + debug(QString("Space datasetSize %1").arg(result.getInt("totalBlocks"))); + debug(QString("Space quotaMaxBytes %1").arg(result.getInt("quotaMaxBytes"))); + debug(QString("Space quotaUsedBytes %1").arg(result.getInt("quotaUsedBytes"))); + debug(QString("Space quotaReservedBytes %1").arg(result.getInt("quotaReservedBytes"))); } void StorageBackend::updateLogLevel(const QString& logLevel) { @@ -664,17 +643,74 @@ void StorageBackend::updateLogLevel(const QString& logLevel) { LogosResult result = m_logos->storage_module.updateLogLevel(logLevel); if (!result.success) { - debug("StorageBackend::updateLogLevel failed with error=" + result.getValue()); + debug("StorageBackend::updateLogLevel failed with error=" + result.getError()); return; } debug("Log level updated to " + logLevel); } -QString StorageBackend::cidText() const { - if (m_cid.isEmpty()) { - return "No CID available."; - } else { - return m_cid; +StorageBackend::StorageStatus StorageBackend::status() const { return m_status; } + +QString StorageBackend::cid() const { return m_cid; } + +QString StorageBackend::configJson() const { return m_configJson; } + +void StorageBackend::reloadIfChanged(const QString& configJson) { + if (configJson == m_configJson) { + return; } + + debug("New config detected"); + + QJsonDocument doc = QJsonDocument::fromJson(configJson.toUtf8()); + if (doc.isNull()) { + debug("Invalid json detected !"); + + m_configJson = configJson; + emit configJsonChanged(); + + return; + } + + if (m_status == StorageStatus::Running || m_status == StorageStatus::Stopping || + m_status == StorageStatus::Starting) { + debug("Cannot reload the config while running, stopping or starting..."); + return; + } + + if (m_status == StorageStatus::Stopped) { + LogosResult result = m_logos->storage_module.destroy(); + + if (!result.success) { + debug("Failed to destroy the context error=" + result.getError()); + return; + } else { + setStatus(StorageStatus::Destroyed); + } + } + + LogosResult result = m_logos->storage_module.init(configJson); + + if (!result.success) { + debug("Failed to init context with new config, will rollback, error=" + result.getError()); + + LogosResult result = m_logos->storage_module.init(m_configJson); + + if (!result.success) { + debug("Failed to init context with old config, that's a serious issue, error=" + result.getError()); + } else { + debug("Old config restored"); + setStatus(StorageStatus::Stopped); + + m_configJson = configJson; + emit configJsonChanged(); + } + return; + } + + debug("New config loaded successfully"); + + m_configJson = configJson; + setStatus(StorageStatus::Stopped); } diff --git a/src/StorageBackend.h b/src/StorageBackend.h index cb8370a..8838a7f 100644 --- a/src/StorageBackend.h +++ b/src/StorageBackend.h @@ -13,41 +13,28 @@ static const int RET_PROGRESS = 3; class StorageBackend : public QObject { Q_OBJECT QML_ELEMENT - Q_PROPERTY(bool canStartStop READ canStartStop NOTIFY statusChanged) - Q_PROPERTY(bool isRunning READ isRunning NOTIFY statusChanged) - Q_PROPERTY(bool showDebug READ showDebug WRITE setShowDebug NOTIFY showDebugChanged) - Q_PROPERTY(QString startStopText READ startStopText NOTIFY statusChanged) - Q_PROPERTY(QString statusText READ statusText NOTIFY statusChanged) - Q_PROPERTY(QString cidText READ cidText NOTIFY cidChanged) - Q_PROPERTY(QString peerId READ peerId WRITE setPeerId NOTIFY peerIdChanged) Q_PROPERTY(QString debugLogs READ debugLogs NOTIFY debugLogsChanged) + Q_PROPERTY(StorageStatus status READ status NOTIFY statusChanged) + Q_PROPERTY(QString cid READ cid NOTIFY cidChanged) + Q_PROPERTY(QString configJson READ configJson NOTIFY configJsonChanged) public: enum StorageStatus { Stopped = 0, Starting, Running, Stopping, Destroyed }; Q_ENUM(StorageStatus) - QString startStopText() const; - QString statusText() const; - QString cidText() const; - QString peerId() const; + QString cid() const; QString debugLogs() const; - - bool showDebug() const; - bool canStartStop() const; - bool isRunning() const; - - void setPeerId(const QString& peerId); - void setShowDebug(const bool showDebug); + StorageStatus status() const; + QString configJson() const; explicit StorageBackend(LogosAPI* logosAPI = nullptr, QObject* parent = nullptr); ~StorageBackend(); public slots: - void startStop(); + LogosResult start(const QString& configJson = ""); void destroy(); - bool isRunning(); void stop(); - void tryPeerConnect(); + void tryPeerConnect(const QString& peerId); void tryDebug(); void tryUpload(); void tryUploadFinalize(); @@ -63,36 +50,28 @@ class StorageBackend : public QObject { void downloadManifest(const QString& cid); void downloadManifests(); void space(); + LogosResult init(const QString& configJson); void updateLogLevel(const QString& logLevel); - bool isInitialised() const; - signals: void statusChanged(); - void peerIdChanged(); - void showDebugChanged(); void debugLogsChanged(); - void cidChanged(); void stopped(); - void test(int code, const QString& msg); + void cidChanged(); + void configJsonChanged(); private slots: private: - void setStatus(StorageStatus newStatus, const QString& statusText); + void setStatus(StorageStatus newStatus); void peerConnect(const QString& peerId); void debug(const QString& log); - void initStorage(); + void reloadIfChanged(const QString& configJson); - StorageStatus m_status; LogosAPI* m_logosAPI; LogosModules* m_logos; - - QString m_statusText; - QString m_cid; - QString m_sessionId; - QString m_peerId; + StorageStatus m_status; QString m_debugLogs; - - bool m_showDebug; + QString m_cid; + QString m_configJson; }; diff --git a/src/StorageUIPlugin.cpp b/src/StorageUIPlugin.cpp index c8badd4..6ab6e03 100644 --- a/src/StorageUIPlugin.cpp +++ b/src/StorageUIPlugin.cpp @@ -31,6 +31,35 @@ QWidget* StorageUIPlugin::createWidget(LogosAPI* logosAPI) { root->setProperty("backend", QVariant::fromValue(static_cast(backend))); + QFileInfo info("config.json"); + QString configJson = "{}"; + + if (info.exists() && info.isFile()) { + qDebug() << "StorageUIPlugin: config.json is found, let's try to load it..."; + + QFile file("config.json"); + if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) { + configJson = QString::fromUtf8(file.readAll()); + + qDebug() << "StorageUIPlugin: config.json is found, let's try to load it... configJson=" << configJson; + } else { + qDebug() << "StorageUIPlugin: Failed to load config.json"; + } + } + + LogosResult result = backend->init(configJson); + + if (!result.success) { + QString error = result.getError(); + qWarning() << "StorageUIPlugin: Failed to init backend, will use mock version:" << error; + } else { + result = backend->start(); + + if (!result.success) { + qWarning() << "StorageUIPlugin: Failed to init backend, will use mock version:" << result.getError(); + } + } + return quickWidget; } @@ -66,13 +95,13 @@ void StorageUIPlugin::destroyWidget(QWidget* widget) { return; } - if (!backend->isInitialised()) { + if (backend->status() != StorageBackend::StorageStatus::Destroyed) { qDebug() << "StorageUIPlugin::destroyWidget: backend is not initialised so let's detroy it."; quickWidget->deleteLater(); return; } - if (!backend->isRunning()) { + if (backend->status() == StorageBackend::StorageStatus::Running) { qDebug() << "StorageUIPlugin::destroyWidget: backend is not running so let's detroy it."; backend->destroy(); diff --git a/src/qml/StorageView.qml b/src/qml/StorageView.qml index 5ceefd4..e5846a7 100644 --- a/src/qml/StorageView.qml +++ b/src/qml/StorageView.qml @@ -1,9 +1,14 @@ import QtQuick import QtQuick.Controls import QtQuick.Dialogs +import QtQuick.Layouts -//import QtQuick.Layouts Rectangle { + id: root + width: 400 + height: 700 + color: "#000000" + property var backend: mockBackend readonly property int stopped: 0 readonly property int starting: 1 @@ -14,38 +19,56 @@ Rectangle { property string downloadDestination: "" property url downloadCid: "" property string logLevel: "" + property bool showDebug: false + property url uploadCid: root.backend.cid + property url configJson: root.backend.configJson - id: root - width: 400 - height: 700 - color: "#000000" + function getStatusLabel() { + switch (backend.status) { + case stopped: + return "Logos Storage stopped." + case starting: + return "Logos Storage is starting..." + case running: + return "Logos Storage started." + case stopping: + return "Logos Storage is stopping..." + case destroyed: + return "Logos Storage is not initialised." + } + } + + function startStopText() { + if (backend.status == running) { + return "Stop" + } + return "Start" + } + + function canStartStop() { + return backend.status == running || backend.status == stopped + } + + function isRunning() { + return backend.status == running + } QtObject { id: mockBackend - signal test(int code, string msg) - property var status: root.stopped - property var statusText: "Destroyed" - property var startStopText: "Start" - property var canStartStop: true - property bool showDebug: false - property var debugLogs: "" + property var debugLogs: "Hello !" + property var configJson: "{}" - function startStop() { - console.log("Start") - if (status === root.running) { - status = root.stopped - statusText = "Stopped" - startStopText = "Start" - } else { - status = root.running - statusText = "Started" - startStopText = "Stop" - } + function start(newConfigJson) { + status = root.running } - function tryPeerConnect() { + function stop() { + status = root.stopped + } + + function tryPeerConnect(peerId) { console.log("Attempting peer connection...") } @@ -101,7 +124,7 @@ Rectangle { Text { id: statusTextElement objectName: "status" - text: root.backend.statusText + text: root.getStatusLabel() color: "white" font.pointSize: 20 anchors.top: parent.top @@ -113,9 +136,10 @@ Rectangle { id: startStopButton objectName: "startStopButton" anchors.leftMargin: 50 - text: root.backend.startStopText - enabled: root.backend.canStartStop - onClicked: root.backend.startStop() + text: root.startStopText() + enabled: root.canStartStop() + onClicked: root.backend.status == root.stopped ? root.backend.start( + jsonEditor.text) : root.backend.stop() anchors.horizontalCenter: parent.horizontalCenter anchors.top: statusTextElement.bottom anchors.topMargin: 10 @@ -124,13 +148,13 @@ Rectangle { TextEdit { id: cidTextEdit objectName: "cid" - text: root.backend.cidText color: "white" font.pointSize: 14 readOnly: true anchors.horizontalCenter: parent.horizontalCenter anchors.top: startStopButton.bottom anchors.topMargin: 10 + text: root.uploadCid } Button { @@ -140,7 +164,7 @@ Rectangle { anchors.horizontalCenter: parent.horizontalCenter anchors.top: cidTextEdit.bottom anchors.topMargin: 15 - enabled: root.backend.isRunning + enabled: root.isRunning } TextField { @@ -160,10 +184,10 @@ Rectangle { id: peerConnectButton objectName: "peerConnectButton" text: "Peer connect" - onClicked: root.backend.tryPeerConnect() + onClicked: root.backend.tryPeerConnect(root.peerId) anchors.top: peerIdField.bottom anchors.horizontalCenter: parent.horizontalCenter - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 10 } @@ -174,7 +198,7 @@ Rectangle { onClicked: root.backend.tryDebug() anchors.top: peerConnectButton.bottom anchors.horizontalCenter: parent.horizontalCenter - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 50 } @@ -185,7 +209,7 @@ Rectangle { onClicked: root.backend.showPeerId() anchors.top: peerConnectButton.bottom anchors.right: debugButton.left - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 50 } @@ -196,7 +220,7 @@ Rectangle { onClicked: root.backend.dataDir() anchors.top: peerConnectButton.bottom anchors.right: peerIdButton.left - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 50 } @@ -207,7 +231,7 @@ Rectangle { onClicked: root.backend.spr() anchors.top: peerConnectButton.bottom anchors.left: debugButton.right - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 50 } @@ -218,7 +242,7 @@ Rectangle { onClicked: root.backend.version() anchors.top: peerConnectButton.bottom anchors.left: sprButton.right - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 50 } @@ -241,7 +265,7 @@ Rectangle { anchors.horizontalCenter: parent.horizontalCenter anchors.top: cidDownloadField.bottom anchors.topMargin: 15 - enabled: root.backend.isRunning + enabled: root.isRunning } Button { @@ -252,7 +276,7 @@ Rectangle { root.downloadDestination) anchors.top: openFile2.bottom anchors.horizontalCenter: parent.horizontalCenter - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 10 } @@ -263,7 +287,7 @@ Rectangle { onClicked: root.backend.exists(root.downloadCid) anchors.top: openFile2.bottom anchors.left: cidDownloadButton.right - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 10 } @@ -274,7 +298,7 @@ Rectangle { onClicked: root.backend.fetch(root.downloadCid) anchors.top: openFile2.bottom anchors.left: existsButton.right - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 10 } @@ -285,7 +309,7 @@ Rectangle { onClicked: root.backend.remove(root.downloadCid) anchors.top: openFile2.bottom anchors.right: cidDownloadButton.left - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 10 } @@ -296,7 +320,7 @@ Rectangle { onClicked: root.backend.downloadManifest(root.downloadCid) anchors.top: openFile2.bottom anchors.right: removeButton.left - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 10 } @@ -307,7 +331,7 @@ Rectangle { onClicked: root.backend.downloadManifests() anchors.top: cidDownloadButton.bottom anchors.horizontalCenter: parent.horizontalCenter - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 10 } @@ -318,7 +342,7 @@ Rectangle { onClicked: root.backend.space() anchors.top: cidDownloadButton.bottom anchors.right: downloadManifestsButton.left - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 10 } @@ -341,7 +365,7 @@ Rectangle { onClicked: root.backend.updateLogLevel(root.logLevel) anchors.top: logLevelField.bottom anchors.horizontalCenter: parent.horizontalCenter - enabled: root.backend.isRunning + enabled: root.isRunning anchors.topMargin: 10 } @@ -406,38 +430,119 @@ Rectangle { anchors.bottom: parent.bottom height: 150 color: "#111111" - visible: root.backend.showDebug // or: visible: showDebug + visible: root.showDebug // or: visible: showDebug - Flickable { - id: flick - anchors.fill: parent - clip: true + TabBar { + id: bar + width: parent.width - contentWidth: width - contentHeight: debugText.paintedHeight + TabButton { + text: qsTr("Logs") + } - TextEdit { - id: debugText - width: flick.width - text: root.backend.debugLogs - color: "#dddddd" - font.family: "monospace" - font.pixelSize: 12 - wrapMode: Text.WrapAnywhere - readOnly: true - - // ✅ auto-scroll to bottom on update - onTextChanged: Qt.callLater(function () { - flick.contentY = Math.max( - 0, flick.contentHeight - flick.height) - }) + TabButton { + text: qsTr("Config") } } + StackLayout { + id: stackLayout + currentIndex: bar.currentIndex + anchors.top: bar.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + + Item { + id: homeTab + + Flickable { + id: flick + anchors.fill: parent + clip: true + + contentWidth: width + contentHeight: debugText.paintedHeight + + TextEdit { + id: debugText + width: flick.width + text: root.backend.debugLogs + color: "#dddddd" + font.family: "monospace" + font.pixelSize: 12 + wrapMode: Text.WrapAnywhere + readOnly: true + + onTextChanged: Qt.callLater(function () { + flick.contentY = Math.max( + 0, flick.contentHeight - flick.height) + }) + } + } + } + Rectangle { + id: discoverTab + + ScrollView { + anchors.fill: parent + + TextArea { + id: jsonEditor + font.family: "monospace" + font.pixelSize: 12 + color: "#d4d4d4" + width: parent.width + height: parent.height + + background: Rectangle { + color: "#1e1e1e" + border.color: jsonEditor.isValid ? "#3a3a3a" : "#ff0000" + border.width: 1 + } + + property bool isValid: true + + Connections { + target: root.backend + + function onConfigJsonChanged() { + jsonEditor.text = root.backend.configJson + try { + const jsonData = JSON.parse(jsonEditor.text) + jsonEditor.isValid = true + } catch (e) { + jsonEditor.isValid = false + } + } + } + + Component.onCompleted: { + text = root.backend.configJson + + try { + const jsonData = JSON.parse(text) + isValid = true + } catch (e) { + isValid = false + } + } + + onTextChanged: { + try { + const jsonData = JSON.parse(text) + isValid = true + } catch (e) { + isValid = false + } + } + } + } + } + } Shortcut { sequence: "Ctrl+D" - onActivated: root.backend.showDebug = !root.backend.showDebug - // if using local var: onActivated: showDebug = !showDebug + onActivated: root.showDebug = !root.showDebug } } } From 855a07ba46677a360b7549f7e3e0bb5ab4993caf Mon Sep 17 00:00:00 2001 From: Arnaud Date: Sun, 15 Feb 2026 20:14:44 +0400 Subject: [PATCH 4/6] Add progress --- src/StorageBackend.cpp | 80 +++++++++++++++++++++++++++++++----------- src/StorageBackend.h | 10 ++++++ 2 files changed, 70 insertions(+), 20 deletions(-) diff --git a/src/StorageBackend.cpp b/src/StorageBackend.cpp index 3a82bb9..2496fd4 100644 --- a/src/StorageBackend.cpp +++ b/src/StorageBackend.cpp @@ -38,14 +38,14 @@ StorageBackend::~StorageBackend() LogosResult StorageBackend::init(const QString& configJson = "{}") { qDebug() << "StorageBackend::initStorage called"; - LogosResult result = m_logos->storage_module.init(m_configJson); + bool result = m_logos->storage_module.init(m_configJson); - qDebug() << "StorageBackend::initStorage: init result =" << result.success; + qDebug() << "StorageBackend::initStorage: init"; - if (!result.success) { + if (!result) { setStatus(Destroyed); - debug(result.getError()); - return result; + debug("Failed to init storage"); + return {false, "", "Filed to init storage"}; } setStatus(Stopped); @@ -101,10 +101,26 @@ LogosResult StorageBackend::init(const QString& configJson = "{}") { if (!success) { QString message = data[1].toString(); debug("Failure during upload progress: " + message); + m_uploadStatus = "Error: " + message; + emit uploadStatusChanged(); } else { QString sessionId = data[1].toString(); - int len = data[2].toInt(); - // debug("Uploaded " + QString::number(len) + " bytes for session " + sessionId); + qint64 len = data[2].toLongLong(); + + m_uploadedBytes += len; + + // Calcule le pourcentage + if (m_uploadTotalBytes > 0) { + m_uploadProgress = (m_uploadedBytes * 100) / m_uploadTotalBytes; + } + + m_uploadStatus = QString("Uploading: %1 / %2 bytes (%3%)") + .arg(m_uploadedBytes) + .arg(m_uploadTotalBytes) + .arg(m_uploadProgress); + + emit uploadProgressChanged(); + emit uploadStatusChanged(); } })) { qWarning() << "StorageWidget: failed to subscribe to storageUploadProgress events"; @@ -116,11 +132,21 @@ LogosResult StorageBackend::init(const QString& configJson = "{}") { if (!success) { QString message = data[1].toString(); debug("Failed to upload: " + message); + m_uploadProgress = 0; + m_uploadStatus = "Upload failed"; + emit uploadProgressChanged(); + emit uploadStatusChanged(); } else { QString sessionId = data[1].toString(); m_cid = data[2].toString(); emit cidChanged(); debug("Upload completed for session " + sessionId + " with CID " + m_cid); + + // Complète la progress bar + m_uploadProgress = 100; + m_uploadStatus = "Upload completed!"; + emit uploadProgressChanged(); + emit uploadStatusChanged(); } })) { qWarning() << "StorageWidget: failed to subscribe to storageUploadProgress events"; @@ -162,7 +188,7 @@ LogosResult StorageBackend::init(const QString& configJson = "{}") { debug("config.json content is: " + m_configJson); - return result; + return {true, ""}; } void StorageBackend::setStatus(StorageStatus newStatus) { @@ -181,12 +207,12 @@ LogosResult StorageBackend::start(const QString& newConfigJson) { if (m_status != Stopped) { debug("The Storage Module is not initialised properly."); - return {false, "The Storage Module is not initialised properly."}; + return {false, "", "The Storage Module is not initialised properly."}; } if (m_status == Running) { debug("The Storage Module is already started."); - return {false, "The Storage Module is already started."}; + return {false, "", "The Storage Module is already started."}; } setStatus(Starting); @@ -194,15 +220,15 @@ LogosResult StorageBackend::start(const QString& newConfigJson) { auto result = m_logos->storage_module.start(); - if (!result.success) { + if (!result) { setStatus(Stopped); - debug(result.getError()); - return result; + debug("Failed to start storage"); + return {false, "", "Failed to start storage"}; } qDebug() << "StorageBackend: start command sent, waiting for events."; - return result; + return {true, ""}; } void StorageBackend::stop() { @@ -343,6 +369,16 @@ void StorageBackend::tryUploadFile(const QUrl& url) { return; } + // Reset and initialize progress tracking + m_uploadProgress = 0; + m_uploadedBytes = 0; + m_uploadTotalBytes = QFileInfo(url.toLocalFile()).size(); + m_uploadStatus = "Starting upload..."; + emit uploadProgressChanged(); + emit uploadStatusChanged(); + + debug(QString("Starting upload of file: %1 bytes").arg(m_uploadTotalBytes)); + // QString filename = url.toLocalFile(); // // QString filename = "/home/arnaud/Work/logos/logos-storage-ui/README.md"; @@ -656,6 +692,10 @@ QString StorageBackend::cid() const { return m_cid; } QString StorageBackend::configJson() const { return m_configJson; } +int StorageBackend::uploadProgress() const { return m_uploadProgress; } + +QString StorageBackend::uploadStatus() const { return m_uploadStatus; } + void StorageBackend::reloadIfChanged(const QString& configJson) { if (configJson == m_configJson) { return; @@ -690,15 +730,15 @@ void StorageBackend::reloadIfChanged(const QString& configJson) { } } - LogosResult result = m_logos->storage_module.init(configJson); + bool result = m_logos->storage_module.init(configJson); - if (!result.success) { - debug("Failed to init context with new config, will rollback, error=" + result.getError()); + if (!result) { + debug("Failed to init context with new config, will rollback."); - LogosResult result = m_logos->storage_module.init(m_configJson); + bool result = m_logos->storage_module.init(m_configJson); - if (!result.success) { - debug("Failed to init context with old config, that's a serious issue, error=" + result.getError()); + if (!result) { + debug("Failed to init context with old config, that's a serious issue."); } else { debug("Old config restored"); setStatus(StorageStatus::Stopped); diff --git a/src/StorageBackend.h b/src/StorageBackend.h index 8838a7f..859da3f 100644 --- a/src/StorageBackend.h +++ b/src/StorageBackend.h @@ -17,6 +17,8 @@ class StorageBackend : public QObject { Q_PROPERTY(StorageStatus status READ status NOTIFY statusChanged) Q_PROPERTY(QString cid READ cid NOTIFY cidChanged) Q_PROPERTY(QString configJson READ configJson NOTIFY configJsonChanged) + Q_PROPERTY(int uploadProgress READ uploadProgress NOTIFY uploadProgressChanged) + Q_PROPERTY(QString uploadStatus READ uploadStatus NOTIFY uploadStatusChanged) public: enum StorageStatus { Stopped = 0, Starting, Running, Stopping, Destroyed }; @@ -26,6 +28,8 @@ class StorageBackend : public QObject { QString debugLogs() const; StorageStatus status() const; QString configJson() const; + int uploadProgress() const; + QString uploadStatus() const; explicit StorageBackend(LogosAPI* logosAPI = nullptr, QObject* parent = nullptr); ~StorageBackend(); @@ -59,6 +63,8 @@ class StorageBackend : public QObject { void stopped(); void cidChanged(); void configJsonChanged(); + void uploadProgressChanged(); + void uploadStatusChanged(); private slots: @@ -74,4 +80,8 @@ class StorageBackend : public QObject { QString m_debugLogs; QString m_cid; QString m_configJson; + int m_uploadProgress = 0; + QString m_uploadStatus = ""; + qint64 m_uploadTotalBytes = 0; + qint64 m_uploadedBytes = 0; }; From 6ed02046d69f5e608050ce022b3282f15f3e9e53 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Mon, 16 Feb 2026 09:41:17 +0400 Subject: [PATCH 5/6] Upload progress --- src/qml/StorageView.qml | 46 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/qml/StorageView.qml b/src/qml/StorageView.qml index e5846a7..dd54af4 100644 --- a/src/qml/StorageView.qml +++ b/src/qml/StorageView.qml @@ -59,6 +59,9 @@ Rectangle { property var status: root.stopped property var debugLogs: "Hello !" property var configJson: "{}" + property url cid: "" + property string uploadStatus: "" + property int uploadProgress: 0 function start(newConfigJson) { status = root.running @@ -167,6 +170,47 @@ Rectangle { enabled: root.isRunning } + Column { + id: uploadProgressColumn + anchors.top: openFile.bottom + anchors.topMargin: 10 + anchors.horizontalCenter: parent.horizontalCenter + width: 300 + spacing: 5 + visible: root.backend.uploadProgress > 0 + + ProgressBar { + width: parent.width + value: root.backend.uploadProgress / 100.0 + + background: Rectangle { + color: "#333333" + radius: 3 + implicitWidth: 300 + implicitHeight: 6 + } + + contentItem: Item { + implicitWidth: 300 + implicitHeight: 6 + + Rectangle { + width: parent.width * parent.parent.visualPosition + height: parent.height + radius: 3 + color: "#4CAF50" + } + } + } + + Text { + text: root.backend.uploadStatus + color: "#888888" + font.pixelSize: 10 + anchors.horizontalCenter: parent.horizontalCenter + } + } + TextField { id: peerIdField placeholderText: "Enter the peer Id" @@ -175,7 +219,7 @@ Rectangle { selectByMouse: true text: root.peerId onTextChanged: root.peerId = text - anchors.top: openFile.bottom + anchors.top: uploadProgressColumn.bottom anchors.topMargin: 50 anchors.horizontalCenter: parent.horizontalCenter } From 6cf36641a0e9d3a608ed7682880aba3e89d9deea Mon Sep 17 00:00:00 2001 From: Arnaud Date: Mon, 16 Feb 2026 09:54:07 +0400 Subject: [PATCH 6/6] Update dependencies --- flake.lock | 14 +++++++------- vendor/logos-cpp-sdk | 2 +- vendor/logos-storage-module | 2 +- vendor/logos-storage-nim | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index d9d524f..ac18b22 100644 --- a/flake.lock +++ b/flake.lock @@ -293,11 +293,11 @@ "nixpkgs": "nixpkgs_7" }, "locked": { - "lastModified": 1770798353, - "narHash": "sha256-S7S3stBLrReeHlMqZkVO4h8sG0qWQIbcO+TNH90LCeY=", + "lastModified": 1770982130, + "narHash": "sha256-qsTf54BP2yEJEDHVR1lgtZ1u2wm7TK5MUHgwUiX6wU0=", "ref": "refs/heads/master", - "rev": "d02f44ffd64216cc9dd1e8cdc047b583eb074a21", - "revCount": 896, + "rev": "e375223500ca0fd919b0e504eab65c6ddb5e4233", + "revCount": 897, "submodules": true, "type": "git", "url": "https://github.com/logos-storage/logos-storage-nim" @@ -322,11 +322,11 @@ ] }, "locked": { - "lastModified": 1770999310, - "narHash": "sha256-0pD6Buni4A2lDyo31xKlGUWnM8Ebs4WRcThF8pKT5Qc=", + "lastModified": 1771221082, + "narHash": "sha256-dpygXvcVOExNXHkUH+/XcR/xBVFKNjw/i9aChSXcZNk=", "owner": "logos-co", "repo": "logos-storage-module", - "rev": "1943e8cfbee46b800bc8b5f08efb4b4376b286a8", + "rev": "b4ecf7a871233608f63b817eeae426f6273695d9", "type": "github" }, "original": { diff --git a/vendor/logos-cpp-sdk b/vendor/logos-cpp-sdk index b7a5564..c3477d2 160000 --- a/vendor/logos-cpp-sdk +++ b/vendor/logos-cpp-sdk @@ -1 +1 @@ -Subproject commit b7a556483a5ac3fa78533105a42c05577a034fb7 +Subproject commit c3477d29e32cae5f73ca637fb81e547f8a6cba58 diff --git a/vendor/logos-storage-module b/vendor/logos-storage-module index c68f855..7dceb6a 160000 --- a/vendor/logos-storage-module +++ b/vendor/logos-storage-module @@ -1 +1 @@ -Subproject commit c68f855f882002431041de291e2ba7f2f19fa05a +Subproject commit 7dceb6a8dfd5a5bbd47dc9b00e55f80b62ab1e6e diff --git a/vendor/logos-storage-nim b/vendor/logos-storage-nim index 7d51740..e375223 160000 --- a/vendor/logos-storage-nim +++ b/vendor/logos-storage-nim @@ -1 +1 @@ -Subproject commit 7d51740f91c0ee3781d40111787f0d450bf729ae +Subproject commit e375223500ca0fd919b0e504eab65c6ddb5e4233