117 lines
6.6 KiB
PHP
117 lines
6.6 KiB
PHP
{{-- Die Bühne liegt ÜBER dem Terminal, nicht daneben.
|
|
|
|
Bis hierher waren es zwei Geschwister, von denen abwechselnd eines
|
|
`hidden` trug: erst der Vorspann, dann der Schirm. Das trug genau einmal —
|
|
beim Aufbau. Für alles danach fehlte die Rückfahrkarte, und was der
|
|
Betreiber beim Abbruch sah, war eine rote ANSI-Zeile mitten in der eigenen
|
|
Ausgabe: die einzige Stelle im Produkt, an der eine Meldung nicht gestaltet
|
|
war, sondern getippt.
|
|
|
|
Als Überlagerung kann dieselbe Bühne dreimal auftreten — beim Verbinden,
|
|
beim Abbruch, beim Ende — und die Sitzung darunter bleibt stehen, statt
|
|
gelöscht zu werden. Was auf ihr steht, kommt aus den Sprachdateien; die
|
|
Meldungen, die erst der Browser kennt, reisen als JSON in
|
|
`data-stage-messages` mit, damit auch sie dort stehen und nicht im Skript. --}}
|
|
@php
|
|
// Ein Grund, den schon der Server kennt (kein Schlüssel hinterlegt, Host
|
|
// noch nicht übernommen), steht sofort auf der Bühne. Sonst beginnt sie mit
|
|
// dem Vorspann. Derselbe Bau, anderer Text, anderer Ton.
|
|
$stageTitle = $problem !== ''
|
|
? __('hosts.terminal.problem.'.$problem.'.title')
|
|
: __('hosts.terminal.stage.connecting.title', ['host' => $host->name]);
|
|
|
|
$stageNote = $problem !== ''
|
|
? __('hosts.terminal.problem.'.$problem.'.note')
|
|
: __('hosts.terminal.stage.connecting.note');
|
|
|
|
// Was der Browser erst später braucht. Welcher Schlüssel wann gilt, steht
|
|
// in resources/js/terminal.js neben den Schließcodes der Brücke.
|
|
$messages = [
|
|
'ended' => [
|
|
'title' => __('hosts.terminal.stage.ended.title'),
|
|
'note' => __('hosts.terminal.stage.ended.note', ['host' => $host->name]),
|
|
],
|
|
'lost' => [
|
|
'title' => __('hosts.terminal.stage.lost.title'),
|
|
'note' => __('hosts.terminal.stage.lost.note', ['host' => $host->name]),
|
|
],
|
|
'rejected' => [
|
|
'title' => __('hosts.terminal.stage.rejected.title'),
|
|
'note' => __('hosts.terminal.stage.rejected.note'),
|
|
],
|
|
'unreachable' => [
|
|
'title' => __('hosts.terminal.stage.unreachable.title', ['host' => $host->name]),
|
|
'note' => __('hosts.terminal.stage.unreachable.note', ['host' => $host->name]),
|
|
],
|
|
];
|
|
@endphp
|
|
<div class="relative flex h-screen w-screen flex-col overflow-hidden bg-ink"
|
|
data-terminal
|
|
data-ticket="{{ $ticket }}">
|
|
|
|
{{-- wire:ignore: xterms eigener DOM-Baum liegt in einem von Livewire
|
|
verwalteten Baum. Heute hat die Komponente keine Aktion, die einen
|
|
Re-Render auslöst — aber das erste `wire:`-irgendwas auf dieser Seite
|
|
würde xterm sonst beim nächsten Umlauf löschen. --}}
|
|
<div data-terminal-screen wire:ignore class="flex-1 overflow-hidden"></div>
|
|
|
|
<div data-terminal-stage
|
|
class="absolute inset-0 z-10 flex flex-col items-center justify-center gap-6 bg-ink px-6 text-center"
|
|
data-stage-messages="{{ json_encode($messages, JSON_UNESCAPED_UNICODE) }}">
|
|
|
|
{{-- Schriftgrafik, keine Bilddatei — deshalb `role="img"` mit einem
|
|
lesbaren Namen statt `aria-hidden`: ein Screenreader soll "CluPilot"
|
|
hören, nicht die einzelnen Zeichen der Zeichnung.
|
|
|
|
Vollblöcke, nicht `_ / \ |`. Die erste Fassung war eine gewöhnliche
|
|
Figlet-Zeichnung, und die funktioniert nur in einer echten
|
|
Terminalschrift: sie setzt darauf, dass der Unterstrich einer Zeile
|
|
den Strich der nächsten berührt. In IBM Plex Mono sitzt der
|
|
Unterstrich tiefer — bei enger Zeilenhöhe verschmierte das Wort, bei
|
|
weiter zerfiel es in Einzelteile. Beides im Browser durchgemessen,
|
|
beides unlesbar. `█` füllt seine Zelle ganz aus und stapelt deshalb
|
|
in jeder Schrift sauber.
|
|
|
|
Immer Akzentfarbe, auch im Fehlerfall: Dunkelrot auf Fast-Schwarz
|
|
hatte kaum Kontrast, und eine Wortmarke, die ihre Farbe wechselt, ist
|
|
ohnehin keine Statuslampe — was los ist, sagt die Zeile darunter.
|
|
|
|
8px am Telefon: bei 11px ist die Zeichnung 403px breit und schöbe auf
|
|
einem schmalen Schirm die Seite zur Seite. --}}
|
|
<pre data-stage-mark
|
|
class="select-none font-mono text-[8px] leading-none text-accent sm:text-[11px]"
|
|
role="img" aria-label="CluPilot"> ██████ ██ ██ ██ ██████ ██ ██ ██████ ████████
|
|
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
|
██ ██ ██ ██ ██████ ██ ██ ██ ██ ██
|
|
██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
|
██████ ███████ ██████ ██ ██ ███████ ██████ ██</pre>
|
|
|
|
{{-- aria-live: die Bühne tauscht ihren Text aus, ohne dass die Seite neu
|
|
lädt. Ohne diesen Hinweis erführe ein Screenreader vom Abbruch
|
|
nichts — für ihn stünde das Fenster weiter beim Vorspann. --}}
|
|
<div class="max-w-sm space-y-2" aria-live="polite">
|
|
<p data-stage-title class="text-sm font-semibold text-bg">{{ $stageTitle }}</p>
|
|
<p data-stage-note class="text-xs leading-relaxed text-bg opacity-70">{{ $stageNote }}</p>
|
|
</div>
|
|
|
|
{{-- Neu laden statt neu verbinden: das Ticket gilt dreißig Sekunden und
|
|
genau einmal, ein zweiter Anlauf mit demselben wäre keiner. Der
|
|
Knopf ist beim Vorspann verborgen und kommt erst, wenn ein neuer
|
|
Versuch überhaupt etwas ändern kann — bei „kein Schlüssel
|
|
hinterlegt" ändert er nichts, dort bleibt er weg. Was er tut, hängt
|
|
terminal.js an; ein `onclick` im Markup wäre Verhalten an der
|
|
Stelle, an der sonst nur Gestalt steht.
|
|
|
|
`hidden` sitzt am Wrapper, nicht am Knopf: `x-ui.button` bringt
|
|
`inline-flex` mit, und beide Klassen haben dieselbe Spezifität —
|
|
wer gewinnt, entschiede dann die Reihenfolge im Stylesheet. Dieselbe
|
|
Falle wie bei `size-4`/`size-5` in R18, und sie ist hier mit einem
|
|
zusätzlichen Element billiger umgangen als nachgewiesen. --}}
|
|
<div data-stage-retry @class(['hidden' => $problem !== 'unknown'])>
|
|
<x-ui.button data-stage-retry-button variant="secondary" size="sm">
|
|
{{ __('hosts.terminal.stage.retry') }}
|
|
</x-ui.button>
|
|
</div>
|
|
</div>
|
|
</div>
|