refresh(); } public function render() { return view('livewire.ui.system.modal.update-modal'); } #[On('update:modal-refresh')] public function refresh(): void { $st = @trim(@file_get_contents(self::STATE_DIR.'/state') ?: ''); $rcRaw = @trim(@file_get_contents(self::STATE_DIR.'/rc') ?: ''); $this->state = $st ?: 'unknown'; $this->rc = is_numeric($rcRaw) ? (int)$rcRaw : null; // Log einlesen $lines = @file(self::LOG, FILE_IGNORE_NEW_LINES) ?: []; $this->tail = array_slice($lines, -30); $last = trim($this->tail ? end($this->tail) : ''); $last = preg_replace('/^\[\w\]\s*/', '', $last); $last = preg_replace('/^=+ .*? =+\s*$/', 'Update beendet', $last); $last = preg_replace('/^\d{4}-\d{2}-\d{2}T[^ ]+\s*::\s*/', '', $last); $this->line = Str::limit($last, 160); // ganz simple Fortschritts-Heuristik über bekannte Meilensteine $text = implode("\n", $this->tail); $pct = 5; foreach ([ 'Update gestartet' => 10, 'Composer' => 25, 'npm ci' => 40, 'npm run build' => 60, 'migrate' => 75, 'optimize' => 85, 'Version aktualisiert' => 95, 'Update beendet' => 100, ] as $needle => $val) { if (stripos($text, $needle) !== false) { $pct = max($pct, $val); } } if ($this->state === 'done') { $pct = 100; } $this->percent = $pct; // Auto-Close vorbereiten if ($this->state === 'done' && $this->rc === 0) { static::$closingAllowed = true; } } public static function modalMaxWidth(): string { return '2xl'; } public static function closeModalOnEscape(): bool { return static::$closingAllowed; } public static function closeModalOnClickAway(): bool { return static::$closingAllowed; } }