user(); // IDs de usuarios con quienes hay mensajes intercambiados $sentTo = Message::where('user_id', $me->id)->pluck('receiver_id'); $receivedFrom = Message::where('receiver_id', $me->id)->pluck('user_id'); $conversationIds = $sentTo->merge($receivedFrom)->unique()->values(); // Amigos (con o sin historial de mensajes) $friendIds = collect($me->friendIds()); $allIds = $conversationIds->merge($friendIds)->unique()->values(); $users = User::whereIn('id', $allIds)->orderBy('name')->get() ->map(function (User $user) use ($me) { $user->is_friend = $me->isFriendWith($user); return $user; }); return view('chat.index', compact('users')); } // Mensajes entre yo y otro usuario public function show(User $user) { $me = auth()->user(); $isFriend = $me->isFriendWith($user); $friendship = $me->friendshipWith($user); $messages = Message::where(function ($q) use ($user) { $q->where('user_id', auth()->id()) ->where('receiver_id', $user->id); }) ->orWhere(function ($q) use ($user) { $q->where('user_id', $user->id) ->where('receiver_id', auth()->id()); }) ->with('sender') ->orderBy('created_at', 'asc') ->get(); // marcar como leĆ­dos solo si son amigos if ($isFriend) { Message::where('user_id', $user->id) ->where('receiver_id', $me->id) ->whereNull('read_at') ->update(['read_at' => now()]); } return view('chat.show', compact('user', 'messages', 'isFriend', 'friendship')); } // Enviar mensaje public function send(Request $request) { $request->validate([ 'receiver_id' => 'required|exists:users,id', 'body' => 'nullable|string', 'attachment' => 'nullable|file|max:51200', ]); $receiver = User::findOrFail($request->receiver_id); abort_unless(auth()->user()->isFriendWith($receiver), 403, 'No puedes enviar mensajes a esta persona.'); $attachment = null; $attachmentType = null; if ($request->hasFile('attachment')) { $file = $request->file('attachment'); $attachment = $file->store('chat', 'local'); $mime = $file->getMimeType(); if (str_starts_with($mime, 'image')) $attachmentType = 'image'; elseif (str_starts_with($mime, 'video')) $attachmentType = 'video'; elseif (str_starts_with($mime, 'audio')) $attachmentType = 'audio'; else $attachmentType = 'file'; } $message = Message::create([ 'user_id' => auth()->id(), 'receiver_id' => $request->receiver_id, 'body' => $request->body, 'attachment' => $attachment, 'attachment_type' => $attachmentType, ]); $message->load('sender'); try { broadcast(new MessageSent($message))->toOthers(); } catch (\Exception $e) { \Log::warning('Chat broadcast failed: ' . $e->getMessage()); } $message->created_at = $message->created_at->format('H:i'); return response()->json($message); } }