feat(settings): migrate Backup Wallet modal to the reference design

Phase 1. Struct-form BlurFloat overlay (was the legacy positional overload);
DialogWarningHeader care header; centered DialogActionFooter (Create Backup +
Close) replacing the StyledButtons + separator; full i18n — title/destination/
button reuse existing backup_* keys, plus two new keys (backup_warn one-line care
line, backup_overwrite_confirm) added in en + 8 langs. No change to backupWallet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-13 21:37:58 -05:00
parent bf81ec1702
commit 22638b094c
11 changed files with 49 additions and 35 deletions

Binary file not shown.

View File

@@ -62,6 +62,7 @@
"backup_data": "SICHERUNG & DATEN", "backup_data": "SICHERUNG & DATEN",
"backup_description": "Erstellen Sie eine Sicherung Ihrer wallet.dat-Datei. Diese Datei enthält alle Ihre privaten Schlüssel und den Transaktionsverlauf. Bewahren Sie die Sicherung an einem sicheren Ort auf.", "backup_description": "Erstellen Sie eine Sicherung Ihrer wallet.dat-Datei. Diese Datei enthält alle Ihre privaten Schlüssel und den Transaktionsverlauf. Bewahren Sie die Sicherung an einem sicheren Ort auf.",
"backup_destination": "Sicherungsziel:", "backup_destination": "Sicherungsziel:",
"backup_overwrite_confirm": "Dort existiert bereits eine Datei — erneut speichern, um sie zu überschreiben.",
"backup_source": "Quelle: %s", "backup_source": "Quelle: %s",
"backup_tip_external": "Speichern Sie Sicherungen auf externen Laufwerken oder Cloud-Speicher", "backup_tip_external": "Speichern Sie Sicherungen auf externen Laufwerken oder Cloud-Speicher",
"backup_tip_multiple": "Erstellen Sie mehrere Sicherungen an verschiedenen Orten", "backup_tip_multiple": "Erstellen Sie mehrere Sicherungen an verschiedenen Orten",
@@ -70,6 +71,7 @@
"backup_title": "Wallet sichern", "backup_title": "Wallet sichern",
"backup_wallet": "Wallet sichern...", "backup_wallet": "Wallet sichern...",
"backup_wallet_not_found": "Warnung: wallet.dat nicht am erwarteten Speicherort gefunden", "backup_wallet_not_found": "Warnung: wallet.dat nicht am erwarteten Speicherort gefunden",
"backup_warn": "Diese Datei enthält alle Ihre privaten Schlüssel — bewahren Sie sie sicher auf.",
"balance": "Guthaben", "balance": "Guthaben",
"balance_history_collecting": "Guthabenverlauf — Daten werden gesammelt...", "balance_history_collecting": "Guthabenverlauf — Daten werden gesammelt...",
"balance_layout": "Guthaben-Layout", "balance_layout": "Guthaben-Layout",

View File

@@ -62,6 +62,7 @@
"backup_data": "RESPALDO Y DATOS", "backup_data": "RESPALDO Y DATOS",
"backup_description": "Crea un respaldo de tu archivo wallet.dat. Este archivo contiene todas tus claves privadas e historial de transacciones. Guarda el respaldo en un lugar seguro.", "backup_description": "Crea un respaldo de tu archivo wallet.dat. Este archivo contiene todas tus claves privadas e historial de transacciones. Guarda el respaldo en un lugar seguro.",
"backup_destination": "Destino del respaldo:", "backup_destination": "Destino del respaldo:",
"backup_overwrite_confirm": "Ya existe un archivo ahí: guarda de nuevo para sobrescribirlo.",
"backup_source": "Origen: %s", "backup_source": "Origen: %s",
"backup_tip_external": "Guarda respaldos en unidades externas o almacenamiento en la nube", "backup_tip_external": "Guarda respaldos en unidades externas o almacenamiento en la nube",
"backup_tip_multiple": "Crea múltiples respaldos en diferentes ubicaciones", "backup_tip_multiple": "Crea múltiples respaldos en diferentes ubicaciones",
@@ -70,6 +71,7 @@
"backup_title": "Respaldar Cartera", "backup_title": "Respaldar Cartera",
"backup_wallet": "Respaldar Cartera...", "backup_wallet": "Respaldar Cartera...",
"backup_wallet_not_found": "Advertencia: wallet.dat no encontrado en la ubicación esperada", "backup_wallet_not_found": "Advertencia: wallet.dat no encontrado en la ubicación esperada",
"backup_warn": "Este archivo contiene todas tus claves privadas: guárdalo en un lugar seguro.",
"balance": "Saldo", "balance": "Saldo",
"balance_history_collecting": "Historial de saldo — recopilando datos...", "balance_history_collecting": "Historial de saldo — recopilando datos...",
"balance_layout": "Diseño de Saldo", "balance_layout": "Diseño de Saldo",

View File

@@ -62,6 +62,7 @@
"backup_data": "SAUVEGARDE & DONNÉES", "backup_data": "SAUVEGARDE & DONNÉES",
"backup_description": "Créez une sauvegarde de votre fichier wallet.dat. Ce fichier contient toutes vos clés privées et l'historique des transactions. Conservez la sauvegarde dans un endroit sûr.", "backup_description": "Créez une sauvegarde de votre fichier wallet.dat. Ce fichier contient toutes vos clés privées et l'historique des transactions. Conservez la sauvegarde dans un endroit sûr.",
"backup_destination": "Destination de sauvegarde :", "backup_destination": "Destination de sauvegarde :",
"backup_overwrite_confirm": "Un fichier existe déjà là — enregistrez à nouveau pour l'écraser.",
"backup_source": "Source : %s", "backup_source": "Source : %s",
"backup_tip_external": "Stockez les sauvegardes sur des disques externes ou un stockage cloud", "backup_tip_external": "Stockez les sauvegardes sur des disques externes ou un stockage cloud",
"backup_tip_multiple": "Créez plusieurs sauvegardes à différents endroits", "backup_tip_multiple": "Créez plusieurs sauvegardes à différents endroits",
@@ -70,6 +71,7 @@
"backup_title": "Sauvegarder le portefeuille", "backup_title": "Sauvegarder le portefeuille",
"backup_wallet": "Sauvegarder le portefeuille...", "backup_wallet": "Sauvegarder le portefeuille...",
"backup_wallet_not_found": "Attention : wallet.dat introuvable à l'emplacement prévu", "backup_wallet_not_found": "Attention : wallet.dat introuvable à l'emplacement prévu",
"backup_warn": "Ce fichier contient toutes vos clés privées — conservez-le en lieu sûr.",
"balance": "Solde", "balance": "Solde",
"balance_history_collecting": "Historique du solde — collecte des données...", "balance_history_collecting": "Historique du solde — collecte des données...",
"balance_layout": "Disposition du solde", "balance_layout": "Disposition du solde",

View File

@@ -62,6 +62,7 @@
"backup_data": "バックアップとデータ", "backup_data": "バックアップとデータ",
"backup_description": "wallet.datファイルのバックアップを作成します。このファイルにはすべての秘密鍵と取引履歴が含まれています。バックアップは安全な場所に保管してください。", "backup_description": "wallet.datファイルのバックアップを作成します。このファイルにはすべての秘密鍵と取引履歴が含まれています。バックアップは安全な場所に保管してください。",
"backup_destination": "バックアップ先:", "backup_destination": "バックアップ先:",
"backup_overwrite_confirm": "そこには既にファイルがあります。もう一度保存すると上書きされます。",
"backup_source": "ソース:%s", "backup_source": "ソース:%s",
"backup_tip_external": "外部ドライブまたはクラウドストレージにバックアップを保存", "backup_tip_external": "外部ドライブまたはクラウドストレージにバックアップを保存",
"backup_tip_multiple": "異なる場所に複数のバックアップを作成", "backup_tip_multiple": "異なる場所に複数のバックアップを作成",
@@ -70,6 +71,7 @@
"backup_title": "ウォレットのバックアップ", "backup_title": "ウォレットのバックアップ",
"backup_wallet": "ウォレットをバックアップ...", "backup_wallet": "ウォレットをバックアップ...",
"backup_wallet_not_found": "警告予想される場所にwallet.datが見つかりません", "backup_wallet_not_found": "警告予想される場所にwallet.datが見つかりません",
"backup_warn": "このファイルにはすべての秘密鍵が含まれています。安全な場所に保管してください。",
"balance": "残高", "balance": "残高",
"balance_history_collecting": "残高履歴 — データを収集中...", "balance_history_collecting": "残高履歴 — データを収集中...",
"balance_layout": "残高レイアウト", "balance_layout": "残高レイアウト",

View File

@@ -62,6 +62,7 @@
"backup_data": "백업 및 데이터", "backup_data": "백업 및 데이터",
"backup_description": "wallet.dat 파일의 백업을 생성합니다. 이 파일에는 모든 개인 키와 거래 내역이 포함되어 있습니다. 백업을 안전한 곳에 보관하세요.", "backup_description": "wallet.dat 파일의 백업을 생성합니다. 이 파일에는 모든 개인 키와 거래 내역이 포함되어 있습니다. 백업을 안전한 곳에 보관하세요.",
"backup_destination": "백업 위치:", "backup_destination": "백업 위치:",
"backup_overwrite_confirm": "그곳에 이미 파일이 있습니다. 다시 저장하면 덮어씁니다.",
"backup_source": "소스: %s", "backup_source": "소스: %s",
"backup_tip_external": "외장 드라이브 또는 클라우드 스토리지에 백업 저장", "backup_tip_external": "외장 드라이브 또는 클라우드 스토리지에 백업 저장",
"backup_tip_multiple": "서로 다른 위치에 여러 백업 생성", "backup_tip_multiple": "서로 다른 위치에 여러 백업 생성",
@@ -70,6 +71,7 @@
"backup_title": "지갑 백업", "backup_title": "지갑 백업",
"backup_wallet": "지갑 백업...", "backup_wallet": "지갑 백업...",
"backup_wallet_not_found": "경고: 예상 위치에서 wallet.dat를 찾을 수 없습니다", "backup_wallet_not_found": "경고: 예상 위치에서 wallet.dat를 찾을 수 없습니다",
"backup_warn": "이 파일에는 모든 개인 키가 들어 있습니다. 안전한 곳에 보관하세요.",
"balance": "잔액", "balance": "잔액",
"balance_history_collecting": "잔액 내역 — 데이터 수집 중...", "balance_history_collecting": "잔액 내역 — 데이터 수집 중...",
"balance_layout": "잔액 레이아웃", "balance_layout": "잔액 레이아웃",

View File

@@ -62,6 +62,7 @@
"backup_data": "BACKUP & DADOS", "backup_data": "BACKUP & DADOS",
"backup_description": "Crie um backup do seu arquivo wallet.dat. Este arquivo contém todas as suas chaves privadas e histórico de transações. Guarde o backup em um local seguro.", "backup_description": "Crie um backup do seu arquivo wallet.dat. Este arquivo contém todas as suas chaves privadas e histórico de transações. Guarde o backup em um local seguro.",
"backup_destination": "Destino do backup:", "backup_destination": "Destino do backup:",
"backup_overwrite_confirm": "Já existe um arquivo ali — salve novamente para sobrescrevê-lo.",
"backup_source": "Origem: %s", "backup_source": "Origem: %s",
"backup_tip_external": "Armazene backups em unidades externas ou armazenamento em nuvem", "backup_tip_external": "Armazene backups em unidades externas ou armazenamento em nuvem",
"backup_tip_multiple": "Crie múltiplos backups em diferentes locais", "backup_tip_multiple": "Crie múltiplos backups em diferentes locais",
@@ -70,6 +71,7 @@
"backup_title": "Backup da Carteira", "backup_title": "Backup da Carteira",
"backup_wallet": "Fazer Backup da Carteira...", "backup_wallet": "Fazer Backup da Carteira...",
"backup_wallet_not_found": "Aviso: wallet.dat não encontrado no local esperado", "backup_wallet_not_found": "Aviso: wallet.dat não encontrado no local esperado",
"backup_warn": "Este arquivo contém todas as suas chaves privadas — guarde-o em local seguro.",
"balance": "Saldo", "balance": "Saldo",
"balance_history_collecting": "Histórico de saldo — coletando dados...", "balance_history_collecting": "Histórico de saldo — coletando dados...",
"balance_layout": "Layout do Saldo", "balance_layout": "Layout do Saldo",

View File

@@ -62,6 +62,7 @@
"backup_data": "РЕЗЕРВНОЕ КОПИРОВАНИЕ И ДАННЫЕ", "backup_data": "РЕЗЕРВНОЕ КОПИРОВАНИЕ И ДАННЫЕ",
"backup_description": "Создайте резервную копию файла wallet.dat. Этот файл содержит все ваши приватные ключи и историю транзакций. Храните копию в безопасном месте.", "backup_description": "Создайте резервную копию файла wallet.dat. Этот файл содержит все ваши приватные ключи и историю транзакций. Храните копию в безопасном месте.",
"backup_destination": "Место сохранения:", "backup_destination": "Место сохранения:",
"backup_overwrite_confirm": "Там уже есть файл — сохраните ещё раз, чтобы перезаписать его.",
"backup_source": "Источник: %s", "backup_source": "Источник: %s",
"backup_tip_external": "Храните резервные копии на внешних дисках или в облаке", "backup_tip_external": "Храните резервные копии на внешних дисках или в облаке",
"backup_tip_multiple": "Создавайте несколько копий в разных местах", "backup_tip_multiple": "Создавайте несколько копий в разных местах",
@@ -70,6 +71,7 @@
"backup_title": "Резервное копирование кошелька", "backup_title": "Резервное копирование кошелька",
"backup_wallet": "Создать резервную копию...", "backup_wallet": "Создать резервную копию...",
"backup_wallet_not_found": "Предупреждение: wallet.dat не найден в ожидаемом расположении", "backup_wallet_not_found": "Предупреждение: wallet.dat не найден в ожидаемом расположении",
"backup_warn": "Этот файл содержит все ваши приватные ключи — храните его в надёжном месте.",
"balance": "Баланс", "balance": "Баланс",
"balance_history_collecting": "История баланса — сбор данных...", "balance_history_collecting": "История баланса — сбор данных...",
"balance_layout": "Макет баланса", "balance_layout": "Макет баланса",

View File

@@ -62,6 +62,7 @@
"backup_data": "备份与数据", "backup_data": "备份与数据",
"backup_description": "创建 wallet.dat 文件的备份。此文件包含您所有的私钥和交易历史。请将备份存放在安全的地方。", "backup_description": "创建 wallet.dat 文件的备份。此文件包含您所有的私钥和交易历史。请将备份存放在安全的地方。",
"backup_destination": "备份目标:", "backup_destination": "备份目标:",
"backup_overwrite_confirm": "该位置已存在文件,再次保存将覆盖它。",
"backup_source": "来源:%s", "backup_source": "来源:%s",
"backup_tip_external": "将备份存储在外部驱动器或云存储中", "backup_tip_external": "将备份存储在外部驱动器或云存储中",
"backup_tip_multiple": "在不同位置创建多个备份", "backup_tip_multiple": "在不同位置创建多个备份",
@@ -70,6 +71,7 @@
"backup_title": "备份钱包", "backup_title": "备份钱包",
"backup_wallet": "备份钱包...", "backup_wallet": "备份钱包...",
"backup_wallet_not_found": "警告:在预期位置未找到 wallet.dat", "backup_wallet_not_found": "警告:在预期位置未找到 wallet.dat",
"backup_warn": "此文件包含您的所有私钥,请妥善保管。",
"balance": "余额", "balance": "余额",
"balance_history_collecting": "余额历史——正在收集数据…", "balance_history_collecting": "余额历史——正在收集数据…",
"balance_layout": "余额布局", "balance_layout": "余额布局",

View File

@@ -3271,42 +3271,44 @@ void App::renderExportKeyDialog()
void App::renderBackupDialog() void App::renderBackupDialog()
{ {
auto dlg = ui::schema::UI().drawElement("inline-dialogs", "backup"); namespace m = ui::material;
auto dlgF = [&](const char* key, float fb) -> float {
auto it = dlg.extraFloats.find(key);
return it != dlg.extraFloats.end() ? it->second : fb;
};
int btnFont = (int)dlgF("button-font", 1);
float btnW = dlgF("button-width", 120.0f);
if (!ui::material::BeginOverlayDialog("Backup Wallet", &show_backup_, dlgF("width", 500.0f), 0.94f)) { m::OverlayDialogSpec ov;
return; ov.title = TR("backup_title");
} ov.p_open = &show_backup_;
ov.style = m::OverlayStyle::BlurFloat;
ov.cardWidth = 560.0f;
ov.idSuffix = "backup";
if (!m::BeginOverlayDialog(ov)) return;
ImGui::TextWrapped("Export all private keys to a file. Keep this file secure!"); m::DialogWarningHeader(TR("backup_warn"));
ImGui::Spacing(); ImGui::Spacing();
ImGui::Text("Backup File Path:");
static char backup_path[512] = "dragonx-backup.txt"; static char backup_path[512] = "dragonx-backup.txt";
static bool s_backup_confirm_overwrite = false; static bool s_backup_confirm_overwrite = false;
ImGui::TextUnformatted(TR("backup_destination"));
ImGui::SetNextItemWidth(-1); ImGui::SetNextItemWidth(-1);
if (ImGui::InputText("##backuppath", backup_path, sizeof(backup_path))) if (ImGui::InputText("##backuppath", backup_path, sizeof(backup_path)))
s_backup_confirm_overwrite = false; // path edited — re-check overwrite on next Save s_backup_confirm_overwrite = false; // path edited — re-check overwrite on next Save
ImGui::Spacing();
if (!backup_status_.empty()) { if (!backup_status_.empty()) {
if (backup_success_) { ImGui::Spacing();
ImGui::TextColored(ui::material::SuccessVec4(), "%s", backup_status_.c_str()); ImGui::PushTextWrapPos(0.0f);
} else { ImGui::TextColored(backup_success_ ? m::SuccessVec4() : ImVec4(0.8f, 0.3f, 0.3f, 1.0f),
ImGui::TextColored(ImVec4(0.8f, 0.3f, 0.3f, 1.0f), "%s", backup_status_.c_str()); "%s", backup_status_.c_str());
} ImGui::PopTextWrapPos();
} }
ImGui::Spacing(); ImGui::Spacing();
ImGui::Separator();
if (ui::material::StyledButton("Save Backup", ImVec2(btnW, 0), ui::material::resolveButtonFont(btnFont))) { bool doSave = false, doClose = false;
m::DialogActionFooter(TR("backup_create"), true, TR("close"), doSave, doClose);
if (doClose) {
show_backup_ = false;
backup_status_.clear();
s_backup_confirm_overwrite = false;
}
if (doSave) {
std::string path(backup_path); std::string path(backup_path);
// Trim surrounding whitespace (a pasted path can carry a trailing newline). // Trim surrounding whitespace (a pasted path can carry a trailing newline).
while (!path.empty() && (path.front()==' '||path.front()=='\t'||path.front()=='\n'||path.front()=='\r')) path.erase(path.begin()); while (!path.empty() && (path.front()==' '||path.front()=='\t'||path.front()=='\n'||path.front()=='\r')) path.erase(path.begin());
@@ -3317,7 +3319,7 @@ void App::renderBackupDialog()
// Don't clobber an existing file (possibly a good earlier backup) without confirmation. // Don't clobber an existing file (possibly a good earlier backup) without confirmation.
s_backup_confirm_overwrite = true; s_backup_confirm_overwrite = true;
backup_success_ = false; backup_success_ = false;
backup_status_ = "A file already exists there — click Save Backup again to overwrite it."; backup_status_ = TR("backup_overwrite_confirm");
} else { } else {
s_backup_confirm_overwrite = false; s_backup_confirm_overwrite = false;
backupWallet(path, [this](bool success, const std::string& msg) { backupWallet(path, [this](bool success, const std::string& msg) {
@@ -3327,14 +3329,8 @@ void App::renderBackupDialog()
} }
} }
} }
ImGui::SameLine();
if (ui::material::StyledButton("Close", ImVec2(btnW, 0), ui::material::resolveButtonFont(btnFont))) {
show_backup_ = false;
backup_status_.clear();
s_backup_confirm_overwrite = false;
}
ui::material::EndOverlayDialog(); m::EndOverlayDialog();
} }
void App::maybeOfferDaemonUpdate() void App::maybeOfferDaemonUpdate()

View File

@@ -1202,6 +1202,8 @@ void I18n::loadBuiltinEnglish()
strings_["backup_created"] = "Wallet backup created"; strings_["backup_created"] = "Wallet backup created";
strings_["backup_description"] = "Create a backup of your wallet.dat file. This file contains all your private keys and transaction history. Store the backup in a secure location."; strings_["backup_description"] = "Create a backup of your wallet.dat file. This file contains all your private keys and transaction history. Store the backup in a secure location.";
strings_["backup_destination"] = "Backup destination:"; strings_["backup_destination"] = "Backup destination:";
strings_["backup_warn"] = "This file holds all your private keys \xE2\x80\x94 keep it somewhere safe.";
strings_["backup_overwrite_confirm"] = "A file already exists there \xE2\x80\x94 Save again to overwrite it.";
strings_["backup_tip_external"] = "Store backups on external drives or cloud storage"; strings_["backup_tip_external"] = "Store backups on external drives or cloud storage";
strings_["backup_tip_multiple"] = "Create multiple backups in different locations"; strings_["backup_tip_multiple"] = "Create multiple backups in different locations";
strings_["backup_tip_test"] = "Test restoring from backup periodically"; strings_["backup_tip_test"] = "Test restoring from backup periodically";