feat: modernize address list with drag-transfer, labels, and UX polish
- Rewrite RenderSharedAddressList with two-pass layout architecture - Add drag-to-transfer: drag address onto another to open transfer dialog - Add AddressLabelDialog with custom label text and 20-icon picker - Add AddressTransferDialog with amount input, fee, and balance preview - Add AddressMeta persistence (label, icon, sortOrder) in settings.json - Gold favorite border inset 2dp from container edge - Show hide button on all addresses, not just zero-balance - Smaller star/hide buttons to clear favorite border - Semi-transparent dragged row with context-aware tooltip - Copy-to-clipboard deferred to mouse-up (no copy on drag) - Themed colors via resolveColor() with CSS variable fallbacks - Keyboard nav (Up/Down/J/K, Enter to copy, F2 to edit label) - Add i18n keys for all new UI strings
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
@@ -141,6 +142,39 @@ public:
|
||||
void unfavoriteAddress(const std::string& addr) { favorite_addresses_.erase(addr); }
|
||||
int getFavoriteAddressCount() const { return (int)favorite_addresses_.size(); }
|
||||
|
||||
// Address metadata (labels, icons, custom ordering)
|
||||
struct AddressMeta {
|
||||
std::string label;
|
||||
std::string icon; // material icon name, e.g. "savings"
|
||||
int sortOrder = -1; // -1 = auto (use default sort)
|
||||
};
|
||||
const AddressMeta& getAddressMeta(const std::string& addr) const {
|
||||
static const AddressMeta empty{};
|
||||
auto it = address_meta_.find(addr);
|
||||
return it != address_meta_.end() ? it->second : empty;
|
||||
}
|
||||
void setAddressLabel(const std::string& addr, const std::string& label) {
|
||||
address_meta_[addr].label = label;
|
||||
}
|
||||
void setAddressIcon(const std::string& addr, const std::string& icon) {
|
||||
address_meta_[addr].icon = icon;
|
||||
}
|
||||
void setAddressSortOrder(const std::string& addr, int order) {
|
||||
address_meta_[addr].sortOrder = order;
|
||||
}
|
||||
int getNextSortOrder() const {
|
||||
int mx = -1;
|
||||
for (const auto& [k, v] : address_meta_)
|
||||
if (v.sortOrder > mx) mx = v.sortOrder;
|
||||
return mx + 1;
|
||||
}
|
||||
void swapAddressOrder(const std::string& a, const std::string& b) {
|
||||
int oa = address_meta_[a].sortOrder;
|
||||
int ob = address_meta_[b].sortOrder;
|
||||
address_meta_[a].sortOrder = ob;
|
||||
address_meta_[b].sortOrder = oa;
|
||||
}
|
||||
|
||||
// First-run wizard
|
||||
bool getWizardCompleted() const { return wizard_completed_; }
|
||||
void setWizardCompleted(bool v) { wizard_completed_ = v; }
|
||||
@@ -301,6 +335,7 @@ private:
|
||||
bool scanline_enabled_ = true;
|
||||
std::set<std::string> hidden_addresses_;
|
||||
std::set<std::string> favorite_addresses_;
|
||||
std::map<std::string, AddressMeta> address_meta_;
|
||||
bool wizard_completed_ = false;
|
||||
int auto_lock_timeout_ = 900; // 15 minutes
|
||||
int unlock_duration_ = 600; // 10 minutes
|
||||
|
||||
Reference in New Issue
Block a user