From a11130769d5c82640d6a4f881e7c754a738a0c06 Mon Sep 17 00:00:00 2001 From: DanS Date: Sun, 18 Oct 2026 09:14:44 -0500 Subject: [PATCH] feat(send): show fee + total on the compose form; fix the stuck confirm on recheck MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The network fee and running total are now shown on the compose form (once an amount is entered), instead of only being revealed in the confirm popup. - When the pre-broadcast re-validation fails (balance dropped, sync restarted, fee pushed total over available), the confirm popup now closes and surfaces a warning toast — previously the reason was drawn on the form behind the still- open popup, so the user was left re-clicking a button that did nothing. Co-Authored-By: Claude Opus 4.8 --- src/ui/windows/send_tab.cpp | 15 +++++++++++++++ src/util/i18n.cpp | 2 ++ 2 files changed, 17 insertions(+) diff --git a/src/ui/windows/send_tab.cpp b/src/ui/windows/send_tab.cpp index ed159b4..cf0c06e 100644 --- a/src/ui/windows/send_tab.cpp +++ b/src/ui/windows/send_tab.cpp @@ -896,6 +896,10 @@ void RenderSendConfirmPopup(App* app) { s_tx_status = TR("send_cannot_send_now"); s_status_success = false; s_status_timestamp = ImGui::GetTime(); + // The status renders on the form BEHIND this popup, so surface it visibly and close the + // popup — otherwise the user is stuck re-clicking a button that silently does nothing. + Notifications::instance().warning(TR("send_cannot_send_now")); + s_show_confirm = false; } // A locked encrypted lite wallet can't spend; prompt to unlock instead of sending // (the backend would otherwise reject with "Wallet is locked"). @@ -1013,6 +1017,17 @@ static void RenderActionButtons(App* app, float width, float vScale, sourceSpendable && !s_sending; + // Network fee + running total on the compose form — previously the fee was only revealed in the + // confirm popup, so the user couldn't see it (or the total) before committing to Review. + if (s_amount > 0.0) { + char feeLine[160]; + snprintf(feeLine, sizeof(feeLine), "%s %.8f %s \xC2\xB7 %s %.8f %s", + TR("send_network_fee_label"), s_fee, DRAGONX_TICKER, + TR("send_total_label"), total, DRAGONX_TICKER); + Type().textColored(TypeStyle::Caption, OnSurfaceMedium(), feeLine); + ImGui::Dummy(ImVec2(0, Layout::spacingXs())); + } + float btnGap = Layout::spacingMd(); float cancelBtnW = std::max(schema::UI().drawElement("tabs.send", "cancel-btn-min-width").size, width * S.drawElement("tabs.send", "cancel-btn-width-ratio").size); float sendBtnW = width - cancelBtnW - btnGap; diff --git a/src/util/i18n.cpp b/src/util/i18n.cpp index 90502bc..aa20e22 100644 --- a/src/util/i18n.cpp +++ b/src/util/i18n.cpp @@ -2550,6 +2550,8 @@ void I18n::loadBuiltinEnglish() strings_["send_go_to_receive"] = "Go to Receive"; strings_["send_keep"] = "Keep"; strings_["send_network_fee"] = "NETWORK FEE"; + strings_["send_network_fee_label"] = "Network fee:"; + strings_["send_total_label"] = "Total:"; strings_["send_no_balance"] = "No balance"; strings_["send_no_recent"] = "No recent sends"; strings_["send_recent_sends"] = "RECENT SENDS";