SPA playlist transitions — no page refresh on track change

- Add GET /videos/{video}/player-data JSON endpoint returning stream URL,
  cover, slides, title, duration (used by client-side SPA transitions)
- Replace music playlist JS with full SPA system: plTransitionTo() swaps
  audio.src in-place (preserving browser autoplay permission), updates
  cover art, resets progress bar, then background-fetches the new page
  to swap #vdbWrap (description) and #ytcSection (comments) via DOMParser
- plSwapContent() re-runs the YTC comments IIFE after swapping innerHTML
  so comments load correctly for the new video
- Prev/next/shuffle/loop/autoplay controls now computed dynamically from
  PL_VIDEOS array — buttons stay correct after each SPA transition
- Sidebar shows ALL playlist tracks (removed @if filter); current track
  highlighted in red; clicking any card triggers SPA transition
- Browser back/forward handled via popstate + history.pushState

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
ghassanandClaude Sonnet 4.6 committed 2026-05-16 12:12:22 +03:00
1 parent 99f71c54e5
commit da02425aeb
3 files changed
+186 -48

No files matched your search

+27
View File
@@ -465,6 +465,33 @@ class VideoController extends Controller
->withCookie(cookie('_did', $did, 60 * 24 * 365 * 5));
}
public function playerData(Video $video, Request $request)
{
if (! $video->canView(Auth::user())) {
abort(403);
}
$coverUrl = $video->thumbnail
? route('media.thumbnail', $video->thumbnail)
: asset('storage/images/logo.png');
$slides = $video->slides->count() > 1
? $video->slides->map(fn ($s) => route('media.thumbnail', $s->filename))->values()->all()
: [];
return response()->json([
'id' => $video->id,
'key' => $video->getRouteKey(),
'type' => $video->type,
'stream_url' => route('videos.stream', $video),
'cover_url' => $coverUrl,
'slides' => $slides,
'title' => $video->title,
'author' => $video->user->name ?? '',
'duration' => $video->duration,
]);
}
public function matchData(Video $video)
{
if (! $video->canView(Auth::user())) {