friends page

This commit is contained in:
Ghostie 2025-01-04 13:12:50 -05:00
parent a2ddb90ae9
commit d38da1722a
9 changed files with 113 additions and 25 deletions

View File

@ -21,6 +21,7 @@ Notice that the styles were taken from [AnySpace](https://anyspace.3to.moe/about
- [x] Follows - [x] Follows
- [x] I cannot follow myself - [x] I cannot follow myself
- [ ] Check when waiting for approval - [ ] Check when waiting for approval
- [ ] Handle Rejection
- [ ] Likes - [ ] Likes
- [ ] Comments - [ ] Comments

View File

@ -46,6 +46,13 @@ class APInboxController extends Controller
if (!$target || !$target->user) if (!$target || !$target->user)
return response ()->json (["error" => "Target not found",], 404); return response ()->json (["error" => "Target not found",], 404);
// check follow doesn't exist
$follow_exists = Follow::where ("actor", $actor->id)
->where ("object", $target->id)
->first ();
if ($follow_exists)
return response ()->json (["error" => "Follow already exists",], 409);
$activity ["activity_id"] = $activity ["id"]; $activity ["activity_id"] = $activity ["id"];
// there's no follows model, it'll be handled with the activity model // there's no follows model, it'll be handled with the activity model
@ -84,7 +91,7 @@ class APInboxController extends Controller
$child_activity_id = $child_activity; $child_activity_id = $child_activity;
if (!TypeActivity::activity_exists ($child_activity_id)) if (!TypeActivity::activity_exists ($child_activity_id))
return response ()->json (["error" => "Child activity not found",], 404); return response ()->json (["error" => "Child activity doesn't exist",], 404);
$child_activity = Activity::where ("activity_id", $child_activity_id)->first (); $child_activity = Activity::where ("activity_id", $child_activity_id)->first ();
$child_activity->delete (); $child_activity->delete ();

View File

@ -106,4 +106,33 @@ class ProfileController extends Controller
return back ()->with ("success", "Profile updated successfully!"); return back ()->with ("success", "Profile updated successfully!");
} }
public function friends ($user_name)
{
// only local users
if (str_starts_with ($user_name, "@"))
{
return redirect ()->route ("users.show", [ "user_name" => $user_name ]);
}
$user = User::where ("name", $user_name)->first ();
if (!$user)
return redirect ()->route ("home");
$actor = $user->actor;
$ids = $user->mutual_friends ();
if (request ()->get ("query"))
{
$friends = Actor::whereIn ("actor_id", $ids)
->where ("preferredUsername", "like", "%" . request ()->get ("query") . "%")
->get ();
}
else
{
$friends = Actor::whereIn ("actor_id", $ids)->get ();
}
return view ("users.friends", compact ("actor", "user", "friends"));
}
} }

View File

@ -199,22 +199,38 @@ class TypeActor {
$well_known = TypeActor::query_wellknown ($actor_name, $parsed_url ["host"]); $well_known = TypeActor::query_wellknown ($actor_name, $parsed_url ["host"]);
foreach ($well_known->links as $link) if (isset ($well_known->links))
{ {
if ($link->rel == "self") foreach ($well_known->links as $link)
{ {
$client = new Client (); if ($link->rel == "self")
$res = $client->request ("GET", $link->href, [ {
"headers" => [ $client = new Client ();
"Accept" => "application/json" $res = $client->request ("GET", $link->href, [
] "headers" => [
]); "Accept" => "application/json"
$actor = json_decode ($res->getBody ()->getContents (), true); ]
]);
$actor = json_decode ($res->getBody ()->getContents (), true);
$result = TypeActor::create_from_request ($actor); $result = TypeActor::create_from_request ($actor);
return $result; return $result;
}
} }
} }
else
{
$client = new Client ();
$res = $client->request ("GET", $actor_id, [
"headers" => [
"Accept" => "application/activity+json"
]
]);
$actor = json_decode ($res->getBody ()->getContents (), true);
$result = TypeActor::create_from_request ($actor);
return $result;
}
return null; return null;
} }

View File

@ -1,9 +1,9 @@
<div class="person"> <div class="person">
<a href="{{ route ('users.show', [ 'user_name' => $user->name ]) }}"> <a href="{{ route ('users.show', [ 'user_name' => $user->local_actor_id ? $user->local_actor_id : $user->name ]) }}">
<p>{{ $user->name }}</p> <p>{{ $user->name }}</p>
</a> </a>
<a href="{{ route ('users.show', [ 'user_name' => $user->name ]) }}"> <a href="{{ route ('users.show', [ 'user_name' => $user->local_actor_id ? $user->local_actor_id : $user->name ]) }}">
<img loading="lazy" src="{{ $user->avatar }}" alt="{{ $user->name }}'s profile picture" <img loading="lazy" src="{{ $user->avatar ? $user->avatar : $user->icon }}" alt="{{ $user->name }}'s profile picture"
class="pfp-fallback" style="width: 100%; max-height: 95px; aspect-ratio: 1/1"> class="pfp-fallback" style="width: 100%; max-height: 95px; aspect-ratio: 1/1">
</a> </a>
</div> </div>

View File

@ -0,0 +1,34 @@
@extends ("partials.layout")
@section ("title", $user->name . "'s Friends")
@section ("content")
<div class="simple-container">
<h1>{{ $user->name }}'s Friends</h1>
<p>
<a href="{{ route ('users.show', [ 'user_name' => $user->name ]) }}">&laquo; Back to profile</a>
</p>
<br>
<form>
<input type="text" name="query" value="{{ request ()->get ('query') ?? '' }}">
<button type="submit">Search</button>
</form>
<br>
<div class="new-people">
<div class="top">
<h4>Friends</h4>
</div>
<div class="inner">
@forelse ($friends as $friend)
<x-user_block :user="$friend" />
@empty
<p>No friends found.</p>
@endforelse
</div>
</div>
</div>
@endsection

View File

@ -1,13 +1,13 @@
@extends ("partials.layout") @extends ("partials.layout")
@section('title', "$actor->preferredUsername's Profile") @section('title', "$actor->name's Profile")
@section('content') @section('content')
<div class="row profile"> <div class="row profile">
<div class="col w-40 left"> <div class="col w-40 left">
<span> <span>
<h1>{{ $actor->preferredUsername }}</h1> <h1>{{ $actor->name }}</h1>
</span> </span>
<div class="general-about"> <div class="general-about">
@ -49,7 +49,7 @@
<div class="contact"> <div class="contact">
<div class="heading"> <div class="heading">
<h4>Contacting {{ $actor->preferredUsername }}</h4> <h4>Contacting {{ $actor->name }}</h4>
</div> </div>
@auth @auth
@ -250,7 +250,7 @@
<div class="blurbs"> <div class="blurbs">
<div class="heading"> <div class="heading">
<h4> <h4>
{{ $actor->preferredUsername }}'s Bio {{ $actor->name }}'s Bio
</h4> </h4>
</div> </div>
<div class="inner"> <div class="inner">
@ -264,16 +264,16 @@
<div class="friends"> <div class="friends">
<div class="heading"> <div class="heading">
<h4> <h4>
{{ $actor->preferredUsername }}'s Friend Space {{ $actor->name }}'s Friend Space
</h4> </h4>
<a href="#" class="more">[view all]</a> <a href="{{ route ('users.friends', [ 'user_name' => $actor->preferredUsername ]) }}" class="more">[view all]</a>
</div> </div>
<div class="inner"> <div class="inner">
<p> <p>
<b> <b>
{{ $actor->preferredUsername }} has <span class="count">{{ count ($user->mutual_friends ()) }}</span> friends. {{ $actor->name }} has <span class="count">{{ count ($user->mutual_friends ()) }}</span> friends.
</b> </b>
</p> </p>
@ -285,11 +285,11 @@
<div id="comments" class="friends"> <div id="comments" class="friends">
<div class="heading"> <div class="heading">
<h4>{{ $actor->preferredUsername }}'s Posts</h4> <h4>{{ $actor->name }}'s Posts</h4>
</div> </div>
<div class="inner"> <div class="inner">
<p> <p>
<b>{{ $actor->preferredUsername }} has <span class="count">{{ count ($actor->posts) }}</span> posts.</b> <b>{{ $actor->name }} has <span class="count">{{ count ($actor->posts) }}</span> posts.</b>
</p> </p>
@if (auth ()->user () && auth ()->user ()->is ($user)) @if (auth ()->user () && auth ()->user ()->is ($user))

View File

@ -31,7 +31,7 @@
<td> <td>
<a href="{{ route ('users.show', [ 'user_name' => $frequest->local_actor_id ? $frequest->local_actor_id : $frequest->preferredUsername ]) }}"> <a href="{{ route ('users.show', [ 'user_name' => $frequest->local_actor_id ? $frequest->local_actor_id : $frequest->preferredUsername ]) }}">
<p> <p>
{{ $frequest->name }} {{ $frequest->name ? $frequest->name : $frequest->preferredUsername }}
</p> </p>
</a> </a>

View File

@ -25,6 +25,7 @@ Route::post ("/user/action/post/new", [ UserActionController::class, "post_new"
// user routes // user routes
Route::get ("/user/edit", [ ProfileController::class, "edit" ])->name ("users.edit")->middleware ("auth"); Route::get ("/user/edit", [ ProfileController::class, "edit" ])->name ("users.edit")->middleware ("auth");
Route::post ("/user/edit", [ ProfileController::class, "update" ])->middleware ("auth"); Route::post ("/user/edit", [ ProfileController::class, "update" ])->middleware ("auth");
Route::get ("/user/{user_name}/friends", [ ProfileController::class, "friends" ])->name ("users.friends");
Route::get ("/user/{user_name}", [ ProfileController::class, "show" ])->name ("users.show"); Route::get ("/user/{user_name}", [ ProfileController::class, "show" ])->name ("users.show");
// posts routes // posts routes