This commit is contained in:
2025-09-18 15:31:27 +02:00
commit 2abba0c2b7
406 changed files with 31879 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
<div class="bg-transparent rounded-lg overflow-hidden bg-white dark:bg-neutral-700/40 p-5">
<div id="comments" class="grid grid-cols-1 bg-transparent rounded-lg">
<p class="leading-normal font-bold text-lg text-rose-600">
{{ __('home.latest-comments') }}
</p>
@comments(['model' => $episode])
</div>
</div>

View File

@@ -0,0 +1,38 @@
<li>
<a class="flex flex-col w-auto text-black dark:text-white hover:text-white hover:bg-rose-900/80 rounded-lg cursor-pointer pt-1"
href="{{ route('hentai.index', ['title' => $episode->slug]) }}">
<div class="flex items-center">
<div class="relative w-full aspect-[16/9]">
@auth
@if ($episode->userWatched(auth()->user()->id))
<p
class="absolute right-1 top-1 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
{{ $episode->getResolution() }}</p>
<p
class="absolute left-1 bottom-1 bg-green-600/80 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i
class="fa-regular fa-comment"></i> {{ $episode->commentCount() }}
</p>
@else
<p
class="absolute right-1 top-1 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
{{ $episode->getResolution() }}</p>
<p
class="absolute left-1 bottom-1 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
<i class="fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }} <i
class="fa-regular fa-heart"></i> {{ $episode->likeCount() }} <i
class="fa-regular fa-comment"></i> {{ $episode->commentCount() }}
</p>
@endif
@endauth
<img loading="lazy" class="block relative rounded-xl object-cover object-center z-20 p-1"
src="{{ optional($episode->gallery->first())->thumbnail_url }}"
alt="{{ $episode->title }} - {{ $episode->episode }}">
</div>
</div>
<div class="basis-3/4 pl-2 text-center">
<p class="text-sm font-bold">{{ $episode->title }} - {{ $episode->episode }}</p>
</div>
</a>
</li>

View File

@@ -0,0 +1,56 @@
<div class="bg-transparent rounded-lg">
<p class="leading-normal font-bold text-lg text-rose-600">
{{ __('stream.gallery') }}
</p>
@if ($gallery->count() > 5)
<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%]">
@if ($counter > 5)
<div class="!visible hidden" id="collapseGallery" data-te-collapse-item>
@else
<div>
@endif
<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
</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>
</li>
@endforeach
</ul>
</div>
@endif
</div>

View File

@@ -0,0 +1,165 @@
<div class="overflow-hidden p-5 bg-transparent bg-white rounded-lg dark:bg-neutral-800">
<!-- Cover -->
<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-lg object-cover object-center aspect-[11/16] z-20"
src="{{ $episode->cover_url }}"></img>
</div>
<!-- Info -->
<div class="relative">
<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"
title="Uploaded {{ $episode->created_at->diffForHumans(['parts' => 2]) }}"
class="pl-1 leading-tight text-gray-800 text-l dark:text-white">
<p class="inline">
| <i class="fa-solid fa-upload"></i> {{ $episode->created_at->format('Y-m-d') }} |
</p>
</a>
<a data-te-toggle="tooltip"
title="Released {{ \Carbon\Carbon::parse($episode->release_date)->diffForHumans(['parts' => 2]) }}"
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>
<!-- View Count and Misc Buttons -->
<div class="float-right">
<div class="grid">
<div class="flex gap-x-4">
@auth
@livewire('view-count', ['episode' => $episode])
@livewire('like-button', ['episode' => $episode])
@endauth
@guest
<div>
<a class="text-xl leading-tight text-gray-800 whitespace-nowrap dark:text-gray-200">
<i class="pr-0.5 fa-regular fa-eye"></i> {{ $episode->viewCountFormatted() }}
</a>
</div>
<div data-te-toggle="tooltip" title="Please login to like the episode"
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>
@endguest
@php $commentcount = $episode->commentCount(); @endphp
@if ($commentcount > 0)
<a href="#comments"
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>
@else
<a href="#comments" data-te-toggle="tooltip" title="Be the first one to comment!"
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>
<a data-te-toggle="modal" data-te-target="#modalDownload" id="reloadCaptchaModal"
class="text-xl leading-tight text-gray-800 whitespace-nowrap cursor-pointer dark:text-gray-200">
<i class="fa-solid fa-download pr-[4px]"></i> {{ __('stream.download') }}
</a>
<a data-te-toggle="modal" data-te-target="#modalShare"
class="text-xl leading-tight text-gray-800 whitespace-nowrap cursor-pointer dark:text-gray-200">
<i class="fa-solid fa-share pr-[4px]"></i> {{ __('stream.share') }}
</a>
</div>
@auth
<div>
<a data-te-toggle="modal" data-te-target="#modalAddToPlaylist"
class="text-xl leading-tight text-gray-800 whitespace-nowrap cursor-pointer dark:text-gray-200">
<i class="fa-solid fa-square-plus pr-[6px]"></i> {{ __('playlist.playlist') }}
</a>
</div>
@endauth
</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>

View File

@@ -0,0 +1,16 @@
@if (count($moreEpisodes) > 0)
<div class="pt-2 sm:px-2 lg:px-4 2xl:w-[450px]">
<div class="bg-transparent overflow-hidden p-4">
<p class="leading-normal font-bold text-xl dark:text-white pb-2">
{{ __('stream.more-from') }} <a class="text-rose-600 hover:underline hover:underline-offset-4 break-words" href="{{ route('hentai.index', ['title' => $episode->hentai->slug]) }}">{{ $episode->title }}</a>
</p>
<div class="text-center xl:text-left">
<ul class="inline-block xl:block">
@foreach ($moreEpisodes as $episode)
@include('stream.partials.episode-partial')
@endforeach
</ul>
</div>
</div>
</div>
@endif

View File

@@ -0,0 +1,16 @@
@if (count($studioEpisodes) > 0)
<div class="pt-2 sm:px-2 lg:px-4 2xl:w-[450px]">
<div class="bg-transparent rounded-lg overflow-hidden p-4">
<p class="leading-normal font-bold text-xl dark:text-white pb-2">
{{ __('stream.more-from-studio') }} <a class="text-rose-600 hover:underline hover:underline-offset-4 break-words" href="{{ route('hentai.search', ['studios[0]' => $episode->studio->slug]) }}">{{ $episode->studio->name }}</a>
</p>
<div class="text-center xl:text-left">
<ul class="inline-block xl:block">
@foreach ($studioEpisodes as $episode)
@include('stream.partials.episode-partial')
@endforeach
</ul>
</div>
</div>
</div>
@endif

View File

@@ -0,0 +1,8 @@
<div class="block">
<div id="player-alert" class="hidden mb-4 rounded-lg bg-danger-100 px-6 py-5 text-base text-danger-700" role="alert">
</div>
<canvas id="ambientVideo" class="decoy"></canvas>
<div class="relative w-full aspect-[16/9]">
<video id="player" playsinline controls crossorigin class="absolute inset-0 w-full h-full"></video>
</div>
</div>

View File

@@ -0,0 +1,94 @@
@isset($playlist)
<div class="pt-2 sm:px-2 lg:px-4 2xl:w-[450px]">
<div class="bg-transparent rounded-lg overflow-hidden bg-white dark:bg-neutral-800">
<div class="p-4">
<p class="leading-normal font-bold text-lg text-rose-600 pb-2">
@if ($playlist->is_private)
<a href="{{ route('profile.playlist.show', $playlist->id) }}">{{ $playlist->name }}</a>
@else
<a href="{{ route('playlist.show', $playlist->id) }}">{{ $playlist->name }}</a>
@endif
</p>
@php
$episodeCount = $playlistEpisodes->count();
$currentIndex = 0;
$nextEpisode = "";
if ($episodeCount > 1) {
$currentIndex = $playlistEpisodes->search(fn($playlistEpisode) => $playlistEpisode->episode->id == $episode->id);
$nextEpisode = $currentIndex !== false && $currentIndex + 1 < $episodeCount
? $playlistEpisodes[$currentIndex + 1]->episode->slug
: "";
}
@endphp
<p class="text-neutral-800 dark:text-neutral-300">
{{ $playlist->user->global_name ?? $playlist->user->username }} {{ $currentIndex + 1 }}/{{ $episodeCount }} Episodes
</p>
</div>
<!-- Table -->
<div id="scrollable" class="flex-none min-w-full px-4 sm:px-6 md:px-0 overflow-auto scrollbar:!w-1.5 scrollbar:!h-1.5 scrollbar:bg-transparent scrollbar-track:!bg-slate-100 scrollbar-thumb:!rounded scrollbar-thumb:!bg-slate-300 scrollbar-track:!rounded dark:scrollbar-track:!bg-slate-500/[0.16] dark:scrollbar-thumb:!bg-slate-500/50 max-h-96 lg:supports-scrollbars:pr-2 lg:max-h-96">
<div class="overflow-y-auto">
<div class="space-y-2 p-0 pb-2 sm:p-2">
@php
$counter = 1;
$isAuthedUsersPlaylist = false;
if (auth()->check() && $playlist->user->id == auth()->user()->id) {
$isAuthedUsersPlaylist = true;
}
@endphp
@foreach($playlistEpisodes as $playlistEpisode)
@if ($playlistEpisode->episode->id == $episode->id)
<div class="flex items-center gap-4 p-2 bg-rose-800/30 rounded-lg shadow swipe-container transition-colors" id="active">
@else
<div
class="flex items-center gap-4 p-2 dark:bg-neutral-900/50 bg-white rounded-lg shadow transition-colors @if($isMobile && $isAuthedUsersPlaylist) swipe-container @endif"
id="{{ $playlist->id }}-{{ $playlistEpisode->episode->id }}">
@endif
<div class="text-black dark:text-white">
@if ($playlistEpisode->episode->id == $episode->id)
<i class="fa-solid fa-play w-[15px]"></i>
@else
<p class="w-[15px]">{{ $counter }}</p>
@endif
</div>
<a href="{{ route('hentai.index', ['title' => $playlistEpisode->episode->slug, 'playlist' => $playlist->id ]) }}" class="contents">
<img loading="lazy" src="{{ $playlistEpisode->episode->gallery->first()->thumbnail_url }}" alt="{{ $playlistEpisode->episode->title }} - {{ $playlistEpisode->episode->episode }}" class="w-20 h-14 object-cover rounded">
</a>
<div class="grow">
<a href="{{ route('hentai.index', ['title' => $playlistEpisode->episode->slug, 'playlist' => $playlist->id ]) }}">
<p class="text-black dark:text-white font-medium text-sm break-words">{{ $playlistEpisode->episode->title }} - {{ $playlistEpisode->episode->episode }}</p>
</a>
<p class="text-gray-700 dark:text-gray-300 text-xs truncate">{{ $playlistEpisode->episode->viewCount() }} Views - {{ $playlistEpisode->episode->studio->name }}</p>
</div>
@if ($playlistEpisode->episode->id != $episode->id && $isAuthedUsersPlaylist)
@if($isMobile)
<div class="justify-self-end flex items-center">
<i class="transition-all fa-solid fa-grip-lines-vertical cursor-grab text-black dark:text-white" id="del-{{ $playlist->id }}-{{ $playlistEpisode->episode->id }}"></i>
</div>
@else
<div class="justify-self-end flex items-center">
<a class="transition-all fa-solid fa-trash cursor-pointer text-red-700/80" id="delD-{{ $playlist->id }}-{{ $playlistEpisode->episode->id }}"></a>
</div>
@endif
@endif
</div>
@php $counter++; @endphp
@endforeach
</div>
</div>
</div>
</div>
</div>
<input id="playlist_id" type="hidden" value="{{ $playlist->id }}">
<input id="playlist_next_episode_slug" type="hidden" value="{{ $nextEpisode }}">
<script>
// Select the scrollable div and the target child element
const scrollableDiv = document.getElementById('scrollable');
const targetElement = document.getElementById('active');
// Scroll to the target element
scrollableDiv.scrollTop = targetElement.offsetTop - scrollableDiv.offsetTop - 50;
</script>
@endisset