Refactor app services and stabilize refresh/UI flows
- Add refresh scheduler and network refresh service boundaries for typed refresh results, ordered RPC collectors, applicators, and price parsing. - Add daemon lifecycle and wallet security workflow helpers while preserving App-owned command RPC, decrypt, cancellation, and UI handoff behavior. - Split balance, console, mining, amount formatting, and async task logic into focused modules with expanded Phase 4 test coverage. - Fix market price loading by triggering price refresh immediately, avoiding queue-pressure drops, tracking loading/error state, and adding translations. - Polish send, explorer, peers, settings, theme/schema, and related tab UI. - Replace checked-in generated language headers with build-generated resources. - Document the cleanup audit, UI static-state guidance, and architecture updates.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
namespace dragonx {
|
||||
namespace ui {
|
||||
@@ -916,7 +917,7 @@ inline bool DrawDialogTitleBar(const char* title, bool* p_open, ImU32 accent_col
|
||||
// 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,
|
||||
float cardBottomViewportRatio = 0.85f)
|
||||
float cardBottomViewportRatio = 0.85f, const char* idSuffix = nullptr)
|
||||
{
|
||||
MarkOverlayDialogActive();
|
||||
|
||||
@@ -933,7 +934,16 @@ inline bool BeginOverlayDialog(const char* title, bool* p_open, float cardWidth
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||
|
||||
bool opened = ImGui::Begin("##OverlayScrim", nullptr,
|
||||
std::string scrimId = "##OverlayScrim";
|
||||
std::string childId = "##OverlayDialogContent";
|
||||
if (idSuffix && idSuffix[0] != '\0') {
|
||||
scrimId += "_";
|
||||
scrimId += idSuffix;
|
||||
childId += "_";
|
||||
childId += idSuffix;
|
||||
}
|
||||
|
||||
bool opened = ImGui::Begin(scrimId.c_str(), nullptr,
|
||||
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar |
|
||||
ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoNav |
|
||||
@@ -983,7 +993,7 @@ inline bool BeginOverlayDialog(const char* title, bool* p_open, float cardWidth
|
||||
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",
|
||||
bool childVisible = ImGui::BeginChild(childId.c_str(),
|
||||
ImVec2(cardWidth, 0), // 0 height = auto-size
|
||||
ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysUseWindowPadding,
|
||||
ImGuiWindowFlags_NoScrollbar);
|
||||
@@ -1007,6 +1017,23 @@ inline void EndOverlayDialog()
|
||||
ImGui::PopStyleColor(); // WindowBg scrim
|
||||
}
|
||||
|
||||
inline void PlaceOverlayDialogActions(float totalWidth)
|
||||
{
|
||||
float rowStartX = ImGui::GetCursorPosX();
|
||||
float contentW = ImGui::GetContentRegionAvail().x;
|
||||
ImGui::SetCursorPosX(rowStartX + std::max(0.0f, (contentW - totalWidth) * 0.5f));
|
||||
}
|
||||
|
||||
inline void BeginOverlayDialogFooter(float totalActionWidth, bool drawSeparator = true)
|
||||
{
|
||||
ImGui::Spacing();
|
||||
if (drawSeparator) {
|
||||
ImGui::Separator();
|
||||
ImGui::Spacing();
|
||||
}
|
||||
PlaceOverlayDialogActions(totalActionWidth);
|
||||
}
|
||||
|
||||
} // namespace material
|
||||
} // namespace ui
|
||||
} // namespace dragonx
|
||||
|
||||
115
src/ui/material/project_icons.h
Normal file
115
src/ui/material/project_icons.h
Normal file
@@ -0,0 +1,115 @@
|
||||
// DragonX Wallet - ImGui Edition
|
||||
// Copyright 2024-2026 The Hush Developers
|
||||
// Released under the GPLv3
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "typography.h"
|
||||
#include "../../embedded/IconsMaterialDesign.h"
|
||||
#include "imgui.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace dragonx {
|
||||
namespace ui {
|
||||
namespace material {
|
||||
namespace project_icons {
|
||||
|
||||
struct ProjectIcon {
|
||||
const char* name;
|
||||
const char* glyph;
|
||||
};
|
||||
|
||||
inline constexpr const char* kPickaxeName = "pickaxe";
|
||||
inline constexpr const char* kPickaxeGlyph = "\xEE\x80\x81";
|
||||
|
||||
inline constexpr ProjectIcon kWalletIcons[] = {
|
||||
{"savings", ICON_MD_SAVINGS}, {"account_balance", ICON_MD_ACCOUNT_BALANCE}, {"account_balance_wallet", ICON_MD_ACCOUNT_BALANCE_WALLET}, {"wallet", ICON_MD_WALLET},
|
||||
{"payments", ICON_MD_PAYMENTS}, {"credit_card", ICON_MD_CREDIT_CARD}, {"local_atm", ICON_MD_LOCAL_ATM}, {"diamond", ICON_MD_DIAMOND},
|
||||
{"attach_money", ICON_MD_ATTACH_MONEY}, {"currency_bitcoin", ICON_MD_CURRENCY_BITCOIN}, {"currency_exchange", ICON_MD_CURRENCY_EXCHANGE}, {"balance", ICON_MD_BALANCE},
|
||||
{"calculate", ICON_MD_CALCULATE}, {"trending_up", ICON_MD_TRENDING_UP}, {"euro", ICON_MD_EURO}, {"leaderboard", ICON_MD_LEADERBOARD},
|
||||
{"paid", ICON_MD_PAID}, {"sell", ICON_MD_SELL}, {"receipt", ICON_MD_RECEIPT}, {"percent", ICON_MD_PERCENT},
|
||||
{"price_change", ICON_MD_PRICE_CHANGE}, {"price_check", ICON_MD_PRICE_CHECK}, {"toll", ICON_MD_TOLL}, {"money", ICON_MD_MONEY},
|
||||
{"show_chart", ICON_MD_SHOW_CHART}, {"candlestick_chart", ICON_MD_CANDLESTICK_CHART}, {"bar_chart", ICON_MD_BAR_CHART}, {"pie_chart", ICON_MD_PIE_CHART},
|
||||
{"area_chart", ICON_MD_AREA_CHART}, {"stacked_bar_chart", ICON_MD_STACKED_BAR_CHART}, {"waterfall_chart", ICON_MD_WATERFALL_CHART}, {"scatter_plot", ICON_MD_SCATTER_PLOT},
|
||||
{"query_stats", ICON_MD_QUERY_STATS}, {"speed", ICON_MD_SPEED}, {"donut_large", ICON_MD_DONUT_LARGE},
|
||||
{kPickaxeName, nullptr},
|
||||
{"hardware", ICON_MD_HARDWARE}, {"construction", ICON_MD_CONSTRUCTION}, {"handyman", ICON_MD_HANDYMAN}, {"build", ICON_MD_BUILD},
|
||||
{"carpenter", ICON_MD_CARPENTER}, {"plumbing", ICON_MD_PLUMBING}, {"home_repair_service", ICON_MD_HOME_REPAIR_SERVICE}, {"precision_manufacturing", ICON_MD_PRECISION_MANUFACTURING},
|
||||
{"factory", ICON_MD_FACTORY}, {"warehouse", ICON_MD_WAREHOUSE}, {"inventory", ICON_MD_INVENTORY}, {"recycling", ICON_MD_RECYCLING},
|
||||
{"oil_barrel", ICON_MD_OIL_BARREL}, {"offline_bolt", ICON_MD_OFFLINE_BOLT}, {"thunderstorm", ICON_MD_THUNDERSTORM}, {"terminal", ICON_MD_TERMINAL},
|
||||
{"storage", ICON_MD_STORAGE}, {"memory", ICON_MD_MEMORY}, {"developer_board", ICON_MD_DEVELOPER_BOARD},
|
||||
{"shield", ICON_MD_SHIELD}, {"security", ICON_MD_SECURITY}, {"lock", ICON_MD_LOCK}, {"swap_horiz", ICON_MD_SWAP_HORIZ},
|
||||
{"verified", ICON_MD_VERIFIED}, {"verified_user", ICON_MD_VERIFIED_USER}, {"key", ICON_MD_KEY}, {"badge", ICON_MD_BADGE},
|
||||
{"store", ICON_MD_STORE}, {"storefront", ICON_MD_STOREFRONT}, {"shopping_bag", ICON_MD_SHOPPING_BAG}, {"business", ICON_MD_BUSINESS},
|
||||
{"work", ICON_MD_WORK}, {"real_estate_agent", ICON_MD_REAL_ESTATE_AGENT}, {"gavel", ICON_MD_GAVEL}, {"local_shipping", ICON_MD_LOCAL_SHIPPING},
|
||||
{"home", ICON_MD_HOME}, {"apartment", ICON_MD_APARTMENT}, {"cottage", ICON_MD_COTTAGE}, {"landscape", ICON_MD_LANDSCAPE},
|
||||
{"account_circle", ICON_MD_ACCOUNT_CIRCLE}, {"face", ICON_MD_FACE}, {"manage_accounts", ICON_MD_MANAGE_ACCOUNTS}, {"groups", ICON_MD_GROUPS}, {"mood", ICON_MD_MOOD},
|
||||
{"rocket_launch", ICON_MD_ROCKET_LAUNCH}, {"flight", ICON_MD_FLIGHT}, {"directions_car", ICON_MD_DIRECTIONS_CAR}, {"travel_explore", ICON_MD_TRAVEL_EXPLORE},
|
||||
{"explore", ICON_MD_EXPLORE}, {"location_on", ICON_MD_LOCATION_ON}, {"map", ICON_MD_MAP}, {"luggage", ICON_MD_LUGGAGE}, {"anchor", ICON_MD_ANCHOR},
|
||||
{"public", ICON_MD_PUBLIC}, {"language", ICON_MD_LANGUAGE}, {"forest", ICON_MD_FOREST}, {"park", ICON_MD_PARK},
|
||||
{"water_drop", ICON_MD_WATER_DROP}, {"beach_access", ICON_MD_BEACH_ACCESS}, {"energy_savings_leaf", ICON_MD_ENERGY_SAVINGS_LEAF}, {"solar_power", ICON_MD_SOLAR_POWER},
|
||||
{"favorite", ICON_MD_FAVORITE}, {"star", ICON_MD_STAR}, {"celebration", ICON_MD_CELEBRATION}, {"casino", ICON_MD_CASINO},
|
||||
{"auto_awesome", ICON_MD_AUTO_AWESOME}, {"emoji_events", ICON_MD_EMOJI_EVENTS}, {"military_tech", ICON_MD_MILITARY_TECH}, {"flag", ICON_MD_FLAG},
|
||||
{"bolt", ICON_MD_BOLT}, {"tungsten", ICON_MD_TUNGSTEN}, {"lightbulb", ICON_MD_LIGHTBULB}, {"insights", ICON_MD_INSIGHTS},
|
||||
{"hub", ICON_MD_HUB}, {"token", ICON_MD_TOKEN}, {"electric_bolt", ICON_MD_ELECTRIC_BOLT}, {"science", ICON_MD_SCIENCE}, {"biotech", ICON_MD_BIOTECH},
|
||||
{"category", ICON_MD_CATEGORY}, {"label", ICON_MD_LABEL}, {"school", ICON_MD_SCHOOL}, {"local_hospital", ICON_MD_LOCAL_HOSPITAL}, {"local_florist", ICON_MD_LOCAL_FLORIST},
|
||||
{"coffee", ICON_MD_LOCAL_CAFE}, {"restaurant", ICON_MD_RESTAURANT}, {"wine_bar", ICON_MD_WINE_BAR}, {"liquor", ICON_MD_LIQUOR},
|
||||
{"outdoor_grill", ICON_MD_OUTDOOR_GRILL}, {"nightlife", ICON_MD_NIGHTLIFE}, {"sports_bar", ICON_MD_SPORTS_BAR},
|
||||
{"pets", ICON_MD_PETS}, {"fitness_center", ICON_MD_FITNESS_CENTER}, {"spa", ICON_MD_SPA}, {"self_improvement", ICON_MD_SELF_IMPROVEMENT},
|
||||
{"psychology", ICON_MD_PSYCHOLOGY}, {"sports_soccer", ICON_MD_SPORTS_SOCCER}, {"sports_esports", ICON_MD_SPORTS_ESPORTS},
|
||||
{"hiking", ICON_MD_HIKING}, {"palette", ICON_MD_PALETTE}, {"museum", ICON_MD_MUSEUM}, {"church", ICON_MD_CHURCH}, {"surfing", ICON_MD_SURFING},
|
||||
{"redeem", ICON_MD_REDEEM}, {"handshake", ICON_MD_HANDSHAKE}, {"healing", ICON_MD_HEALING}, {"volunteer", ICON_MD_VOLUNTEER_ACTIVISM},
|
||||
{"stadium", ICON_MD_STADIUM}, {"temple_buddhist", ICON_MD_TEMPLE_BUDDHIST}, {"theater_comedy", ICON_MD_THEATER_COMEDY}, {"watch", ICON_MD_WATCH},
|
||||
};
|
||||
|
||||
inline int walletIconCount()
|
||||
{
|
||||
return static_cast<int>(sizeof(kWalletIcons) / sizeof(kWalletIcons[0]));
|
||||
}
|
||||
|
||||
inline const char* walletIconName(int index)
|
||||
{
|
||||
return (index >= 0 && index < walletIconCount()) ? kWalletIcons[index].name : "";
|
||||
}
|
||||
|
||||
inline const char* glyphForName(const std::string& name)
|
||||
{
|
||||
for (const auto& icon : kWalletIcons) {
|
||||
if (name == icon.name) return icon.glyph;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline bool drawByName(ImDrawList* drawList,
|
||||
const std::string& name,
|
||||
ImVec2 center,
|
||||
ImU32 color,
|
||||
ImFont* iconFont,
|
||||
float iconFontSize)
|
||||
{
|
||||
if (!drawList) return false;
|
||||
|
||||
if (name == kPickaxeName) {
|
||||
ImFont* pickaxeFont = Typography::instance().pickaxeFontForSize(iconFontSize);
|
||||
if (!pickaxeFont) return false;
|
||||
|
||||
ImVec2 iconSize = pickaxeFont->CalcTextSizeA(iconFontSize, 1000.0f, 0.0f, kPickaxeGlyph);
|
||||
drawList->AddText(pickaxeFont, iconFontSize,
|
||||
ImVec2(center.x - iconSize.x * 0.5f, center.y - iconSize.y * 0.5f), color, kPickaxeGlyph);
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* glyph = glyphForName(name);
|
||||
if (!glyph || !iconFont) return false;
|
||||
|
||||
ImVec2 iconSize = iconFont->CalcTextSizeA(iconFontSize, 1000.0f, 0.0f, glyph);
|
||||
drawList->AddText(iconFont, iconFontSize,
|
||||
ImVec2(center.x - iconSize.x * 0.5f, center.y - iconSize.y * 0.5f), color, glyph);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace project_icons
|
||||
} // namespace material
|
||||
} // namespace ui
|
||||
} // namespace dragonx
|
||||
Reference in New Issue
Block a user