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:
@@ -25,6 +25,7 @@ use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rules\Password as PasswordRule;
|
||||
use Inertia\Inertia;
|
||||
|
||||
class ProfileController extends Controller
|
||||
{
|
||||
@@ -220,6 +221,10 @@ class ProfileController extends Controller
|
||||
$profileUpdates['friend_upload_notice'] = filter_var($validated['notify'], FILTER_VALIDATE_BOOLEAN) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (array_key_exists('auto_post_upload', $validated)) {
|
||||
$profileUpdates['auto_post_upload'] = filter_var($validated['auto_post_upload'], FILTER_VALIDATE_BOOLEAN) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (isset($validated['signature'])) $profileUpdates['signature'] = $validated['signature'];
|
||||
if (isset($validated['description'])) $profileUpdates['description'] = $validated['description'];
|
||||
|
||||
@@ -498,24 +503,70 @@ class ProfileController extends Controller
|
||||
} catch (\Throwable) {}
|
||||
}
|
||||
|
||||
return response()->view('legacy::profile', [
|
||||
'user' => $user,
|
||||
'profile' => $profile,
|
||||
'artworks' => $artworks,
|
||||
'featuredArtworks' => $featuredArtworks,
|
||||
'favourites' => $favourites,
|
||||
// ── Normalise artworks for JSON serialisation ────────────────────
|
||||
$artworkItems = collect($artworks->items())->values();
|
||||
$artworkPayload = [
|
||||
'data' => $artworkItems,
|
||||
'next_cursor' => $artworks->nextCursor()?->encode(),
|
||||
'has_more' => $artworks->hasMorePages(),
|
||||
];
|
||||
|
||||
// ── Avatar URL on user object ────────────────────────────────────
|
||||
$avatarUrl = AvatarUrl::forUser((int) $user->id, $user->profile?->avatar_hash, 128);
|
||||
|
||||
// ── Auth context for JS ───────────────────────────────────────────
|
||||
$authData = null;
|
||||
if (Auth::check()) {
|
||||
/** @var \App\Models\User $authUser */
|
||||
$authUser = Auth::user();
|
||||
$authAvatarUrl = AvatarUrl::forUser((int) $authUser->id, $authUser->profile?->avatar_hash, 64);
|
||||
$authData = [
|
||||
'user' => [
|
||||
'id' => $authUser->id,
|
||||
'username' => $authUser->username,
|
||||
'name' => $authUser->name,
|
||||
'avatar' => $authAvatarUrl,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$canonical = url('/@' . strtolower((string) ($user->username ?? '')));
|
||||
|
||||
return Inertia::render('Profile/ProfileShow', [
|
||||
'user' => [
|
||||
'id' => $user->id,
|
||||
'username' => $user->username,
|
||||
'name' => $user->name,
|
||||
'avatar_url' => $avatarUrl,
|
||||
'created_at' => $user->created_at?->toISOString(),
|
||||
'last_visit_at' => $user->last_visit_at ? (string) $user->last_visit_at : null,
|
||||
],
|
||||
'profile' => $profile ? [
|
||||
'about' => $profile->about ?? null,
|
||||
'website' => $profile->website ?? null,
|
||||
'country_code' => $profile->country_code ?? null,
|
||||
'gender' => $profile->gender ?? null,
|
||||
'birthdate' => $profile->birthdate ?? null,
|
||||
'cover_image' => $profile->cover_image ?? null,
|
||||
] : null,
|
||||
'artworks' => $artworkPayload,
|
||||
'featuredArtworks' => $featuredArtworks->values(),
|
||||
'favourites' => $favourites->values(),
|
||||
'stats' => $stats,
|
||||
'socialLinks' => $socialLinks,
|
||||
'followerCount' => $followerCount,
|
||||
'recentFollowers' => $recentFollowers,
|
||||
'recentFollowers' => $recentFollowers->values(),
|
||||
'viewerIsFollowing' => $viewerIsFollowing,
|
||||
'heroBgUrl' => $heroBgUrl,
|
||||
'profileComments' => $profileComments,
|
||||
'profileComments' => $profileComments->values(),
|
||||
'countryName' => $countryName,
|
||||
'isOwner' => $isOwner,
|
||||
'page_title' => 'Profile: ' . ($user->username ?? $user->name ?? ''),
|
||||
'page_canonical' => url('/@' . strtolower((string) ($user->username ?? ''))),
|
||||
'auth' => $authData,
|
||||
])->withViewData([
|
||||
'page_title' => ($user->username ?? $user->name ?? 'User') . ' on Skinbase',
|
||||
'page_canonical' => $canonical,
|
||||
'page_meta_description' => 'View the profile of ' . ($user->username ?? $user->name) . ' on Skinbase.org — artworks, favourites and more.',
|
||||
'og_image' => $avatarUrl,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user