fix(ui): keep a chosen send-from address from auto-select overwrite
The Send tab auto-selected the highest-balance address on first load. When another tab had already pre-filled the source with "Send from this address", that first-load pick overwrote the user's choice, and the dropdown's selected index could drift out of step with the address that would actually be debited when the address list changed. - The send-from string is now the single source of truth. The one-shot auto-pick only fills an empty source and never replaces one the user or another tab set, and the list index is re-derived from the string each frame so it cannot desync. - An explicit "Send from this address" choice latches the auto-pick off, so the first visit cannot undo it. - A chosen source the dropdown does not list (zero balance, view-only, or the list still loading) now previews the address that will be debited instead of the "Select a source" placeholder. User-visible: a send-from address chosen from another tab survives the first load and later refresh ticks. Tests: the source resolver keeps a pre-fill on first visit, fills an empty source with the best spendable address, keeps a source missing from a short list with index -1, latches nothing while disconnected or with an empty list, and re-derives a stale index from the string. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1131,6 +1131,39 @@ void testSpendableFiltering()
|
||||
|
||||
auto includeZero = dragonx::sortedSpendableAddressIndices(addresses, false);
|
||||
EXPECT_EQ(includeZero.size(), static_cast<size_t>(3));
|
||||
|
||||
using dragonx::resolveSourceSelection;
|
||||
EXPECT_EQ(dragonx::addressIndexByString(addresses, "R-high"), 3);
|
||||
EXPECT_EQ(dragonx::addressIndexByString(addresses, "nope"), -1);
|
||||
EXPECT_EQ(dragonx::addressIndexByString(addresses, ""), -1);
|
||||
{ // a "Send from this address" pre-fill on the first visit must survive the auto-pick
|
||||
auto r = resolveSourceSelection(addresses, "zs-low", /*latched=*/false, /*connected=*/true);
|
||||
EXPECT_EQ(r.address, std::string("zs-low"));
|
||||
EXPECT_EQ(r.index, 1);
|
||||
EXPECT_TRUE(r.autoLatched);
|
||||
}
|
||||
{ // empty source -> best spendable (R-high), latched
|
||||
auto r = resolveSourceSelection(addresses, "", false, true);
|
||||
EXPECT_EQ(r.address, std::string("R-high"));
|
||||
EXPECT_EQ(r.index, 3);
|
||||
EXPECT_TRUE(r.autoLatched);
|
||||
}
|
||||
{ // a pre-fill that is not in the (short) list is kept, index -1, no re-pick
|
||||
auto r = resolveSourceSelection(addresses, "zs-gone", false, true);
|
||||
EXPECT_EQ(r.address, std::string("zs-gone"));
|
||||
EXPECT_EQ(r.index, -1);
|
||||
EXPECT_TRUE(r.autoLatched);
|
||||
}
|
||||
{ // not connected / empty list: nothing latches, pre-fill kept
|
||||
EXPECT_FALSE(resolveSourceSelection(addresses, "zs-low", false, false).autoLatched);
|
||||
EXPECT_FALSE(resolveSourceSelection({}, "zs-low", false, true).autoLatched);
|
||||
EXPECT_EQ(resolveSourceSelection({}, "zs-low", false, true).address, std::string("zs-low"));
|
||||
}
|
||||
{ // already latched + stale index: index is re-derived from the string
|
||||
auto r = resolveSourceSelection(addresses, "R-high", true, true);
|
||||
EXPECT_EQ(r.index, 3);
|
||||
EXPECT_TRUE(r.autoLatched);
|
||||
}
|
||||
}
|
||||
|
||||
// S8: deferFor() is an absolute hold, independent of the page interval (the retry-storm fix).
|
||||
|
||||
Reference in New Issue
Block a user