// DragonX Wallet - ImGui Edition // Copyright 2024-2026 The Hush Developers // Released under the GPLv3 #include "qr_popup_dialog.h" #include "../../app.h" #include "../../util/i18n.h" #include "../widgets/qr_code.h" #include "../schema/ui_schema.h" #include "../material/draw_helpers.h" #include "../theme.h" #include "imgui.h" namespace dragonx { namespace ui { // Static member initialization bool QRPopupDialog::s_open = false; std::string QRPopupDialog::s_address; std::string QRPopupDialog::s_label; uintptr_t QRPopupDialog::s_qr_texture = 0; int QRPopupDialog::s_qr_width = 0; int QRPopupDialog::s_qr_height = 0; void QRPopupDialog::show(const std::string& address, const std::string& label) { // Cleanup previous texture if (s_qr_texture != 0) { FreeQRTexture(s_qr_texture); s_qr_texture = 0; } s_open = true; s_address = address; s_label = label; // Generate new QR texture s_qr_texture = GenerateQRTexture(address.c_str(), &s_qr_width, &s_qr_height); } bool QRPopupDialog::isOpen() { return s_open; } void QRPopupDialog::close() { s_open = false; if (s_qr_texture != 0) { FreeQRTexture(s_qr_texture); s_qr_texture = 0; } } void QRPopupDialog::render(App* app) { (void)app; // Unused for now if (!s_open) return; auto& S = schema::UI(); auto win = S.window("dialogs.qr-popup"); auto qr = S.drawElement("dialogs.qr-popup", "qr-code"); auto addrInput = S.input("dialogs.qr-popup", "address-input"); auto actionBtn = S.button("dialogs.qr-popup", "action-button"); if (material::BeginOverlayDialog(TR("qr_title"), &s_open, win.width, 0.94f)) { // Label if present if (!s_label.empty()) { ImGui::TextWrapped("%s", s_label.c_str()); ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); } // Center the QR code float qr_size = qr.size > 0 ? qr.size : 280; float window_width = ImGui::GetWindowWidth(); float padding = (window_width - qr_size) / 2.0f; ImGui::SetCursorPosX(padding); // Render QR code if (s_qr_texture != 0) { ImGui::Image((ImTextureID)s_qr_texture, ImVec2(qr_size, qr_size)); } else { // Fallback: show error ImGui::BeginChild("QRPlaceholder", ImVec2(qr_size, qr_size), true); ImGui::TextWrapped("%s", TR("qr_failed")); ImGui::EndChild(); } ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); // Address display ImGui::Text("%s", TR("address_label")); // Use multiline for z-addresses if (s_address.length() > 50) { char addr_buf[512]; strncpy(addr_buf, s_address.c_str(), sizeof(addr_buf) - 1); addr_buf[sizeof(addr_buf) - 1] = '\0'; ImGui::InputTextMultiline("##QRAddress", addr_buf, sizeof(addr_buf), ImVec2(-1, addrInput.height > 0 ? addrInput.height : 60), ImGuiInputTextFlags_ReadOnly); } else { char addr_buf[128]; strncpy(addr_buf, s_address.c_str(), sizeof(addr_buf) - 1); addr_buf[sizeof(addr_buf) - 1] = '\0'; ImGui::SetNextItemWidth(-1); ImGui::InputText("##QRAddress", addr_buf, sizeof(addr_buf), ImGuiInputTextFlags_ReadOnly); } ImGui::Spacing(); // Buttons float button_width = actionBtn.width; float total_width = button_width * 2 + ImGui::GetStyle().ItemSpacing.x; float start_x = (window_width - total_width) / 2.0f; ImGui::SetCursorPosX(start_x); if (material::StyledButton(TR("copy_address"), ImVec2(button_width, 0), S.resolveFont(actionBtn.font))) { ImGui::SetClipboardText(s_address.c_str()); } ImGui::SameLine(); if (material::StyledButton(TR("close"), ImVec2(button_width, 0), S.resolveFont(actionBtn.font))) { close(); } material::EndOverlayDialog(); } // Handle window close button if (!s_open && s_qr_texture != 0) { FreeQRTexture(s_qr_texture); s_qr_texture = 0; } } } // namespace ui } // namespace dragonx