// 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 #include #include #include 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 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 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 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