From 020f55f53dc755750cdf3de0ab6b1a33c9367e77 Mon Sep 17 00:00:00 2001 From: boban Date: Wed, 22 Oct 2025 16:48:46 +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/Livewire/Ui/System/UpdateCard.php | 306 +++++++++++++++--- .../livewire/ui/system/update-card.blade.php | 224 +++++++++---- 2 files changed, 415 insertions(+), 115 deletions(-) diff --git a/app/Livewire/Ui/System/UpdateCard.php b/app/Livewire/Ui/System/UpdateCard.php index 02e5c25..fd81183 100644 --- a/app/Livewire/Ui/System/UpdateCard.php +++ b/app/Livewire/Ui/System/UpdateCard.php @@ -1,38 +1,46 @@ readLowLevel(); $this->current = $this->readCurrentVersion(); - $this->latest = Cache::get('mailwolt.update_available'); - $this->refreshLowLevelState(); + $this->latest = $this->readCachedLatest(); - // 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(); + 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'; } } @@ -41,12 +49,9 @@ class UpdateCard extends Component return view('livewire.ui.system.update-card'); } - /** - * „Erneut prüfen“ – ohne Toast: - * - Progress anzeigen - * - Check-Command laufen lassen - * - Message in der Box aktualisieren - */ + // ---- UI actions -------------------------------------------------------- + + /** Button: „Erneut prüfen“ (no toast; shows inline progress) */ public function refreshState(): void { $this->state = 'running'; @@ -54,41 +59,37 @@ class UpdateCard extends Component $this->messagePositive = null; try { - // Passe den Namen hier an dein tatsächliches Command an: + // your checker should update the cache key below Artisan::call('mailwolt:check-updates'); } catch (\Throwable $e) { - // weich fallen + // swallow but still continue to show something meaningful } - // Daten neu einlesen $this->current = $this->readCurrentVersion(); - $this->latest = Cache::get('mailwolt.update_available'); + $this->latest = $this->readCachedLatest(); + $this->readLowLevel(); if ($this->hasUpdate()) { $this->message = "Neue Version verfügbar: {$this->latest}"; - $this->messagePositive = false; // neutral + $this->messagePositive = false; } else { - $cur = $this->current ?: '–'; - $this->message = "Du bist auf dem neuesten Stand ({$cur})"; - $this->messagePositive = true; // grün + $this->message = "Du bist auf dem neuesten Stand ($this->current ?? '–')"; + $this->messagePositive = true; } - $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 - */ + /** 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; @@ -96,16 +97,65 @@ class UpdateCard extends Component $this->messagePositive = null; } - /** --------------------- helpers --------------------- */ + /** + * 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 { - if (!$this->latest) return false; - $cur = $this->current ?: '0.0.0'; - return version_compare($this->latest, $cur, '>'); + $cur = $this->normalizeVersion($this->current); + $lat = $this->normalizeVersion($this->latest); + + if ($lat === null || $cur === null) return false; + return version_compare($lat, $cur, '>'); } - protected function refreshLowLevelState(): void + protected function readLowLevel(): void { $state = @trim(@file_get_contents('/var/lib/mailwolt/update/state') ?: ''); $this->running = ($state === 'running'); @@ -116,21 +166,183 @@ class UpdateCard extends Component protected function readCurrentVersion(): ?string { - // bevorzugt /etc/mailwolt/build.info (wird im Installer/Updater gepflegt) + // 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 $v; + if ($v !== '') return $this->prettyVersion($v); } } } - $v = config('app.version'); - return $v !== '' ? $v : null; + $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; diff --git a/resources/views/livewire/ui/system/update-card.blade.php b/resources/views/livewire/ui/system/update-card.blade.php index 6eed2c8..0f5112d 100644 --- a/resources/views/livewire/ui/system/update-card.blade.php +++ b/resources/views/livewire/ui/system/update-card.blade.php @@ -1,60 +1,60 @@ -@php - $hasUpdate = $latest && $current && version_compare($latest, $current, '>'); -@endphp +{{--@php--}} +{{-- $hasUpdate = $latest && $current && version_compare($latest, $current, '>');--}} +{{--@endphp--}} -
-
- {{-- Shield-Bot --}} -
-
+{{--
--}} +{{--
--}} +{{-- --}}{{-- Shield-Bot --}} +{{--
--}} +{{--
--}} - - - - - - - - - - - - - - - - - - -
-
+{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{--
--}} +{{--
--}} -
-
-
-
MailWolt Update
- {{-- kleine Statuszeile mit Versionen, wenn vorhanden --}} -
- @if($current) - aktuell: v{{ $current }} - @else - aktuell: - @endif - @if($latest) - - verfügbar: v{{ $latest }} - @endif -
-
-
- {{-- Badge rechts --}} - - - {{ $hasUpdate ? 'Update verfügbar' : 'Aktuell' }} - +{{--
--}} +{{--
--}} +{{--
--}} +{{--
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 --}} +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
MailWolt Update
+ +
+ @if($current) + aktuell: {{ $current }} + @else + aktuell: + @endif + + @if($latest) + + verfügbar: {{ $latest }} + @endif +
+ + {{-- Badge rechts --}} + + + {{ $this->hasUpdate ? 'Update verfügbar' : 'Aktuell' }} +
+
- @if($hasUpdate) + @if($this->hasUpdate) @endif
- {{-- Progress-Bar, wenn running --}} + {{-- Fortschritt nur während running --}} @if($state === 'running')
-
+
- + @endif