Merge pull request #255 from naturallaw777/copilot/fix-tile-loading-spinner

Show per-tile “Checking…” state while domain reachability cache warms up
This commit is contained in:
Sovran_Systems
2026-04-15 13:17:15 -05:00
committed by GitHub
3 changed files with 23 additions and 3 deletions
+20 -3
View File
@@ -2378,6 +2378,16 @@ async def api_services():
domain = val if val else None
except OSError:
domain = None
cached_reachable: bool | None = None
domain_reachability = None
if needs_domain and domain and enabled:
cached_reachable = _is_domain_reachable_cached(domain)
if cached_reachable is None:
domain_reachability = "checking"
elif cached_reachable:
domain_reachability = "reachable"
else:
domain_reachability = "unreachable"
# Compute composite health
sync_progress: float | None = None
@@ -2408,10 +2418,15 @@ async def api_services():
_cached_external_ip,
)
if not has_domain_issues and domain:
cached_reachable = _is_domain_reachable_cached(domain)
if cached_reachable is False:
has_domain_issues = True
health = "needs_attention" if (has_port_issues or has_domain_issues) else "healthy"
if has_port_issues or has_domain_issues:
health = "needs_attention"
else:
if needs_domain and domain:
health = "checking_reachability" if cached_reachable is None else "healthy"
else:
health = "healthy"
# Check Bitcoin IBD state
if unit == "bitcoind.service" and enabled:
sync = await loop.run_in_executor(None, _get_bitcoin_sync_info)
@@ -2434,7 +2449,6 @@ async def api_services():
_cached_external_ip,
)
if not has_domain_issues and domain:
cached_reachable = _is_domain_reachable_cached(domain)
if cached_reachable is False:
has_domain_issues = True
has_port_issues = False
@@ -2451,6 +2465,8 @@ async def api_services():
break
if has_domain_issues or has_port_issues:
health = "needs_attention"
elif needs_domain and domain:
health = "checking_reachability" if cached_reachable is None else "inactive"
else:
health = "inactive"
elif status == "failed":
@@ -2471,6 +2487,7 @@ async def api_services():
"port_requirements": port_requirements,
"needs_domain": needs_domain,
"domain": domain,
"domain_reachability": domain_reachability,
}
if sync_ibd is not None:
service_data["sync_ibd"] = sync_ibd
@@ -95,6 +95,7 @@
.status-dot.disabled { background-color: var(--grey); }
.status-dot.needs-attention { background-color: var(--yellow); }
.status-dot.syncing { background-color: #f5a623; animation: pulse-badge 1.5s infinite; }
.status-dot.checking-reachability { background-color: var(--accent-color); animation: pulse-badge 1s infinite; }
/* ── Bitcoin IBD sync progress bar ──────────────────────────────── */
@@ -14,6 +14,7 @@ function statusClass(health) {
if (health === "disabled") return "disabled";
if (health === "syncing") return "syncing";
if (STATUS_LOADING_STATES.has(health)) return "loading";
if (health === "checking_reachability") return "checking-reachability";
return "unknown";
}
@@ -27,6 +28,7 @@ function statusText(health, enabled) {
if (health === "syncing") return "Syncing\u2026";
if (!health || health === "unknown") return "Unknown";
if (STATUS_LOADING_STATES.has(health)) return health;
if (health === "checking_reachability") return "Checking\u2026";
return health;
}