From c3955c4a7c377f710e000432c5713a085773d135 Mon Sep 17 00:00:00 2001 From: ghassan Date: Wed, 21 Oct 2026 10:31:27 +0300 Subject: [PATCH] feat(home): Shorts shelf above the main feed The home grid used to interleave shorts with regular videos ordered by upload date, so a cluster of 60-second portrait clips could fill the first row and push the non-shorts off the fold. Split them: - The main feed grid now excludes shorts (notShorts() filter). - A horizontally-scrolling Shorts shelf renders above the grid with up to 12 latest shorts, each a real to /shorts/{id} so tapping it deep-links the vertical feed to that short. - "See all" link in the shelf header jumps to the full /shorts feed. - Shelf is skipped entirely when there are no shorts to show. Co-Authored-By: Claude Opus 4.7 (1M context) --- app/Http/Controllers/VideoController.php | 9 +++- resources/views/videos/index.blade.php | 54 ++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/VideoController.php b/app/Http/Controllers/VideoController.php index 18b7545..4e58924 100644 --- a/app/Http/Controllers/VideoController.php +++ b/app/Http/Controllers/VideoController.php @@ -176,7 +176,12 @@ class VideoController extends Controller } // ── All (home) — mixed chronological feed ───────────────── - $videos = Video::public()->latest()->limit(60)->get(); + // Videos shown in the grid are the newest non-shorts. Shorts render + // in their own horizontally-scrolling shelf injected after the first + // row of cards (see videos/index.blade.php), so the home grid isn't + // diluted by 60-second portrait clips. + $videos = Video::public()->notShorts()->latest()->limit(60)->get(); + $homeShorts = Video::public()->where('is_shorts', true)->latest()->limit(12)->get(); $playlistQuery = Playlist::withCount('videos') ->with(['user', 'videos' => fn($q) => $q->orderBy('playlist_videos.position')->limit(1)]) @@ -193,7 +198,7 @@ class VideoController extends Controller ->sortByDesc('date') ->values(); - return view('videos.index', compact('feedItems', 'filter', 'langChips') + [ + return view('videos.index', compact('feedItems', 'filter', 'langChips', 'homeShorts') + [ 'videos' => collect(), 'shorts' => collect(), 'matches' => collect(), 'playlists' => collect(), ]); } diff --git a/resources/views/videos/index.blade.php b/resources/views/videos/index.blade.php index 219f41e..d124171 100644 --- a/resources/views/videos/index.blade.php +++ b/resources/views/videos/index.blade.php @@ -237,6 +237,60 @@ ══════════════════════════════════════════════ --}} @elseif(!isset($query) && (!isset($filter) || $filter === 'all')) + @if(!empty($homeShorts) && $homeShorts->count()) + {{-- Horizontally-scrolling Shorts shelf. Sits above the main feed grid + so the user sees fresh short-form content without the feed being + drowned in 60-second portrait clips. --}} +
+ + +
+ + @endif + @if(isset($feedItems) && $feedItems->count())
@foreach($feedItems as $entry)