feat: blockchain rescan via daemon restart + status bar progress
- Fix z_importwallet to use full path instead of filename only - Add rescanBlockchain() method that restarts daemon with -rescan flag - Track rescan progress via daemon output parsing and getrescaninfo RPC - Display rescan progress in status bar with animated indicator when starting - Improve dark theme card contrast: lighter surface-variant, tinted borders, stronger rim-light
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#include "../effects/imgui_acrylic.h"
|
||||
#include "../theme.h"
|
||||
#include "../../util/noise_texture.h"
|
||||
#include "../../embedded/IconsMaterialDesign.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
#include <algorithm>
|
||||
@@ -774,6 +775,171 @@ inline void ApplySmoothScroll(float speed = 12.0f)
|
||||
ImGui::SetScrollY(s.current);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Dialog Title Bar with Close Button
|
||||
// ============================================================================
|
||||
// Draws a custom title bar for modal popups with a title and close button.
|
||||
// Returns true if the close button was clicked.
|
||||
|
||||
inline bool DrawDialogTitleBar(const char* title, bool* p_open, ImU32 accent_col = 0)
|
||||
{
|
||||
bool closeClicked = false;
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
ImVec2 winPos = ImGui::GetWindowPos();
|
||||
float winWidth = ImGui::GetWindowWidth();
|
||||
float barHeight = 36.0f;
|
||||
|
||||
// Get accent color from theme if not provided
|
||||
if (!accent_col) {
|
||||
accent_col = schema::UI().resolveColor("var(--primary)", IM_COL32(76, 175, 80, 255));
|
||||
}
|
||||
|
||||
// Draw title bar background with subtle gradient
|
||||
ImVec2 barMin = winPos;
|
||||
ImVec2 barMax(winPos.x + winWidth, winPos.y + barHeight);
|
||||
|
||||
// Slightly darker top edge
|
||||
ImU32 barTop = IM_COL32(0, 0, 0, 40);
|
||||
ImU32 barBot = IM_COL32(0, 0, 0, 20);
|
||||
dl->AddRectFilledMultiColor(barMin, barMax, barTop, barTop, barBot, barBot);
|
||||
|
||||
// Accent line at bottom of title bar
|
||||
dl->AddLine(ImVec2(barMin.x, barMax.y), ImVec2(barMax.x, barMax.y),
|
||||
ScaleAlpha(accent_col, 0.6f), 1.0f);
|
||||
|
||||
// Title text
|
||||
ImFont* titleFont = Type().subtitle1();
|
||||
ImGui::PushFont(titleFont);
|
||||
ImVec2 titleSize = ImGui::CalcTextSize(title);
|
||||
float titleX = barMin.x + 16.0f;
|
||||
float titleY = barMin.y + (barHeight - titleSize.y) * 0.5f;
|
||||
DrawTextShadow(dl, ImVec2(titleX, titleY), OnSurface(), title);
|
||||
ImGui::PopFont();
|
||||
|
||||
// Close button (X) on right side
|
||||
if (p_open) {
|
||||
float btnSize = 24.0f;
|
||||
float btnX = barMax.x - btnSize - 12.0f;
|
||||
float btnY = barMin.y + (barHeight - btnSize) * 0.5f;
|
||||
ImVec2 btnMin(btnX, btnY);
|
||||
ImVec2 btnMax(btnX + btnSize, btnY + btnSize);
|
||||
|
||||
bool hovered = ImGui::IsMouseHoveringRect(btnMin, btnMax);
|
||||
bool held = false;
|
||||
if (hovered && ImGui::IsMouseClicked(0)) {
|
||||
held = true;
|
||||
}
|
||||
|
||||
// Button background on hover
|
||||
if (hovered) {
|
||||
dl->AddRectFilled(btnMin, btnMax, IM_COL32(255, 255, 255, held ? 40 : 25), 4.0f);
|
||||
}
|
||||
|
||||
// Draw X icon
|
||||
ImGui::PushFont(Type().iconSmall());
|
||||
ImVec2 iconSize = ImGui::CalcTextSize(ICON_MD_CLOSE);
|
||||
float iconX = btnX + (btnSize - iconSize.x) * 0.5f;
|
||||
float iconY = btnY + (btnSize - iconSize.y) * 0.5f;
|
||||
dl->AddText(ImVec2(iconX, iconY),
|
||||
hovered ? IM_COL32(255, 255, 255, 255) : OnSurfaceMedium(),
|
||||
ICON_MD_CLOSE);
|
||||
ImGui::PopFont();
|
||||
|
||||
// Handle click
|
||||
if (hovered && ImGui::IsMouseReleased(0)) {
|
||||
*p_open = false;
|
||||
closeClicked = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Reserve space for title bar so content starts below it
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + barHeight + 8.0f);
|
||||
|
||||
return closeClicked;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Fullscreen Overlay Dialog
|
||||
// ============================================================================
|
||||
// Creates a fullscreen semi-transparent overlay with a centered card dialog.
|
||||
// Similar to the shutdown screen pattern but for interactive dialogs.
|
||||
|
||||
inline bool BeginOverlayDialog(const char* title, bool* p_open, float cardWidth = 460.0f, float scrimOpacity = 0.92f)
|
||||
{
|
||||
ImGuiViewport* vp = ImGui::GetMainViewport();
|
||||
ImVec2 vp_pos = vp->Pos;
|
||||
ImVec2 vp_size = vp->Size;
|
||||
|
||||
// Fullscreen scrim overlay
|
||||
ImGui::SetNextWindowPos(vp_pos);
|
||||
ImGui::SetNextWindowSize(vp_size);
|
||||
ImGui::SetNextWindowFocus();
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.04f, 0.04f, 0.06f, scrimOpacity));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||
|
||||
bool opened = ImGui::Begin("##OverlayScrim", nullptr,
|
||||
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar |
|
||||
ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoNav |
|
||||
ImGuiWindowFlags_NoSavedSettings);
|
||||
|
||||
if (!opened) {
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::PopStyleColor();
|
||||
return false;
|
||||
}
|
||||
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
|
||||
// Calculate card position (centered)
|
||||
float cardX = vp_pos.x + (vp_size.x - cardWidth) * 0.5f;
|
||||
float cardY = vp_pos.y + vp_size.y * 0.15f;
|
||||
|
||||
// Draw glass card background
|
||||
ImVec2 cardMin(cardX, cardY);
|
||||
ImVec2 cardMax(cardX + cardWidth, vp_pos.y + vp_size.y * 0.85f);
|
||||
|
||||
// Card background with glass effect
|
||||
GlassPanelSpec cardGlass;
|
||||
cardGlass.rounding = 16.0f;
|
||||
cardGlass.fillAlpha = 35;
|
||||
cardGlass.borderAlpha = 50;
|
||||
cardGlass.borderWidth = 1.0f;
|
||||
DrawGlassPanel(dl, cardMin, cardMax, cardGlass);
|
||||
|
||||
// Set up child region for card content
|
||||
ImGui::SetCursorScreenPos(ImVec2(cardX, cardY));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 16.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(28, 24));
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0, 0, 0, 0)); // Transparent - glass already drawn
|
||||
|
||||
bool childVisible = ImGui::BeginChild("##OverlayDialogContent",
|
||||
ImVec2(cardWidth, 0), // 0 height = auto-size
|
||||
ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysUseWindowPadding,
|
||||
ImGuiWindowFlags_NoScrollbar);
|
||||
|
||||
// Draw title bar with close button
|
||||
if (childVisible && title) {
|
||||
DrawDialogTitleBar(title, p_open);
|
||||
}
|
||||
|
||||
return childVisible;
|
||||
}
|
||||
|
||||
inline void EndOverlayDialog()
|
||||
{
|
||||
ImGui::EndChild();
|
||||
ImGui::PopStyleColor(); // ChildBg
|
||||
ImGui::PopStyleVar(2); // ChildRounding, WindowPadding (for child)
|
||||
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar(3); // WindowRounding, WindowBorderSize, WindowPadding (for scrim)
|
||||
ImGui::PopStyleColor(); // WindowBg scrim
|
||||
}
|
||||
|
||||
} // namespace material
|
||||
} // namespace ui
|
||||
} // namespace dragonx
|
||||
|
||||
Reference in New Issue
Block a user