diff --git a/CMakeLists.txt b/CMakeLists.txt index 08a00a7..3a4b7d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -474,10 +474,8 @@ set(APP_SOURCES src/ui/windows/shield_dialog.cpp src/ui/windows/request_payment_dialog.cpp src/ui/windows/block_info_dialog.cpp - src/ui/windows/import_key_dialog.cpp src/ui/windows/export_all_keys_dialog.cpp src/ui/windows/export_transactions_dialog.cpp - src/ui/windows/backup_wallet_dialog.cpp src/ui/widgets/qr_code.cpp src/rpc/rpc_client.cpp src/rpc/rpc_worker.cpp @@ -600,10 +598,8 @@ set(APP_HEADERS src/ui/windows/shield_dialog.h src/ui/windows/request_payment_dialog.h src/ui/windows/block_info_dialog.h - src/ui/windows/import_key_dialog.h src/ui/windows/export_all_keys_dialog.h src/ui/windows/export_transactions_dialog.h - src/ui/windows/backup_wallet_dialog.h src/ui/widgets/qr_code.h src/rpc/rpc_client.h src/rpc/rpc_worker.h diff --git a/src/app.cpp b/src/app.cpp index 650cbff..e0aaae4 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -2579,41 +2579,6 @@ void App::renderLiteUnlockPrompt() } } -void App::renderAboutDialog() -{ - auto dlg = ui::schema::UI().drawElement("inline-dialogs", "about"); - auto dlgF = [&](const char* key, float fb) -> float { - auto it = dlg.extraFloats.find(key); - return it != dlg.extraFloats.end() ? it->second : fb; - }; - - if (!ui::material::BeginOverlayDialog("About ObsidianDragon", &show_about_, dlgF("width", 400.0f), 0.94f)) { - return; - } - - ui::material::Type().text(ui::material::TypeStyle::H6, DRAGONX_APP_NAME); - ImGui::Dummy(ImVec2(0, ui::Layout::spacingSm())); - - ImGui::Text("Version: %s", DRAGONX_VERSION); - ImGui::Text("ImGui: %s", IMGUI_VERSION); - ImGui::Spacing(); - - ImGui::TextWrapped("A shielded cryptocurrency wallet for DragonX (DRGX), " - "built with Dear ImGui for a lightweight, portable experience."); - ImGui::Spacing(); - - ImGui::Text("Copyright 2024-2026 The Hush Developers"); - ImGui::Text("Released under the GPLv3 License"); - - ImGui::Spacing(); - ImGui::Separator(); - - if (ui::material::StyledButton("Close", ImVec2(dlgF("close-button-width", 120.0f), 0), ui::material::resolveButtonFont((int)dlgF("button-font", 1)))) { - show_about_ = false; - } - - ui::material::EndOverlayDialog(); -} void App::renderImportKeyDialog() { diff --git a/src/app.h b/src/app.h index 1c5318f..2803c02 100644 --- a/src/app.h +++ b/src/app.h @@ -839,7 +839,6 @@ private: // Private methods - rendering void renderStatusBar(); - void renderAboutDialog(); void renderLiteFirstRunPrompt(); // lite-only welcome modal when no wallet exists yet void renderLiteUnlockPrompt(); // lite-only send-time unlock modal void renderImportKeyDialog(); diff --git a/src/ui/windows/backup_wallet_dialog.cpp b/src/ui/windows/backup_wallet_dialog.cpp deleted file mode 100644 index e2470a6..0000000 --- a/src/ui/windows/backup_wallet_dialog.cpp +++ /dev/null @@ -1,189 +0,0 @@ -// DragonX Wallet - ImGui Edition -// Copyright 2024-2026 The Hush Developers -// Released under the GPLv3 - -#include "backup_wallet_dialog.h" -#include "../../app.h" -#include "../../rpc/rpc_client.h" -#include "../../rpc/rpc_worker.h" -#include "../../util/i18n.h" -#include "../../util/platform.h" -#include "../notifications.h" -#include "../schema/ui_schema.h" -#include "../material/draw_helpers.h" -#include "../theme.h" -#include "imgui.h" - -#include -#include -#include -#include - -namespace dragonx { -namespace ui { - -namespace fs = std::filesystem; -using json = nlohmann::json; - -// Static state -static bool s_open = false; -static char s_destination[512] = ""; -static std::string s_status; -static bool s_backing_up = false; - -void BackupWalletDialog::show() -{ - s_open = true; - s_status.clear(); - s_backing_up = false; - - // Generate default destination with timestamp - std::time_t now = std::time(nullptr); - char timebuf[32]; - std::strftime(timebuf, sizeof(timebuf), "%Y%m%d_%H%M%S", std::localtime(&now)); - - // Default to home directory - std::string home = util::Platform::getHomeDir(); - snprintf(s_destination, sizeof(s_destination), "%s/wallet_backup_%s.dat", home.c_str(), timebuf); -} - -bool BackupWalletDialog::isOpen() -{ - return s_open; -} - -void BackupWalletDialog::render(App* app) -{ - if (!s_open) return; - - auto& S = schema::UI(); - auto win = S.window("dialogs.backup-wallet"); - auto backupBtn = S.button("dialogs.backup-wallet", "backup-button"); - auto closeBtn = S.button("dialogs.backup-wallet", "close-button"); - - if (material::BeginOverlayDialog(TR("backup_title"), &s_open, win.width, 0.94f)) { - ImGui::TextWrapped("%s", TR("backup_description")); - - ImGui::Spacing(); - ImGui::Separator(); - ImGui::Spacing(); - - if (s_backing_up) { - ImGui::BeginDisabled(); - } - - // Destination path - ImGui::Text("%s", TR("backup_destination")); - ImGui::SetNextItemWidth(-1); - ImGui::InputText("##Destination", s_destination, sizeof(s_destination)); - - ImGui::Spacing(); - - // Show wallet.dat location - std::string walletPath = util::Platform::getDataDir() + "/wallet.dat"; - ImGui::TextDisabled(TR("backup_source"), walletPath.c_str()); - - // Check if source exists - bool sourceExists = fs::exists(walletPath); - if (!sourceExists) { - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.4f, 0.4f, 1.0f)); - ImGui::Text("%s", TR("backup_wallet_not_found")); - ImGui::PopStyleColor(); - } - - if (s_backing_up) { - ImGui::EndDisabled(); - } - - ImGui::Spacing(); - ImGui::Separator(); - ImGui::Spacing(); - - // Backup button - use RPC backupwallet - if (s_backing_up) { - ImGui::BeginDisabled(); - } - - if (material::StyledButton(TR("backup_create"), ImVec2(backupBtn.width, 0), S.resolveFont(backupBtn.font))) { - if (strlen(s_destination) == 0) { - Notifications::instance().warning("Please enter a destination path"); - } else if (!app->rpc() || !app->rpc()->isConnected()) { - Notifications::instance().error("Not connected to daemon"); - } else { - s_backing_up = true; - s_status = "Creating backup..."; - - // Run backup on worker thread to avoid freezing UI - std::string dest(s_destination); - if (app->worker()) { - app->worker()->post([rpc = app->rpc(), dest]() -> rpc::RPCWorker::MainCb { - bool success = false; - std::string statusMsg; - try { - rpc::RPCClient::TraceScope trace("Settings / Backup wallet"); - rpc->call("backupwallet", json::array({dest})); - // Check if file was created - if (fs::exists(dest)) { - auto size = fs::file_size(dest); - char sizebuf[32]; - if (size > 1024 * 1024) { - snprintf(sizebuf, sizeof(sizebuf), "%.2f MB", size / (1024.0 * 1024.0)); - } else if (size > 1024) { - snprintf(sizebuf, sizeof(sizebuf), "%.2f KB", size / 1024.0); - } else { - snprintf(sizebuf, sizeof(sizebuf), "%zu bytes", size); - } - statusMsg = std::string("Backup created successfully (") + sizebuf + ")"; - success = true; - } else { - statusMsg = "Backup may have failed - file not found"; - } - } catch (const std::exception& e) { - statusMsg = std::string("Backup failed: ") + e.what(); - } - return [success, statusMsg]() { - s_status = statusMsg; - s_backing_up = false; - if (success) { - Notifications::instance().success(TR("backup_created"), 5.0f); - } else { - Notifications::instance().warning(statusMsg); - } - }; - }); - } - } - } - - if (s_backing_up) { - ImGui::EndDisabled(); - ImGui::SameLine(); - ImGui::TextDisabled("%s", TR("backup_backing_up")); - } - - ImGui::SameLine(); - if (material::StyledButton(TR("close"), ImVec2(closeBtn.width, 0), S.resolveFont(closeBtn.font))) { - s_open = false; - } - - // Status - if (!s_status.empty()) { - ImGui::Spacing(); - ImGui::TextWrapped("%s", s_status.c_str()); - } - - ImGui::Spacing(); - ImGui::Separator(); - ImGui::Spacing(); - - // Tips - ImGui::TextDisabled("%s", TR("backup_tips")); - ImGui::BulletText("%s", TR("backup_tip_external")); - ImGui::BulletText("%s", TR("backup_tip_multiple")); - ImGui::BulletText("%s", TR("backup_tip_test")); - material::EndOverlayDialog(); - } -} - -} // namespace ui -} // namespace dragonx diff --git a/src/ui/windows/backup_wallet_dialog.h b/src/ui/windows/backup_wallet_dialog.h deleted file mode 100644 index 8f5d96e..0000000 --- a/src/ui/windows/backup_wallet_dialog.h +++ /dev/null @@ -1,31 +0,0 @@ -// DragonX Wallet - ImGui Edition -// Copyright 2024-2026 The Hush Developers -// Released under the GPLv3 - -#pragma once - -#include - -namespace dragonx { - -class App; - -namespace ui { - -/** - * @brief Dialog for backing up wallet.dat - */ -class BackupWalletDialog { -public: - // Show the dialog - static void show(); - - // Render the dialog (call each frame) - static void render(App* app); - - // Check if dialog is open - static bool isOpen(); -}; - -} // namespace ui -} // namespace dragonx diff --git a/src/ui/windows/import_key_dialog.cpp b/src/ui/windows/import_key_dialog.cpp deleted file mode 100644 index 1f5afc3..0000000 --- a/src/ui/windows/import_key_dialog.cpp +++ /dev/null @@ -1,412 +0,0 @@ -// DragonX Wallet - ImGui Edition -// Copyright 2024-2026 The Hush Developers -// Released under the GPLv3 - -#include "import_key_dialog.h" -#include "../../app.h" -#include "../../rpc/rpc_client.h" -#include "../../rpc/rpc_worker.h" -#include "../../util/i18n.h" -#include "../notifications.h" -#include "../schema/ui_schema.h" -#include "../material/draw_helpers.h" -#include "../material/type.h" -#include "../../embedded/IconsMaterialDesign.h" -#include "imgui.h" - -#include -#include -#include - -namespace dragonx { -namespace ui { - -using json = nlohmann::json; - -// Static state -static bool s_open = false; -static char s_key_input[4096] = ""; -static bool s_rescan = true; -static int s_rescan_height = 0; // 0 = full rescan -static bool s_importing = false; -static std::string s_status; -static int s_total_keys = 0; -static int s_imported_keys = 0; -static int s_failed_keys = 0; -static bool s_paste_previewing = false; -static std::string s_preview_text; - -// Helper to detect key type -static std::string detectKeyType(const std::string& key) -{ - if (key.empty()) return "unknown"; - - // Z-address spending keys start with "secret-extended-key-" or "SK" prefix patterns - if (key.substr(0, 20) == "secret-extended-key-") { - return "z-spending"; - } - - // Legacy z-addr keys (SK prefix) - if (key.length() >= 2 && key[0] == 'S' && key[1] == 'K') { - return "z-spending"; - } - - // T-address private keys (WIF format) - start with 5, K, or L for Bitcoin-derived - // DragonX/HUSH uses different prefixes - if (key.length() >= 51 && key.length() <= 52) { - char first = key[0]; - if (first == '5' || first == 'K' || first == 'L' || first == 'U') { - return "t-privkey"; - } - } - - return "unknown"; -} - -// Helper to split input into individual keys -static std::vector splitKeys(const std::string& input) -{ - std::vector keys; - std::istringstream stream(input); - std::string line; - - while (std::getline(stream, line)) { - // Trim whitespace - size_t start = line.find_first_not_of(" \t\r\n"); - size_t end = line.find_last_not_of(" \t\r\n"); - - if (start != std::string::npos && end != std::string::npos) { - std::string key = line.substr(start, end - start + 1); - if (!key.empty() && key[0] != '#') { // Skip comments - keys.push_back(key); - } - } - } - - return keys; -} - -void ImportKeyDialog::show() -{ - s_open = true; - s_key_input[0] = '\0'; - s_rescan = true; - s_rescan_height = 0; - s_importing = false; - s_status.clear(); - s_total_keys = 0; - s_imported_keys = 0; - s_failed_keys = 0; - s_paste_previewing = false; - s_preview_text.clear(); -} - -bool ImportKeyDialog::isOpen() -{ - return s_open; -} - -void ImportKeyDialog::render(App* app) -{ - if (!s_open) return; - - auto& S = schema::UI(); - auto win = S.window("dialogs.import-key"); - auto keyInput = S.input("dialogs.import-key", "key-input"); - auto rescanInput = S.input("dialogs.import-key", "rescan-height-input"); - auto importBtn = S.button("dialogs.import-key", "import-button"); - auto closeBtn = S.button("dialogs.import-key", "close-button"); - - if (material::BeginOverlayDialog(TR("import_key_title"), &s_open, win.width, 0.94f)) { - // Warning - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.8f, 0.0f, 1.0f)); - ImGui::PushFont(material::Type().iconSmall()); - ImGui::Text(ICON_MD_WARNING); - ImGui::PopFont(); - ImGui::SameLine(0, 4.0f); - ImGui::TextWrapped("%s", TR("import_key_warning")); - ImGui::PopStyleColor(); - - ImGui::Spacing(); - ImGui::Separator(); - ImGui::Spacing(); - - // Key input - ImGui::Text("%s", TR("import_key_label")); - ImGui::SameLine(); - ImGui::TextDisabled("(?)"); - if (ImGui::IsItemHovered()) { - material::Tooltip("%s", TR("import_key_tooltip")); - } - - // Validation indicator inline with title — check preview text during hover, - // otherwise check the actual input - { - const char* checkSrc = s_key_input; - if (s_paste_previewing && !s_preview_text.empty()) - checkSrc = s_preview_text.c_str(); - if (checkSrc[0] != '\0') { - auto previewKeys = splitKeys(checkSrc); - int pz = 0, pt = 0, pu = 0; - for (const auto& k : previewKeys) { - std::string kt = detectKeyType(k); - if (kt == "z-spending") pz++; - else if (kt == "t-privkey") pt++; - else pu++; - } - if (pz > 0 || pt > 0) { - ImGui::SameLine(); - char vbuf[128]; - if (pz > 0 && pt > 0) - snprintf(vbuf, sizeof(vbuf), "%d shielded, %d transparent", pz, pt); - else if (pz > 0) - snprintf(vbuf, sizeof(vbuf), "%d shielded key(s)", pz); - else - snprintf(vbuf, sizeof(vbuf), "%d transparent key(s)", pt); - material::Type().textColored(material::TypeStyle::Caption, material::Success(), vbuf); - if (pu > 0) { - ImGui::SameLine(); - snprintf(vbuf, sizeof(vbuf), "(%d unrecognized)", pu); - material::Type().textColored(material::TypeStyle::Caption, material::Error(), vbuf); - } - } else if (pu > 0 && !s_paste_previewing) { - ImGui::SameLine(); - material::Type().textColored(material::TypeStyle::Caption, material::Error(), "Unrecognized key format"); - } - } - } - - if (s_importing) { - ImGui::BeginDisabled(); - } - - ImGui::SetNextItemWidth(-1); - ImGui::InputTextMultiline("##KeyInput", s_key_input, sizeof(s_key_input), - ImVec2(-1, keyInput.height > 0 ? keyInput.height : 150), ImGuiInputTextFlags_AllowTabInput); - ImVec2 inputMin = ImGui::GetItemRectMin(); - ImVec2 inputMax = ImGui::GetItemRectMax(); - - // Detect paste button hover before drawing it - ImVec2 pasteBtnPos = ImGui::GetCursorScreenPos(); - // Estimate button size for hover detection - ImFont* btnFont = S.resolveFont(importBtn.font); - ImVec2 pasteBtnSize = btnFont - ? ImVec2(btnFont->CalcTextSizeA(btnFont->LegacySize, FLT_MAX, 0, TR("paste_from_clipboard")).x - + ImGui::GetStyle().FramePadding.x * 2, - ImGui::GetFrameHeight()) - : ImVec2(150, ImGui::GetFrameHeight()); - bool paste_hovered = material::IsRectHovered(pasteBtnPos, - ImVec2(pasteBtnPos.x + pasteBtnSize.x, pasteBtnPos.y + pasteBtnSize.y)); - - // Handle preview state - if (paste_hovered && !s_paste_previewing) { - const char* clip = ImGui::GetClipboardText(); - if (clip && clip[0] != '\0') { - std::string trimmed(clip); - while (!trimmed.empty() && (trimmed.front() == ' ' || trimmed.front() == '\t' || - trimmed.front() == '\n' || trimmed.front() == '\r')) - trimmed.erase(trimmed.begin()); - while (!trimmed.empty() && (trimmed.back() == ' ' || trimmed.back() == '\t' || - trimmed.back() == '\n' || trimmed.back() == '\r')) - trimmed.pop_back(); - if (!trimmed.empty() && s_key_input[0] == '\0') { - s_preview_text = trimmed; - s_paste_previewing = true; - } - } - } else if (!paste_hovered && s_paste_previewing) { - s_paste_previewing = false; - s_preview_text.clear(); - } - - // Draw transparent preview text overlay on the input field - if (s_paste_previewing && !s_preview_text.empty()) { - ImVec2 textPos(inputMin.x + ImGui::GetStyle().FramePadding.x, - inputMin.y + ImGui::GetStyle().FramePadding.y); - ImVec4 previewCol = ImGui::GetStyleColorVec4(ImGuiCol_Text); - previewCol.w = S.drawElement("dialogs.import-key", "paste-preview-alpha").sizeOr(0.3f); - size_t maxChars = (size_t)S.drawElement("dialogs.import-key", "paste-preview-max-chars").sizeOr(200.0f); - // Clip to input rect - ImGui::GetWindowDrawList()->PushClipRect(inputMin, inputMax, true); - ImGui::GetWindowDrawList()->AddText(textPos, ImGui::ColorConvertFloat4ToU32(previewCol), - s_preview_text.c_str(), s_preview_text.c_str() + std::min(s_preview_text.size(), maxChars)); - ImGui::GetWindowDrawList()->PopClipRect(); - } - - // Paste button - if (material::StyledButton(TR("paste_from_clipboard"), ImVec2(0,0), S.resolveFont(importBtn.font))) { - if (s_paste_previewing) { - snprintf(s_key_input, sizeof(s_key_input), "%s", s_preview_text.c_str()); - s_paste_previewing = false; - s_preview_text.clear(); - } else { - const char* clipboard = ImGui::GetClipboardText(); - if (clipboard) { - std::string trimmed(clipboard); - while (!trimmed.empty() && (trimmed.front() == ' ' || trimmed.front() == '\t' || - trimmed.front() == '\n' || trimmed.front() == '\r')) - trimmed.erase(trimmed.begin()); - while (!trimmed.empty() && (trimmed.back() == ' ' || trimmed.back() == '\t' || - trimmed.back() == '\n' || trimmed.back() == '\r')) - trimmed.pop_back(); - snprintf(s_key_input, sizeof(s_key_input), "%s", trimmed.c_str()); - } - } - } - - ImGui::SameLine(); - if (material::StyledButton(TR("clear"), ImVec2(0,0), S.resolveFont(importBtn.font))) { - s_key_input[0] = '\0'; - s_paste_previewing = false; - s_preview_text.clear(); - } - - ImGui::Spacing(); - - // Rescan options - ImGui::Checkbox(TR("import_key_rescan"), &s_rescan); - - if (s_rescan) { - ImGui::Indent(); - ImGui::Text("%s", TR("import_key_start_height")); - ImGui::SameLine(); - ImGui::SetNextItemWidth(rescanInput.width); - ImGui::InputInt("##RescanHeight", &s_rescan_height); - if (s_rescan_height < 0) s_rescan_height = 0; - ImGui::SameLine(); - ImGui::TextDisabled("%s", TR("import_key_full_rescan")); - ImGui::Unindent(); - } - - if (s_importing) { - ImGui::EndDisabled(); - } - - ImGui::Spacing(); - ImGui::Separator(); - ImGui::Spacing(); - - // Import button - if (s_importing) { - ImGui::BeginDisabled(); - } - - if (material::StyledButton(TR("import_key_btn"), ImVec2(importBtn.width, 0), S.resolveFont(importBtn.font))) { - auto keys = splitKeys(s_key_input); - - if (keys.empty()) { - Notifications::instance().warning(TR("import_key_no_valid")); - } else if (!app->rpc() || !app->rpc()->isConnected()) { - Notifications::instance().error(TR("not_connected")); - } else { - s_importing = true; - s_total_keys = static_cast(keys.size()); - s_imported_keys = 0; - s_failed_keys = 0; - s_status = "Importing..."; - - // Import keys on worker thread to avoid freezing UI - bool rescan = s_rescan; - int rescanHeight = s_rescan_height; - if (app->worker()) { - app->worker()->post([app, rpc = app->rpc(), keys, rescan, rescanHeight]() -> rpc::RPCWorker::MainCb { - int imported = 0; - int failed = 0; - - for (const auto& key : keys) { - std::string keyType = detectKeyType(key); - - try { - rpc::RPCClient::TraceScope trace("Settings / Import private keys"); - if (keyType == "z-spending") { - // z_importkey "key" "yes"|"no" startheight - if (rescan && rescanHeight > 0) { - rpc->call("z_importkey", {key, "yes", rescanHeight}); - } else { - rpc->call("z_importkey", {key, rescan ? "yes" : "no"}); - } - imported++; - } else if (keyType == "t-privkey") { - // importprivkey does not accept a startheight; - // import without rescan, then rescanblockchain - // from the requested height afterward. - if (rescan && rescanHeight > 0) { - rpc->call("importprivkey", {key, "", false}); - } else { - rpc->call("importprivkey", {key, "", rescan}); - } - imported++; - } else { - failed++; - } - } catch (...) { - failed++; - } - } - - // If t-keys were imported without rescan (because a - // specific start height was requested), trigger a - // single rescanblockchain from that height now. - if (rescan && rescanHeight > 0 && imported > 0) { - try { - rpc::RPCClient::TraceScope trace("Settings / Import private keys"); - rpc->call("rescanblockchain", {rescanHeight}); - } catch (...) { - // rescan failure is non-fatal; user can retry - } - } - - return [app, imported, failed]() { - s_imported_keys = imported; - s_failed_keys = failed; - s_importing = false; - char buf[128]; - snprintf(buf, sizeof(buf), "Import complete: %d success, %d failed", - imported, failed); - s_status = buf; - if (imported > 0) { - app->invalidateAddressValidationCache(); - app->refreshNow(); - Notifications::instance().success(TR("import_key_success"), 5.0f); - } - }; - }); - } - } - } - - if (s_importing) { - ImGui::EndDisabled(); - ImGui::SameLine(); - ImGui::TextDisabled(TR("import_key_progress"), s_imported_keys + s_failed_keys, s_total_keys); - } - - ImGui::SameLine(); - if (material::StyledButton(TR("close"), ImVec2(closeBtn.width, 0), S.resolveFont(closeBtn.font))) { - s_open = false; - } - - // Status - if (!s_status.empty()) { - ImGui::Spacing(); - bool success = s_failed_keys == 0 && !s_importing; - ImGui::TextColored( - success ? ImVec4(0.2f, 0.8f, 0.2f, 1.0f) : ImVec4(1.0f, 0.8f, 0.0f, 1.0f), - "%s", s_status.c_str() - ); - } - - ImGui::Spacing(); - ImGui::Separator(); - ImGui::Spacing(); - - // Help text - ImGui::TextDisabled("%s", TR("import_key_formats")); - ImGui::BulletText("%s", TR("import_key_z_format")); - ImGui::BulletText("%s", TR("import_key_t_format")); - material::EndOverlayDialog(); - } -} - -} // namespace ui -} // namespace dragonx diff --git a/src/ui/windows/import_key_dialog.h b/src/ui/windows/import_key_dialog.h deleted file mode 100644 index c2ae4a5..0000000 --- a/src/ui/windows/import_key_dialog.h +++ /dev/null @@ -1,36 +0,0 @@ -// DragonX Wallet - ImGui Edition -// Copyright 2024-2026 The Hush Developers -// Released under the GPLv3 - -#pragma once - -#include - -namespace dragonx { - -class App; - -namespace ui { - -/** - * @brief Dialog for importing private keys - * - * Supports importing: - * - Z-address private keys (z_importkey) - * - T-address private keys (importprivkey) - * - Batch import (multiple keys, one per line) - */ -class ImportKeyDialog { -public: - // Show the dialog - static void show(); - - // Render the dialog (call each frame) - static void render(App* app); - - // Check if dialog is open - static bool isOpen(); -}; - -} // namespace ui -} // namespace dragonx