Compare commits

..

6 Commits

Author SHA1 Message Date
w33b a6fe34a0d1 Reduce queries on home page by eager loading into cache 2026-05-24 22:15:16 +02:00
w33b bb53e06c69 Smaller style fix 2026-05-24 21:39:46 +02:00
w33b 5cae5dc658 Fix more responsiveness issues 2026-05-24 19:39:20 +02:00
w33b 356d07365f Update episode card design 2026-05-24 19:38:50 +02:00
w33b 3574d20fae Update hentai info design & Remove livewire view count 2026-05-24 15:52:22 +02:00
w33b 9fc9e8ed10 Update comments design 2026-05-24 14:49:46 +02:00
17 changed files with 616 additions and 458 deletions
+1 -1
View File
@@ -128,7 +128,7 @@ class CacheHelper
public static function getLatestComments() public static function getLatestComments()
{ {
return Cache::remember('latest_comments', now()->addMinutes(60), function () { return Cache::remember('latest_comments', now()->addMinutes(60), function () {
return Comment::latest()->take(10)->get(); return Comment::with('user')->latest()->take(10)->get();
}); });
} }
} }
-29
View File
@@ -1,29 +0,0 @@
<?php
namespace App\Livewire;
use App\Models\Episode;
use Livewire\Component;
class ViewCount extends Component
{
public $episodeId = 0;
public $viewCount = 0;
public function mount(Episode $episode)
{
$this->episodeId = $episode->id;
$this->viewCount = $episode->view_count;
}
public function update()
{
$this->viewCount = Episode::where('id', $this->episodeId)->firstOrFail()->view_count;
}
public function render()
{
return view('livewire.view-count');
}
}
@@ -24,7 +24,7 @@
<div class="group w-full p-1"> <div class="group w-full p-1">
<a <a
href="{{ route('hentai.index', ['title' => $episode->slug]) }}" href="{{ route('hentai.index', ['title' => $episode->slug]) }}"
class="block overflow-hidden rounded-2xl border dark:border-neutral-800 border-neutral-300 dark:bg-neutral-900 transition-all duration-300 hover:-translate-y-1 dark:hover:border-neutral-700 hover:border-neutral-400 hover:shadow-2xl hover:shadow-black/30" class="block overflow-hidden rounded-2xl border border-neutral-200 bg-white transition-all duration-300 hover:-translate-y-1 hover:border-neutral-400 hover:shadow-xl dark:border-neutral-800 dark:bg-neutral-900 dark:hover:border-neutral-700"
> >
<div class="relative overflow-hidden"> <div class="relative overflow-hidden">
@@ -35,7 +35,7 @@
alt="{{ $episode->title }} - {{ $episode->episode }}" alt="{{ $episode->title }} - {{ $episode->episode }}"
loading="lazy" loading="lazy"
width="400" width="400"
class="aspect-[11/16] w-full object-cover object-center transform-gpu transition-transform duration-500 group-hover:scale-[1.02]" class="aspect-[11/16] w-full object-cover object-center transition-transform duration-500 group-hover:scale-[1.03]"
> >
@elseif ($view === 'thumbnail') @elseif ($view === 'thumbnail')
@php @php
@@ -50,49 +50,56 @@
loading="lazy" loading="lazy"
width="1000" width="1000"
data-gallery='@json($galleryImages)' data-gallery='@json($galleryImages)'
class="preview-gallery aspect-video w-full object-cover object-center transform-gpu transition-transform duration-500 group-hover:scale-[1.02]" class="preview-gallery aspect-video w-full object-cover object-center transition-transform duration-500 group-hover:scale-[1.03]"
> >
@endif @endif
{{-- Overlay Gradient --}} {{-- Dark Overlay --}}
<div class="pointer-events-none absolute inset-0 bg-gradient-to-t from-black/80 via-black/10 to-transparent"></div> <div class="pointer-events-none absolute inset-0 bg-gradient-to-t from-black/90 via-black/20 to-transparent"></div>
{{-- Top Row --}} {{-- Top Meta --}}
<div class="absolute inset-x-0 top-0 z-20 flex items-start justify-between p-3"> <div class="pointer-events-none absolute inset-x-0 top-0 z-20 flex items-start justify-between p-3">
{{-- Problematic Tags --}} {{-- Problematic Tags --}}
@if (!empty($problematic)) @if (!empty($problematic))
<div class="rounded-xl border border-red-500/30 bg-red-900/70 px-2.5 py-1 text-xs font-semibold text-white"> <div class="rounded-full bg-red-700/40 px-2 py-1 text-[11px] font-semibold uppercase tracking-wide text-white ring-1 ring-red-700/70">
<i class="fa-solid fa-triangle-exclamation mr-1"></i> <i class="fa-solid fa-triangle-exclamation mr-1"></i>
{{ $problematic }} {{ $problematic }}
</div> </div>
@endif @endif
{{-- Resolution --}} {{-- Resolution --}}
<div class="ml-auto rounded-xl bg-black/70 px-2.5 py-1 text-xs font-semibold tracking-wide text-neutral-100 ring-1 ring-white/10"> <div class="ml-auto rounded-full bg-black/70 px-2 py-1 text-[11px] font-semibold tracking-wide text-white ring-1 ring-white/10">
{{ $episode->getResolution() }} {{ $episode->getResolution() }}
</div> </div>
</div> </div>
{{-- Bottom Stats --}} {{-- Bottom Content --}}
<div class="absolute inset-x-0 bottom-0 z-20 p-3"> <div class="pointer-events-none absolute inset-x-0 bottom-0 z-20 p-4">
<div class="flex items-end justify-between gap-3">
{{-- Title --}}
<h3 class=" text-sm font-semibold leading-snug text-white md:text-base">
{{ $title }}
</h3>
{{-- Bottom Row --}}
<div class="mt-3 flex items-center justify-between gap-3">
{{-- Stats --}} {{-- Stats --}}
<div class="flex flex-1 flex-wrap items-center gap-x-3 gap-y-1 text-sm font-bold text-neutral-200"> <div class="flex flex-wrap items-center gap-3 text-sm font-bold text-neutral-200">
<span class="flex items-center gap-1"> <span class="flex items-center gap-1">
<i class="fa-regular fa-eye text-neutral-400"></i> <i class="fa-regular fa-eye text-neutral-200 font-bold"></i>
{{ $episode->viewCountFormatted() }} {{ $episode->viewCountFormatted() }}
</span> </span>
<span class="flex items-center gap-1"> <span class="flex items-center gap-1">
<i class="fa-regular fa-heart text-neutral-400"></i> <i class="fa-regular fa-heart text-neutral-200 font-bold"></i>
{{ $episode->likeCount() }} {{ $episode->likeCount() }}
</span> </span>
<span class="flex items-center gap-1"> <span class="flex items-center gap-1">
<i class="fa-regular fa-comment text-neutral-400"></i> <i class="fa-regular fa-comment text-neutral-200 font-bold"></i>
{{ $episode->commentCount() }} {{ $episode->commentCount() }}
</span> </span>
</div> </div>
@@ -102,9 +109,9 @@
@if ($isWatched) @if ($isWatched)
<div class="shrink-0 rounded-full bg-emerald-800/40 px-2.5 py-1 text-xs font-semibold text-emerald-300 ring-1 ring-emerald-500/30"> <div class="shrink-0 rounded-full bg-emerald-800/40 px-2.5 py-1 text-xs font-semibold text-emerald-300 ring-1 ring-emerald-500/30">
@if ($view === 'thumbnail') @if ($view === 'thumbnail')
<i class="fa-solid fa-check mr-1"></i> Watched <i class="fa-solid fa-eye mr-1"></i> Watched
@else @else
<i class="fa-solid fa-check"></i> <i class="fa-solid fa-eye"></i>
@endif @endif
</div> </div>
@else @else
@@ -116,13 +123,7 @@
</div> </div>
</div> </div>
</div>
{{-- Content --}}
<div class="relative isolate border-t dark:border-neutral-800 dark:bg-neutral-900 bg-white border-neutral-100 p-4">
<h3 class="text-sm font-semibold leading-relaxed dark:text-neutral-100 text-neutral-900 transition-colors duration-200 dark:group-hover:text-white">
{{ $title }}
</h3>
</div> </div>
</a> </a>
</div> </div>
@@ -55,10 +55,9 @@
> >
{{-- Resolution Badge --}} {{-- Resolution Badge --}}
<span <div class="absolute right-2 top-2 rounded-lg bg-black/70 px-2 py-1 text-[11px] font-semibold tracking-wide text-white ring-1 ring-white/10">
class="absolute right-0 top-0 rounded-bl-lg bg-rose-700/70 px-3 py-1 text-xs font-semibold text-white shadow-lg backdrop-blur">
{{ $resolution }} {{ $resolution }}
</span> </div>
{{-- Gradient Overlay --}} {{-- Gradient Overlay --}}
<div <div
@@ -4,10 +4,10 @@
@php @php
$random = \cache()->remember('random_home', 300, function () { $random = \cache()->remember('random_home', 300, function () {
return \App\Models\Episode::inRandomOrder()->limit(8)->get(); ; return \App\Models\Episode::inRandomOrder()->limit(7)->get(); ;
}); });
@endphp @endphp
<div class="mb-6"> <div class="mb-6">
@include('home.partials.tab.template', ['episodes' => $random, 'showThumbnails' => false]) @include('home.partials.tab.template', ['episodes' => $random, 'isThumbnail' => false, 'rowsCount' => 1])
</div> </div>
@@ -1,9 +1,12 @@
@php @props([
$isThumbnail = $showThumbnails; 'isThumbnail',
'rowsCount' => 2,
])
@php
$gridClasses = $isThumbnail $gridClasses = $isThumbnail
? 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-6' ? 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4'
: 'grid-cols-2 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-8'; : 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-6 3xl:grid-cols-7';
// Render enough items for largest possible layout // Render enough items for largest possible layout
$limit = 24; $limit = 24;
@@ -13,7 +16,7 @@
<div <div
class="episode-grid grid {{ $gridClasses }}" class="episode-grid grid {{ $gridClasses }}"
data-rows="2" data-rows="{{ $rowsCount }}"
> >
@foreach ($episodes->take($limit) as $ep) @foreach ($episodes->take($limit) as $ep)
@php @php
@@ -22,7 +25,7 @@
: $ep; : $ep;
@endphp @endphp
<div class="episode-item"> <div class="episode-item p-1">
<x-episode-cover <x-episode-cover
:episode="$episode" :episode="$episode"
:view="$view" :view="$view"
@@ -34,11 +34,11 @@
</li> </li>
</ul> </ul>
@php $showThumbnails = true; @endphp @php $isThumbnail = true; @endphp
@auth @auth
@if (!Auth::user()->home_middle_design) @if (!Auth::user()->home_middle_design)
@php $showThumbnails = false; @endphp @php $isThumbnail = false; @endphp
@endif @endif
@endauth @endauth
@@ -48,7 +48,7 @@
id="tabs-most-views" role="tabpanel" aria-labelledby="tabs-most-views-tab" data-te-tab-active> id="tabs-most-views" role="tabpanel" aria-labelledby="tabs-most-views-tab" data-te-tab-active>
@include('home.partials.tab.template', [ @include('home.partials.tab.template', [
'episodes' => $popularAllTime, 'episodes' => $popularAllTime,
'showThumbnails' => $showThumbnails, 'isThumbnail' => $isThumbnail,
]) ])
<div class="grid text-center pt-5 "> <div class="grid text-center pt-5 ">
<a href="{{ route('hentai.search', ['order' => 'view-count']) }}" <a href="{{ route('hentai.search', ['order' => 'view-count']) }}"
@@ -61,7 +61,7 @@
id="tabs-most-likes" role="tabpanel" aria-labelledby="tabs-most-likes-tab"> id="tabs-most-likes" role="tabpanel" aria-labelledby="tabs-most-likes-tab">
@include('home.partials.tab.template', [ @include('home.partials.tab.template', [
'episodes' => $mostLikes, 'episodes' => $mostLikes,
'showThumbnails' => $showThumbnails, 'isThumbnail' => $isThumbnail,
]) ])
<div class="grid text-center pt-5 "> <div class="grid text-center pt-5 ">
<a href="{{ route('hentai.search', ['order' => 'view-count']) }}" <a href="{{ route('hentai.search', ['order' => 'view-count']) }}"
@@ -74,7 +74,7 @@
id="tabs-popular-weekly" role="tabpanel" aria-labelledby="tabs-popular-weekly-tab"> id="tabs-popular-weekly" role="tabpanel" aria-labelledby="tabs-popular-weekly-tab">
@include('home.partials.tab.template', [ @include('home.partials.tab.template', [
'episodes' => $popularWeekly, 'episodes' => $popularWeekly,
'showThumbnails' => $showThumbnails, 'isThumbnail' => $isThumbnail,
'popularView' => true, 'popularView' => true,
]) ])
<div class="grid text-center pt-5 "> <div class="grid text-center pt-5 ">
@@ -88,7 +88,7 @@
id="tabs-popular-monthly" role="tabpanel" aria-labelledby="tabs-popular-monthly-tab"> id="tabs-popular-monthly" role="tabpanel" aria-labelledby="tabs-popular-monthly-tab">
@include('home.partials.tab.template', [ @include('home.partials.tab.template', [
'episodes' => $popularMonthly, 'episodes' => $popularMonthly,
'showThumbnails' => $showThumbnails, 'isThumbnail' => $isThumbnail,
'popularView' => true, 'popularView' => true,
]) ])
<div class="grid text-center pt-5 "> <div class="grid text-center pt-5 ">
@@ -21,18 +21,18 @@
</ul> </ul>
@php $showThumbnails = false; @endphp @php $isThumbnail = false; @endphp
@auth @auth
@if(Auth::user()->home_top_design) @if(Auth::user()->home_top_design)
@php $showThumbnails = true; @endphp @php $isThumbnail = true; @endphp
@endif @endif
@endauth @endauth
<!--Tabs content--> <!--Tabs content-->
<div class="mb-6"> <div class="mb-6">
<div class="hidden opacity-100 transition-opacity duration-150 ease-linear data-[te-tab-active]:block" id="tabs-recently-uploaded" role="tabpanel" aria-labelledby="tabs-recently-uploaded-tab" data-te-tab-active> <div class="hidden opacity-100 transition-opacity duration-150 ease-linear data-[te-tab-active]:block" id="tabs-recently-uploaded" role="tabpanel" aria-labelledby="tabs-recently-uploaded-tab" data-te-tab-active>
@include('home.partials.tab.template', ['episodes' => $recentlyUploaded, 'showThumbnails' => $showThumbnails]) @include('home.partials.tab.template', ['episodes' => $recentlyUploaded, 'isThumbnail' => $isThumbnail])
<div class="grid text-center pt-5 "> <div class="grid text-center pt-5 ">
<a href="{{ route('hentai.search', ['order' => 'recently-uploaded']) }}" <a href="{{ route('hentai.search', ['order' => 'recently-uploaded']) }}"
class="rounded bg-rose-600 p-1 mr-2 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600"> class="rounded bg-rose-600 p-1 mr-2 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600">
@@ -41,7 +41,7 @@
</div> </div>
</div> </div>
<div class="hidden opacity-0 transition-opacity duration-150 ease-linear data-[te-tab-active]:block" id="tabs-recently-released" role="tabpanel"aria-labelledby="tabs-recently-released-tab"> <div class="hidden opacity-0 transition-opacity duration-150 ease-linear data-[te-tab-active]:block" id="tabs-recently-released" role="tabpanel"aria-labelledby="tabs-recently-released-tab">
@include('home.partials.tab.template', ['episodes' => $recentlyReleased, 'showThumbnails' => $showThumbnails]) @include('home.partials.tab.template', ['episodes' => $recentlyReleased, 'isThumbnail' => $isThumbnail])
<div class="grid text-center pt-5 "> <div class="grid text-center pt-5 ">
<a href="{{ route('hentai.search', ['order' => 'recently-released']) }}" <a href="{{ route('hentai.search', ['order' => 'recently-released']) }}"
class="rounded bg-rose-600 p-1 mr-2 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600"> class="rounded bg-rose-600 p-1 mr-2 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600">
@@ -50,7 +50,7 @@
</div> </div>
</div> </div>
<div class="hidden opacity-0 transition-opacity duration-150 ease-linear data-[te-tab-active]:block" id="tabs-trending" role="tabpanel"aria-labelledby="tabs-trending-tab"> <div class="hidden opacity-0 transition-opacity duration-150 ease-linear data-[te-tab-active]:block" id="tabs-trending" role="tabpanel"aria-labelledby="tabs-trending-tab">
@include('home.partials.tab.template', ['episodes' => $popularDaily, 'showThumbnails' => $showThumbnails, 'popularView' => true]) @include('home.partials.tab.template', ['episodes' => $popularDaily, 'isThumbnail' => $isThumbnail, 'popularView' => true])
<div class="grid text-center pt-5 "> <div class="grid text-center pt-5 ">
<a href="{{ route('hentai.search', ['order' => 'recently-released']) }}" <a href="{{ route('hentai.search', ['order' => 'recently-released']) }}"
class="rounded invisible bg-rose-600 p-1 mr-2 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600"> class="rounded invisible bg-rose-600 p-1 mr-2 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600">
+233 -133
View File
@@ -1,153 +1,253 @@
<div> <div id="comment-{{ $comment->id }}">
<div class="flex" id="comment-{{ $comment->id }}">
<div class="flex-shrink-0 mr-4"> <div class="group flex gap-4">
{{-- Avatar --}}
<div class="shrink-0">
@if($comment->isDeletedByModerator()) @if($comment->isDeletedByModerator())
<img class="h-10 w-10 rounded-full" src="{{ asset('images/default-avatar.webp') }}" alt="Deleted comment"> <img
class="h-10 w-10 rounded-full object-cover opacity-60"
src="{{ asset('images/default-avatar.webp') }}"
alt="Deleted comment"
>
@else @else
<img class="h-10 w-10 rounded-full" src="{{ $comment->user->getAvatar() }}" alt="{{ $comment->user->name }}"> <img
class="h-10 w-10 rounded-full object-cover ring-2 ring-white dark:ring-neutral-800"
src="{{ $comment->user->getAvatar() }}"
alt="{{ $comment->user->name }}"
>
@endif @endif
</div> </div>
<div class="flex-grow">
<div class="flex gap-2">
@if($comment->isDeletedByModerator())
@if (Auth::check() && (Auth::user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR) || Auth::user()->hasRole(\App\Enums\UserRole::MODERATOR)))
<p class="font-medium text-gray-900 dark:text-gray-100">Deleted ({{ $comment->user->name }})</p>
@else
<p class="font-medium text-gray-900 dark:text-gray-100">Deleted</p>
@endif
@else
<p class="font-medium text-gray-900 dark:text-gray-100">{{ $comment->user->name }}</p>
@endif
@if($comment->user->hasRole(\App\Enums\UserRole::ADMINISTRATOR))
<a data-te-toggle="tooltip" title="Admin"><i class="fa-solid fa-crown text-yellow-600"></i></a>
@endif
@if($comment->user->hasRole(\App\Enums\UserRole::MODERATOR))
<a data-te-toggle="tooltip" title="Admin" class="text-rose-600">Moderator</a>
@endif
@if($comment->user->hasRole(\App\Enums\UserRole::SUPPORTER))
<a data-te-toggle="tooltip" title="Badge of appreciation for the horny people supporting us! :3"><i class="fa-solid fa-hand-holding-heart text-rose-600"></i></a>
@endif
</div>
<div class="mt-1 flex-grow w-full">
@if($comment->isDeletedByModerator())
<div class="text-gray-700 dark:text-gray-200">Deleted by moderation.</div>
@if (Auth::check() && (Auth::user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR) || Auth::user()->hasRole(\App\Enums\UserRole::MODERATOR)))
<div class="text-gray-700 dark:text-gray-300 pt-1">Original comment: {!! $comment->presenter()->markdownBody() !!}</div>
@endif
@else
@if ($isEditing)
<form wire:submit.prevent="editComment">
<div>
<label for="comment" class="sr-only">Comment body</label>
<textarea id="comment" name="comment" rows="3"
class="bg-white dark:bg-neutral-700 shadow-sm block w-full focus:ring-rose-500 focus:border-rose-500 border-gray-300 dark:border-gray-400/40 text-gray-900 dark:text-gray-200 placeholder:text-gray-400 rounded-md
@error('editState.body') border-red-500 @enderror"
placeholder="Write something" wire:model.defer="editState.body"></textarea>
@error('editState.body')
<p class="mt-2 text-sm text-red-500">{{ $message }}</p>
@enderror
</div>
<div class="mt-3 flex items-center justify-between">
<button type="submit"
class="inline-flex items-center justify-center px-4 py-2 border border-transparent font-medium rounded-md shadow-sm text-white bg-rose-600 hover:bg-rose-700 focus:outline-none focus:ring-2 focus:ring-rose-500">
Edit
</button>
</div>
</form>
@else
<div class="text-gray-700 dark:text-gray-200">{!! $comment->presenter()->markdownBody() !!}</div>
@endif
@endif
</div>
<div class="mt-2 space-x-2 flex flex-row">
<span class="text-gray-500 dark:text-gray-300">
{{ $comment->presenter()->relativeCreatedAt() }}
</span>
@guest {{-- Content --}}
<span data-te-toggle="tooltip" title="Please login to like the episode" class="text-gray-800 cursor-pointer dark:text-gray-200"> <div class="min-w-0 flex-1">
<i class="fa-regular fa-heart"></i> {{ $comment->likeCount() }}
</span>
@endguest
@auth <div class="rounded-2xl border border-neutral-200 bg-white px-5 py-4 shadow-sm transition group-hover:border-neutral-300 dark:border-neutral-800 dark:bg-neutral-800 dark:group-hover:border-neutral-700">
<!-- Like Button -->
<button class="text-gray-800 dark:text-gray-200 leading-tight cursor-pointer whitespace-nowrap" wire:click="like"> {{-- Header --}}
@if ($liked) <div class="mb-3 flex flex-wrap items-center gap-2">
<i class="fa-solid fa-heart text-rose-600"></i> {{ $likeCount }}
@else @if($comment->isDeletedByModerator())
<i class="fa-solid fa-heart"></i> {{ $likeCount }}
<span class="font-semibold text-neutral-900 dark:text-neutral-100">
@if (Auth::check() && (Auth::user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR) || Auth::user()->hasRole(\App\Enums\UserRole::MODERATOR)))
Deleted ({{ $comment->user->name }})
@else
Deleted
@endif
</span>
@else
<span class="font-semibold text-neutral-900 dark:text-neutral-100">
{{ $comment->user->name }}
</span>
@endif
{{-- Badges --}}
@if($comment->user->hasRole(\App\Enums\UserRole::ADMINISTRATOR))
<span class="inline-flex items-center rounded-full bg-yellow-100 px-2 py-0.5 text-xs font-medium text-yellow-700 dark:bg-yellow-500/10 dark:text-yellow-400">
<i class="fa-solid fa-crown mr-1"></i>
Admin
</span>
@endif
@if($comment->user->hasRole(\App\Enums\UserRole::MODERATOR))
<span class="inline-flex items-center rounded-full bg-rose-100 px-2 py-0.5 text-xs font-medium text-rose-700 dark:bg-rose-500/10 dark:text-rose-400">
Moderator
</span>
@endif
@if($comment->user->hasRole(\App\Enums\UserRole::SUPPORTER))
<span class="inline-flex items-center rounded-full bg-pink-100 px-2 py-0.5 text-xs font-medium text-pink-700 dark:bg-pink-500/10 dark:text-pink-400">
<i class="fa-solid fa-heart mr-1"></i>
Supporter
</span>
@endif
</div>
{{-- Body --}}
<div class="prose prose-sm max-w-none dark:prose-invert">
@if($comment->isDeletedByModerator())
<p class="italic text-neutral-500 dark:text-neutral-400">
Deleted by moderation.
</p>
@if (Auth::check() && (Auth::user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR) || Auth::user()->hasRole(\App\Enums\UserRole::MODERATOR)))
<div class="mt-3 rounded-xl bg-neutral-100 p-3 text-sm dark:bg-neutral-800">
{!! $comment->presenter()->markdownBody() !!}
</div>
@endif
@else
@if ($isEditing)
<form wire:submit.prevent="editComment" class="space-y-4">
<textarea
rows="4"
wire:model.defer="editState.body"
class="w-full rounded-2xl border border-neutral-300 bg-white px-4 py-3 text-sm text-neutral-900 shadow-sm transition focus:border-rose-500 focus:outline-none focus:ring-4 focus:ring-rose-500/10 dark:border-neutral-700 dark:bg-neutral-950 dark:text-neutral-100 @error('editState.body') border-red-500 @enderror"
></textarea>
@error('editState.body')
<p class="text-sm text-red-500">
{{ $message }}
</p>
@enderror
<div class="flex justify-end">
<button
type="submit"
class="rounded-xl bg-rose-600 px-4 py-2 text-sm font-medium text-white transition hover:bg-rose-700"
>
Save Changes
</button>
</div>
</form>
@else
<div class="text-gray-700 dark:text-gray-200">
{!! $comment->presenter()->markdownBody() !!}
</div>
@endif @endif
</button>
@endauth
@auth
@if ($comment->depth() < 2)
<button wire:click="$toggle('isReplying')" type="button" class="text-gray-900 dark:text-gray-100 font-medium">
Reply
</button>
@endif @endif
@can ('update', $comment) </div>
<button wire:click="$toggle('isEditing')" type="button" class="text-gray-900 dark:text-gray-100 font-medium">
Edit
</button>
@endcan
@can ('destroy', $comment) {{-- Footer --}}
<button x-data="{ <div class="mt-4 flex flex-wrap items-center gap-4 text-sm">
confirmCommentDeletion () {
if (window.confirm('Are you sure you want to delete this comment?')) {
@this.call('deleteComment');
}
}
}"
@click="confirmCommentDeletion"
type="button"
class="text-gray-900 dark:text-gray-100 font-medium"
>
Delete
</button>
@endcan
@can ('restore', $comment) <span class="text-neutral-500 dark:text-neutral-400">
{{ $comment->presenter()->relativeCreatedAt() }}
</span>
{{-- Like --}}
@guest
<span class="flex items-center gap-1 text-neutral-500 dark:text-neutral-400">
<i class="fa-regular fa-heart"></i>
{{ $comment->likeCount() }}
</span>
@endguest
@auth
<button <button
wire:click="restoreComment" wire:click="like"
type="button" class="flex items-center gap-1 text-neutral-500 transition hover:text-rose-600 dark:text-neutral-400 dark:hover:text-rose-400"
class="text-gray-900 dark:text-gray-100 font-medium"
> >
Restore @if ($liked)
<i class="fa-solid fa-heart text-rose-600"></i>
@else
<i class="fa-regular fa-heart"></i>
@endif
{{ $likeCount }}
</button> </button>
@endcan @endauth
@endauth
{{-- Actions --}}
@auth
@if ($comment->depth() < 2)
<button
wire:click="$toggle('isReplying')"
class="font-medium text-neutral-600 transition hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-neutral-100"
>
Reply
</button>
@endif
@can ('update', $comment)
<button
wire:click="$toggle('isEditing')"
class="font-medium text-neutral-600 transition hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-neutral-100"
>
Edit
</button>
@endcan
@can ('destroy', $comment)
<button
x-data="{
confirmCommentDeletion () {
if (window.confirm('Delete this comment?')) {
@this.call('deleteComment');
}
}
}"
@click="confirmCommentDeletion"
class="font-medium text-red-500 transition hover:text-red-600"
>
Delete
</button>
@endcan
@can ('restore', $comment)
<button
wire:click="restoreComment"
class="font-medium text-emerald-600 transition hover:text-emerald-700"
>
Restore
</button>
@endcan
@endauth
</div>
</div> </div>
{{-- Reply Form --}}
@if ($isReplying)
<div class="mt-4 ml-2">
<form wire:submit.prevent="postReply" class="space-y-4">
<textarea
rows="3"
wire:model.defer="replyState.body"
placeholder="Write a reply..."
class="w-full rounded-2xl border border-neutral-300 bg-white px-4 py-3 text-sm text-neutral-900 shadow-sm transition focus:border-rose-500 focus:outline-none focus:ring-4 focus:ring-rose-500/10 dark:border-neutral-700 dark:bg-neutral-950 dark:text-neutral-100 @error('replyState.body') border-red-500 @enderror"
></textarea>
@error('replyState.body')
<p class="text-sm text-red-500">
{{ $message }}
</p>
@enderror
<div class="flex justify-end">
<button
type="submit"
class="rounded-xl bg-rose-600 px-4 py-2 text-sm font-medium text-white transition hover:bg-rose-700"
>
Reply
</button>
</div>
</form>
</div>
@endif
{{-- Replies --}}
@if ($comment->children->count())
<div class="mt-2 space-y-2 border-l-2 border-neutral-200 pl-6 dark:border-neutral-700">
@foreach ($comment->children as $child)
<livewire:comment :comment="$child" :key="$child->id"/>
@endforeach
</div>
@endif
</div> </div>
</div> </div>
<div class="ml-14 mt-6">
@if ($isReplying)
<form wire:submit.prevent="postReply" class="my-4">
<div>
<label for="comment" class="sr-only">Reply body</label>
<textarea id="comment" name="comment" rows="3"
class="bg-white dark:bg-neutral-700 shadow-sm block w-full focus:ring-rose-500 focus:border-rose-500 border-gray-300 dark:border-gray-400/40 text-gray-900 dark:text-gray-200 placeholder:text-gray-400 rounded-md
@error('replyState.body') border-red-500 @enderror"
placeholder="Write something" wire:model.defer="replyState.body"></textarea>
@error('replyState.body')
<p class="mt-2 text-sm text-red-500">{{ $message }}</p>
@enderror
</div>
<div class="mt-3 flex items-center justify-between">
<button type="submit"
class="inline-flex items-center justify-center px-4 py-2 border border-transparent font-medium rounded-md shadow-sm text-white bg-rose-600 hover:bg-rose-700 focus:outline-none focus:ring-2 focus:ring-rose-500">
Comment
</button>
</div>
</form>
@endif
@foreach ($comment->children as $child)
<livewire:comment :comment="$child" :key="$child->id"/>
@endforeach
</div>
</div> </div>
+77 -41
View File
@@ -1,57 +1,93 @@
<section> <section>
<div class="bg-white dark:bg-neutral-800 shadow sm:rounded-xl sm:overflow-hidden"> <div id="comments" class="overflow-hidden rounded-2xl border border-neutral-200 bg-white shadow-sm dark:border-neutral-800 dark:bg-neutral-900">
<div class="px-4 py-5 sm:px-6">
<h2 class="leading-normal font-bold text-lg text-gray-900 dark:text-gray-200">Comments</h2> {{-- Header --}}
<div class="border-b border-neutral-200 px-6 py-5 dark:border-neutral-800">
<h2 class="text-xl font-semibold tracking-tight text-neutral-900 dark:text-neutral-100">
Comments
</h2>
</div> </div>
<div>
<!-- Comment Input --> {{-- Comment Form --}}
<div class="bg-gray-50 dark:bg-neutral-800 px-4 py-6 sm:px-6 border-t border-b dark:border-neutral-950 border-neutral-200"> <div class="border-b border-neutral-200 bg-neutral-50/80 px-6 py-6 dark:border-neutral-800 dark:bg-neutral-950/40">
@auth @auth
<div class="flex"> <div class="flex gap-4">
<div class="flex-shrink-0 mr-4"> <img
<img class="h-10 w-10 rounded-full" src="{{ auth()->user()->getAvatar() }}" alt="{{ auth()->user()->name }}"> class="h-11 w-11 rounded-full object-cover ring-2 ring-white dark:ring-neutral-800"
</div> src="{{ auth()->user()->getAvatar() }}"
<div class="min-w-0 flex-1"> alt="{{ auth()->user()->name }}"
<form wire:submit.prevent="postComment"> >
<div class="flex-1">
<form wire:submit.prevent="postComment" class="space-y-4">
<div> <div>
<label for="comment" class="sr-only">Comment body</label> <label for="comment" class="sr-only">
<textarea id="comment" name="comment" rows="3" Comment body
class="peer block min-h-[auto] w-full border-1 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear dark:placeholder:text-neutral-200 border-gray-300 dark:border-neutral-950 dark:bg-neutral-900 dark:text-gray-300 focus:border-rose-500 dark:focus:border-rose-600 focus:ring-rose-500 dark:focus:ring-rose-600 rounded-md shadow-sm </label>
@error('newCommentState.body') border-red-500 @enderror"
placeholder="Write something" wire:model.defer="newCommentState.body"></textarea> <textarea
id="comment"
rows="4"
wire:model.defer="newCommentState.body"
placeholder="Write a comment..."
class="w-full rounded-2xl border border-neutral-300 bg-white px-4 py-3 text-sm text-neutral-900 placeholder:text-neutral-400 shadow-sm transition focus:border-rose-500 focus:outline-none focus:ring-4 focus:ring-rose-500/10 dark:border-neutral-700 dark:bg-neutral-900 dark:text-neutral-100 dark:placeholder:text-neutral-500 dark:focus:border-rose-500 @error('newCommentState.body') border-red-500 @enderror"
></textarea>
@error('newCommentState.body') @error('newCommentState.body')
<p class="mt-2 text-sm text-red-500">{{ $message }}</p> <p class="mt-2 text-sm text-red-500">
{{ $message }}
</p>
@enderror @enderror
</div> </div>
<div class="mt-3 flex items-center justify-between">
<button type="submit" <div class="flex justify-end">
class="inline-flex items-center justify-center px-4 py-2 border border-transparent font-medium rounded-md shadow-sm text-white bg-rose-600 hover:bg-rose-700 focus:outline-none focus:ring-2 focus:ring-rose-500"> <button
Comment type="submit"
class="inline-flex items-center rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-medium text-white transition hover:bg-rose-700 focus:outline-none focus:ring-4 focus:ring-rose-500/30"
>
Post Comment
</button> </button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
@endauth @endauth
@guest @guest
<p class="text-gray-900 dark:text-gray-200">Log in to comment.</p> <div class="rounded-xl border border-dashed border-neutral-300 p-6 text-center dark:border-neutral-700">
@endguest <p class="text-sm text-neutral-600 dark:text-neutral-400">
</div> Log in to join the discussion.
</p>
<!-- Comments -->
<div class="px-4 py-6 sm:px-6">
<div class="space-y-8">
@if ($comments->isNotEmpty())
@foreach($comments as $comment)
<livewire:comment :comment="$comment" :key="$comment->id"/>
@endforeach
{{ $comments->links('pagination::tailwind') }}
@else
<p class="text-gray-900 dark:text-gray-200">No comments yet.</p>
@endif
</div> </div>
</div> @endguest
</div>
{{-- Comments --}}
<div class="px-6 py-6">
@if ($comments->isNotEmpty())
<div class="space-y-6">
@foreach($comments as $comment)
<livewire:comment :comment="$comment" :key="$comment->id"/>
@endforeach
</div>
<div class="mt-8">
{{ $comments->links('pagination::tailwind') }}
</div>
@else
<div class="rounded-2xl border border-dashed border-neutral-300 py-12 text-center dark:border-neutral-700">
<p class="text-neutral-500 dark:text-neutral-400">
No comments yet.
</p>
</div>
@endif
</div> </div>
</div> </div>
</section> </section>
@@ -1,13 +1,9 @@
<div> <div>
@if (Auth::check()) <button class="inline-flex font-bold items-center gap-2 rounded-xl bg-gray-100 px-4 py-2 text-gray-700 dark:bg-white/5 dark:text-gray-200" wire:click="like" wire:poll.90000ms="update">
<div class="text-xl text-gray-800 dark:text-gray-200 leading-tight cursor-pointer whitespace-nowrap" wire:click="like" wire:poll.90000ms="update">
@else
<div data-te-toggle="tooltip" title="Please login to like the episode" class="text-xl text-gray-800 dark:text-gray-200 leading-tight cursor-pointer whitespace-nowrap" wire:poll.60000ms="update">
@endif
@if ($liked) @if ($liked)
<i class="fa-solid fa-heart pr-[4px] text-rose-600"></i> {{ $likeCount }} <i class="fa-solid fa-heart pr-[4px] text-rose-600"></i> {{ $likeCount }}
@else @else
<i class="fa-regular fa-heart pr-[4px]"></i> {{ $likeCount }} <i class="fa-regular fa-heart pr-[4px]"></i> {{ $likeCount }}
@endif @endif
</div> </button>
</div> </div>
@@ -1,5 +0,0 @@
<div>
<a class="text-xl text-gray-800 dark:text-gray-200 leading-tight whitespace-nowrap" wire:poll.90000ms="update">
<i class="fa-regular fa-eye pr-0.5"></i> {{ $viewCount }}
</a>
</div>
+2 -2
View File
@@ -12,7 +12,7 @@
</p> </p>
</div> </div>
<div class="flex justify-center"> <div class="flex justify-center">
<div class="grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5"> <div class="grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-4">
@foreach ($episodes as $episode) @foreach ($episodes as $episode)
<div class="mt-2 mb-6 ml-4"> <div class="mt-2 mb-6 ml-4">
<x-episode-cover :episode="$episode->episode" view="thumbnail" /> <x-episode-cover :episode="$episode->episode" view="thumbnail" />
@@ -25,4 +25,4 @@
</ol> </ol>
{{ $watched->links('pagination::tailwind') }} {{ $watched->links('pagination::tailwind') }}
</div> </div>
</div </div>
+1 -2
View File
@@ -1,7 +1,6 @@
<x-app-layout> <x-app-layout>
@include('partials.background') @include('partials.background')
<div <div class="relative max-w-[120rem] mx-auto sm:px-6 lg:px-8 space-y-6 pt-10 flex flex-row justify-center md:justify-normal">
class="relative max-w-[120rem] mx-auto sm:px-6 lg:px-8 space-y-6 pt-20 mt-[65px] flex flex-row justify-center md:justify-normal">
<div class="grid md:grid-flow-col gap-4 xl:w-5/6 flex-row"> <div class="grid md:grid-flow-col gap-4 xl:w-5/6 flex-row">
@include('profile.partials.sidebar') @include('profile.partials.sidebar')
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
@@ -1,58 +1,66 @@
<div class="bg-transparent rounded-lg"> <div>
<div class="px-1 sm:px-2">
<p class="leading-normal font-bold text-lg text-gray-900 dark:text-gray-200"> <div class="mb-5 flex items-center justify-between">
<h2 class="text-xl font-bold text-gray-900 dark:text-white">
{{ __('stream.gallery') }} {{ __('stream.gallery') }}
</p> </h2>
@if ($gallery->count() > 5)
<button
id="galleryToggle"
class="text-sm font-semibold text-gray-900 dark:text-white transition">
{{ __('home.show-more') }}
</button>
@endif
</div> </div>
@if ($gallery->count() > 5)
<div class="grid grid-rows-1 w-30 text-left"> <div
<ul data-te-lightbox-init class="list-none text-center" style="overflow: hidden;"> data-te-lightbox-init
@php $counter = 0; @endphp class="grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
@foreach($gallery as $image)
@php $counter++; @endphp @foreach($gallery as $index => $image)
<li class="inline-block m-1 w-[45%] sm:w-[45%] md:w-[20%] xl:w-[18%]">
@if ($counter > 5) <div class="{{ $index >= 5 ? 'hidden extra-gallery-item' : '' }}">
<div class="!visible hidden" id="collapseGallery" data-te-collapse-item>
@else <div
<div> class="group overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-sm transition hover:-translate-y-1 hover:shadow-xl dark:border-neutral-700 dark:bg-neutral-800">
@endif
<div class="py-2 mt-2"> <img
<img onClick="(function(){player.play(); player.pause(); })();" src="{{ $image->thumbnail_url }}" data-te-img="{{ $image->image_url }}" alt="{{ $episode->title }} - {{ $episode->episode }} - Screenshot {{ $counter }}" class="relative block items-center h-full w-full rounded-lg tracking-widest transition ease-in-out duration-150 cursor-zoom-in shadow-sm data-[te-lightbox-disabled]:cursor-auto" /> onClick="(function(){player.play(); player.pause(); })();"
</div> src="{{ $image->thumbnail_url }}"
</div> data-te-img="{{ $image->image_url }}"
</li> alt="{{ $episode->title }} - Screenshot {{ $index + 1 }}"
@endforeach class="aspect-video w-full cursor-zoom-in object-cover transition duration-300 group-hover:scale-105"
</ul> >
</div>
<div class="grid grid-rows-1 w-30 text-center">
<a id="galleryShowMore" data-te-collapse-init data-te-ripple-init data-te-ripple-color="light" href="#collapseGallery" role="button" aria-expanded="false" aria-controls="collapseGallery" class="text-sm float-right cursor-pointer text-rose-600">{{ __('home.show-more') }}</a>
</div>
<script>
var state = 0;
function toggleGallery() {
if (state == 0) {
document.getElementById('galleryShowMore').innerText = "{{ __('stream.show-less') }}";
state = 1;
} else {
document.getElementById('galleryShowMore').innerText = "{{ __('home.show-more') }}";
state = 0;
}
}
document.getElementById('galleryShowMore').addEventListener('click', toggleGallery);
</script>
@else
<div class="grid grid-rows-1 w-30 text-left">
<ul data-te-lightbox-init class="list-none text-center" style="overflow: hidden;">
@php $counter = 0; @endphp
@foreach($gallery as $image)
@php $counter++; @endphp
<li class="inline-block m-1 w-[45%] sm:w-[45%] md:w-[20%] xl:w-[18%]">
<div class="py-2 mt-2">
<img onClick="(function(){player.play(); player.pause(); })();" src="{{ $image->thumbnail_url }}" data-te-img="{{ $image->image_url }}" alt="{{ $episode->title }} - {{ $episode->episode }} - Screenshot {{ $counter }}" class="relative block items-center h-full w-full rounded-lg tracking-widest transition ease-in-out duration-150 cursor-zoom-in shadow-sm data-[te-lightbox-disabled]:cursor-auto" />
</div> </div>
</li>
@endforeach </div>
</ul>
@endforeach
</div> </div>
@endif
</div> </div>
@if ($gallery->count() > 5)
<script>
const toggleBtn = document.getElementById('galleryToggle');
const hiddenItems = document.querySelectorAll('.extra-gallery-item');
let expanded = false;
toggleBtn.addEventListener('click', () => {
expanded = !expanded;
hiddenItems.forEach(item => {
item.classList.toggle('hidden');
});
toggleBtn.innerText = expanded
? "{{ __('stream.show-less') }}"
: "{{ __('home.show-more') }}";
});
</script>
@endif
+169 -138
View File
@@ -1,167 +1,198 @@
<div class="overflow-hidden p-5 bg-transparent bg-white rounded-xl dark:bg-neutral-800"> <div
<!-- Cover --> class="overflow-hidden rounded-2xl border border-gray-200/70 bg-white/90 shadow-sm backdrop-blur-sm transition-colors dark:border-white/10 dark:bg-neutral-900/80">
<div class="w-[100px] md:w-[150px] mr-4 float-left hidden md:block">
<img alt="{{ $episode->title }}" loading="lazy" width="150"
class="block relative rounded-xl object-cover object-center aspect-[11/16] z-20"
src="{{ $episode->cover_url }}"></img>
</div>
<!-- Info --> <div class="p-5 md:p-7">
<div class="relative">
<input id="e_id" type="hidden" value="{{ $episode->id }}" /> <input id="e_id" type="hidden" value="{{ $episode->id }}" />
<div class="flex flex-col justify-between xl:flex-row">
<div>
<!-- Title -->
<h1 class="text-3xl font-bold text-rose-600">
<a class="text-rose-600 break-words hover:underline hover:underline-offset-4"
href="{{ route('hentai.index', ['title' => $episode->hentai->slug]) }}">{{ $episode->title }}</a>
- {{ $episode->episode }}
</h1>
<div>
<h2 class="inline leading-tight text-gray-800 dark:text-white">{{ $episode->title_jpn }}</h2>
<a data-te-toggle="tooltip" <div class="flex flex-col gap-6 lg:flex-row">
title="Uploaded {{ $episode->created_at->diffForHumans(['parts' => 2]) }}" <!-- Cover -->
class="pl-1 leading-tight text-gray-800 text-l dark:text-white"> <div class="hidden shrink-0 md:block">
<p class="inline"> <img
| <i class="fa-solid fa-upload"></i> {{ $episode->created_at->format('Y-m-d') }} | alt="{{ $episode->title }}"
</p> loading="lazy"
</a> width="180"
<a data-te-toggle="tooltip" src="{{ $episode->cover_url }}"
title="Released {{ \Carbon\Carbon::parse($episode->release_date)->diffForHumans(['parts' => 2]) }}" class="aspect-[11/16] w-[140px] rounded-2xl object-cover shadow-lg ring-1 ring-black/5 dark:ring-white/10" />
class="pl-1 leading-tight text-gray-800 text-l dark:text-white">
<p class="inline">
<i class="fa-regular fa-calendar"></i> {{ $episode->release_date }}
|
</p>
</a>
<a href="{{ route('hentai.search', ['order' => 'recently-uploaded', 'studios[0]' => $episode->studio->slug]) }}"
class="leading-tight text-gray-800 text-l dark:text-white hover:underline hover:underline-offset-4">
{{ $episode->studio->name }}
</a>
<a id="av1-unsupported" data-te-toggle="tooltip"
title="For 1080p and 4k streams we are using the new AV1 codec. Edge users on Windows have to install the AV1 extension pack from the Microsoft Store."
class="hidden leading-tight text-red-800 cursor-pointer text-l dark:text-red-500">
AV1 Unsupported
</a>
</div>
</div> </div>
<div> <!-- Main Content -->
<!-- View Count and Misc Buttons --> <div class="flex-1">
<div class="float-right"> <div class="flex flex-col gap-5 xl:flex-row xl:items-start xl:justify-between">
<div class="grid">
<div class="flex gap-x-4"> <!-- Title + Metadata -->
<div class="min-w-0">
<h1
class="break-words text-2xl font-black tracking-tight text-gray-900 dark:text-white md:text-4xl">
<a
href="{{ route('hentai.index', ['title' => $episode->hentai->slug]) }}"
class="bg-gradient-to-r from-rose-500 to-pink-500 bg-clip-text text-transparent transition hover:opacity-80">
{{ $episode->title }} - {{ $episode->episode }}
</a>
</h1>
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400 md:text-base">
{{ $episode->title_jpn }}
</p>
<!-- Meta Pills -->
<div class="mt-4 flex flex-wrap items-center gap-2 text-sm">
<div
class="inline-flex items-center gap-2 rounded-full bg-gray-100 px-3 py-1 text-gray-700 dark:bg-white/5 dark:text-gray-300">
<i class="fa-solid fa-upload text-xs"></i>
{{ $episode->created_at->format('Y-m-d') }}
</div>
<div
class="inline-flex items-center gap-2 rounded-full bg-gray-100 px-3 py-1 text-gray-700 dark:bg-white/5 dark:text-gray-300">
<i class="fa-regular fa-calendar text-xs"></i>
{{ $episode->release_date }}
</div>
<a
href="{{ route('hentai.search', ['order' => 'recently-uploaded', 'studios[0]' => $episode->studio->slug]) }}"
class="inline-flex items-center rounded-full bg-rose-100 px-3 py-1 font-medium text-rose-700 transition hover:bg-rose-200 dark:bg-rose-500/10 dark:text-rose-300 dark:hover:bg-rose-500/20">
{{ $episode->studio->name }}
</a>
<a
id="av1-unsupported"
data-te-toggle="tooltip"
title="For 1080p and 4k streams we are using the new AV1 codec."
class="hidden rounded-full bg-red-100 px-3 py-1 text-sm font-medium text-red-700 dark:bg-red-500/10 dark:text-red-400">
AV1 Unsupported
</a>
</div>
</div>
<!-- Stats + Actions -->
<div class="flex flex-col gap-3 xl:items-end min-w-[330px]">
<!-- Stats -->
<div class="flex flex-wrap items-center gap-3">
<div
class="inline-flex font-bold items-center gap-2 rounded-xl bg-gray-100 px-4 py-2 text-gray-700 dark:bg-white/5 dark:text-gray-200">
<i class="fa-regular fa-eye"></i>
{{ $episode->viewCountFormatted() }}
</div>
@auth @auth
@livewire('view-count', ['episode' => $episode])
@livewire('like-button', ['episode' => $episode]) @livewire('like-button', ['episode' => $episode])
@endauth @endauth
@guest @guest
<div> <div
<a class="text-xl leading-tight text-gray-800 whitespace-nowrap dark:text-gray-200"> data-te-toggle="tooltip"
<i class="pr-0.5 fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} title="Please login to like the episode"
</a> class="inline-flex cursor-pointer items-center gap-2 rounded-xl bg-gray-100 px-4 py-2 text-gray-700 dark:bg-white/5 dark:text-gray-200">
</div> <i class="fa-regular fa-heart"></i>
<div data-te-toggle="tooltip" title="Please login to like the episode" {{ $episode->likeCount() }}
class="text-xl leading-tight text-gray-800 whitespace-nowrap cursor-pointer dark:text-gray-200">
<i class="fa-regular fa-heart pr-[4px]"></i> {{ $episode->likeCount() }}
</div> </div>
@endguest @endguest
@php $commentcount = $episode->commentCount(); @endphp @php $commentcount = $episode->commentCount(); @endphp
@if ($commentcount > 0)
<a href="#comments" <a
class="text-xl leading-tight text-gray-800 whitespace-nowrap dark:text-gray-200"> href="#comments"
<i class="pr-0.5 fa-regular fa-comment"></i> {{ $commentcount }} class="inline-flex items-center gap-2 rounded-xl bg-gray-100 px-4 py-2 text-gray-700 transition hover:bg-gray-200 dark:bg-white/5 dark:text-gray-200 dark:hover:bg-white/10">
</a> <i class="fa-regular fa-comment"></i>
@else {{ $commentcount }}
<a href="#comments" data-te-toggle="tooltip" title="Be the first one to comment!" </a>
class="text-xl leading-tight text-gray-800 whitespace-nowrap dark:text-gray-200">
<i class="pr-0.5 fa-regular fa-comment"></i> {{ $commentcount }}
</a>
@endif
</div> </div>
<div> <!-- Action Buttons -->
<div class="flex flex-wrap gap-2">
@if(!$episode->dmca_takedown) @if(!$episode->dmca_takedown)
<a data-te-toggle="modal" data-te-target="#modalDownload" id="reloadCaptchaModal" <a
class="text-xl leading-tight text-gray-800 whitespace-nowrap cursor-pointer dark:text-gray-200"> data-te-toggle="modal"
<i class="fa-solid fa-download pr-[4px]"></i> {{ __('stream.download') }} data-te-target="#modalDownload"
</a> id="reloadCaptchaModal"
class="inline-flex cursor-pointer items-center gap-2 rounded-xl bg-rose-600 px-4 py-2 text-sm font-semibold text-white transition hover:bg-rose-700">
<i class="fa-solid fa-download"></i>
{{ __('stream.download') }}
</a>
@endif @endif
<a data-te-toggle="modal" data-te-target="#modalShare" <a
class="text-xl leading-tight text-gray-800 whitespace-nowrap cursor-pointer dark:text-gray-200"> data-te-toggle="modal"
<i class="fa-solid fa-share pr-[4px]"></i> {{ __('stream.share') }} data-te-target="#modalShare"
class="inline-flex cursor-pointer items-center gap-2 rounded-xl border border-gray-300 bg-white px-4 py-2 text-sm font-semibold text-gray-700 transition hover:bg-gray-100 dark:border-white/10 dark:bg-white/5 dark:text-gray-200 dark:hover:bg-white/10">
<i class="fa-solid fa-share"></i>
{{ __('stream.share') }}
</a> </a>
</div>
@auth @auth
<div> <a
<a data-te-toggle="modal" data-te-target="#modalAddToPlaylist" data-te-toggle="modal"
class="text-xl leading-tight text-gray-800 whitespace-nowrap cursor-pointer dark:text-gray-200"> data-te-target="#modalAddToPlaylist"
<i class="fa-solid fa-square-plus pr-[6px]"></i> {{ __('playlist.playlist') }} class="inline-flex cursor-pointer items-center gap-2 rounded-xl border border-gray-300 bg-white px-4 py-2 text-sm font-semibold text-gray-700 transition hover:bg-gray-100 dark:border-white/10 dark:bg-white/5 dark:text-gray-200 dark:hover:bg-white/10">
<i class="fa-solid fa-square-plus"></i>
{{ __('playlist.playlist') }}
</a> </a>
</div> @endauth
@endauth </div>
</div> </div>
</div> </div>
<!-- Description -->
<div class="mt-8 border-t border-gray-200 pt-6 dark:border-white/10">
<h2 class="mb-3 text-lg font-bold text-gray-900 dark:text-white">
{{ __('stream.description') }}
</h2>
<p class="leading-relaxed text-gray-700 dark:text-gray-300">
{{ $episode->description }}
</p>
</div>
<!-- Genres -->
<div class="mt-8 border-t border-gray-200 pt-6 dark:border-white/10">
<h2 class="mb-4 text-lg font-bold text-gray-900 dark:text-white">
{{ __('stream.genres') }}
</h2>
<div class="flex flex-wrap gap-2">
@foreach ($episode->tags->sortBy('slug') as $tag)
@php
$classes = 'bg-gray-100 text-gray-700 hover:bg-rose-600 hover:text-white dark:bg-white/5 dark:text-gray-300 dark:hover:bg-rose-600';
if (in_array($tag->slug, ['uncensored', 'vanilla', '4k'])) {
$classes = 'bg-green-100 text-green-700 hover:bg-green-600 hover:text-white dark:hover:text-white dark:bg-green-500/10 dark:text-green-400 dark:hover:bg-green-600';
}
if ($tag->slug === 'censored') {
$classes = 'bg-yellow-100 text-yellow-700 hover:bg-yellow-500 hover:text-white dark:hover:text-white dark:bg-yellow-500/10 dark:text-yellow-400 dark:hover:bg-yellow-500';
}
if (in_array($tag->slug, ['gore', 'horror', 'scat', 'ntr', 'rape'])) {
$classes = 'bg-red-100 text-red-700 hover:bg-red-600 hover:text-white dark:hover:text-white dark:bg-red-500/10 dark:text-red-400 dark:hover:bg-red-600';
}
@endphp
<a
href="{{ route('hentai.search', ['order' => 'recently-uploaded', 'tags[0]' => $tag->slug]) }}"
class="inline-flex items-center gap-2 rounded-full px-4 py-2 text-xs font-bold uppercase tracking-wide transition {{ $classes }}">
@if(in_array($tag->slug, ['gore', 'horror', 'scat', 'ntr', 'rape']))
<i class="fa-solid fa-triangle-exclamation text-[10px]"></i>
@endif
{{ $tag->name }}
</a>
@endforeach
</div>
</div>
<!-- Gallery -->
<div class="mt-8 border-t border-gray-200 pt-6 dark:border-white/10">
@include('stream.partials.gallery')
</div>
</div> </div>
</div> </div>
<hr class="mt-2 mb-2 border-gray-400/40">
<p class="text-lg font-bold leading-normal text-rose-600">
{{ __('stream.description') }}
</p>
<p class="text-gray-800 dark:text-gray-200 leading-tight min-h-[50%]">
{{ $episode->description }}
</p>
<hr class="mt-2 mb-1 border-gray-400/40">
<p class="text-lg font-bold leading-normal text-rose-600">
{{ __('stream.genres') }}
</p>
<ul class="list-none text-center" style="overflow: hidden;">
<a class="text-gray-400">
|
</a>
@foreach ($episode->tags->sortBy('slug') as $tag)
<li class="inline-block p-1">
@if ($tag->slug == 'uncensored' || $tag->slug == 'vanilla' || $tag->slug == '4k')
<a href="{{ route('hentai.search', ['order' => 'recently-uploaded', 'tags[0]' => $tag->slug]) }}"
class="block relative items-center px-2 py-2 mt-1 text-xs font-semibold tracking-widest text-green-500 uppercase rounded-md border border-transparent transition duration-150 ease-in-out dark:focus:ring-offset-gray-800 dark:hover:text-white hover:text-white hover:bg-green-700 focus:bg-green-700 active:bg-green-900 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2">
{{ $tag->name }}
</a>
@elseif($tag->slug == 'censored')
<a href="{{ route('hentai.search', ['order' => 'recently-uploaded', 'tags[0]' => $tag->slug]) }}"
class="block relative items-center px-2 py-2 mt-1 text-xs font-semibold tracking-widest text-yellow-600 uppercase rounded-md border border-transparent transition duration-150 ease-in-out dark:focus:ring-offset-gray-800 dark:hover:text-white hover:text-white hover:bg-yellow-700 focus:bg-yellow-700 active:bg-yellow-900 focus:outline-none focus:ring-2 focus:ring-yellow-500 focus:ring-offset-2">
{{ $tag->name }}
</a>
@elseif(
$tag->slug == 'gore' ||
$tag->slug == 'horror' ||
$tag->slug == 'scat' ||
$tag->slug == 'ntr' ||
$tag->slug == 'rape')
<a href="{{ route('hentai.search', ['order' => 'recently-uploaded', 'tags[0]' => $tag->slug]) }}"
class="block relative items-center px-2 py-2 mt-1 text-xs font-semibold tracking-widest text-red-600 uppercase rounded-md border border-transparent transition duration-150 ease-in-out dark:focus:ring-offset-gray-800 dark:hover:text-white hover:text-white hover:bg-red-700 focus:bg-red-700 active:bg-red-900 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2">
<i class="fa-solid fa-triangle-exclamation"></i> {{ $tag->name }}
</a>
@else
<a href="{{ route('hentai.search', ['order' => 'recently-uploaded', 'tags[0]' => $tag->slug]) }}"
class="block relative items-center px-2 py-2 mt-1 text-xs font-semibold tracking-widest uppercase rounded-md border border-transparent transition duration-150 ease-in-out dark:focus:ring-offset-gray-800 dark:text-white hover:text-white hover:bg-rose-700 focus:bg-rose-700 active:bg-rose-900 focus:outline-none focus:ring-2 focus:ring-rose-500 focus:ring-offset-2">
{{ $tag->name }}
</a>
@endif
</li>
<a class="text-gray-400">
|
</a>
@endforeach
</ul>
<hr class="mt-2 mb-1 border-gray-400/40">
<div class="inline-block pt-5">
@include('stream.partials.gallery')
</div>
</div> </div>
</div> </div>
+19
View File
@@ -18,6 +18,25 @@ export default {
sans: ['Figtree', ...defaultTheme.fontFamily.sans], sans: ['Figtree', ...defaultTheme.fontFamily.sans],
}, },
}, },
screens: {
'sm': '640px',
// => @media (min-width: 640px) { ... }
'md': '768px',
// => @media (min-width: 768px) { ... }
'lg': '1024px',
// => @media (min-width: 1024px) { ... }
'xl': '1280px',
// => @media (min-width: 1280px) { ... }
'2xl': '1536px',
// => @media (min-width: 1536px) { ... }
'3xl': '1900px',
}
}, },
plugins: [forms, require("tw-elements/dist/plugin")], plugins: [forms, require("tw-elements/dist/plugin")],