I created firebase website using JS and frontend.
Eveything works correctly expect this one thing. My chats are not ordering by date correctly.I want them to order in chronological order, so the older messages are on top.
My JSON snippet
"messages": {
"-O70WTtDPs8et5-zRVV4": {
"message": "Hello!",
"senderId": "UJA4AVrSSdZGOJc0bXYbxOcLOB22",
"timestamp": 1726602407195
},
"-O70WW1AMJk4mJHBZuaY": {
"message": "Hey",
"senderId": "nKHb1krQokcFdo5VcDusaaj9TLl1",
"timestamp": 1726602415953
},
"-O70WYXD2x6cNmQJAg2n": {
"message": "How are you?",
"senderId": "UJA4AVrSSdZGOJc0bXYbxOcLOB22",
"timestamp": 1726602426203
},
"-O70WbhflR-FBuYtvcNn": {
"message": "Good, thanks !",
"senderId": "nKHb1krQokcFdo5VcDusaaj9TLl1",
"timestamp": 1726602443313
},
"-O70X0TNMogcRrGyKYiJ": {
"message": "Can I exchange X",
"senderId": "UJA4AVrSSdZGOJc0bXYbxOcLOB22",
"timestamp": 1726602548834
},
"-O70X2GLfa2aKc1KOV-C": {
"message": "Yep",
"senderId": "nKHb1krQokcFdo5VcDusaaj9TLl1",
"timestamp": 1726602556185
},
"-O70hzi8OgVY6eRybn3D": {
"message": "Hallo",
"senderId": "UJA4AVrSSdZGOJc0bXYbxOcLOB22",
"timestamp": 1726605687282
}
}
This is what i see now:
What I want to see:
So even though User2 texted first when logged in as User1 I see first mt messages and only then User2 messages
My code
document.addEventListener("DOMContentLoaded", () => {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
const chatId = new URLSearchParams(window.location.search).get("chatId");
if (!chatId) {
console.error("Invalid or missing chatId in URL.");
return;
}
// Retrieve messages ordered by timestamp
const messagesRefForDisplay = firebase
.database()
.ref(`chats/${chatId}/messages`)
.orderByChild("timestamp");
// Use a regular reference for sending messages
const messagesRefForSending = firebase
.database()
.ref(`chats/${chatId}/messages`);
// Function to get username from user ID
function getUsername(userId, callback) {
const userRef = firebase.database().ref(`users/${userId}`);
userRef.once("value", (snapshot) => {
const userData = snapshot.val();
callback(userData.username);
});
}
function formatTimestamp(timestamp) {
const date = new Date(timestamp);
return date.toLocaleString(); // Customize the format if needed
}
// Load messages ordered by timestamp
messagesRefForDisplay.on("child_added", (snapshot) => {
const message = snapshot.val();
getUsername(message.senderId, (username) => {
const messageElement = document.createElement("div");
messageElement.classList.add("message");
const formattedTimestamp = formatTimestamp(message.timestamp);
messageElement.innerHTML = `<span class="sender">${username}:</span> ${message.message} <span class="timestamp">(${formattedTimestamp})</span>`;
document.getElementById("messages").appendChild(messageElement);
// Auto scroll to the bottom after a new message is added
document.getElementById("messages").scrollTop =
document.getElementById("messages").scrollHeight;
});
});
// Send message
document.getElementById("sendMessage").addEventListener("click", () => {
const messageInput = document.getElementById("messageInput");
const messageText = messageInput.value.trim();
if (messageText) {
// Use the unfiltered messagesRef for sending
messagesRefForSending
.push({
message: messageText,
senderId: user.uid, // Use user.uid here
timestamp: Date.now(),
})
.then(() => {
console.log("Message sent successfully");
})
.catch((error) => {
console.error("Error sending message:", error);
});
messageInput.value = ""; // Clear the input
}
});
} else {
console.log("User is not logged in.");
}
});
});
I think you might be experiencing a race condition due to the loading of the user names. A simple fix is to add the element to the HTML straight away, before you start loading the user name:
// Load messages ordered by timestamp
messagesRefForDisplay.on("child_added", (snapshot) => {
const message = snapshot.val();
const messageElement = document.createElement("div");
messageElement.classList.add("message");
document.getElementById("messages").appendChild(messageElement);
getUsername(message.senderId, (username) => {
const formattedTimestamp = formatTimestamp(message.timestamp);
messageElement.innerHTML = `<span class="sender">${username}:</span> ${message.message} <span class="timestamp">(${formattedTimestamp})</span>`;
// Auto scroll to the bottom after a new message is added
document.getElementById("messages").scrollTop =
document.getElementById("messages").scrollHeight;
});
});