feat(send): add a shared contact picker to the recipient field

Phase 0c. The Send recipient field only offered Paste and a tx-history
suggestion list — no way to pick a saved contact. Add a compact contacts
icon button next to Paste that opens a picker popup over the App-owned
address book; selecting a contact fills the recipient (re-validated next
frame).

- New header-only src/ui/windows/contact_picker.h: ContactPickerPopup(id,
  book, outBuf, outSz) — a reusable popup listing contacts ([Z]/[T] tag +
  label + short address) that copies the chosen address into the caller's
  buffer. Kept out of the material layer so the design-system headers stay
  free of data/ deps; reserved for Chat "new conversation" later.
- send_tab: shrink the recipient input to make room for the icon button
  (ICON_MD_CONTACTS), wire the popup to app->addressBook(). Coexists with the
  existing Paste + suggestion affordances.
- i18n: send_contacts_button tooltip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-05 17:04:58 -05:00
parent ee59a9e2cd
commit ddd53dc006
4 changed files with 79 additions and 1 deletions

View File

@@ -16,6 +16,7 @@
#include "../../util/text_format.h"
#include "../notifications.h"
#include "../layout.h"
#include "contact_picker.h"
#include "../schema/ui_schema.h"
#include "../material/type.h"
#include "../material/draw_helpers.h"
@@ -1272,7 +1273,8 @@ void RenderSendTab(App* app)
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
float pasteW = std::max(schema::UI().drawElement("tabs.send", "paste-btn-min-width").size, colW * schema::UI().drawElement("tabs.send", "paste-btn-width-ratio").size);
ImGui::PushItemWidth(colW - pasteW - Layout::spacingSm());
float contactsW = ImGui::GetFrameHeight(); // compact square icon button for the contact picker
ImGui::PushItemWidth(colW - pasteW - contactsW - Layout::spacingSm() * 2.0f);
// Show clipboard preview as transparent overlay when paste button is hovered
bool paste_hovered = false;
@@ -1331,6 +1333,15 @@ void RenderSendTab(App* app)
}
}
// Contact picker — pick a saved contact's address as the recipient.
ImGui::SameLine();
if (material::TactileButton(ICON_MD_CONTACTS "##pickContact", ImVec2(contactsW, 0),
material::Type().iconMed()))
ImGui::OpenPopup("##ContactPickerPopup");
if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("send_contacts_button"));
ContactPickerPopup("##ContactPickerPopup", app->addressBook(),
s_to_address, sizeof(s_to_address));
// Recently sent-to suggestions
RenderAddressSuggestions(state, colW, "##AddrSugForm");
}