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>
66 lines
2.3 KiB
C++
66 lines
2.3 KiB
C++
// DragonX Wallet - ImGui Edition
|
|
// Copyright 2024-2026 The Hush Developers
|
|
// Released under the GPLv3
|
|
|
|
#pragma once
|
|
|
|
#include "imgui.h"
|
|
#include "../../data/address_book.h"
|
|
#include "../../util/i18n.h"
|
|
#include "../../util/text_format.h"
|
|
#include <cstring>
|
|
#include <string>
|
|
|
|
namespace dragonx {
|
|
namespace ui {
|
|
|
|
/**
|
|
* @brief Shared address-book contact picker popup.
|
|
*
|
|
* Header-only so Send (and later Chat "new conversation") can reuse it without
|
|
* pulling the address book into the material layer. Trigger with
|
|
* ImGui::OpenPopup(id) from a button, then call this every frame. On selection
|
|
* it copies the chosen contact's address into outBuf (NUL-terminated) and
|
|
* returns true.
|
|
*
|
|
* @param id Popup id (must match the ImGui::OpenPopup(id) call).
|
|
* @param book The App-owned address book (app->addressBook()).
|
|
* @param outBuf Destination buffer for the chosen address.
|
|
* @param outSz Size of outBuf.
|
|
* @return true on the frame a contact is picked.
|
|
*/
|
|
inline bool ContactPickerPopup(const char* id, const data::AddressBook& book,
|
|
char* outBuf, size_t outSz)
|
|
{
|
|
bool picked = false;
|
|
if (ImGui::BeginPopup(id)) {
|
|
if (book.empty()) {
|
|
ImGui::TextDisabled("%s", TR("address_book_empty"));
|
|
} else {
|
|
const auto& entries = book.entries();
|
|
for (size_t i = 0; i < entries.size(); ++i) {
|
|
const auto& e = entries[i];
|
|
ImGui::PushID(static_cast<int>(i));
|
|
// [Z]/[T] type marker (derived from the address) + label + short address.
|
|
const char* tag = (!e.address.empty() && e.address[0] == 'z') ? "[Z] " : "[T] ";
|
|
std::string shortAddr = util::truncateMiddle(e.address, 24);
|
|
std::string row = std::string(tag) + e.label + " " + shortAddr;
|
|
if (ImGui::Selectable(row.c_str())) {
|
|
if (outSz > 0) {
|
|
std::strncpy(outBuf, e.address.c_str(), outSz - 1);
|
|
outBuf[outSz - 1] = '\0';
|
|
}
|
|
picked = true;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::PopID();
|
|
}
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
return picked;
|
|
}
|
|
|
|
} // namespace ui
|
|
} // namespace dragonx
|