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
{
$user = User::whereId($userId)
->with(['following', 'followers'])
->firstOrFail();
$mods = $user->mods()

View File

@ -3,19 +3,15 @@
namespace App\Livewire\User;
use App\Models\User;
use Illuminate\Support\Collection;
use Illuminate\View\View;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Locked;
use Livewire\Attributes\On;
use Livewire\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.
* Currently, either "followers" or "following".
@ -68,19 +64,31 @@ class FollowCard extends Component
public User $profileUser;
/**
* The number of users being displayed.
* A collection of user IDs that the auth user follows.
*/
#[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.
*/
public function mount(): void
{
$this->profileUser = User::select(['id', 'name', 'profile_photo_path', 'cover_photo_path'])
->findOrFail($this->profileUserId);
$this->setTitle();
$this->setEmptyMessage();
$this->setDialogTitle();
@ -135,35 +143,11 @@ class FollowCard extends Component
/**
* Called when the user follows or unfollows a user.
*/
#[On('user-follow-change')]
#[On('auth-follow-change')]
public function populateFollowUsers(): void
{
// Fetch IDs of all users the authenticated user is following.
$followingIds = collect();
$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();
// Update the collection of profile user's followers (or following).
$this->followUsers = $this->profileUser->{$this->relationship}()->get();
}
/**

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
$allUsers = User::all();
/* We got a little ahead of ourselves here. This hasn't been merged yet!
// User Follows
progress(
label: 'adding user follows ...',
@ -76,7 +75,6 @@ class DatabaseSeeder extends Seeder
$user->following()->attach($following);
}
});
*/
// Mods
$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>
</div>
@if ($followUsersCount === 0)
@if ($this->followUsersCount === 0)
<div class="flex justify-center text-sm pt-2">
{{ $emptyMessage }}
</div>
@else
<div class="flex ml-6 py-2 justify-center items-center">
@foreach ($displayLimit as $data)
@foreach ($followUsers->take($limit) as $user)
{{-- User Badge --}}
<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">
<img src="{{ $data['user']->profile_photo_url }}" alt="{{ $data['user']->name }}" class="h-full w-full rounded-full" />
<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="{{ $user->profile_photo_url }}" alt="{{ $user->name }}" class="h-full w-full rounded-full" />
</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">
{{ $data['user']->name }}
{{ $user->name }}
</div>
</div>
@endforeach
@if ($followUsersCount > $limit)
@if ($this->followUsersCount > $limit)
{{-- Count Badge --}}
<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">
{{ $followUsersCount }} total
{{ $this->followUsersCount }} total
</div>
</div>
@endif
</div>
@endif
@if ($followUsersCount > $limit)
@if ($this->followUsersCount > $limit)
{{-- View All Button --}}
<div class="flex justify-center items-center">
<button wire:click="toggleFollowDialog" class="hover:underline active:underline">View All</button>
@ -49,22 +49,20 @@
</x-slot>
<x-slot name="content">
<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">
<a href="{{ $data['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" />
<a href="{{ $user->profileUrl() }}" class="flex-shrink-0 w-16 h-16 items-center">
<img src="{{ $user->profile_photo_url }}" alt="{{ $user->name }}" class="block w-full h-full rounded-full" />
</a>
<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>
{{ __("Member Since") }}
<x-time :datetime="$data['user']->created_at" />
<x-time :datetime="$user->created_at" />
</span>
</div>
@if (auth()->check() && auth()->user()->id !== $data['user']->id)
<livewire:user.follow-buttons :profile-user-id="$data['user']->id" :is-following="$data['isFollowing']" />
@if (auth()->check() && auth()->user()->id !== $user->id)
<livewire:user.follow-buttons :profile-user-id="$user->id" :is-following="$authFollowIds->contains($user->id)" />
@endif
</div>
@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">
{{-- Mobile Follows --}}
<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>
{{-- Left Column --}}
@ -106,7 +106,7 @@
{{-- Desktop Follows --}}
<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>