Files
ObsidianDragon/src/ui/windows/console_tab.h
DanS 4416e01f9c feat(console): parameter builder in the command explorer (phase 3)
The detail pane's Parameters section is now an editable form: each parameter is
a type-hinted input field (string / number / json, optional marked), and a live
"Builds" preview shows the command being assembled. String values are
auto-quoted; a required field left empty keeps its placeholder and disables
"Insert & run"; trailing empty optionals are omitted.

Insert and Insert & run now use the assembled command (not just the template),
so Insert & run works for parameterized commands once the required fields are
filled — destructive commands still confirm first. Param fields reset when the
selected command changes or the modal opens. Keyboard nav (Up/Down/Enter) is
scoped to the search box so typing in a field doesn't move the selection.

A best-effort parseParamSpecs turns the human-readable param templates into
fields; JSON-array params (z_sendmany, createrawtransaction) surface as a single
"json" field the user pastes into. Adds the console_ref_builds label + 8
translations.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 11:32:35 -05:00

202 lines
8.8 KiB
C++

// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3
#pragma once
#include "console_channel.h"
#include "console_model.h"
#include "console_scroll_controller.h"
#include "console_selection_controller.h"
#include "console_text_layout.h"
#include "../layout.h"
#include "../../daemon/embedded_daemon.h"
#include "../../daemon/xmrig_manager.h"
#include "../../rpc/rpc_client.h"
#include "../../rpc/rpc_worker.h"
#include <string>
#include <vector>
#include <deque>
#include <mutex>
namespace dragonx {
namespace ui {
class ConsoleCommandExecutor;
struct ConsoleLogFilterCaps;
struct ConsoleCommandEntry;
/**
* @brief Console tab — a rich terminal shared by the full-node and lite variants.
*
* The command execution + log sources are provided by a ConsoleCommandExecutor, so this
* one widget serves both dragonxd (RPC) and the lite backend.
*/
class ConsoleTab {
public:
ConsoleTab();
~ConsoleTab();
/**
* @brief Render the console tab against a backend executor.
*/
void render(ConsoleCommandExecutor& exec);
/**
* @brief Render the RPC Command Reference popup at top-level scope.
* Must be called outside any child window so the modal blocks all input.
*/
void renderCommandsPopupModal();
// Debug/UI-sweep hook: force the RPC command-reference popup open/closed so the full UI sweep
// can capture it (the popup is otherwise opened only by a toolbar button).
void sweepSetCommandsPopup(bool open) { show_commands_popup_ = open; }
/**
* @brief Add a line to the console output
*/
void addLine(const std::string& line, ConsoleChannel channel = ConsoleChannel::None);
void addRpcTraceLine(const std::string& source, const std::string& method);
/**
* @brief Clear console output
*/
void clear();
// Scanline effect toggle (set from settings)
static bool s_scanline_enabled;
// Console output zoom factor (1.0 = default caption font size)
static float s_console_zoom;
// Draw the per-line left color accent bars (channel-colored). Toggled from the toolbar.
static bool s_line_accents_enabled;
// Color output text per channel. When false the console is monochrome text. Toolbar-toggled.
static bool s_line_text_color_enabled;
// Show/hide daemon output messages
static bool s_daemon_messages_enabled;
// Show only error messages (filter toggle)
static bool s_errors_only_enabled;
// Show app RPC calls made through RPCClient (method/source only)
static bool s_rpc_trace_enabled;
// Show "[app] ..." wallet log lines
static bool s_app_messages_enabled;
/// Refresh console text colors for current theme (call after theme switch)
static void refreshColors();
// Colors — follow active theme (public for use by notification forwarding)
static ImU32 COLOR_COMMAND;
static ImU32 COLOR_RESULT;
static ImU32 COLOR_ERROR;
static ImU32 COLOR_DAEMON;
static ImU32 COLOR_INFO;
static ImU32 COLOR_RPC;
private:
// Text color for a channel, resolved from the current theme (COLOR_* + material). Each
// line stores only its semantic ConsoleChannel (in ConsoleModel); the text color and
// the left accent-bar color are both derived from it at draw time.
ImU32 channelTextColor(ConsoleChannel channel) const;
// Saturated accent color for a channel — the left accent-bar color, also used to tint the
// matching toolbar filter toggle. 0 for channels that get no accent (result/JSON/None).
static ImU32 channelAccentColor(ConsoleChannel channel);
// Drain the thread-safe ingest queue into the visible model (once per frame, main
// thread), applying the line cap + selection/scroll bookkeeping for the new lines.
void drainModel();
// Format a completed command result (JSON role -> channel) into console lines.
void addFormattedResult(const std::string& result, bool is_error);
void renderStatusHeader(ConsoleCommandExecutor& exec);
void renderCommandsPopup();
void renderCommandDetail(const ConsoleCommandEntry& cmd, const char* catLabel); // right pane
void insertCommandToInput(const ConsoleCommandEntry& cmd); // fill input + close the modal
// renderToolbar() draws the top bar; these are its sub-steps:
void renderToolbar(ConsoleCommandExecutor& exec);
void drawToolbarStatus(ConsoleCommandExecutor& exec); // backend status dot + label
void drawLogFilterToggles(const ConsoleLogFilterCaps& caps); // color-coded filter checkboxes
void drawFilterInput(); // text filter + match count
void drawZoomControls(); // zoom -/+ buttons
// renderInput() draws the command line; dispatch is factored out:
void renderInput(ConsoleCommandExecutor& exec);
// Echo + handle a submitted command line (built-ins + submit). True if non-empty/handled.
bool submitConsoleCommand(ConsoleCommandExecutor& exec, const std::string& cmd);
// renderOutput() orchestrates the scrollable output area; these are its sub-steps:
void renderOutput();
void computeVisibleLines(bool& hasTextFilter, std::string& filterLower); // -> visible_indices_
void handleOutputInteraction(ImVec2 mousePos, bool mouseInOutput); // wheel/selection/keys
void drawVisibleLines(float padX, float lineHeight, bool hasTextFilter,
const std::string& filterLower); // bars/guides/highlight/text
void drawNewOutputIndicator(); // jump-to-bottom pill
void drawOutputContextMenu(); // right-click menu
// Map a screen point to a raw {line, col} position via this frame's wrapped layout.
// (View-side because it needs layout_ + output_origin_; feeds the selection controller.)
ConsoleTextPos screenToTextPos(ImVec2 screen_pos) const;
// The current selection's text (via selection_ over the visible model). "" if inactive.
std::string selectedText() const;
// Thread-safe line store: producers on any thread call model_.ingest(); the main
// thread drains it once per frame in render(). The visible deque is main-thread-only.
ConsoleModel model_;
std::vector<std::string> command_history_;
int history_index_ = -1;
char input_buffer_[4096] = {0};
bool stop_confirm_pending_ = false; // 'stop' typed once, awaiting a confirming second 'stop'
// (log-ingestion cursors + result queue moved to the ConsoleCommandExecutor)
// Auto-scroll state machine (pin-to-bottom, wheel-up cooldown, new-line backlog count).
ConsoleScrollController scroll_;
// Text-selection state + logic (anchor/caret, ordering, extraction, eviction shift).
ConsoleSelectionController selection_;
float output_scroll_y_ = 0.0f; // Track scroll position for selection
ImVec2 output_origin_ = {0, 0}; // Top-left of output area
float output_line_height_ = 0.0f; // Text line height (for scanline alignment)
struct ScanlineRow {
float yTop = 0.0f;
float yBot = 0.0f;
int rowIndex = 0;
};
std::vector<ScanlineRow> scanline_rows_;
// Output filter
char filter_text_[128] = {0};
mutable int filter_match_count_ = 0; // lines matching the text filter (for the toolbar)
std::string context_token_; // hash/address under the cursor at right-click
mutable std::vector<int> visible_indices_; // Cached for selection mapping
bool folding_active_ = true; // fold UI shown only in the unfiltered (foldable) view
bool has_text_filter_ = false; // computed once per frame (before the toolbar draws it)
std::string filter_lower_; // lowercased filter needle for match highlighting
// Wrap layout for the visible lines (segments + per-line heights + cumulative Y),
// recomputed each frame by the pure BuildConsoleLayout (console_text_layout.h) and
// consumed by the renderer + hit-testing.
mutable ConsoleLayout layout_;
// Commands popup (RPC command explorer)
bool show_commands_popup_ = false;
char command_search_[128] = {0}; // RPC-reference search filter (cleared when the modal opens)
int cmd_sel_cat_ = -1; // detail-pane selection: category index into consoleCommandCategories()
int cmd_sel_idx_ = -1; // detail-pane selection: command index within that category
std::string pending_submit_; // command to run next frame (deferred so the modal needs no executor)
const ConsoleCommandEntry* run_confirm_cmd_ = nullptr; // destructive "Insert & run" awaiting confirmation
char cmd_param_bufs_[6][256] = {{0}}; // parameter-builder input fields
const ConsoleCommandEntry* cmd_param_owner_ = nullptr; // command the param buffers currently hold
};
} // namespace ui
} // namespace dragonx