messages implemented

This commit is contained in:
2026-02-26 21:12:32 +01:00
parent d0aefc5ddc
commit 15b7b77d20
168 changed files with 14728 additions and 6786 deletions

View File

@@ -0,0 +1,113 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use App\Models\ArtworkComment;
use App\Support\AvatarUrl;
use App\Services\ThumbnailPresenter;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
use Carbon\Carbon;
class LatestCommentsApiController extends Controller
{
private const PER_PAGE = 20;
public function index(Request $request): JsonResponse
{
$type = $request->query('type', 'all');
// Validate filter type
if (! in_array($type, ['all', 'following', 'mine'], true)) {
$type = 'all';
}
// 'mine' and 'following' require auth
if (in_array($type, ['mine', 'following'], true) && ! $request->user()) {
return response()->json(['error' => 'Unauthenticated'], 401);
}
$query = ArtworkComment::with(['user', 'user.profile', 'artwork'])
->whereHas('artwork', function ($q) {
$q->public()->published()->whereNull('deleted_at');
})
->orderByDesc('artwork_comments.created_at');
switch ($type) {
case 'mine':
$query->where('artwork_comments.user_id', $request->user()->id);
break;
case 'following':
$followingIds = $request->user()
->following()
->pluck('users.id');
$query->whereIn('artwork_comments.user_id', $followingIds);
break;
default:
// 'all' — cache the first page only
if ((int) $request->query('page', 1) === 1) {
$cacheKey = 'comments.latest.all.page1';
$ttl = 120; // 2 minutes
$paginator = Cache::remember($cacheKey, $ttl, fn () => $query->paginate(self::PER_PAGE));
} else {
$paginator = $query->paginate(self::PER_PAGE);
}
break;
}
if (! isset($paginator)) {
$paginator = $query->paginate(self::PER_PAGE);
}
$items = $paginator->getCollection()->map(function (ArtworkComment $c) {
$art = $c->artwork;
$user = $c->user;
$present = $art ? ThumbnailPresenter::present($art, 'md') : null;
$thumb = $present ? ($present['url'] ?? null) : null;
$userId = (int) ($c->user_id ?? 0);
$avatarHash = $user?->profile?->avatar_hash ?? null;
return [
'comment_id' => $c->getKey(),
'comment_text' => e(strip_tags($c->content ?? '')),
'created_at' => $c->created_at?->toIso8601String(),
'time_ago' => $c->created_at ? Carbon::parse($c->created_at)->diffForHumans() : null,
'commenter' => [
'id' => $userId,
'username' => $user?->username ?? null,
'display' => $user?->username ?? $user?->name ?? 'User',
'profile_url' => $user?->username ? '/@' . $user->username : '/profile/' . $userId,
'avatar_url' => AvatarUrl::forUser($userId, $avatarHash, 64),
],
'artwork' => $art ? [
'id' => $art->id,
'title' => $art->title,
'slug' => $art->slug ?? Str::slug($art->title ?? ''),
'url' => '/art/' . $art->id . '/' . ($art->slug ?? Str::slug($art->title ?? '')),
'thumb' => $thumb,
] : null,
];
});
return response()->json([
'data' => $items,
'meta' => [
'current_page' => $paginator->currentPage(),
'last_page' => $paginator->lastPage(),
'per_page' => $paginator->perPage(),
'total' => $paginator->total(),
'has_more' => $paginator->hasMorePages(),
],
]);
}
}