diff --git a/web/index.php b/web/index.php
index 35dd2d4..6cb5216 100644
--- a/web/index.php
+++ b/web/index.php
@@ -22,7 +22,6 @@ auth_require();
Tor Relay Panel
-
Logout
@@ -391,29 +390,41 @@ async function refreshChart(){
setChartData(labels, rx, tx);
}
-async function loadReach(){
- const r = await fetch('api/reach.php');
- const j = await r.json();
- if (!j.ok) return;
- if (el.reachNick) el.reachNick.textContent = j.nickname || '—';
- if (el.reachFP) el.reachFP.textContent = j.fingerprint || '—';
- if (el.reachPort) el.reachPort.textContent = j.orport || '—';
- if (el.reachLAN) el.reachLAN.textContent = j.lan_ip || '—';
- if (el.hintPort) el.hintPort.textContent = j.orport || '—';
- if (el.hintLAN) el.hintLAN.textContent = j.lan_ip || '—';
- if (el.reachAddr) el.reachAddr.textContent = j.tor_address || '—';
- let flagStr = '—', seenStr = '—';
- if (j.onionoo && j.onionoo.found) {
- flagStr = (j.onionoo.flags || []).join(', ') || '—';
- if (j.onionoo.last_seen) seenStr = 'Last seen: ' + new Date(j.onionoo.last_seen).toLocaleString();
+async function loadReach(){
+ try{
+ const r = await fetch('api/reach.php', {cache:'no-store'});
+ const j = await r.json();
+ if (!j.ok) return false;
+
+ if (el.reachNick) el.reachNick.textContent = j.nickname || '—';
+ if (el.reachFP) el.reachFP.textContent = j.fingerprint || '—';
+ if (el.reachPort) el.reachPort.textContent = j.orport || '—';
+ if (el.reachLAN) el.reachLAN.textContent = j.lan_ip || '—';
+ if (el.hintPort) el.hintPort.textContent = j.orport || '—';
+ if (el.hintLAN) el.hintLAN.textContent = j.lan_ip || '—';
+ if (el.reachAddr) el.reachAddr.textContent = j.tor_address || '—';
+
+ let flagStr = '—', seenStr = '—';
+ if (j.onionoo && j.onionoo.found) {
+ flagStr = (j.onionoo.flags || []).join(', ') || '—';
+ if (j.onionoo.last_seen) seenStr = 'Last seen: ' + new Date(j.onionoo.last_seen).toLocaleString();
+ }
+ const running = !!(j.onionoo && j.onionoo.running);
+
+ if (el.reachBadge){
+ el.reachBadge.textContent = running ? 'Running (publicly reachable)' : (j.onionoo && j.onionoo.found ? 'Not Running yet' : 'Not in consensus yet');
+ el.reachBadge.className = 'badge ' + (running ? 'bg-success' : (j.onionoo && j.onionoo.found ? 'bg-warning' : 'bg-danger'));
+ el.reachBadge.title = 'Last checked: ' + new Date().toLocaleString();
+ }
+ if (el.reachFlags) el.reachFlags.textContent = flagStr;
+ if (el.reachSeen) el.reachSeen.textContent = seenStr;
+ if (el.reachHelp) el.reachHelp.style.display = running ? 'none' : 'block';
+
+ return running;
+ }catch(e){
+ return false;
}
- const running = !!(j.onionoo && j.onionoo.running);
- if (el.reachBadge){
- el.reachBadge.textContent = running ? 'Running (publicly reachable)' : (j.onionoo && j.onionoo.found ? 'Not Running yet' : 'Not in consensus yet');
- el.reachBadge.className = 'badge ' + (running ? 'bg-success' : (j.onionoo && j.onionoo.found ? 'bg-warning' : 'bg-danger'));
- }
- if (el.reachHelp) el.reachHelp.style.display = running ? 'none' : 'block';
}
if (el.btnEditCfg){
@@ -454,6 +465,26 @@ if (el.cfgForm){
});
}
+if (el.reachRefresh){
+ el.reachRefresh.addEventListener('click', async ()=>{
+ const btn = el.reachRefresh;
+ const originalClasses = btn.className;
+ btn.disabled = true;
+ btn.innerHTML = '
Checking…';
+
+ const running = await loadReach();
+
+ btn.className = running ? 'btn btn-sm btn-success' : 'btn btn-sm btn-danger';
+ btn.innerHTML = running ? 'Reachable ✓' : 'Not reachable ✗';
+
+ setTimeout(()=>{
+ btn.className = originalClasses;
+ btn.innerHTML = 'Check status';
+ btn.disabled = false;
+ }, 1500);
+ });
+}
+
(function initTheme(){
const t = preferredTheme();
document.documentElement.setAttribute('data-theme', t);