5 Commits

Author SHA1 Message Date
bbf53a130c refactor: tab-aware prioritized refresh system
Split monolithic refreshData() into independent sub-functions
(refreshCoreData, refreshAddressData, refreshTransactionData,
refreshEncryptionState) each with its own timer and atomic guard.

Per-category timers replace the single 5s refresh_timer_:
- core_timer_: balance + blockchain info (5s default)
- transaction_timer_: tx list + enrichment (10s default)
- address_timer_: z/t address lists (15s default)
- peer_timer_: encryption state (10s default)

Tab-switching via setCurrentPage() adjusts active intervals so
the current tab's data refreshes faster (e.g. 3s core on Overview,
5s transactions on History) while background categories slow down.

Use fast_worker_ for core data on Overview tab to avoid blocking
behind the main refresh batch.

Bump version to 1.1.2.
2026-04-04 13:05:00 -05:00
1f9e43d7b2 refactor: extract AI/agent files into separate repo
ObsidianDragon-agent/ is now a standalone git repo (future submodule)
so AI configuration files are not pushed to the main repository.

- Remove copilot-instructions.md and ARCHITECTURE.md from main tracking
- Remove symlinks from .github/ and docs/
- Add ObsidianDragon-agent/ and .github/ to .gitignore
2026-04-04 11:36:04 -05:00
5ebccceffc refactor: move AI/agent files into ObsidianDragon-agent/
- copilot-instructions.md → ObsidianDragon-agent/copilot-instructions.md
- ARCHITECTURE.md → ObsidianDragon-agent/ARCHITECTURE.md
- Symlinks at original locations preserve Copilot auto-discovery
2026-04-04 11:29:12 -05:00
9d2d581474 docs: add ARCHITECTURE.md with project overview
Covers directory layout, threading model, RPC architecture,
connection lifecycle, UI system, build system, and key conventions.
2026-04-04 11:17:21 -05:00
096f8ee90e docs: add copilot-instructions.md and file-level comments
- Create .github/copilot-instructions.md with project coding standards,
  architecture overview, threading model, and key rules for AI sessions
- Add module description comments to app.cpp, rpc_client.cpp, rpc_worker.cpp,
  embedded_daemon.cpp, xmrig_manager.cpp, console_tab.cpp, settings.cpp
- Add ASCII connection state diagram to app_network.cpp
- Remove /.github/ from .gitignore so instructions file is tracked
2026-04-04 11:14:31 -05:00
12 changed files with 555 additions and 611 deletions

1
.gitignore vendored
View File

@@ -37,6 +37,7 @@ asmap.dat
/memory /memory
/todo.md /todo.md
/.github/ /.github/
/ObsidianDragon-agent/
# macOS # macOS
.DS_Store .DS_Store

View File

@@ -15,7 +15,7 @@ if(APPLE)
endif() endif()
project(ObsidianDragon project(ObsidianDragon
VERSION 1.1.1 VERSION 1.1.2
LANGUAGES C CXX LANGUAGES C CXX
DESCRIPTION "DragonX Cryptocurrency Wallet" DESCRIPTION "DragonX Cryptocurrency Wallet"
) )

View File

@@ -1,6 +1,9 @@
// DragonX Wallet - ImGui Edition // DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers // Copyright 2024-2026 The Hush Developers
// Released under the GPLv3 // Released under the GPLv3
//
// app.cpp — Main application: init, shutdown, ImGui render loop, NavPage
// dispatch, dialog rendering, and frame-level state management.
#include "app.h" #include "app.h"
#include "config/version.h" #include "config/version.h"
@@ -340,7 +343,10 @@ void App::update()
} }
// Update timers // Update timers
refresh_timer_ += io.DeltaTime; core_timer_ += io.DeltaTime;
address_timer_ += io.DeltaTime;
transaction_timer_ += io.DeltaTime;
peer_timer_ += io.DeltaTime;
price_timer_ += io.DeltaTime; price_timer_ += io.DeltaTime;
fast_refresh_timer_ += io.DeltaTime; fast_refresh_timer_ += io.DeltaTime;
tx_age_timer_ += io.DeltaTime; tx_age_timer_ += io.DeltaTime;
@@ -588,20 +594,37 @@ void App::update()
transactions_dirty_ = true; transactions_dirty_ = true;
addresses_dirty_ = true; addresses_dirty_ = true;
last_tx_block_height_ = -1; last_tx_block_height_ = -1;
refresh_timer_ = REFRESH_INTERVAL; core_timer_ = active_core_interval_;
transaction_timer_ = active_tx_interval_;
address_timer_ = active_addr_interval_;
} }
}; };
}); });
} }
// Regular refresh every 5 seconds // Per-category refresh with tab-aware intervals
// Skip when wallet is locked — same reason as above. // Skip when wallet is locked — same reason as above.
if (refresh_timer_ >= REFRESH_INTERVAL) { if (state_.connected && !state_.isLocked()) {
refresh_timer_ = 0.0f; if (core_timer_ >= active_core_interval_) {
if (state_.connected && !state_.isLocked()) { core_timer_ = 0.0f;
refreshData(); refreshCoreData();
} else if (!connection_in_progress_ && }
wizard_phase_ == WizardPhase::None) { if (transaction_timer_ >= active_tx_interval_) {
transaction_timer_ = 0.0f;
refreshTransactionData();
}
if (address_timer_ >= active_addr_interval_) {
address_timer_ = 0.0f;
refreshAddressData();
}
if (peer_timer_ >= active_peer_interval_) {
peer_timer_ = 0.0f;
refreshEncryptionState();
}
} else if (core_timer_ >= active_core_interval_) {
core_timer_ = 0.0f;
if (!connection_in_progress_ &&
wizard_phase_ == WizardPhase::None) {
tryConnect(); tryConnect();
} }
} }
@@ -616,7 +639,7 @@ void App::update()
// Keyboard shortcut: Ctrl+, to open Settings page // Keyboard shortcut: Ctrl+, to open Settings page
if (io.KeyCtrl && ImGui::IsKeyPressed(ImGuiKey_Comma)) { if (io.KeyCtrl && ImGui::IsKeyPressed(ImGuiKey_Comma)) {
current_page_ = ui::NavPage::Settings; setCurrentPage(ui::NavPage::Settings);
} }
// Keyboard shortcut: Ctrl+Left/Right to cycle themes // Keyboard shortcut: Ctrl+Left/Right to cycle themes
@@ -1883,7 +1906,11 @@ void App::renderAntivirusHelpDialog()
void App::refreshNow() void App::refreshNow()
{ {
refresh_timer_ = REFRESH_INTERVAL; // Trigger immediate refresh // Trigger immediate refresh on all categories
core_timer_ = active_core_interval_;
transaction_timer_ = active_tx_interval_;
address_timer_ = active_addr_interval_;
peer_timer_ = active_peer_interval_;
transactions_dirty_ = true; // Force transaction list update transactions_dirty_ = true; // Force transaction list update
addresses_dirty_ = true; // Force address/balance update addresses_dirty_ = true; // Force address/balance update
last_tx_block_height_ = -1; // Reset tx cache last_tx_block_height_ = -1; // Reset tx cache
@@ -1906,7 +1933,7 @@ void App::handlePaymentURI(const std::string& uri)
pending_label_ = payment.label; pending_label_ = payment.label;
// Switch to Send page // Switch to Send page
current_page_ = ui::NavPage::Send; setCurrentPage(ui::NavPage::Send);
// Notify user // Notify user
std::string msg = "Payment request loaded"; std::string msg = "Payment request loaded";
@@ -1933,7 +1960,7 @@ void App::setCurrentTab(int tab) {
ui::NavPage::Settings, // 9 = Settings ui::NavPage::Settings, // 9 = Settings
}; };
if (tab >= 0 && tab < static_cast<int>(sizeof(kTabMap)/sizeof(kTabMap[0]))) if (tab >= 0 && tab < static_cast<int>(sizeof(kTabMap)/sizeof(kTabMap[0])))
current_page_ = kTabMap[tab]; setCurrentPage(kTabMap[tab]);
} }
bool App::startEmbeddedDaemon() bool App::startEmbeddedDaemon()

View File

@@ -221,13 +221,19 @@ public:
void refreshPeerInfo(); void refreshPeerInfo();
void refreshMarketData(); void refreshMarketData();
/// @brief Per-category refresh intervals, adjusted by active tab
struct RefreshIntervals {
float core; // balance + sync status
float transactions; // tx list + enrichment
float addresses; // address lists + balances
float peers; // peer info (0 = disabled)
};
/// @brief Get recommended refresh intervals for a given page
static RefreshIntervals getIntervalsForPage(ui::NavPage page);
// UI navigation // UI navigation
void setCurrentPage(ui::NavPage page) { void setCurrentPage(ui::NavPage page);
if (page != current_page_) {
current_page_ = page;
if (page == ui::NavPage::Peers) refreshPeerInfo();
}
}
ui::NavPage getCurrentPage() const { return current_page_; } ui::NavPage getCurrentPage() const { return current_page_; }
// Dialog triggers (used by settings page to open modal dialogs) // Dialog triggers (used by settings page to open modal dialogs)
@@ -362,7 +368,6 @@ private:
// Shutdown state // Shutdown state
std::atomic<bool> shutting_down_{false}; std::atomic<bool> shutting_down_{false};
std::atomic<bool> shutdown_complete_{false}; std::atomic<bool> shutdown_complete_{false};
std::atomic<bool> refresh_in_progress_{false};
bool address_list_dirty_ = false; // P8: dedup rebuildAddressList bool address_list_dirty_ = false; // P8: dedup rebuildAddressList
std::string shutdown_status_; std::string shutdown_status_;
std::thread shutdown_thread_; std::thread shutdown_thread_;
@@ -438,16 +443,33 @@ private:
std::string pending_memo_; std::string pending_memo_;
std::string pending_label_; std::string pending_label_;
// Timers (in seconds since last update) // Per-category timers (in seconds since last refresh)
float refresh_timer_ = 0.0f; float core_timer_ = 0.0f; // balance + sync status
float address_timer_ = 0.0f; // address lists
float transaction_timer_ = 0.0f; // transaction list
float peer_timer_ = 0.0f; // peer info
float price_timer_ = 0.0f; float price_timer_ = 0.0f;
float fast_refresh_timer_ = 0.0f; // For mining stats float fast_refresh_timer_ = 0.0f; // For mining stats
// Refresh intervals (seconds) // Default refresh intervals (seconds)
static constexpr float REFRESH_INTERVAL = 5.0f; static constexpr float CORE_INTERVAL_DEFAULT = 5.0f;
static constexpr float ADDRESS_INTERVAL_DEFAULT = 15.0f;
static constexpr float TX_INTERVAL_DEFAULT = 10.0f;
static constexpr float PEER_INTERVAL_DEFAULT = 10.0f;
static constexpr float PRICE_INTERVAL = 60.0f; static constexpr float PRICE_INTERVAL = 60.0f;
static constexpr float FAST_REFRESH_INTERVAL = 1.0f; static constexpr float FAST_REFRESH_INTERVAL = 1.0f;
// Active intervals — adjusted by tab priority via applyRefreshPolicy()
float active_core_interval_ = CORE_INTERVAL_DEFAULT;
float active_tx_interval_ = TX_INTERVAL_DEFAULT;
float active_addr_interval_ = ADDRESS_INTERVAL_DEFAULT;
float active_peer_interval_ = PEER_INTERVAL_DEFAULT;
// Per-category refresh guards (prevent worker queue pileup)
std::atomic<bool> core_refresh_in_progress_{false};
std::atomic<bool> address_refresh_in_progress_{false};
std::atomic<bool> tx_refresh_in_progress_{false};
// Mining refresh guard (prevents worker queue pileup) // Mining refresh guard (prevents worker queue pileup)
std::atomic<bool> mining_refresh_in_progress_{false}; std::atomic<bool> mining_refresh_in_progress_{false};
int mining_slow_counter_ = 0; // counts fast ticks; fires slow refresh every N int mining_slow_counter_ = 0; // counts fast ticks; fires slow refresh every N
@@ -604,11 +626,17 @@ private:
void applyDefaultBanlist(); void applyDefaultBanlist();
// Private methods - data refresh // Private methods - data refresh
void refreshData(); void refreshData(); // Orchestrator: dispatches per-category refreshes
void refreshBalance(); void refreshCoreData(); // Balance + blockchain info (can use fast_worker_)
void refreshAddresses(); void refreshAddressData(); // Address lists + balances
void refreshTransactionData(); // Transaction list + z_viewtransaction enrichment
void refreshEncryptionState(); // Wallet encryption/lock state
void refreshBalance(); // Legacy: balance-only refresh (used by specific callers)
void refreshAddresses(); // Legacy: standalone address refresh
void refreshPrice(); void refreshPrice();
void refreshWalletEncryptionState(); void refreshWalletEncryptionState();
void applyRefreshPolicy(ui::NavPage page);
bool shouldRefreshTransactions() const;
void checkAutoLock(); void checkAutoLock();
void checkIdleMining(); void checkIdleMining();
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,9 @@
// DragonX Wallet - ImGui Edition // DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers // Copyright 2024-2026 The Hush Developers
// Released under the GPLv3 // Released under the GPLv3
//
// settings.cpp — JSON settings persistence. Loads/saves user preferences
// to ~/.config/ObsidianDragon/settings.json (Linux/macOS) or %APPDATA% (Windows).
#include "settings.h" #include "settings.h"
#include "version.h" #include "version.h"

View File

@@ -7,10 +7,10 @@
// !! DO NOT EDIT version.h — it is generated from version.h.in by CMake. // !! DO NOT EDIT version.h — it is generated from version.h.in by CMake.
// !! Change the version in CMakeLists.txt: project(... VERSION x.y.z ...) // !! Change the version in CMakeLists.txt: project(... VERSION x.y.z ...)
#define DRAGONX_VERSION "1.1.1" #define DRAGONX_VERSION "1.1.2"
#define DRAGONX_VERSION_MAJOR 1 #define DRAGONX_VERSION_MAJOR 1
#define DRAGONX_VERSION_MINOR 1 #define DRAGONX_VERSION_MINOR 1
#define DRAGONX_VERSION_PATCH 1 #define DRAGONX_VERSION_PATCH 2
#define DRAGONX_APP_NAME "ObsidianDragon" #define DRAGONX_APP_NAME "ObsidianDragon"
#define DRAGONX_ORG_NAME "Hush" #define DRAGONX_ORG_NAME "Hush"

View File

@@ -1,6 +1,9 @@
// DragonX Wallet - ImGui Edition // DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers // Copyright 2024-2026 The Hush Developers
// Released under the GPLv3 // Released under the GPLv3
//
// embedded_daemon.cpp — Manages the dragonxd child process lifecycle:
// binary discovery, process spawn, stdout/stderr monitoring, crash recovery.
#include "embedded_daemon.h" #include "embedded_daemon.h"
#include "../config/version.h" #include "../config/version.h"

View File

@@ -1,6 +1,9 @@
// DragonX Wallet - ImGui Edition // DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers // Copyright 2024-2026 The Hush Developers
// Released under the GPLv3 // Released under the GPLv3
//
// xmrig_manager.cpp — Pool mining process management via xmrig-hac.
// Spawns xmrig, monitors via HTTP API, tracks hashrate and shares.
#include "xmrig_manager.h" #include "xmrig_manager.h"
#include "../resources/embedded_resources.h" #include "../resources/embedded_resources.h"

View File

@@ -1,6 +1,9 @@
// DragonX Wallet - ImGui Edition // DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers // Copyright 2024-2026 The Hush Developers
// Released under the GPLv3 // Released under the GPLv3
//
// rpc_client.cpp — JSON-RPC client over HTTPS using libcurl.
// All calls are blocking; run on RPCWorker threads, never on main thread.
#include "rpc_client.h" #include "rpc_client.h"
#include "../config/version.h" #include "../config/version.h"

View File

@@ -1,6 +1,9 @@
// DragonX Wallet - ImGui Edition // DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers // Copyright 2024-2026 The Hush Developers
// Released under the GPLv3 // Released under the GPLv3
//
// rpc_worker.cpp — Background work queue. Executes WorkFn on its own thread,
// returns MainCb callbacks drained each frame on the main thread.
#include "rpc_worker.h" #include "rpc_worker.h"
#include <cstdio> #include <cstdio>

View File

@@ -1,6 +1,9 @@
// DragonX Wallet - ImGui Edition // DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers // Copyright 2024-2026 The Hush Developers
// Released under the GPLv3 // Released under the GPLv3
//
// console_tab.cpp — Interactive RPC console with command history,
// tab completion, daemon log display, and color-coded output.
#include "console_tab.h" #include "console_tab.h"
#include "../material/colors.h" #include "../material/colors.h"