diff --git a/src/app.cpp b/src/app.cpp index 8c0b331..d767a8f 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -479,7 +479,18 @@ void App::update() if (!lite_autoopen_done_) { lite_autoopen_done_ = true; if (!lite_wallet_->walletOpen() && lite_wallet_->walletExists()) { - lite_wallet_->openWallet(wallet::LiteWalletOpenRequest{}); + const auto openResult = lite_wallet_->openWallet(wallet::LiteWalletOpenRequest{}); + // Surface why an existing wallet failed to open (e.g. the lightwalletd server + // is unreachable) โ€” otherwise the UI just shows a silent "disconnected" spinner. + if (!openResult.ok && !openResult.walletReady) { + lite_open_error_ = !openResult.error.empty() ? openResult.error + : (!openResult.status.message.empty() + ? openResult.status.message + : "Could not open the wallet"); + DEBUG_LOGF("[Lite] auto-open failed: %s\n", lite_open_error_.c_str()); + ui::Notifications::instance().error( + std::string("Wallet open failed: ") + lite_open_error_, 8.0f); + } } } @@ -488,6 +499,7 @@ void App::update() // A wallet is open only after a successful backend init against the lite server, so this // is a non-blocking proxy for "lite backend operational". state_.connected = lite_wallet_->walletOpen(); + if (state_.connected) lite_open_error_.clear(); // opened successfully โ€” clear any prior error // Suppress the status bar's full-node connection-detail line in lite ("" and "Connected" // are both hidden); the connected/no-wallet indicator + sync status convey lite state. connection_status_ = state_.connected ? "Connected" : ""; diff --git a/src/app.h b/src/app.h index 885f7da..1a7ef1f 100644 --- a/src/app.h +++ b/src/app.h @@ -157,6 +157,8 @@ public: config::Settings* settings() { return settings_.get(); } // Lite wallet controller (non-null only in lite builds with a linked backend). wallet::LiteWalletController* liteWallet() { return lite_wallet_.get(); } + // Reason the lite wallet failed to auto-open this session (empty if none / opened OK). + const std::string& liteOpenError() const { return lite_open_error_; } // Show the lite send-time unlock modal (called when a spend is attempted on a locked wallet). void requestLiteUnlock() { lite_unlock_prompt_ = true; } // (Re)build the lite controller from current settings so a changed lite-server selection @@ -442,6 +444,9 @@ private: // One-shot guard: auto-open an existing lite wallet on the first update() tick (kept off // init() so a slow initialize_existing network call doesn't freeze startup before the window). bool lite_autoopen_done_ = false; + // Reason an existing lite wallet failed to auto-open (e.g. server unreachable). Surfaced in + // the UI so a stuck "disconnected" state isn't silent; cleared once a wallet opens. + std::string lite_open_error_; // Lite first-run welcome prompt: dismissed for the session once the user picks an action. bool lite_firstrun_dismissed_ = false; // Lite send-time unlock: set to show the unlock modal when a spend is attempted while locked. diff --git a/src/ui/windows/network_tab.cpp b/src/ui/windows/network_tab.cpp index 985b11b..4cda491 100644 --- a/src/ui/windows/network_tab.cpp +++ b/src/ui/windows/network_tab.cpp @@ -122,10 +122,14 @@ void RenderLiteNetworkTab(App* app) OnSurfaceMedium(), inUse.c_str()); // Bottom row: sync detail + (while syncing) a thin progress bar. - char syncBuf[96]; - if (!connected) - snprintf(syncBuf, sizeof(syncBuf), "%s: %s", TR("lite_net_sync_label"), TR("lite_net_no_wallet")); - else if (sync.syncing) + char syncBuf[160]; + if (!connected) { + // If an auto-open actually failed, show why (e.g. server unreachable) instead of a + // bare "no wallet open" โ€” otherwise the disconnected state is silent/confusing. + const std::string& openErr = app->liteOpenError(); + snprintf(syncBuf, sizeof(syncBuf), "%s: %s", TR("lite_net_sync_label"), + openErr.empty() ? TR("lite_net_no_wallet") : openErr.c_str()); + } else if (sync.syncing) snprintf(syncBuf, sizeof(syncBuf), "%s: %.1f%% ยท %d / %d", TR("lite_net_sync_label"), sync.verification_progress * 100.0, sync.blocks, sync.headers); else