Initial commit: Animexe Laravel platform
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Frontend;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Conversation;
|
||||
use App\Models\ConversationParticipant;
|
||||
use App\Models\Message;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class MessageController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
try {
|
||||
$conversations = $user->conversations()
|
||||
->with(['participants', 'lastMessage.user'])
|
||||
->orderByDesc('conversations.updated_at')
|
||||
->get()
|
||||
->map(function ($conv) use ($user) {
|
||||
$other = $conv->participants->firstWhere('id', '!=', $user->id);
|
||||
return [
|
||||
'id' => $conv->id,
|
||||
'other' => $other,
|
||||
'last_message' => $conv->lastMessage,
|
||||
'unread' => $conv->unreadCountFor($user->id),
|
||||
'updated_at' => $conv->updated_at,
|
||||
];
|
||||
});
|
||||
} catch (\Throwable $e) {
|
||||
$conversations = collect();
|
||||
}
|
||||
|
||||
return view('frontend.messages.index', compact('conversations'));
|
||||
}
|
||||
|
||||
public function show(Conversation $conversation)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
abort_unless(
|
||||
$conversation->participants()->where('user_id', $user->id)->exists(),
|
||||
403
|
||||
);
|
||||
|
||||
$other = $conversation->participants()->where('user_id', '!=', $user->id)->first();
|
||||
|
||||
$messages = $conversation->messages()
|
||||
->with('user')
|
||||
->orderBy('created_at')
|
||||
->get();
|
||||
|
||||
// Mark as read
|
||||
$conversation->participants()
|
||||
->updateExistingPivot($user->id, ['last_read_at' => now()]);
|
||||
|
||||
return view('frontend.messages.show', compact('conversation', 'messages', 'other'));
|
||||
}
|
||||
|
||||
public function startOrOpen(User $user)
|
||||
{
|
||||
$me = Auth::user();
|
||||
|
||||
if ($me->id === $user->id) abort(422);
|
||||
|
||||
// Find existing conversation between these two users
|
||||
$conv = Conversation::whereHas('participants', fn($q) => $q->where('user_id', $me->id))
|
||||
->whereHas('participants', fn($q) => $q->where('user_id', $user->id))
|
||||
->first();
|
||||
|
||||
if (!$conv) {
|
||||
$conv = DB::transaction(function () use ($me, $user) {
|
||||
$c = Conversation::create();
|
||||
$c->participants()->attach([$me->id, $user->id]);
|
||||
return $c;
|
||||
});
|
||||
}
|
||||
|
||||
return redirect()->route('messages.show', $conv);
|
||||
}
|
||||
|
||||
public function send(Request $request, Conversation $conversation)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
abort_unless(
|
||||
$conversation->participants()->where('user_id', $user->id)->exists(),
|
||||
403
|
||||
);
|
||||
|
||||
$request->validate(['body' => 'required|string|max:5000']);
|
||||
|
||||
$message = Message::create([
|
||||
'conversation_id' => $conversation->id,
|
||||
'user_id' => $user->id,
|
||||
'body' => $request->body,
|
||||
]);
|
||||
|
||||
$conversation->touch();
|
||||
|
||||
// Mark sender as read
|
||||
$conversation->participants()
|
||||
->updateExistingPivot($user->id, ['last_read_at' => now()]);
|
||||
|
||||
if ($request->expectsJson()) {
|
||||
return response()->json([
|
||||
'id' => $message->id,
|
||||
'body' => $message->body,
|
||||
'user_id' => $user->id,
|
||||
'created_at' => $message->created_at->format('H:i'),
|
||||
'avatar' => $user->avatar ? \App\Support\MediaUrl::fromStoragePath($user->avatar) : null,
|
||||
'name' => $user->name,
|
||||
]);
|
||||
}
|
||||
|
||||
return back();
|
||||
}
|
||||
|
||||
public function poll(Request $request, Conversation $conversation)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
abort_unless(
|
||||
$conversation->participants()->where('user_id', $user->id)->exists(),
|
||||
403
|
||||
);
|
||||
|
||||
$after = $request->query('after', 0);
|
||||
|
||||
$messages = $conversation->messages()
|
||||
->with('user')
|
||||
->where('id', '>', $after)
|
||||
->orderBy('created_at')
|
||||
->get()
|
||||
->map(fn($m) => [
|
||||
'id' => $m->id,
|
||||
'body' => $m->body,
|
||||
'user_id' => $m->user_id,
|
||||
'created_at' => $m->created_at->format('H:i'),
|
||||
'avatar' => $m->user->avatar ? \App\Support\MediaUrl::fromStoragePath($m->user->avatar) : null,
|
||||
'name' => $m->user->name,
|
||||
]);
|
||||
|
||||
// Update last_read
|
||||
$conversation->participants()
|
||||
->updateExistingPivot($user->id, ['last_read_at' => now()]);
|
||||
|
||||
return response()->json(['messages' => $messages]);
|
||||
}
|
||||
|
||||
public function unreadCount()
|
||||
{
|
||||
$user = Auth::user();
|
||||
if (!$user) return response()->json(['count' => 0]);
|
||||
|
||||
$count = 0;
|
||||
foreach ($user->conversations()->with(['messages'])->get() as $conv) {
|
||||
$count += $conv->unreadCountFor($user->id);
|
||||
}
|
||||
|
||||
return response()->json(['count' => $count]);
|
||||
}
|
||||
|
||||
public function conversationsJson()
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
$convs = $user->conversations()
|
||||
->with(['participants', 'lastMessage.user'])
|
||||
->orderByDesc('conversations.updated_at')
|
||||
->limit(30)
|
||||
->get()
|
||||
->map(function ($conv) use ($user) {
|
||||
$other = $conv->participants->firstWhere('id', '!=', $user->id);
|
||||
$last = $conv->lastMessage;
|
||||
$unread = $conv->unreadCountFor($user->id);
|
||||
|
||||
$preview = null;
|
||||
if ($last) {
|
||||
if (str_starts_with($last->body, 'ANIMESHARE::')) {
|
||||
try { $sd = json_decode(substr($last->body, 12), true); $preview = '🎬 ' . ($sd['title'] ?? 'Anime paylaştı'); } catch(\Throwable) {}
|
||||
} elseif (str_starts_with($last->body, 'IMAGE::')) {
|
||||
$preview = ($last->user_id === $user->id ? 'Sen: ' : '') . '📷 Fotoğraf';
|
||||
} elseif (str_starts_with($last->body, 'GIF::')) {
|
||||
$preview = ($last->user_id === $user->id ? 'Sen: ' : '') . '🎞 GIF';
|
||||
} else {
|
||||
$isMine = $last->user_id === $user->id;
|
||||
$preview = ($isMine ? 'Sen: ' : '') . \Illuminate\Support\Str::limit($last->body, 50);
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'conv_id' => $conv->id,
|
||||
'id' => $other?->id,
|
||||
'name' => $other?->name ?? 'Silinmiş',
|
||||
'avatar' => $other?->avatar ? \App\Support\MediaUrl::fromStoragePath($other->avatar) : null,
|
||||
'last_preview' => $preview,
|
||||
'unread' => $unread,
|
||||
'time' => $conv->updated_at ? $conv->updated_at->diffForHumans(null, true) : null,
|
||||
];
|
||||
});
|
||||
|
||||
return response()->json($convs);
|
||||
}
|
||||
|
||||
public function uploadImage(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'image' => 'required|file|image|max:8192|mimes:jpeg,jpg,png,gif,webp',
|
||||
]);
|
||||
|
||||
$path = $request->file('image')->store('chat-images', 'public');
|
||||
$url = Storage::disk('public')->url($path);
|
||||
|
||||
return response()->json(['url' => $url]);
|
||||
}
|
||||
|
||||
public function quickShare(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'to_user_id' => 'required|integer|exists:users,id',
|
||||
'body' => 'required|string|max:3000',
|
||||
]);
|
||||
|
||||
$me = Auth::user();
|
||||
$target = User::findOrFail($request->to_user_id);
|
||||
|
||||
if ($me->id === $target->id) abort(422, 'Kendinize gönderemezsiniz.');
|
||||
|
||||
$conv = Conversation::whereHas('participants', fn($q) => $q->where('user_id', $me->id))
|
||||
->whereHas('participants', fn($q) => $q->where('user_id', $target->id))
|
||||
->first();
|
||||
|
||||
if (!$conv) {
|
||||
$conv = DB::transaction(function () use ($me, $target) {
|
||||
$c = Conversation::create();
|
||||
$c->participants()->attach([$me->id, $target->id]);
|
||||
return $c;
|
||||
});
|
||||
}
|
||||
|
||||
$message = Message::create([
|
||||
'conversation_id' => $conv->id,
|
||||
'user_id' => $me->id,
|
||||
'body' => $request->body,
|
||||
]);
|
||||
|
||||
$conv->touch();
|
||||
$conv->participants()->updateExistingPivot($me->id, ['last_read_at' => now()]);
|
||||
|
||||
return response()->json([
|
||||
'ok' => true,
|
||||
'conversation_id' => $conv->id,
|
||||
'message_id' => $message->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user