From 67f5d0db8b5fd689b288a315baecece008cf5127 Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 14:06:00 +0100 Subject: [PATCH 01/20] Remove laravelista/comments --- app/Models/Episode.php | 3 +- app/Models/Hentai.php | 3 +- app/Models/User.php | 4 +- app/Override/Comments/CommentPolicy.php | 56 ----- app/Override/Comments/CommentService.php | 138 ------------ composer.json | 11 +- composer.lock | 196 +----------------- resources/views/profile/comments.blade.php | 2 +- .../views/series/partials/comments.blade.php | 2 +- .../views/stream/partials/comments.blade.php | 2 +- .../views/vendor/comments/_comment.blade.php | 87 -------- .../views/vendor/comments/_form.blade.php | 30 --- .../comments/components/comments.blade.php | 80 ------- 13 files changed, 10 insertions(+), 604 deletions(-) delete mode 100644 app/Override/Comments/CommentPolicy.php delete mode 100644 app/Override/Comments/CommentService.php delete mode 100644 resources/views/vendor/comments/_comment.blade.php delete mode 100644 resources/views/vendor/comments/_form.blade.php delete mode 100644 resources/views/vendor/comments/components/comments.blade.php diff --git a/app/Models/Episode.php b/app/Models/Episode.php index eef658e..7029eb3 100644 --- a/app/Models/Episode.php +++ b/app/Models/Episode.php @@ -8,7 +8,6 @@ use App\Models\PopularWeekly; use App\Models\PopularDaily; use Conner\Tagging\Taggable; -use Laravelista\Comments\Commentable; use Laravel\Scout\Searchable; use Maize\Markable\Markable; use Maize\Markable\Models\Like; @@ -26,7 +25,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; class Episode extends Model implements Sitemapable { - use Commentable, Markable, Taggable; + use Markable, Taggable; use HasFactory; use Searchable; diff --git a/app/Models/Hentai.php b/app/Models/Hentai.php index f17bd6f..c07852a 100644 --- a/app/Models/Hentai.php +++ b/app/Models/Hentai.php @@ -10,11 +10,10 @@ use Illuminate\Support\Carbon; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Conner\Tagging\Taggable; -use Laravelista\Comments\Commentable; class Hentai extends Model implements Sitemapable { - use Commentable, Taggable; + use Taggable; use HasFactory; /** diff --git a/app/Models/User.php b/app/Models/User.php index e2c7754..fc627a6 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -9,13 +9,11 @@ use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Illuminate\Support\Facades\Storage; -use Laravelista\Comments\Commenter; - use Illuminate\Support\Facades\DB; class User extends Authenticatable { - use HasFactory, Notifiable, Commenter; + use HasFactory, Notifiable; /** * The attributes that are mass assignable. diff --git a/app/Override/Comments/CommentPolicy.php b/app/Override/Comments/CommentPolicy.php deleted file mode 100644 index 5d473d0..0000000 --- a/app/Override/Comments/CommentPolicy.php +++ /dev/null @@ -1,56 +0,0 @@ -getKey() == $comment->commenter_id) || $user->is_admin; - } - - /** - * Can user update the comment - * - * @param $user - * @param Comment $comment - * @return bool - */ - public function update($user, Comment $comment) : bool - { - return $user->getKey() == $comment->commenter_id; - } - - /** - * Can user reply to the comment - * - * @param $user - * @param Comment $comment - * @return bool - */ - public function reply($user, Comment $comment) : bool - { - return $user->getKey() != $comment->commenter_id; - } -} - diff --git a/app/Override/Comments/CommentService.php b/app/Override/Comments/CommentService.php deleted file mode 100644 index b72f260..0000000 --- a/app/Override/Comments/CommentService.php +++ /dev/null @@ -1,138 +0,0 @@ - 'required|string|max:255', - 'guest_email' => 'required|string|email|max:255', - ]; - } - - // Merge guest rules, if any, with normal validation rules. - Validator::make($request->all(), array_merge($guest_rules ?? [], [ - 'commentable_type' => 'required|string', - 'commentable_id' => 'required|string|min:1', - 'message' => 'required|string' - ]))->validate(); - - $model = $request->commentable_type::findOrFail($request->commentable_id); - - $commentClass = Config::get('comments.model'); - $comment = new $commentClass; - - if (!Auth::check()) { - $comment->guest_name = $request->guest_name; - $comment->guest_email = $request->guest_email; - } else { - $comment->commenter()->associate(Auth::user()); - } - - $comment->commentable()->associate($model); - $comment->comment = $request->message; - $comment->approved = !Config::get('comments.approval_required'); - $comment->save(); - - return $comment; - } - - /** - * Handles updating the message of the comment. - * @return mixed the configured comment-model - */ - public function update(Request $request, Comment $comment) - { - Gate::authorize('edit-comment', $comment); - - Validator::make($request->all(), [ - 'message' => 'required|string' - ])->validate(); - - $comment->update([ - 'comment' => $request->message - ]); - - return $comment; - } - - /** - * Handles deleting a comment. - * @return mixed the configured comment-model - */ - public function destroy(Comment $comment): void - { - Gate::authorize('delete-comment', $comment); - - if (Config::get('comments.soft_deletes') == true) { - $comment->delete(); - } else { - $comment->delete(); - } - } - - /** - * Handles creating a reply "comment" to a comment. - * @return mixed the configured comment-model - */ - public function reply(Request $request, Comment $comment) - { - Gate::authorize('reply-to-comment', $comment); - - Validator::make($request->all(), [ - 'message' => 'required|string' - ])->validate(); - - $commentClass = Config::get('comments.model'); - $reply = new $commentClass; - $reply->commenter()->associate(Auth::user()); - $reply->commentable()->associate($comment->commentable); - $reply->parent()->associate($comment); - $reply->comment = $request->message; - $reply->approved = !Config::get('comments.approval_required'); - $reply->save(); - - // Notify - if ($comment->commentable_type == 'App\Models\Episode') { - $episode = Episode::where('id', $comment->commentable_id)->firstOrFail(); - $url = '/hentai/' . $episode->slug . '#comment-' . $reply->id; - - $user = Auth::user(); - - $parentCommentUser = User::where('id', $comment->commenter_id)->firstOrFail(); - $parentCommentUser->notify( - new CommentNotification( - "{$user->name} replied to your comment.", - Str::limit($reply->comment, 50), - $url - ) - ); - } - - return $reply; - } -} diff --git a/composer.json b/composer.json index d0233f2..d59ce9d 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,6 @@ "laravel/scout": "^10.20", "laravel/socialite": "^5.24", "laravel/tinker": "^2.10", - "laravelista/comments": "dev-l11-compatibility", "livewire/livewire": "^3.6.4", "maize-tech/laravel-markable": "^2.3.0", "meilisearch/meilisearch-php": "^1.16", @@ -50,19 +49,13 @@ } ], "autoload": { - "exclude-from-classmap": [ - "vendor/laravelista/comments/src/CommentPolicy.php", - "vendor/laravelista/comments/src/CommentService.php" - ], + "exclude-from-classmap": [], "psr-4": { "App\\": "app/", "Database\\Factories\\": "database/factories/", "Database\\Seeders\\": "database/seeders/" }, - "files": [ - "app/Override/Comments/CommentPolicy.php", - "app/Override/Comments/CommentService.php" - ] + "files": [] }, "autoload-dev": { "psr-4": { diff --git a/composer.lock b/composer.lock index cedb267..68a4f97 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "749225dc4ea2aca06f1639bef889cc59", + "content-hash": "cf750c98603544d91cf1bdb428866a8f", "packages": [ { "name": "brick/math", @@ -581,56 +581,6 @@ ], "time": "2025-03-06T22:45:56+00:00" }, - { - "name": "erusev/parsedown", - "version": "1.7.4", - "source": { - "type": "git", - "url": "https://github.com/erusev/parsedown.git", - "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3", - "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35" - }, - "type": "library", - "autoload": { - "psr-0": { - "Parsedown": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Emanuil Rusev", - "email": "hello@erusev.com", - "homepage": "http://erusev.com" - } - ], - "description": "Parser for Markdown.", - "homepage": "http://parsedown.org", - "keywords": [ - "markdown", - "parser" - ], - "support": { - "issues": "https://github.com/erusev/parsedown/issues", - "source": "https://github.com/erusev/parsedown/tree/1.7.x" - }, - "time": "2019-12-30T22:54:17+00:00" - }, { "name": "firebase/php-jwt", "version": "v7.0.2", @@ -2266,70 +2216,6 @@ }, "time": "2025-01-27T14:24:01+00:00" }, - { - "name": "laravelista/comments", - "version": "dev-l11-compatibility", - "source": { - "type": "git", - "url": "https://github.com/renatokira/comments.git", - "reference": "490764a774d520a4d9e43395b472d0f9bf802ef6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/renatokira/comments/zipball/490764a774d520a4d9e43395b472d0f9bf802ef6", - "reference": "490764a774d520a4d9e43395b472d0f9bf802ef6", - "shasum": "" - }, - "require": { - "erusev/parsedown": "^1.7", - "illuminate/database": "^9.0|^10.0|^11.0", - "illuminate/http": "^9.0|^10.0|^11.0", - "illuminate/pagination": "^9.0|^10.0|^11.0", - "illuminate/queue": "^9.0|^10.0|^11.0", - "illuminate/routing": "^9.0|^10.0|^11.0", - "illuminate/support": "^9.0|^10.0|^11.0", - "php": "^8.0", - "spatie/laravel-honeypot": "^4.5" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Laravelista\\Comments\\ServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Laravelista\\Comments\\": "src/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mario Bašić", - "email": "mario@laravelista.hr", - "homepage": "https://laravelista.hr" - } - ], - "description": "Comments for Laravel.", - "keywords": [ - "comments", - "laravel" - ], - "support": { - "source": "https://github.com/renatokira/comments/tree/l11-compatibility" - }, - "funding": [ - { - "type": "patreon", - "url": "https://www.patreon.com/laravelista" - } - ], - "time": "2024-03-16T14:14:11+00:00" - }, { "name": "league/commonmark", "version": "2.7.1", @@ -5817,82 +5703,6 @@ ], "time": "2025-05-20T08:42:52+00:00" }, - { - "name": "spatie/laravel-honeypot", - "version": "4.6.1", - "source": { - "type": "git", - "url": "https://github.com/spatie/laravel-honeypot.git", - "reference": "38d164f14939e943b92771859fc206c74cba8397" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-honeypot/zipball/38d164f14939e943b92771859fc206c74cba8397", - "reference": "38d164f14939e943b92771859fc206c74cba8397", - "shasum": "" - }, - "require": { - "illuminate/contracts": "^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/encryption": "^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/http": "^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/validation": "^8.0|^9.0|^10.0|^11.0|^12.0", - "nesbot/carbon": "^2.0|^3.0", - "php": "^8.0", - "spatie/laravel-package-tools": "^1.9", - "symfony/http-foundation": "^5.1.2|^6.0|^7.0" - }, - "require-dev": { - "livewire/livewire": "^2.10|^3.0", - "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0|^10.0", - "pestphp/pest-plugin-livewire": "^1.0|^2.1|^3.0", - "phpunit/phpunit": "^9.6|^10.5|^11.5", - "spatie/pest-plugin-snapshots": "^1.1|^2.1", - "spatie/phpunit-snapshot-assertions": "^4.2|^5.1", - "spatie/test-time": "^1.2.1" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Spatie\\Honeypot\\HoneypotServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Spatie\\Honeypot\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Freek Van der Herten", - "email": "freek@spatie.be", - "homepage": "https://spatie.be", - "role": "Developer" - } - ], - "description": "Preventing spam submitted through forms", - "homepage": "https://github.com/spatie/laravel-honeypot", - "keywords": [ - "laravel-honeypot", - "spatie" - ], - "support": { - "source": "https://github.com/spatie/laravel-honeypot/tree/4.6.1" - }, - "funding": [ - { - "url": "https://spatie.be/open-source/support-us", - "type": "custom" - } - ], - "time": "2025-05-05T13:50:37+00:00" - }, { "name": "spatie/laravel-package-tools", "version": "1.92.7", @@ -11900,9 +11710,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "laravelista/comments": 20 - }, + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { diff --git a/resources/views/profile/comments.blade.php b/resources/views/profile/comments.blade.php index 3f65c5a..22e59fe 100644 --- a/resources/views/profile/comments.blade.php +++ b/resources/views/profile/comments.blade.php @@ -65,7 +65,7 @@
- @comments(['model' => $episode]) + {{--@comments(['model' => $episode])--}}
@endforeach diff --git a/resources/views/series/partials/comments.blade.php b/resources/views/series/partials/comments.blade.php index 811fbd6..1f0589c 100644 --- a/resources/views/series/partials/comments.blade.php +++ b/resources/views/series/partials/comments.blade.php @@ -3,6 +3,6 @@

{{ __('home.latest-comments') }}

- @comments(['model' => $hentai]) + {{--@comments(['model' => $hentai])--}} diff --git a/resources/views/stream/partials/comments.blade.php b/resources/views/stream/partials/comments.blade.php index 1f46bae..6427f85 100644 --- a/resources/views/stream/partials/comments.blade.php +++ b/resources/views/stream/partials/comments.blade.php @@ -3,6 +3,6 @@

{{ __('home.latest-comments') }}

- @comments(['model' => $episode]) + {{--@comments(['model' => $episode])--}} diff --git a/resources/views/vendor/comments/_comment.blade.php b/resources/views/vendor/comments/_comment.blade.php deleted file mode 100644 index ac77b9f..0000000 --- a/resources/views/vendor/comments/_comment.blade.php +++ /dev/null @@ -1,87 +0,0 @@ -@inject('markdown', 'Parsedown') -@php - // TODO: There should be a better place for this. - $markdown->setSafeMode(true); -@endphp - - -
- -
- {{ $comment->commenter->name }} Avatar -
- -
-
- @if($comment->commenter->is_patreon) -
{{ $comment->commenter->name }} - {{ $comment->created_at->diffForHumans() }}
- @else -
{{ $comment->commenter->name }} - {{ $comment->created_at->diffForHumans() }}
- @endif -
-
{!! $markdown->line($comment->comment) !!}
- - @if (! Illuminate\Support\Facades\Route::is('profile.comments')) -
- @can('reply-to-comment', $comment) - - @endcan - @can('edit-comment', $comment) - - @endcan - @can('delete-comment', $comment) - @lang('comments::comments.delete') - - @endcan -
- @endif - - - @can('edit-comment', $comment) - @include('modals.comment-edit') - @endcan - - @can('reply-to-comment', $comment) - @include('modals.comment-reply') - @endcan - -
{{-- Margin bottom --}} - - - - {{-- Recursion for children --}} - @if($grouped_comments->has($comment->getKey()) && $indentationLevel <= $maxIndentationLevel) - {{-- TODO: Don't repeat code. Extract to a new file and include it. --}} - @foreach($grouped_comments[$comment->getKey()] as $child) -
-
- @include('comments::_comment', [ - 'comment' => $child, - 'grouped_comments' => $grouped_comments - ]) -
- @endforeach - @endif - -
-
- -{{-- Recursion for children --}} -@if($grouped_comments->has($comment->getKey()) && $indentationLevel > $maxIndentationLevel) - {{-- TODO: Don't repeat code. Extract to a new file and include it. --}} - @foreach($grouped_comments[$comment->getKey()] as $child) - @include('comments::_comment', [ - 'comment' => $child, - 'grouped_comments' => $grouped_comments - ]) - @endforeach -@endif diff --git a/resources/views/vendor/comments/_form.blade.php b/resources/views/vendor/comments/_form.blade.php deleted file mode 100644 index ecb7536..0000000 --- a/resources/views/vendor/comments/_form.blade.php +++ /dev/null @@ -1,30 +0,0 @@ - -
- @if($errors->has('commentable_type')) - - @endif - @if($errors->has('commentable_id')) - - @endif -
- @csrf - @honeypot - - - -
- - -
- - - @lang('comments::comments.submit') - -
-
- -
diff --git a/resources/views/vendor/comments/components/comments.blade.php b/resources/views/vendor/comments/components/comments.blade.php deleted file mode 100644 index d02a0e0..0000000 --- a/resources/views/vendor/comments/components/comments.blade.php +++ /dev/null @@ -1,80 +0,0 @@ -@php - if (isset($approved) and $approved == true) { - $comments = $model->approvedComments; - } else { - $comments = $model->comments; - } -@endphp - -@if($comments->count() < 1) -
@lang('comments::comments.there_are_no_comments')
-@endif - -
- @php - $comments = $comments->sortByDesc('created_at'); - - if (isset($perPage)) { - $page = request()->query('page', 1) - 1; - - $parentComments = $comments->where('child_id', ''); - - $slicedParentComments = $parentComments->slice($page * $perPage, $perPage); - - $m = Config::get('comments.model'); // This has to be done like this, otherwise it will complain. - $modelKeyName = (new $m)->getKeyName(); // This defaults to 'id' if not changed. - - $slicedParentCommentsIds = $slicedParentComments->pluck($modelKeyName)->toArray(); - - // Remove parent Comments from comments. - $comments = $comments->where('child_id', '!=', ''); - - $grouped_comments = new \Illuminate\Pagination\LengthAwarePaginator( - $slicedParentComments->merge($comments)->groupBy('child_id'), - $parentComments->count(), - $perPage - ); - - $grouped_comments->withPath(request()->url()); - } else { - $grouped_comments = $comments->groupBy('child_id'); - } - @endphp - @foreach($grouped_comments as $comment_id => $comments) - {{-- Process parent nodes --}} - @if($comment_id == '') - @foreach($comments as $comment) - @include('comments::_comment', [ - 'comment' => $comment, - 'grouped_comments' => $grouped_comments, - 'maxIndentationLevel' => $maxIndentationLevel ?? 3 - ]) - @endforeach - @endif - @endforeach -
- -@isset ($perPage) - {{ $grouped_comments->links() }} -@endisset - -@if ((! Illuminate\Support\Facades\Route::is('profile.comments')) && (! Illuminate\Support\Facades\Route::is('home.index'))) - @auth - @include('comments::_form') - @elseif(Config::get('comments.guest_commenting') == true) - @include('comments::_form', [ - 'guest_commenting' => true - ]) - @else -
-
-
@lang('comments::comments.authentication_required')
-

@lang('comments::comments.you_must_login_to_post_a_comment')

-
- - Login - -
-
- @endauth -@endif From 5f575024e2f720f5abf1b504a66a126081faba88 Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 15:02:14 +0100 Subject: [PATCH 02/20] Add Livewire comment system --- app/Livewire/Comment.php | 90 +++++++++++++++++ app/Livewire/Comments.php | 56 +++++++++++ app/Models/Comment.php | 61 ++++++++++++ app/Models/Episode.php | 5 + app/Models/Presenters/CommentPresenter.php | 28 ++++++ app/Policies/CommentPolicy.php | 22 +++++ ...026_01_10_120521_create_comments_table.php | 38 +++++++ .../views/home/partials/comments.blade.php | 4 +- resources/views/livewire/comment.blade.php | 99 +++++++++++++++++++ resources/views/livewire/comments.blade.php | 54 ++++++++++ resources/views/partials/comment.blade.php | 22 ----- resources/views/stream/index.blade.php | 2 +- .../views/stream/partials/comments.blade.php | 8 -- 13 files changed, 456 insertions(+), 33 deletions(-) create mode 100644 app/Livewire/Comment.php create mode 100644 app/Livewire/Comments.php create mode 100644 app/Models/Comment.php create mode 100644 app/Models/Presenters/CommentPresenter.php create mode 100644 app/Policies/CommentPolicy.php create mode 100644 database/migrations/2026_01_10_120521_create_comments_table.php create mode 100644 resources/views/livewire/comment.blade.php create mode 100644 resources/views/livewire/comments.blade.php delete mode 100644 resources/views/partials/comment.blade.php delete mode 100644 resources/views/stream/partials/comments.blade.php diff --git a/app/Livewire/Comment.php b/app/Livewire/Comment.php new file mode 100644 index 0000000..65d823f --- /dev/null +++ b/app/Livewire/Comment.php @@ -0,0 +1,90 @@ + '' + ]; + + public $isEditing = false; + + public $editState = [ + 'body' => '' + ]; + + protected $listeners = [ + 'refresh' => '$refresh' + ]; + + protected $validationAttributes = [ + 'replyState.body' => 'reply' + ]; + + public function updatedIsEditing($isEditing) + { + if (! $isEditing) { + return; + } + + $this->editState = [ + 'body' => $this->comment->body + ]; + } + + public function editComment() + { + $this->authorize('update', $this->comment); + + $this->comment->update($this->editState); + + $this->isEditing = false; + } + + public function deleteComment() + { + $this->authorize('destroy', $this->comment); + + $this->comment->delete(); + } + + public function postReply() + { + if (! $this->comment->depth() < 2) { + return; + } + + $this->validate([ + 'replyState.body' => 'required' + ]); + + $reply = $this->comment->children()->make($this->replyState); + $reply->user()->associate(auth()->user()); + $reply->commentable()->associate($this->comment->commentable); + + $reply->save(); + + $this->replyState = [ + 'body' => '' + ]; + + $this->isReplying = false; + + $this->dispatch('refresh')->self(); + } + + public function render() + { + return view('livewire.comment'); + } +} \ No newline at end of file diff --git a/app/Livewire/Comments.php b/app/Livewire/Comments.php new file mode 100644 index 0000000..824a4ec --- /dev/null +++ b/app/Livewire/Comments.php @@ -0,0 +1,56 @@ + '' + ]; + + protected $validationAttributes = [ + 'newCommentState.body' => 'comment' + ]; + + protected $listeners = [ + 'refresh' => '$refresh' + ]; + + public function postComment() + { + $this->validate([ + 'newCommentState.body' => 'required' + ]); + + $comment = $this->model->comments()->make($this->newCommentState); + $comment->user()->associate(auth()->user()); + $comment->save(); + + $this->newCommentState = [ + 'body' => '' + ]; + + $this->resetPage(); + } + + public function render() + { + $comments = $this->model + ->comments() + ->with('user', 'children.user', 'children.children') + ->parent() + ->latest() + ->paginate(3); + + return view('livewire.comments', [ + 'comments' => $comments + ]); + } +} \ No newline at end of file diff --git a/app/Models/Comment.php b/app/Models/Comment.php new file mode 100644 index 0000000..45b4071 --- /dev/null +++ b/app/Models/Comment.php @@ -0,0 +1,61 @@ +belongsTo(User::class); + } + + public function scopeParent(Builder $builder) + { + $builder->whereNull('parent_id'); + } + + public function children() + { + return $this->hasMany(Comment::class, 'parent_id')->oldest(); + } + + public function commentable() + { + return $this->morphTo(); + } + + public function parent() + { + return $this->hasOne(Comment::class, 'id', 'parent_id'); + } + + // Recursevly calculates how deep the nesting is + public function depth(): int + { + return $this->parent + ? $this->parent->depth() + 1 + : 0; + } +} diff --git a/app/Models/Episode.php b/app/Models/Episode.php index 7029eb3..31ef83d 100644 --- a/app/Models/Episode.php +++ b/app/Models/Episode.php @@ -160,6 +160,11 @@ class Episode extends Model implements Sitemapable return cache()->remember('episodeComments' . $this->id, 300, fn() => $this->comments->count()); } + public function comments() + { + return $this->morphMany(Comment::class, 'commentable'); + } + public function getProblematicTags(): string { $problematicTags = ['Gore', 'Scat', 'Horror']; diff --git a/app/Models/Presenters/CommentPresenter.php b/app/Models/Presenters/CommentPresenter.php new file mode 100644 index 0000000..645f85f --- /dev/null +++ b/app/Models/Presenters/CommentPresenter.php @@ -0,0 +1,28 @@ +comment = $comment; + } + + public function markdownBody() + { + return Str::of($this->comment->body)->markdown([ + 'html_input' => 'strip', + ]); + } + + public function relativeCreatedAt() + { + return $this->comment->created_at->diffForHumans(); + } +} \ No newline at end of file diff --git a/app/Policies/CommentPolicy.php b/app/Policies/CommentPolicy.php new file mode 100644 index 0000000..4f52686 --- /dev/null +++ b/app/Policies/CommentPolicy.php @@ -0,0 +1,22 @@ +id === $comment->user_id; + } + + public function destroy(User $user, Comment $comment): bool + { + return $user->id === $comment->user_id; + } +} \ No newline at end of file diff --git a/database/migrations/2026_01_10_120521_create_comments_table.php b/database/migrations/2026_01_10_120521_create_comments_table.php new file mode 100644 index 0000000..98806de --- /dev/null +++ b/database/migrations/2026_01_10_120521_create_comments_table.php @@ -0,0 +1,38 @@ +id(); + $table->foreignId('user_id')->constrained()->cascadeOnDelete(); + $table->foreignId('parent_id')->nullable()->constrained('comments')->cascadeOnDelete(); + $table->morphs('commentable'); // What is being commented on + $table->text('body'); + $table->softDeletes(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('comments'); + + // Revert to old table from laravelista/comments + Schema::rename('comments_old', 'comments'); + } +}; diff --git a/resources/views/home/partials/comments.blade.php b/resources/views/home/partials/comments.blade.php index 5ed6af4..2548d70 100644 --- a/resources/views/home/partials/comments.blade.php +++ b/resources/views/home/partials/comments.blade.php @@ -31,7 +31,7 @@
- @include('partials.comment', ['comment' => $comment]) + {{--@include('partials.comment', ['comment' => $comment])--}}
@elseif($comment->commentable_type == 'App\Models\Hentai') @@ -53,7 +53,7 @@
- @include('partials.comment', ['comment' => $comment]) + {{--@include('partials.comment', ['comment' => $comment])--}}
@endif diff --git a/resources/views/livewire/comment.blade.php b/resources/views/livewire/comment.blade.php new file mode 100644 index 0000000..fccc75d --- /dev/null +++ b/resources/views/livewire/comment.blade.php @@ -0,0 +1,99 @@ +
+
+
+ {{ $comment->user->name }} +
+
+ +
+ @if ($isEditing) +
+
+ + + @error('editState.body') +

{{ $message }}

+ @enderror +
+
+ +
+
+ @else +

{!! $comment->presenter()->markdownBody() !!}

+ @endif +
+
+ + {{ $comment->presenter()->relativeCreatedAt() }} + + @auth + {{--@if ($comment->hasParent())--}} + @if ($comment->depth() < 2) + + @endif + {{--@endif--}} + + @can ('update', $comment) + + @endcan + + @can ('destroy', $comment) + + @endcan + @endauth +
+
+
+ +
+ @if ($isReplying) +
+
+ + + @error('replyState.body') +

{{ $message }}

+ @enderror +
+
+ +
+
+ @endif + + @foreach ($comment->children as $child) + + @endforeach +
+
\ No newline at end of file diff --git a/resources/views/livewire/comments.blade.php b/resources/views/livewire/comments.blade.php new file mode 100644 index 0000000..2aa0d26 --- /dev/null +++ b/resources/views/livewire/comments.blade.php @@ -0,0 +1,54 @@ +
+
+
+
+

Comments

+
+
+
+ @if ($comments->isNotEmpty()) + @foreach($comments as $comment) + + @endforeach + {{ $comments->links() }} + @else +

No comments yet.

+ @endif +
+
+
+
+ @auth +
+
+ {{ auth()->user()->name }} +
+
+
+
+ + + @error('newCommentState.body') +

{{ $message }}

+ @enderror +
+
+ +
+
+
+
+ @endauth + + @guest +

Log in to comment.

+ @endguest +
+
+
\ No newline at end of file diff --git a/resources/views/partials/comment.blade.php b/resources/views/partials/comment.blade.php deleted file mode 100644 index c9eb525..0000000 --- a/resources/views/partials/comment.blade.php +++ /dev/null @@ -1,22 +0,0 @@ -@inject('markdown', 'Parsedown') -@php - // TODO: There should be a better place for this. - $markdown->setSafeMode(true); -@endphp -
- @php $user = cache()->rememberForever('commentUser'.$comment->commenter_id, fn () => \App\Models\User::where('id', $comment->commenter_id)->first()); @endphp -
- {{ $user->name }} Avatar -
-
-
- @if($user->is_patreon) -
{{ $user->name }} - {{ \Carbon\Carbon::parse($comment->created_at)->diffForHumans() }}
- @else -
{{ $user->name }} - {{ \Carbon\Carbon::parse($comment->created_at)->diffForHumans() }}
- @endif -
-
{!! $markdown->line($comment->comment) !!}
-
-
-
\ No newline at end of file diff --git a/resources/views/stream/index.blade.php b/resources/views/stream/index.blade.php index 89fd342..826828d 100644 --- a/resources/views/stream/index.blade.php +++ b/resources/views/stream/index.blade.php @@ -26,7 +26,7 @@ @include('stream.partials.info') - @include('stream.partials.comments') +
@if(! $isMobile) diff --git a/resources/views/stream/partials/comments.blade.php b/resources/views/stream/partials/comments.blade.php deleted file mode 100644 index 6427f85..0000000 --- a/resources/views/stream/partials/comments.blade.php +++ /dev/null @@ -1,8 +0,0 @@ -
-
-

- {{ __('home.latest-comments') }} -

- {{--@comments(['model' => $episode])--}} -
-
From 4c2a6024d715ec5848187ba469b083bb1aef753a Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 15:27:37 +0100 Subject: [PATCH 03/20] Add dark mode --- resources/views/livewire/comment.blade.php | 18 ++++++++---------- resources/views/livewire/comments.blade.php | 16 ++++++++-------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/resources/views/livewire/comment.blade.php b/resources/views/livewire/comment.blade.php index fccc75d..876286a 100644 --- a/resources/views/livewire/comment.blade.php +++ b/resources/views/livewire/comment.blade.php @@ -5,7 +5,7 @@
- {{ $comment->user->name }} +

{{ $comment->user->name }}

@if ($isEditing) @@ -13,7 +13,7 @@
@error('editState.body') @@ -28,24 +28,22 @@
@else -

{!! $comment->presenter()->markdownBody() !!}

+
{!! $comment->presenter()->markdownBody() !!}
@endif
- + {{ $comment->presenter()->relativeCreatedAt() }} @auth - {{--@if ($comment->hasParent())--}} @if ($comment->depth() < 2) - @endif - {{--@endif--}} @can ('update', $comment) - @endcan @@ -60,7 +58,7 @@ }" @click="confirmCommentDeletion" type="button" - class="text-gray-900 font-medium" + class="text-gray-900 dark:text-gray-100 font-medium" > Delete @@ -76,7 +74,7 @@
@error('replyState.body') diff --git a/resources/views/livewire/comments.blade.php b/resources/views/livewire/comments.blade.php index 2aa0d26..7005fc8 100644 --- a/resources/views/livewire/comments.blade.php +++ b/resources/views/livewire/comments.blade.php @@ -1,8 +1,8 @@
-
-
+
+
-

Comments

+

Comments

@@ -12,12 +12,12 @@ @endforeach {{ $comments->links() }} @else -

No comments yet.

+

No comments yet.

@endif
-
+
@auth
@@ -28,7 +28,7 @@
@error('newCommentState.body') @@ -37,7 +37,7 @@
@@ -47,7 +47,7 @@ @endauth @guest -

Log in to comment.

+

Log in to comment.

@endguest
From a3b66b483bcece554e9e5b3946c131194d2300e6 Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 15:34:05 +0100 Subject: [PATCH 04/20] Add admin and donator badge --- resources/views/livewire/comment.blade.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/resources/views/livewire/comment.blade.php b/resources/views/livewire/comment.blade.php index 876286a..4de4f20 100644 --- a/resources/views/livewire/comment.blade.php +++ b/resources/views/livewire/comment.blade.php @@ -4,8 +4,14 @@ {{ $comment->user->name }}
-
+

{{ $comment->user->name }}

+ @if($comment->user->is_admin) + + @endif + @if($comment->user->is_patreon) + + @endif
@if ($isEditing) From e136e8e1b663f40018e6dc772628fc9c3ed827bd Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 15:45:41 +0100 Subject: [PATCH 05/20] Refresh on delete --- app/Livewire/Comment.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Livewire/Comment.php b/app/Livewire/Comment.php index 65d823f..cdda05c 100644 --- a/app/Livewire/Comment.php +++ b/app/Livewire/Comment.php @@ -56,6 +56,8 @@ class Comment extends Component $this->authorize('destroy', $this->comment); $this->comment->delete(); + + $this->dispatch('refresh'); } public function postReply() From 6ce0255764b9a37fb54e0b2a822fe8dc57ae71cd Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 15:45:52 +0100 Subject: [PATCH 06/20] Remove ring offset --- resources/views/livewire/comment.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/livewire/comment.blade.php b/resources/views/livewire/comment.blade.php index 4de4f20..f800ba9 100644 --- a/resources/views/livewire/comment.blade.php +++ b/resources/views/livewire/comment.blade.php @@ -28,7 +28,7 @@
@@ -89,7 +89,7 @@
From 871028930b388654e75a28332a2fb3f1b17f7334 Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 16:41:06 +0100 Subject: [PATCH 07/20] Migrate existing comments --- ...026_01_10_120521_create_comments_table.php | 38 ---------- ...26_01_10_120521_migrate_comments_table.php | 75 +++++++++++++++++++ 2 files changed, 75 insertions(+), 38 deletions(-) delete mode 100644 database/migrations/2026_01_10_120521_create_comments_table.php create mode 100644 database/migrations/2026_01_10_120521_migrate_comments_table.php diff --git a/database/migrations/2026_01_10_120521_create_comments_table.php b/database/migrations/2026_01_10_120521_create_comments_table.php deleted file mode 100644 index 98806de..0000000 --- a/database/migrations/2026_01_10_120521_create_comments_table.php +++ /dev/null @@ -1,38 +0,0 @@ -id(); - $table->foreignId('user_id')->constrained()->cascadeOnDelete(); - $table->foreignId('parent_id')->nullable()->constrained('comments')->cascadeOnDelete(); - $table->morphs('commentable'); // What is being commented on - $table->text('body'); - $table->softDeletes(); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('comments'); - - // Revert to old table from laravelista/comments - Schema::rename('comments_old', 'comments'); - } -}; diff --git a/database/migrations/2026_01_10_120521_migrate_comments_table.php b/database/migrations/2026_01_10_120521_migrate_comments_table.php new file mode 100644 index 0000000..94278fc --- /dev/null +++ b/database/migrations/2026_01_10_120521_migrate_comments_table.php @@ -0,0 +1,75 @@ +dropForeign(['child_id']); + $table->dropIndex(['commenter_id', 'commenter_type']); + }); + + // Rename and Drop columns + Schema::table('comments', function (Blueprint $table) { + $table->renameColumn('commenter_id', 'user_id'); + $table->dropColumn('commenter_type'); + $table->dropColumn('guest_name'); + $table->dropColumn('guest_email'); + $table->renameColumn('child_id', 'parent_id'); + $table->renameColumn('comment', 'body'); + $table->dropColumn('approved'); + }); + + // Add Foreign Keys + Schema::table('comments', function (Blueprint $table) { + // Ensure the column is unsigned + $table->bigInteger('user_id')->unsigned()->change(); + + // Add the foreign key constraint + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + $table->foreign('parent_id')->references('id')->on('comments')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // Drop Foreign Keys + Schema::table('comments', function (Blueprint $table) { + $table->dropForeign(['parent_id']); + $table->dropForeign(['user_id']); + }); + + // Rename and Re-Add Columns + Schema::table('comments', function (Blueprint $table) { + $table->renameColumn('user_id', 'commenter_id'); + $table->string('commenter_type')->nullable()->after('commenter_id'); + $table->string('guest_name')->nullable()->after('commenter_type'); + $table->string('guest_email')->nullable()->after('guest_name'); + $table->renameColumn('parent_id', 'child_id'); + $table->renameColumn('body', 'comment'); + $table->boolean('approved')->default(true)->after('comment'); + }); + + DB::table('comments')->update([ + 'commenter_type' => 'App\Models\User', + ]); + + // Re-Add foreign key constraint and index + Schema::table('comments', function (Blueprint $table) { + $table->foreign('child_id')->references('id')->on('comments')->onDelete('cascade'); + $table->index(["commenter_id", "commenter_type"]); + }); + } +}; From 7810cd53fbf4c039398fc3403432ceaee51c7819 Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 18:54:48 +0100 Subject: [PATCH 08/20] Add comments to Hentai --- app/Models/Hentai.php | 5 +++++ resources/views/series/index.blade.php | 2 +- resources/views/series/partials/comments.blade.php | 8 -------- 3 files changed, 6 insertions(+), 9 deletions(-) delete mode 100644 resources/views/series/partials/comments.blade.php diff --git a/app/Models/Hentai.php b/app/Models/Hentai.php index c07852a..2c5430a 100644 --- a/app/Models/Hentai.php +++ b/app/Models/Hentai.php @@ -36,6 +36,11 @@ class Hentai extends Model implements Sitemapable return $this->episodes->first()->title; } + public function comments() + { + return $this->morphMany(Comment::class, 'commentable'); + } + /** * Has a Gallery. */ diff --git a/resources/views/series/index.blade.php b/resources/views/series/index.blade.php index 0986d93..0e6f84a 100644 --- a/resources/views/series/index.blade.php +++ b/resources/views/series/index.blade.php @@ -16,7 +16,7 @@ @include('series.partials.episodes') - @include('series.partials.comments') +
@include('series.partials.popular') diff --git a/resources/views/series/partials/comments.blade.php b/resources/views/series/partials/comments.blade.php deleted file mode 100644 index 1f0589c..0000000 --- a/resources/views/series/partials/comments.blade.php +++ /dev/null @@ -1,8 +0,0 @@ -
-
-

- {{ __('home.latest-comments') }} -

- {{--@comments(['model' => $hentai])--}} -
-
From cfd6af59fb2c2deb8540bebfcb37148512299d9c Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 18:55:47 +0100 Subject: [PATCH 09/20] Add Profile Comment Search (Livewire) --- app/Http/Controllers/ProfileController.php | 4 +- app/Livewire/UserComments.php | 49 ++++++++ app/Models/User.php | 10 +- .../views/livewire/user-comments.blade.php | 116 ++++++++++++++++++ resources/views/profile/comments.blade.php | 59 +-------- 5 files changed, 178 insertions(+), 60 deletions(-) create mode 100644 app/Livewire/UserComments.php create mode 100644 resources/views/livewire/user-comments.blade.php diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index 4d77ea2..c58ece8 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -3,8 +3,6 @@ namespace App\Http\Controllers; use App\Models\Episode; -use App\Models\Playlist; -use App\Models\PlaylistEpisode; use App\Models\User; use App\Http\Requests\ProfileUpdateRequest; use Illuminate\Http\RedirectResponse; @@ -84,7 +82,7 @@ class ProfileController extends Controller public function comments(Request $request): View { return view('profile.comments', [ - 'user' => $request->user(), + 'user' => $request->user(), ]); } diff --git a/app/Livewire/UserComments.php b/app/Livewire/UserComments.php new file mode 100644 index 0000000..010dfbb --- /dev/null +++ b/app/Livewire/UserComments.php @@ -0,0 +1,49 @@ +order) { + case 'created_at_desc': + $orderby = 'created_at'; + $orderdirection = 'desc'; + break; + case 'created_at_asc': + $orderby = 'created_at'; + $orderdirection = 'asc'; + break; + default: + $orderby = 'created_at'; + $orderdirection = 'desc'; + } + + + $comments = Comment::where('user_id', $this->model->id) + ->when($this->commentSearch != '', fn ($query) => $query->where('body', 'like', '%'.$this->commentSearch.'%')) + ->orderBy($orderby, $orderdirection) + ->paginate(10); + + return view('livewire.user-comments', [ + 'comments' => $comments + ]); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index fc627a6..d9de512 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -89,9 +89,17 @@ class User extends Authenticatable /** * Has Many Comments. */ + public function comments() + { + return $this->hasMany(Comment::class, 'user_id'); + } + + /** + * Get Comment Count. + */ public function commentCount(): int { - return DB::table('comments')->where('commenter_id', $this->id)->count(); + return cache()->remember('userComments' . $this->id, 300, fn() => $this->comments->count()); } /** diff --git a/resources/views/livewire/user-comments.blade.php b/resources/views/livewire/user-comments.blade.php new file mode 100644 index 0000000..9131288 --- /dev/null +++ b/resources/views/livewire/user-comments.blade.php @@ -0,0 +1,116 @@ +
+
+ +
+
+ + +
+ +
+
+ +
+ + + +
+ +
+
+
+ + +
+
+
+ +
+ +
+
+
+
+
+
+
+
+
+
+ + +
+ +
+ +
Comment
+
+ + + @foreach ($comments as $comment) +
+ + +
+ @if($comment->commentable_type == \App\Models\Episode::class) + @php $episode = \App\Models\Episode::find($comment->commentable_id); @endphp + + @endif +
+ + +
+ {!! $comment->presenter()->markdownBody() !!} + +
+ +
+ + {{ $comment->presenter()->relativeCreatedAt() }} + +
+
+ @endforeach +
+
+
+
+
+ {{ $comments->links('pagination::tailwind') }} +
+
diff --git a/resources/views/profile/comments.blade.php b/resources/views/profile/comments.blade.php index 22e59fe..5d9b79c 100644 --- a/resources/views/profile/comments.blade.php +++ b/resources/views/profile/comments.blade.php @@ -12,63 +12,10 @@ 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 xl:justify-normal">
@include('profile.partials.sidebar') -
+
+ + - @php - $episode_ids = array_unique( - DB::table('comments') - ->where('commenter_id', $user->id) - ->get() - ->pluck('commentable_id') - ->toArray(), - ); - @endphp - - @foreach ($episode_ids as $episode_id) - @php $episode = App\Models\Episode::where('id', $episode_id)->first(); @endphp - - @endforeach
From 13b70fdf2372f5f80f106380e193a168f0c9cc71 Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 18:55:53 +0100 Subject: [PATCH 10/20] Misc changes --- app/Livewire/Comments.php | 2 +- resources/views/home/partials/comments.blade.php | 4 ++-- resources/views/livewire/comments.blade.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/Livewire/Comments.php b/app/Livewire/Comments.php index 824a4ec..b263330 100644 --- a/app/Livewire/Comments.php +++ b/app/Livewire/Comments.php @@ -47,7 +47,7 @@ class Comments extends Component ->with('user', 'children.user', 'children.children') ->parent() ->latest() - ->paginate(3); + ->paginate(50); return view('livewire.comments', [ 'comments' => $comments diff --git a/resources/views/home/partials/comments.blade.php b/resources/views/home/partials/comments.blade.php index 2548d70..9a9eb7c 100644 --- a/resources/views/home/partials/comments.blade.php +++ b/resources/views/home/partials/comments.blade.php @@ -4,7 +4,7 @@
@foreach ($latestComments as $comment) - @if ($comment->commentable_type == 'App\Models\Episode') + @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
$comment])--}}
- @elseif($comment->commentable_type == 'App\Models\Hentai') + @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
@endforeach - {{ $comments->links() }} + {{ $comments->links('pagination::tailwind') }} @else

No comments yet.

@endif From db6da608aa183cfcff3e8a72f31a12ab6f60f2bf Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 19:11:28 +0100 Subject: [PATCH 11/20] Add comments to home page --- app/Helpers/CacheHelper.php | 3 +- .../views/home/partials/comments.blade.php | 29 ++++++++++++------- resources/views/partials/comment.blade.php | 26 +++++++++++++++++ 3 files changed, 46 insertions(+), 12 deletions(-) create mode 100644 resources/views/partials/comment.blade.php diff --git a/app/Helpers/CacheHelper.php b/app/Helpers/CacheHelper.php index 155e044..cde2cee 100644 --- a/app/Helpers/CacheHelper.php +++ b/app/Helpers/CacheHelper.php @@ -2,6 +2,7 @@ namespace App\Helpers; +use App\Models\Comment; use App\Models\Episode; use App\Models\Hentai; use App\Models\PopularMonthly; @@ -126,7 +127,7 @@ class CacheHelper public static function getLatestComments() { return Cache::remember("latest_comments", now()->addMinutes(60), function () { - return DB::table('comments')->latest()->take(10)->get(); + return Comment::latest()->take(10)->get(); }); } } diff --git a/resources/views/home/partials/comments.blade.php b/resources/views/home/partials/comments.blade.php index 9a9eb7c..01c3258 100644 --- a/resources/views/home/partials/comments.blade.php +++ b/resources/views/home/partials/comments.blade.php @@ -2,14 +2,14 @@ {{ __('home.latest-comments') }}

-
+
@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
-
- {{--@include('partials.comment', ['comment' => $comment])--}} +
+ @include('partials.comment', ['comment' => $comment])
@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 @endif diff --git a/resources/views/partials/comment.blade.php b/resources/views/partials/comment.blade.php new file mode 100644 index 0000000..1e3b6bc --- /dev/null +++ b/resources/views/partials/comment.blade.php @@ -0,0 +1,26 @@ +
+
+
+ {{ $comment->user->name }} +
+
+
+

{{ $comment->user->name }}

+ @if($comment->user->is_admin) + + @endif + @if($comment->user->is_patreon) + + @endif +
+
+
{!! $comment->presenter()->markdownBody() !!}
+
+
+ + {{ $comment->presenter()->relativeCreatedAt() }} + +
+
+
+
\ No newline at end of file From 41c34e6d8960d0783c2fe07342c155888d65175b Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 19:15:32 +0100 Subject: [PATCH 12/20] Fix style --- resources/views/livewire/comment.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/comment.blade.php b/resources/views/livewire/comment.blade.php index f800ba9..d136f2d 100644 --- a/resources/views/livewire/comment.blade.php +++ b/resources/views/livewire/comment.blade.php @@ -28,7 +28,7 @@
From b133db05735380b0e8de562818bf3aebd3050280 Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 19:41:23 +0100 Subject: [PATCH 13/20] Add likes to comments --- app/Livewire/Comment.php | 39 ++++++++++++++++++++++ app/Models/Comment.php | 17 +++++++++- resources/views/livewire/comment.blade.php | 20 ++++++++++- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/app/Livewire/Comment.php b/app/Livewire/Comment.php index cdda05c..bc632cf 100644 --- a/app/Livewire/Comment.php +++ b/app/Livewire/Comment.php @@ -1,10 +1,17 @@ '' ]; @@ -85,6 +96,34 @@ class Comment extends Component $this->dispatch('refresh')->self(); } + public function like() + { + if (! Auth::check()) { + return; + } + + Like::toggle($this->comment, User::where('id', Auth::user()->id)->firstOrFail()); + + Cache::forget('commentLikes'.$this->comment->id); + + if ($this->liked) { + $this->liked = false; + $this->likeCount--; + return; + } + + $this->liked = true; + $this->likeCount++; + } + + public function mount() + { + if (Auth::check()) { + $this->likeCount = $this->comment->likeCount(); + $this->liked = Like::has($this->comment, User::where('id', Auth::user()->id)->firstOrFail()); + } + } + public function render() { return view('livewire.comment'); diff --git a/app/Models/Comment.php b/app/Models/Comment.php index 45b4071..cc92d83 100644 --- a/app/Models/Comment.php +++ b/app/Models/Comment.php @@ -8,9 +8,16 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Maize\Markable\Markable; +use Maize\Markable\Models\Like; + class Comment extends Model { - use HasFactory, SoftDeletes; + use HasFactory, SoftDeletes, Markable; + + protected static $marks = [ + Like::class + ]; /** * The attributes that are mass assignable. @@ -58,4 +65,12 @@ class Comment extends Model ? $this->parent->depth() + 1 : 0; } + + /** + * Get cached like count + */ + public function likeCount(): int + { + return cache()->remember('commentLikes' . $this->id, 300, fn() => $this->likes->count()); + } } diff --git a/resources/views/livewire/comment.blade.php b/resources/views/livewire/comment.blade.php index d136f2d..4128bbe 100644 --- a/resources/views/livewire/comment.blade.php +++ b/resources/views/livewire/comment.blade.php @@ -37,10 +37,28 @@
{!! $comment->presenter()->markdownBody() !!}
@endif
-
+
+ @guest + + {{ $comment->likeCount() }} + + @endguest + + @auth + + + @endauth + {{ $comment->presenter()->relativeCreatedAt() }} + @auth @if ($comment->depth() < 2)
-
+
@include('partials.comment', ['comment' => $comment])
@@ -59,7 +59,7 @@ src="{{ $hentai->episodes->first()->cover_url }}">
-
+
@include('partials.comment', ['comment' => $comment])
From 819e2fde27af9d58f5d48c900011371e9f76a64b Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 20:33:35 +0100 Subject: [PATCH 15/20] Misc changes --- resources/views/livewire/comment.blade.php | 18 ++-- resources/views/livewire/comments.blade.php | 90 ++++++++++--------- .../views/livewire/user-comments.blade.php | 14 +++ 3 files changed, 71 insertions(+), 51 deletions(-) diff --git a/resources/views/livewire/comment.blade.php b/resources/views/livewire/comment.blade.php index 4128bbe..2879be9 100644 --- a/resources/views/livewire/comment.blade.php +++ b/resources/views/livewire/comment.blade.php @@ -38,27 +38,27 @@ @endif
+ + {{ $comment->presenter()->relativeCreatedAt() }} + + @guest - - {{ $comment->likeCount() }} + + {{ $comment->likeCount() }} @endguest @auth - @endauth - - {{ $comment->presenter()->relativeCreatedAt() }} - - @auth @if ($comment->depth() < 2)
-
- @auth -
-
- {{ auth()->user()->name }} -
-
-
-
- - - @error('newCommentState.body') -

{{ $message }}

- @enderror +
+ +
+ @auth +
+
+ {{ auth()->user()->name }}
-
- +
+ +
+ + + @error('newCommentState.body') +

{{ $message }}

+ @enderror +
+
+ +
+
- -
-
- @endauth +
+ @endauth - @guest -

Log in to comment.

- @endguest + @guest +

Log in to comment.

+ @endguest +
+ + +
+
+ @if ($comments->isNotEmpty()) + @foreach($comments as $comment) + + @endforeach + {{ $comments->links('pagination::tailwind') }} + @else +

No comments yet.

+ @endif +
+
+
+
\ No newline at end of file diff --git a/resources/views/livewire/user-comments.blade.php b/resources/views/livewire/user-comments.blade.php index 9131288..59078f6 100644 --- a/resources/views/livewire/user-comments.blade.php +++ b/resources/views/livewire/user-comments.blade.php @@ -88,6 +88,20 @@ {{ $episode->likeCount() }} {{ $episode->commentCount() }}

+ +
+ @elseif($comment->commentable_type == \App\Models\Hentai::class) + @php + $hentai = \App\Models\Hentai::find($comment->commentable_id); + $episode = $hentai->episodes->first(); + @endphp + @endif From e949ba955a65c502d569886333a7dca69bf2a5e4 Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 21:04:26 +0100 Subject: [PATCH 16/20] Add rate limiter to comment system --- app/Livewire/Comment.php | 15 ++++++++++++++- app/Livewire/Comments.php | 19 ++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/app/Livewire/Comment.php b/app/Livewire/Comment.php index bc632cf..66b68e0 100644 --- a/app/Livewire/Comment.php +++ b/app/Livewire/Comment.php @@ -8,6 +8,7 @@ use App\Models\User; use Livewire\Component; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\RateLimiter; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Maize\Markable\Models\Like; @@ -77,12 +78,24 @@ class Comment extends Component return; } + $user = auth()->user(); + $rateLimitKey = "send-comment:{$user->id}"; + + if (RateLimiter::tooManyAttempts($rateLimitKey, 5)) { + $seconds = RateLimiter::availableIn($rateLimitKey); + + $this->addError('replyState.body', "Too many comments. Try again in {$seconds} seconds."); + return; + } + + RateLimiter::hit($rateLimitKey, 60); + $this->validate([ 'replyState.body' => 'required' ]); $reply = $this->comment->children()->make($this->replyState); - $reply->user()->associate(auth()->user()); + $reply->user()->associate($user); $reply->commentable()->associate($this->comment->commentable); $reply->save(); diff --git a/app/Livewire/Comments.php b/app/Livewire/Comments.php index b263330..75d499a 100644 --- a/app/Livewire/Comments.php +++ b/app/Livewire/Comments.php @@ -5,6 +5,8 @@ namespace App\Livewire; use Livewire\Component; use Livewire\WithPagination; +use Illuminate\Support\Facades\RateLimiter; + class Comments extends Component { use WithPagination; @@ -29,8 +31,23 @@ class Comments extends Component 'newCommentState.body' => 'required' ]); + $this->addError('newCommentState.body', "Too many comments. Try again in 1 seconds."); + return; + + $user = auth()->user(); + $rateLimitKey = "send-comment:{$user->id}"; + + if (RateLimiter::tooManyAttempts($rateLimitKey, 5)) { + $seconds = RateLimiter::availableIn($rateLimitKey); + + $this->addError('newCommentState.body', "Too many comments. Try again in {$seconds} seconds."); + return; + } + + RateLimiter::hit($rateLimitKey, 60); + $comment = $this->model->comments()->make($this->newCommentState); - $comment->user()->associate(auth()->user()); + $comment->user()->associate($user); $comment->save(); $this->newCommentState = [ From 81038b6c26f982c630bcab675b52246a5d878ea1 Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 21:59:08 +0100 Subject: [PATCH 17/20] Add id to comment, so it can autoscroll to that notification --- resources/views/livewire/comment.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/comment.blade.php b/resources/views/livewire/comment.blade.php index 2879be9..2230dd9 100644 --- a/resources/views/livewire/comment.blade.php +++ b/resources/views/livewire/comment.blade.php @@ -1,5 +1,5 @@
-
+
{{ $comment->user->name }}
From ab61574956f43f5f185d4679a3238e3d5e1dd353 Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 21:59:53 +0100 Subject: [PATCH 18/20] Fix comment depth chain check --- app/Livewire/Comment.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Livewire/Comment.php b/app/Livewire/Comment.php index 66b68e0..d06c7b7 100644 --- a/app/Livewire/Comment.php +++ b/app/Livewire/Comment.php @@ -74,7 +74,7 @@ class Comment extends Component public function postReply() { - if (! $this->comment->depth() < 2) { + if (!($this->comment->depth() < 2)) { return; } From 268e3eb4c2a149d0688195ce09607dd53a85d862 Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 22:00:09 +0100 Subject: [PATCH 19/20] Add Notification for comments --- app/Livewire/Comment.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/app/Livewire/Comment.php b/app/Livewire/Comment.php index d06c7b7..6ecd5f9 100644 --- a/app/Livewire/Comment.php +++ b/app/Livewire/Comment.php @@ -4,8 +4,12 @@ namespace App\Livewire; use App\Models\User; +use App\Models\Episode; +use App\Notifications\CommentNotification; use Livewire\Component; + +use Illuminate\Support\Str; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\RateLimiter; @@ -75,6 +79,7 @@ class Comment extends Component public function postReply() { if (!($this->comment->depth() < 2)) { + $this->addError('replyState.body', "Too many sub comments."); return; } @@ -100,6 +105,22 @@ class Comment extends Component $reply->save(); + // Notify if Episode and if not the same user + if ($reply->commentable_type == Episode::class && $user->id !== $reply->parent->user->id) { + $episode = Episode::where('id', $reply->commentable_id) + ->firstOrFail(); + + $url = route('hentai.index', ['title' => $episode->slug]); + + $reply->parent->user->notify( + new CommentNotification( + "{$user->name} replied to your comment.", + Str::limit($reply->body, 50), + "{$url}#comment-{$reply->id}" + ) + ); + } + $this->replyState = [ 'body' => '' ]; From dfedf4058eced0beb901c98efd287aeeaa10b1ec Mon Sep 17 00:00:00 2001 From: w33b Date: Sat, 10 Jan 2026 22:15:50 +0100 Subject: [PATCH 20/20] Fix rate limit and make it more strict (1 message in 5 minutes) --- app/Livewire/Comment.php | 5 +++-- app/Livewire/Comments.php | 8 +++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/Livewire/Comment.php b/app/Livewire/Comment.php index 6ecd5f9..9fe9bf8 100644 --- a/app/Livewire/Comment.php +++ b/app/Livewire/Comment.php @@ -85,15 +85,16 @@ class Comment extends Component $user = auth()->user(); $rateLimitKey = "send-comment:{$user->id}"; + $rateLimitMinutes = 60 * 5; // 5 minutes - if (RateLimiter::tooManyAttempts($rateLimitKey, 5)) { + if (RateLimiter::tooManyAttempts($rateLimitKey, 1)) { $seconds = RateLimiter::availableIn($rateLimitKey); $this->addError('replyState.body', "Too many comments. Try again in {$seconds} seconds."); return; } - RateLimiter::hit($rateLimitKey, 60); + RateLimiter::hit($rateLimitKey, $rateLimitMinutes); $this->validate([ 'replyState.body' => 'required' diff --git a/app/Livewire/Comments.php b/app/Livewire/Comments.php index 75d499a..156ef60 100644 --- a/app/Livewire/Comments.php +++ b/app/Livewire/Comments.php @@ -31,20 +31,18 @@ class Comments extends Component 'newCommentState.body' => 'required' ]); - $this->addError('newCommentState.body', "Too many comments. Try again in 1 seconds."); - return; - $user = auth()->user(); $rateLimitKey = "send-comment:{$user->id}"; + $rateLimitMinutes = 60 * 5; // 5 minutes - if (RateLimiter::tooManyAttempts($rateLimitKey, 5)) { + if (RateLimiter::tooManyAttempts($rateLimitKey, 1)) { $seconds = RateLimiter::availableIn($rateLimitKey); $this->addError('newCommentState.body', "Too many comments. Try again in {$seconds} seconds."); return; } - RateLimiter::hit($rateLimitKey, 60); + RateLimiter::hit($rateLimitKey, $rateLimitMinutes); $comment = $this->model->comments()->make($this->newCommentState); $comment->user()->associate($user);