Compare commits
42 Commits
de6efb877c
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f8022b3f18 | |||
| 57d1ec34c3 | |||
| 81639aaabf | |||
| 5dc1bff60c | |||
| 2f3f0edc30 | |||
| a71b2976af | |||
| 2c016274ab | |||
| 5ba0a55316 | |||
| a6fe34a0d1 | |||
| bb53e06c69 | |||
| 5cae5dc658 | |||
| 356d07365f | |||
| 3574d20fae | |||
| 9fc9e8ed10 | |||
| f5c706b587 | |||
| cbea71d9ae | |||
| 64a621173c | |||
| 839779b82e | |||
| 112cf9433e | |||
| 26a6500fca | |||
| d8cf70e747 | |||
| 0d4545c2ab | |||
| 900103e1c2 | |||
| d4c90976f8 | |||
| 72263127df | |||
| 6d3de59929 | |||
| ddb1bc2d14 | |||
| 5f3874a233 | |||
| ba3650899e | |||
| 904604fcfb | |||
| b7b34b503c | |||
| 4928733383 | |||
| 6340302ac6 | |||
| c1829ba7bd | |||
| 0b155bbb80 | |||
| 9f959efa14 | |||
| 38e3346dc3 | |||
| 09c08f3fea | |||
| 75f631c3e6 | |||
| fdf26604f3 | |||
| 59cb39ca77 | |||
| 62647be75c |
@@ -16,7 +16,7 @@ class GenerateSitemap extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'sitemap:generate';
|
||||
protected $signature = 'app:generate-sitemap';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
|
||||
@@ -8,6 +8,7 @@ use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SyncSubscriptionKeys extends Command
|
||||
{
|
||||
@@ -83,8 +84,11 @@ class SyncSubscriptionKeys extends Command
|
||||
->whereNotIn('subscription_key', $activeKeys)
|
||||
->chunk(100, function ($users) {
|
||||
foreach($users as $user) {
|
||||
if ($user->hasRole(UserRole::SUPPORTER)) {
|
||||
Log::info("Removed Supporter Role from {$user->name}");
|
||||
$user->removeRole(UserRole::SUPPORTER);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -95,8 +99,11 @@ class SyncSubscriptionKeys extends Command
|
||||
->whereIn('subscription_key', $activeKeys)
|
||||
->chunk(100, function ($users) {
|
||||
foreach($users as $user) {
|
||||
if (!$user->hasRole(UserRole::SUPPORTER)) {
|
||||
Log::info("Added Supporter Role for {$user->name}");
|
||||
$user->addRole(UserRole::SUPPORTER);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ class CacheHelper
|
||||
public static function getLatestComments()
|
||||
{
|
||||
return Cache::remember('latest_comments', now()->addMinutes(60), function () {
|
||||
return Comment::latest()->take(10)->get();
|
||||
return Comment::with('user')->latest()->take(10)->get();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Conner\Tagging\Model\Tag;
|
||||
|
||||
class FilterCategories
|
||||
{
|
||||
public static function getFilterCategories()
|
||||
{
|
||||
$taglist = Cache::remember(
|
||||
'searchtags',
|
||||
300,
|
||||
fn () => Tag::where('count', '>', 0)
|
||||
->orderBy('slug')
|
||||
->get(),
|
||||
);
|
||||
|
||||
$appearances = [
|
||||
'Loli',
|
||||
'Shota',
|
||||
'Milf',
|
||||
'Futanari',
|
||||
'Big Boobs',
|
||||
'Small Boobs',
|
||||
'Dark Skin',
|
||||
'Cosplay',
|
||||
'Elf',
|
||||
'Maid',
|
||||
'Nekomimi',
|
||||
'Nurse',
|
||||
'School Girl',
|
||||
'Succubus',
|
||||
'Teacher',
|
||||
'Trap',
|
||||
'Pregnant',
|
||||
'Glasses',
|
||||
'Swim Suit',
|
||||
'Ugly Bastard',
|
||||
'Monster',
|
||||
];
|
||||
|
||||
$types = [
|
||||
'3D',
|
||||
'4K',
|
||||
'48Fps',
|
||||
'4K 48Fps',
|
||||
'Censored',
|
||||
'Uncensored',
|
||||
'Comedy',
|
||||
'Fantasy',
|
||||
'Horror',
|
||||
'Vanilla',
|
||||
'Ntr',
|
||||
'Pov',
|
||||
'Filmed',
|
||||
'X-Ray',
|
||||
];
|
||||
|
||||
$actions = [
|
||||
'Anal',
|
||||
'Bdsm',
|
||||
'Facial',
|
||||
'Blow Job',
|
||||
'Boob Job',
|
||||
'Foot Job',
|
||||
'Hand Job',
|
||||
'Rimjob',
|
||||
'Inflation',
|
||||
'Masturbation',
|
||||
'Public Sex',
|
||||
'Rape',
|
||||
'Reverse Rape',
|
||||
'Threesome',
|
||||
'Orgy',
|
||||
'Gangbang',
|
||||
];
|
||||
|
||||
$excluded = [...$appearances, ...$types, ...$actions];
|
||||
|
||||
$categories = [
|
||||
'Genres' => $taglist
|
||||
->reject(fn ($tag) => in_array($tag->name, $excluded))
|
||||
->pluck('name')
|
||||
->toArray(),
|
||||
|
||||
'Actions' => $actions,
|
||||
|
||||
'Appearance' => collect($appearances)
|
||||
->reject(function ($tag) {
|
||||
return Auth::guest() && in_array($tag, ['Loli', 'Shota']);
|
||||
})
|
||||
->toArray(),
|
||||
|
||||
'Types' => $types,
|
||||
];
|
||||
|
||||
return $categories;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Enums\UserRole;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Jobs\DiscordReleaseNotification;
|
||||
use App\Models\Episode;
|
||||
@@ -63,6 +64,17 @@ class EpisodeController extends Controller
|
||||
public function update(Request $request): RedirectResponse
|
||||
{
|
||||
$episode = Episode::with('hentai')->where('id', $request->input('episode_id'))->firstOrFail();
|
||||
|
||||
if ($request->user()->hasRole(UserRole::MODERATOR)) {
|
||||
$this->episodeService->updateEpisodeModerator($request, $episode->id);
|
||||
|
||||
cache()->flush();
|
||||
|
||||
return to_route('hentai.index', [
|
||||
'title' => $episode->slug,
|
||||
]);
|
||||
}
|
||||
|
||||
$studio = $this->episodeService->getOrCreateStudio(json_decode($request->input('studio'))[0]->value);
|
||||
|
||||
$oldinterpolated = $episode->interpolated;
|
||||
|
||||
@@ -17,11 +17,13 @@ class IsModerator
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if (Auth::check() && Auth::user()->hasRole(UserRole::MODERATOR)) {
|
||||
if (Auth::check() && (
|
||||
Auth::user()->hasRole(UserRole::MODERATOR) ||
|
||||
Auth::user()->hasRole(UserRole::ADMINISTRATOR))) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
session()->flash('error_msg', 'This resource is restricted to Administrators!');
|
||||
session()->flash('error_msg', 'This resource is restricted to Moderators!');
|
||||
|
||||
return redirect()->route('home.index');
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@ class SetLocale
|
||||
}
|
||||
|
||||
// 2. Session (guest or user override)
|
||||
if (session()->has('locale') && in_array($request->language, config('app.supported_locales'), true)) {
|
||||
if ($request->session()->has('locale') &&
|
||||
in_array(session('locale'), config('app.supported_locales'), true)) {
|
||||
|
||||
App::setLocale(session('locale'));
|
||||
|
||||
return $next($request);
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Enums\UserRole;
|
||||
use App\Models\Episode;
|
||||
use App\Models\ModLog;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CommentNotification;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
@@ -43,7 +45,7 @@ class Comment extends Component
|
||||
'replyState.body' => 'reply',
|
||||
];
|
||||
|
||||
public function updatedIsEditing($isEditing)
|
||||
public function updatedIsEditing(bool $isEditing)
|
||||
{
|
||||
if (! $isEditing) {
|
||||
return;
|
||||
@@ -67,11 +69,45 @@ class Comment extends Component
|
||||
{
|
||||
$this->authorize('destroy', $this->comment);
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
if ($user->hasRole(UserRole::ADMINISTRATOR) || $user->hasRole(UserRole::MODERATOR)) {
|
||||
// Log to ModLog
|
||||
ModLog::create([
|
||||
'moderator' => $user->name,
|
||||
'data' => "Deleted comment {$this->comment->id} written by {$this->comment->user->id} with contents: {$this->comment->body}",
|
||||
]);
|
||||
|
||||
$this->comment->deleted_by_moderator_id = $user->id;
|
||||
$this->comment->save();
|
||||
$this->dispatch('refresh');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->comment->delete();
|
||||
|
||||
$this->dispatch('refresh');
|
||||
}
|
||||
|
||||
public function restoreComment()
|
||||
{
|
||||
$this->authorize('restore', $this->comment);
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
if ($user->hasRole(UserRole::ADMINISTRATOR) || $user->hasRole(UserRole::MODERATOR)) {
|
||||
// Log to ModLog
|
||||
ModLog::create([
|
||||
'moderator' => $user->name,
|
||||
'data' => "Restored comment {$this->comment->id} written by {$this->comment->user->id} with contents: {$this->comment->body}",
|
||||
]);
|
||||
|
||||
$this->comment->deleted_by_moderator_id = null;
|
||||
$this->comment->save();
|
||||
$this->dispatch('refresh');
|
||||
}
|
||||
}
|
||||
|
||||
public function postReply()
|
||||
{
|
||||
if (! ($this->comment->depth() < 2)) {
|
||||
|
||||
@@ -23,11 +23,21 @@ class DownloadButton extends Component
|
||||
|
||||
public $fileExtension = 'HEVC';
|
||||
|
||||
public $version = '';
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (str_contains($this->downloadUrl, 'AV1')) {
|
||||
$this->fileExtension = 'AV1';
|
||||
}
|
||||
|
||||
if (str_contains($this->downloadUrl, 'v2')) {
|
||||
$this->version = 'v2';
|
||||
}
|
||||
|
||||
if (str_contains($this->downloadUrl, 'v3')) {
|
||||
$this->version = 'v3';
|
||||
}
|
||||
}
|
||||
|
||||
public function clicked($downloadId)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Enums\UserRole;
|
||||
use App\Models\User;
|
||||
use App\Services\SubscriptionService;
|
||||
use Livewire\Component;
|
||||
@@ -14,6 +15,8 @@ class UserSubscription extends Component
|
||||
|
||||
public $subscriptionKey = '';
|
||||
|
||||
public $isActive = false;
|
||||
|
||||
protected $rules = [
|
||||
'subscriptionKey' => 'required|string|size:48',
|
||||
];
|
||||
@@ -22,6 +25,7 @@ class UserSubscription extends Component
|
||||
{
|
||||
$this->userId = $user ? $user->id : auth()->user()->id;
|
||||
$this->subscriptionKey = $user->subscription_key ?? '';
|
||||
$this->isActive = $user->hasRole(UserRole::SUPPORTER) ?? false;
|
||||
}
|
||||
|
||||
public function applyKey(SubscriptionService $subscriptionService)
|
||||
@@ -61,6 +65,7 @@ class UserSubscription extends Component
|
||||
|
||||
$user->subscription_key = $this->subscriptionKey;
|
||||
$user->save();
|
||||
$this->isActive = true;
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -72,4 +72,12 @@ class Comment extends Model
|
||||
{
|
||||
return cache()->remember('commentLikes'.$this->id, 300, fn () => $this->likes->count());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns wether or not comment has been removed by moderation
|
||||
*/
|
||||
public function isDeletedByModerator(): bool
|
||||
{
|
||||
return $this->deleted_by_moderator_id !== null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ModLog extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = [
|
||||
'moderator',
|
||||
'data',
|
||||
];
|
||||
}
|
||||
+5
-1
@@ -157,7 +157,11 @@ class User extends Authenticatable implements HasPasskeys
|
||||
return;
|
||||
}
|
||||
|
||||
$this->roles = array_diff($this->roles, [$role->value]);
|
||||
$this->roles = collect($this->roles)
|
||||
->reject(fn ($value) => $value === $role->value)
|
||||
->values()
|
||||
->all();
|
||||
|
||||
$this->save();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Enums\UserRole;
|
||||
use App\Models\Comment;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
@@ -17,6 +18,26 @@ class CommentPolicy
|
||||
|
||||
public function destroy(User $user, Comment $comment): bool
|
||||
{
|
||||
if ($user->hasRole(UserRole::ADMINISTRATOR) ||
|
||||
$user->hasRole(UserRole::MODERATOR)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $user->id === $comment->user_id;
|
||||
}
|
||||
|
||||
public function restore(User $user, Comment $comment): bool
|
||||
{
|
||||
// Comment not deleted
|
||||
if ($comment->deleted_by_moderator_id === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($user->hasRole(UserRole::ADMINISTRATOR) ||
|
||||
$user->hasRole(UserRole::MODERATOR)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Services;
|
||||
use App\Models\Episode;
|
||||
use App\Models\Hentai;
|
||||
use App\Models\Studios;
|
||||
use App\Models\ModLog;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@@ -62,6 +63,68 @@ class EpisodeService
|
||||
return $episode;
|
||||
}
|
||||
|
||||
private function applyTags(Request $request, Episode $episode): void
|
||||
{
|
||||
$tags = json_decode($request->input('tags'));
|
||||
$newtags = [];
|
||||
foreach ($tags as $t) {
|
||||
$newtags[] = $t->value;
|
||||
}
|
||||
|
||||
$newTagsTemp = $newtags;
|
||||
$oldTagsTemp = $episode->tagNames();
|
||||
|
||||
sort($newTagsTemp);
|
||||
sort($oldTagsTemp);
|
||||
|
||||
if ($newTagsTemp !== $oldTagsTemp) {
|
||||
ModLog::create([
|
||||
'moderator' => $request->user()->name,
|
||||
'data' => sprintf(
|
||||
'Updated Episode tags from %s to %s',
|
||||
implode(', ', $oldTagsTemp),
|
||||
implode(', ', $newTagsTemp),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
$episode->retag($newtags);
|
||||
}
|
||||
|
||||
private function updateTitle(Request $request, Episode $episode): void
|
||||
{
|
||||
$updates = [];
|
||||
|
||||
if ($episode->title !== $request->input('title')) {
|
||||
$updates['title'] = $request->input('title');
|
||||
$updates['title_search'] = preg_replace(
|
||||
'/[^A-Za-z0-9 ]/',
|
||||
'',
|
||||
$request->input('title')
|
||||
);
|
||||
|
||||
// Log to ModLog
|
||||
ModLog::create([
|
||||
'moderator' => $request->user()->name,
|
||||
'data' => "Updating Hentai Title from {$episode->title} to {$request->input('title')}",
|
||||
]);
|
||||
}
|
||||
|
||||
if ($episode->title_jpn !== $request->input('title_jpn')) {
|
||||
$updates['title_jpn'] = $request->input('title_jpn');
|
||||
|
||||
// Log to ModLog
|
||||
ModLog::create([
|
||||
'moderator' => $request->user()->name,
|
||||
'data' => "Updating Hentai Title from {$episode->title_jpn} to {$request->input('title_jpn')}",
|
||||
]);
|
||||
}
|
||||
|
||||
if (! empty($updates)) {
|
||||
$episode->hentai->episodes()->update($updates);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateEpisode(Request $request, Studios $studio, int $episodeId): Episode
|
||||
{
|
||||
$episode = Episode::where('id', $episodeId)->firstOrFail();
|
||||
@@ -75,17 +138,31 @@ class EpisodeService
|
||||
$episode->dmca_takedown = $request->input('dmca_takedown') == 'true';
|
||||
$episode->save();
|
||||
|
||||
// Tagging
|
||||
$tags = json_decode($request->input('tags'));
|
||||
$newtags = [];
|
||||
foreach ($tags as $t) {
|
||||
$newtags[] = $t->value;
|
||||
}
|
||||
$episode->retag($newtags);
|
||||
$this->applyTags($request, $episode);
|
||||
$this->updateTitle($request, $episode);
|
||||
|
||||
return $episode;
|
||||
}
|
||||
|
||||
public function updateEpisodeModerator(Request $request, int $episodeId): void
|
||||
{
|
||||
$episode = Episode::where('id', $episodeId)->firstOrFail();
|
||||
$oldDescription = $episode->description;
|
||||
$episode->description = $request->input('description');
|
||||
$episode->save();
|
||||
|
||||
if ($episode->description !== $oldDescription) {
|
||||
// Log to ModLog
|
||||
ModLog::create([
|
||||
'moderator' => $request->user()->name,
|
||||
'data' => "Updated Episode description from {$oldDescription} to {$episode->description}",
|
||||
]);
|
||||
}
|
||||
|
||||
$this->applyTags($request, $episode);
|
||||
$this->updateTitle($request, $episode);
|
||||
}
|
||||
|
||||
public function getOrCreateStudio(string $studioName): Studios
|
||||
{
|
||||
return Studios::firstOrCreate(
|
||||
|
||||
Generated
+430
-427
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('comments', function (Blueprint $table) {
|
||||
$table->bigInteger('deleted_by_moderator_id')
|
||||
->nullable()
|
||||
->after('parent_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('comments', function (Blueprint $table) {
|
||||
$table->dropColumn('deleted_by_moderator_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('mod_logs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('moderator');
|
||||
$table->text('data');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('mod_logs');
|
||||
}
|
||||
};
|
||||
Generated
+382
-319
File diff suppressed because it is too large
Load Diff
+40
-44
@@ -1,56 +1,52 @@
|
||||
const sleep = (ms = 0) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
var old_timestamp = document.getElementById('ts_reference').value;
|
||||
function initGalleryPreviews() {
|
||||
const previews = document.querySelectorAll('.preview-gallery');
|
||||
|
||||
function initPreviews() {
|
||||
var thumbs = document.querySelectorAll('div[data-thumbs]');
|
||||
thumbs.forEach(function (thumb) {
|
||||
var thumbsJSON = JSON.parse(thumb.dataset.thumbs);
|
||||
var originalImage = thumb.children[0].children[1].src;
|
||||
var interval;
|
||||
var i = 1;
|
||||
previews.forEach((img) => {
|
||||
// Prevent double initialization
|
||||
if (img.dataset.previewInitialized) return;
|
||||
|
||||
function clear() {
|
||||
thumb.children[0].children[1].src = originalImage;
|
||||
i = 1;
|
||||
clearTimeout(interval);
|
||||
}
|
||||
img.dataset.previewInitialized = 'true';
|
||||
|
||||
function toggle() {
|
||||
if (i == 0) {
|
||||
clear();
|
||||
let images = [];
|
||||
|
||||
try {
|
||||
images = JSON.parse(img.dataset.gallery);
|
||||
} catch (e) {
|
||||
console.error('Invalid gallery JSON', e);
|
||||
return;
|
||||
}
|
||||
|
||||
thumb.children[0].children[1].src = thumbsJSON[i];
|
||||
i = (i + 1) % thumbsJSON.length;
|
||||
}
|
||||
if (images.length <= 1) return;
|
||||
|
||||
function interval() {
|
||||
// Start Preview
|
||||
interval = setInterval(toggle, 700);
|
||||
}
|
||||
const original = img.src;
|
||||
|
||||
thumb.addEventListener('mouseenter', interval);
|
||||
thumb.addEventListener('mouseleave', clear);
|
||||
let index = 0;
|
||||
let interval = null;
|
||||
|
||||
const startPreview = () => {
|
||||
console.log("startPreview");
|
||||
interval = setInterval(() => {
|
||||
index = (index + 1) % images.length;
|
||||
img.src = images[index];
|
||||
}, 700);
|
||||
};
|
||||
|
||||
const stopPreview = () => {
|
||||
console.log("stopPreview");
|
||||
clearInterval(interval);
|
||||
interval = null;
|
||||
|
||||
index = 0;
|
||||
img.src = original;
|
||||
};
|
||||
|
||||
img.addEventListener('mouseenter', startPreview);
|
||||
img.addEventListener('mouseleave', stopPreview);
|
||||
});
|
||||
}
|
||||
|
||||
async function init() {
|
||||
for (let i = 0; i < 9; i++) {
|
||||
var new_timestamp = document.getElementById('ts_reference').value;
|
||||
if (new_timestamp != old_timestamp) {
|
||||
console.log('== Changed ==');
|
||||
initPreviews();
|
||||
break;
|
||||
}
|
||||
console.log('== Didnt Change ==');
|
||||
await sleep(1000);
|
||||
}
|
||||
}
|
||||
// Initial page load
|
||||
document.addEventListener('DOMContentLoaded', initGalleryPreviews);
|
||||
|
||||
window.addEventListener('contentChanged', event => {
|
||||
console.log('== Received contentChanged Event ==');
|
||||
init();
|
||||
});
|
||||
|
||||
initPreviews();
|
||||
// Livewire v3 navigation/update
|
||||
document.addEventListener('contentChanged', initGalleryPreviews);
|
||||
@@ -1,13 +1,32 @@
|
||||
<div data-te-modal-init class="fixed left-0 top-0 z-[1055] hidden h-full w-full overflow-y-auto overflow-x-hidden outline-none" id="modalEditEpisode" tabindex="-1" aria-labelledby="Upload" aria-modal="true" role="dialog">
|
||||
<div data-te-modal-dialog-ref class="pointer-events-none relative flex min-h-[calc(100%-1rem)] w-auto translate-y-[-50px] items-center opacity-0 transition-all duration-300 ease-in-out min-[576px]:mx-auto min-[576px]:mt-7 min-[576px]:min-h-[calc(100%-3.5rem)] min-[576px]:max-w-[95%] md:min-[576px]:max-w-[90%] lg:min-[576px]:max-w-[80%] xl:min-[576px]:max-w-[70%] 2xl:min-[576px]:max-w-[50%]">
|
||||
<div class="flex relative flex-col w-full text-current bg-clip-padding bg-white rounded-md border-none shadow-lg outline-none pointer-events-auto dark:bg-neutral-800">
|
||||
<div
|
||||
data-te-modal-init
|
||||
id="modalEditEpisode"
|
||||
tabindex="-1"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="fixed inset-0 z-[1055] hidden overflow-y-auto bg-black/60 backdrop-blur-sm"
|
||||
>
|
||||
<div data-te-modal-dialog-ref class="flex min-h-screen items-center justify-center p-4">
|
||||
<div class="relative w-full max-w-7xl overflow-hidden rounded-2xl border border-neutral-200 bg-white shadow-2xl dark:border-neutral-700 dark:bg-neutral-900">
|
||||
<x-modal-header :title="__('Edit Episode')"/>
|
||||
|
||||
<!--Modal body-->
|
||||
<div class="relative p-4 pt-0">
|
||||
<form method="POST" action="{{ route('admin.edit') }}" enctype="multipart/form-data">
|
||||
<form method="POST" action="{{ route('admin.episode.edit') }}" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<div class="grid grid-cols-3">
|
||||
<div class="flex flex-col gap-2 p-2">
|
||||
<div>
|
||||
<label class="leading-tight text-gray-800 dark:text-gray-200 w-full" for="title">Title:</label>
|
||||
<x-text-input id="title" value="{{ $episode->title }}" class="block w-full" type="text" name="title" required autofocus/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="leading-tight text-gray-800 dark:text-gray-200 w-full" for="title_jpn">Title JPN:</label>
|
||||
<x-text-input id="title_jpn" value="{{ $episode->title_jpn }}" class="block w-full" type="text" name="title_jpn" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-3 p-2">
|
||||
<div class="col-span-2">
|
||||
<!-- Tags -->
|
||||
<div class="row-span-2 p-0">
|
||||
@@ -16,6 +35,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if(auth()->user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR))
|
||||
<div class="grid grid-rows-2">
|
||||
<!-- Studio -->
|
||||
<div class="p-2 pt-0">
|
||||
@@ -47,13 +67,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if(auth()->user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR))
|
||||
<!-- Stream URL -->
|
||||
<div class="p-2 pt-0">
|
||||
<label class="w-full leading-tight text-gray-800 dark:text-gray-200" for="baseurl">Stream:</label>
|
||||
<x-text-input id="baseurl" class="block w-full" type="text" name="baseurl" value="{{ $episode->url }}" required />
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<input name="episode_id" id="episode_id" type="hidden" value="{{ $episode->id }}" />
|
||||
|
||||
@@ -62,6 +85,7 @@
|
||||
<textarea rows="4" cols="50" id="description" name="description" class="block mt-1 w-full rounded-md border-gray-300 shadow-sm dark:border-gray-700 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" required>{{ $episode->description }}</textarea>
|
||||
</div>
|
||||
|
||||
@if(auth()->user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR))
|
||||
<!-- Episodes -->
|
||||
<div class="grid grid-cols-2">
|
||||
<!-- Cover -->
|
||||
@@ -95,8 +119,10 @@
|
||||
<label class="w-full leading-tight text-gray-800 dark:text-gray-200" for="downloadUHDi1">Download 4k Interpolated:</label>
|
||||
<x-text-input id="downloadUHDi1" class="block w-full" type="text" name="downloadUHDi1" value="{{ $episode->getDownloadByType('UHDi')->url ?? '' }}" />
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="flex flex-wrap flex-shrink-0 justify-end items-center p-4 rounded-b-md">
|
||||
<div class="sticky bottom-0 flex items-center justify-end gap-3 border-t border-neutral-200 bg-white/90 px-6 py-4 backdrop-blur dark:border-neutral-700 dark:bg-neutral-900/90">
|
||||
@if(auth()->user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR))
|
||||
<div class="inline-block mr-2">
|
||||
<input class="w-4 h-4 text-rose-600 bg-gray-100 border-gray-300 rounded focus:ring-rose-500 dark:focus:ring-rose-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
|
||||
type="checkbox" value="true" id="v2" name="v2" />
|
||||
@@ -111,10 +137,17 @@
|
||||
DMCA Takedown
|
||||
</label>
|
||||
</div>
|
||||
<button type="button" class="inline-block px-6 pt-2.5 pb-2 text-xs font-medium leading-normal uppercase rounded transition duration-150 ease-in-out bg-primary-100 text-primary-700 hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200" data-te-modal-dismiss data-te-ripple-init data-te-ripple-color="light">
|
||||
@endif
|
||||
<button
|
||||
type="button"
|
||||
data-te-modal-dismiss
|
||||
class="rounded-xl border border-neutral-300 px-5 py-2.5 text-sm font-medium text-neutral-700 transition hover:bg-neutral-100 dark:border-neutral-600 dark:text-neutral-200 dark:hover:bg-neutral-800">
|
||||
Cancel
|
||||
</button>
|
||||
<button type="submit" class="inline-block px-6 pt-2.5 pb-2 ml-1 text-xs font-medium leading-normal text-white uppercase bg-rose-600 rounded transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600" data-te-ripple-init data-te-ripple-color="light">
|
||||
<button
|
||||
type="submit"
|
||||
data-te-ripple-init
|
||||
class="rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700">
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
@auth
|
||||
@if(Auth::user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR))
|
||||
<div class="relative p-5 bg-white dark:bg-neutral-700/40 rounded-lg overflow-hidden z-10">
|
||||
<div class="float-left">
|
||||
<a data-te-toggle="modal" data-te-target="#modalUploadEpisode" class="text-xl text-gray-800 dark:text-gray-200 leading-tight cursor-pointer whitespace-nowrap">
|
||||
<i class="fa-solid fa-plus pr-[6px]"></i> Add Episode
|
||||
</a>
|
||||
</div>
|
||||
<div class="float-right">
|
||||
<a data-te-toggle="modal" data-te-target="#modalAddSubtitles" class="text-xl text-gray-800 dark:text-gray-200 leading-tight cursor-pointer whitespace-nowrap">
|
||||
<i class="fa-solid fa-plus pr-[6px]"></i> Add Subtitles
|
||||
</a>
|
||||
<a data-te-toggle="modal" data-te-target="#modalEditEpisode" class="text-xl text-gray-800 dark:text-gray-200 leading-tight cursor-pointer whitespace-nowrap">
|
||||
<i class="fa-solid fa-pen pr-[6px]"></i> Edit Episode
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@endauth
|
||||
@@ -1,5 +1,5 @@
|
||||
<x-guest-layout>
|
||||
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-neutral-950/50 shadow-md overflow-hidden sm:rounded-lg">
|
||||
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-neutral-800 shadow-md overflow-hidden sm:rounded-lg">
|
||||
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
|
||||
{{ __('This is a secure area of the application. Please confirm your password before continuing.') }}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<x-guest-layout>
|
||||
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-neutral-950/50 shadow-md overflow-hidden sm:rounded-lg">
|
||||
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-neutral-800 shadow-md overflow-hidden sm:rounded-lg">
|
||||
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
|
||||
{{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}
|
||||
</div>
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
<div class="w-full sm:max-w-md mt-6">
|
||||
<ul class="flex list-none flex-row flex-wrap border-b-0 pl-0 relative " role="tablist" data-te-nav-ref>
|
||||
<li role="presentation" class="flex-auto text-center">
|
||||
<a href="#tabs-login" class="rounded-l-lg my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white/50 dark:bg-neutral-950/50 backdrop-blur-sm dark:hover:bg-neutral-800 dark:data-[te-nav-active]:text-white"
|
||||
<a href="#tabs-login" class="rounded-l-lg my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white/50 dark:bg-neutral-800 backdrop-blur-sm dark:hover:bg-neutral-900 dark:data-[te-nav-active]:text-white"
|
||||
data-te-toggle="pill" data-te-target="#tabs-login" data-te-nav-active role="tab" aria-controls="tabs-login" aria-selected="true">
|
||||
{{ __('Login') }}
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation" class="flex-auto text-center">
|
||||
<a href="#tabs-register" class="rounded-r-lg my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white/50 dark:bg-neutral-950/50 backdrop-blur-sm dark:hover:bg-neutral-800 dark:data-[te-nav-active]:text-white"
|
||||
<a href="#tabs-register" class="rounded-r-lg my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white/50 dark:bg-neutral-800 backdrop-blur-sm dark:hover:bg-neutral-900 dark:data-[te-nav-active]:text-white"
|
||||
data-te-toggle="pill" data-te-target="#tabs-register" role="tab" aria-controls="tabs-register" aria-selected="false">
|
||||
{{ __('Register') }}
|
||||
</a>
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
<!-- Login -->
|
||||
<div class="w-full sm:max-w-md hidden opacity-100 transition-opacity duration-150 ease-linear data-[te-tab-active]:block" id="tabs-login" role="tabpanel" aria-labelledby="tabs-login" data-te-tab-active>
|
||||
<div class="px-6 py-4 bg-white dark:bg-neutral-950/50 shadow-md overflow-hidden sm:rounded-lg">
|
||||
<div class="px-6 py-4 bg-white dark:bg-neutral-800 shadow-md overflow-hidden sm:rounded-lg">
|
||||
<div class="w-full text-center text-white mb-3">
|
||||
<a href="{{ route('discord.login') }}">
|
||||
<div
|
||||
@@ -102,7 +102,7 @@
|
||||
|
||||
<!-- Register -->
|
||||
<div class="w-full sm:max-w-md hidden opacity-0 transition-opacity duration-150 ease-linear data-[te-tab-active]:block" id="tabs-register" role="tabpanel" aria-labelledby="tabs-register">
|
||||
<div class="px-6 py-4 bg-white dark:bg-neutral-950/50 shadow-md overflow-hidden sm:rounded-lg">
|
||||
<div class="px-6 py-4 bg-white dark:bg-neutral-800 shadow-md overflow-hidden sm:rounded-lg">
|
||||
<form method="POST" action="{{ route('register') }}">
|
||||
@csrf
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<x-guest-layout>
|
||||
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-neutral-950/50 shadow-md overflow-hidden sm:rounded-lg">
|
||||
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-neutral-800 shadow-md overflow-hidden sm:rounded-lg">
|
||||
<form method="POST" action="{{ route('password.store') }}">
|
||||
@csrf
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<x-guest-layout>
|
||||
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-neutral-950/50 shadow-md overflow-hidden sm:rounded-lg">
|
||||
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-neutral-800 shadow-md overflow-hidden sm:rounded-lg">
|
||||
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
|
||||
{{ __('Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
@props([
|
||||
'episode',
|
||||
'view',
|
||||
'displayjapanese' => false
|
||||
])
|
||||
|
||||
@php
|
||||
$title = $displayjapanese
|
||||
? "{$episode->title_jpn} ({$episode->title}) - {$episode->episode}"
|
||||
: "{$episode->title} - {$episode->episode}";
|
||||
|
||||
$isLoggedIn = auth()->check();
|
||||
|
||||
$isWatched = $isLoggedIn
|
||||
? $episode->userWatched(auth()->id())
|
||||
: false;
|
||||
|
||||
$problematic = cache()->rememberForever(
|
||||
"episodeProblematic{$episode->id}",
|
||||
fn () => $episode->getProblematicTags()
|
||||
);
|
||||
@endphp
|
||||
|
||||
<div class="group w-full p-1">
|
||||
<a
|
||||
href="{{ route('hentai.index', ['title' => $episode->slug]) }}"
|
||||
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">
|
||||
|
||||
{{-- Thumbnail / Cover --}}
|
||||
@if ($view === 'poster')
|
||||
<img
|
||||
src="{{ $episode->cover_url }}"
|
||||
alt="{{ $episode->title }} - {{ $episode->episode }}"
|
||||
loading="lazy"
|
||||
width="400"
|
||||
class="aspect-[11/16] w-full object-cover object-center transition-transform duration-500 group-hover:scale-[1.03]"
|
||||
>
|
||||
@elseif ($view === 'thumbnail')
|
||||
@php
|
||||
$galleryImages = $episode->gallery
|
||||
->pluck('thumbnail_url')
|
||||
->filter()
|
||||
->values();
|
||||
@endphp
|
||||
<img
|
||||
src="{{ $galleryImages->first() }}"
|
||||
alt="{{ $episode->title }} - {{ $episode->episode }}"
|
||||
loading="lazy"
|
||||
width="1000"
|
||||
data-gallery='@json($galleryImages)'
|
||||
class="preview-gallery aspect-video w-full object-cover object-center transition-transform duration-500 group-hover:scale-[1.03]"
|
||||
>
|
||||
@endif
|
||||
|
||||
{{-- Dark Overlay --}}
|
||||
<div class="pointer-events-none absolute inset-0 bg-gradient-to-t from-black/90 via-black/20 to-transparent"></div>
|
||||
|
||||
{{-- Top Meta --}}
|
||||
<div class="pointer-events-none absolute inset-x-0 top-0 z-20 flex items-start justify-between p-3">
|
||||
|
||||
{{-- Problematic Tags --}}
|
||||
@if (!empty($problematic))
|
||||
<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>
|
||||
{{ $problematic }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Resolution --}}
|
||||
<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() }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Bottom Content --}}
|
||||
<div class="pointer-events-none absolute inset-x-0 bottom-0 z-20 p-4">
|
||||
|
||||
{{-- 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 --}}
|
||||
<div class="flex flex-wrap items-center gap-3 text-sm font-bold text-neutral-200">
|
||||
|
||||
<span class="flex items-center gap-1">
|
||||
<i class="fa-regular fa-eye text-neutral-200 font-bold"></i>
|
||||
{{ $episode->viewCountFormatted() }}
|
||||
</span>
|
||||
|
||||
<span class="flex items-center gap-1">
|
||||
<i class="fa-regular fa-heart text-neutral-200 font-bold"></i>
|
||||
{{ $episode->likeCount() }}
|
||||
</span>
|
||||
|
||||
<span class="flex items-center gap-1">
|
||||
<i class="fa-regular fa-comment text-neutral-200 font-bold"></i>
|
||||
{{ $episode->commentCount() }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{{-- Watched Status (logged in users only) --}}
|
||||
@auth
|
||||
@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">
|
||||
@if ($view === 'thumbnail')
|
||||
<i class="fa-solid fa-eye mr-1"></i> Watched
|
||||
@else
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
<div class="shrink-0 rounded-full bg-rose-800/40 px-2.5 py-1 text-xs font-semibold text-rose-300 ring-1 ring-rose-500/30">
|
||||
<i class="fa-solid fa-eye-slash"></i>
|
||||
</div>
|
||||
@endif
|
||||
@endauth
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
@@ -1,58 +0,0 @@
|
||||
@props(['episode'])
|
||||
|
||||
<div class="relative p-1 mb-8 w-full transition duration-300 ease-in-out md:p-2 md:hover:-translate-y-1 md:hover:scale-110">
|
||||
<a class="hover:text-blue-600" href="{{ route('hentai.index', ['title' => $episode->slug]) }}">
|
||||
<img alt="{{ $episode->title }} - {{ $episode->episode }}" loading="lazy" width="1000"
|
||||
class="block object-cover object-center relative z-20 rounded-lg aspect-video"
|
||||
src="{{ $episode->gallery->first()->thumbnail_url }}"></img>
|
||||
|
||||
@guest
|
||||
<p
|
||||
class="absolute right-1 md:right-2 top-1 md:top-2 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 md:left-4 bottom-1 md:bottom-2 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>
|
||||
@endguest
|
||||
|
||||
@php $problematic = cache()->rememberForever('episodeProblematic'.$episode->id, fn () => $episode->getProblematicTags()); @endphp
|
||||
@if (!empty($problematic))
|
||||
<p
|
||||
class="absolute left-4 top-2 bg-red-700/70 !text-white rounded-br-lg rounded-tl-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||
<i class="fa-solid fa-triangle-exclamation"></i> {{ $problematic }}
|
||||
</p>
|
||||
@endif
|
||||
|
||||
@auth
|
||||
@if ($episode->userWatched(auth()->user()->id))
|
||||
<p
|
||||
class="absolute right-1 md:right-2 top-1 md:top-2 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 md:left-2 bottom-1 md:bottom-2 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 md:right-2 top-1 md:top-2 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 md:left-2 bottom-1 md:bottom-2 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
|
||||
|
||||
<div class="absolute w-[95%] grid grid-cols-1 text-center">
|
||||
<p class="text-sm text-center text-black dark:text-white">{{ $episode->title }} -
|
||||
{{ $episode->episode }}</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
@@ -1,13 +1,19 @@
|
||||
@props(['title'])
|
||||
<div class="flex flex-shrink-0 items-center justify-between rounded-t-md p-4 bg-rose-600">
|
||||
<!--Modal title-->
|
||||
<h5 class="text-xl font-medium leading-normal text-white">
|
||||
<div class="sticky top-0 z-10 flex items-center justify-between border-b border-neutral-200 bg-white/90 px-6 py-4 backdrop-blur dark:border-neutral-700 dark:bg-neutral-900/90">
|
||||
<div>
|
||||
<h2
|
||||
id="modalGenresLabel"
|
||||
class="text-xl font-semibold text-neutral-900 dark:text-white"
|
||||
>
|
||||
{{ $title }}
|
||||
</h5>
|
||||
<!--Close button-->
|
||||
<button type="button" class="box-content text-white rounded-none border-none hover:no-underline hover:opacity-75 focus:opacity-100 focus:shadow-none focus:outline-none" data-te-modal-dismiss aria-label="Close">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-6 w-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-te-modal-dismiss
|
||||
class="rounded-lg p-2 text-neutral-500 transition hover:bg-neutral-100 hover:text-black dark:hover:bg-neutral-800 dark:hover:text-white"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
@@ -1,61 +1,83 @@
|
||||
<p class="leading-normal font-bold text-lg text-neutral-800 dark:text-white">
|
||||
<p class="text-lg font-bold leading-normal text-neutral-800 dark:text-white">
|
||||
{{ __('home.categories') }}
|
||||
</p>
|
||||
|
||||
@php
|
||||
$categories = [
|
||||
'Uncensored' => 'uncensored',
|
||||
'Milf' => 'milf',
|
||||
'Maid' => 'maid',
|
||||
'School Girl' => 'school-girl',
|
||||
'Succubus' => 'succubus',
|
||||
'Tentacle' => 'tentacle',
|
||||
'Big Boobs' => 'big-boobs',
|
||||
'BDSM' => 'bdsm',
|
||||
'Elf' => 'elf',
|
||||
'4k 48fps' => '4k-48fps',
|
||||
$categories = collect([
|
||||
['name' => 'Uncensored', 'slug' => 'uncensored'],
|
||||
['name' => 'Milf', 'slug' => 'milf'],
|
||||
['name' => 'Maid', 'slug' => 'maid'],
|
||||
['name' => 'School Girl', 'slug' => 'school-girl'],
|
||||
['name' => 'Succubus', 'slug' => 'succubus'],
|
||||
['name' => 'Tentacle', 'slug' => 'tentacle'],
|
||||
['name' => 'Big Boobs', 'slug' => 'big-boobs'],
|
||||
['name' => 'BDSM', 'slug' => 'bdsm'],
|
||||
['name' => 'Elf', 'slug' => 'elf'],
|
||||
['name' => '4K 48FPS', 'slug' => '4k-48fps'],
|
||||
]);
|
||||
@endphp
|
||||
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-5">
|
||||
@foreach ($categories as $category)
|
||||
@php
|
||||
$episodes = cache()->remember(
|
||||
"category_{$category['slug']}",
|
||||
now()->addMinutes(15),
|
||||
fn () => \App\Models\Episode::query()
|
||||
->withAllTags([$category['slug']])
|
||||
->inRandomOrder()
|
||||
->limit(3)
|
||||
->get()
|
||||
);
|
||||
|
||||
[$left, $center, $right] = [
|
||||
$episodes->get(0),
|
||||
$episodes->get(1),
|
||||
$episodes->get(2),
|
||||
];
|
||||
@endphp
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-5 lg:grid-cols-5 xl:grid-cols-5 2xl:grid-cols-5 gap-2">
|
||||
@foreach ($categories as $name => $slug)
|
||||
@php
|
||||
$cacheKey = 'category_' . $slug;
|
||||
<a
|
||||
href="{{ route('hentai.search', [
|
||||
'order' => 'recently-uploaded',
|
||||
'tags[0]' => $category['slug'],
|
||||
]) }}"
|
||||
class="group relative overflow-hidden rounded-2xl border dark:border-neutral-800 border-neutral-300 dark:bg-neutral-900 dark:hover:border-neutral-700 hover:border-neutral-400 hover:shadow-2xl hover:shadow-black/30 shadow-md transition-all duration-300 hover:-translate-y-1"
|
||||
>
|
||||
<div class="p-4">
|
||||
<h2 class="text-center text-lg font-semibold text-neutral-900 dark:text-white">
|
||||
{{ $category['name'] }}
|
||||
</h2>
|
||||
|
||||
$collection = \cache()->remember(
|
||||
$cacheKey,
|
||||
900,
|
||||
fn() => \App\Models\Episode::withAllTags([$slug])
|
||||
->inRandomOrder()
|
||||
->limit(3)
|
||||
->get(),
|
||||
);
|
||||
|
||||
$count = $collection->count();
|
||||
|
||||
@endphp
|
||||
<a href="{{ route('hentai.search', ['order' => 'recently-uploaded', 'tags[0]' => $slug]) }}"
|
||||
class="relative mx-auto w-96 sm:w-full h-56 bg-white dark:bg-neutral-800 text-black dark:text-white rounded-lg overflow-hidden shadow-lg mt-4 transition ease-in-out hover:-translate-y-1 hover:scale-110 duration-300">
|
||||
<h2 class="text-lg font-semibold text-center pt-2">{{ $name }}</h2>
|
||||
<div class="relative w-full h-full flex justify-center">
|
||||
<!-- Left Image -->
|
||||
@if ($count > 0)
|
||||
<img src="{{ $collection->first()->cover_url }}"
|
||||
class="absolute w-32 h-44 rounded-lg object-cover shadow-md left-4 top-4 rotate-[-15deg] z-0">
|
||||
<div class="relative mt-4 flex h-52 items-center justify-center">
|
||||
@if ($left)
|
||||
<img
|
||||
src="{{ $left->cover_url }}"
|
||||
alt="{{ $category['name'] }}"
|
||||
loading="lazy"
|
||||
class="absolute left-2 top-4 h-44 w-32 rotate-[-12deg] rounded-xl object-cover shadow-lg transition-transform duration-300 group-hover:rotate-[-16deg]"
|
||||
>
|
||||
@endif
|
||||
|
||||
<!-- Center Image -->
|
||||
@if ($count > 1)
|
||||
<img src="{{ $collection->skip(1)->first()->cover_url }}"
|
||||
class="absolute w-32 h-44 rounded-lg object-cover shadow-lg top-4 z-10">
|
||||
@if ($center)
|
||||
<img
|
||||
src="{{ $center->cover_url }}"
|
||||
alt="{{ $category['name'] }}"
|
||||
loading="lazy"
|
||||
class="absolute top-2 z-10 h-44 w-32 rounded-xl object-cover shadow-2xl transition-transform duration-300 group-hover:scale-105"
|
||||
>
|
||||
@endif
|
||||
|
||||
<!-- Right Image -->
|
||||
@if ($count > 2)
|
||||
<img src="{{ $collection->skip(2)->first()->cover_url }}"
|
||||
class="absolute w-32 h-44 rounded-lg object-cover shadow-lg right-4 top-14 z-20 rotate-[15deg]">
|
||||
@if ($right)
|
||||
<img
|
||||
src="{{ $right->cover_url }}"
|
||||
alt="{{ $category['name'] }}"
|
||||
loading="lazy"
|
||||
class="absolute right-2 top-8 z-20 h-44 w-32 rotate-[12deg] rounded-xl object-cover shadow-lg transition-transform duration-300 group-hover:rotate-[16deg]"
|
||||
>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@@ -1,68 +1,80 @@
|
||||
<p class="text-lg font-bold leading-normal text-neutral-800 dark:text-white">
|
||||
<p class="mb-6 text-2xl font-bold tracking-tight text-neutral-900 dark:text-white">
|
||||
{{ __('home.latest-comments') }}
|
||||
</p>
|
||||
|
||||
<div class="grid gap-2 grid-cols-1 xl:grid-cols-2">
|
||||
<div class="grid grid-cols-1 gap-6 xl:grid-cols-2">
|
||||
@foreach ($latestComments as $comment)
|
||||
@if ($comment->commentable_type == \App\Models\Episode::class)
|
||||
@php $episode = cache()->rememberForever('commentEpisode'.$comment->commentable_id, fn () => App\Models\Episode::with('gallery')->where('id', $comment->commentable_id)->first()); @endphp
|
||||
<div id="comments" class="flex p-4 bg-white rounded-lg dark:bg-neutral-950">
|
||||
|
||||
@php
|
||||
$isEpisode = $comment->commentable_type == \App\Models\Episode::class;
|
||||
|
||||
if ($isEpisode) {
|
||||
$item = cache()->rememberForever(
|
||||
'commentEpisode' . $comment->commentable_id,
|
||||
fn () => \App\Models\Episode::with('gallery')
|
||||
->find($comment->commentable_id)
|
||||
);
|
||||
|
||||
$url = route('hentai.index', ['title' => $item->slug]);
|
||||
$title = $item->title . ' - ' . $item->episode;
|
||||
$thumbnail = $item->gallery->first()?->thumbnail_url ?? $item->cover_url;
|
||||
$cover = $item->cover_url;
|
||||
$resolution = $item->getResolution();
|
||||
} else {
|
||||
$item = cache()->rememberForever(
|
||||
'commentHentai' . $comment->commentable_id,
|
||||
fn () => \App\Models\Hentai::with('gallery', 'episodes')
|
||||
->find($comment->commentable_id)
|
||||
);
|
||||
|
||||
$episode = $item->episodes->first();
|
||||
|
||||
$url = route('hentai.index', ['title' => $item->slug]);
|
||||
$title = $episode?->title;
|
||||
$thumbnail = $item->gallery->first()?->thumbnail_url ?? $episode?->cover_url;
|
||||
$cover = $episode?->cover_url;
|
||||
$resolution = $episode?->getResolution();
|
||||
}
|
||||
@endphp
|
||||
|
||||
<div
|
||||
class="w-[15vw] mr-5 p-1 md:p-2 mb-4 relative transition ease-in-out hover:-translate-y-1 hover:scale-110 duration-300">
|
||||
<a class="hidden 2xl:block"
|
||||
href="{{ route('hentai.index', ['title' => $episode->slug]) }}">
|
||||
<img alt="{{ $episode->title }} - {{ $episode->episode }}" loading="lazy" width="1000"
|
||||
class="block object-cover object-center relative z-20 rounded-lg aspect-video"
|
||||
src="{{ $episode->gallery->first()->thumbnail_url }}"></img>
|
||||
<p
|
||||
class="absolute right-2 top-2 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>
|
||||
<div class="absolute w-[95%] grid grid-cols-1 text-center">
|
||||
<p class="text-sm text-center text-black dark:text-white truncate">{{ $episode->title }} -
|
||||
{{ $episode->episode }}</p>
|
||||
class="group overflow-hidden rounded-2xl border dark:border-neutral-800 border-neutral-300 dark:bg-neutral-900 dark:hover:border-neutral-700 hover:border-neutral-400 hover:shadow-2xl hover:shadow-black/30 shadow-md transition-all duration-300 hover:-translate-y-1">
|
||||
|
||||
<div class="flex flex-col md:flex-row">
|
||||
|
||||
{{-- Thumbnail --}}
|
||||
<a href="{{ $url }}"
|
||||
class="relative w-full md:w-72 shrink-0 overflow-hidden">
|
||||
|
||||
{{-- Desktop Thumbnail --}}
|
||||
<img
|
||||
src="{{ $thumbnail }}"
|
||||
alt="{{ $title }}"
|
||||
loading="lazy"
|
||||
class="h-full w-full object-cover transition-transform duration-500 group-hover:scale-105 aspect-video"
|
||||
>
|
||||
|
||||
{{-- Resolution Badge --}}
|
||||
<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">
|
||||
{{ $resolution }}
|
||||
</div>
|
||||
|
||||
{{-- Gradient Overlay --}}
|
||||
<div
|
||||
class="absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/80 via-black/30 to-transparent p-4">
|
||||
<p class="line-clamp-1 text-sm font-medium text-white">
|
||||
{{ $title }}
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="block 2xl:hidden"
|
||||
href="{{ route('hentai.index', ['title' => $episode->slug]) }}">
|
||||
<img alt="{{ $episode->title }} - {{ $episode->episode }}" loading="lazy" width="1000"
|
||||
class="block object-cover object-center relative z-20 rounded-lg"
|
||||
src="{{ $episode->cover_url }}"></img>
|
||||
</a>
|
||||
</div>
|
||||
<div class="w-[60vw] pt-4 bg-neutral-100 dark:bg-neutral-800 rounded-lg pl-4">
|
||||
{{-- Comment Content --}}
|
||||
<div class="flex-1 p-4 md:p-6 bg-neutral-50 dark:bg-neutral-900">
|
||||
@include('partials.comment', ['comment' => $comment])
|
||||
</div>
|
||||
</div>
|
||||
@elseif($comment->commentable_type == \App\Models\Hentai::class)
|
||||
@php $hentai = cache()->rememberForever('commentHentai'.$comment->commentable_id, fn () => App\Models\Hentai::with('gallery', 'episodes')->where('id', $comment->commentable_id)->first()); @endphp
|
||||
<div id="comments" class="flex p-4 bg-white rounded-lg dark:bg-neutral-950">
|
||||
<div
|
||||
class="w-[15vw] mr-5 p-1 md:p-2 mb-8 relative transition ease-in-out hover:-translate-y-1 hover:scale-110 duration-300">
|
||||
<a class="hidden 2xl:block" href="{{ route('hentai.index', ['title' => $hentai->slug]) }}">
|
||||
<img alt="{{ $hentai->episodes->first()->title }}" loading="lazy" width="1000"
|
||||
class="block object-cover object-center relative z-20 rounded-lg aspect-video"
|
||||
src="{{ $hentai->gallery->first()->thumbnail_url }}"></img>
|
||||
<p
|
||||
class="absolute right-2 top-2 bg-rose-700/70 !text-white rounded-bl-lg rounded-tr-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||
{{ $hentai->episodes->first()->getResolution() }}</p>
|
||||
<div class="absolute w-[95%] grid grid-cols-1 text-center">
|
||||
<p class="text-sm text-center text-black dark:text-white truncate">
|
||||
{{ $hentai->episodes->first()->title }}</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="block 2xl:hidden"
|
||||
href="{{ route('hentai.index', ['title' => $hentai->slug]) }}">
|
||||
<img alt="{{ $hentai->episodes->first()->title }}" loading="lazy" width="1000"
|
||||
class="block object-cover object-center relative z-20 rounded-lg"
|
||||
src="{{ $hentai->episodes->first()->cover_url }}"></img>
|
||||
</a>
|
||||
</div>
|
||||
<div class="w-[60vw] pt-4 bg-neutral-100 dark:bg-neutral-800 rounded-lg pl-4">
|
||||
@include('partials.comment', ['comment' => $comment])
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@endforeach
|
||||
</div>
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
@php
|
||||
$random = \cache()->remember('random_home', 300, function () {
|
||||
return \App\Models\Episode::inRandomOrder()->limit(8)->get(); ;
|
||||
return \App\Models\Episode::inRandomOrder()->limit(16)->get(); ;
|
||||
});
|
||||
@endphp
|
||||
|
||||
<div class="mb-6">
|
||||
@include('home.partials.tab.template', ['episodes' => $random, 'showThumbnails' => false])
|
||||
@include('home.partials.tab.template', ['episodes' => $random, 'isThumbnail' => false])
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,46 @@
|
||||
@if ($showThumbnails)
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-2">
|
||||
@include('partials.episode-thumbnail', ['limit' => 15])
|
||||
</div>
|
||||
@props(['isThumbnail'])
|
||||
|
||||
@php
|
||||
// Render enough items for largest possible layout
|
||||
$limit = 16;
|
||||
|
||||
$view = $isThumbnail ? 'thumbnail' : 'poster';
|
||||
@endphp
|
||||
|
||||
@if ($isThumbnail)
|
||||
<div
|
||||
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-4 3xl:grid-cols-5
|
||||
[&>.episode-item]:hidden
|
||||
[&>.episode-item:nth-child(-n+8)]:block
|
||||
md:[&>.episode-item:nth-child(-n+8)]:block
|
||||
lg:[&>.episode-item:nth-child(-n+9)]:block
|
||||
xl:[&>.episode-item:nth-child(-n+9)]:block
|
||||
2xl:[&>.episode-item:nth-child(-n+12)]:block
|
||||
3xl:[&>.episode-item:nth-child(-n+15)]:block"
|
||||
>
|
||||
@else
|
||||
<div class="grid grid-cols-2 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 xl:grid-cols-7 2xl:grid-cols-8 gap-2">
|
||||
@include('partials.episode-cover', ['limit' => 16])
|
||||
</div>
|
||||
<div
|
||||
class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-4 2xl:grid-cols-5 3xl:grid-cols-8
|
||||
[&>.episode-item]:hidden
|
||||
[&>.episode-item:nth-child(-n+12)]:block
|
||||
md:[&>.episode-item:nth-child(-n+12)]:block
|
||||
xl:[&>.episode-item:nth-child(-n+12)]:block
|
||||
2xl:[&>.episode-item:nth-child(-n+15)]:block
|
||||
3xl:[&>.episode-item:nth-child(-n+16)]:block"
|
||||
>
|
||||
@endif
|
||||
@foreach ($episodes->take($limit) as $ep)
|
||||
@php
|
||||
$episode = isset($popularView)
|
||||
? $ep->episode
|
||||
: $ep;
|
||||
@endphp
|
||||
|
||||
<div class="episode-item p-1">
|
||||
<x-episode-cover
|
||||
:episode="$episode"
|
||||
:view="$view"
|
||||
/>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@@ -2,7 +2,7 @@
|
||||
<ul class="-mb-6 flex list-none flex-row flex-wrap border-b-0 pl-0 relative z-10" role="tablist" data-te-nav-ref>
|
||||
<li role="presentation" class="flex-auto text-center">
|
||||
<a href="#tabs-most-views"
|
||||
class="rounded-l-lg my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:data-[te-nav-active]:text-white"
|
||||
class="rounded-l-xl my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white dark:bg-neutral-900 dark:hover:bg-neutral-800 dark:data-[te-nav-active]:text-white"
|
||||
data-te-toggle="pill" data-te-target="#tabs-most-views" data-te-nav-active role="tab"
|
||||
aria-controls="tabs-most-views" aria-selected="true">
|
||||
{{ __('home.most-views') }}
|
||||
@@ -10,7 +10,7 @@
|
||||
</li>
|
||||
<li role="presentation" class="flex-auto text-center">
|
||||
<a href="#tabs-most-likes"
|
||||
class="my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:data-[te-nav-active]:text-white"
|
||||
class="my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white dark:bg-neutral-900 dark:hover:bg-neutral-800 dark:data-[te-nav-active]:text-white"
|
||||
data-te-toggle="pill" data-te-target="#tabs-most-likes" role="tab" aria-controls="tabs-most-likes"
|
||||
aria-selected="false">
|
||||
{{ __('home.most-likes') }}
|
||||
@@ -18,7 +18,7 @@
|
||||
</li>
|
||||
<li role="presentation" class="flex-auto text-center">
|
||||
<a href="#tabs-popular-weekly"
|
||||
class="my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:data-[te-nav-active]:text-white"
|
||||
class="my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white dark:bg-neutral-900 dark:hover:bg-neutral-800 dark:data-[te-nav-active]:text-white"
|
||||
data-te-toggle="pill" data-te-target="#tabs-popular-weekly" role="tab"
|
||||
aria-controls="tabs-popular-weekly" aria-selected="false">
|
||||
{{ __('home.popular-weekly') }}
|
||||
@@ -26,7 +26,7 @@
|
||||
</li>
|
||||
<li role="presentation" class="flex-auto text-center">
|
||||
<a href="#tabs-popular-monthly"
|
||||
class="rounded-r-lg my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white dark:bg-neutral-950 dark:hover:bg-neutral-800 dark:data-[te-nav-active]:text-white"
|
||||
class="rounded-r-xl my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white dark:bg-neutral-900 dark:hover:bg-neutral-800 dark:data-[te-nav-active]:text-white"
|
||||
data-te-toggle="pill" data-te-target="#tabs-popular-monthly" role="tab"
|
||||
aria-controls="tabs-popular-monthly" aria-selected="false">
|
||||
{{ __('home.popular-monthly') }}
|
||||
@@ -34,11 +34,11 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@php $showThumbnails = true; @endphp
|
||||
@php $isThumbnail = true; @endphp
|
||||
|
||||
@auth
|
||||
@if (!Auth::user()->home_middle_design)
|
||||
@php $showThumbnails = false; @endphp
|
||||
@php $isThumbnail = false; @endphp
|
||||
@endif
|
||||
@endauth
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
id="tabs-most-views" role="tabpanel" aria-labelledby="tabs-most-views-tab" data-te-tab-active>
|
||||
@include('home.partials.tab.template', [
|
||||
'episodes' => $popularAllTime,
|
||||
'showThumbnails' => $showThumbnails,
|
||||
'isThumbnail' => $isThumbnail,
|
||||
])
|
||||
<div class="grid text-center pt-5 ">
|
||||
<a href="{{ route('hentai.search', ['order' => 'view-count']) }}"
|
||||
@@ -61,7 +61,7 @@
|
||||
id="tabs-most-likes" role="tabpanel" aria-labelledby="tabs-most-likes-tab">
|
||||
@include('home.partials.tab.template', [
|
||||
'episodes' => $mostLikes,
|
||||
'showThumbnails' => $showThumbnails,
|
||||
'isThumbnail' => $isThumbnail,
|
||||
])
|
||||
<div class="grid text-center pt-5 ">
|
||||
<a href="{{ route('hentai.search', ['order' => 'view-count']) }}"
|
||||
@@ -74,7 +74,7 @@
|
||||
id="tabs-popular-weekly" role="tabpanel" aria-labelledby="tabs-popular-weekly-tab">
|
||||
@include('home.partials.tab.template', [
|
||||
'episodes' => $popularWeekly,
|
||||
'showThumbnails' => $showThumbnails,
|
||||
'isThumbnail' => $isThumbnail,
|
||||
'popularView' => true,
|
||||
])
|
||||
<div class="grid text-center pt-5 ">
|
||||
@@ -88,7 +88,7 @@
|
||||
id="tabs-popular-monthly" role="tabpanel" aria-labelledby="tabs-popular-monthly-tab">
|
||||
@include('home.partials.tab.template', [
|
||||
'episodes' => $popularMonthly,
|
||||
'showThumbnails' => $showThumbnails,
|
||||
'isThumbnail' => $isThumbnail,
|
||||
'popularView' => true,
|
||||
])
|
||||
<div class="grid text-center pt-5 ">
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<!--Tabs navigation-->
|
||||
<ul class="-mb-6 flex list-none flex-row flex-wrap border-b-0 pl-0 relative z-10" role="tablist" data-te-nav-ref>
|
||||
<li role="presentation" class="flex-auto text-center">
|
||||
<a href="#tabs-recently-uploaded" class="rounded-l-lg my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white/50 dark:bg-neutral-950/50 backdrop-blur-sm dark:hover:bg-neutral-800 dark:data-[te-nav-active]:text-white"
|
||||
<a href="#tabs-recently-uploaded" class="rounded-l-xl my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white/50 dark:bg-neutral-900/50 backdrop-blur-sm dark:hover:dark:hover:bg-neutral-900 dark:data-[te-nav-active]:text-white"
|
||||
data-te-toggle="pill" data-te-target="#tabs-recently-uploaded" data-te-nav-active role="tab" aria-controls="tabs-recently-uploaded" aria-selected="true">
|
||||
{{ __('home.recently-uploaded') }} ({{ Carbon\Carbon::parse($recentlyUploaded[0]->created_at)->diffForHumans([ 'parts' => 2 ]) }})
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation" class="flex-auto text-center">
|
||||
<a href="#tabs-recently-released" class="my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white/50 dark:bg-neutral-950/50 backdrop-blur-sm dark:hover:bg-neutral-800 dark:data-[te-nav-active]:text-white"
|
||||
<a href="#tabs-recently-released" class="my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white/50 dark:bg-neutral-900/50 backdrop-blur-sm dark:hover:bg-neutral-900 dark:data-[te-nav-active]:text-white"
|
||||
data-te-toggle="pill" data-te-target="#tabs-recently-released" role="tab" aria-controls="tabs-recently-released" aria-selected="false">
|
||||
{{ __('home.recently-released') }}
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation" class="flex-auto text-center">
|
||||
<a href="#tabs-trending" class="rounded-r-lg my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white/50 dark:bg-neutral-950/50 backdrop-blur-sm dark:hover:bg-neutral-800 dark:data-[te-nav-active]:text-white"
|
||||
<a href="#tabs-trending" class="rounded-r-xl my-2 block border-x-0 border-b-2 border-t-0 border-transparent px-7 pb-3.5 pt-4 text-xs font-medium uppercase leading-tight text-neutral-500 hover:isolate hover:border-transparent hover:bg-neutral-50 focus:isolate focus:border-transparent data-[te-nav-active]:border-rose-600 data-[te-nav-active]:text-black dark:text-neutral-400 bg-white/50 dark:bg-neutral-900/50 backdrop-blur-sm dark:hover:bg-neutral-900 dark:data-[te-nav-active]:text-white"
|
||||
data-te-toggle="pill" data-te-target="#tabs-trending" role="tab" aria-controls="tabs-trending" aria-selected="false">
|
||||
{{ __('home.trending') }}
|
||||
</a>
|
||||
@@ -21,18 +21,18 @@
|
||||
|
||||
</ul>
|
||||
|
||||
@php $showThumbnails = false; @endphp
|
||||
@php $isThumbnail = false; @endphp
|
||||
|
||||
@auth
|
||||
@if(Auth::user()->home_top_design)
|
||||
@php $showThumbnails = true; @endphp
|
||||
@php $isThumbnail = true; @endphp
|
||||
@endif
|
||||
@endauth
|
||||
|
||||
<!--Tabs content-->
|
||||
<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>
|
||||
@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 ">
|
||||
<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">
|
||||
@@ -41,7 +41,7 @@
|
||||
</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">
|
||||
@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 ">
|
||||
<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">
|
||||
@@ -50,7 +50,7 @@
|
||||
</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">
|
||||
@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 ">
|
||||
<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">
|
||||
|
||||
@@ -1,47 +1,78 @@
|
||||
<x-app-layout>
|
||||
<div class="container my-24 mx-auto md:px-6 z-10 relative">
|
||||
<section class="mb-32 text-center">
|
||||
<div class="flex justify-center pb-10">
|
||||
<img src="/images/cropped-HS-1-270x270.webp" class="max-w-[150px]" alt="hstream.moe Logo" />
|
||||
<div class="container mx-auto px-4 py-12 md:py-24">
|
||||
<section class="text-center mb-16">
|
||||
<!-- Logo -->
|
||||
<div class="flex justify-center mb-8">
|
||||
<img
|
||||
src="/images/cropped-HS-1-270x270.webp"
|
||||
alt="hstream.moe Logo"
|
||||
class="max-w-[150px] w-full h-auto rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-4 lg:gap-x-12">
|
||||
<div class="mb-12 md:mb-0">
|
||||
<div class="mb-6 inline-block rounded-md bg-white dark:bg-neutral-950 p-4 text-sky-500">
|
||||
<i class="fa-solid fa-eye text-3xl"> {{ number_format($viewCount) }}</i>
|
||||
|
||||
<!-- Stats Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 md:gap-8">
|
||||
<!-- View Count Card -->
|
||||
<div class="bg-sky-300/50 dark:bg-sky-950/50 rounded-xl p-6 shadow-sm hover:shadow-md transition-shadow duration-300">
|
||||
<div class="flex justify-center mb-4">
|
||||
<i class="fa-solid fa-eye text-4xl text-sky-600 dark:text-sky-400 p-3"></i>
|
||||
</div>
|
||||
<h5 class="text-lg font-medium dark:text-neutral-300">
|
||||
<div class="text-3xl font-bold text-gray-900 dark:text-white mb-2">
|
||||
{{ number_format($viewCount) }}
|
||||
</div>
|
||||
<h5 class="text-lg font-medium text-gray-700 dark:text-neutral-300">
|
||||
total views
|
||||
</h5>
|
||||
</div>
|
||||
<div class="mb-12 md:mb-0">
|
||||
<div class="b-6 inline-block rounded-md bg-white dark:bg-neutral-950 p-4 text-sky-500">
|
||||
<i class="fa-solid fa-video text-3xl"> {{ $episodeCount }}</i>
|
||||
|
||||
<!-- Episode Count Card -->
|
||||
<div class="bg-sky-300/50 dark:bg-sky-950/50 rounded-xl p-6 shadow-sm hover:shadow-md transition-shadow duration-300">
|
||||
<div class="flex justify-center mb-4">
|
||||
<i class="fa-solid fa-video text-4xl text-sky-600 dark:text-sky-400 p-3"></i>
|
||||
</div>
|
||||
<h5 class="text-lg font-medium dark:text-neutral-300">
|
||||
<div class="text-3xl font-bold text-gray-900 dark:text-white mb-2">
|
||||
{{ $episodeCount }}
|
||||
</div>
|
||||
<h5 class="text-lg font-medium text-gray-700 dark:text-neutral-300">
|
||||
episodes on this site
|
||||
</h5>
|
||||
</div>
|
||||
<div class="mb-12 md:mb-0">
|
||||
<div class="mb-6 inline-block rounded-md bg-white dark:bg-neutral-950 p-4 text-rose-600">
|
||||
<i class="fa-solid fa-list text-3xl"> {{ $hentaiCount }}</i>
|
||||
|
||||
<!-- Hentai Count Card -->
|
||||
<div class="bg-rose-300/50 dark:bg-rose-950/50 rounded-xl p-6 shadow-sm hover:shadow-md transition-shadow duration-300">
|
||||
<div class="flex justify-center mb-4">
|
||||
<i class="fa-solid fa-list text-4xl text-rose-600 dark:text-rose-400 p-3"></i>
|
||||
</div>
|
||||
<h5 class="text-lg font-medium dark:text-neutral-300">
|
||||
<div class="text-3xl font-bold text-gray-900 dark:text-white mb-2">
|
||||
{{ $hentaiCount }}
|
||||
</div>
|
||||
<h5 class="text-lg font-medium text-gray-700 dark:text-neutral-300">
|
||||
hentais on this site
|
||||
</h5>
|
||||
</div>
|
||||
<div class="mb-12 md:mb-0">
|
||||
<div class="mb-6 inline-block rounded-md bg-white dark:bg-neutral-950 p-4 text-rose-600">
|
||||
<i class="fa-solid fa-clock text-3xl"> {{ number_format($viewCount * 6) }}</i>
|
||||
|
||||
<!-- Watch Time Card -->
|
||||
<div class="bg-rose-300/50 dark:bg-rose-950/50 rounded-xl p-6 shadow-sm hover:shadow-md transition-shadow duration-300">
|
||||
<div class="flex justify-center mb-4">
|
||||
<i class="fa-solid fa-clock text-4xl text-rose-600 dark:text-rose-400 p-3"></i>
|
||||
</div>
|
||||
<h5 class="text-lg font-medium dark:text-neutral-300">
|
||||
<div class="text-3xl font-bold text-gray-900 dark:text-white mb-2">
|
||||
{{ number_format($viewCount * 6) }}
|
||||
</div>
|
||||
<h5 class="text-lg font-medium text-gray-700 dark:text-neutral-300">
|
||||
estimated minutes of watch time
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-center dark:bg-neutral-950 bg-gray-50 rounded-xl md:m-11 hidden md:block">
|
||||
<canvas id="monthlyChart"></canvas>
|
||||
|
||||
<!-- Chart Container -->
|
||||
<div class="mt-12 mx-auto max-w-4xl">
|
||||
<div class="bg-gray-50 dark:bg-neutral-950 rounded-xl p-4 md:p-6 shadow-inner hidden sm:block">
|
||||
<canvas id="monthlyChart" class="w-full h-64 md:h-80"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@vite(['resources/js/stats.js'])
|
||||
</x-app-layout>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
@include('partials.head')
|
||||
|
||||
<body class="font-sans antialiased">
|
||||
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-900">
|
||||
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-950">
|
||||
@include('layouts.navigation')
|
||||
|
||||
<!-- Page Heading -->
|
||||
|
||||
@@ -1,77 +1,99 @@
|
||||
<footer class="bg-white z-10 rounded-lg shadow dark:bg-neutral-950 m-4 mb-0 mt-auto">
|
||||
<div class="w-full xl:max-w-[95%] 2xl:max-w-[84%] mx-auto p-4">
|
||||
<div class="sm:flex sm:items-center sm:justify-between">
|
||||
<a href="https://hstream.moe/" class="flex items-center mb-4 sm:mb-0">
|
||||
<img src="/images/cropped-HS-1-192x192.webp" class="h-8 mr-3" alt="hstream.moe Logo" />
|
||||
<span class="self-center text-2xl font-semibold whitespace-nowrap dark:text-white">hstream.moe</span>
|
||||
<footer class="bg-white z-10 rounded-xl shadow-lg dark:bg-neutral-950 m-4 mb-0 mt-auto">
|
||||
<div class="w-full max-w-7xl mx-auto px-4 py-6">
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 items-center">
|
||||
<!-- Logo -->
|
||||
<div class="flex items-center justify-center md:justify-start">
|
||||
<a href="https://hstream.moe/" class="flex items-center">
|
||||
<img src="/images/cropped-HS-1-192x192.webp"
|
||||
class="h-10 w-10 mr-3 rounded-lg object-cover"
|
||||
alt="hstream.moe Logo" />
|
||||
<span class="text-xl font-bold whitespace-nowrap text-gray-600 dark:text-white">hstream.moe</span>
|
||||
</a>
|
||||
<ul class="flex flex-wrap items-center mb-6 text-sm font-medium text-gray-500 sm:mb-0 dark:text-gray-400">
|
||||
<li>
|
||||
<a href="{{ route('contact.index') }}" class="mr-4 hover:underline md:mr-6 "><i
|
||||
class="fa-solid fa-message"></i> Contact</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ config('discord.invite_link') }}" class="mr-4 hover:underline md:mr-6 "><i
|
||||
class="fa-brands fa-discord"></i> Discord</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route('home.stats') }}" class="mr-4 hover:underline md:mr-6 "><i
|
||||
class="fa-solid fa-chart-simple"></i> Stats</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- Links to friendly sites -->
|
||||
<ul class="flex flex-wrap items-center mb-6 text-sm font-medium text-gray-500 sm:mb-0 dark:text-gray-400">
|
||||
<li>
|
||||
<a target="_blank" href="https://everythingmoe.com/"
|
||||
class="mr-4 hover:underline md:mr-6">everythingmoe.com</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://theindex.moe/"
|
||||
class="mr-4 hover:underline md:mr-6">theindex.moe</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://www.squid-board.org/"
|
||||
class="mr-4 hover:underline md:mr-6">squidboard.org</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://hentaizilla.com/"
|
||||
class="hover:underline md:mr-6">hentaizilla.com</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://hentaipulse.com/"
|
||||
class="hover:underline md:mr-6">hentaipulse.com</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://hentaisites.com/"
|
||||
class="hover:underline md:mr-6">hentaisites.com</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://zhentube.com/"
|
||||
class="hover:underline md:mr-6">zhentube.com</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="flex flex-wrap items-center mb-6 text-sm font-medium text-gray-500 sm:mb-0 dark:text-gray-400">
|
||||
<li>
|
||||
<a class="hover:underline md:mr-6 cursor-pointer" data-te-toggle="modal"
|
||||
data-te-target="#modalLanguage">Language</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Main Navigation -->
|
||||
<div class="flex justify-center">
|
||||
<ul class="flex flex-wrap items-center gap-4 text-sm font-medium text-gray-600 dark:text-gray-300">
|
||||
<li>
|
||||
<a href="{{ route('contact.index') }}"
|
||||
class="flex items-center gap-1 hover:text-blue-600 transition-colors">
|
||||
<i class="fa-solid fa-message"></i> Contact
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ config('discord.invite_link') }}"
|
||||
class="flex items-center gap-1 hover:text-blue-600 transition-colors">
|
||||
<i class="fa-brands fa-discord"></i> Discord
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ route('home.stats') }}"
|
||||
class="flex items-center gap-1 hover:text-blue-600 transition-colors">
|
||||
<i class="fa-solid fa-chart-simple"></i> Stats
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Language Selector -->
|
||||
<div class="flex justify-center md:justify-end">
|
||||
<button data-te-toggle="modal"
|
||||
data-te-target="#modalLanguage"
|
||||
class="flex items-center gap-1 text-sm font-medium text-gray-600 hover:text-blue-600 transition-colors dark:text-gray-300">
|
||||
<i class="fa-solid fa-globe"></i> Language
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Friendly Sites -->
|
||||
<div class="mt-6 pt-6 border-t border-gray-200 dark:border-gray-700">
|
||||
<h3 class="text-sm font-semibold text-gray-500 dark:text-gray-400 mb-3 text-center">Friendly Sites</h3>
|
||||
<div class="flex flex-wrap justify-center gap-3">
|
||||
@foreach([
|
||||
'everythingmoe.com' => 'https://everythingmoe.com/',
|
||||
'theindex.moe' => 'https://theindex.moe/',
|
||||
'squidboard.org' => 'https://www.squid-board.org/',
|
||||
'hentaizilla.com' => 'https://hentaizilla.com/',
|
||||
'hentaipulse.com' => 'https://hentaipulse.com/',
|
||||
'hentaisites.com' => 'https://hentaisites.com/',
|
||||
'zhentube.com' => 'https://zhentube.com/'
|
||||
] as $name => $url)
|
||||
<a href="{{ $url }}"
|
||||
target="_blank"
|
||||
class="text-sm text-gray-600 hover:text-blue-600 transition-colors dark:text-gray-300">
|
||||
{{ $name }}
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Footer Info -->
|
||||
<div class="m-4 w-full max-w-7xl mx-auto">
|
||||
<div class="text-xs text-gray-500 text-center dark:text-gray-400">
|
||||
<p>Render time: {{ number_format(microtime(true) - (defined('LARAVEL_START') ? LARAVEL_START : request()->server('REQUEST_TIME_FLOAT')), 3) }} seconds |
|
||||
Memory usage: {{ number_format(memory_get_peak_usage(true) / 1048576, 2) }} MB |
|
||||
Git: <a href="https://gitea.hstream.moe/w33b/hstream/commits/branch/main"
|
||||
target="_blank"
|
||||
class="hover:text-blue-600 transition-colors">
|
||||
{{ \App\Helpers\GitHelper::shortCommit() }}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SweetAlert Scripts -->
|
||||
@if (!Session::has('alert.config'))
|
||||
<script src="{{ asset('vendor/sweetalert/sweetalert.all.js') }}"></script>
|
||||
@endif
|
||||
@if (config('sweetalert.theme') != 'default')
|
||||
<link href="https://cdn.jsdelivr.net/npm/@sweetalert2/theme-{{ config('sweetalert.theme') }}"
|
||||
rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/@sweetalert2/theme-{{ config('sweetalert.theme') }}" rel="stylesheet">
|
||||
@endif
|
||||
@include('sweetalert::alert')
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Modals -->
|
||||
@include('modals.language-selector')
|
||||
|
||||
<div class="m-2 w-full mx-auto">
|
||||
<div class="text-sm text-gray-500 text-center">
|
||||
<p>Render time: {{ number_format(microtime(true) - (defined('LARAVEL_START') ? LARAVEL_START : request()->server('REQUEST_TIME_FLOAT')), 3) }} seconds | Memory usage: {{ number_format(memory_get_peak_usage(true) / 1048576, 2) }} MB | Git: <a href="https://gitea.hstream.moe/w33b/hstream/commits/branch/main" target="_blank">{{ \App\Helpers\GitHelper::shortCommit() }}</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Thumbnail hover -->
|
||||
@vite(['resources/js/preview.js'])
|
||||
@@ -4,7 +4,7 @@
|
||||
@include('partials.head')
|
||||
|
||||
<body class="font-sans antialiased">
|
||||
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100 dark:bg-neutral-900">
|
||||
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100 dark:bg-neutral-950">
|
||||
<div>
|
||||
<a href="/">
|
||||
<x-application-logo class="w-24 h-24 fill-current text-gray-500" />
|
||||
|
||||
@@ -1,121 +1,253 @@
|
||||
<div>
|
||||
<div class="flex" id="comment-{{ $comment->id }}">
|
||||
<div class="flex-shrink-0 mr-4">
|
||||
<img class="h-10 w-10 rounded-full" src="{{ $comment->user->getAvatar() }}" alt="{{ $comment->user->name }}">
|
||||
<div id="comment-{{ $comment->id }}">
|
||||
|
||||
<div class="group flex gap-4">
|
||||
|
||||
{{-- Avatar --}}
|
||||
<div class="shrink-0">
|
||||
@if($comment->isDeletedByModerator())
|
||||
<img
|
||||
class="h-10 w-10 rounded-full object-cover opacity-60"
|
||||
src="{{ asset('images/default-avatar.webp') }}"
|
||||
alt="Deleted comment"
|
||||
>
|
||||
@else
|
||||
<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
|
||||
</div>
|
||||
<div class="flex-grow">
|
||||
<div class="flex gap-2">
|
||||
<p class="font-medium text-gray-900 dark:text-gray-100">{{ $comment->user->name }}</p>
|
||||
|
||||
{{-- Content --}}
|
||||
<div class="min-w-0 flex-1">
|
||||
|
||||
<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">
|
||||
|
||||
{{-- Header --}}
|
||||
<div class="mb-3 flex flex-wrap items-center gap-2">
|
||||
|
||||
@if($comment->isDeletedByModerator())
|
||||
|
||||
<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))
|
||||
<a data-te-toggle="tooltip" title="Admin"><i class="fa-solid fa-crown text-yellow-600"></i></a>
|
||||
<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))
|
||||
<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>
|
||||
<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>
|
||||
<div class="mt-1 flex-grow w-full">
|
||||
|
||||
{{-- 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">
|
||||
<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>
|
||||
|
||||
<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="mt-2 text-sm text-red-500">{{ $message }}</p>
|
||||
<p class="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
|
||||
|
||||
<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
|
||||
<div class="text-gray-700 dark:text-gray-200">
|
||||
{!! $comment->presenter()->markdownBody() !!}
|
||||
</div>
|
||||
<div class="mt-2 space-x-2 flex flex-row">
|
||||
<span class="text-gray-500 dark:text-gray-300">
|
||||
@endif
|
||||
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
{{-- Footer --}}
|
||||
<div class="mt-4 flex flex-wrap items-center gap-4 text-sm">
|
||||
|
||||
<span class="text-neutral-500 dark:text-neutral-400">
|
||||
{{ $comment->presenter()->relativeCreatedAt() }}
|
||||
</span>
|
||||
|
||||
{{-- Like --}}
|
||||
@guest
|
||||
<span data-te-toggle="tooltip" title="Please login to like the episode" class="text-gray-800 cursor-pointer dark:text-gray-200">
|
||||
<i class="fa-regular fa-heart"></i> {{ $comment->likeCount() }}
|
||||
<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
|
||||
<!-- Like Button -->
|
||||
<button class="text-gray-800 dark:text-gray-200 leading-tight cursor-pointer whitespace-nowrap" wire:click="like">
|
||||
<button
|
||||
wire:click="like"
|
||||
class="flex items-center gap-1 text-neutral-500 transition hover:text-rose-600 dark:text-neutral-400 dark:hover:text-rose-400"
|
||||
>
|
||||
@if ($liked)
|
||||
<i class="fa-solid fa-heart text-rose-600"></i> {{ $likeCount }}
|
||||
<i class="fa-solid fa-heart text-rose-600"></i>
|
||||
@else
|
||||
<i class="fa-solid fa-heart"></i> {{ $likeCount }}
|
||||
<i class="fa-regular fa-heart"></i>
|
||||
@endif
|
||||
|
||||
{{ $likeCount }}
|
||||
</button>
|
||||
@endauth
|
||||
|
||||
{{-- Actions --}}
|
||||
@auth
|
||||
|
||||
@if ($comment->depth() < 2)
|
||||
<button wire:click="$toggle('isReplying')" type="button" class="text-gray-900 dark:text-gray-100 font-medium">
|
||||
<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')" type="button" class="text-gray-900 dark:text-gray-100 font-medium">
|
||||
<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="{
|
||||
<button
|
||||
x-data="{
|
||||
confirmCommentDeletion () {
|
||||
if (window.confirm('Are you sure you want to delete this comment?')) {
|
||||
if (window.confirm('Delete this comment?')) {
|
||||
@this.call('deleteComment');
|
||||
}
|
||||
}
|
||||
}"
|
||||
@click="confirmCommentDeletion"
|
||||
type="button"
|
||||
class="text-gray-900 dark:text-gray-100 font-medium"
|
||||
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>
|
||||
|
||||
<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
|
||||
|
||||
{{-- 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>
|
||||
@@ -1,60 +1,93 @@
|
||||
<section>
|
||||
<div class="bg-white dark:bg-neutral-800 shadow sm:rounded-lg sm:overflow-hidden">
|
||||
<div class="divide-y divide-gray-200 dark:divide-gray-400/40">
|
||||
<div class="px-4 py-5 sm:px-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-200">Comments</h2>
|
||||
<div id="comments" class="overflow-hidden rounded-2xl border border-neutral-200 bg-white shadow-sm dark:border-neutral-800 dark:bg-neutral-900">
|
||||
|
||||
{{-- 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>
|
||||
<!-- Comment Input -->
|
||||
<div class="bg-gray-50 dark:bg-neutral-800 px-4 py-6 sm:px-6">
|
||||
|
||||
{{-- Comment Form --}}
|
||||
<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
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0 mr-4">
|
||||
<img class="h-10 w-10 rounded-full" src="{{ auth()->user()->getAvatar() }}" alt="{{ auth()->user()->name }}">
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<form wire:submit.prevent="postComment">
|
||||
<div class="flex gap-4">
|
||||
<img
|
||||
class="h-11 w-11 rounded-full object-cover ring-2 ring-white dark:ring-neutral-800"
|
||||
src="{{ auth()->user()->getAvatar() }}"
|
||||
alt="{{ auth()->user()->name }}"
|
||||
>
|
||||
|
||||
<div class="flex-1">
|
||||
<form wire:submit.prevent="postComment" class="space-y-4">
|
||||
|
||||
<div>
|
||||
<label for="comment" class="sr-only">Comment body</label>
|
||||
<textarea id="comment" name="comment" rows="3"
|
||||
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
|
||||
@error('newCommentState.body') border-red-500 @enderror"
|
||||
placeholder="Write something" wire:model.defer="newCommentState.body"></textarea>
|
||||
<label for="comment" class="sr-only">
|
||||
Comment body
|
||||
</label>
|
||||
|
||||
<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')
|
||||
<p class="mt-2 text-sm text-red-500">{{ $message }}</p>
|
||||
<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
|
||||
|
||||
<div class="flex justify-end">
|
||||
<button
|
||||
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>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endauth
|
||||
|
||||
@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">
|
||||
<p class="text-sm text-neutral-600 dark:text-neutral-400">
|
||||
Log in to join the discussion.
|
||||
</p>
|
||||
</div>
|
||||
@endguest
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Comments -->
|
||||
<div class="px-4 py-6 sm:px-6">
|
||||
<div class="space-y-8">
|
||||
{{-- 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
|
||||
<p class="text-gray-900 dark:text-gray-200">No comments yet.</p>
|
||||
|
||||
<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>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
@@ -8,10 +8,18 @@
|
||||
</div>
|
||||
<div class="flex flex-col text-center w-full">
|
||||
@if($fillNumbers)
|
||||
@if($version)
|
||||
<p class="text-lg">Episode {{ str_pad($episodeNumber, 2, '0', STR_PAD_LEFT) }} ({{ $version }})</p>
|
||||
@else
|
||||
<p class="text-lg">Episode {{ str_pad($episodeNumber, 2, '0', STR_PAD_LEFT) }}</p>
|
||||
@endif
|
||||
@else
|
||||
@if($version)
|
||||
<p class="text-lg">Episode {{ $episodeNumber }} ({{ $version }})</p>
|
||||
@else
|
||||
<p class="text-lg">Episode {{ $episodeNumber }}</p>
|
||||
@endif
|
||||
@endif
|
||||
<p class="text-xs">{{ $fileExtension }} MKV {{ $fileSize ?? '' }}</p>
|
||||
<p class="text-xs" id="count-{{ $downloadId }}">Downloaded {{ $downloadCount }} times</p>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
<div>
|
||||
@if (Auth::check())
|
||||
<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
|
||||
<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">
|
||||
@if ($liked)
|
||||
<i class="fa-solid fa-heart pr-[4px] text-rose-600"></i> {{ $likeCount }}
|
||||
@else
|
||||
<i class="fa-regular fa-heart pr-[4px]"></i> {{ $likeCount }}
|
||||
@endif
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="py-24">
|
||||
<div class="py-10">
|
||||
<div class="mx-auto sm:px-6 lg:px-8 space-y-6 max-w-[100%] xl:max-w-[95%] 2xl:max-w-[90%]">
|
||||
@include('livewire.partials.search-filter')
|
||||
</div>
|
||||
@@ -24,5 +24,4 @@
|
||||
</div>
|
||||
{{ $episodes->appends(['tags' => $selectedtags])->links('pagination::tailwind') }}
|
||||
</div>
|
||||
@vite(['resources/js/preview.js'])
|
||||
</div>
|
||||
|
||||
@@ -1,90 +1,141 @@
|
||||
<!-- Search Filter -->
|
||||
<!-- Search Filters -->
|
||||
<div>
|
||||
<div class="p-4 sm:p-8 bg-white/40 dark:bg-neutral-950/40 backdrop-blur shadow sm:rounded-lg">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4">
|
||||
<div class="rounded-2xl border border-neutral-200/70 bg-white/80 p-4 shadow-sm backdrop-blur-xl dark:border-neutral-800 dark:bg-neutral-950/70 space-y-4">
|
||||
|
||||
<!-- Title -->
|
||||
<div>
|
||||
<label for="live-search" class="mb-2 text-sm font-medium text-gray-900 sr-only dark:text-white">Search</label>
|
||||
<div class="relative right-2 left-0 sm:left-2 transition-all">
|
||||
<div class="absolute inset-y-0 left-2 flex items-center pl-3 pointer-events-none">
|
||||
<svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
|
||||
<!-- Filters Grid -->
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-5">
|
||||
|
||||
<!-- Search -->
|
||||
<div class="xl:col-span-2">
|
||||
<label for="live-search" class="sr-only">
|
||||
{{ __('search.search-hentai') }}
|
||||
</label>
|
||||
|
||||
<div class="relative">
|
||||
<!-- Search Icon -->
|
||||
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-4">
|
||||
<svg class="h-5 w-5 text-neutral-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<input wire:model.live.debounce.600ms="search" type="search" id="live-search" class="block w-full p-4 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-rose-800 focus:border-rose-900 dark:bg-neutral-900 dark:border-neutral-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-rose-800 dark:focus:border-rose-900" placeholder="{{ __('search.search-hentai') }}" required>
|
||||
<!-- Input -->
|
||||
<input
|
||||
wire:model.live.debounce.500ms="search"
|
||||
type="search"
|
||||
id="live-search"
|
||||
placeholder="{{ __('search.search-hentai') }}"
|
||||
class="w-full rounded-xl border border-neutral-300 bg-white py-5 pl-12 pr-12 text-sm text-neutral-900 shadow-sm transition focus:border-rose-500 focus:outline-none focus:ring-4 focus:ring-rose-500/20 dark:border-neutral-700 dark:bg-neutral-900 dark:text-white dark:placeholder-neutral-500"
|
||||
/>
|
||||
|
||||
<div class="absolute right-0 top-[11px]" wire:loading>
|
||||
<svg aria-hidden="true" class="inline w-8 h-8 mr-2 text-gray-200 animate-spin dark:text-gray-600 fill-pink-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor" />
|
||||
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill" />
|
||||
<!-- Loading -->
|
||||
<div wire:loading.class="opacity-100" class="opacity-0">
|
||||
<div class="absolute inset-y-0 right-3 flex items-center">
|
||||
<svg class="h-5 w-5 animate-spin text-rose-500" viewBox="0 0 24 24" fill="none">
|
||||
<circle class="opacity-20" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-90" fill="currentColor"
|
||||
d="M22 12a10 10 0 0 1-10 10V18a6 6 0 0 0 6-6h4Z">
|
||||
</path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Genres -->
|
||||
<div>
|
||||
<div class="relative right-2 left-0 sm:left-2 transition-all">
|
||||
<div class="absolute inset-y-0 left-2 flex items-center pl-3 pointer-events-none">
|
||||
<i class="fa-solid fa-sliders text-gray-500 dark:text-gray-400"></i>
|
||||
</div>
|
||||
<p data-te-toggle="modal" data-te-target="#modalGenres" data-te-ripple-init data-te-ripple-color="light" id="genres-filter" class="block cursor-pointer w-full p-4 pl-10 text-sm text-gray-500 dark:text-gray-400 border border-gray-300 rounded-lg bg-gray-50 focus:ring-rose-800 focus:border-rose-900 dark:bg-neutral-900 dark:border-neutral-600 dark:placeholder-gray-400 dark:focus:ring-rose-800 dark:focus:border-rose-900">
|
||||
<button
|
||||
type="button"
|
||||
data-te-toggle="modal"
|
||||
data-te-target="#modalGenres"
|
||||
class="group flex items-center gap-3 rounded-xl border border-neutral-300 bg-white px-4 py-3 text-left shadow-sm transition hover:border-rose-400 hover:bg-rose-50 dark:border-neutral-700 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
<i class="fa-solid fa-sliders text-neutral-400 group-hover:text-rose-500"></i>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<span class="text-xs font-medium uppercase tracking-wide text-neutral-400">
|
||||
Genres
|
||||
</span>
|
||||
|
||||
<span class="text-sm text-neutral-700 dark:text-neutral-200">
|
||||
@if($tagcount === 0)
|
||||
Select Genres
|
||||
@elseif($tagcount === 1)
|
||||
Selected {{$tagcount }} Genre
|
||||
@elseif($tagcount > 1)
|
||||
Selected {{$tagcount }} Genres
|
||||
1 Genre Selected
|
||||
@else
|
||||
{{ $tagcount }} Genres Selected
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<!-- Genres Blacklist -->
|
||||
<div>
|
||||
<div class="relative right-2 left-0 sm:left-2 transition-all">
|
||||
<div class="absolute inset-y-0 left-2 flex items-center pl-3 pointer-events-none">
|
||||
<i class="fa-solid fa-shield text-gray-500 dark:text-gray-400"></i>
|
||||
</div>
|
||||
<p data-te-toggle="modal" data-te-target="#modalBlacklist" data-te-ripple-init data-te-ripple-color="light" id="blacklist-filter" class="block cursor-pointer w-full p-4 pl-10 text-sm text-gray-500 dark:text-gray-400 border border-gray-300 rounded-lg bg-gray-50 focus:ring-rose-800 focus:border-rose-900 dark:bg-neutral-900 dark:border-neutral-600 dark:placeholder-gray-400 dark:focus:ring-rose-800 dark:focus:border-rose-900">
|
||||
<!-- Blacklist -->
|
||||
<button
|
||||
type="button"
|
||||
data-te-toggle="modal"
|
||||
data-te-target="#modalBlacklist"
|
||||
class="group flex items-center gap-3 rounded-xl border border-neutral-300 bg-white px-4 py-3 text-left shadow-sm transition hover:border-rose-400 hover:bg-rose-50 dark:border-neutral-700 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
<i class="fa-solid fa-shield text-neutral-400 group-hover:text-rose-500"></i>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<span class="text-xs font-medium uppercase tracking-wide text-neutral-400">
|
||||
Blacklist
|
||||
</span>
|
||||
|
||||
<span class="text-sm text-neutral-700 dark:text-neutral-200">
|
||||
@if($blacklistcount === 0)
|
||||
Select Blacklist
|
||||
@elseif($blacklistcount === 1)
|
||||
Selected {{ $blacklistcount }} Blacklist Item
|
||||
@elseif($blacklistcount > 1)
|
||||
Selected {{ $blacklistcount }} Blacklist Items
|
||||
1 Item Selected
|
||||
@else
|
||||
{{ $blacklistcount }} Items Selected
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<!-- Studios -->
|
||||
<div>
|
||||
<div class="relative right-2 left-0 sm:left-2 transition-all">
|
||||
<div class="absolute inset-y-0 left-2 flex items-center pl-3 pointer-events-none">
|
||||
<i class="fa-solid fa-microphone-lines text-gray-500 dark:text-gray-400"></i>
|
||||
</div>
|
||||
<p data-te-toggle="modal" data-te-target="#modalStudios" data-te-ripple-init data-te-ripple-color="light" id="studios-filter" class="block cursor-pointer w-full p-4 pl-10 text-sm text-gray-500 dark:text-gray-400 border border-gray-300 rounded-lg bg-gray-50 focus:ring-rose-800 focus:border-rose-900 dark:bg-neutral-900 dark:border-neutral-600 dark:placeholder-gray-400 dark:focus:ring-rose-800 dark:focus:border-rose-900">
|
||||
<button
|
||||
type="button"
|
||||
data-te-toggle="modal"
|
||||
data-te-target="#modalStudios"
|
||||
class="group flex items-center gap-3 rounded-xl border border-neutral-300 bg-white px-4 py-3 text-left shadow-sm transition hover:border-rose-400 hover:bg-rose-50 dark:border-neutral-700 dark:bg-neutral-900 dark:hover:bg-neutral-800"
|
||||
>
|
||||
<i class="fa-solid fa-microphone-lines text-neutral-400 group-hover:text-rose-500"></i>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<span class="text-xs font-medium uppercase tracking-wide text-neutral-400">
|
||||
Studios
|
||||
</span>
|
||||
|
||||
<span class="text-sm text-neutral-700 dark:text-neutral-200">
|
||||
@if($studiocount === 0)
|
||||
Select Studios
|
||||
@elseif($studiocount === 1)
|
||||
Selected {{ $studiocount }} Studio
|
||||
@elseif($studiocount > 1)
|
||||
Selected {{ $studiocount }} Studios
|
||||
1 Studio Selected
|
||||
@else
|
||||
{{ $studiocount }} Studios Selected
|
||||
@endif
|
||||
</p>
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Ordering -->
|
||||
<div class="grid grid-cols-2">
|
||||
<div class="relative right-2 left-0 sm:left-2 transition-all">
|
||||
<div class="absolute inset-y-0 left-2 flex items-center pl-3 pointer-events-none">
|
||||
<i class="fa-solid fa-sort text-gray-500 dark:text-gray-400"></i>
|
||||
</div>
|
||||
<select wire:model.live="order" class="block w-full p-4 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-rose-800 focus:border-rose-900 dark:bg-neutral-900 dark:border-neutral-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-rose-800 dark:focus:border-rose-900">
|
||||
<!-- Bottom Controls -->
|
||||
<div class="mt-4 flex flex-col gap-4 border-t border-neutral-200 pt-4 dark:border-neutral-800 lg:flex-row lg:items-center lg:justify-between">
|
||||
|
||||
<!-- Selects -->
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
|
||||
<!-- Order -->
|
||||
<div class="relative">
|
||||
<i class="fa-solid fa-sort pointer-events-none absolute left-4 top-1/2 -translate-y-1/2 text-neutral-400"></i>
|
||||
|
||||
<select
|
||||
wire:model.live="order"
|
||||
class="w-full appearance-none rounded-xl border border-neutral-300 bg-white py-3 pl-11 pr-10 text-sm text-neutral-900 shadow-sm transition focus:border-rose-500 focus:outline-none focus:ring-4 focus:ring-rose-500/20 dark:border-neutral-700 dark:bg-neutral-900 dark:text-white"
|
||||
>
|
||||
<option value="az">A-Z</option>
|
||||
<option value="za">Z-A</option>
|
||||
<option value="recently-uploaded">{{ __('home.recently-uploaded') }}</option>
|
||||
@@ -95,28 +146,40 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="relative right-2 left-0 ml-2 sm:left-2 transition-all">
|
||||
<div class="absolute inset-y-0 left-2 flex items-center pl-3 pointer-events-none">
|
||||
<i class="fa-solid fa-list text-gray-500 dark:text-gray-400"></i>
|
||||
</div>
|
||||
<select wire:model.live="view" class="block w-full p-4 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-rose-800 focus:border-rose-900 dark:bg-neutral-900 dark:border-neutral-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-rose-800 dark:focus:border-rose-900">
|
||||
<!-- View -->
|
||||
<div class="relative">
|
||||
<i class="fa-solid fa-list pointer-events-none absolute left-4 top-1/2 -translate-y-1/2 text-neutral-400"></i>
|
||||
|
||||
<select
|
||||
wire:model.live="view"
|
||||
class="w-full appearance-none rounded-xl border border-neutral-300 bg-white py-3 pl-11 pr-10 text-sm text-neutral-900 shadow-sm transition focus:border-rose-500 focus:outline-none focus:ring-4 focus:ring-rose-500/20 dark:border-neutral-700 dark:bg-neutral-900 dark:text-white"
|
||||
>
|
||||
<option value="thumbnail">Thumbnail</option>
|
||||
<option value="poster">Poster</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Auth Options -->
|
||||
@auth
|
||||
<div class="float-right pt-1">
|
||||
<input class="w-4 h-4 text-rose-600 bg-gray-100 border-gray-300 rounded focus:ring-rose-500 dark:focus:ring-rose-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
|
||||
type="checkbox" wire:model.live="hideWatched" value="true" id="checkBoxHideWatched" />
|
||||
<label class="inline-block hover:cursor-pointer dark:text-white" for="checkBoxHideWatched">
|
||||
Hide watched
|
||||
<label
|
||||
for="checkBoxHideWatched"
|
||||
class="flex cursor-pointer items-center gap-3 text-sm text-neutral-700 dark:text-neutral-300"
|
||||
>
|
||||
<input
|
||||
id="checkBoxHideWatched"
|
||||
type="checkbox"
|
||||
wire:model.live="hideWatched"
|
||||
class="h-4 w-4 rounded border-neutral-300 text-rose-600 focus:ring-rose-500 dark:border-neutral-700 dark:bg-neutral-800"
|
||||
/>
|
||||
|
||||
<span>Hide watched</span>
|
||||
</label>
|
||||
</div>
|
||||
@endauth
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modals -->
|
||||
@include('modals.filter-genres')
|
||||
@include('modals.filter-studios')
|
||||
@include('modals.filter-blacklist')
|
||||
|
||||
@@ -1,86 +1,3 @@
|
||||
<div wire:key="episode-{{ $episode->id }}">
|
||||
@if ($searchIsJpn)
|
||||
<div class="relative p-1 mb-14 w-full transition duration-300 ease-in-out md:p-2 md:hover:-translate-y-1 md:hover:scale-110"
|
||||
data-thumbs="{{ optional($episode->gallery)->pluck('thumbnail_url') }}">
|
||||
@else
|
||||
<div class="relative p-1 mb-8 w-full transition duration-300 ease-in-out md:p-2 md:hover:-translate-y-1 md:hover:scale-110"
|
||||
data-thumbs="{{ optional($episode->gallery)->pluck('thumbnail_url') }}">
|
||||
@endif
|
||||
<a class="hover:text-blue-600" href="{{ route('hentai.index', ['title' => $episode->slug]) }}">
|
||||
<div class="absolute w-[95%] top-[38%] text-center z-10">
|
||||
<svg aria-hidden="true"
|
||||
class="inline mr-2 w-8 h-8 text-gray-200 animate-spin dark:text-gray-600 fill-pink-600"
|
||||
viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
||||
fill="currentFill" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
@switch(true)
|
||||
@case($view === 'thumbnail')
|
||||
<img alt="{{ $episode->title }} - {{ $episode->episode }}" loading="lazy" width="500"
|
||||
class="block object-cover object-center relative z-20 rounded-lg aspect-video"
|
||||
src="{{ optional($episode->gallery->first())->thumbnail_url }}">
|
||||
@if ($episode->hasAutoTrans())
|
||||
<p
|
||||
class="absolute right-1 md:right-2 bottom-1 md:bottom-2 bg-blue-600/80 !text-white rounded-tl-lg rounded-br-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||
<i class="fa-regular fa-closed-captioning"></i> Multi-Subs
|
||||
</p>
|
||||
@endif
|
||||
@break
|
||||
|
||||
@case($view === 'poster')
|
||||
<img alt="{{ $episode->title }} - {{ $episode->episode }}" loading="lazy" width="400"
|
||||
class="block relative rounded-lg object-cover object-center aspect-[11/16] z-20"
|
||||
src="{{ $episode->cover_url }}">
|
||||
@break
|
||||
|
||||
@endswitch
|
||||
|
||||
@php $problematic = cache()->rememberForever('episodeProblematic'.$episode->id, fn () => $episode->getProblematicTags()); @endphp
|
||||
@if (!empty($problematic))
|
||||
<p
|
||||
class="absolute left-1 md:left-2 top-1 md:top-2 bg-red-700/70 !text-white rounded-br-lg rounded-tl-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||
<i class="fa-solid fa-triangle-exclamation"></i> {{ $problematic }}
|
||||
</p>
|
||||
@endif
|
||||
|
||||
@if (auth()->check() && $episode->userWatched(auth()->user()->id))
|
||||
<p
|
||||
class="absolute right-1 md:right-2 top-1 md:top-2 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 md:left-2 bottom-1 md:bottom-2 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 md:right-2 top-1 md:top-2 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 md:left-2 bottom-1 md:bottom-2 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
|
||||
|
||||
<div class="absolute w-[95%] grid grid-cols-1 text-center">
|
||||
@if ($searchIsJpn)
|
||||
<p class="text-sm text-center text-black dark:text-white">{{ $episode->title }}
|
||||
({{ $episode->title_jpn }}) - {{ $episode->episode }}</p>
|
||||
@else
|
||||
<p class="text-sm text-center text-black dark:text-white">{{ $episode->title }} -
|
||||
{{ $episode->episode }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<x-episode-cover :episode="$episode" :view="$view" :displayjapanese="$searchIsJpn" />
|
||||
</div>
|
||||
|
||||
@@ -24,5 +24,4 @@
|
||||
</div>
|
||||
{{ $episodes->appends(['tags' => $selectedtags])->links('pagination::tailwind') }}
|
||||
</div>
|
||||
@vite(['resources/js/preview.js'])
|
||||
</div
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@php
|
||||
$isActive = auth()->user()->hasRole(\App\Enums\UserRole::SUPPORTER);
|
||||
@endphp
|
||||
|
||||
<span class="inline-flex items-center gap-2 rounded-full px-3 py-1 text-sm font-medium border
|
||||
{{ $isActive ? 'bg-green-500/10 text-green-300 border-green-500/20' : 'bg-red-500/10 text-red-300 border-red-500/20' }}">
|
||||
<span class="h-2 w-2 rounded-full {{ $isActive ? 'bg-green-400' : 'bg-red-400' }}"></span>
|
||||
|
||||
@@ -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>
|
||||
@@ -12,10 +12,10 @@
|
||||
</p>
|
||||
</div>
|
||||
<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)
|
||||
<div class="mt-2 mb-6 ml-4">
|
||||
<x-episode-thumbnail :episode="$episode->episode" />
|
||||
<x-episode-cover :episode="$episode->episode" view="thumbnail" />
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@@ -25,4 +25,4 @@
|
||||
</ol>
|
||||
{{ $watched->links('pagination::tailwind') }}
|
||||
</div>
|
||||
</div
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
@auth
|
||||
<!--Verically centered modal-->
|
||||
<div data-te-modal-init class="fixed left-0 top-0 z-[1055] hidden h-full w-full overflow-y-auto overflow-x-hidden outline-none" id="modalAddToPlaylist" tabindex="-1" aria-labelledby="Playlist" aria-modal="true" role="dialog">
|
||||
<div data-te-modal-dialog-ref class="pointer-events-none relative flex min-h-[calc(100%-1rem)] w-auto translate-y-[-50px] items-center opacity-0 transition-all duration-300 ease-in-out min-[576px]:mx-auto min-[576px]:mt-7 min-[576px]:min-h-[calc(100%-3.5rem)] min-[576px]:max-w-[95%] md:min-[576px]:max-w-[90%] lg:min-[576px]:max-w-[80%] xl:min-[576px]:max-w-[70%] 2xl:min-[576px]:max-w-[30%]">
|
||||
<div class="pointer-events-auto relative flex w-full flex-col rounded-md border-none bg-white bg-clip-padding text-current shadow-lg outline-none dark:bg-neutral-800">
|
||||
<div
|
||||
data-te-modal-init
|
||||
id="modalAddToPlaylist"
|
||||
tabindex="-1"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="fixed inset-0 z-[1055] hidden overflow-y-auto bg-black/60 backdrop-blur-sm"
|
||||
>
|
||||
<div data-te-modal-dialog-ref class="flex min-h-screen items-center justify-center p-4">
|
||||
<div class="relative w-full max-w-2xl overflow-hidden rounded-2xl border border-neutral-200 bg-white shadow-2xl dark:border-neutral-700 dark:bg-neutral-900">
|
||||
<x-modal-header :title="__('Add to Playlist')" />
|
||||
|
||||
<!--Modal body-->
|
||||
@@ -26,11 +32,16 @@
|
||||
<x-input-error :messages="$errors->get('playlist')" class="mt-2" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4">
|
||||
<a id="playlist-cancel" class="inline-block cursor-pointer rounded bg-primary-100 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-primary-700 transition duration-150 ease-in-out hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200" data-te-modal-dismiss data-te-ripple-init data-te-ripple-color="light">
|
||||
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4 gap-3">
|
||||
<a
|
||||
data-te-modal-dismiss
|
||||
id="playlist-cancel"
|
||||
class="cursor-pointer rounded-xl border border-neutral-300 px-5 py-2.5 text-sm font-medium text-neutral-700 transition hover:bg-neutral-100 dark:border-neutral-600 dark:text-neutral-200 dark:hover:bg-neutral-800">
|
||||
Cancel
|
||||
</a>
|
||||
<a id="playlist-add" class="ml-1 cursor-pointer inline-block rounded bg-rose-600 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600" data-te-ripple-init data-te-ripple-color="light">
|
||||
<a
|
||||
id="playlist-add"
|
||||
class="cursor-pointer rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700">
|
||||
Add
|
||||
</a>
|
||||
</div>
|
||||
@@ -52,7 +63,9 @@
|
||||
</div>
|
||||
|
||||
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4">
|
||||
<a id="playlist-create-and-add" class="ml-1 cursor-pointer inline-block rounded bg-rose-600 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600" data-te-ripple-init data-te-ripple-color="light">
|
||||
<a
|
||||
id="playlist-create-and-add"
|
||||
class="cursor-pointer rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700">
|
||||
Create and Add Episode
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
<!--Verically centered modal-->
|
||||
<div
|
||||
data-te-modal-init
|
||||
class="fixed left-0 top-0 z-[1055] hidden h-full w-full overflow-y-auto overflow-x-hidden outline-none"
|
||||
id="comment-modal-{{ $comment->getKey() }}"
|
||||
tabindex="-1"
|
||||
aria-labelledby="exampleModalCenterTitle"
|
||||
aria-modal="true"
|
||||
role="dialog">
|
||||
<div data-te-modal-dialog-ref class="pointer-events-none relative flex min-h-[calc(100%-1rem)] w-auto translate-y-[-50px] items-center opacity-0 transition-all duration-300 ease-in-out min-[576px]:mx-auto min-[576px]:mt-7 min-[576px]:min-h-[calc(100%-3.5rem)] min-[576px]:max-w-[95%] md:min-[576px]:max-w-[90%] lg:min-[576px]:max-w-[80%] xl:min-[576px]:max-w-[70%] 2xl:min-[576px]:max-w-[40%]">
|
||||
<div class="pointer-events-auto relative flex w-full flex-col rounded-md border-none bg-white bg-clip-padding text-current shadow-lg outline-none dark:bg-neutral-800">
|
||||
<x-modal-header :title="__('comments::comments.edit_comment')" />
|
||||
|
||||
<!--Modal body-->
|
||||
<div class="relative p-4">
|
||||
|
||||
<form method="POST" action="{{ route('comments.update', $comment->getKey()) }}">
|
||||
@method('PUT')
|
||||
@csrf
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label class="mb-2 leading-tight text-gray-800 dark:text-gray-200 w-full" for="message">@lang('comments::comments.update_your_message_here')</label>
|
||||
<textarea 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" name="message" rows="3">{{ $comment->comment }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4">
|
||||
<button
|
||||
type="button"
|
||||
id="modal-blacklist-filter-close-bottom"
|
||||
class="inline-block rounded bg-primary-100 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-primary-700 transition duration-150 ease-in-out hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200"
|
||||
data-te-modal-dismiss
|
||||
data-te-ripple-init
|
||||
data-te-ripple-color="light">
|
||||
@lang('comments::comments.cancel')
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
id="modal-blacklist-filter-save"
|
||||
class="ml-1 inline-block rounded bg-rose-600 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600"
|
||||
data-te-modal-dismiss
|
||||
data-te-ripple-init
|
||||
data-te-ripple-color="light">
|
||||
@lang('comments::comments.update')
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,49 +0,0 @@
|
||||
<!--Verically centered modal-->
|
||||
<div
|
||||
data-te-modal-init
|
||||
class="fixed left-0 top-0 z-[1055] hidden h-full w-full overflow-y-auto overflow-x-hidden outline-none"
|
||||
id="reply-modal-{{ $comment->getKey() }}"
|
||||
tabindex="-1"
|
||||
aria-labelledby="exampleModalCenterTitle"
|
||||
aria-modal="true"
|
||||
role="dialog">
|
||||
<div data-te-modal-dialog-ref class="pointer-events-none relative flex min-h-[calc(100%-1rem)] w-auto translate-y-[-50px] items-center opacity-0 transition-all duration-300 ease-in-out min-[576px]:mx-auto min-[576px]:mt-7 min-[576px]:min-h-[calc(100%-3.5rem)] min-[576px]:max-w-[95%] md:min-[576px]:max-w-[90%] lg:min-[576px]:max-w-[80%] xl:min-[576px]:max-w-[70%] 2xl:min-[576px]:max-w-[40%]">
|
||||
<div class="pointer-events-auto relative flex w-full flex-col rounded-md border-none bg-white bg-clip-padding text-current shadow-lg outline-none dark:bg-neutral-800">
|
||||
<x-modal-header :title="__('comments::comments.reply_to_comment')" />
|
||||
|
||||
<!--Modal body-->
|
||||
<div class="relative p-4">
|
||||
|
||||
<form method="POST" action="{{ route('comments.reply', $comment->getKey()) }}">
|
||||
@csrf
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label class="mb-2 leading-tight text-gray-800 dark:text-gray-200 w-full" for="message">@lang('comments::comments.enter_your_message_here')</label>
|
||||
<textarea required 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" name="message" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4">
|
||||
<button
|
||||
type="button"
|
||||
id="modal-blacklist-filter-close-bottom"
|
||||
class="inline-block rounded bg-primary-100 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-primary-700 transition duration-150 ease-in-out hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200"
|
||||
data-te-modal-dismiss
|
||||
data-te-ripple-init
|
||||
data-te-ripple-color="light">
|
||||
@lang('comments::comments.cancel')
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
id="modal-blacklist-filter-save"
|
||||
class="ml-1 inline-block rounded bg-rose-600 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600"
|
||||
data-te-modal-dismiss
|
||||
data-te-ripple-init
|
||||
data-te-ripple-color="light">
|
||||
@lang('comments::comments.reply')
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,7 +1,14 @@
|
||||
<!--Verically centered modal-->
|
||||
<div data-te-modal-init class="fixed left-0 top-0 z-[1055] hidden h-full w-full overflow-y-auto overflow-x-hidden outline-none" id="modalCreatePlaylist" tabindex="-1" aria-labelledby="Playlist" aria-modal="true" role="dialog">
|
||||
<div data-te-modal-dialog-ref class="pointer-events-none relative flex min-h-[calc(100%-1rem)] w-auto translate-y-[-50px] items-center opacity-0 transition-all duration-300 ease-in-out min-[576px]:mx-auto min-[576px]:mt-7 min-[576px]:min-h-[calc(100%-3.5rem)] min-[576px]:max-w-[95%] md:min-[576px]:max-w-[90%] lg:min-[576px]:max-w-[80%] xl:min-[576px]:max-w-[70%] 2xl:min-[576px]:max-w-[30%]">
|
||||
<div class="pointer-events-auto relative flex w-full flex-col rounded-md border-none bg-white bg-clip-padding text-current shadow-lg outline-none dark:bg-neutral-800">
|
||||
<div
|
||||
data-te-modal-init
|
||||
id="modalCreatePlaylist"
|
||||
tabindex="-1"
|
||||
aria-labelledby="modalCreatePlaylist"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="fixed inset-0 z-[1055] hidden overflow-y-auto bg-black/60 backdrop-blur-sm"
|
||||
>
|
||||
<div data-te-modal-dialog-ref class="flex min-h-screen items-center justify-center p-4">
|
||||
<div class="relative w-full max-w-4xl overflow-hidden rounded-2xl border border-neutral-200 bg-white shadow-2xl dark:border-neutral-700 dark:bg-neutral-900">
|
||||
<x-modal-header :title="__('Create Playlist')" />
|
||||
|
||||
<!--Modal body-->
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
<!--Verically centered modal-->
|
||||
<div data-te-modal-init class="fixed left-0 top-0 z-[1055] hidden h-full w-full overflow-y-auto overflow-x-hidden outline-none" id="modalDownload" tabindex="-1" aria-labelledby="Download" aria-modal="true" role="dialog">
|
||||
<div data-te-modal-dialog-ref class="pointer-events-none relative flex min-h-[calc(100%-1rem)] w-auto translate-y-[-50px] items-center opacity-0 transition-all duration-300 ease-in-out min-[576px]:mx-auto min-[576px]:mt-7 min-[576px]:min-h-[calc(100%-3.5rem)] min-[576px]:max-w-[95%] md:min-[576px]:max-w-[90%] lg:min-[576px]:max-w-[80%] xl:min-[576px]:max-w-[50%] 2xl:min-[576px]:max-w-[30%]">
|
||||
<div class="pointer-events-auto relative flex w-full flex-col rounded-md border-none bg-white bg-clip-padding text-current shadow-lg outline-none dark:bg-neutral-800">
|
||||
<x-modal-header :title='__("Download {$episode->title} - {$episode->episode}")' />
|
||||
<div
|
||||
data-te-modal-init
|
||||
id="modalDownload"
|
||||
tabindex="-1"
|
||||
aria-labelledby="modalDownload"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="fixed inset-0 z-[1055] hidden overflow-y-auto bg-black/60 backdrop-blur-sm"
|
||||
>
|
||||
<div data-te-modal-dialog-ref class="flex min-h-screen items-center justify-center p-4">
|
||||
<div class="relative w-full max-w-4xl overflow-hidden rounded-2xl border border-neutral-200 bg-white shadow-2xl dark:border-neutral-700 dark:bg-neutral-900">
|
||||
<x-modal-header title="Download {{ $episode->title }} - {{ $episode->episode }}" />
|
||||
|
||||
@php
|
||||
$dldomains = config('hstream.download_domain');
|
||||
|
||||
@@ -1,165 +1,107 @@
|
||||
<!--Verically centered modal-->
|
||||
<div data-te-modal-init
|
||||
class="fixed left-0 top-0 z-[1055] hidden h-full w-full overflow-y-auto overflow-x-hidden outline-none"
|
||||
id="modalBlacklist" tabindex="-1" aria-labelledby="modalBlacklist" aria-modal="true" role="dialog">
|
||||
<div data-te-modal-dialog-ref
|
||||
class="pointer-events-none relative flex min-h-[calc(100%-1rem)] w-auto translate-y-[-50px] items-center opacity-0 transition-all duration-300 ease-in-out min-[576px]:mx-auto min-[576px]:mt-7 min-[576px]:min-h-[calc(100%-3.5rem)] min-[576px]:max-w-[95%] md:min-[576px]:max-w-[90%] lg:min-[576px]:max-w-[80%] xl:min-[576px]:max-w-[70%] 2xl:min-[576px]:max-w-[60%]">
|
||||
<div
|
||||
class="pointer-events-auto relative flex w-full flex-col rounded-md border-none bg-white bg-clip-padding text-current shadow-lg outline-none dark:bg-neutral-800">
|
||||
<x-modal-header :title="__('Blacklist')" />
|
||||
data-te-modal-init
|
||||
id="modalBlacklist"
|
||||
tabindex="-1"
|
||||
aria-labelledby="modalBlacklistLabel"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="fixed inset-0 z-[1055] hidden overflow-y-auto bg-black/60 backdrop-blur-sm"
|
||||
>
|
||||
<div
|
||||
data-te-modal-dialog-ref
|
||||
class="flex min-h-screen items-center justify-center p-4"
|
||||
>
|
||||
<div
|
||||
class="relative w-full max-w-6xl overflow-hidden rounded-2xl border border-neutral-200 bg-white shadow-2xl dark:border-neutral-700 dark:bg-neutral-900"
|
||||
>
|
||||
<!-- Header -->
|
||||
<div class="sticky top-0 z-10 flex items-center justify-between border-b border-neutral-200 bg-white/90 px-6 py-4 backdrop-blur dark:border-neutral-700 dark:bg-neutral-900/90">
|
||||
<div>
|
||||
<h2
|
||||
id="modalGenresLabel"
|
||||
class="text-xl font-semibold text-neutral-900 dark:text-white"
|
||||
>
|
||||
Genres & Filters
|
||||
</h2>
|
||||
|
||||
<!--Modal body-->
|
||||
<div class="relative p-4">
|
||||
<p class="mt-1 text-sm text-neutral-500 dark:text-neutral-400">
|
||||
Select tags to blacklist from your content.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-te-modal-dismiss
|
||||
wire:click="revertFilters"
|
||||
class="rounded-lg p-2 text-neutral-500 transition hover:bg-neutral-100 hover:text-black dark:hover:bg-neutral-800 dark:hover:text-white"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Body -->
|
||||
<form class="max-h-[75vh] overflow-y-auto">
|
||||
<div class="space-y-8 p-6">
|
||||
@foreach (\App\Helpers\FilterCategories::getFilterCategories() as $section => $items)
|
||||
<section>
|
||||
<div class="mb-4 flex items-center justify-between">
|
||||
<h3 class="text-lg font-semibold text-neutral-800 dark:text-white">
|
||||
{{ $section }}
|
||||
</h3>
|
||||
|
||||
<div class="h-px flex-1 bg-neutral-200 ml-4 dark:bg-neutral-700"></div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-3">
|
||||
@foreach ($items as $tag)
|
||||
@php
|
||||
$taglist = \cache()->remember(
|
||||
'searchtags',
|
||||
300,
|
||||
fn() => Conner\Tagging\Model\Tag::where('count', '>', 0)->orderBy('slug', 'ASC')->get(),
|
||||
);
|
||||
$appearances = [
|
||||
'Loli',
|
||||
'Shota',
|
||||
'Milf',
|
||||
'Futanari',
|
||||
'Big Boobs',
|
||||
'Small Boobs',
|
||||
'Dark Skin',
|
||||
'Cosplay',
|
||||
'Elf',
|
||||
'Maid',
|
||||
'Nekomimi',
|
||||
'Nurse',
|
||||
'School Girl',
|
||||
'Succubus',
|
||||
'Teacher',
|
||||
'Trap',
|
||||
'Pregnant',
|
||||
'Glasses',
|
||||
'Swim Suit',
|
||||
'Ugly Bastard',
|
||||
'Monster',
|
||||
];
|
||||
$types = [
|
||||
'3D',
|
||||
'4K',
|
||||
'48Fps',
|
||||
'4K 48Fps',
|
||||
'Censored',
|
||||
'Uncensored',
|
||||
'Comedy',
|
||||
'Fantasy',
|
||||
'Horror',
|
||||
'Vanilla',
|
||||
'Ntr',
|
||||
'Pov',
|
||||
'Filmed',
|
||||
'X-Ray',
|
||||
];
|
||||
$actions = [
|
||||
'Anal',
|
||||
'Bdsm',
|
||||
'Facial',
|
||||
'Blow Job',
|
||||
'Boob Job',
|
||||
'Foot Job',
|
||||
'Hand Job',
|
||||
'Rimjob',
|
||||
'Inflation',
|
||||
'Masturbation',
|
||||
'Public Sex',
|
||||
'Rape',
|
||||
'Reverse Rape',
|
||||
'Threesome',
|
||||
'Orgy',
|
||||
'Gangbang',
|
||||
];
|
||||
$slug = Str::slug($tag);
|
||||
@endphp
|
||||
|
||||
<ul class="list-none text-justify" style="overflow: hidden;">
|
||||
@foreach ($taglist as $tag)
|
||||
@if (in_array($tag->name, $types) || in_array($tag->name, $appearances) || in_array($tag->name, $actions))
|
||||
@continue
|
||||
@endif
|
||||
<li class="inline-block m-1">
|
||||
<input class="m-5 hidden peer" wire:model="blacklist" type="checkbox"
|
||||
id="blacklist-{{ $tag->slug }}" name="blacklist[]" value="{{ $tag->slug }}">
|
||||
<label
|
||||
class="relative block cursor-pointer p-2 rounded bg-neutral-200 dark:bg-neutral-600 peer-checked:bg-rose-600 text-black peer-checked:text-white dark:peer-checked:text-white dark:text-white select-none"
|
||||
for="blacklist-{{ $tag->slug }}">{{ $tag->name }}</label>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
<div>
|
||||
<input
|
||||
wire:model="blacklist"
|
||||
type="checkbox"
|
||||
id="blacklist-{{ $slug }}"
|
||||
name="blacklist[]"
|
||||
value="{{ $slug }}"
|
||||
class="peer hidden"
|
||||
>
|
||||
|
||||
<br>
|
||||
<!-- Actions -->
|
||||
<p class="font-medium leading-normal text-neutral-800 dark:text-white">
|
||||
Action
|
||||
</p>
|
||||
<ul class="list-none text-justify" style="overflow: hidden;">
|
||||
@foreach ($actions as $tag)
|
||||
<li class="inline-block m-1">
|
||||
@php $slug = Illuminate\Support\Str::slug($tag); @endphp
|
||||
<input class="m-5 hidden peer" wire:model="blacklist" type="checkbox"
|
||||
id="blacklist-{{ $slug }}" name="blacklist[]" value="{{ $slug }}">
|
||||
<label
|
||||
class="relative block cursor-pointer p-2 rounded bg-neutral-200 dark:bg-neutral-600 peer-checked:bg-rose-600 text-black peer-checked:text-white dark:peer-checked:text-white dark:text-white select-none"
|
||||
for="blacklist-{{ $slug }}">{{ $tag }}</label>
|
||||
</li>
|
||||
for="blacklist-{{ $slug }}"
|
||||
class="inline-flex cursor-pointer items-center rounded-full border border-neutral-300 bg-neutral-100 px-4 py-2 text-sm font-medium text-neutral-700 transition-all duration-200 hover:border-rose-400 hover:bg-rose-50 hover:text-rose-600 peer-checked:border-rose-600 peer-checked:bg-rose-600 peer-checked:text-white dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-200 dark:hover:border-rose-500 dark:hover:bg-neutral-700"
|
||||
>
|
||||
{{ $tag }}
|
||||
</label>
|
||||
</div>
|
||||
@endforeach
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
<!-- Character Appearance -->
|
||||
<p class="font-medium leading-normal text-neutral-800 dark:text-white">
|
||||
Appearance
|
||||
</p>
|
||||
<ul class="list-none text-justify" style="overflow: hidden;">
|
||||
@foreach ($appearances as $tag)
|
||||
@guest
|
||||
@php if ($tag === "Loli" || $tag === "Shota") continue; @endphp
|
||||
@endguest
|
||||
<li class="inline-block m-1">
|
||||
@php $slug = Illuminate\Support\Str::slug($tag); @endphp
|
||||
<input class="m-5 hidden peer" wire:model="blacklist" type="checkbox"
|
||||
id="blacklist-{{ $slug }}" name="blacklist[]" value="{{ $slug }}">
|
||||
<label
|
||||
class="relative block cursor-pointer p-2 rounded bg-neutral-200 dark:bg-neutral-600 peer-checked:bg-rose-600 text-black peer-checked:text-white dark:peer-checked:text-white dark:text-white select-none"
|
||||
for="blacklist-{{ $slug }}">{{ $tag }}</label>
|
||||
</li>
|
||||
</div>
|
||||
</section>
|
||||
@endforeach
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
|
||||
<!-- Video Types -->
|
||||
<p class="font-medium leading-normal text-neutral-800 dark:text-white">
|
||||
Type
|
||||
</p>
|
||||
<ul class="list-none text-justify" style="overflow: hidden;">
|
||||
@foreach ($types as $tag)
|
||||
<li class="inline-block m-1">
|
||||
@php $slug = Illuminate\Support\Str::slug($tag); @endphp
|
||||
<input class="m-5 hidden peer" wire:model="blacklist" type="checkbox"
|
||||
id="blacklist-{{ $slug }}" name="blacklist[]" value="{{ $slug }}">
|
||||
<label
|
||||
class="relative block cursor-pointer p-2 rounded bg-neutral-200 dark:bg-neutral-600 peer-checked:bg-rose-600 text-black peer-checked:text-white dark:peer-checked:text-white dark:text-white select-none"
|
||||
for="blacklist-{{ $slug }}">{{ $tag }}</label>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!--Modal footer-->
|
||||
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4">
|
||||
<button data-te-modal-dismiss wire:click="revertFilters" type="button"
|
||||
class="inline-block rounded bg-primary-100 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-primary-700 transition duration-150 ease-in-out hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200">
|
||||
Close
|
||||
<!-- Footer -->
|
||||
<div class="sticky bottom-0 flex items-center justify-end gap-3 border-t border-neutral-200 bg-white/90 px-6 py-4 backdrop-blur dark:border-neutral-700 dark:bg-neutral-900/90">
|
||||
<button
|
||||
type="button"
|
||||
data-te-modal-dismiss
|
||||
wire:click="revertFilters"
|
||||
class="rounded-xl border border-neutral-300 px-5 py-2.5 text-sm font-medium text-neutral-700 transition hover:bg-neutral-100 dark:border-neutral-600 dark:text-neutral-200 dark:hover:bg-neutral-800"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button data-te-modal-dismiss wire:click="applyFilters" type="button"
|
||||
class="ml-1 inline-block rounded bg-rose-600 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600">
|
||||
Apply
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-te-modal-dismiss
|
||||
wire:click="applyFilters"
|
||||
class="rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700"
|
||||
>
|
||||
Apply Filters
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,163 +1,99 @@
|
||||
<!--Verically centered modal-->
|
||||
<div data-te-modal-init
|
||||
class="fixed left-0 top-0 z-[1055] hidden h-full w-full overflow-y-auto overflow-x-hidden outline-none"
|
||||
id="modalGenres" tabindex="-1" aria-labelledby="modalGenres" aria-modal="true" role="dialog">
|
||||
<div data-te-modal-dialog-ref
|
||||
class="pointer-events-none relative flex min-h-[calc(100%-1rem)] w-auto translate-y-[-50px] items-center opacity-0 transition-all duration-300 ease-in-out min-[576px]:mx-auto min-[576px]:mt-7 min-[576px]:min-h-[calc(100%-3.5rem)] min-[576px]:max-w-[95%] md:min-[576px]:max-w-[90%] lg:min-[576px]:max-w-[80%] xl:min-[576px]:max-w-[70%] 2xl:min-[576px]:max-w-[60%]">
|
||||
<div
|
||||
class="pointer-events-auto relative flex w-full flex-col rounded-md border-none bg-white bg-clip-padding text-current shadow-lg outline-none dark:bg-neutral-800">
|
||||
<x-modal-header :title="__('Genres')" />
|
||||
<form>
|
||||
<!--Modal body-->
|
||||
<div class="relative p-4">
|
||||
@php
|
||||
$taglist = cache()->remember(
|
||||
'searchtags',
|
||||
300,
|
||||
fn() => Conner\Tagging\Model\Tag::where('count', '>', 0)->orderBy('slug', 'ASC')->get(),
|
||||
);
|
||||
$appearances = [
|
||||
'Loli',
|
||||
'Shota',
|
||||
'Milf',
|
||||
'Futanari',
|
||||
'Big Boobs',
|
||||
'Small Boobs',
|
||||
'Dark Skin',
|
||||
'Cosplay',
|
||||
'Elf',
|
||||
'Maid',
|
||||
'Nekomimi',
|
||||
'Nurse',
|
||||
'School Girl',
|
||||
'Succubus',
|
||||
'Teacher',
|
||||
'Trap',
|
||||
'Pregnant',
|
||||
'Glasses',
|
||||
'Swim Suit',
|
||||
'Ugly Bastard',
|
||||
'Monster',
|
||||
];
|
||||
$types = [
|
||||
'3D',
|
||||
'4K',
|
||||
'48Fps',
|
||||
'4K 48Fps',
|
||||
'Censored',
|
||||
'Uncensored',
|
||||
'Comedy',
|
||||
'Fantasy',
|
||||
'Horror',
|
||||
'Vanilla',
|
||||
'Ntr',
|
||||
'Pov',
|
||||
'Filmed',
|
||||
'X-Ray',
|
||||
];
|
||||
$actions = [
|
||||
'Anal',
|
||||
'Bdsm',
|
||||
'Facial',
|
||||
'Blow Job',
|
||||
'Boob Job',
|
||||
'Foot Job',
|
||||
'Hand Job',
|
||||
'Rimjob',
|
||||
'Inflation',
|
||||
'Masturbation',
|
||||
'Public Sex',
|
||||
'Rape',
|
||||
'Reverse Rape',
|
||||
'Threesome',
|
||||
'Orgy',
|
||||
'Gangbang',
|
||||
];
|
||||
@endphp
|
||||
data-te-modal-init
|
||||
id="modalGenres"
|
||||
tabindex="-1"
|
||||
aria-labelledby="modalGenresLabel"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="fixed inset-0 z-[1055] hidden overflow-y-auto bg-black/60 backdrop-blur-sm"
|
||||
>
|
||||
<div data-te-modal-dialog-ref class="flex min-h-screen items-center justify-center p-4">
|
||||
<div class="relative w-full max-w-6xl overflow-hidden rounded-2xl border border-neutral-200 bg-white shadow-2xl dark:border-neutral-700 dark:bg-neutral-900">
|
||||
<!-- Header -->
|
||||
<div class="sticky top-0 z-10 flex items-center justify-between border-b border-neutral-200 bg-white/90 px-6 py-4 backdrop-blur dark:border-neutral-700 dark:bg-neutral-900/90">
|
||||
<div>
|
||||
<h2
|
||||
id="modalGenresLabel"
|
||||
class="text-xl font-semibold text-neutral-900 dark:text-white"
|
||||
>
|
||||
Genres & Filters
|
||||
</h2>
|
||||
|
||||
<ul class="list-none text-justify" style="overflow: hidden;">
|
||||
@foreach ($taglist as $tag)
|
||||
@if (in_array($tag->name, $types) || in_array($tag->name, $appearances) || in_array($tag->name, $actions))
|
||||
@continue
|
||||
@endif
|
||||
<li class="inline-block m-1">
|
||||
<input class="m-5 hidden peer" wire:model="tags" type="checkbox"
|
||||
id="tags-{{ $tag->slug }}" name="tags[]" value="{{ $tag->slug }}">
|
||||
<label
|
||||
class="relative block cursor-pointer p-2 rounded bg-neutral-200 dark:bg-neutral-600 peer-checked:bg-rose-600 text-black peer-checked:text-white dark:peer-checked:text-white dark:text-white select-none"
|
||||
for="tags-{{ $tag->slug }}">{{ $tag->name }}</label>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
<!-- Actions -->
|
||||
<p class="font-medium leading-normal text-neutral-800 dark:text-white">
|
||||
Action
|
||||
<p class="mt-1 text-sm text-neutral-500 dark:text-neutral-400">
|
||||
Select tags to filter your content.
|
||||
</p>
|
||||
<ul class="list-none text-justify" style="overflow: hidden;">
|
||||
@foreach ($actions as $tag)
|
||||
<li class="inline-block m-1">
|
||||
@php $slug = Illuminate\Support\Str::slug($tag); @endphp
|
||||
<input class="m-5 hidden peer" wire:model="tags" type="checkbox"
|
||||
id="tags-{{ $slug }}" name="tags[]" value="{{ $slug }}">
|
||||
<label
|
||||
class="relative block cursor-pointer p-2 rounded bg-neutral-200 dark:bg-neutral-600 peer-checked:bg-rose-600 text-black peer-checked:text-white dark:peer-checked:text-white dark:text-white select-none"
|
||||
for="tags-{{ $slug }}">{{ $tag }}</label>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
<!-- Character Appearance -->
|
||||
<p class="font-medium leading-normal text-neutral-800 dark:text-white">
|
||||
Appearance
|
||||
</p>
|
||||
<ul class="list-none text-justify" style="overflow: hidden;">
|
||||
@foreach ($appearances as $tag)
|
||||
@guest
|
||||
@php if ($tag === "Loli" || $tag === "Shota") continue; @endphp
|
||||
@endguest
|
||||
<li class="inline-block m-1">
|
||||
@php $slug = Illuminate\Support\Str::slug($tag); @endphp
|
||||
<input class="m-5 hidden peer" wire:model="tags" type="checkbox"
|
||||
id="tags-{{ $slug }}" name="tags[]" value="{{ $slug }}">
|
||||
<label
|
||||
class="relative block cursor-pointer p-2 rounded bg-neutral-200 dark:bg-neutral-600 peer-checked:bg-rose-600 text-black peer-checked:text-white dark:peer-checked:text-white dark:text-white select-none"
|
||||
for="tags-{{ $slug }}">{{ $tag }}</label>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
|
||||
<!-- Video Types -->
|
||||
<p class="font-medium leading-normal text-neutral-800 dark:text-white">
|
||||
Type
|
||||
</p>
|
||||
<ul class="list-none text-justify" style="overflow: hidden;">
|
||||
@foreach ($types as $tag)
|
||||
<li class="inline-block m-1">
|
||||
@php $slug = Illuminate\Support\Str::slug($tag); @endphp
|
||||
<input class="m-5 hidden peer" wire:model="tags" type="checkbox"
|
||||
id="tags-{{ $slug }}" name="tags[]" value="{{ $slug }}">
|
||||
<label
|
||||
class="relative block cursor-pointer p-2 rounded bg-neutral-200 dark:bg-neutral-600 peer-checked:bg-rose-600 text-black peer-checked:text-white dark:peer-checked:text-white dark:text-white select-none"
|
||||
for="tags-{{ $slug }}">{{ $tag }}</label>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!--Modal footer-->
|
||||
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4">
|
||||
<button data-te-modal-dismiss wire:click="revertFilters" type="button"
|
||||
class="inline-block rounded bg-primary-100 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-primary-700 transition duration-150 ease-in-out hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200">
|
||||
Close
|
||||
<button
|
||||
type="button"
|
||||
data-te-modal-dismiss
|
||||
wire:click="revertFilters"
|
||||
class="rounded-lg p-2 text-neutral-500 transition hover:bg-neutral-100 hover:text-black dark:hover:bg-neutral-800 dark:hover:text-white"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
<button data-te-modal-dismiss wire:click="applyFilters" type="button"
|
||||
class="ml-1 inline-block rounded bg-rose-600 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600">
|
||||
Apply
|
||||
</div>
|
||||
|
||||
<!-- Body -->
|
||||
<form class="max-h-[75vh] overflow-y-auto">
|
||||
<div class="space-y-8 p-6">
|
||||
@foreach (\App\Helpers\FilterCategories::getFilterCategories() as $section => $items)
|
||||
<section>
|
||||
<div class="mb-4 flex items-center justify-between">
|
||||
<h3 class="text-lg font-semibold text-neutral-800 dark:text-white">
|
||||
{{ $section }}
|
||||
</h3>
|
||||
|
||||
<div class="h-px flex-1 bg-neutral-200 ml-4 dark:bg-neutral-700"></div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-3">
|
||||
@foreach ($items as $tag)
|
||||
@php
|
||||
$slug = Str::slug($tag);
|
||||
@endphp
|
||||
|
||||
<div>
|
||||
<input
|
||||
wire:model="tags"
|
||||
type="checkbox"
|
||||
id="tags-{{ $slug }}"
|
||||
name="tags[]"
|
||||
value="{{ $slug }}"
|
||||
class="peer hidden"
|
||||
>
|
||||
|
||||
<label
|
||||
for="tags-{{ $slug }}"
|
||||
class="inline-flex cursor-pointer items-center rounded-full border border-neutral-300 bg-neutral-100 px-4 py-2 text-sm font-medium text-neutral-700 transition-all duration-200 hover:border-rose-400 hover:bg-rose-50 hover:text-rose-600 peer-checked:border-rose-600 peer-checked:bg-rose-600 peer-checked:text-white dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-200 dark:hover:border-rose-500 dark:hover:bg-neutral-700"
|
||||
>
|
||||
{{ $tag }}
|
||||
</label>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</section>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="sticky bottom-0 flex items-center justify-end gap-3 border-t border-neutral-200 bg-white/90 px-6 py-4 backdrop-blur dark:border-neutral-700 dark:bg-neutral-900/90">
|
||||
<button
|
||||
type="button"
|
||||
data-te-modal-dismiss
|
||||
wire:click="revertFilters"
|
||||
class="rounded-xl border border-neutral-300 px-5 py-2.5 text-sm font-medium text-neutral-700 transition hover:bg-neutral-100 dark:border-neutral-600 dark:text-neutral-200 dark:hover:bg-neutral-800"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-te-modal-dismiss
|
||||
wire:click="applyFilters"
|
||||
class="rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700"
|
||||
>
|
||||
Apply Filters
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -1,40 +1,86 @@
|
||||
<!--Verically centered modal-->
|
||||
<div data-te-modal-init
|
||||
class="fixed left-0 top-0 z-[1055] hidden h-full w-full overflow-y-auto overflow-x-hidden outline-none"
|
||||
id="modalStudios" tabindex="-1" aria-labelledby="modalStudios" aria-modal="true" role="dialog">
|
||||
<div data-te-modal-dialog-ref
|
||||
class="pointer-events-none relative flex min-h-[calc(100%-1rem)] w-auto translate-y-[-50px] items-center opacity-0 transition-all duration-300 ease-in-out min-[576px]:mx-auto min-[576px]:mt-7 min-[576px]:min-h-[calc(100%-3.5rem)] min-[576px]:max-w-[95%] md:min-[576px]:max-w-[90%] lg:min-[576px]:max-w-[80%] xl:min-[576px]:max-w-[70%] 2xl:min-[576px]:max-w-[60%]">
|
||||
<div
|
||||
class="pointer-events-auto relative flex w-full flex-col rounded-md border-none bg-white bg-clip-padding text-current shadow-lg outline-none dark:bg-neutral-800">
|
||||
<x-modal-header :title="__('Studios')" />
|
||||
data-te-modal-init
|
||||
id="modalStudios"
|
||||
tabindex="-1"
|
||||
aria-labelledby="modalStudios"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="fixed inset-0 z-[1055] hidden overflow-y-auto bg-black/60 backdrop-blur-sm"
|
||||
>
|
||||
<div data-te-modal-dialog-ref class="flex min-h-screen items-center justify-center p-4">
|
||||
<div class="relative w-full max-w-6xl overflow-hidden rounded-2xl border border-neutral-200 bg-white shadow-2xl dark:border-neutral-700 dark:bg-neutral-900">
|
||||
<!-- Header -->
|
||||
<div class="sticky top-0 z-10 flex items-center justify-between border-b border-neutral-200 bg-white/90 px-6 py-4 backdrop-blur dark:border-neutral-700 dark:bg-neutral-900/90">
|
||||
<div>
|
||||
<h2
|
||||
id="modalGenresLabel"
|
||||
class="text-xl font-semibold text-neutral-900 dark:text-white"
|
||||
>
|
||||
Studios
|
||||
</h2>
|
||||
|
||||
<!--Modal body-->
|
||||
<div class="relative p-4">
|
||||
<ul class="list-none text-justify" style="overflow: hidden;">
|
||||
<p class="mt-1 text-sm text-neutral-500 dark:text-neutral-400">
|
||||
Select studios to filter your content.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-te-modal-dismiss
|
||||
wire:click="revertFilters"
|
||||
class="rounded-lg p-2 text-neutral-500 transition hover:bg-neutral-100 hover:text-black dark:hover:bg-neutral-800 dark:hover:text-white"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Body -->
|
||||
<form class="max-h-[75vh] overflow-y-auto">
|
||||
<div class="space-y-8 p-6">
|
||||
@php $studios = \cache()->remember('searchstudios', 300, fn () => App\Models\Studios::orderBy('name', 'ASC')->get()); @endphp
|
||||
<div class="flex flex-wrap gap-3">
|
||||
@foreach ($studios as $studio)
|
||||
<li class="inline-block m-1">
|
||||
<input class="m-5 hidden peer" wire:model="studios" type="checkbox"
|
||||
id="studio-{{ $studio->slug }}" name="studios[]" value="{{ $studio->slug }}">
|
||||
<div>
|
||||
<input
|
||||
wire:model="studios"
|
||||
type="checkbox"
|
||||
id="studio-{{ $studio->slug }}"
|
||||
name="studios[]"
|
||||
value="{{ $studio->slug }}"
|
||||
class="m-5 hidden peer"
|
||||
>
|
||||
<label
|
||||
class="relative block cursor-pointer p-2 rounded bg-neutral-200 dark:bg-neutral-600 peer-checked:bg-rose-600 text-black peer-checked:text-white dark:peer-checked:text-white dark:text-white select-none"
|
||||
for="studio-{{ $studio->slug }}">{{ $studio->name }}</label>
|
||||
</li>
|
||||
for="studio-{{ $studio->slug }}"
|
||||
class="inline-flex cursor-pointer items-center rounded-full border border-neutral-300 bg-neutral-100 px-4 py-2 text-sm font-medium text-neutral-700 transition-all duration-200 hover:border-rose-400 hover:bg-rose-50 hover:text-rose-600 peer-checked:border-rose-600 peer-checked:bg-rose-600 peer-checked:text-white dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-200 dark:hover:border-rose-500 dark:hover:bg-neutral-700"
|
||||
>
|
||||
{{ $studio->name }}
|
||||
</label>
|
||||
</div>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Modal footer-->
|
||||
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4">
|
||||
<button data-te-modal-dismiss wire:click="revertFilters" type="button"
|
||||
class="inline-block rounded bg-primary-100 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-primary-700 transition duration-150 ease-in-out hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200">
|
||||
Close
|
||||
<!-- Footer -->
|
||||
<div class="sticky bottom-0 flex items-center justify-end gap-3 border-t border-neutral-200 bg-white/90 px-6 py-4 backdrop-blur dark:border-neutral-700 dark:bg-neutral-900/90">
|
||||
<button
|
||||
type="button"
|
||||
data-te-modal-dismiss
|
||||
wire:click="revertFilters"
|
||||
class="rounded-xl border border-neutral-300 px-5 py-2.5 text-sm font-medium text-neutral-700 transition hover:bg-neutral-100 dark:border-neutral-600 dark:text-neutral-200 dark:hover:bg-neutral-800"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button data-te-modal-dismiss wire:click="applyFilters" type="button"
|
||||
class="ml-1 inline-block rounded bg-rose-600 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600">
|
||||
Apply
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-te-modal-dismiss
|
||||
wire:click="applyFilters"
|
||||
class="rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700"
|
||||
>
|
||||
Apply Filters
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,18 +1,45 @@
|
||||
<!--Verically centered modal-->
|
||||
<div data-te-modal-init
|
||||
class="fixed left-0 top-0 z-[1055] hidden h-full w-full overflow-y-auto overflow-x-hidden outline-none"
|
||||
id="modalLanguage" tabindex="-1" aria-modal="true" role="dialog">
|
||||
<div data-te-modal-dialog-ref
|
||||
class="pointer-events-none relative flex min-h-[calc(100%-1rem)] w-auto translate-y-[-50px] items-center opacity-0 transition-all duration-300 ease-in-out min-[576px]:mx-auto min-[576px]:mt-7 min-[576px]:min-h-[calc(100%-3.5rem)] min-[576px]:max-w-[90%] md:min-[576px]:max-w-[80%] lg:min-[576px]:max-w-[60%] xl:min-[576px]:max-w-[40%] 2xl:min-[576px]:max-w-[20%]">
|
||||
<div
|
||||
class="pointer-events-auto relative flex w-full flex-col rounded-md border-none bg-white bg-clip-padding text-current shadow-lg outline-none dark:bg-neutral-800">
|
||||
<x-modal-header :title="__('Language')" />
|
||||
data-te-modal-init
|
||||
id="modalLanguage"
|
||||
tabindex="-1"
|
||||
aria-labelledby="modalLanguage"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="fixed inset-0 z-[1055] hidden overflow-y-auto bg-black/60 backdrop-blur-sm"
|
||||
>
|
||||
<div data-te-modal-dialog-ref class="flex min-h-screen items-center justify-center p-4">
|
||||
<div class="relative w-full max-w-2xl overflow-hidden rounded-2xl border border-neutral-200 bg-white shadow-2xl dark:border-neutral-700 dark:bg-neutral-900">
|
||||
<!-- Header -->
|
||||
<div class="sticky top-0 z-10 flex items-center justify-between border-b border-neutral-200 bg-white/90 px-6 py-4 backdrop-blur dark:border-neutral-700 dark:bg-neutral-900/90">
|
||||
<div>
|
||||
<h2
|
||||
id="modalGenresLabel"
|
||||
class="text-xl font-semibold text-neutral-900 dark:text-white"
|
||||
>
|
||||
Language
|
||||
</h2>
|
||||
|
||||
<p class="mt-1 text-sm text-neutral-500 dark:text-neutral-400">
|
||||
Select your preffered language of the website.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-te-modal-dismiss
|
||||
wire:click="revertFilters"
|
||||
class="rounded-lg p-2 text-neutral-500 transition hover:bg-neutral-100 hover:text-black dark:hover:bg-neutral-800 dark:hover:text-white"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!--Modal body-->
|
||||
<div class="relative p-4">
|
||||
<form method="POST" action="{{ route('update.language') }}">
|
||||
@csrf
|
||||
|
||||
<div class="pb-6">
|
||||
<label class="mb-2 leading-tight text-gray-800 dark:text-gray-200 w-full" for="language">Select
|
||||
Language:</label>
|
||||
<select name="language" id="language"
|
||||
@@ -27,16 +54,20 @@
|
||||
Français (fr)
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-shrink-0 flex-wrap items-center justify-end rounded-b-md p-4">
|
||||
<button type="button"
|
||||
class="inline-block rounded bg-primary-100 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-primary-700 transition duration-150 ease-in-out hover:bg-primary-accent-100 focus:bg-primary-accent-100 focus:outline-none focus:ring-0 active:bg-primary-accent-200"
|
||||
data-te-modal-dismiss data-te-ripple-init data-te-ripple-color="light">
|
||||
<div class="sticky bottom-0 flex items-center justify-end gap-3 border-t border-neutral-200 bg-white/90 px-6 py-4 backdrop-blur dark:border-neutral-700 dark:bg-neutral-900/90">
|
||||
<button
|
||||
type="button"
|
||||
data-te-modal-dismiss
|
||||
class="rounded-xl border border-neutral-300 px-5 py-2.5 text-sm font-medium text-neutral-700 transition hover:bg-neutral-100 dark:border-neutral-600 dark:text-neutral-200 dark:hover:bg-neutral-800"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button type="submit"
|
||||
class="ml-1 inline-block rounded bg-rose-600 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out hover:bg-rose-700 focus:bg-rose-600"
|
||||
data-te-ripple-init data-te-ripple-color="light">
|
||||
<button
|
||||
type="submit"
|
||||
class="rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700"
|
||||
>
|
||||
Apply
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
@php
|
||||
$download = $hdl->getDownloadByType('FHDi');
|
||||
$downloadURL = $dldomains[array_rand($dldomains)].'/'.$download->url;
|
||||
$version = str_contains($download->url, 'v2') ? 'v2' : '';
|
||||
@endphp
|
||||
|
||||
<livewire:download-button
|
||||
@@ -14,5 +15,6 @@
|
||||
:download-count="$download->count"
|
||||
:episode-number="$hdl->episode"
|
||||
:fill-numbers="$fillNumbers"
|
||||
:file-size="$download->getFileSize()">
|
||||
:file-size="$download->getFileSize()"
|
||||
:version="$version">
|
||||
@endif
|
||||
@@ -10,6 +10,7 @@
|
||||
$now = \Illuminate\Support\Carbon::now();
|
||||
$expire = \Illuminate\Support\Facades\Crypt::encryptString($now->addHours(6));
|
||||
$file = \Illuminate\Support\Facades\Crypt::encryptString('hentai/'.$download->url);
|
||||
$version = str_contains($download->url, 'v2') ? 'v2' : '';
|
||||
|
||||
$downloadURL = $dlpdomains[array_rand($dlpdomains)].'/download/'.$file.'/'.$expire;
|
||||
@endphp
|
||||
@@ -20,5 +21,6 @@
|
||||
:download-count="$download->count"
|
||||
:episode-number="$hdl->episode"
|
||||
:fill-numbers="$fillNumbers"
|
||||
:file-size="$download->getFileSize()">
|
||||
:file-size="$download->getFileSize()"
|
||||
:version="$version">
|
||||
@endif
|
||||
@@ -10,6 +10,7 @@
|
||||
$now = \Illuminate\Support\Carbon::now();
|
||||
$expire = \Illuminate\Support\Facades\Crypt::encryptString($now->addHours(6));
|
||||
$file = \Illuminate\Support\Facades\Crypt::encryptString('hentai/'.$download->url);
|
||||
$version = str_contains($download->url, 'v2') ? 'v2' : '';
|
||||
|
||||
$downloadURL = $dlpdomains[array_rand($dlpdomains)].'/download/'.$file.'/'.$expire;
|
||||
@endphp
|
||||
@@ -20,5 +21,6 @@
|
||||
:download-count="$download->count"
|
||||
:episode-number="$hdl->episode"
|
||||
:fill-numbers="$fillNumbers"
|
||||
:file-size="$download->getFileSize()">
|
||||
:file-size="$download->getFileSize()"
|
||||
:version="$version">
|
||||
@endif
|
||||
@@ -1,12 +1,15 @@
|
||||
<!--Verically centered modal-->
|
||||
<div data-te-modal-init
|
||||
class="fixed left-0 top-0 z-[1055] hidden h-full w-full overflow-y-auto overflow-x-hidden outline-none"
|
||||
id="modalShare" tabindex="-1" aria-labelledby="Share" aria-modal="true" role="dialog">
|
||||
<div data-te-modal-dialog-ref
|
||||
class="pointer-events-none relative flex min-h-[calc(100%-1rem)] w-auto translate-y-[-50px] items-center opacity-0 transition-all duration-300 ease-in-out min-[576px]:mx-auto min-[576px]:mt-7 min-[576px]:min-h-[calc(100%-3.5rem)] min-[576px]:max-w-[95%] md:min-[576px]:max-w-[90%] lg:min-[576px]:max-w-[80%] xl:min-[576px]:max-w-[50%] 2xl:min-[576px]:max-w-[25%]">
|
||||
<div
|
||||
class="pointer-events-auto relative flex w-full flex-col rounded-md border-none bg-white bg-clip-padding text-current shadow-lg outline-none dark:bg-neutral-800">
|
||||
<x-modal-header :title='__("Share {$episode->title} - {$episode->episode}")' />
|
||||
data-te-modal-init
|
||||
id="modalShare"
|
||||
tabindex="-1"
|
||||
aria-labelledby="Share"
|
||||
aria-modal="true"
|
||||
role="dialog"
|
||||
class="fixed inset-0 z-[1055] hidden overflow-y-auto bg-black/60 backdrop-blur-sm"
|
||||
>
|
||||
<div data-te-modal-dialog-ref class="flex min-h-screen items-center justify-center p-4">
|
||||
<div class="relative w-full max-w-2xl overflow-hidden rounded-2xl border border-neutral-200 bg-white shadow-2xl dark:border-neutral-700 dark:bg-neutral-900">
|
||||
<x-modal-header title="Share {{ $episode->title }} - {{ $episode->episode }}" />
|
||||
|
||||
<!--Modal body-->
|
||||
<div class="relative p-4">
|
||||
@@ -15,8 +18,8 @@
|
||||
$currentUrl = url()->current();
|
||||
$text = 'Watch ' . $episode->title . ' - ' . $episode->episode . ' in 4k on hstream.moe!';
|
||||
@endphp
|
||||
<div class="flex flex-wrap justify-stretch">
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition py-3 px-5 rounded-lg text-white border-rose-600 bg-rose-600 hover:bg-rose-700 hover:border-rose-700"
|
||||
<div class="flex flex-wrap justify-stretch gap-3">
|
||||
<a class="cursor-pointer inline-flex items-center rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://facebook.com/sharer/sharer.php?u={{ $currentUrl }}"
|
||||
aria-label="Share on Facebook" draggable="false">
|
||||
@@ -29,7 +32,7 @@
|
||||
</svg>
|
||||
<span class="ml-2">Facebook</span>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition py-3 px-5 rounded-lg text-white border-rose-600 bg-rose-600 hover:bg-rose-700 hover:border-rose-700"
|
||||
<a class="cursor-pointer inline-flex items-center rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://twitter.com/intent/tweet?url={{ $currentUrl }}&text={{ $text }}"
|
||||
aria-label="Share on Twitter" draggable="false">
|
||||
@@ -42,7 +45,7 @@
|
||||
</svg>
|
||||
<span class="ml-2">Twitter</span>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition py-3 px-5 rounded-lg text-white border-rose-600 bg-rose-600 hover:bg-rose-700 hover:border-rose-700"
|
||||
<a class="cursor-pointer inline-flex items-center rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://reddit.com/submit/?url={{ $currentUrl }}&resubmit=true&title={{ $text }}"
|
||||
aria-label="Share on Reddit" draggable="false">
|
||||
@@ -55,7 +58,7 @@
|
||||
</svg>
|
||||
<span class="ml-2">Reddit</span>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition py-3 px-5 rounded-lg text-white border-rose-600 bg-rose-600 hover:bg-rose-700 hover:border-rose-700"
|
||||
<a class="cursor-pointer inline-flex items-center rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://wa.me/?text={{ $text }}%20{{ $currentUrl }}"
|
||||
aria-label="Share on Whatsapp" draggable="false" style="">
|
||||
@@ -68,7 +71,7 @@
|
||||
</svg>
|
||||
<span class="ml-2">Whatsapp</span>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition py-3 px-5 rounded-lg text-white border-rose-600 bg-rose-600 hover:bg-rose-700 hover:border-rose-700"
|
||||
<a class="cursor-pointer inline-flex items-center rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="https://telegram.me/share/url?text={{ $text }}&url={{ $currentUrl }}"
|
||||
aria-label="Share on Telegram" draggable="false">
|
||||
@@ -81,7 +84,7 @@
|
||||
</svg>
|
||||
<span class="ml-2">Telegram</span>
|
||||
</a>
|
||||
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition py-3 px-5 rounded-lg text-white border-rose-600 bg-rose-600 hover:bg-rose-700 hover:border-rose-700"
|
||||
<a class="cursor-pointer inline-flex items-center rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700"
|
||||
target="_blank" rel="noopener"
|
||||
href="mailto:?subject={{ $text }}&body={{ $currentUrl }}"
|
||||
aria-label="Share by Email" draggable="false">
|
||||
@@ -100,7 +103,7 @@
|
||||
<div>
|
||||
<button id="copy-button" type="button" data-te-clipboard-init
|
||||
data-te-clipboard-target="#copy-target" data-te-ripple-init data-te-ripple-color="light"
|
||||
class="inline-block rounded border-rose-600 bg-rose-600 hover:bg-rose-700 hover:border-rose-700 px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white transition duration-150 ease-in-out focus:bg-rose-600 focus:outline-none focus:ring-0 active:bg-rose-700">
|
||||
class="cursor-pointer rounded-xl bg-rose-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-rose-600/20 transition hover:bg-rose-700">
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
@php $limitcounter = 0; @endphp
|
||||
|
||||
@foreach ($episodes as $ep)
|
||||
@if (isset($popularView))
|
||||
@php $episode = $ep->episode @endphp
|
||||
@else
|
||||
@php $episode = $ep @endphp
|
||||
@endif
|
||||
|
||||
@if ($limitcounter >= $limit)
|
||||
@break
|
||||
@endif
|
||||
|
||||
<div
|
||||
class="relative p-1 mb-8 w-full transition duration-300 ease-in-out md:p-2 md:hover:-translate-y-1 md:hover:scale-110">
|
||||
<a class="hover:text-blue-600" href="{{ route('hentai.index', ['title' => $episode->slug]) }}">
|
||||
<img alt="{{ $episode->title }} - {{ $episode->episode }}" loading="lazy" width="400"
|
||||
class="block relative rounded-lg object-cover object-center aspect-[11/16] z-20 "
|
||||
src="{{ $episode->cover_url }}"></img>
|
||||
|
||||
@guest
|
||||
<p
|
||||
class="absolute right-1 md:right-2 top-1 md:top-2 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 md:left-2 bottom-1 md:bottom-2 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>
|
||||
@endguest
|
||||
|
||||
@php $problematic = cache()->rememberForever('episodeProblematic'.$episode->id, fn () => $episode->getProblematicTags()); @endphp
|
||||
@if (!empty($problematic))
|
||||
<p
|
||||
class="absolute left-1 md:left-2 top-1 md:top-2 bg-red-700/70 !text-white rounded-br-lg rounded-tl-lg p-1 pr-2 pl-2 font-semibold text-sm z-30">
|
||||
<i class="fa-solid fa-triangle-exclamation"></i> {{ $problematic }}
|
||||
</p>
|
||||
@endif
|
||||
|
||||
@auth
|
||||
@if ($episode->userWatched(auth()->user()->id))
|
||||
<p
|
||||
class="absolute right-1 md:right-2 top-1 md:top-2 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 md:left-2 bottom-1 md:bottom-2 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 md:right-2 top-1 md:top-2 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 md:left-2 bottom-1 md:bottom-2 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
|
||||
|
||||
<div class="absolute w-[95%] grid grid-cols-1 text-center">
|
||||
<p class="text-sm text-center text-black dark:text-white">{{ $episode->title }} -
|
||||
{{ $episode->episode }}</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@php $limitcounter++; @endphp
|
||||
@endforeach
|
||||
@@ -1,17 +0,0 @@
|
||||
@php $limitcounter = 0; @endphp
|
||||
|
||||
@foreach ($episodes as $ep)
|
||||
@if (isset($popularView))
|
||||
@php $episode = $ep->episode @endphp
|
||||
@else
|
||||
@php $episode = $ep @endphp
|
||||
@endif
|
||||
|
||||
@if ($limitcounter >= $limit)
|
||||
@break
|
||||
@endif
|
||||
|
||||
<x-episode-thumbnail :episode="$episode" />
|
||||
|
||||
@php $limitcounter++; @endphp
|
||||
@endforeach
|
||||
@@ -1,14 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="scroll-smooth">
|
||||
@include('partials.head')
|
||||
<body class="font-sans antialiased">
|
||||
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-900">
|
||||
@include('layouts.navigation')
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
<x-app-layout>
|
||||
@include('partials.background')
|
||||
<div
|
||||
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="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">
|
||||
<div class="grid md:grid-flow-col gap-4 xl:w-5/6 flex-row">
|
||||
@include('profile.partials.sidebar')
|
||||
<div class="flex flex-col gap-2">
|
||||
@@ -16,8 +8,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@include('layouts.footer')
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</x-app-layout>
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="scroll-smooth">
|
||||
@include('partials.head')
|
||||
|
||||
<body class="font-sans antialiased">
|
||||
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-900">
|
||||
@include('layouts.navigation')
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
<x-app-layout>
|
||||
@include('partials.background')
|
||||
<div 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="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">
|
||||
<div class="grid md:grid-flow-col gap-4 w-5/6 flex-row">
|
||||
@include('profile.partials.sidebar')
|
||||
@include('profile.partials.info')
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@include('layouts.footer')
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</x-app-layout>
|
||||
@@ -1,20 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="scroll-smooth">
|
||||
@include('partials.head')
|
||||
<body class="font-sans antialiased">
|
||||
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-900">
|
||||
@include('layouts.navigation')
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
<x-app-layout>
|
||||
@include('partials.background')
|
||||
<div 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="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">
|
||||
<div class="flex flex-col md:flex-row">
|
||||
@include('profile.partials.sidebar')
|
||||
@livewire('user-likes')
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@include('layouts.footer')
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</x-app-layout>
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="scroll-smooth">
|
||||
@include('partials.head')
|
||||
<body class="font-sans antialiased">
|
||||
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-900">
|
||||
@include('layouts.navigation')
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
<x-app-layout>
|
||||
@include('partials.background')
|
||||
<div
|
||||
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">
|
||||
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">
|
||||
<div class="grid md:grid-flow-col gap-4 xl:w-5/6 flex-row">
|
||||
@include('profile.partials.sidebar')
|
||||
<div class="flex flex-col gap-2">
|
||||
@@ -59,8 +52,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@include('layouts.footer')
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</x-app-layout>
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="scroll-smooth">
|
||||
@include('partials.head')
|
||||
<body class="font-sans antialiased">
|
||||
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-900">
|
||||
@include('layouts.navigation')
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
<x-app-layout>
|
||||
@include('partials.background')
|
||||
<div class="relative max-w-[120rem] mx-auto sm:px-6 lg:px-8 space-y-6 pt-20 mt-[65px] flex flex-row">
|
||||
<div class="relative max-w-[120rem] mx-auto sm:px-6 lg:px-8 space-y-6 pt-10 flex flex-row">
|
||||
<div class="flex flex-col md:flex-row">
|
||||
@include('profile.partials.sidebar')
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
|
||||
@@ -18,8 +11,4 @@
|
||||
@include('modals.create-playlist')
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@include('layouts.footer')
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</x-app-layout>
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="scroll-smooth">
|
||||
@include('partials.head')
|
||||
|
||||
<body class="font-sans antialiased">
|
||||
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-900">
|
||||
@include('layouts.navigation')
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
<x-app-layout>
|
||||
@include('partials.background')
|
||||
<div class="relative max-w-[120rem] mx-auto sm:px-6 lg:px-8 space-y-6 pt-20 mt-[65px] mb-14 flex flex-row">
|
||||
<div class="relative max-w-[120rem] mx-auto sm:px-6 lg:px-8 space-y-6 pt-10 mb-14 flex flex-row">
|
||||
<div class="flex flex-col md:flex-row">
|
||||
@include('profile.partials.sidebar')
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 mt-8 md:mt-0 space-y-6">
|
||||
@@ -35,9 +27,4 @@
|
||||
@vite(['resources/js/user-blacklist.js'])
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@include('layouts.footer')
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</x-app-layout>
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="scroll-smooth">
|
||||
@include('partials.head')
|
||||
<body class="font-sans antialiased">
|
||||
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-900">
|
||||
@include('layouts.navigation')
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
<x-app-layout>
|
||||
@include('partials.background')
|
||||
<div class="relative max-w-[120rem] mx-auto sm:px-6 lg:px-8 space-y-6 pt-20 mt-[65px] flex flex-row">
|
||||
<div class="relative max-w-[120rem] mx-auto sm:px-6 lg:px-8 space-y-6 pt-10 flex flex-row">
|
||||
<div class="flex flex-col md:flex-row">
|
||||
@include('profile.partials.sidebar')
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 mt-8 md:mt-0 space-y-6">
|
||||
@@ -15,8 +8,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@include('layouts.footer')
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</x-app-layout>
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="scroll-smooth">
|
||||
@include('partials.head')
|
||||
<body class="font-sans antialiased">
|
||||
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-900">
|
||||
@include('layouts.navigation')
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
<x-app-layout>
|
||||
@include('partials.background')
|
||||
<div class="relative max-w-[120rem] mx-auto sm:px-6 lg:px-8 space-y-6 pt-20 mt-[65px] flex flex-row">
|
||||
<div class="relative max-w-[120rem] mx-auto sm:px-6 lg:px-8 space-y-6 pt-10 flex flex-row">
|
||||
<div class="flex flex-col md:flex-row">
|
||||
@include('profile.partials.sidebar')
|
||||
@livewire('watched', ['user' => $user])
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@include('layouts.footer')
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</x-app-layout>
|
||||
|
||||
@@ -1,17 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="scroll-smooth">
|
||||
@include('partials.head')
|
||||
|
||||
<body class="font-sans antialiased">
|
||||
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-900">
|
||||
@include('layouts.navigation')
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
<x-app-layout>
|
||||
@include('partials.background')
|
||||
@livewire('live-search')
|
||||
</main>
|
||||
@include('layouts.footer')
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</x-app-layout>
|
||||
|
||||
@@ -1,18 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="scroll-smooth">
|
||||
|
||||
@include('partials.head')
|
||||
|
||||
<body class="font-sans antialiased">
|
||||
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-900">
|
||||
@include('layouts.navigation')
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
<x-app-layout>
|
||||
@php $episode = $hentai->episodes[0]; @endphp
|
||||
<div class="pt-6 mt-[65px]">
|
||||
<div class="pt-6">
|
||||
<div class="flex flex-col lg:flex-row justify-center">
|
||||
<div class="pt-2 sm:px-2 lg:px-4 space-y-6 max-w-[100%] xl:max-w-[70%] 2xl:max-w-[60%] z-10">
|
||||
@include('series.partials.info')
|
||||
@include('stream.partials.info', ['streamPage' => false])
|
||||
|
||||
@include('series.partials.episodes')
|
||||
|
||||
@@ -23,8 +14,5 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@include('layouts.footer')
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</x-app-layout>
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<div class="bg-transparent rounded-lg overflow-hidden bg-white dark:bg-neutral-800 p-5">
|
||||
<a class="leading-normal font-bold text-lg text-rose-600">
|
||||
<div 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="p-5 md:p-7">
|
||||
<a class="text-lg font-bold text-gray-900 dark:text-white">
|
||||
{{ __('home.episodes') }} ({{ $hentai->episodes->count() }})
|
||||
</a>
|
||||
|
||||
<!-- Episode List -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-1 md:grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-2">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-1 md:grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-2 mt-4">
|
||||
@foreach ($hentai->episodes as $episode)
|
||||
<x-episode-thumbnail :episode="$episode" />
|
||||
<x-episode-cover :episode="$episode" view="thumbnail" />
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
<div class="bg-transparent rounded-lg overflow-hidden bg-white dark:bg-neutral-800 p-5">
|
||||
<!-- Cover -->
|
||||
<div class="w-[100px] md:w-[150px] mr-4 float-left">
|
||||
<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">
|
||||
<!-- Title -->
|
||||
<h1 class="text-3xl font-bold text-rose-600">
|
||||
{{ $episode->title }} ({{ $episode->title_jpn }})
|
||||
</h1>
|
||||
<div>
|
||||
<a data-te-toggle="tooltip"
|
||||
title="Released {{ \Carbon\Carbon::parse($episode->release_date)->diffForHumans(['parts' => 2]) }}"
|
||||
class="text-l text-gray-800 dark:text-white leading-tight pl-1">
|
||||
<i class="fa-regular fa-calendar"></i> {{ $episode->release_date }}
|
||||
|
|
||||
</a>
|
||||
<a href="{{ route('hentai.search', ['order' => 'recently-uploaded', 'studios[0]' => $episode->studio->slug]) }}"
|
||||
class="text-l text-gray-800 dark:text-white leading-tight hover:underline hover:underline-offset-4">
|
||||
{{ $episode->studio->name }}
|
||||
</a>
|
||||
</div>
|
||||
<hr class="border-gray-400/40 mt-2 mb-2">
|
||||
<p class="leading-normal font-bold text-lg text-rose-600">
|
||||
{{ __('stream.description') }}
|
||||
</p>
|
||||
<p class="text-gray-800 dark:text-gray-200 leading-tight min-h-[50%]">
|
||||
{{ $hentai->description }}
|
||||
</p>
|
||||
<hr class="border-gray-400/40 mt-2 mb-1">
|
||||
<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="relative block items-center px-2 py-2 mt-1 dark:focus:ring-offset-gray-800 border border-transparent rounded-md font-semibold text-xs text-green-500 dark:hover:text-white hover:text-white uppercase tracking-widest 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 transition ease-in-out duration-150">
|
||||
{{ $tag->name }}
|
||||
</a>
|
||||
@elseif($tag->slug == 'censored')
|
||||
<a href="{{ route('hentai.search', ['order' => 'recently-uploaded', 'tags[0]' => $tag->slug]) }}"
|
||||
class="relative block items-center px-2 py-2 mt-1 dark:focus:ring-offset-gray-800 border border-transparent rounded-md font-semibold text-xs text-yellow-600 dark:hover:text-white hover:text-white uppercase tracking-widest 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 transition ease-in-out duration-150">
|
||||
{{ $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="relative block items-center px-2 py-2 mt-1 dark:focus:ring-offset-gray-800 border border-transparent rounded-md font-semibold text-xs text-red-600 dark:hover:text-white hover:text-white uppercase tracking-widest 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 transition ease-in-out duration-150">
|
||||
<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="relative block items-center px-2 py-2 mt-1 dark:focus:ring-offset-gray-800 border border-transparent rounded-md font-semibold text-xs dark:text-white hover:text-white uppercase tracking-widest 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 transition ease-in-out duration-150">
|
||||
{{ $tag->name }}
|
||||
</a>
|
||||
@endif
|
||||
</li>
|
||||
<a class="text-gray-400">
|
||||
|
|
||||
</a>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,7 +1,6 @@
|
||||
<div class="pt-2 sm:px-2 lg:px-4 2xl:w-[450px]">
|
||||
<div class="bg-transparent rounded-lg overflow-hidden p-2">
|
||||
<div class="pt-2 sm:px-2 lg:px-4 2xl:w-[450px] p-2">
|
||||
@if (count($popularWeekly) > 0)
|
||||
<p class="leading-normal font-bold text-xl dark:text-white pb-2">
|
||||
<p class="leading-normal font-bold text-xl dark:text-white text-black pb-2">
|
||||
{{ __('home.popular-weekly') }}
|
||||
</p>
|
||||
<div class="text-center xl:text-left">
|
||||
@@ -12,11 +11,12 @@
|
||||
@if($counter >= 8)
|
||||
@continue
|
||||
@endif
|
||||
@include('stream.partials.episode-partial')
|
||||
<li>
|
||||
<x-episode-cover :episode="$episode" view="thumbnail"/>
|
||||
</li>
|
||||
@php $counter += 1; @endphp
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="scroll-smooth">
|
||||
@include('partials.head')
|
||||
<body class="font-sans antialiased">
|
||||
<div class="flex flex-col min-h-screen bg-gray-100 dark:bg-neutral-900">
|
||||
@include('layouts.navigation')
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
<div class="pt-6 mt-[65px]">
|
||||
<x-app-layout>
|
||||
<div class="pt-10">
|
||||
<div class="flex flex-col xl:flex-row justify-center">
|
||||
@if($episode->is_dvd_aspect)
|
||||
<div class="pt-2 sm:px-2 lg:px-4 space-y-6 max-w-[100%] xl:max-w-[80%] 2xl:max-w-[58%]">
|
||||
@@ -22,7 +15,6 @@
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@include('admin.stream')
|
||||
<!-- Infos -->
|
||||
@include('stream.partials.info')
|
||||
<!-- Comments -->
|
||||
@@ -45,18 +37,18 @@
|
||||
@include('modals.add-to-playlist')
|
||||
@include('modals.share')
|
||||
|
||||
|
||||
@auth
|
||||
@if(Auth::user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR))
|
||||
@if (auth()->user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR))
|
||||
@include('admin.modals.upload-episode')
|
||||
@include('admin.modals.add-subtitles')
|
||||
@endif
|
||||
|
||||
@if (auth()->user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR) || auth()->user()->hasRole(\App\Enums\UserRole::MODERATOR))
|
||||
@include('admin.modals.edit-episode')
|
||||
@endif
|
||||
@endauth
|
||||
|
||||
<!-- Player Script -->
|
||||
@vite(['resources/js/player.js'])
|
||||
</main>
|
||||
@include('layouts.footer')
|
||||
</div>
|
||||
@livewireScripts
|
||||
</body>
|
||||
</html>
|
||||
</x-app-layout>
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
<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>
|
||||
@@ -1,56 +1,66 @@
|
||||
<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>
|
||||
|
||||
<div class="mb-5 flex items-center justify-between">
|
||||
<h2 class="text-xl font-bold text-gray-900 dark:text-white">
|
||||
{{ __('stream.gallery') }}
|
||||
</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 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
|
||||
data-te-lightbox-init
|
||||
class="grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
|
||||
|
||||
@foreach($gallery as $index => $image)
|
||||
|
||||
<div class="{{ $index >= 5 ? 'hidden extra-gallery-item' : '' }}">
|
||||
|
||||
<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">
|
||||
|
||||
<img
|
||||
onClick="(function(){player.play(); player.pause(); })();"
|
||||
src="{{ $image->thumbnail_url }}"
|
||||
data-te-img="{{ $image->image_url }}"
|
||||
alt="{{ $episode->title }} - Screenshot {{ $index + 1 }}"
|
||||
class="aspect-video w-full cursor-zoom-in object-cover transition duration-300 group-hover:scale-105"
|
||||
>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</div>
|
||||
|
||||
@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>
|
||||
|
||||
@if ($gallery->count() > 5)
|
||||
<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);
|
||||
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>
|
||||
@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>
|
||||
|
||||
@@ -1,167 +1,246 @@
|
||||
<div class="overflow-hidden p-5 bg-transparent bg-white rounded-lg dark:bg-neutral-800">
|
||||
@props([
|
||||
'streamPage' => true,
|
||||
])
|
||||
|
||||
<div
|
||||
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="p-5 md:p-7">
|
||||
@if($streamPage)
|
||||
<input id="e_id" type="hidden" value="{{ $episode->id }}" />
|
||||
@endif
|
||||
|
||||
<div class="flex flex-col gap-6 lg:flex-row">
|
||||
<!-- 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 class="hidden shrink-0 md:block">
|
||||
<img
|
||||
alt="{{ $episode->title }}"
|
||||
loading="lazy"
|
||||
width="180"
|
||||
src="{{ $episode->cover_url }}"
|
||||
class="aspect-[11/16] w-[140px] rounded-2xl object-cover shadow-lg ring-1 ring-black/5 dark:ring-white/10" />
|
||||
</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>
|
||||
<!-- Main Content -->
|
||||
<div class="flex-1">
|
||||
<div class="flex flex-col gap-5 xl:flex-row xl:items-start xl:justify-between">
|
||||
|
||||
<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>
|
||||
<!-- 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">
|
||||
@if ($streamPage)
|
||||
<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>
|
||||
<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 }}
|
||||
|
|
||||
@else
|
||||
<span
|
||||
class="bg-gradient-to-r from-rose-500 to-pink-500 bg-clip-text text-transparent transition">
|
||||
{{ $episode->title }}
|
||||
</span>
|
||||
@endif
|
||||
</h1>
|
||||
|
||||
|
||||
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400 md:text-base">
|
||||
{{ $episode->title_jpn }}
|
||||
</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">
|
||||
|
||||
<!-- 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. 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">
|
||||
|
||||
<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>
|
||||
|
||||
<div>
|
||||
<!-- View Count and Misc Buttons -->
|
||||
<div class="float-right">
|
||||
<div class="grid">
|
||||
<div class="flex gap-x-4">
|
||||
@if($streamPage)
|
||||
<!-- 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
|
||||
@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
|
||||
data-te-toggle="tooltip"
|
||||
title="Please login to like the episode"
|
||||
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">
|
||||
<i class="fa-regular fa-heart"></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
|
||||
href="#comments"
|
||||
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">
|
||||
<i class="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>
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex flex-wrap gap-2">
|
||||
|
||||
@if(!$episode->dmca_takedown)
|
||||
<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
|
||||
data-te-toggle="modal"
|
||||
data-te-target="#modalDownload"
|
||||
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
|
||||
|
||||
<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
|
||||
data-te-toggle="modal"
|
||||
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>
|
||||
</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
|
||||
data-te-toggle="modal"
|
||||
data-te-target="#modalAddToPlaylist"
|
||||
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>
|
||||
</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">
|
||||
|
|
||||
|
||||
@if(auth()->check() && (auth()->user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR) || auth()->user()->hasRole(\App\Enums\UserRole::MODERATOR)))
|
||||
<div class="flex flex-wrap flex-row-reverse gap-2">
|
||||
@if(auth()->user()->hasRole(\App\Enums\UserRole::ADMINISTRATOR))
|
||||
<a
|
||||
data-te-toggle="modal"
|
||||
data-te-target="#modalAddSubtitles"
|
||||
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-plus"></i>
|
||||
Add Subtitles
|
||||
</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
|
||||
data-te-toggle="modal"
|
||||
data-te-target="#modalUploadEpisode"
|
||||
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-plus"></i>
|
||||
Add Episode
|
||||
</a>
|
||||
@endif
|
||||
</li>
|
||||
<a class="text-gray-400">
|
||||
|
|
||||
|
||||
<a
|
||||
data-te-toggle="modal"
|
||||
data-te-target="#modalEditEpisode"
|
||||
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-pen"></i>
|
||||
Edit Episode
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</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
|
||||
</ul>
|
||||
<hr class="mt-2 mb-1 border-gray-400/40">
|
||||
<div class="inline-block pt-5">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gallery -->
|
||||
@if($streamPage)
|
||||
<div class="mt-8 border-t border-gray-200 pt-6 dark:border-white/10">
|
||||
@include('stream.partials.gallery')
|
||||
</div>
|
||||
@endisset
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,16 +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">
|
||||
<div class="pt-2 sm:px-2 lg:px-4 2xl:w-[450px] p-2">
|
||||
<p class="leading-normal font-bold text-xl dark:text-white text-black 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')
|
||||
<li>
|
||||
<x-episode-cover :episode="$episode" view="thumbnail"/>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@@ -1,16 +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">
|
||||
<div class="pt-2 sm:px-2 lg:px-4 2xl:w-[450px] p-2">
|
||||
<p class="leading-normal font-bold text-xl dark:text-white text-black 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')
|
||||
<li>
|
||||
<x-episode-cover :episode="$episode" view="thumbnail"/>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
+15
-5
@@ -45,18 +45,28 @@ Route::group(['middleware' => ['auth', 'auth.admin']], function () {
|
||||
|
||||
// Episode
|
||||
Route::post('/admin/episode/upload', [EpisodeController::class, 'store'])->name('admin.upload.episode');
|
||||
Route::post('/admin/episode/edit', [EpisodeController::class, 'update'])->name('admin.edit');
|
||||
|
||||
|
||||
// Get Tags used for Upload Form
|
||||
Route::get('/admin/tags', [AdminApiController::class, 'getTags'])->name('admin.tags');
|
||||
Route::get('/admin/studios', [AdminApiController::class, 'getStudios'])->name('admin.studios');
|
||||
|
||||
// Get Tags for editing Episode
|
||||
Route::get('/admin/tags/{episode_id}', [AdminApiController::class, 'getEpisodeTags'])->name('admin.tags.episode');
|
||||
Route::get('/admin/studio/{episode_id}', [AdminApiController::class, 'getEpisodeStudio'])->name('admin.studio.episode');
|
||||
|
||||
// Subtitles
|
||||
Route::get('/admin/subtitles/{episode_id}', [AdminApiController::class, 'getSubtitles'])->name('admin.subtitles');
|
||||
Route::post('/admin/add-new-subtitle', [SubtitleController::class, 'store'])->name('admin.add.new.subtitle');
|
||||
Route::post('/admin/update-subtitles', [SubtitleController::class, 'update'])->name('admin.update.subtitles');
|
||||
});
|
||||
|
||||
/*
|
||||
|---------------------------------------------------------------------------------
|
||||
| Moderator Routes
|
||||
|---------------------------------------------------------------------------------
|
||||
*/
|
||||
Route::group(['middleware' => ['auth', 'auth.moderator']], function () {
|
||||
// Get Tags for editing Episode
|
||||
Route::get('/admin/tags/{episode_id}', [AdminApiController::class, 'getEpisodeTags'])->name('admin.tags.episode');
|
||||
Route::get('/admin/studio/{episode_id}', [AdminApiController::class, 'getEpisodeStudio'])->name('admin.studio.episode');
|
||||
|
||||
// Edit Episode
|
||||
Route::post('/admin/episode/edit', [EpisodeController::class, 'update'])->name('admin.episode.edit');
|
||||
});
|
||||
+5
-3
@@ -2,6 +2,7 @@
|
||||
|
||||
use Illuminate\Foundation\Inspiring;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Schedule;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -14,6 +15,7 @@ use Illuminate\Support\Facades\Artisan;
|
||||
|
|
||||
*/
|
||||
|
||||
Artisan::command('inspire', function () {
|
||||
$this->comment(Inspiring::quote());
|
||||
})->purpose('Display an inspiring quote');
|
||||
Schedule::command('app:auto-stats')->hourly();
|
||||
Schedule::command('app:reset-user-downloads')->daily();
|
||||
Schedule::command('app:generate-sitemap')->daily();
|
||||
Schedule::command('app:sync-subscription-keys')->daily();
|
||||
|
||||
@@ -18,6 +18,25 @@ export default {
|
||||
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")],
|
||||
|
||||
Reference in New Issue
Block a user