feat: add support for online status and read receipt preferences

- Added `showOnlineStatus` and `showReadReceipts` fields to settings form.
- Introduced real-time synchronization for read receipts in message threads.
- Enhanced avatars to display online status indicators.
- Automatically mark messages as read when viewing active conversations.
This commit is contained in:
Mathis HERRIOT
2026-01-29 18:20:58 +01:00
parent f882a70343
commit 616d7f76d7
3 changed files with 127 additions and 13 deletions

View File

@@ -2,7 +2,15 @@
import { formatDistanceToNow } from "date-fns";
import { fr } from "date-fns/locale";
import { ArrowLeft, Search, Send, UserPlus, X } from "lucide-react";
import {
ArrowLeft,
Check,
CheckCheck,
Search,
Send,
UserPlus,
X,
} from "lucide-react";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import * as React from "react";
@@ -142,6 +150,8 @@ export default function MessagesPage() {
if (activeConv?.id === data.conversationId) {
setMessages((prev) => [...prev, data.message]);
setIsOtherTyping(false); // S'il a envoyé un message, il ne tape plus
// Marquer comme lu immédiatement si on est sur la conversation
MessageService.markAsRead(data.conversationId).catch(console.error);
}
// Mettre à jour la liste des conversations
setConversations((prev) => {
@@ -184,10 +194,26 @@ export default function MessagesPage() {
}
});
socket.on(
"messages_read",
(data: { conversationId: string; readerId: string }) => {
if (activeConv?.id === data.conversationId) {
setMessages((prev) =>
prev.map((msg) =>
msg.senderId !== data.readerId && !msg.readAt
? { ...msg, readAt: new Date().toISOString() }
: msg,
),
);
}
},
);
return () => {
socket.off("new_message");
socket.off("user_status");
socket.off("user_typing");
socket.off("messages_read");
};
}
}, [socket, activeConv]);
@@ -351,7 +377,7 @@ export default function MessagesPage() {
: "hover:bg-zinc-100 dark:hover:bg-zinc-900"
}`}
>
<Avatar>
<Avatar isOnline={onlineUsers.has(conv.recipient.uuid)}>
<AvatarImage src={conv.recipient.avatarUrl} />
<AvatarFallback>
{conv.recipient.username[0].toUpperCase()}
@@ -403,7 +429,10 @@ export default function MessagesPage() {
href={`/user/${activeConv.recipient.username}`}
className="flex-1 flex items-center gap-3 hover:opacity-80 transition-opacity"
>
<Avatar className="h-8 w-8">
<Avatar
className="h-8 w-8"
isOnline={onlineUsers.has(activeConv.recipient.uuid)}
>
<AvatarImage src={activeConv.recipient.avatarUrl} />
<AvatarFallback>
{activeConv.recipient.username[0].toUpperCase()}
@@ -465,8 +494,12 @@ export default function MessagesPage() {
})}
</span>
{msg.senderId === user?.uuid && (
<span className="font-bold">
{msg.readAt ? "• Lu" : "• Envoyé"}
<span className="flex items-center">
{msg.readAt ? (
<CheckCheck className="h-3 w-3" />
) : (
<Check className="h-3 w-3" />
)}
</span>
)}
</div>