@php // CHANGELOG.md uses German Keep-a-Changelog headings as the canonical section keys; // map each to a localized display label + a badge tone. $sectionKey = [ 'Hinzugefügt' => 'added', 'Geändert' => 'changed', 'Behoben' => 'fixed', 'Sicherheit' => 'security', 'Entfernt' => 'removed', 'Veraltet' => 'deprecated', ]; $sectionTone = [ 'added' => 'accent', 'changed' => 'cyan', 'fixed' => 'neutral', 'security' => 'accent', 'removed' => 'neutral', 'deprecated' => 'neutral', ]; $sectionLabel = fn (string $g): string => isset($sectionKey[$g]) ? __('versions.section_'.$sectionKey[$g]) : $g; $tone = fn (string $g): string => $sectionTone[$sectionKey[$g] ?? ''] ?? 'neutral'; // Toned glance-dots on each collapsed release row (static classes so Tailwind's scanner sees them). $dotClass = ['accent' => 'bg-accent', 'cyan' => 'bg-cyan', 'neutral' => 'bg-ink-4']; $repoHost = parse_url($repository, PHP_URL_HOST); $repoPath = trim((string) parse_url($repository, PHP_URL_PATH), '/'); $isUpdate = $updateState === 'update'; @endphp {{-- Auto-check for updates on load (async, non-blocking) so an available update + button show without the operator clicking "check" first. autoCheck() no-ops while an update is running. --}}
{{-- Header --}}

{{ __('versions.eyebrow') }}

{{ __('versions.heading') }}

{{ __('versions.check_updates') }}
{{-- Honest status banner — installed version vs. newest release tag in the channel --}}
$isUpdate, 'border-line' => ! $isUpdate, ])> {{-- Icon + version/badges block --}}
$isUpdate, 'border-accent/25 bg-accent/10 text-accent-text' => ! $isUpdate, ])>

Clusev v{{ $version }} {{ __('versions.channel_badge', ['channel' => $channel]) }} @if ($latestTag) {{ __('versions.latest_release_badge', ['tag' => $latestTag]) }} @endif

@if ($updateStatus) {{ $updateStatus }} @else {{ __('versions.banner_default') }} @endif

{{-- One-click update: writes the update sentinel; a host watcher runs update.sh. Mirrors the System restart button (direct click → "running" notice via a flag — not data-destructive, so no modal). Only offered once a check found a newer release. --}} @if ($updateRequested) {{-- Poll until the rebuilt stack reports a newer version (pollUpdate flips the state + fires a success toast). Survives the rebuild downtime: failed polls just retry. --}}

{{ __('versions.update_running') }}

@elseif ($isUpdate) {{ __('versions.update_now') }} @endif @if ($lastChecked) {{ __('versions.checked_at', ['time' => $lastChecked]) }} @endif
{{-- Release history — grouped into major.minor series, paginated (no endless scroll) --}} @if (empty($seriesList))

{{ __('versions.changelog_empty') }}

@else
{{-- Series index: horizontal pills on small/medium screens, a vertical rail from xl --}} {{-- Releases for the active series --}}
@if ($activeSeries) {{-- Series sub-header: which series, how many releases, latest date --}}
@if ($activeSeries['unreleased'] || $activeSeries['key'] === 'other') {{ $activeSeries['label'] }} @else {{ __('versions.series_label', ['series' => $activeSeries['label']]) }} @endif {{ trans_choice('versions.series_count', $activeSeries['count'], ['count' => $activeSeries['count']]) }} @if ($activeSeries['latest']) {{ $activeSeries['latest'] }} @endif
{{-- Accordion: the first release of each page is open, the rest collapse --}}
@foreach ($pagedReleases as $rel) {{-- wire:ignore.self keeps a user's open/closed toggle from being reset when an unrelated re-render (autoCheck / check-updates / the in-update poll) morphs the page; a series/page change uses a fresh wire:key, so it re-defaults to first-open. --}}
first) open @endif> @if ($rel['unreleased']) {{ __('versions.unreleased') }} {{ __('versions.in_progress') }} @else v{{ $rel['version'] }} @if ($rel['date']) {{ $rel['date'] }} @endif @endif {{-- Toned glance-dots: which change categories this release has --}}
@foreach ($rel['groups'] as $group => $items)
{{ $sectionLabel($group) }}
    @foreach ($items as $text)
  • {{ $text }}
  • @endforeach
@endforeach
@endforeach
{{-- Pagination within the active series --}} @if ($totalPages > 1) @endif @endif
@endif
{{-- Aside --}}
v{{ $version }} {{ __('versions.running') }}
{{ __('versions.build') }}
{{ $build['sha'] ?? '—' }}
{{ __('versions.branch') }}
{{ $build['branch'] }}
{{ __('versions.channel') }}
{{ $channel }}
{{ __('versions.latest_release') }}
{{ $latestTag ? 'v'.$latestTag : '—' }}
{{ __('versions.license') }}
{{ $license }}

{{ __('versions.update_hint') }}

sudo clusev update
{{ $repoPath }} {{ $repoHost }}

{{ __('versions.open_core', ['license' => $license]) }}