feat: forum rich-text editor, emoji picker, mentions, discover nav, feed, uploads, profile

Forum:
- TipTap WYSIWYG editor with full toolbar
- @emoji-mart/react emoji picker (consistent with tweets)
- @mention autocomplete with user search API
- Fix PHP 8.4 parse errors in Blade templates
- Fix thread data display (paginator items)
- Align forum page widths to max-w-5xl

Discover:
- Extract shared _nav.blade.php partial
- Add missing nav links to for-you page
- Add Following link for authenticated users

Feed/Posts:
- Post model, controllers, policies, migrations
- Feed page components (PostComposer, FeedCard, etc)
- Post reactions, comments, saves, reports, sharing
- Scheduled publishing support
- Link preview controller

Profile:
- Profile page components (ProfileHero, ProfileTabs)
- Profile API controller

Uploads:
- Upload wizard enhancements
- Scheduled publish picker
- Studio status bar and readiness checklist
This commit is contained in:
2026-03-03 09:48:31 +01:00
parent 1266f81d35
commit dc51d65440
178 changed files with 14308 additions and 665 deletions

View File

@@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\View\View;
use App\Support\AvatarUrl;
class FavoriteController extends Controller
{
@@ -36,16 +37,41 @@ class FavoriteController extends Controller
$artworks = collect();
if ($slice !== []) {
$arts = Artwork::query()->whereIn('id', $slice)->with('user')->get()->keyBy('id');
$arts = Artwork::query()
->whereIn('id', $slice)
->with(['user.profile', 'categories'])
->withCount(['favourites', 'comments'])
->get()
->keyBy('id');
foreach ($slice as $id) {
$a = $arts->get($id);
if (! $a) continue;
$primaryCategory = $a->categories->sortBy('sort_order')->first();
$username = $a->user?->username ?? $a->user?->name ?? '';
$artworks->push((object) [
'id' => $a->id,
'name' => $a->title,
'title' => $a->title,
'thumb' => $a->thumbUrl('md') ?? $a->thumbnail_url ?? null,
'thumb_url' => $a->thumbUrl('md') ?? $a->thumbnail_url ?? null,
'slug' => $a->slug,
'author' => $a->user?->username ?? $a->user?->name,
'author' => $username,
'uname' => $username,
'username' => $a->user?->username ?? '',
'avatar_url' => AvatarUrl::forUser(
(int) ($a->user_id ?? 0),
$a->user?->profile?->avatar_hash ?? null,
64
),
'category_name' => $primaryCategory->name ?? '',
'category_slug' => $primaryCategory->slug ?? '',
'width' => $a->width,
'height' => $a->height,
'likes' => (int) ($a->favourites_count ?? $a->likes ?? 0),
'comments_count' => (int) ($a->comments_count ?? 0),
'published_at' => $a->published_at,
]);
}