feat(network): give the "no peers" banner an honest detail and a Restart action
The no-peers banner headline ("Connected, but no network peers") was followed
by a detail line that just repeated connection_status ("Connected"/"Peers: 0"),
reading as a contradiction, and it offered no action at the exact moment the
wallet looks synced but is silently stalled at a stale height.
- NoPeers now clears the passthrough detail; App renders a translated,
actionable hint (node_banner_no_peers_detail) for this reason instead.
- When the embedded daemon is the node, offer a Restart button (re-triggers
peer discovery via the -addnode seeds); an external node stays action-less
since it is the user's own to restart.
- Update + extend the evaluator unit tests (external = no action/empty detail;
embedded = RestartNode).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -116,14 +116,20 @@ inline NodeBannerState evaluateNodeStatusBanner(const NodeBannerInputs& in) {
|
||||
|
||||
// Connected to the daemon (RPC works) but with no peer-derived tip → the node has no peers and
|
||||
// cannot learn about new blocks; it silently stalls at a stale height while everything looks
|
||||
// synced. Surface it as a recoverable warning (reconnect won't help, so no action button).
|
||||
// synced. Surface it as a recoverable warning. A plain reconnect won't help, but restarting the
|
||||
// embedded daemon re-triggers peer discovery (it re-reads the -addnode seeds), so offer that when
|
||||
// we own the node; an external node is the user's own to restart, so no button there. The detail
|
||||
// is left empty: here connection_status is just "Connected", which would contradict the
|
||||
// "no peers" headline — App renders a translated, actionable hint for this reason instead.
|
||||
if (in.connected) {
|
||||
if (!in.tip_known && in.blocks > 0) {
|
||||
s.show = true;
|
||||
s.severity = NodeBannerSeverity::Warning;
|
||||
s.reason = NodeBannerReason::NoPeers;
|
||||
s.action = NodeBannerAction::None;
|
||||
s.detail = in.connection_status;
|
||||
s.action = (in.using_embedded_daemon && in.has_daemon_controller)
|
||||
? NodeBannerAction::RestartNode
|
||||
: NodeBannerAction::None;
|
||||
s.detail.clear();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user