First phase of multi-wallet support: keep each wallet's data separate so loading
a different wallet no longer shows the previous one's data, and lay the metadata
groundwork for the wallet-files list.
- Address book scoped per wallet: AddressBookEntry gains a "scope" ("global" or a
wallet-identity hash); the Contacts tab shows global + current-wallet contacts
(App::activeWalletIdentityHash) with a "show in every wallet" toggle + globe
badge. Legacy entries migrate to "global". Scope-aware de-dup allows the same
address across different wallets.
- Wallet metadata index (data/wallet_index -> wallets.json): file-keyed cache of
balance / address count / identity / size / last-opened / synced-here, since
those can't be read off a wallet.dat without loading it. Populated on connect +
address refresh (change-detecting upsert). Plus an active_wallet_file setting
for the -wallet=<name> switch coming in P2.
Unit-tested (testAddressBookScope, testWalletIndex): migration, visibility filter,
scope-aware de-dup, upsert change-detection, save/reload round-trip.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Screenshot-sweep review follow-ups:
- sweepPageName() had its own page-name switch that lacked a Contacts case,
so the tab's screenshots landed under the fallback "page/" dir. Add the
case so they capture under "contacts/".
- The Z/T type badge (green/amber) washed out on light skins. Use darker,
more-saturated variants when IsLightTheme(); keep the brighter ones on dark.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 0d — the accessibility pass on the Contacts tab.
- Search box filters by label/address/notes (case-insensitive); a distinct
"no matching contacts" empty state.
- Sortable columns (ImGuiTableFlags_Sortable) — click a header to sort the
view by label/address/notes, ascending or descending.
- Keyboard nav (when the tab owns focus, no field/modal active): Up/Down move
the selection through the *visible* order, Enter edits, Delete deletes
(feeding the two-click confirm), Ctrl+C copies.
- Contrast: the address is no longer rendered as muted TextDisabled (it's the
row's key data) — normal legible text, with a coloured Z/T type badge.
Notes are legible too.
- The add/edit form focuses its first field on open (SetKeyboardFocusHere).
- The delete confirm is now visible: the Delete button relabels to
"Confirm delete?" while armed, instead of a transient toast.
Correctness: selection is tracked by STORAGE index, decoupled from the
filtered/sorted visible order, so edit/delete/copy always target the right
entry. (ImGui renders to a canvas with no OS accessibility tree, so this is a
keyboard/contrast/findability pass, not screen-reader support.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 0b. The address book was buried in Settings behind a modal dialog.
Make it a first-class "Contacts" tab (which will also become the chat
roster), rendered inline in the main content area.
- New NavPage::Contacts (after History; ICON_MD_CONTACTS) +
WalletUiSurface::Contacts. isUiSurfaceAvailable's `default: return true`
shows it in BOTH variants; uiSurfaceNeedsWalletData's default keeps it
usable before wallet data loads. All the touchpoints wired: NavPageSurface,
GetNavIconMD, the app.cpp dispatch case, the app_network.cpp tracePageName
case, and the `contacts` i18n label.
- New src/ui/windows/contacts_tab.{h,cpp}: RenderContactsTab lifts the
toolbar + table + add/edit modal out of address_book_dialog, rendered in a
BeginChild scroll region (peers_tab pattern) instead of an overlay; the
add/edit form stays a modal layered over the tab. Reuses the existing
address_book_* i18n keys and the dialogs.address-book schema.
- Delete address_book_dialog.{h,cpp}; remove its app.cpp render pump and the
dead App::show_address_book_. The Settings "Address Book…" button now
navigates to the tab (setCurrentPage) instead of opening the modal, so the
Tools & Actions grid layout is untouched.
- CMake: swap the dialog sources for contacts_tab.
Behavior-preserving move; search/sort/keyboard/contrast land in 0d. Visual
check pending the per-theme screenshot sweep.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>