feat(console): left-edge channel accent bar (replaces inline log prefixes)
Each line gets a `channel` inferred in addLine() from its color and any "[daemon]"/"[xmrig]"/"[app]"/"[rpc]" prefix, which is then stripped. renderOutput draws a thin colored bar in the existing left margin (padX) per line — node log (blue), mining (amber), app (teal), rpc (secondary), command (accent), error (red). Drawn in the margin so it never touches the text layout or selection; filtering is unaffected (it keys off color, not the prefix). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -813,7 +813,30 @@ void ConsoleTab::renderOutput()
|
|||||||
const auto& segs = visible_wrap_segments_[vi];
|
const auto& segs = visible_wrap_segments_[vi];
|
||||||
ImVec2 lineOrigin = ImGui::GetCursorScreenPos();
|
ImVec2 lineOrigin = ImGui::GetCursorScreenPos();
|
||||||
float totalH = wrapped_heights_[vi];
|
float totalH = wrapped_heights_[vi];
|
||||||
|
|
||||||
|
// Left-edge channel accent bar, drawn in the padX margin so it never overlaps
|
||||||
|
// the text or the selection highlight.
|
||||||
|
if (line.channel != CH_NONE) {
|
||||||
|
ImU32 barCol = 0;
|
||||||
|
switch (line.channel) {
|
||||||
|
case CH_COMMAND: barCol = Primary(); break;
|
||||||
|
case CH_ERROR: barCol = Error(); break;
|
||||||
|
case CH_RPC: barCol = Secondary(); break;
|
||||||
|
case CH_DAEMON: barCol = IM_COL32(90, 130, 190, 210); break; // node log — blue
|
||||||
|
case CH_XMRIG: barCol = Warning(); break; // mining — amber
|
||||||
|
case CH_APP: barCol = IM_COL32(120, 190, 160, 210); break; // app — teal
|
||||||
|
case CH_INFO: barCol = OnSurfaceDisabled(); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
if (barCol != 0) {
|
||||||
|
float barW = 3.0f * Layout::hScale();
|
||||||
|
float barX = output_origin_.x - padX + 3.0f * Layout::hScale();
|
||||||
|
dl->AddRectFilled(ImVec2(barX, lineOrigin.y + 1.0f),
|
||||||
|
ImVec2(barX + barW, lineOrigin.y + totalH - 1.0f),
|
||||||
|
barCol, barW * 0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Determine byte-level selection range for this line
|
// Determine byte-level selection range for this line
|
||||||
int selByteStart = 0, selByteEnd = 0;
|
int selByteStart = 0, selByteEnd = 0;
|
||||||
bool lineSelected = false;
|
bool lineSelected = false;
|
||||||
@@ -1488,8 +1511,27 @@ void ConsoleTab::renderStatusHeader(ConsoleCommandExecutor& exec)
|
|||||||
void ConsoleTab::addLine(const std::string& line, ImU32 color)
|
void ConsoleTab::addLine(const std::string& line, ImU32 color)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(lines_mutex_);
|
std::lock_guard<std::mutex> lock(lines_mutex_);
|
||||||
|
|
||||||
lines_.push_back({line, color});
|
// Infer the channel (for the left accent bar) from the color, then strip the now
|
||||||
|
// redundant "[daemon]"/"[xmrig]"/"[app]" text prefix so the bar carries the source.
|
||||||
|
int channel = CH_NONE;
|
||||||
|
if (color == COLOR_ERROR) channel = CH_ERROR;
|
||||||
|
else if (color == COLOR_RPC) channel = CH_RPC;
|
||||||
|
else if (color == COLOR_COMMAND) channel = CH_COMMAND;
|
||||||
|
else if (color == COLOR_DAEMON) channel = CH_DAEMON;
|
||||||
|
else if (color == COLOR_INFO) channel = CH_INFO;
|
||||||
|
|
||||||
|
std::string text = line;
|
||||||
|
auto stripPrefix = [&text, &channel](const char* p, int ch) {
|
||||||
|
const size_t n = std::strlen(p);
|
||||||
|
if (text.rfind(p, 0) == 0) { text.erase(0, n); channel = ch; }
|
||||||
|
};
|
||||||
|
stripPrefix("[daemon] ", CH_DAEMON);
|
||||||
|
stripPrefix("[xmrig] ", CH_XMRIG);
|
||||||
|
stripPrefix("[app] ", CH_APP);
|
||||||
|
stripPrefix("[rpc] ", CH_RPC);
|
||||||
|
|
||||||
|
lines_.push_back({text, color, channel});
|
||||||
|
|
||||||
// Limit buffer size — adjust selection indices when lines are removed
|
// Limit buffer size — adjust selection indices when lines are removed
|
||||||
// from the front so the highlight stays on the text the user selected.
|
// from the front so the highlight stays on the text the user selected.
|
||||||
|
|||||||
@@ -88,11 +88,16 @@ public:
|
|||||||
static ImU32 COLOR_RPC;
|
static ImU32 COLOR_RPC;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Line source, for the left-edge channel accent bar. Inferred in addLine() from the
|
||||||
|
// color + any "[daemon]"/"[xmrig]"/"[app]" prefix (which is then stripped).
|
||||||
|
enum Channel { CH_NONE = 0, CH_COMMAND, CH_INFO, CH_ERROR, CH_RPC, CH_DAEMON, CH_XMRIG, CH_APP };
|
||||||
|
|
||||||
struct ConsoleLine {
|
struct ConsoleLine {
|
||||||
std::string text;
|
std::string text;
|
||||||
ImU32 color;
|
ImU32 color;
|
||||||
|
int channel = CH_NONE;
|
||||||
};
|
};
|
||||||
|
|
||||||
void addCommandResult(const std::string& cmd, const std::string& result, bool is_error = false);
|
void addCommandResult(const std::string& cmd, const std::string& result, bool is_error = false);
|
||||||
// Format + color a completed command result (JSON-aware) into console lines.
|
// Format + color a completed command result (JSON-aware) into console lines.
|
||||||
void addFormattedResult(const std::string& result, bool is_error);
|
void addFormattedResult(const std::string& result, bool is_error);
|
||||||
|
|||||||
Reference in New Issue
Block a user