diff --git a/src/app.cpp b/src/app.cpp index 726fb02..e7a2d48 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -454,6 +454,10 @@ bool App::init() tryConnect(); } + // Populate the shared contact store from disk (per-variant addressbook.json). + // Idempotent; a missing file is fine (returns true). Purely local — no daemon/RPC dependency. + address_book_.load(); + DEBUG_LOGF("Initialization complete\n"); return true; } diff --git a/src/app.h b/src/app.h index 3e135c7..99eb7a2 100644 --- a/src/app.h +++ b/src/app.h @@ -14,6 +14,7 @@ #include #include #include "data/transaction_history_cache.h" +#include "data/address_book.h" #include "data/wallet_state.h" #include "rpc/connection.h" #include "services/network_refresh_service.h" @@ -175,6 +176,10 @@ public: WalletState& state() { return state_; } const WalletState& state() const { return state_; } const WalletState& getWalletState() const { return state_; } + // Shared contact store (Contacts tab / Send picker / future Chat roster). App-owned so + // every surface reads one source of truth instead of a per-dialog singleton. + data::AddressBook& addressBook() { return address_book_; } + const data::AddressBook& addressBook() const { return address_book_; } // Connection state (convenience wrappers) bool isConnected() const { return state_.connected; } @@ -814,6 +819,7 @@ private: // PIN vault std::unique_ptr vault_; data::TransactionHistoryCache transaction_history_cache_; + data::AddressBook address_book_; // shared contact store; loaded once in init(), self-saves on mutation std::string pending_transaction_history_cache_passphrase_; bool transaction_history_cache_loaded_ = false; diff --git a/src/ui/windows/address_book_dialog.cpp b/src/ui/windows/address_book_dialog.cpp index 5ebeba8..2b0be1b 100644 --- a/src/ui/windows/address_book_dialog.cpp +++ b/src/ui/windows/address_book_dialog.cpp @@ -12,7 +12,6 @@ #include "../material/draw_helpers.h" #include "imgui.h" #include -#include namespace dragonx { namespace ui { @@ -26,17 +25,6 @@ char AddressBookDialog::s_edit_label[128] = ""; char AddressBookDialog::s_edit_address[512] = ""; char AddressBookDialog::s_edit_notes[512] = ""; -// Shared address book instance -static std::unique_ptr s_address_book; - -static data::AddressBook& getAddressBook() { - if (!s_address_book) { - s_address_book = std::make_unique(); - s_address_book->load(); - } - return *s_address_book; -} - static void copyEditField(char* dest, size_t destSize, const std::string& source) { if (destSize == 0) return; std::strncpy(dest, source.c_str(), destSize - 1); @@ -49,9 +37,9 @@ void AddressBookDialog::show() s_selected_index = -1; s_show_add_dialog = false; s_show_edit_dialog = false; - - // Reload address book - getAddressBook().load(); + // The address book is App-owned and loaded once at startup (App::init); it stays + // authoritative for the app lifetime and self-saves on every mutation, so there is + // nothing to reload here. (show() is static and has no App* to reach it anyway.) } bool AddressBookDialog::isOpen() @@ -61,8 +49,6 @@ bool AddressBookDialog::isOpen() void AddressBookDialog::render(App* app) { - (void)app; // May use for send-to feature later - if (!s_open) return; auto& S = schema::UI(); @@ -137,14 +123,14 @@ void AddressBookDialog::render(App* app) }; data::AddressBookEntry entry(trimAB(s_edit_label), trimAB(s_edit_address), s_edit_notes); if (isEdit) { - if (getAddressBook().updateEntry(s_selected_index, entry)) { + if (app->addressBook().updateEntry(s_selected_index, entry)) { Notifications::instance().success(TR("address_book_updated")); s_show_edit_dialog = false; } else { Notifications::instance().error(TR("address_book_update_failed")); } } else { - if (getAddressBook().addEntry(entry)) { + if (app->addressBook().addEntry(entry)) { Notifications::instance().success(TR("address_book_added")); s_show_add_dialog = false; } else { @@ -165,7 +151,7 @@ void AddressBookDialog::render(App* app) }; if (material::BeginOverlayDialog(TR("address_book_title"), &s_open, win.width, 0.94f)) { - auto& book = getAddressBook(); + auto& book = app->addressBook(); // Toolbar if (material::StyledButton(TR("address_book_add_new"), ImVec2(0,0), S.resolveFont(actionBtn.font))) {