feat(ui): in-app FAQ, DPI-scaling audit fixes, mining/stratum polish + localize strings

Bundles the session's UI work (the touched files carry several of these
changes together, so they are committed as one coherent UI batch):

- FAQ: new RenderFaqDialog + data-driven faq_content, opened from a
  status-bar "?" (and the Windows title bar), styled like the Wallets
  modal with search, Wallet/Daemon tabs, and smooth scroll.
- DPI/font-scale audit: multiply hand-drawn absolute geometry by
  Layout::dpiScale() across ~30 files so nothing renders native-size at
  HiDPI / font_scale 1.5 (verified with a full sweep at 1.5x).
- Mining: chart now fills the horizontal space; thread stepper +/- buttons
  match the input-box height; move the stratum-host toggle into
  Node & Security (v1.3.0+).
- Settings: fix the auto-shield status text overlapping the grid.
- Sidebar: drop the peer-count badge on the Network button.
- i18n: wrap 193 hardcoded literals with TR() (keys/translations added in
  the preceding i18n commit), so the security/PIN/lock flow, seed-backup
  wizard, and witness-rebuild dialog localize.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-01 19:37:16 -05:00
co-authored by Claude Opus 4.8
parent ed675f90d8
commit d27f387d6d
35 changed files with 867 additions and 366 deletions
+12 -12
View File
@@ -216,7 +216,7 @@ void RenderSettingsWindow(App* app, bool* p_open)
if (!skin.valid) {
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.3f, 0.3f, 1.0f));
ImGui::BeginDisabled(true);
std::string label = skin.name + " (invalid)";
std::string label = skin.name + TR("swin_invalid_suffix");
ImGui::Selectable(label.c_str(), false);
ImGui::EndDisabled();
ImGui::PopStyleColor();
@@ -261,7 +261,7 @@ void RenderSettingsWindow(App* app, bool* p_open)
ImGui::PushFont(material::Type().iconSmall());
if (material::StyledButton(ICON_REFRESH_THEMES, ImVec2(0, 0))) {
skinMgr.refresh();
Notifications::instance().info("Theme list refreshed");
Notifications::instance().info(TR("swin_theme_list_refreshed"));
}
ImGui::PopFont();
if (ImGui::IsItemHovered()) {
@@ -425,14 +425,14 @@ void RenderSettingsWindow(App* app, bool* p_open)
app->rpc()->getInfo([](const nlohmann::json& result, const std::string& error) {
if (error.empty()) {
std::string version = result.value("version", "unknown");
std::string msg = "Connection successful!\ndragonxd version: " + version;
std::string msg = std::string(TR("swin_connection_successful")) + version;
Notifications::instance().success(msg);
} else {
Notifications::instance().error("Connection failed: " + error);
Notifications::instance().error(std::string(TR("swin_connection_failed")) + error);
}
});
} else {
Notifications::instance().error("RPC client not initialized");
Notifications::instance().error(TR("swin_rpc_client_not_initialized"));
}
}
@@ -455,15 +455,15 @@ void RenderSettingsWindow(App* app, bool* p_open)
if (error.empty()) {
int start = result.value("start_height", 0);
int end = result.value("stop_height", 0);
std::string msg = "Rescan started from block " + std::to_string(start) +
" to " + std::to_string(end);
std::string msg = std::string(TR("swin_rescan_started_from_block")) + std::to_string(start) +
TR("swin_rescan_to") + std::to_string(end);
Notifications::instance().success(msg);
} else {
Notifications::instance().error("Rescan failed: " + error);
Notifications::instance().error(std::string(TR("swin_rescan_failed")) + error);
}
});
} else {
Notifications::instance().error("RPC client not initialized");
Notifications::instance().error(TR("swin_rpc_client_not_initialized"));
}
}
ImGui::TextDisabled(" %s", TR("settings_rescan_desc"));
@@ -503,9 +503,9 @@ void RenderSettingsWindow(App* app, bool* p_open)
if (doConfirm) {
std::string ztx_file = util::Platform::getDragonXDataDir() + "ztx_history.json";
if (util::Platform::deleteFile(ztx_file)) {
Notifications::instance().success("Z-transaction history cleared");
Notifications::instance().success(TR("swin_ztx_history_cleared"));
} else {
Notifications::instance().info("No history file found");
Notifications::instance().info(TR("swin_no_history_file_found"));
}
s_confirm_clear_ztx = false;
}
@@ -568,7 +568,7 @@ void RenderSettingsWindow(App* app, bool* p_open)
// Save/Cancel buttons
if (material::StyledButton(TR("save"), ImVec2(saveBtn.width, 0), S.resolveFont(saveBtn.font))) {
saveSettingsFromUI(app->settings());
Notifications::instance().success("Settings saved");
Notifications::instance().success(TR("swin_settings_saved"));
*p_open = false;
}
ImGui::SameLine();