feat(wallets): show "HD wallet" instead of "?" when the seed flag is unreadable

When a row is probed as an HD wallet (has hdseed/hdchain records) but the
mnemonic flag can't be read — e.g. the rare tier-1 byte-scan fallback on an
unusual BDB variant or a >256 MB file — it now shows a neutral "HD wallet"
badge (ICON_MD_ACCOUNT_TREE) rather than a bare "?", which read as alarming.
"Unknown" (?) is reserved for a scan that couldn't even establish it's HD
(incomplete, no HD marker seen). Both still yield to the Lock badge when
encrypted. Seed/legacy/hd/unknown remain mutually exclusive.

Adds wallets_badge_hd / _hd_short strings (EN source + all 8 languages,
additive) and rebuilds the CJK subset font for the new glyphs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-15 16:47:17 -05:00
parent e6c78da062
commit bb5124c1ae
11 changed files with 27 additions and 5 deletions

Binary file not shown.

View File

@@ -1474,6 +1474,8 @@
"wallets_add_folder_toggle": "+ Weiteren Ordner nach Wallets durchsuchen…",
"wallets_badge_encrypted": "Verschlüsselt (passphrasengeschützt)",
"wallets_badge_encrypted_short": "Verschlüsselt",
"wallets_badge_hd": "HD-Wallet Seed-Phrase ohne Öffnen nicht bestätigbar",
"wallets_badge_hd_short": "HD-Wallet",
"wallets_badge_legacy": "Legacy-Wallet (keine Seed-Phrase)",
"wallets_badge_legacy_short": "Legacy",
"wallets_badge_seed": "Seed-Phrase-Wallet (HD)",

View File

@@ -1474,6 +1474,8 @@
"wallets_add_folder_toggle": "+ Buscar wallets en otra carpeta…",
"wallets_badge_encrypted": "Cifrada (protegida con contraseña)",
"wallets_badge_encrypted_short": "Cifrada",
"wallets_badge_hd": "Cartera HD: no se puede confirmar la frase semilla sin abrirla",
"wallets_badge_hd_short": "Cartera HD",
"wallets_badge_legacy": "Billetera heredada (sin frase semilla)",
"wallets_badge_legacy_short": "Heredada",
"wallets_badge_seed": "Billetera con frase semilla (HD)",

View File

@@ -1474,6 +1474,8 @@
"wallets_add_folder_toggle": "+ Analyser un autre dossier pour les portefeuilles…",
"wallets_badge_encrypted": "Chiffré (protégé par phrase secrète)",
"wallets_badge_encrypted_short": "Chiffré",
"wallets_badge_hd": "Portefeuille HD — impossible de confirmer une phrase de récupération sans l'ouvrir",
"wallets_badge_hd_short": "Portefeuille HD",
"wallets_badge_legacy": "Portefeuille hérité (sans phrase de récupération)",
"wallets_badge_legacy_short": "Hérité",
"wallets_badge_seed": "Portefeuille à phrase de récupération (HD)",

View File

@@ -1474,6 +1474,8 @@
"wallets_add_folder_toggle": "+ 別のフォルダーをウォレット検索…",
"wallets_badge_encrypted": "暗号化済み(パスフレーズ保護)",
"wallets_badge_encrypted_short": "暗号化",
"wallets_badge_hd": "HDウォレット — 開かないとシードフレーズを確認できません",
"wallets_badge_hd_short": "HDウォレット",
"wallets_badge_legacy": "レガシーウォレット(シードフレーズなし)",
"wallets_badge_legacy_short": "レガシー",
"wallets_badge_seed": "シードフレーズウォレット (HD)",

View File

@@ -1474,6 +1474,8 @@
"wallets_add_folder_toggle": "+ 다른 폴더에서 지갑 검색…",
"wallets_badge_encrypted": "암호화됨 (암호로 보호됨)",
"wallets_badge_encrypted_short": "암호화됨",
"wallets_badge_hd": "HD 지갑 — 열지 않으면 시드 문구를 확인할 수 없습니다",
"wallets_badge_hd_short": "HD 지갑",
"wallets_badge_legacy": "레거시 지갑 (시드 문구 없음)",
"wallets_badge_legacy_short": "레거시",
"wallets_badge_seed": "시드 문구 지갑 (HD)",

View File

@@ -1474,6 +1474,8 @@
"wallets_add_folder_toggle": "+ Procurar carteiras noutra pasta…",
"wallets_badge_encrypted": "Encriptada (protegida por senha)",
"wallets_badge_encrypted_short": "Encriptada",
"wallets_badge_hd": "Carteira HD — não é possível confirmar a frase-semente sem abri-la",
"wallets_badge_hd_short": "Carteira HD",
"wallets_badge_legacy": "Carteira legada (sem frase semente)",
"wallets_badge_legacy_short": "Legada",
"wallets_badge_seed": "Carteira com frase semente (HD)",

View File

@@ -1474,6 +1474,8 @@
"wallets_add_folder_toggle": "+ Искать кошельки в другой папке…",
"wallets_badge_encrypted": "Зашифрован (защищён паролем)",
"wallets_badge_encrypted_short": "Зашифрован",
"wallets_badge_hd": "HD-кошелёк — невозможно подтвердить seed-фразу без открытия",
"wallets_badge_hd_short": "HD-кошелёк",
"wallets_badge_legacy": "Устаревший кошелёк (без seed-фразы)",
"wallets_badge_legacy_short": "Устаревший",
"wallets_badge_seed": "Кошелёк с seed-фразой (HD)",

View File

@@ -1474,6 +1474,8 @@
"wallets_add_folder_toggle": "+ 扫描其他文件夹中的钱包…",
"wallets_badge_encrypted": "已加密(密码保护)",
"wallets_badge_encrypted_short": "已加密",
"wallets_badge_hd": "HD 钱包 — 打开钱包才能确认助记词",
"wallets_badge_hd_short": "HD 钱包",
"wallets_badge_legacy": "旧版钱包(无助记词)",
"wallets_badge_legacy_short": "旧版",
"wallets_badge_seed": "助记词钱包 (HD)",

View File

@@ -301,15 +301,19 @@ public:
}
const bool bSeed = (seed == 1);
const bool bLegacy = (seed == 2);
// Undecided: probed but neither the runtime status nor the on-disk flag could classify it
// (incomplete scan, or an unreadable hdchain value) — show a question mark rather than
// mislabel. Suppressed for encrypted rows, which still carry a definitive Lock badge.
const bool bUnknown = (seed == 0) && pres.probed && !pres.encrypted;
// seed==0 splits by what the probe DID learn: if it saw HD records we know it's an HD
// wallet (we just couldn't read the phrase flag — e.g. the tier-1 byte-scan fallback), so
// label it "HD wallet" rather than a bare "?"; only a scan that couldn't even establish
// that (incomplete, no HD marker yet) stays "Unknown". Both yield to the Lock badge when
// encrypted, so an encrypted-but-unclassified row shows just the lock.
const bool bHd = (seed == 0) && pres.probed && pres.hdSeed && !pres.encrypted;
const bool bUnknown = (seed == 0) && pres.probed && !pres.hdSeed && !pres.encrypted;
struct Badge { const char* glyph; ImU32 col; const char* label; const char* tip; };
Badge bl[4]; int nb = 0;
Badge bl[4]; int nb = 0; // seed/legacy/hd/unknown are mutually exclusive → at most one + lock
if (bSeed) bl[nb++] = { ICON_MD_ECO, WithAlpha(Success(), 235), TR("wallets_badge_seed_short"), TR("wallets_badge_seed") };
if (bLock) bl[nb++] = { ICON_MD_LOCK, WithAlpha(Warning(), 240), TR("wallets_badge_encrypted_short"), TR("wallets_badge_encrypted") };
if (bLegacy) bl[nb++] = { ICON_MD_HISTORY, WithAlpha(OnSurfaceMedium(), 220), TR("wallets_badge_legacy_short"), TR("wallets_badge_legacy") };
if (bHd) bl[nb++] = { ICON_MD_ACCOUNT_TREE, WithAlpha(OnSurfaceMedium(), 210), TR("wallets_badge_hd_short"), TR("wallets_badge_hd") };
if (bUnknown) bl[nb++] = { ICON_MD_HELP_OUTLINE, WithAlpha(OnSurfaceMedium(), 185), TR("wallets_badge_unknown_short"), TR("wallets_badge_unknown") };
const float bGap = Layout::spacingSm();
float maxLabelW = 0.0f;

View File

@@ -276,9 +276,11 @@ void I18n::loadBuiltinEnglish()
strings_["wallets_badge_seed"] = "Seed phrase wallet (HD)";
strings_["wallets_badge_legacy"] = "Legacy wallet (no seed phrase)";
strings_["wallets_badge_unknown"] = "Wallet type not fully determined (large file — open to confirm)";
strings_["wallets_badge_hd"] = "HD wallet — can't confirm a seed phrase without opening it";
strings_["wallets_badge_seed_short"] = "Seed phrase";
strings_["wallets_badge_encrypted_short"] = "Encrypted";
strings_["wallets_badge_legacy_short"] = "Legacy";
strings_["wallets_badge_hd_short"] = "HD wallet";
strings_["wallets_badge_unknown_short"] = "Unknown";
strings_["wallets_open"] = "Open";
strings_["wallets_open_folder"] = "Open folder location";