feat(seed,console): persistent re-nudging seed backup; confirm destructive console commands
- Seed backup: the one-time 12s toast that marked itself "reminded" the instant it fired (so a funded, unbacked wallet was never nudged again) is replaced by an actionable alert with a "Back up now" link that opens the backup dialog and persists in the bell panel. "Reminded" now means the user actually viewed the phrase (set from the backup dialog), so the nudge re-fires each session until they do, and escalates to a warning once a balance exists. - Console: fund-moving / key-revealing commands (dumpprivkey, z_exportkey, z_sendmany, z_mergetoaddress, …) now require a confirming re-entry when typed or PASTED, honoring the command reference's `destructive` flag that was previously enforced only by the reference dialog's Run button. (Output masking of key dumps in the scrollback is still a follow-up.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+20
-6
@@ -5833,7 +5833,8 @@ void App::maybeRemindSeedBackup()
|
||||
if (capture_mode_) return; // no live ops during a UI sweep
|
||||
if (window_background_) return; // when someone can see it
|
||||
if (lite_wallet_) return; // lite has its own seed UX
|
||||
if (!settings_ || settings_->getSeedBackupReminded()) return;
|
||||
if (!settings_ || settings_->getSeedBackupReminded()) return; // already backed up (saw the phrase)
|
||||
if (seed_backup_nudged_this_session_) return; // already nudged/classified this run
|
||||
if (!state_.connected || !state_.encryption_state_known) return;
|
||||
if (state_.isLocked()) return; // wait until unlocked to read it
|
||||
if (seed_backup_reminder_in_flight_) return;
|
||||
@@ -5844,16 +5845,29 @@ void App::maybeRemindSeedBackup()
|
||||
exportSeedPhrase([this](bool ok, bool noMnemonic, const std::string& /*phrase*/,
|
||||
const std::string& /*error*/) {
|
||||
seed_backup_reminder_in_flight_ = false;
|
||||
// Only mark "reminded" once we have a definitive answer, so a transient failure retries
|
||||
// next session rather than silently suppressing the reminder forever.
|
||||
if (ok || noMnemonic) {
|
||||
if (ok) {
|
||||
// The wallet HAS a mnemonic and the user hasn't backed it up yet. Don't mark "reminded"
|
||||
// here — that permanent flag now means "the user has seen the phrase" (set from the backup
|
||||
// dialog), so leaving it clear re-nudges next session until they actually do. Nudge once
|
||||
// per session as an ACTIONABLE alert (survives in the bell panel with a "Back up now" link),
|
||||
// not a 12s toast that's gone before it's read. Escalate to a warning once funds exist.
|
||||
seed_backup_nudged_this_session_ = true;
|
||||
const bool hasFunds = state_.totalBalance > 0.0;
|
||||
ui::Notifications::instance().action(
|
||||
TR("seed_backup_reminder"),
|
||||
hasFunds ? ui::NotificationType::Warning : ui::NotificationType::Info,
|
||||
[this]() { showSeedBackupDialog(); },
|
||||
TR("seed_backup_reminder_action"),
|
||||
hasFunds ? 15.0f : 12.0f);
|
||||
} else if (noMnemonic) {
|
||||
// A legacy (non-mnemonic) wallet has nothing to back up this way — suppress for good.
|
||||
seed_backup_nudged_this_session_ = true;
|
||||
settings_->setSeedBackupReminded(true);
|
||||
settings_->save();
|
||||
} else {
|
||||
// Inconclusive (busy/old daemon) — retry later this session rather than suppressing forever.
|
||||
seed_backup_reminder_retry_at_ = std::chrono::steady_clock::now() + std::chrono::minutes(5);
|
||||
}
|
||||
if (ok)
|
||||
ui::Notifications::instance().info(TR("seed_backup_reminder"), 12.0f);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user