feat(send): migrate the Confirm-Send modal to the reference design

Presentation-only migration of RenderSendConfirmPopup (the confirm-before-broadcast
popup) — a fund-moving modal:
- struct-form BeginOverlayDialog(OverlayDialogSpec{BlurFloat, cardWidth popupW,
  idSuffix confirmsend}) replacing the legacy positional overload; p_open stays
  nullptr (the popup keeps its own Escape + Cancel handling)
- TR() the one hardcoded status string in the synchronous live-revalidation guard
  ("Cannot send now …") -> new send_cannot_send_now key, 8 langs (em-dash preserved)

The fund path is byte-for-byte unchanged: the live re-validation guard, the
app->sendTransaction call + its success/failure callback, the lite-locked
requestLiteUnlock branch, the s_sending/s_show_confirm state, the Escape handler,
and the FROM/TO cards + fee-tier/summary rendering.

Verified: build + ctest + hygiene clean; a 2-lens adversarial review
(fund-path-untouched / ui-i18n) returned zero findings, with the fund-path lens
proving the send path diffs byte-for-byte identical to HEAD.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-14 17:58:11 -05:00
parent 4ef09d5546
commit dae677acd8
10 changed files with 15 additions and 2 deletions

View File

@@ -1084,6 +1084,7 @@
"send_amount": "Betrag",
"send_amount_details": "BETRAGSDETAILS",
"send_amount_upper": "BETRAG",
"send_cannot_send_now": "Senden derzeit nicht möglich — prüfen Sie Verbindung, Synchronisierung und verfügbares Guthaben.",
"send_clear_fields": "Alle Formularfelder leeren?",
"send_contacts_button": "Aus Kontakten auswählen",
"send_copy_error": "Fehler kopieren",

View File

@@ -1084,6 +1084,7 @@
"send_amount": "Cantidad",
"send_amount_details": "DETALLES DE CANTIDAD",
"send_amount_upper": "CANTIDAD",
"send_cannot_send_now": "No se puede enviar ahora — revisa la conexión, la sincronización y el saldo disponible.",
"send_clear_fields": "¿Limpiar todos los campos del formulario?",
"send_contacts_button": "Elegir de contactos",
"send_copy_error": "Copiar Error",

View File

@@ -1084,6 +1084,7 @@
"send_amount": "Montant",
"send_amount_details": "DÉTAILS DU MONTANT",
"send_amount_upper": "MONTANT",
"send_cannot_send_now": "Envoi impossible pour le moment — vérifiez la connexion, la synchronisation et le solde disponible.",
"send_clear_fields": "Effacer tous les champs du formulaire ?",
"send_contacts_button": "Choisir parmi les contacts",
"send_copy_error": "Copier l'erreur",

View File

@@ -1084,6 +1084,7 @@
"send_amount": "金額",
"send_amount_details": "金額の詳細",
"send_amount_upper": "金額",
"send_cannot_send_now": "現在送信できません — 接続、同期、利用可能な残高を確認してください。",
"send_clear_fields": "すべてのフォームフィールドをクリアしますか?",
"send_contacts_button": "連絡先から選択",
"send_copy_error": "エラーをコピー",

View File

@@ -1084,6 +1084,7 @@
"send_amount": "금액",
"send_amount_details": "금액 상세",
"send_amount_upper": "금액",
"send_cannot_send_now": "지금 보낼 수 없습니다 — 연결, 동기화, 사용 가능한 잔액을 확인하세요.",
"send_clear_fields": "모든 양식 필드를 지우시겠습니까?",
"send_contacts_button": "연락처에서 선택",
"send_copy_error": "오류 복사",

View File

@@ -1084,6 +1084,7 @@
"send_amount": "Valor",
"send_amount_details": "DETALHES DO VALOR",
"send_amount_upper": "VALOR",
"send_cannot_send_now": "Não é possível enviar agora — verifique a conexão, a sincronização e o saldo disponível.",
"send_clear_fields": "Limpar todos os campos do formulário?",
"send_contacts_button": "Escolher dos contatos",
"send_copy_error": "Copiar Erro",

View File

@@ -1084,6 +1084,7 @@
"send_amount": "Сумма",
"send_amount_details": "ДЕТАЛИ СУММЫ",
"send_amount_upper": "СУММА",
"send_cannot_send_now": "Сейчас отправить нельзя — проверьте соединение, синхронизацию и доступный баланс.",
"send_clear_fields": "Очистить все поля формы?",
"send_contacts_button": "Выбрать из контактов",
"send_copy_error": "Копировать ошибку",

View File

@@ -1084,6 +1084,7 @@
"send_amount": "金额",
"send_amount_details": "金额详情",
"send_amount_upper": "金额",
"send_cannot_send_now": "现在无法发送 — 请检查连接、同步和可用余额。",
"send_clear_fields": "清除所有表单字段?",
"send_contacts_button": "从联系人中选择",
"send_copy_error": "复制错误",

View File

@@ -696,7 +696,11 @@ void RenderSendConfirmPopup(App* app) {
float popupAvailW = ImGui::GetMainViewport()->Size.x * S.drawElement("tabs.send", "confirm-popup-width-ratio").size;
float popupW = std::min(schema::UI().drawElement("tabs.send", "confirm-popup-max-width").size, popupAvailW);
float popVs = Layout::vScale();
if (material::BeginOverlayDialog(TR("confirm_send"), nullptr, popupW, 0.94f)) {
material::OverlayDialogSpec ov;
ov.title = TR("confirm_send"); ov.p_open = nullptr;
ov.style = material::OverlayStyle::BlurFloat;
ov.cardWidth = popupW; ov.idSuffix = "confirmsend";
if (material::BeginOverlayDialog(ov)) {
if (ImGui::IsKeyPressed(ImGuiKey_Escape) && !s_sending) {
s_show_confirm = false;
@@ -826,7 +830,7 @@ void RenderSendConfirmPopup(App* app) {
double liveAvail = GetAvailableBalance(app);
if (!app->isConnected() || liveState.sync.syncing || s_amount <= 0 ||
(s_amount + s_fee) > liveAvail) {
s_tx_status = "Cannot send now — check connection, sync, and available balance.";
s_tx_status = TR("send_cannot_send_now");
s_status_success = false;
s_status_timestamp = ImGui::GetTime();
}

View File

@@ -1837,6 +1837,7 @@ void I18n::loadBuiltinEnglish()
strings_["send_total"] = "Total";
strings_["send_tx_failed"] = "Transaction failed";
strings_["send_tx_sent"] = "Transaction sent!";
strings_["send_cannot_send_now"] = "Cannot send now — check connection, sync, and available balance.";
strings_["send_tx_success"] = "Transaction sent successfully!";
strings_["send_status_unconfirmed"] = "Transaction status could not be confirmed";
strings_["send_err_needs_rescan"] = "Your wallet's shielded note data is out of date with the blockchain (this happens after a bootstrap or reindex). Run a full rescan via Settings -> Rescan Blockchain and let it finish completely, then try sending again.";