diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 80fea93..92d3854 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -18,7 +18,7 @@ class UserController extends Controller { public function __construct() { - $this->middleware('auth')->except(['channel']); + $this->middleware('auth')->except(['channel', 'channelVideosMore']); } // Typeahead search for members (used by the "Share to member" picker) @@ -372,6 +372,38 @@ class UserController extends Controller return redirect()->route('history')->with('toast_success', 'Watch history cleared.'); } + /** + * JSON endpoint powering the "Load more" button on the channel Videos + * tab. Takes a username + optional cursor and returns a page of + * server-rendered video cards + next cursor. Reuses the cursorPaginate + * pattern Phase 2 established for the home feed. + */ + public function channelVideosMore(Request $request, string $username) + { + $owner = User::where('username', $username)->firstOrFail(); + $viewer = Auth::user(); + $isOwner = $viewer && $viewer->id === $owner->id; + + $query = $isOwner + ? Video::where('user_id', $owner->id) + : Video::public()->where('user_id', $owner->id); + + $paginator = $query->where('is_shorts', false) + ->latest('id') + ->cursorPaginate(24); + + $html = ''; + foreach ($paginator->items() as $video) { + $html .= view('components.video-card', ['video' => $video, 'hideChannelInfo' => true])->render(); + } + + return response()->json([ + 'items' => $html, + 'next_cursor' => optional($paginator->nextCursor())->encode(), + 'has_more' => $paginator->hasMorePages(), + ]); + } + /** * Subscriptions feed — the public videos uploaded by every channel the * viewer is subscribed to, newest first. Replaces the dead href="#" that diff --git a/resources/views/user/channel.blade.php b/resources/views/user/channel.blade.php index 5840fd3..66cdcc6 100644 --- a/resources/views/user/channel.blade.php +++ b/resources/views/user/channel.blade.php @@ -701,6 +701,56 @@ $headerSocialMap = [ No videos match your search + + {{-- Cursor-paginated Load More. The sentinel sits below the grid and + fetches the next slice when scrolled into view. A manual Load More + button is the fallback for browsers without IntersectionObserver. --}} +
+ + @else