Update playlist sidebar to use livewire
This commit is contained in:
@@ -56,14 +56,11 @@ class StreamController extends Controller
|
||||
// Playlist
|
||||
if ($request->has('playlist')) {
|
||||
// Get and check if playlist exists
|
||||
$playlist = Playlist::where('id', $request->input('playlist'))->firstOrFail();
|
||||
$playlist = Playlist::withCount('episodes')->where('id', $request->input('playlist'))->firstOrFail();
|
||||
|
||||
// Check if episode is in playlist
|
||||
$inPlaylist = PlaylistEpisode::where('playlist_id', $playlist->id)->where('episode_id', $episode->id)->firstOrFail();
|
||||
|
||||
// Get Playlist Episodes and order them
|
||||
$playlistEpisodes = $playlist->episodes()->orderBy('position')->get();
|
||||
|
||||
// Check if authorized
|
||||
if ($playlist->is_private && (Auth::guest() || (! Auth::guest() && Auth::user()->id != $playlist->user_id))) {
|
||||
abort(404);
|
||||
@@ -75,7 +72,6 @@ class StreamController extends Controller
|
||||
'studioEpisodes' => $studioEpisodes,
|
||||
'gallery' => $gallery,
|
||||
'playlist' => $playlist,
|
||||
'playlistEpisodes' => $playlistEpisodes,
|
||||
'popularWeekly' => CacheHelper::getPopularWeekly(),
|
||||
'isMobile' => $isMobile,
|
||||
]);
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Models\Episode;
|
||||
use App\Models\Playlist;
|
||||
use App\Models\PlaylistEpisode;
|
||||
use App\Services\PlaylistService;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Livewire\Component;
|
||||
|
||||
class PlaylistSidebar extends Component
|
||||
{
|
||||
public const PAGE_SIZE = 20;
|
||||
|
||||
public const MAX_WINDOW = 60;
|
||||
|
||||
protected PlaylistService $playlistService;
|
||||
|
||||
public Playlist $playlist;
|
||||
|
||||
public Episode $currentEpisode;
|
||||
|
||||
public int $currentEpisodeId;
|
||||
|
||||
public int $total = 0;
|
||||
|
||||
public int $windowStart = 1;
|
||||
|
||||
public int $windowEnd = 0;
|
||||
|
||||
public bool $isOwner = false;
|
||||
|
||||
public bool $collapsible = false;
|
||||
|
||||
public ?string $previousEpisodeSlug = null;
|
||||
|
||||
public ?string $nextEpisodeSlug = null;
|
||||
|
||||
public function boot(PlaylistService $playlistService): void
|
||||
{
|
||||
$this->playlistService = $playlistService;
|
||||
}
|
||||
|
||||
public function mount(int $playlistId, int $currentEpisodeId, bool $collapsible = false): void
|
||||
{
|
||||
$this->playlist = Playlist::with('user')->withCount('episodes')->findOrFail($playlistId);
|
||||
$this->currentEpisodeId = $currentEpisodeId;
|
||||
$this->currentEpisode = Episode::with(['gallery' => fn ($query) => $query->orderBy('id')->limit(1)])
|
||||
->findOrFail($currentEpisodeId);
|
||||
$this->total = $this->playlist->episodes_count;
|
||||
$this->collapsible = $collapsible;
|
||||
$this->isOwner = Auth::check() && Auth::user()->id === $this->playlist->user_id;
|
||||
|
||||
$this->repairNullPositions();
|
||||
|
||||
$position = $this->currentPosition() ?? 1;
|
||||
|
||||
$this->setWindowAround($position);
|
||||
$this->resolveAdjacentSlugs($position);
|
||||
}
|
||||
|
||||
public function getEpisodesProperty(): Collection
|
||||
{
|
||||
return PlaylistEpisode::query()
|
||||
->where('playlist_id', $this->playlist->id)
|
||||
->whereBetween('position', [$this->windowStart, $this->windowEnd])
|
||||
->orderBy('position')
|
||||
->with([
|
||||
'episode.gallery' => fn ($gallery) => $gallery->orderBy('id')->limit(1),
|
||||
'episode.studio',
|
||||
])
|
||||
->get();
|
||||
}
|
||||
|
||||
public function appendChunk(): void
|
||||
{
|
||||
if ($this->windowEnd >= $this->total) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->windowEnd = min($this->total, $this->windowEnd + self::PAGE_SIZE);
|
||||
$this->windowStart = max(1, $this->windowEnd - self::MAX_WINDOW + 1);
|
||||
}
|
||||
|
||||
public function prependChunk(): void
|
||||
{
|
||||
if ($this->windowStart <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->windowStart = max(1, $this->windowStart - self::PAGE_SIZE);
|
||||
$this->windowEnd = min($this->total, $this->windowStart + self::MAX_WINDOW - 1);
|
||||
}
|
||||
|
||||
public function remove(int $playlistEpisodeId): void
|
||||
{
|
||||
if (! $this->isOwner) {
|
||||
return;
|
||||
}
|
||||
|
||||
$playlistEpisode = PlaylistEpisode::find($playlistEpisodeId);
|
||||
|
||||
if (! $playlistEpisode) {
|
||||
return;
|
||||
}
|
||||
|
||||
$playlistEpisode->delete();
|
||||
$this->playlistService->reorderPositions($this->playlist);
|
||||
$this->playlist->loadCount('episodes');
|
||||
|
||||
$this->total = $this->playlist->episodes_count;
|
||||
|
||||
$this->windowEnd = min($this->windowEnd, max(1, $this->total));
|
||||
$this->windowStart = min($this->windowStart, max(1, $this->total));
|
||||
|
||||
$position = $this->currentPosition();
|
||||
|
||||
if ($position) {
|
||||
$this->resolveAdjacentSlugs($position);
|
||||
}
|
||||
}
|
||||
|
||||
public function render(): View
|
||||
{
|
||||
$activePlaylistEpisode = $this->activePlaylistEpisode();
|
||||
|
||||
return view('livewire.playlist-sidebar', [
|
||||
'episodes' => $this->episodes,
|
||||
'currentPosition' => $activePlaylistEpisode?->position ?? 1,
|
||||
'currentPlaylistEpisodeId' => $activePlaylistEpisode?->id,
|
||||
'isOwner' => $this->isOwner,
|
||||
]);
|
||||
}
|
||||
|
||||
private function activePlaylistEpisode(): ?PlaylistEpisode
|
||||
{
|
||||
return PlaylistEpisode::where('playlist_id', $this->playlist->id)
|
||||
->where('episode_id', $this->currentEpisodeId)
|
||||
->first();
|
||||
}
|
||||
|
||||
private function currentPosition(): ?int
|
||||
{
|
||||
return $this->activePlaylistEpisode()?->position;
|
||||
}
|
||||
|
||||
private function setWindowAround(int $position): void
|
||||
{
|
||||
$this->windowStart = max(1, $position - self::PAGE_SIZE);
|
||||
$this->windowEnd = min($this->total, $position + self::PAGE_SIZE);
|
||||
}
|
||||
|
||||
private function resolveAdjacentSlugs(int $position): void
|
||||
{
|
||||
$adjacent = PlaylistEpisode::query()
|
||||
->where('playlist_id', $this->playlist->id)
|
||||
->whereBetween('position', [$position - 1, $position + 1])
|
||||
->orderBy('position')
|
||||
->with('episode')
|
||||
->get();
|
||||
|
||||
$slugsByPosition = $adjacent->keyBy('position');
|
||||
|
||||
$this->previousEpisodeSlug = $slugsByPosition->get($position - 1)?->episode->slug;
|
||||
$this->nextEpisodeSlug = $slugsByPosition->get($position + 1)?->episode->slug;
|
||||
}
|
||||
|
||||
private function repairNullPositions(): void
|
||||
{
|
||||
if (! PlaylistEpisode::where('playlist_id', $this->playlist->id)->whereNull('position')->exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlaylistEpisode::where('playlist_id', $this->playlist->id)
|
||||
->orderBy('position')->orderBy('id')
|
||||
->get()
|
||||
->each(fn ($playlistEpisode, $index) => $playlistEpisode->update(['position' => $index + 1]));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user