Language filter chips on the videos feed

Adds one chip per language currently present in public content —
counting both primary language and any secondary audio track, sorted
by video count, capped at 12. Clicking a chip lists every video whose
primary is that language or that has a matching secondary track; cards
surfaced only via a secondary track link straight to /videos/{key}?track=<id>
so the pinned playback wiring loads the right audio, get a small flag
badge on the thumbnail, and their hover-preview streams the track file
instead of the primary.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
ghassanandClaude Opus 4.7 committed 2026-07-31 03:27:42 +03:00
1 parent 8d27520bdb
commit fcb752dd76
4 files changed
+163 -10

No files matched your search

@@ -3,7 +3,15 @@
@php
use App\Data\Languages;
$videoUrl = $video ? route('videos.stream', $video) : null;
// When a specific audio track is being surfaced (e.g. via the language
// filter chips), the hover-preview should play that language, not the
// primary. audio-track route serves the track file directly.
$forceTrackIdEarly = $video ? $video->getAttribute('_force_track_id') : null;
$videoUrl = $video
? ($forceTrackIdEarly
? route('videos.audio-track', ['video' => $video, 'track' => $forceTrackIdEarly])
: route('videos.stream', $video))
: null;
$thumbnailUrl = $video && $video->thumbnail
? route('media.thumbnail', $video->thumbnail)
: ($video ? 'https://picsum.photos/seed/' . $video->id . '/640/360' : 'https://picsum.photos/seed/random/640/360');
@@ -20,8 +28,18 @@ $isShorts = $video && $video->isShorts();
// Check if current user is the owner of the video
$isOwner = $video && auth()->check() && auth()->id() == $video->user_id;
// Language flag code (null when no language set)
$langFlag = $video ? Languages::flag($video->language) : null;
// When surfacing a video via a secondary audio track (e.g. from the
// language filter chips) the controller tags it with these runtime
// attributes so the card links straight to that track and badges the
// thumbnail with its flag.
$forceTrackId = $video ? $video->getAttribute('_force_track_id') : null;
$forceTrackFlag = $video ? $video->getAttribute('_force_track_flag') : null;
// Language flag code (null when no language set). Prefer the forced
// track flag when set — it's the language the card is being surfaced for.
$langFlag = $forceTrackFlag ?: ($video ? Languages::flag($video->language) : null);
$showUrl = $video ? route('videos.show', $video) . ($forceTrackId ? ('?track=' . $forceTrackId) : '') : '#';
// Size classes
$sizeClasses = match($size) {
@@ -31,7 +49,7 @@ $sizeClasses = match($size) {
@endphp
<div class="yt-video-card {{ $sizeClasses }}" data-video-url="{{ $videoUrl }}">
<a href="{{ $video ? route('videos.show', $video) : '#' }}">
<a href="{{ $showUrl }}">
<div class="yt-video-thumb" onmouseenter="playVideo(this)" onmouseleave="stopVideo(this)"
data-audio="{{ $video && $video->isAudioOnly() ? 'true' : 'false' }}">
<img src="{{ $thumbnailUrl }}" alt="{{ $video->title ?? 'Video' }}" loading="lazy" decoding="async" onload="this.classList.add('loaded');this.closest('.yt-video-thumb').classList.add('loaded')">
@@ -54,6 +72,12 @@ $sizeClasses = match($size) {
<i class="bi bi-collection-play-fill"></i> SHORTS
</span>
@endif
@if($forceTrackId && $forceTrackFlag)
<span class="yt-track-lang-badge" title="Plays the {{ strtoupper($video->language ?? '') }} track's language variant">
<span class="fi fi-{{ $forceTrackFlag }}"></span>
<span>Track</span>
</span>
@endif
@if($isOwner && $video->visibility === 'private')
<span class="yt-visibility-badge yt-visibility-private">
<i class="bi bi-lock-fill"></i> Private
@@ -74,7 +98,7 @@ $sizeClasses = match($size) {
</a>
<div class="yt-video-details">
<h3 class="yt-video-title">
<a href="{{ $video ? route('videos.show', $video) : '#' }}">
<a href="{{ $showUrl }}">
@if($langFlag)
<span class="fi fi-{{ $langFlag }} vc-lang-flag"></span>
@endif