Fix des bugs de scroll dans la page de message

Fix des bugs de l'api dans le cache pour les messages
This commit is contained in:
Bilal Dieumegard 2024-12-17 21:13:43 +01:00
parent caf6e771f8
commit 15b0c91992
4 changed files with 59 additions and 25 deletions

View file

@ -1,18 +1,4 @@
services:
app:
build: .
hostname: chat-app
restart: always
environment:
- DATABASE_URL=mongodb://temp-root-username:temp-password@mongodb:27017/chat_projetweb
- JWT_SECRET=1f49ba5426afebd6e27eed416d0c31925ca5c4dc39ab4fdea514c8a858312608
ports:
- "3000:3000"
networks:
- app_network
depends_on:
- mongodb
- redis
mongodb:
build: ./mongodb_rs

View file

@ -1,7 +1,7 @@
import { createClient } from 'redis';
const client = await createClient({
url: process.env.REDIS_URL || 'redis://redis-server:6379'
url: process.env.REDIS_URL || 'redis://localhost:6379'
});

View file

@ -14,13 +14,28 @@ export async function GET({ params, url }) {
try {
logger.debug(`Tentative de récupération des messages du cache pour le channel : ${channelId}`);
const redisMessageKeys = await redisClient.zRangeWithScores(
let redisMessageKeys = await redisClient.zRangeWithScores(
`channel:${channelId}:messages`,
offset,
offset + limit - 1,
{ REV: true }
);
const redisPipelineRemove = redisClient.multi();
for (const messageKey of redisMessageKeys) {
// Vérifie si la clé existe dans Redis
const messageKeyValue = messageKey.value;
const exists = await redisClient.exists(messageKeyValue);
if (!exists) {
// Supprime la référence expirée dans le zSet
redisPipelineRemove.zRem(`channel:${channelId}:messages`, messageKeyValue);
redisMessageKeys = redisMessageKeys.filter((key) => key.value !== messageKeyValue);
}
}
await redisPipelineRemove.exec();
if (redisMessageKeys.length > 0) {
const messages = await Promise.all(
redisMessageKeys.map(async (key) => {
@ -114,7 +129,7 @@ export async function POST({ params, request }) {
});
// Ajouter le message dans Redis
await redisClient.set(`message:${newMessage.id}`, JSON.stringify(newMessage));
await redisClient.set(`message:${newMessage.id}`, JSON.stringify(newMessage), {EX: 1800});
await redisClient.zAdd(`channel:${channelId}:messages`, {
score: new Date(newMessage.createdAt).getTime(),
value: `message:${newMessage.id}`,
@ -125,6 +140,7 @@ export async function POST({ params, request }) {
let channels = cachedChannels ? JSON.parse(cachedChannels) : [];
let channel = channels.find((c) => c.id === channelId);
if(channel){
console.log('channel found')
channel.lastMessage = {
id: newMessage.id,
text: newMessage.text,
@ -141,8 +157,8 @@ export async function POST({ params, request }) {
user: newMessage.user,
createdAt: newMessage.createdAt,
}, lastUpdate: newMessage.createdAt, messages: undefined};
channels = [channel, ...channels];
}
channels = [channel, ...channels];
await redisClient.set('channels', JSON.stringify(channels), { EX: 600 });
newMessage.channel = {

View file

@ -77,6 +77,10 @@
}
isLoading = true;
const previousMessages = $messagesStore;
let newMessages = [];
try {
// Calculer la page à charger en fonction du nombre total de messages existants
const totalMessages = $messagesStore.length;
@ -90,7 +94,7 @@
});
if (response.ok) {
const newMessages = await response.json();
newMessages = await response.json();
if (newMessages.messages.length <= 0) {
console.log("Pas d'autres anciens messages");
@ -116,6 +120,23 @@
console.error("Erreur réseau lors du chargement des messages:", error);
} finally {
isLoading = false;
await tick();
const filteredNewMessages = newMessages.messages.filter((msg) => {
return !previousMessages.some((m) => m.id === msg.id);
});
scrollContainer.scrollTo({
top: filteredNewMessages.length*300,
});
}
}
function handleScroll() {
if (scrollContainer) {
// Détection quand on est en haut du scroll
if (scrollContainer.scrollTop <= 0 && !isLoading) {
loadMoreMessages();
}
}
}
@ -139,7 +160,7 @@
socket.emit('stop-writing', { userId: data.userId, channelId: data.channelId });
}
async function scrollToBottom(retries = 3) {
async function scrollToBottom(retries = 20) {
await tick();
const attemptScroll = () => {
@ -151,16 +172,22 @@
}
};
attemptScroll();
// Protéger l'utilisation de requestAnimationFrame
if (typeof window !== 'undefined' && typeof requestAnimationFrame === 'function') {
attemptScroll();
if (retries > 0) {
requestAnimationFrame(() => scrollToBottom(retries - 1));
if (retries > 0) {
requestAnimationFrame(() => scrollToBottom(retries - 1));
}
}
}
onDestroy(() => {
socket.emit('leave-channel', { userId: data.userId, channelId: data.channelId });
socket.disconnect(); // Déconnexion propre du socket
if (scrollContainer) {
scrollContainer.removeEventListener('scroll', handleScroll);
}
});
// Ecoute des événements socket
@ -221,12 +248,16 @@
messagesStore.subscribe(async () => {
await tick();
await scrollToBottom(); // Scroll to the bottom after the message is added
});
let firstPageLoad = true;
onMount(async () => {
await tick();
await scrollToBottom();
if(firstPageLoad){
firstPageLoad = false;
await scrollToBottom();
}
});
</script>
@ -254,6 +285,7 @@
<div
class="m-10 flex flex-col gap-5 overflow-auto flex-grow"
bind:this={scrollContainer}
on:scroll={handleScroll}
>
{#if isLoading}
<div class="loading-indicator">Chargement...</div>