From 3504ca59c85168d12cb96b0f32ff04a34589a8f3 Mon Sep 17 00:00:00 2001 From: boban Date: Sat, 25 Oct 2025 15:31:50 +0200 Subject: [PATCH] =?UTF-8?q?Fix:=20Mailbox=20Stats=20=C3=BCber=20Dovecot=20?= =?UTF-8?q?mit=20config/mailpool.php?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Console/Commands/CheckUpdates.php | 27 - app/Livewire/Ui/System/UpdateCard.php | 1483 ++++------------- .../livewire/ui/system/update-card.blade.php | 256 ++- 3 files changed, 483 insertions(+), 1283 deletions(-) diff --git a/app/Console/Commands/CheckUpdates.php b/app/Console/Commands/CheckUpdates.php index de07c78..82e45ee 100644 --- a/app/Console/Commands/CheckUpdates.php +++ b/app/Console/Commands/CheckUpdates.php @@ -89,31 +89,4 @@ class CheckUpdates extends Command $v = preg_replace('/-.*$/', '', $v); // Build-/dirty-Suffix abschneiden return $v !== '' ? $v : null; } -// public function handle(): int -// { -// $appPath = base_path(); -// $current = trim(@file_get_contents(base_path('VERSION'))) ?: '0.0.0'; -// // newest tag from origin (sorted semver-friendly) -// $latest = trim(shell_exec( -// "cd {$appPath} && git fetch --tags --quiet origin && git tag --list | sort -V | tail -n1" -// ) ?? ''); -// -// // Tags haben usually ein 'v' Prefix – entfernen -// $latest = ltrim($latest, 'v'); -// -// if (!$latest) { -// $this->warn('Keine Release-Tags gefunden.'); -// cache()->forget('mailwolt.update_available'); -// return 0; -// } -// -// if (version_compare($latest, $current, '>')) { -// cache()->forever('mailwolt.update_available', $latest); -// $this->info("Update verfügbar: {$latest} (installiert: {$current})"); -// } else { -// cache()->forget('mailwolt.update_available'); -// $this->info("Aktuell (installiert: {$current})."); -// } -// return 0; -// } } diff --git a/app/Livewire/Ui/System/UpdateCard.php b/app/Livewire/Ui/System/UpdateCard.php index 01a24dc..12206e1 100644 --- a/app/Livewire/Ui/System/UpdateCard.php +++ b/app/Livewire/Ui/System/UpdateCard.php @@ -1,63 +1,161 @@ reloadVersionsAndStatus(); $this->recompute(); + $this->progressLine = $this->tailUpdateLog(); - // falls ein Update bereits läuft (State-Datei existiert), gleich “running” zeigen if ($this->running) { $this->state = 'running'; } + + $this->recomputeUi(); } + public function render() + { + return view('livewire.ui.system.update-card'); + } + + /* ================== Aktionen ================== */ + + public function runUpdate(): void + { + // evtl. alte Einträge aufräumen + Cache::forget('mailwolt.update_available'); + Cache::put($this->cacheStartedAtKey, time(), now()->addHour()); + + // Wrapper starten (setzt /var/lib/mailwolt/update/{state,rc} und schreibt Versionen) + @shell_exec('nohup sudo -n /usr/local/sbin/mailwolt-update >/dev/null 2>&1 &'); + + // Sofort ins Running gehen + $this->latest = null; + $this->displayLatest = null; + $this->hasUpdate = false; + $this->state = 'running'; + $this->running = true; + $this->errorLine = null; + $this->progressLine = 'Update gestartet …'; + + $this->recomputeUi(); + } + + public function pollUpdate(): void + { + // 1) aktuellen Wrapper-Status einlesen + $this->refreshLowLevelState(); + + // 2) Failsafe + $started = (int)Cache::get($this->cacheStartedAtKey, 0); + if ($this->running && $started > 0 && (time() - $started) > $this->failsafeSeconds) { + $this->running = false; + $this->rc ??= 0; // wenn unklar, als erfolgreich werten + } + + // 3) Abschluss? + if (!$this->running) { + Cache::forget($this->cacheStartedAtKey); + + // Nachlauf: Versionen & Vergleich neu aufbauen + $this->reloadVersionsAndStatus(); + $this->recompute(); + + if ($this->rc === 0 && !$this->postActionsDone) { + // Dienste neu starten (asynchron) + @shell_exec('nohup php /var/www/mailwolt/artisan mailwolt:restart-services >/dev/null 2>&1 &'); + $this->postActionsDone = true; + + $ver = $this->displayCurrent ?? 'aktuelle Version'; + $this->dispatch('toast', + type: 'success', + title: 'Update erfolgreich', + text: "MailWolt wurde auf {$ver} aktualisiert.", + badge: 'System', + duration: 4000 + ); + } elseif ($this->rc !== null && $this->rc !== 0 && !$this->postActionsDone) { + // Fehlerfall + $this->postActionsDone = true; + $this->errorLine = "Update fehlgeschlagen (rc={$this->rc})."; + $this->dispatch('toast', + type: 'error', + title: 'Update fehlgeschlagen', + text: $this->progressLine ?: 'Bitte Logs prüfen: /var/log/mailwolt-update.log', + badge: 'System', + duration: 0 + ); + } + + $this->state = 'idle'; + } + + // UI bei jedem Poll neu ableiten + $this->recomputeUi(); + } + + /* ================== Helpers ================== */ + protected function reloadVersionsAndStatus(): void { $this->current = $this->readCurrentVersion(); - // Update-Checker soll beide Keys schreiben: - // - updates:latest (normiert, ohne v) - // - updates:latest_raw (Original) + // Update-Checker schreibt: + // - updates:latest (normiert) + // - updates:latest_raw (original) $latNorm = Cache::get('updates:latest'); - $latRaw = Cache::get('updates:latest_raw'); + $latRaw = Cache::get('updates:latest_raw'); - // Falls dein alter Key noch benutzt wird, weiter kompatibel: + // Legacy-Fallback if (!$latNorm && ($legacy = Cache::get('mailwolt.update_available'))) { $latNorm = $this->normalizeVersion($legacy); - $latRaw = $legacy; + $latRaw = $legacy; } - $this->latest = $latNorm ?: null; // für Vergleiche - $this->displayLatest = $latRaw ?: ($latNorm ? 'v'.$latNorm : null); + $this->latest = $latNorm ?: null; + $this->displayLatest = $latRaw ?: ($latNorm ? 'v' . $latNorm : null); $this->refreshLowLevelState(); } @@ -71,39 +169,84 @@ class UpdateCard extends Component ? version_compare($latNorm, $curNorm, '>') : false; - // Anzeige immer hübsch mit "v", Vergleich bleibt normiert - $this->displayCurrent = $curNorm ? 'v'.$curNorm : null; + $this->displayCurrent = $curNorm ? 'v' . $curNorm : null; - // displayLatest NICHT mehr vom hasUpdate abhängig machen – bleibt informativ sichtbar if (!$this->displayLatest && $latNorm) { - $this->displayLatest = 'v'.$latNorm; + $this->displayLatest = 'v' . $latNorm; } } + protected function recomputeUi(): void + { + if ($this->state === 'running') { + $this->badgeText = 'Update läuft'; + $this->badgeIcon = 'ph-arrows-clockwise animate-spin'; + $this->badgeClass = 'text-sky-200 bg-sky-500/10 border-sky-400/30'; + $this->showButton = true; + $this->buttonDisabled = true; + $this->buttonLabel = 'Update läuft …'; + return; + } + + if ($this->rc !== null && $this->rc !== 0) { + $this->badgeText = 'Fehlgeschlagen'; + $this->badgeIcon = 'ph-warning-circle'; + $this->badgeClass = 'text-rose-200 bg-rose-500/10 border-rose-400/30'; + $this->showButton = true; + $this->buttonDisabled = false; + $this->buttonLabel = 'Erneut versuchen'; + return; + } + + if ($this->hasUpdate) { + $this->badgeText = 'Update verfügbar'; + $this->badgeIcon = 'ph-arrow-fat-line-up'; + $this->badgeClass = 'text-yellow-200 bg-yellow-500/10 border-yellow-400/30'; + $this->showButton = true; + $this->buttonDisabled = false; + $this->buttonLabel = 'Jetzt aktualisieren'; + return; + } + + // Aktuell + $this->badgeText = 'Aktuell'; + $this->badgeIcon = 'ph-check-circle'; + $this->badgeClass = 'text-emerald-200 bg-emerald-500/10 border-emerald-400/30'; + $this->showButton = false; + $this->buttonDisabled = true; + $this->buttonLabel = ''; + } + protected function finishUiIfNoUpdate(): void { if (!$this->hasUpdate) { $this->state = 'idle'; - $cur = $this->displayCurrent ?? '–'; - $this->message = "Du bist auf dem neuesten Stand ({$cur})"; - $this->messagePositive = true; - - // Nur den alten Legacy-Key aufräumen - Cache::forget('mailwolt.update_available'); + Cache::forget('mailwolt.update_available'); // Legacy-Key } } + protected function refreshLowLevelState(): void + { + $state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: ''); + $this->running = ($state === 'running'); + + $rcRaw = @trim(@file_get_contents('/var/lib/mailwolt/update/rc') ?: ''); + $this->rc = is_numeric($rcRaw) ? (int)$rcRaw : null; + + $this->progressLine = $this->tailUpdateLog(); + } + protected function readCurrentVersion(): ?string { - // 1) Wrapper-Datei (normiert, ohne „v“) + // 1) normierte Version vom Wrapper $v = @trim(@file_get_contents(self::VERSION_FILE) ?: ''); if ($v !== '') return $v; - // 2) Raw -> normieren + // 2) raw -> normieren $raw = @trim(@file_get_contents(self::VERSION_FILE_RAW) ?: ''); if ($raw !== '') return $this->normalizeVersion($raw); - // 3) Fallback build.info (format: "version=…") + // 3) build.info $build = @file_get_contents(self::BUILD_INFO); if ($build) { foreach (preg_split('/\R+/', $build) as $line) { @@ -114,7 +257,7 @@ class UpdateCard extends Component } } - // 4) Noch ein letzter Fallback + // 4) Fallback auf config(app.version) $v = $this->normalizeVersion(config('app.version') ?: ''); return $v ?: null; } @@ -125,129 +268,169 @@ class UpdateCard extends Component $v = trim($v); if ($v === '') return null; - // führendes v entfernen, Build-Suffixe (z.B. "-3-gabcd" oder "-dirty") kappen - $v = ltrim($v, "vV \t\n\r\0\x0B"); - $v = preg_replace('/-.*$/', '', $v); // alles nach erster '-' weg + $v = ltrim($v, "vV \t\n\r\0\x0B"); // führendes v weg + $v = preg_replace('/-.*$/', '', $v); // Build-/dirty-Suffix kappen return $v !== '' ? $v : null; } - public function runUpdate(): void + /** Einzeilige letzte Log-Zeile hübsch aufbereitet */ + protected function tailUpdateLog(): ?string { - Cache::forget('mailwolt.update_available'); - Cache::put($this->cacheStartedAtKey, time(), now()->addHour()); + $p = self::UPDATE_LOG; + if (!is_readable($p)) return null; - // Name korrigiert: Wrapper ist /usr/local/sbin/mailwolt-update - @shell_exec('nohup sudo -n /usr/local/sbin/mailwolt-update >/dev/null 2>&1 &'); + $lines = @file($p, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + if (!$lines || !count($lines)) return null; - $this->latest = null; - $this->displayLatest = null; - $this->hasUpdate = false; - $this->state = 'running'; - $this->running = true; - $this->message = 'Update läuft …'; + $last = trim(end($lines)); + + // Kosmetik + $last = preg_replace('/^\[\w\]\s*/', '', $last); // "[i] " etc. + $last = preg_replace('/^=+ .*? =+\s*$/', 'Update beendet', $last); // Banner zusammenfassen + $last = preg_replace('/^\d{4}-\d{2}-\d{2}T[^ ]+\s*::\s*/', '', $last); // "2025-.. :: " entfernen + + return Str::limit($last, 120); } - - protected function refreshLowLevelState(): void - { - // Wrapper-Status lesen - $state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: ''); - - // Läuft, wenn Datei "running" enthält – alles andere gilt als nicht laufend - $this->running = ($state === 'running'); - - // Rückgabecode (nur gesetzt, wenn Update beendet ist) - $rcRaw = @trim(@file_get_contents('/var/lib/mailwolt/update/rc') ?: ''); - $this->rc = is_numeric($rcRaw) ? (int)$rcRaw : null; - } - - public function pollUpdate(): void - { - // 1) Low-Level Status vom Wrapper (/var/lib/mailwolt/update/{state,rc}) - $this->refreshLowLevelState(); - - // 2) failsafe: wenn zu lange läuft, als beendet markieren - $started = (int) Cache::get($this->cacheStartedAtKey, 0); - if ($this->running && $started > 0 && (time() - $started) > $this->failsafeSeconds) { - $this->running = false; - $this->rc ??= 0; // notfalls als “erfolgreich” werten - } - - // 3) Wenn nicht mehr running ⇒ Abschluss behandeln - if (!$this->running) { - Cache::forget($this->cacheStartedAtKey); - - // Versionen neu laden und “hasUpdate” neu berechnen - $this->reloadVersionsAndStatus(); - $this->recompute(); - - // 3a) Erfolg: jetzt erst Dienste neu starten - if ($this->rc === 0 && !$this->postActionsDone) { - // Restart asynchron starten (dein Artisan-Command macht systemctl etc.) - @shell_exec('nohup php /var/www/mailwolt/artisan mailwolt:restart-services >/dev/null 2>&1 &'); - $this->postActionsDone = true; - - // Toast - $ver = $this->displayCurrent ?? 'aktuelle Version'; - $this->dispatch('toast', - type: 'success', - title: 'Update erfolgreich', - text: "MailWolt wurde auf {$ver} aktualisiert. Dienste werden neu gestartet …", - badge: 'System', - duration: 5000 - ); - - // Seite nach 5s neu laden - $this->dispatch('reload-page', delay: 5000); - } - // 3b) Fehler: Meldung zeigen - elseif ($this->rc !== null && $this->rc !== 0 && !$this->postActionsDone) { - $this->postActionsDone = true; - $this->dispatch('toast', - type: 'error', - title: 'Update fehlgeschlagen', - text: "Update ist mit Rückgabecode {$this->rc} fehlgeschlagen. Bitte Logs prüfen.", - badge: 'System', - duration: 0 - ); - } - - // 4) UI zurück auf idle - $this->state = 'idle'; - } - } - } - - +//namespace App\Livewire\Ui\System; +// +//use Illuminate\Support\Facades\Artisan; +//use Illuminate\Support\Facades\Cache; +//use Livewire\Component; +// +//class UpdateCard extends Component +//{ +// public ?string $current = null; +// public ?string $latest = null; +// public ?string $displayCurrent = null; +// public ?string $displayLatest = null; +// +// public bool $hasUpdate = false; +// public string $state = 'idle'; +// public ?string $message = null; +// public ?bool $messagePositive = null; +// +// public bool $running = false; +// public ?int $rc = null; +// +// // NEU: UI-Properties (nur fürs Blade ausgeben) +// public string $badgeText = ''; +// public string $badgeClass = ''; +// public string $badgeIcon = ''; +// public bool $showButton = false; +// public bool $buttonDisabled = false; +// public string $buttonLabel = ''; +// public ?string $progressLine = null; // Einzeiler unter der Version +// public ?string $errorLine = null; // optionaler Fehlertext +// +// public bool $postActionsDone = false; +// +// protected string $cacheStartedAtKey = 'mw.update.started_at'; +// protected int $failsafeSeconds = 20 * 60; +// private const VERSION_FILE = '/var/lib/mailwolt/version'; // normiert, ohne "v" +// private const VERSION_FILE_RAW = '/var/lib/mailwolt/version_raw'; // original ("v1.0.25" o.ä.) +// private const BUILD_INFO = '/etc/mailwolt/build.info'; // Fallback +// // public function mount(): void // { // $this->reloadVersionsAndStatus(); // $this->recompute(); -// if ($this->running) $this->state = 'running'; +// +// // falls ein Update bereits läuft (State-Datei existiert), gleich “running” zeigen +// if ($this->running) { +// $this->state = 'running'; +// } // } // -// public function render() +// protected function reloadVersionsAndStatus(): void // { -// return view('livewire.ui.system.update-card'); -// } +// $this->current = $this->readCurrentVersion(); // -// /* ========== Aktionen ========== */ +// // Update-Checker soll beide Keys schreiben: +// // - updates:latest (normiert, ohne v) +// // - updates:latest_raw (Original) +// $latNorm = Cache::get('updates:latest'); +// $latRaw = Cache::get('updates:latest_raw'); // -// public function refreshState(): void -// { -// $this->state = 'running'; -// $this->message = 'Prüfe auf Updates …'; -// $this->messagePositive = null; -// -// try { -// Artisan::call('mailwolt:check-updates'); -// } catch (\Throwable $e) { -// // kein fataler Abbruch +// // Falls dein alter Key noch benutzt wird, weiter kompatibel: +// if (!$latNorm && ($legacy = Cache::get('mailwolt.update_available'))) { +// $latNorm = $this->normalizeVersion($legacy); +// $latRaw = $legacy; // } // -// $this->reloadVersionsAndStatus(); -// $this->recompute(); -// $this->finishUiIfNoUpdate(); +// $this->latest = $latNorm ?: null; // für Vergleiche +// $this->displayLatest = $latRaw ?: ($latNorm ? 'v'.$latNorm : null); +// +// $this->refreshLowLevelState(); +// } +// +// protected function recompute(): void +// { +// $curNorm = $this->normalizeVersion($this->current); +// $latNorm = $this->normalizeVersion($this->latest); +// +// $this->hasUpdate = ($curNorm && $latNorm) +// ? version_compare($latNorm, $curNorm, '>') +// : false; +// +// // Anzeige immer hübsch mit "v", Vergleich bleibt normiert +// $this->displayCurrent = $curNorm ? 'v'.$curNorm : null; +// +// // displayLatest NICHT mehr vom hasUpdate abhängig machen – bleibt informativ sichtbar +// if (!$this->displayLatest && $latNorm) { +// $this->displayLatest = 'v'.$latNorm; +// } +// } +// +// protected function finishUiIfNoUpdate(): void +// { +// if (!$this->hasUpdate) { +// $this->state = 'idle'; +// $cur = $this->displayCurrent ?? '–'; +// $this->message = "Du bist auf dem neuesten Stand ({$cur})"; +// $this->messagePositive = true; +// +// // Nur den alten Legacy-Key aufräumen +// Cache::forget('mailwolt.update_available'); +// } +// } +// +// protected function readCurrentVersion(): ?string +// { +// // 1) Wrapper-Datei (normiert, ohne „v“) +// $v = @trim(@file_get_contents(self::VERSION_FILE) ?: ''); +// if ($v !== '') return $v; +// +// // 2) Raw -> normieren +// $raw = @trim(@file_get_contents(self::VERSION_FILE_RAW) ?: ''); +// if ($raw !== '') return $this->normalizeVersion($raw); +// +// // 3) Fallback build.info (format: "version=…") +// $build = @file_get_contents(self::BUILD_INFO); +// if ($build) { +// foreach (preg_split('/\R+/', $build) as $line) { +// if (str_starts_with($line, 'version=')) { +// $v = $this->normalizeVersion(trim(substr($line, 8))); +// if ($v) return $v; +// } +// } +// } +// +// // 4) Noch ein letzter Fallback +// $v = $this->normalizeVersion(config('app.version') ?: ''); +// return $v ?: null; +// } +// +// protected function normalizeVersion(?string $v): ?string +// { +// if ($v === null) return null; +// $v = trim($v); +// if ($v === '') return null; +// +// // führendes v entfernen, Build-Suffixe (z.B. "-3-gabcd" oder "-dirty") kappen +// $v = ltrim($v, "vV \t\n\r\0\x0B"); +// $v = preg_replace('/-.*$/', '', $v); // alles nach erster '-' weg +// return $v !== '' ? $v : null; // } // // public function runUpdate(): void @@ -255,7 +438,8 @@ class UpdateCard extends Component // Cache::forget('mailwolt.update_available'); // Cache::put($this->cacheStartedAtKey, time(), now()->addHour()); // -// @shell_exec('nohup sudo -n /usr/local/sbin/mw-update >/dev/null 2>&1 &'); +// // Name korrigiert: Wrapper ist /usr/local/sbin/mailwolt-update +// @shell_exec('nohup sudo -n /usr/local/sbin/mailwolt-update >/dev/null 2>&1 &'); // // $this->latest = null; // $this->displayLatest = null; @@ -265,37 +449,61 @@ class UpdateCard extends Component // $this->message = 'Update läuft …'; // } // -// public function tick(): void +// protected function refreshLowLevelState(): void // { +// // Wrapper-Status lesen +// $state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: ''); +// +// // Läuft, wenn Datei "running" enthält – alles andere gilt als nicht laufend +// $this->running = ($state === 'running'); +// +// // Rückgabecode (nur gesetzt, wenn Update beendet ist) +// $rcRaw = @trim(@file_get_contents('/var/lib/mailwolt/update/rc') ?: ''); +// $this->rc = is_numeric($rcRaw) ? (int)$rcRaw : null; +// } +// +// public function pollUpdate(): void +// { +// // 1) Low-Level Status vom Wrapper (/var/lib/mailwolt/update/{state,rc}) // $this->refreshLowLevelState(); // -// $started = (int)Cache::get($this->cacheStartedAtKey, 0); +// // 2) failsafe: wenn zu lange läuft, als beendet markieren +// $started = (int) Cache::get($this->cacheStartedAtKey, 0); // if ($this->running && $started > 0 && (time() - $started) > $this->failsafeSeconds) { // $this->running = false; -// $this->rc ??= 0; +// $this->rc ??= 0; // notfalls als “erfolgreich” werten // } // +// // 3) Wenn nicht mehr running ⇒ Abschluss behandeln // if (!$this->running) { // Cache::forget($this->cacheStartedAtKey); +// +// // Versionen neu laden und “hasUpdate” neu berechnen // $this->reloadVersionsAndStatus(); // $this->recompute(); -// $this->finishUiIfNoUpdate(); // -// if ($this->rc === 0) { +// // 3a) Erfolg: jetzt erst Dienste neu starten +// if ($this->rc === 0 && !$this->postActionsDone) { +// // Restart asynchron starten (dein Artisan-Command macht systemctl etc.) +// @shell_exec('nohup php /var/www/mailwolt/artisan mailwolt:restart-services >/dev/null 2>&1 &'); +// $this->postActionsDone = true; +// +// // Toast // $ver = $this->displayCurrent ?? 'aktuelle Version'; -// -// // ✅ zentraler Toastra-Toast // $this->dispatch('toast', // type: 'success', // title: 'Update erfolgreich', -// text: "MailWolt wurde erfolgreich auf {$ver} aktualisiert. Die Seite wird in 5 Sekunden neu geladen …", +// text: "MailWolt wurde auf {$ver} aktualisiert. Dienste werden neu gestartet …", // badge: 'System', // duration: 5000 // ); // -// // nach 5 Sekunden Seite neu laden +// // Seite nach 5s neu laden // $this->dispatch('reload-page', delay: 5000); -// } elseif ($this->rc !== null) { +// } +// // 3b) Fehler: Meldung zeigen +// elseif ($this->rc !== null && $this->rc !== 0 && !$this->postActionsDone) { +// $this->postActionsDone = true; // $this->dispatch('toast', // type: 'error', // title: 'Update fehlgeschlagen', @@ -305,976 +513,9 @@ class UpdateCard extends Component // ); // } // +// // 4) UI zurück auf idle // $this->state = 'idle'; // } // } // -// /* ========== Helper ========== */ -// -// protected function reloadVersionsAndStatus(): void -// { -// $this->current = $this->readCurrentVersion(); -// $this->latest = Cache::get('mailwolt.update_available'); -// $this->refreshLowLevelState(); -// } -// -// protected function finishUiIfNoUpdate(): void -// { -// if (!$this->hasUpdate) { -// $this->state = 'idle'; -// $cur = $this->displayCurrent ?? '–'; -// $this->message = "Du bist auf dem neuesten Stand ({$cur})"; -// $this->messagePositive = true; -// Cache::forget('mailwolt.update_available'); -// } -// } -// -// protected function recompute(): void -// { -// $curNorm = $this->normalizeVersion($this->current); -// $latNorm = $this->normalizeVersion($this->latest); -// -// $this->hasUpdate = ($curNorm && $latNorm) -// ? version_compare($latNorm, $curNorm, '>') -// : false; -// -// // Immer mit v-Präfix anzeigen -// $this->displayCurrent = $curNorm ? 'v' . $curNorm : null; -// $this->displayLatest = ($this->hasUpdate && $latNorm) ? 'v' . $latNorm : null; -// } -// -// protected function refreshLowLevelState(): void -// { -// $state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: ''); -// $this->running = ($state === 'running'); -// -// $rcRaw = @trim(@file_get_contents('/var/lib/mailwolt/update/rc') ?: ''); -// $this->rc = is_numeric($rcRaw) ? (int)$rcRaw : null; -// } -// -// protected function readCurrentVersion(): ?string -// { -// $build = @file_get_contents('/etc/mailwolt/build.info'); -// if ($build) { -// foreach (preg_split('/\R+/', $build) as $line) { -// if (str_starts_with($line, 'version=')) { -// $v = trim(substr($line, 8)); -// return $v !== '' ? $v : null; -// } -// } -// } -// $v = config('app.version'); -// return $v !== '' ? $v : null; -// } -// -// protected function normalizeVersion(?string $v): ?string -// { -// if ($v === null) return null; -// $v = trim($v); -// return ltrim($v, "vV \t\n\r\0\x0B") ?: null; -// } - - -//namespace App\Livewire\Ui\System; -// -//use Illuminate\Support\Facades\Artisan; -//use Illuminate\Support\Facades\Cache; -//use Livewire\Component; -// -//class UpdateCard extends Component -//{ -// /** Rohwerte (so wie gelesen/aus Cache) */ -// public ?string $current = null; // z.B. "v1.0.20" oder "1.0.20" -// public ?string $latest = null; // z.B. "1.0.20" oder "v1.0.20" -// -// /** Anzeige (immer mit v-Präfix) */ -// public ?string $displayCurrent = null; // z.B. "v1.0.20" -// public ?string $displayLatest = null; // nur gesetzt, wenn wirklich neuer -// -// /** Status/UX */ -// public bool $hasUpdate = false; -// public string $state = 'idle'; // idle|running -// public ?string $message = null; -// public ?bool $messagePositive = null; -// -// /** low-level / Wrapper */ -// public bool $running = false; -// public ?int $rc = null; -// -// /** intern */ -// protected string $cacheStartedAtKey = 'mw.update.started_at'; -// protected int $failsafeSeconds = 20 * 60; // 20 Min -// -// public function mount(): void -// { -// $this->current = $this->readCurrentVersion(); -// $this->latest = Cache::get('mailwolt.update_available'); -// $this->refreshLowLevelState(); -// -// $this->recompute(); // setzt hasUpdate + display* + ggf. message -// if ($this->running) $this->state = 'running'; -// } -// -// public function render() -// { -// return view('livewire.ui.system.update-card'); -// } -// -// /* =================== Aktionen =================== */ -// -// public function refreshState(): void -// { -// $this->state = 'running'; -// $this->message = 'Prüfe auf Updates …'; -// $this->messagePositive = null; -// -// try { -// Artisan::call('mailwolt:check-updates'); -// } catch (\Throwable $e) { -// // weich fallen -// } -// -// $this->reloadVersionsAndStatus(); -// $this->recompute(); -// $this->finishUiIfNoUpdate(); // beendet progress, wenn nichts mehr offen ist -// } -// -// public function runUpdate(): void -// { -// // Hinweis sofort entfernen (Badge weg) -// Cache::forget('mailwolt.update_available'); -// Cache::put($this->cacheStartedAtKey, time(), now()->addHour()); -// -// // Wrapper asynchron starten -// @shell_exec('nohup sudo -n /usr/local/sbin/mw-update >/dev/null 2>&1 &'); -// -// // UI-Status -// $this->latest = null; -// $this->displayLatest = null; -// $this->hasUpdate = false; -// -// $this->state = 'running'; -// $this->running = true; -// $this->message = 'Update läuft …'; -// $this->messagePositive = null; -// } -// -// /** Wird nur gepollt, solange $state==='running' (wire:poll) */ -// public function tick(): void -// { -// $this->refreshLowLevelState(); -// -// // Failsafe -// $started = (int)Cache::get($this->cacheStartedAtKey, 0); -// if ($this->running && $started > 0 && (time() - $started) > $this->failsafeSeconds) { -// $this->running = false; -// } -// -// if (!$this->running) { -// Cache::forget($this->cacheStartedAtKey); -// $this->reloadVersionsAndStatus(); -// $this->recompute(); -// $this->finishUiIfNoUpdate(); -// } -// } -// -// /* =================== Helpers =================== */ -// -// protected function reloadVersionsAndStatus(): void -// { -// $this->current = $this->readCurrentVersion(); -// $this->latest = Cache::get('mailwolt.update_available'); -// $this->refreshLowLevelState(); -// } -// -// protected function finishUiIfNoUpdate(): void -// { -// if (!$this->hasUpdate) { -// $this->state = 'idle'; -// $cur = $this->displayCurrent ?? '–'; -// // <<< Klammern-Fix: erst coalescen, dann in den String einsetzen -// $this->message = "Du bist auf dem neuesten Stand ({$cur})"; -// $this->messagePositive = true; -// -// // zur Sicherheit: Cache leeren -// Cache::forget('mailwolt.update_available'); -// } -// } -// -// protected function recompute(): void -// { -// $curNorm = $this->normalizeVersion($this->current); -// $latNorm = $this->normalizeVersion($this->latest); -// -// $this->hasUpdate = ($curNorm && $latNorm) -// ? version_compare($latNorm, $curNorm, '>') -// : false; -// -// // Anzeige immer mit v-Präfix -// $this->displayCurrent = $curNorm ? 'v' . $curNorm : null; -// $this->displayLatest = ($this->hasUpdate && $latNorm) ? 'v' . $latNorm : null; -// -// // Initiale Message (nur wenn noch nicht gesetzt) -// if ($this->message === null) { -// if ($this->hasUpdate) { -// $this->message = "Neue Version verfügbar: {$this->displayLatest}"; -// $this->messagePositive = false; -// } else { -// $cur = $this->displayCurrent ?? '–'; -// $this->message = "Du bist auf dem neuesten Stand ({$cur})"; -// $this->messagePositive = true; -// } -// } -// } -// -// protected function refreshLowLevelState(): void -// { -// $state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: ''); -// $this->running = ($state === 'running'); -// -// $rcRaw = @trim(@file_get_contents('/var/lib/mailwolt/update/rc') ?: ''); -// $this->rc = is_numeric($rcRaw) ? (int)$rcRaw : null; -// } -// -// protected function readCurrentVersion(): ?string -// { -// // bevorzugt build.info -// $build = @file_get_contents('/etc/mailwolt/build.info'); -// if ($build) { -// foreach (preg_split('/\R+/', $build) as $line) { -// if (str_starts_with($line, 'version=')) { -// $v = trim(substr($line, 8)); -// return $v !== '' ? $v : null; -// } -// } -// } -// $v = config('app.version'); -// return $v !== '' ? $v : null; -// } -// -// protected function normalizeVersion(?string $v): ?string -// { -// if ($v === null) return null; -// $v = trim($v); -// // führendes v/V + whitespace entfernen -// $v = ltrim($v, "vV \t\n\r\0\x0B"); -// return $v === '' ? null : $v; -// } //} - -//namespace App\Livewire\Ui\System; -// -//use Illuminate\Support\Facades\Artisan; -//use Illuminate\Support\Facades\Cache; -//use Livewire\Component; -// -//class UpdateCard extends Component -//{ -// public ?string $current = null; // installierte Version -// public ?string $latest = null; // verfügbare Version (oder null) -// public string $state = 'idle'; // idle | running -// -// public ?string $message = null; -// public ?bool $messagePositive = null; -// -// // low-level -// public bool $running = false; -// public ?int $rc = null; -// -// // intern -// protected string $cacheStartedAtKey = 'mw.update.started_at'; -// protected int $failsafeSeconds = 20 * 60; // 20 Min -// -// public function mount(): void -// { -// $this->current = $this->readCurrentVersion(); -// $this->latest = Cache::get('mailwolt.update_available'); -// $this->refreshLowLevelState(); -// -// // initiale Message -// if ($this->message === null) { -// if ($this->getHasUpdateProperty()) { -// $this->message = "Neue Version verfügbar: {$this->latest}"; -// $this->messagePositive = false; -// } else { -// $cur = $this->current ?: '–'; -// $this->message = "Du bist auf dem neuesten Stand ({$cur})"; -// $this->messagePositive = true; -// } -// } -// -// // falls der Wrapper gerade läuft → visuell „running“ -// if ($this->running) { -// $this->state = 'running'; -// } -// } -// -// public function render() -// { -// return view('livewire.ui.system.update-card'); -// } -// -// /* =================== Aktionen =================== */ -// -// public function refreshState(): void -// { -// $this->state = 'running'; -// $this->message = 'Prüfe auf Updates …'; -// $this->messagePositive = null; -// -// try { -// Artisan::call('mailwolt:check-updates'); -// } catch (\Throwable $e) { -// // weich fallen -// } -// -// $this->reloadVersionsAndStatus(); -// $this->finishUiIfNoUpdate(); -// } -// -// public function runUpdate(): void -// { -// // Badge „Update verfügbar“ sofort ausblenden -// Cache::forget('mailwolt.update_available'); -// -// // Startzeit merken (Failsafe) -// Cache::put($this->cacheStartedAtKey, time(), now()->addHours(1)); -// -// // Wrapper asynchron starten -// @shell_exec('nohup sudo -n /usr/local/sbin/mw-update >/dev/null 2>&1 &'); -// -// $this->latest = null; -// $this->state = 'running'; -// $this->running = true; -// $this->message = 'Update läuft …'; -// $this->messagePositive = null; -// } -// -// /** -// * Wird vom Blade nur während running gepollt (wire:poll="tick"). -// * Bricht den Fortschritt ab, sobald der Wrapper „done“ meldet ODER -// * der Failsafe greift. Lädt danach Versionen & Badge neu. -// */ -// public function tick(): void -// { -// $this->refreshLowLevelState(); -// -// // Failsafe: nach N Minuten Fortschritt aus -// $started = (int)Cache::get($this->cacheStartedAtKey, 0); -// if ($this->running && $started > 0 && (time() - $started) > $this->failsafeSeconds) { -// $this->running = false; -// } -// -// if (!$this->running) { -// // abgeschlossen → Startmarke löschen -// Cache::forget($this->cacheStartedAtKey); -// -// // Versionen/Caches neu laden -// $this->reloadVersionsAndStatus(); -// -// // wenn erfolgreich (rc=0) und keine neue Version mehr → Done -// $this->finishUiIfNoUpdate(); -// } -// // wenn weiterhin running: nichts tun, UI zeigt Progress weiter -// } -// -// /* =================== Computed =================== */ -// -// // Blade nutzt $this->hasUpdate -// public function getHasUpdateProperty(): bool -// { -// $cur = $this->normalizeVersion($this->current ?? null); -// $lat = $this->normalizeVersion($this->latest ?? null); -// if ($lat === null || $cur === null) return false; -// return version_compare($lat, $cur, '>'); -// } -// -// /* =================== Helpers =================== */ -// -// protected function reloadVersionsAndStatus(): void -// { -// $this->current = $this->readCurrentVersion(); -// $this->latest = Cache::get('mailwolt.update_available'); -// $this->refreshLowLevelState(); -// } -// -// protected function finishUiIfNoUpdate(): void -// { -// if (!$this->getHasUpdateProperty()) { -// // alles aktuell → Fortschritt aus, Badge „Aktuell“, Hinweistext grün -// $this->state = 'idle'; -// $this->message = "Du bist auf dem neuesten Stand (" . $this->current ?? '–' . ")"; -// $this->messagePositive = true; -// -// // zur Sicherheit Badge-Cache entfernen -// Cache::forget('mailwolt.update_available'); -// } -// } -// -// protected function refreshLowLevelState(): void -// { -// $state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: ''); -// $this->running = ($state === 'running'); -// -// $rcRaw = @trim(@file_get_contents('/var/lib/mailwolt/update/rc') ?: ''); -// $this->rc = is_numeric($rcRaw) ? (int)$rcRaw : null; -// } -// -// protected function readCurrentVersion(): ?string -// { -// $build = @file_get_contents('/etc/mailwolt/build.info'); -// if ($build) { -// foreach (preg_split('/\R+/', $build) as $line) { -// if (str_starts_with($line, 'version=')) { -// $v = trim(substr($line, 8)); -// if ($v !== '') return $v; -// } -// } -// } -// $v = config('app.version'); -// return $v !== '' ? $v : null; -// } -// -// protected function normalizeVersion(?string $v): ?string -// { -// if ($v === null) return null; -// $v = trim($v); -// $v = ltrim($v, 'v'); // führt "v1.0.19" und "1.0.19" zusammen -// return $v === '' ? null : $v; -// } -//} - -//namespace App\Livewire\Ui\System; -// -//use Illuminate\Support\Facades\Artisan; -//use Illuminate\Support\Facades\Cache; -//use Livewire\Component; -// -//class UpdateCard extends Component -//{ -// public ?string $current = null; // installed (pretty) -// public ?string $latest = null; // available (pretty or null) -// public string $state = 'idle'; // idle|running -// -// public ?string $message = null; // inline message -// public ?bool $messagePositive = null; -// -// // low-level -// public bool $running = false; -// public ?int $rc = null; -// -// // ---- lifecycle --------------------------------------------------------- -// -// public function mount(): void -// { -// $this->readLowLevel(); -// $this->current = $this->readCurrentVersion(); -// $this->latest = $this->readCachedLatest(); -// -// if ($this->message === null) { -// if ($this->hasUpdate()) { -// $this->message = "Neue Version verfügbar: {$this->latest}"; -// $this->messagePositive = false; -// } else { -// $cur = $this->current ?? '–'; -// $this->message = "Du bist auf dem neuesten Stand ({$cur})"; -// $this->messagePositive = true; -// } -// } -// -// // if wrapper is already running when page loads, reflect that -// if ($this->running) { -// $this->state = 'running'; -// } -// } -// -// public function render() -// { -// return view('livewire.ui.system.update-card'); -// } -// -// // ---- UI actions -------------------------------------------------------- -// -// /** Button: „Erneut prüfen“ (no toast; shows inline progress) */ -// public function refreshState(): void -// { -// $this->state = 'running'; -// $this->message = 'Prüfe auf Updates …'; -// $this->messagePositive = null; -// -// try { -// // your checker should update the cache key below -// Artisan::call('mailwolt:check-updates'); -// } catch (\Throwable $e) { -// // swallow but still continue to show something meaningful -// } -// -// $this->current = $this->readCurrentVersion(); -// $this->latest = $this->readCachedLatest(); -// $this->readLowLevel(); -// -// if ($this->hasUpdate()) { -// $this->message = "Neue Version verfügbar: {$this->latest}"; -// $this->messagePositive = false; -// } else { -// $this->message = "Du bist auf dem neuesten Stand ($this->current ?? '–')"; -// $this->messagePositive = true; -// } -// -// $this->state = 'idle'; -// } -// -// /** Button: „Jetzt aktualisieren“ (no toast; start wrapper + progress) */ -// public function runUpdate(): void -// { -// // Hide the yellow badges immediately -// Cache::forget('mailwolt.update_available'); -// -// // spawn wrapper in the background -// @shell_exec('nohup sudo -n /usr/local/sbin/mw-update >/dev/null 2>&1 &'); -// -// // reflect “running” in UI -// $this->latest = null; -// $this->state = 'running'; -// $this->running = true; -// $this->message = 'Update läuft …'; -// $this->messagePositive = null; -// } -// -// /** -// * Called from the blade with `wire:poll.1200ms="tick"` – but **only** -// * when $state === 'running'. This finishes the UX once the wrapper ends. -// */ -// public function tick(): void -// { -// if ($this->state !== 'running') return; -// -// $this->readLowLevel(); -// -// if (!$this->running) { // wrapper finished -// // give build.info a split second to land on slow disks -// usleep(150000); -// -// $this->current = $this->readCurrentVersion(); -// $this->latest = $this->readCachedLatest(); -// -// if ($this->rc === 0) { -// // success path -// if ($this->hasUpdate()) { -// // very unlikely right after success, but handle anyway -// $this->message = "Neue Version verfügbar: {$this->latest}"; -// $this->messagePositive = false; -// } else { -// $this->message = "Update erfolgreich – jetzt: {$this->current}"; -// $this->messagePositive = true; -// } -// } else { -// // failure path -// $rc = $this->rc ?? 1; -// $this->message = "Update fehlgeschlagen (rc={$rc})"; -// $this->messagePositive = false; -// } -// -// $this->state = 'idle'; -// } -// } -// -// // ---- helpers ----------------------------------------------------------- -// -// public function getHasUpdateProperty(): bool -// { -// // gleiche Logik wie in deiner Klasse: -// $cur = $this->normalizeVersion($this->current ?? null); -// $lat = $this->normalizeVersion($this->latest ?? null); -// if ($lat === null || $cur === null) return false; -// return version_compare($lat, $cur, '>'); -// } -// -// protected function hasUpdate(): bool -// { -// $cur = $this->normalizeVersion($this->current); -// $lat = $this->normalizeVersion($this->latest); -// -// if ($lat === null || $cur === null) return false; -// return version_compare($lat, $cur, '>'); -// } -// -// protected function readLowLevel(): void -// { -// $state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: ''); -// $this->running = ($state === 'running'); -// -// $rcRaw = @trim(@file_get_contents('/var/lib/mailwolt/update/rc') ?: ''); -// $this->rc = is_numeric($rcRaw) ? (int)$rcRaw : null; -// } -// -// protected function readCurrentVersion(): ?string -// { -// // Prefer the installer/updater stamp -// $build = @file_get_contents('/etc/mailwolt/build.info'); -// if ($build) { -// foreach (preg_split('/\R+/', $build) as $line) { -// if (str_starts_with($line, 'version=')) { -// $v = trim(substr($line, 8)); -// if ($v !== '') return $this->prettyVersion($v); -// } -// } -// } -// $v = trim((string)config('app.version', '')); -// return $v !== '' ? $this->prettyVersion($v) : null; -// } -// -// protected function readCachedLatest(): ?string -// { -// $v = Cache::get('mailwolt.update_available'); -// if (!is_string($v) || $v === '') return null; -// return $this->prettyVersion($v); -// } -// -// /** -// * Return a “compare-safe” semver string: e.g. `v1.0.18` → `1.0.18`. -// * Accepts tags like `release-1.0.18` too. -// */ -// protected function normalizeVersion(?string $v): ?string -// { -// if (!$v) return null; -// // keep only the first x.y.z like portion -// if (preg_match('/(\d+\.\d+\.\d+)/', $v, $m)) { -// return $m[1]; -// } -// // fallback: bare digits (x.y) -// if (preg_match('/(\d+\.\d+)/', $v, $m)) { -// return $m[1]; -// } -// return null; -// } -// -// /** Always render with a single leading `v` (no “vv…”) */ -// protected function prettyVersion(string $v): string -// { -// $n = $this->normalizeVersion($v); -// return $n ? 'v' . $n : $v; -// } -//} - -//namespace App\Livewire\Ui\System; -// -//use Livewire\Component; -//use Illuminate\Support\Facades\Artisan; -//use Illuminate\Support\Facades\Cache; -// -//class UpdateCard extends Component -//{ -// public ?string $current = null; // installierte Version -// public ?string $latest = null; // verfügbare Version (oder null) -// public string $state = 'idle'; // idle | running -// -// // UI-Textausgabe nach einer Prüfung / Aktion -// public ?string $message = null; // z.B. "Du bist auf dem neuesten Stand (v1.0.16)" -// public ?bool $messagePositive = null; // true = grün, false = neutral/weiß -// -// // low-level (falls du sie später brauchst) -// public bool $running = false; // aus /var/lib/mailwolt/update/state -// public ?int $rc = null; -// -// public function mount(): void -// { -// $this->current = $this->readCurrentVersion(); -// $this->latest = Cache::get('mailwolt.update_available'); -// $this->refreshLowLevelState(); -// -// // Starttext, falls nichts geprüft wurde -// if ($this->message === null) { -// $this->message = $this->latest && $this->hasUpdate() -// ? "Neue Version verfügbar: {$this->latest}" -// : ($this->current ? "Du bist auf dem neuesten Stand ({$this->current})" : "Status unbekannt"); -// $this->messagePositive = !$this->hasUpdate(); -// } -// } -// -// public function render() -// { -// return view('livewire.ui.system.update-card'); -// } -// -// /** -// * „Erneut prüfen“ – ohne Toast: -// * - Progress anzeigen -// * - Check-Command laufen lassen -// * - Message in der Box aktualisieren -// */ -// public function refreshState(): void -// { -// $this->state = 'running'; -// $this->message = 'Prüfe auf Updates …'; -// $this->messagePositive = null; -// -// try { -// // Passe den Namen hier an dein tatsächliches Command an: -// Artisan::call('mailwolt:check-updates'); -// } catch (\Throwable $e) { -// // weich fallen -// } -// -// // Daten neu einlesen -// $this->current = $this->readCurrentVersion(); -// $this->latest = Cache::get('mailwolt.update_available'); -// -// if ($this->hasUpdate()) { -// $this->message = "Neue Version verfügbar: {$this->latest}"; -// $this->messagePositive = false; // neutral -// } else { -// $cur = $this->current ?: '–'; -// $this->message = "Du bist auf dem neuesten Stand ({$cur})"; -// $this->messagePositive = true; // grün -// } -// -// $this->refreshLowLevelState(); -// $this->state = 'idle'; -// } -// -// /** -// * „Jetzt aktualisieren“ – ohne Toast: -// * - Hinweis sofort aus Cache entfernen (Badge weg) -// * - Update-Wrapper starten -// * - Running + Text in der Box anzeigen -// */ -// public function runUpdate(): void -// { -// Cache::forget('mailwolt.update_available'); -// -// @shell_exec('nohup sudo -n /usr/local/sbin/mw-update >/dev/null 2>&1 &'); -// -// $this->latest = null; -// $this->state = 'running'; -// $this->running = true; -// $this->message = 'Update läuft …'; -// $this->messagePositive = null; -// } -// -// /** --------------------- helpers --------------------- */ -// -// protected function hasUpdate(): bool -// { -// if (!$this->latest) return false; -// $cur = $this->current ?: '0.0.0'; -// return version_compare($this->latest, $cur, '>'); -// } -// -// protected function refreshLowLevelState(): void -// { -// $state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: ''); -// $this->running = ($state === 'running'); -// -// $rcRaw = @trim(@file_get_contents('/var/lib/mailwolt/update/rc') ?: ''); -// $this->rc = is_numeric($rcRaw) ? (int)$rcRaw : null; -// } -// -// protected function readCurrentVersion(): ?string -// { -// // bevorzugt /etc/mailwolt/build.info (wird im Installer/Updater gepflegt) -// $build = @file_get_contents('/etc/mailwolt/build.info'); -// if ($build) { -// foreach (preg_split('/\R+/', $build) as $line) { -// if (str_starts_with($line, 'version=')) { -// $v = trim(substr($line, 8)); -// if ($v !== '') return $v; -// } -// } -// } -// $v = config('app.version'); -// return $v !== '' ? $v : null; -// } -//} - -// -// -//namespace App\Livewire\Ui\System; -// -//use Livewire\Component; -//use Illuminate\Support\Facades\Artisan; -//use Illuminate\Support\Facades\Cache; -// -//class UpdateCard extends Component -//{ -// public ?string $current = null; // z.B. v1.0.16 (aktuell installiert) -// public ?string $latest = null; // z.B. v1.0.17 (verfügbar) oder null -// public string $state = 'idle'; // idle | running -// -// // optional: Low-level-Infos, falls du sie irgendwo anders brauchst -// public bool $running = false; // Wrapper-/Updater läuft gerade (aus State-Datei) -// public string $log = ''; -// public ?int $rc = null; -// -// public function mount(): void -// { -// $this->current = $this->readCurrentVersion(); -// $this->latest = Cache::get('mailwolt.update_available'); -// $this->refreshLowLevelState(); // liest /var/lib/mailwolt/update/* -// } -// -// public function render() -// { -// return view('livewire.ui.system.update-card'); -// } -// -// /** -// * „Erneut prüfen“: -// * - zeigt Running-Progress -// * - ruft den Checker (dein bestehendes Artisan-Command) -// * - aktualisiert $latest / $current -// * - dispatcht passenden Toast -// */ -// public function refreshState(): void -// { -// $this->state = 'running'; -// -// // Falls vorhanden: dein Command, der cache('mailwolt.update_available') setzt -// // -> Namen ggf. anpassen (du hattest z.B. mailwolt:check-updates erwähnt) -// try { -// Artisan::call('mailwolt:check-updates'); -// } catch (\Throwable $e) { -// // Wenn das Command (noch) nicht existiert, nicht crashen – state einfach zurücksetzen -// } -// -// // App-Status neu einlesen -// $this->current = $this->readCurrentVersion(); -// $this->latest = Cache::get('mailwolt.update_available'); -// -// $hasUpdate = $this->hasUpdate(); -// -// // Toast ausspielen -// $this->dispatch('toast', -// type: $hasUpdate ? 'info' : 'done', -// badge: 'Update', -// title: $hasUpdate ? 'Neue Version verfügbar' : 'Alles aktuell', -// text: $hasUpdate -// ? "Verfügbar: {$this->latest} – installiert: {$this->current}" -// : "Du bist auf dem neuesten Stand ({$this->current}).", -// duration: 6000 -// ); -// -// // Low-level-State (optional) und UI-State zurücksetzen -// $this->refreshLowLevelState(); -// $this->state = 'idle'; -// } -// -// /** -// * „Jetzt aktualisieren“: -// * - blendet die verfügbare-Version sofort aus -// * - startet den Root-Wrapper im Hintergrund -// * - zeigt einen Toast „Update gestartet“ -// */ -// public function runUpdate(): void -// { -// Cache::forget('mailwolt.update_available'); // Badge sofort weg -// @shell_exec('nohup sudo -n /usr/local/sbin/mw-update >/dev/null 2>&1 &'); -// -// $this->state = 'running'; -// $this->running = true; -// -// $this->dispatch('toast', -// type: 'info', -// badge: 'Update', -// title: 'Update gestartet', -// text: 'Das System wird aktualisiert …', -// duration: 6000 -// ); -// } -// -// /** ---- Helpers ------------------------------------------------------- */ -// -// protected function hasUpdate(): bool -// { -// if (!$this->latest) return false; -// $cur = $this->current ?: '0.0.0'; -// return version_compare($this->latest, $cur, '>'); -// } -// -// protected function refreshLowLevelState(): void -// { -// $state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: ''); -// $this->running = ($state === 'running'); -// -// $rcRaw = @trim(@file_get_contents('/var/lib/mailwolt/update/rc') ?: ''); -// $this->rc = is_numeric($rcRaw) ? (int)$rcRaw : null; -// -// // Log bewusst NICHT angezeigt, aber verfügbar, falls du es später brauchst -// $this->log = @shell_exec('tail -n 200 /var/log/mailwolt-update.log 2>/dev/null') ?? ''; -// } -// -// protected function readCurrentVersion(): ?string -// { -// // bevorzugt build.info, sonst config('app.version') -// $build = @file_get_contents('/etc/mailwolt/build.info'); -// if ($build) { -// foreach (preg_split('/\R+/', $build) as $line) { -// if (str_starts_with($line, 'version=')) { -// $v = trim(substr($line, 8)); -// if ($v !== '') return $v; -// } -// } -// } -// $v = config('app.version'); -// return $v !== '' ? $v : null; -// } -//} -//// -////namespace App\Livewire\Ui\System; -//// -////use Livewire\Component; -////use Illuminate\Support\Facades\Artisan; -////use Illuminate\Support\Facades\Cache; -//// -////class UpdateCard extends Component -////{ -//// public ?string $current = null; -//// public ?string $latest = null; -//// public string $state = 'idle'; // idle|running -//// -//// public bool $running = false; -//// public string $log = ''; -//// public ?int $rc = null; -//// -//// public function mount(): void -//// { -////// $this->refreshState(); -//// $this->latest = cache('mailwolt.update_available'); -//// -//// } -//// -//// public function render() -//// { -//// return view('livewire.ui.system.update-card'); -//// } -//// -//// public function refreshState(): void -//// { -//// $state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: ''); -//// $this->running = ($state === 'running'); -//// -//// $rcRaw = @trim(@file_get_contents('/var/lib/mailwolt/update/rc') ?: ''); -//// $this->rc = is_numeric($rcRaw) ? (int)$rcRaw : null; -//// -//// // letzte 200 Zeilen Log -//// $this->log = @shell_exec('tail -n 200 /var/log/mailwolt-update.log 2>/dev/null') ?? ''; -//// } -//// -//// public function runUpdate(): void -//// { -//// // Hinweis „Update verfügbar“ ausblenden -//// cache()->forget('mailwolt.update_available'); -//// -//// // Update im Hintergrund starten -//// @shell_exec('nohup sudo -n /usr/local/sbin/mw-update >/dev/null 2>&1 &'); -//// -//// $this->running = true; -//// $this->dispatch('toast', -//// type: 'info', -//// badge: 'Update', -//// title: 'Update gestartet', -//// text: 'Das System wird aktualisiert …', -//// duration: 6000 -//// ); -//// } -////} diff --git a/resources/views/livewire/ui/system/update-card.blade.php b/resources/views/livewire/ui/system/update-card.blade.php index 60455f2..19d2855 100644 --- a/resources/views/livewire/ui/system/update-card.blade.php +++ b/resources/views/livewire/ui/system/update-card.blade.php @@ -1,108 +1,11 @@ -{{--@php--}} -{{-- $hasUpdate = $latest && $current && version_compare($latest, $current, '>');--}} -{{--@endphp--}} - -{{--
--}} -{{--
--}} -{{-- --}}{{-- Shield-Bot --}} -{{--
--}} -{{--
--}} - -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{-- --}} -{{--
--}} -{{--
--}} - -{{--
--}} -{{--
--}} -{{--
--}} -{{--
MailWolt Update
--}} -{{-- --}}{{-- kleine Statuszeile mit Versionen, wenn vorhanden --}} -{{--
--}} -{{-- @if($current)--}} -{{-- aktuell: {{ $current }}--}} -{{-- @else--}} -{{-- aktuell: --}} -{{-- @endif--}} -{{-- @if($latest)--}} -{{-- --}} -{{-- verfügbar: {{ $latest }}--}} -{{-- @endif--}} -{{--
--}} -{{--
--}} -{{--
--}} -{{-- --}}{{-- Badge rechts --}} -{{-- --}} -{{-- --}} -{{-- {{ $hasUpdate ? 'Update verfügbar' : 'Aktuell' }}--}} -{{-- --}} -{{-- --}} - -{{--
--}} -{{--
--}} -{{--
--}} -{{-- @if($hasUpdate)--}} -{{-- --}} -{{-- @endif--}} -{{--
--}} - -{{-- --}}{{-- Progress-Bar, wenn running --}} -{{-- @if($state === 'running')--}} -{{--
--}} -{{--
--}} -{{--
--}} -{{-- --}} -{{-- @endif--}} -{{--
--}} -{{--
--}} -{{--
--}}
- {{-- Shield + Update-Icon --}} + {{-- Shield + Spinner --}}
- + +
@@ -131,6 +33,7 @@
{{ config('app.name') }} Update
+ {{-- Versionszeile --}}
@if($displayCurrent) aktuell: {{ $displayCurrent }} @@ -143,47 +46,44 @@ verfügbar: {{ $displayLatest }} @endif
-
-
- - - {{ $this->hasUpdate ? 'Update verfügbar' : 'Aktuell' }} - - @if($this->hasUpdate) - + {{-- Einzeilige Fortschritts-/Fehleranzeige (optional) --}} + @if($progressLine || $errorLine) +
+ @if($progressLine) +
{{ $progressLine }}
+ @endif + @if($errorLine) +
{{ $errorLine }}
+ @endif +
@endif
+ {{-- Badge + Button (rein aus Properties) --}} +
+ + + {{ $badgeText }} + + + @if($showButton) + + @endif +
-{{--
--}} -{{-- @if($this->hasUpdate)--}} -{{-- --}} -{{-- @endif--}} -{{--
--}} - - {{-- Fortschritt nur während running --}} + {{-- Progress-Balken nur während running --}} @if($state === 'running') -
+ --}} +{{-- @endif--}} +{{--
--}} +{{--
--}} +{{----}}