feat(wallets): in-app folder picker + roomier, full-width list controls
Wallets dialog refinements: - More space between wallet cards (cardGap: spacingSm -> spacingMd). - "Scan another folder" is now always visible as a full-width button (no expandable toggle) that opens the new picker. - The Create-wallet row and the scan button span the full list width, so their right edges align with the wallet cards / Open|Import buttons. New in-app folder picker (folder_picker.h): a Material-styled modal replacing the raw path input. Browse the filesystem (Up / Home / click a sub-folder), see the *.dat wallet files present + a count, and pick a folder to scan. The picker takes over the modal surface while open (the overlay framework doesn't nest); it remembers the last browsed location across opens. Fixed-height card (no auto-height feedback), UTF-8-aware truncation, full-node icons confirmed in the embedded MaterialIcons range. Added a modal-folder-picker sweep surface; verified at 100% + 150%, dark + light. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
#include "../material/colors.h"
|
||||
#include "../material/draw_helpers.h"
|
||||
#include "../material/type.h"
|
||||
#include "folder_picker.h"
|
||||
|
||||
namespace dragonx {
|
||||
namespace ui {
|
||||
@@ -39,13 +40,15 @@ public:
|
||||
s_open = true;
|
||||
s_app = app;
|
||||
s_needScan = true;
|
||||
s_newFolder[0] = '\0';
|
||||
}
|
||||
|
||||
static void hide() { s_open = false; }
|
||||
|
||||
static void render() {
|
||||
if (!s_open || !s_app) return;
|
||||
// The folder picker (opened by "Scan another folder") takes over the modal surface while
|
||||
// it's up — the overlay framework doesn't nest, so only one overlay renders at a time.
|
||||
if (FolderPicker::isOpen()) { FolderPicker::render(); return; }
|
||||
using namespace material;
|
||||
App* app = s_app;
|
||||
const float dp = Layout::dpiScale();
|
||||
@@ -62,16 +65,16 @@ public:
|
||||
const int visRows = std::min(std::max(1, (int)s_rows.size()), kMaxVisibleRows);
|
||||
const float cardPadY = Layout::spacingMd(); // roomier cards (was spacingSm)
|
||||
const float walRowH = cardPadY * 2.0f + nameFont->LegacySize + Layout::spacingSm() + metaFont->LegacySize;
|
||||
const float cardGap = Layout::spacingSm();
|
||||
const float cardGap = Layout::spacingMd(); // more breathing room between wallet cards
|
||||
// ItemSpacing is zeroed inside the list child, so the content is exactly cards + inter-card
|
||||
// gaps; a small bottom pad keeps the last card off the clip edge (no spurious scrollbar).
|
||||
const float listH = visRows * walRowH + (float)std::max(0, visRows - 1) * cardGap + Layout::spacingSm();
|
||||
|
||||
const float ctrlRow = ImGui::GetFrameHeightWithSpacing();
|
||||
const float capRow = Type().caption()->LegacySize + style.ItemSpacing.y;
|
||||
const float belowH = 3.0f * Layout::spacingSm()
|
||||
const float belowH = 4.0f * Layout::spacingSm()
|
||||
+ (capRow + ctrlRow) // Create label + input row
|
||||
+ (s_showAddFolder ? (capRow + ctrlRow) : capRow) // folder row OR toggle link
|
||||
+ ctrlRow // full-width "scan folder" button
|
||||
+ (style.ItemSpacing.y + 1.0f) // separator
|
||||
+ ctrlRow // footer buttons
|
||||
+ 6.0f * style.ItemSpacing.y; // uncounted inter-item gaps
|
||||
@@ -206,12 +209,13 @@ public:
|
||||
|
||||
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
|
||||
|
||||
// ---- Create a new wallet (primary) ----------------------------------------------------
|
||||
// ---- Create a new wallet (primary) — the input + button span the full list width -----
|
||||
const float createBtnW = 140.0f * dp;
|
||||
Type().textColored(TypeStyle::Caption, OnSurfaceMedium(), TR("wallets_new_label"));
|
||||
ImGui::SetNextItemWidth(-150.0f * dp);
|
||||
ImGui::SetNextItemWidth(listW - createBtnW - style.ItemSpacing.x);
|
||||
ImGui::InputTextWithHint("##newWalletName", TR("wallets_new_hint"), s_newName, sizeof(s_newName));
|
||||
ImGui::SameLine();
|
||||
if (StyledButton(TR("wallets_create"), ImVec2(120.0f * dp, 0))) {
|
||||
if (StyledButton(TR("wallets_create"), ImVec2(createBtnW, 0))) {
|
||||
std::string name = normalizeWalletName(s_newName);
|
||||
std::error_code ec;
|
||||
if (name.empty()) {
|
||||
@@ -228,29 +232,17 @@ public:
|
||||
|
||||
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
|
||||
|
||||
// ---- Add-folder tucked behind a toggle so it doesn't compete with Create --------------
|
||||
if (!s_showAddFolder) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, OnSurfaceMedium());
|
||||
ImGui::TextUnformatted(TR("wallets_add_folder_toggle"));
|
||||
ImGui::PopStyleColor();
|
||||
if (ImGui::IsItemHovered()) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||
if (ImGui::IsItemClicked()) s_showAddFolder = true;
|
||||
} else {
|
||||
Type().textColored(TypeStyle::Caption, OnSurfaceMedium(), TR("wallets_add_folder"));
|
||||
ImGui::SetNextItemWidth(-150.0f * dp);
|
||||
ImGui::InputTextWithHint("##walletFolder", TR("wallets_folder_hint"), s_newFolder, sizeof(s_newFolder));
|
||||
ImGui::SameLine();
|
||||
if (StyledButton(TR("wallets_add"), ImVec2(120.0f * dp, 0))) {
|
||||
// ---- Scan another folder — always visible, full-width, opens the in-app folder picker -
|
||||
if (StyledButton(TR("wallets_scan_folder"), ImVec2(listW, 0))) {
|
||||
FolderPicker::open("", [app](const std::string& dir) {
|
||||
std::error_code ec;
|
||||
std::string dir = s_newFolder;
|
||||
if (!dir.empty() && std::filesystem::is_directory(dir, ec)) {
|
||||
if (app->walletIndex().addExtraFolder(dir)) app->walletIndex().save();
|
||||
s_newFolder[0] = '\0';
|
||||
s_needScan = true;
|
||||
} else {
|
||||
Notifications::instance().warning(TR("wallets_folder_invalid"));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ImGui::Dummy(ImVec2(0, Layout::spacingSm()));
|
||||
@@ -352,9 +344,7 @@ private:
|
||||
static inline bool s_open = false;
|
||||
static inline App* s_app = nullptr;
|
||||
static inline bool s_needScan = false;
|
||||
static inline char s_newFolder[512] = "";
|
||||
static inline char s_newName[128] = "";
|
||||
static inline bool s_showAddFolder = false;
|
||||
static inline std::vector<WalletRow> s_rows;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user