feat(settings): period-earnings preferences + per-address opt-in

Persists the Balance-tab earnings settings: interval (0=Hour 1=Day 2=Month
3=Year, default Day), mode (0=Inflows 1=Net, default Inflows), display
format (0=Coin 1=Coin+fiat 2=Fiat, default Coin+fiat), a global show-all
toggle (default off), and an opt-in set of addresses whose earnings column
is shown when show-all is off. All values are clamped on load and saved,
mirroring the existing favorite/hidden address sets.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-15 11:22:12 -05:00
co-authored by Claude Opus 4.8
parent 19da7d1474
commit 2ef91ea7d4
2 changed files with 40 additions and 0 deletions
+19
View File
@@ -242,6 +242,18 @@ bool Settings::load(const std::string& path)
for (const auto& a : j["favorite_addresses"])
if (a.is_string()) favorite_addresses_.insert(a.get<std::string>());
}
if (j.contains("earnings_addresses") && j["earnings_addresses"].is_array()) {
earnings_addresses_.clear();
for (const auto& a : j["earnings_addresses"])
if (a.is_string()) earnings_addresses_.insert(a.get<std::string>());
}
loadScalar(j, "earnings_interval", earnings_interval_);
earnings_interval_ = std::clamp(earnings_interval_, 0, 3);
loadScalar(j, "earnings_mode", earnings_mode_);
earnings_mode_ = std::clamp(earnings_mode_, 0, 1);
loadScalar(j, "earnings_format", earnings_format_);
earnings_format_ = std::clamp(earnings_format_, 0, 2);
loadScalar(j, "earnings_show_all", earnings_show_all_);
if (j.contains("address_meta") && j["address_meta"].is_object()) {
address_meta_.clear();
for (auto& [addr, meta] : j["address_meta"].items()) {
@@ -562,6 +574,13 @@ bool Settings::save(const std::string& path)
j["favorite_addresses"] = json::array();
for (const auto& addr : favorite_addresses_)
j["favorite_addresses"].push_back(addr);
j["earnings_addresses"] = json::array();
for (const auto& addr : earnings_addresses_)
j["earnings_addresses"].push_back(addr);
j["earnings_interval"] = earnings_interval_;
j["earnings_mode"] = earnings_mode_;
j["earnings_format"] = earnings_format_;
j["earnings_show_all"] = earnings_show_all_;
{
json meta_obj = json::object();
for (const auto& [addr, m] : address_meta_) {
+21
View File
@@ -321,6 +321,22 @@ public:
void unfavoriteAddress(const std::string& addr) { favorite_addresses_.erase(addr); }
int getFavoriteAddressCount() const { return (int)favorite_addresses_.size(); }
// Inline period-earnings (Balance tab). interval: 0=Hour 1=Day 2=Month 3=Year; mode: 0=Inflows
// 1=Net; format: 0=DRGX 1=DRGX+fiat 2=Fiat. show-all toggles the per-address earnings column for
// every address at once; earnings_addresses_ is the opt-in set shown when show-all is off.
int getEarningsInterval() const { return earnings_interval_; }
void setEarningsInterval(int v) { earnings_interval_ = (v < 0 ? 0 : (v > 3 ? 3 : v)); }
int getEarningsMode() const { return earnings_mode_; }
void setEarningsMode(int v) { earnings_mode_ = (v < 0 ? 0 : (v > 1 ? 1 : v)); }
int getEarningsFormat() const { return earnings_format_; }
void setEarningsFormat(int v) { earnings_format_ = (v < 0 ? 0 : (v > 2 ? 2 : v)); }
bool getEarningsShowAll() const { return earnings_show_all_; }
void setEarningsShowAll(bool v) { earnings_show_all_ = v; }
const std::set<std::string>& getEarningsAddresses() const { return earnings_addresses_; }
bool isAddressEarningsShown(const std::string& addr) const { return earnings_addresses_.count(addr) > 0; }
void showAddressEarnings(const std::string& addr) { earnings_addresses_.insert(addr); }
void hideAddressEarnings(const std::string& addr) { earnings_addresses_.erase(addr); }
// Address metadata (labels, icons, custom ordering)
struct AddressMeta {
std::string label;
@@ -712,6 +728,11 @@ private:
bool console_auto_focus_ = false; // focus the command input when the Console tab is opened (opt-in)
std::set<std::string> hidden_addresses_;
std::set<std::string> favorite_addresses_;
std::set<std::string> earnings_addresses_; // per-address earnings column opt-in (when show-all off)
int earnings_interval_ = 1; // 0=Hour 1=Day 2=Month 3=Year
int earnings_mode_ = 0; // 0=Inflows 1=Net
int earnings_format_ = 1; // 0=DRGX 1=DRGX+fiat 2=Fiat
bool earnings_show_all_ = false;
std::map<std::string, AddressMeta> address_meta_;
bool wizard_completed_ = false;
bool seed_backup_reminded_ = false;