improve diagnostics, security UX, and network tab refresh
Diagnostics & logging: - add verbose logging system (VERBOSE_LOGF) with toggle in Settings - forward app-level log messages to Console tab for in-UI visibility - add detailed connection attempt logging (attempt #, daemon state, config paths, auth failures, port owner identification) - detect HTTP 401 auth failures and show actionable error messages - identify port owner process (PID + name) on both Linux and Windows - demote noisy acrylic/shader traces from DEBUG_LOGF to VERBOSE_LOGF - persist verbose_logging preference in settings.json - link iphlpapi on Windows for GetExtendedTcpTable Security & encryption: - update local encryption state immediately after encryptwallet RPC so Settings reflects the change before daemon restarts - show notifications for encrypt success/failure and PIN skip - use dedicated RPC client for z_importwallet during decrypt flow to avoid blocking main rpc_ curl_mutex (which starved peer/tx refresh) - force full state refresh (addresses, transactions, peers) after successful wallet import Network tab: - redesign peers refresh button as glass-panel with icon + label, matching the mining button style - add spinning arc animation while peer data is loading (peer_refresh_in_progress_ atomic flag set/cleared in refreshPeerInfo) - prevent double-click spam during refresh - add refresh-button size to ui.toml Other: - use fast_rpc_ for rescan polling to avoid blocking on main rpc_ - enable DRAGONX_DEBUG in all build configs (was debug-only) - setup.sh: pull latest xmrig-hac when repo already exists
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include "../../data/wallet_state.h"
|
||||
#include "../theme.h"
|
||||
#include "../effects/imgui_acrylic.h"
|
||||
#include "../effects/low_spec.h"
|
||||
#include "../schema/ui_schema.h"
|
||||
#include "../material/type.h"
|
||||
#include "../material/draw_helpers.h"
|
||||
@@ -505,28 +506,111 @@ void RenderPeersTab(App* app)
|
||||
}
|
||||
if (ImGui::IsItemHovered()) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||
|
||||
// Refresh button — top-right of the toggle header line
|
||||
// Refresh button — top-right, glass panel style (similar to mining button)
|
||||
{
|
||||
bool isRefreshing = app->isPeerRefreshInProgress();
|
||||
auto refreshBtn = S.drawElement("tabs.peers", "refresh-button");
|
||||
float btnW = refreshBtn.size;
|
||||
float btnH = toggleH - 4.0f * Layout::dpiScale();
|
||||
float btnX = ImGui::GetWindowPos().x + availWidth - btnW - Layout::spacingSm();
|
||||
float btnY = toggleY + (toggleH - btnH) * 0.5f;
|
||||
ImVec2 bMin(btnX, btnY);
|
||||
ImVec2 bMax(btnX + btnW, btnY + btnH);
|
||||
|
||||
bool btnHovered = material::IsRectHovered(bMin, bMax);
|
||||
bool btnClicked = btnHovered && ImGui::IsMouseClicked(0);
|
||||
|
||||
// Glass panel background
|
||||
GlassPanelSpec btnGlass;
|
||||
btnGlass.rounding = Layout::glassRounding();
|
||||
if (isRefreshing) {
|
||||
float pulse = effects::isLowSpecMode()
|
||||
? 0.5f
|
||||
: 0.5f + 0.5f * (float)std::sin((double)ImGui::GetTime() * 4.0);
|
||||
btnGlass.fillAlpha = (int)(15 + 25 * pulse);
|
||||
} else {
|
||||
btnGlass.fillAlpha = btnHovered ? 30 : 18;
|
||||
}
|
||||
DrawGlassPanel(dl, bMin, bMax, btnGlass);
|
||||
|
||||
// Hover highlight
|
||||
if (btnHovered && !isRefreshing) {
|
||||
dl->AddRectFilled(bMin, bMax, WithAlpha(Primary(), 20), btnGlass.rounding);
|
||||
}
|
||||
|
||||
// Icon: spinner while refreshing, refresh icon otherwise
|
||||
float cx = bMin.x + btnW * 0.35f;
|
||||
float cy = bMin.y + btnH * 0.5f;
|
||||
ImFont* iconFont = Type().iconMed();
|
||||
float iconSz = iconFont->LegacySize;
|
||||
float btnPad = Layout::spacingSm();
|
||||
float btnX = ImGui::GetWindowPos().x + availWidth - iconSz - btnPad;
|
||||
float btnY = toggleY + (toggleH - iconSz) * 0.5f;
|
||||
ImGui::SetCursorScreenPos(ImVec2(btnX, btnY));
|
||||
ImGui::PushID("##peersRefresh");
|
||||
if (ImGui::InvisibleButton("##btn", ImVec2(iconSz + btnPad, iconSz + btnPad))) {
|
||||
app->refreshPeerInfo();
|
||||
app->refreshNow();
|
||||
|
||||
if (isRefreshing) {
|
||||
// Spinning arc spinner (same style as mining toggle)
|
||||
float spinnerR = iconSz * 0.5f;
|
||||
float thickness = std::max(1.5f, spinnerR * 0.18f);
|
||||
float time = (float)ImGui::GetTime();
|
||||
|
||||
// Track circle (faint)
|
||||
dl->AddCircle(ImVec2(cx, cy), spinnerR, WithAlpha(Primary(), 40), 0, thickness);
|
||||
|
||||
// Animated arc
|
||||
float rotation = fmodf(time * 2.0f * IM_PI / 1.4f, IM_PI * 2.0f);
|
||||
float cycleTime = fmodf(time, 1.333f);
|
||||
float arcLength = (cycleTime < 0.666f)
|
||||
? (cycleTime / 0.666f) * 0.75f + 0.1f
|
||||
: ((1.333f - cycleTime) / 0.666f) * 0.75f + 0.1f;
|
||||
float startAngle = rotation - IM_PI * 0.5f;
|
||||
float endAngle = startAngle + IM_PI * 2.0f * arcLength;
|
||||
int segments = (int)(32 * arcLength) + 1;
|
||||
float angleStep = (endAngle - startAngle) / segments;
|
||||
ImU32 arcCol = Primary();
|
||||
for (int si = 0; si < segments; si++) {
|
||||
float a1 = startAngle + angleStep * si;
|
||||
float a2 = startAngle + angleStep * (si + 1);
|
||||
ImVec2 p1(cx + cosf(a1) * spinnerR, cy + sinf(a1) * spinnerR);
|
||||
ImVec2 p2(cx + cosf(a2) * spinnerR, cy + sinf(a2) * spinnerR);
|
||||
dl->AddLine(p1, p2, arcCol, thickness);
|
||||
}
|
||||
} else {
|
||||
// Static refresh icon
|
||||
ImU32 iconCol = btnHovered ? OnSurface() : OnSurfaceMedium();
|
||||
ImVec2 iSz = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, ICON_MD_REFRESH);
|
||||
dl->AddText(iconFont, iconFont->LegacySize,
|
||||
ImVec2(cx - iSz.x * 0.5f, cy - iSz.y * 0.5f),
|
||||
iconCol, ICON_MD_REFRESH);
|
||||
}
|
||||
bool hovered = ImGui::IsItemHovered();
|
||||
if (hovered) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||
ImU32 iconCol = hovered ? OnSurface() : OnSurfaceMedium();
|
||||
// Centre icon within the invisible button
|
||||
float drawX = btnX + (iconSz + btnPad - iconSz) * 0.5f;
|
||||
float drawY = btnY + (iconSz + btnPad - iconSz) * 0.5f;
|
||||
dl->AddText(iconFont, iconSz, ImVec2(drawX, drawY), iconCol, ICON_MD_REFRESH);
|
||||
if (hovered) {
|
||||
ImGui::SetTooltip("Refresh peers & blockchain");
|
||||
|
||||
// Label to the right of icon
|
||||
{
|
||||
const char* label = isRefreshing ? "REFRESHING" : "REFRESH";
|
||||
ImU32 lblCol;
|
||||
if (isRefreshing) {
|
||||
float pulse = effects::isLowSpecMode()
|
||||
? 0.7f
|
||||
: 0.5f + 0.5f * (float)std::sin((double)ImGui::GetTime() * 3.0);
|
||||
lblCol = WithAlpha(Primary(), (int)(120 + 135 * pulse));
|
||||
} else {
|
||||
lblCol = btnHovered ? OnSurface() : WithAlpha(OnSurface(), 160);
|
||||
}
|
||||
ImVec2 lblSz = ovFont->CalcTextSizeA(ovFont->LegacySize, FLT_MAX, 0, label);
|
||||
float lblX = cx + iconSz * 0.5f + Layout::spacingXs();
|
||||
float lblY = cy - lblSz.y * 0.5f;
|
||||
dl->AddText(ovFont, ovFont->LegacySize, ImVec2(lblX, lblY), lblCol, label);
|
||||
}
|
||||
|
||||
// Invisible button for click handling
|
||||
ImGui::SetCursorScreenPos(bMin);
|
||||
ImGui::PushID("##peersRefresh");
|
||||
if (ImGui::InvisibleButton("##btn", ImVec2(btnW, btnH))) {
|
||||
if (!isRefreshing) {
|
||||
app->refreshPeerInfo();
|
||||
app->refreshNow();
|
||||
}
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||
if (!isRefreshing)
|
||||
ImGui::SetTooltip("Refresh peers & blockchain");
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user