feat(lite): network-tab polish, reworked key-export/QR dialogs
Network tab: glow only the active node, drop the left accent bar. Key-export dialog: fix the lite-wallet "Not connected" failure by exporting the key locally via the SDXL backend when there's no daemon; rework the layout to wrapping click-to-copy fields with a side QR (empty placeholder when hidden), 85% modal width, HRP-preserving key chunking, and a centered, emphasized warning. QR popup matched to the same sizing and click-to-copy address. Shared field rendering extracted to widgets/copy_field.h so both dialogs stay in sync. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,8 +6,10 @@
|
||||
#include "../../app.h"
|
||||
#include "../../util/i18n.h"
|
||||
#include "../widgets/qr_code.h"
|
||||
#include "../widgets/copy_field.h"
|
||||
#include "../schema/ui_schema.h"
|
||||
#include "../material/draw_helpers.h"
|
||||
#include "../layout.h"
|
||||
#include "../theme.h"
|
||||
#include "imgui.h"
|
||||
|
||||
@@ -59,12 +61,13 @@ void QRPopupDialog::render(App* app)
|
||||
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)) {
|
||||
// Match the key-export modal: 85% of the window width (divide out the dpiScale that
|
||||
// BeginOverlayDialog re-applies, so the final card is exactly 85% at any font scale).
|
||||
const float cardW = (0.85f * ImGui::GetMainViewport()->Size.x) / Layout::dpiScale();
|
||||
if (material::BeginOverlayDialog(TR("qr_title"), &s_open, cardW, 0.94f)) {
|
||||
|
||||
// Label if present
|
||||
if (!s_label.empty()) {
|
||||
@@ -74,10 +77,14 @@ void QRPopupDialog::render(App* app)
|
||||
ImGui::Spacing();
|
||||
}
|
||||
|
||||
// Center the QR code
|
||||
float qr_size = qr.size > 0 ? qr.size : 280;
|
||||
// Center the QR code (responsive — larger, to suit the wider modal).
|
||||
float window_width = ImGui::GetWindowWidth();
|
||||
float qr_size = qr.size > 0 ? (float)qr.size : 280.0f;
|
||||
const float responsive = window_width * 0.5f;
|
||||
if (responsive > qr_size) qr_size = responsive;
|
||||
if (qr_size > 420.0f) qr_size = 420.0f;
|
||||
float padding = (window_width - qr_size) / 2.0f;
|
||||
if (padding < 0.0f) padding = 0.0f;
|
||||
|
||||
ImGui::SetCursorPosX(padding);
|
||||
|
||||
@@ -95,39 +102,29 @@ void QRPopupDialog::render(App* app)
|
||||
ImGui::Separator();
|
||||
ImGui::Spacing();
|
||||
|
||||
// Address display
|
||||
// Address — click-to-copy field (same formatting as the key-export dialog).
|
||||
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);
|
||||
}
|
||||
widgets::AddressCopyField("##QRAddress", s_address);
|
||||
|
||||
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))) {
|
||||
// Buttons — size each to its label (so "Copy address" never clips), then center the pair.
|
||||
ImFont* btnFont = S.resolveFont(actionBtn.font);
|
||||
ImGui::PushFont(btnFont);
|
||||
const float btnPad = ImGui::GetStyle().FramePadding.x * 2.0f + 24.0f;
|
||||
float w_copy = ImGui::CalcTextSize(TR("copy_address")).x + btnPad;
|
||||
float w_close = ImGui::CalcTextSize(TR("close")).x + btnPad;
|
||||
ImGui::PopFont();
|
||||
if (w_copy < actionBtn.width) w_copy = actionBtn.width;
|
||||
if (w_close < actionBtn.width) w_close = actionBtn.width;
|
||||
const float total_width = w_copy + w_close + ImGui::GetStyle().ItemSpacing.x;
|
||||
ImGui::SetCursorPosX((window_width - total_width) / 2.0f);
|
||||
|
||||
if (material::StyledButton(TR("copy_address"), ImVec2(w_copy, 0), btnFont)) {
|
||||
ImGui::SetClipboardText(s_address.c_str());
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (material::StyledButton(TR("close"), ImVec2(button_width, 0), S.resolveFont(actionBtn.font))) {
|
||||
if (material::StyledButton(TR("close"), ImVec2(w_close, 0), btnFont)) {
|
||||
close();
|
||||
}
|
||||
material::EndOverlayDialog();
|
||||
|
||||
Reference in New Issue
Block a user