129 lines
4.2 KiB
PHP
129 lines
4.2 KiB
PHP
<?php
|
||
|
||
namespace App\Livewire\System;
|
||
|
||
use Livewire\Component;
|
||
use Illuminate\Support\Facades\Cache;
|
||
use Illuminate\Support\Facades\Redis;
|
||
|
||
class ToastHub extends Component
|
||
{
|
||
// /** Merker pro Key, um doppelte Events zu vermeiden */
|
||
// public array $last = [];
|
||
//
|
||
// /** Poll alle X Sekunden */
|
||
// public function poll(): void
|
||
// {
|
||
// // Menge der aktuell sichtbaren Toast-Keys
|
||
// $keys = Redis::smembers('ui:toasts'); // Set enthält z.B. ["issue-cert:mail.example.com"]
|
||
//
|
||
// foreach ($keys as $key) {
|
||
// $task = Cache::store('redis')->get($key);
|
||
// if (!$task) {
|
||
// // Kein Datensatz mehr? Aufräumen.
|
||
// Redis::srem('ui:toasts', $key);
|
||
// continue;
|
||
// }
|
||
//
|
||
// $status = $task['status'] ?? 'queued'; // queued|running|done|failed
|
||
// $message = $task['message'] ?? '';
|
||
// $hash = $status.'|'.$message;
|
||
//
|
||
// // Nur senden, wenn sich etwas geändert hat
|
||
// if (($this->last[$key] ?? null) === $hash) {
|
||
// continue;
|
||
// }
|
||
// $this->last[$key] = $hash;
|
||
//
|
||
// $this->dispatch('toastra:show', [
|
||
// 'id' => $key, // gleicher Key => Toast wird ersetzt
|
||
// 'state' => $status, // queued|running|done|failed
|
||
// 'badge' => strtoupper($task['type'] ?? 'TASK'),
|
||
// 'domain' => $task['payload']['domain'] ?? '',
|
||
// 'message' => $message,
|
||
// 'position' => 'bottom-center',
|
||
// 'duration' => in_array($status, ['done','failed']) ? 6000 : 0,
|
||
// 'close' => true,
|
||
// ]);
|
||
//
|
||
// // Optionales Aufräumen, sobald final:
|
||
// if (in_array($status, ['done','failed'])) {
|
||
// // Im Set entfernen; der Client blendet selbst aus (Duration).
|
||
// Redis::srem('ui:toasts', $key);
|
||
// }
|
||
// }
|
||
// }
|
||
//
|
||
// public function render()
|
||
// {
|
||
// // Minimaler Root – kein Inhalt, nur Poll
|
||
// return <<<'BLADE'
|
||
//<div wire:poll.3s="poll"></div>
|
||
//BLADE;
|
||
// }
|
||
public bool $active = false; // steuert, ob überhaupt gepollt wird
|
||
public int $idleHits = 0; // schützt vor Dauerklingeln
|
||
|
||
public function mount(): void
|
||
{
|
||
$this->active = $this->hasKeys();
|
||
}
|
||
|
||
protected function hasKeys(): bool
|
||
{
|
||
try {
|
||
return (int) Redis::command('SCARD', ['ui:toasts']) > 0;
|
||
} catch (\Throwable $e) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public function loadAll(): void
|
||
{
|
||
// Wenn nix ansteht -> nach ein paar „leeren“ Runden Poll ganz stoppen
|
||
if (! $this->hasKeys()) {
|
||
if (++$this->idleHits >= 3) { // ~9 Sekunden bei poll.3s
|
||
$this->active = false;
|
||
}
|
||
return;
|
||
}
|
||
|
||
$this->idleHits = 0; // wieder aktiv
|
||
|
||
$keys = Redis::command('SMEMBERS', ['ui:toasts']) ?? [];
|
||
foreach ($keys as $key) {
|
||
$task = Cache::store('redis')->get($key);
|
||
|
||
if (! $task) {
|
||
Redis::command('SREM', ['ui:toasts', $key]);
|
||
continue;
|
||
}
|
||
|
||
$status = $task['status'] ?? 'queued';
|
||
|
||
// an deinen Glas-Toast weiterreichen
|
||
$this->dispatch('notify', [
|
||
'id' => $key,
|
||
'state' => $status, // queued|running|done|failed
|
||
'badge' => strtoupper($task['type'] ?? 'task'),
|
||
'domain' => $task['payload']['domain'] ?? '',
|
||
'message' => $task['message'] ?? '',
|
||
'position' => 'bottom-center',
|
||
'duration' => in_array($status, ['done','failed']) ? 6000 : 0,
|
||
'close' => true,
|
||
]);
|
||
|
||
// „fertige“ Tasks räumen wir sofort aus dem Set
|
||
if (in_array($status, ['done','failed'])) {
|
||
Redis::command('SREM', ['ui:toasts', $key]);
|
||
}
|
||
}
|
||
}
|
||
|
||
public function render()
|
||
{
|
||
return view('livewire.system.toast-hub');
|
||
}
|
||
|
||
}
|