Optimize User Follow Components

Much better, still not perfect. The mobile and the desktop components are being rendered twice, and each of their methods are running twice as well. Going to see if I can modify the structure to get away with only using one.
This commit is contained in:
Refringe 2024-10-05 14:09:22 -04:00
parent 1521e50dcb
commit 80f3da13b9
Signed by: Refringe
SSH Key Fingerprint: SHA256:t865XsQpfTeqPRBMN2G6+N8wlDjkgUCZF3WGW6O9N/k
8 changed files with 103 additions and 68 deletions

View File

@ -14,6 +14,7 @@ class UserController extends Controller
public function show(Request $request, int $userId, string $username): View public function show(Request $request, int $userId, string $username): View
{ {
$user = User::whereId($userId) $user = User::whereId($userId)
->with(['following', 'followers'])
->firstOrFail(); ->firstOrFail();
$mods = $user->mods() $mods = $user->mods()

View File

@ -3,19 +3,15 @@
namespace App\Livewire\User; namespace App\Livewire\User;
use App\Models\User; use App\Models\User;
use Illuminate\Support\Collection;
use Illuminate\View\View; use Illuminate\View\View;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Locked; use Livewire\Attributes\Locked;
use Livewire\Attributes\On; use Livewire\Attributes\On;
use Livewire\Component; use Livewire\Component;
class FollowCard extends Component class FollowCard extends Component
{ {
/**
* The ID of the user whose profile is being viewed.
*/
#[Locked]
public int $profileUserId;
/** /**
* The type of user follow relationship to display. * The type of user follow relationship to display.
* Currently, either "followers" or "following". * Currently, either "followers" or "following".
@ -68,19 +64,31 @@ class FollowCard extends Component
public User $profileUser; public User $profileUser;
/** /**
* The number of users being displayed. * A collection of user IDs that the auth user follows.
*/ */
#[Locked] #[Locked]
public int $followUsersCount; public Collection $authFollowIds;
/**
* The profile user's followers (or following).
*/
#[Locked]
public Collection $followUsers;
/**
* The number of users being displayed.
*/
#[Computed]
public function followUsersCount(): int
{
return $this->followUsers->count();
}
/** /**
* Called when the component is initialized. * Called when the component is initialized.
*/ */
public function mount(): void public function mount(): void
{ {
$this->profileUser = User::select(['id', 'name', 'profile_photo_path', 'cover_photo_path'])
->findOrFail($this->profileUserId);
$this->setTitle(); $this->setTitle();
$this->setEmptyMessage(); $this->setEmptyMessage();
$this->setDialogTitle(); $this->setDialogTitle();
@ -135,35 +143,11 @@ class FollowCard extends Component
/** /**
* Called when the user follows or unfollows a user. * Called when the user follows or unfollows a user.
*/ */
#[On('user-follow-change')] #[On('auth-follow-change')]
public function populateFollowUsers(): void public function populateFollowUsers(): void
{ {
// Fetch IDs of all users the authenticated user is following. // Update the collection of profile user's followers (or following).
$followingIds = collect(); $this->followUsers = $this->profileUser->{$this->relationship}()->get();
$authUser = auth()->user();
if ($authUser) {
$followingIds = $authUser->following()->pluck('following_id');
}
// Load the profile user's followers (or following).
$users = $this->profileUser->{$this->relationship}()->with([])->get();
// Count the number of users.
$this->followUsersCount = $users->count();
// Load the users to display and whether the authenticated user is following each user.
$this->display = $users
->map(function (User $user) use ($followingIds) {
return [
'user' => $user,
'isFollowing' => $followingIds->contains($user->id),
];
})->toArray();
// Store limited users for the main view.
$this->displayLimit = collect($this->display)
->take($this->limit)
->toArray();
} }
/** /**

View File

@ -0,0 +1,49 @@
<?php
namespace App\Livewire\User;
use App\Models\User;
use Illuminate\Support\Collection;
use Illuminate\View\View;
use Livewire\Attributes\Locked;
use Livewire\Attributes\On;
use Livewire\Component;
class FollowCards extends Component
{
/**
* The user account that is being viewed.
*/
#[Locked]
public User $profileUser;
/**
* A collection of user IDs that the auth user follows.
*/
#[Locked]
public Collection $authFollowIds;
/**
* Called when the user follows or unfollows a user.
*/
#[On('user-follow-change')]
public function updateAuthFollowIds(): void
{
// Fetch IDs of all users the authenticated user is following.
$this->authFollowIds = collect();
$authUser = auth()->user();
if ($authUser) {
$this->authFollowIds = $authUser->following()->pluck('following_id');
}
$this->dispatch('auth-follow-change');
}
/**
* Render the component.
*/
public function render(): View
{
return view('livewire.user.follow-cards');
}
}

View File

@ -57,7 +57,6 @@ class DatabaseSeeder extends Seeder
// All Users // All Users
$allUsers = User::all(); $allUsers = User::all();
/* We got a little ahead of ourselves here. This hasn't been merged yet!
// User Follows // User Follows
progress( progress(
label: 'adding user follows ...', label: 'adding user follows ...',
@ -76,7 +75,6 @@ class DatabaseSeeder extends Seeder
$user->following()->attach($following); $user->following()->attach($following);
} }
}); });
*/
// Mods // Mods
$mods = collect(progress( $mods = collect(progress(

View File

@ -1,8 +0,0 @@
@props(['profileUserId'])
<div class="flex w-full max-w-sm">
<livewire:user.follow-card relationship="followers" :profile-user-id="$profileUserId" />
</div>
<div class="flex w-full max-w-sm">
<livewire:user.follow-card relationship="following" :profile-user-id="$profileUserId" />
</div>

View File

@ -4,37 +4,37 @@
<h2 class="text-2xl">{{ $title }}</h2> <h2 class="text-2xl">{{ $title }}</h2>
</div> </div>
@if ($followUsersCount === 0) @if ($this->followUsersCount === 0)
<div class="flex justify-center text-sm pt-2"> <div class="flex justify-center text-sm pt-2">
{{ $emptyMessage }} {{ $emptyMessage }}
</div> </div>
@else @else
<div class="flex ml-6 py-2 justify-center items-center"> <div class="flex ml-6 py-2 justify-center items-center">
@foreach ($displayLimit as $data) @foreach ($followUsers->take($limit) as $user)
{{-- User Badge --}} {{-- User Badge --}}
<div class="relative group"> <div class="relative group">
<a href="{{ $data['user']->profileUrl() }}" class="rounded-full -ml-6 z-20 bg-[#ebf4ff] h-16 w-16 flex justify-center items-center border"> <a href="{{ $user->profileUrl() }}" class="rounded-full -ml-6 z-20 bg-[#ebf4ff] h-16 w-16 flex justify-center items-center border">
<img src="{{ $data['user']->profile_photo_url }}" alt="{{ $data['user']->name }}" class="h-full w-full rounded-full" /> <img src="{{ $user->profile_photo_url }}" alt="{{ $user->name }}" class="h-full w-full rounded-full" />
</a> </a>
<div class="absolute bottom-full -ml-3 left-1/2 transform -translate-x-1/2 mb-2 w-max px-2 py-1 text-sm text-white bg-gray-700 rounded shadow-lg opacity-0 group-hover:opacity-100"> <div class="absolute bottom-full -ml-3 left-1/2 transform -translate-x-1/2 mb-2 w-max px-2 py-1 text-sm text-white bg-gray-700 rounded shadow-lg opacity-0 group-hover:opacity-100">
{{ $data['user']->name }} {{ $user->name }}
</div> </div>
</div> </div>
@endforeach @endforeach
@if ($followUsersCount > $limit) @if ($this->followUsersCount > $limit)
{{-- Count Badge --}} {{-- Count Badge --}}
<div class="relative group"> <div class="relative group">
<button wire:click="toggleFollowDialog" class="rounded-full -ml-6 z-20 bg-cyan-500 dark:bg-cyan-700 h-16 w-16 flex justify-center items-center border text-white">+{{ $followUsersCount - $limit }}</button> <button wire:click="toggleFollowDialog" class="rounded-full -ml-6 z-20 bg-cyan-500 dark:bg-cyan-700 h-16 w-16 flex justify-center items-center border text-white">+{{ $this->followUsersCount - $limit }}</button>
<div class="absolute bottom-full -ml-3 left-1/2 transform -translate-x-1/2 mb-2 w-max px-2 py-1 text-sm text-white bg-gray-700 rounded shadow-lg opacity-0 group-hover:opacity-100"> <div class="absolute bottom-full -ml-3 left-1/2 transform -translate-x-1/2 mb-2 w-max px-2 py-1 text-sm text-white bg-gray-700 rounded shadow-lg opacity-0 group-hover:opacity-100">
{{ $followUsersCount }} total {{ $this->followUsersCount }} total
</div> </div>
</div> </div>
@endif @endif
</div> </div>
@endif @endif
@if ($followUsersCount > $limit) @if ($this->followUsersCount > $limit)
{{-- View All Button --}} {{-- View All Button --}}
<div class="flex justify-center items-center"> <div class="flex justify-center items-center">
<button wire:click="toggleFollowDialog" class="hover:underline active:underline">View All</button> <button wire:click="toggleFollowDialog" class="hover:underline active:underline">View All</button>
@ -49,22 +49,20 @@
</x-slot> </x-slot>
<x-slot name="content"> <x-slot name="content">
<div class="h-96 overflow-y-auto"> <div class="h-96 overflow-y-auto">
@foreach ($display as $data) @foreach ($followUsers as $user)
<div class="flex group/item dark:hover:bg-gray-950 items-center p-2 pr-3 rounded-md"> <div class="flex group/item dark:hover:bg-gray-950 items-center p-2 pr-3 rounded-md">
<a href="{{ $data['user']->profileUrl() }}" class="flex-shrink-0 w-16 h-16 items-center"> <a href="{{ $user->profileUrl() }}" class="flex-shrink-0 w-16 h-16 items-center">
<img src="{{ $data['user']->profile_photo_url }}" alt="{{ $data['user']->name }}" class="block w-full h-full rounded-full" /> <img src="{{ $user->profile_photo_url }}" alt="{{ $user->name }}" class="block w-full h-full rounded-full" />
</a> </a>
<div class="flex flex-col w-full pl-3"> <div class="flex flex-col w-full pl-3">
<a href="{{ $data['user']->profileUrl() }}" class="text-2xl group-hover/item:underline group-hover/item:text-white">{{ $data['user']->name }}</a> <a href="{{ $user->profileUrl() }}" class="text-2xl group-hover/item:underline group-hover/item:text-white">{{ $user->name }}</a>
<span> <span>
{{ __("Member Since") }} {{ __("Member Since") }}
<x-time :datetime="$data['user']->created_at" /> <x-time :datetime="$user->created_at" />
</span> </span>
</div> </div>
@if (auth()->check() && auth()->user()->id !== $user->id)
@if (auth()->check() && auth()->user()->id !== $data['user']->id) <livewire:user.follow-buttons :profile-user-id="$user->id" :is-following="$authFollowIds->contains($user->id)" />
<livewire:user.follow-buttons :profile-user-id="$data['user']->id" :is-following="$data['isFollowing']" />
@endif @endif
</div> </div>
@endforeach @endforeach

View File

@ -0,0 +1,13 @@
@props([
'profileUser',
'authFollowIds' => collect(),
])
<div class="w-full max-w-sm">
<div class="flex w-full max-w-sm">
<livewire:user.follow-card relationship="followers" :profile-user="$profileUser" :auth-follow-ids="$authFollowIds" />
</div>
<div class="flex w-full max-w-sm">
<livewire:user.follow-card relationship="following" :profile-user="$profileUser" :auth-follow-ids="$authFollowIds" />
</div>
</div>

View File

@ -39,7 +39,7 @@
<div class="grid grid-cols-1 lg:grid-cols-4 gap-6"> <div class="grid grid-cols-1 lg:grid-cols-4 gap-6">
{{-- Mobile Follows --}} {{-- Mobile Follows --}}
<div class="lg:hidden flex flex-col justify-top items-center"> <div class="lg:hidden flex flex-col justify-top items-center">
<x-user-follow-cards :profile-user-id="$user->id" /> <livewire:user.follow-cards :profile-user="$user" />
</div> </div>
{{-- Left Column --}} {{-- Left Column --}}
@ -106,7 +106,7 @@
{{-- Desktop Follows --}} {{-- Desktop Follows --}}
<div class="max-lg:hidden flex flex-col justify-top items-center gap-6"> <div class="max-lg:hidden flex flex-col justify-top items-center gap-6">
<x-user-follow-cards :profile-user-id="$user->id" /> <livewire:user.follow-cards :profile-user="$user" />
</div> </div>
</div> </div>
</div> </div>