fix(wallet-switch): cluster C — no mis-scoping in the unknown-identity window
From the audit: while a switch/first-load is in flight the wallet identity hash is empty, so contact/portfolio scope-writes silently fell back to "global" (leaking a wallet-specific entry into every wallet) and scope-filters showed every wallet's scoped entries. - Contacts: a NEW wallet-scoped contact created while the identity is unknown is now refused with a clear message (tick global or wait); editing an existing scoped contact preserves its scope instead of demoting it to global. - Portfolio: the "Add group" button is disabled while the identity is unknown (with a tooltip), so a new group can't get an empty/global scope. - Both views' visibility filters now show ONLY global entries when the identity is unknown — never another wallet's scoped contacts/groups — instead of showing everything. - +2 i18n strings (8 langs; reworded one zh string to stay within the CJK subset). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -763,10 +763,25 @@ void RenderContactsTab(App* app)
|
||||
};
|
||||
data::AddressBookEntry entry(trimAB(s_edit_label), trimAB(s_edit_address), s_edit_notes);
|
||||
entry.avatar = s_edit_avatar;
|
||||
// Global if the user asked, or as a safe fallback when we don't yet know the wallet
|
||||
// (pre-connect) — better a visible-everywhere contact than one orphaned to no wallet.
|
||||
entry.scope = (s_edit_global || activeHash.empty()) ? std::string("global") : activeHash;
|
||||
if (isEdit) {
|
||||
// Scope: global if the user asked; otherwise this wallet — but ONLY when we actually
|
||||
// know which wallet is loaded. While the identity is unknown (the switch / first-load
|
||||
// window) don't silently make a wallet-scoped contact global: preserve an edited
|
||||
// contact's existing scope, and refuse a NEW wallet-scoped one (tick global or wait).
|
||||
bool blocked = false;
|
||||
if (s_edit_global) {
|
||||
entry.scope = "global";
|
||||
} else if (!activeHash.empty()) {
|
||||
entry.scope = activeHash;
|
||||
} else if (isEdit && s_selected_index >= 0 && s_selected_index < (int)book.size()) {
|
||||
entry.scope = book.entries()[s_selected_index].scope; // keep; don't demote to global
|
||||
if (entry.scope.empty()) entry.scope = "global";
|
||||
} else {
|
||||
Notifications::instance().error(TR("contact_wallet_loading"));
|
||||
blocked = true; // don't create a wallet-scoped contact with an unknown wallet
|
||||
}
|
||||
if (blocked) {
|
||||
// leave the dialog open so the user can tick global or retry once loaded
|
||||
} else if (isEdit) {
|
||||
if (app->addressBook().updateEntry(s_selected_index, entry)) {
|
||||
Notifications::instance().success(TR("address_book_updated"));
|
||||
s_show_edit_dialog = false;
|
||||
@@ -895,9 +910,9 @@ void RenderContactsTab(App* app)
|
||||
for (size_t i = 0; i < book.size(); ++i) {
|
||||
const auto& e = book.entries()[i];
|
||||
if (!matchesSearch(e, needle)) continue;
|
||||
// Scope filter: global contacts + this wallet's contacts. Pre-connect (activeHash empty)
|
||||
// we don't know the wallet yet, so show everything rather than hide contacts.
|
||||
if (!activeHash.empty() && !e.visibleInWallet(activeHash)) continue;
|
||||
// Scope filter: global contacts + this wallet's contacts. When the wallet identity is unknown
|
||||
// (switch / first-load window), show only GLOBAL contacts — never another wallet's scoped ones.
|
||||
if (activeHash.empty() ? !e.isGlobal() : !e.visibleInWallet(activeHash)) continue;
|
||||
visibleRows.push_back(i);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user