diff --git a/app/(app)/settings/page.tsx b/app/(app)/settings/page.tsx index ab1185a..c357703 100644 --- a/app/(app)/settings/page.tsx +++ b/app/(app)/settings/page.tsx @@ -119,24 +119,46 @@ export default function SettingsPage() { if (!confirm(`Update auf ${status?.latest} jetzt installieren?\n\nDer Server wird neu gestartet (kurze Downtime der Admin-UI). Redirects bleiben über Caddy aktiv.`)) return; setApplying(true); setMsg("Update läuft — bitte warten..."); + + // Fallback: reload after 90s no matter what (in case fetch/poll get stuck) + const fallbackReload = setTimeout(() => window.location.reload(), 90_000); + try { - const r = await fetch("/api/update/apply", { method: "POST" }); let d: { ok?: boolean; from?: string; to?: string; error?: string } = {}; - try { d = await r.json(); } catch {} - if (!r.ok || d.error) { - setMsg(`Fehler: ${d.error || r.statusText}`); + try { + const r = await fetch("/api/update/apply", { method: "POST" }); + try { d = await r.json(); } catch {} + if (!r.ok && !d.error) d.error = r.statusText; + } catch (e) { + // Connection drop = server probably restarted mid-response (legacy update.sh) + d.error = e instanceof Error ? e.message : "connection_lost"; + } + + if (d.error === "no_update") { + setMsg("Bereits auf aktueller Version."); + clearTimeout(fallbackReload); + await fetch("/api/update/check?force=1").catch(() => {}); + load(); setApplying(false); return; } - setMsg(`Update gezogen (${d.from} → ${d.to}). Server startet neu...`); - // Wait for restart, then hard-reload to drop all client cache + + if (d.error && !d.to) { + setMsg(`Fehler: ${d.error}`); + clearTimeout(fallbackReload); + setApplying(false); + return; + } + + setMsg(d.to ? `Update gezogen (${d.from} → ${d.to}). Server startet neu...` : "Server startet neu..."); await new Promise((res) => setTimeout(res, 3000)); const back = await waitForServerBack(); - setMsg(back ? "Server zurück. Lade Seite neu..." : "Restart dauert ungewöhnlich lang. Trotzdem neu laden."); + setMsg(back ? "Server zurück. Lade Seite neu..." : "Restart dauert ungewöhnlich lang — lade trotzdem neu."); + clearTimeout(fallbackReload); window.location.reload(); } catch (e) { - setMsg(`Fehler: ${e instanceof Error ? e.message : String(e)}`); - setApplying(false); + setMsg(`Fehler: ${e instanceof Error ? e.message : String(e)} — lade in 5s neu.`); + setTimeout(() => window.location.reload(), 5000); } } diff --git a/bin/nexredirect b/bin/nexredirect index 0a31f1f..8128762 100755 --- a/bin/nexredirect +++ b/bin/nexredirect @@ -25,7 +25,8 @@ nexredirect — CoreX NexRedirect CLI stop Service stoppen restart Service neu starten logs [-n N] Logs streamen (default: -f) - update [tag] Auf neueste Version (oder bestimmten Tag) + update [tag] Auf neueste Version (oder bestimmten Tag); skip wenn schon aktuell + update -f [tag] Update erzwingen auch wenn Version gleich version Aktuelle + neueste Version (GitHub) caddy reload Caddyfile neu generieren + reload caddy show Aktuellen Caddyfile anzeigen @@ -52,7 +53,25 @@ cmd_logs() { cmd_update() { require_root update - "$INSTALL_DIR/scripts/update.sh" "${1:-}" + local force=0 + local target="${1:-}" + if [[ "$target" == "-f" || "$target" == "--force" ]]; then force=1; target="${2:-}"; fi + + if [[ $force -eq 0 ]]; then + local current latest + current=$(grep -m1 '"version"' "$INSTALL_DIR/package.json" 2>/dev/null | sed -E 's/.*"version": *"([^"]+)".*/v\1/') + if [[ -n "$target" ]]; then + latest="$target" + else + latest=$(curl -fsSL https://api.github.com/repos/CoreXManagement/CoreX-NexRedirect/releases/latest 2>/dev/null \ + | grep -m1 '"tag_name"' | sed -E 's/.*"tag_name": *"([^"]+)".*/\1/') + fi + if [[ -n "$current" && "$current" == "$latest" ]]; then + echo "Bereits auf $current — nichts zu tun. Mit --force trotzdem ausführen." + return 0 + fi + fi + "$INSTALL_DIR/scripts/update.sh" "$target" } cmd_version() {