FireChat Technical Documentation
ᴀʟᴇx
Posted on November 30, 2024
FireChat is a robust real-time chat application designed for secure, fast, and interactive messaging. This documentation outlines the core functionalities, architecture, and code snippets for developers to understand how FireChat operates under the hood.
Message Handling System
Send Message Logic
The sendMessage
function handles sending messages to the database and triggering real-time notifications via Firebase Cloud Messaging (FCM).
const sendMessage = async (chatId, message, type = 'text') => {
const messageData = {
chatId,
senderId: currentUser.uid,
text: message,
type,
timestamp: serverTimestamp(),
status: 'sent'
};
// Add to Firestore
const docRef = await addDoc(collection(db, "messages"), messageData);
// Trigger FCM notification
await triggerNotification(chatId, messageData);
return docRef.id;
};
Firebase Cloud Messaging (FCM) Server Integration
To ensure users receive push notifications, FireChat integrates FCM for sending notifications to multiple devices simultaneously.
const sendFCMNotification = async (tokens, data) => {
const message = {
notification: {
title: data.title,
body: data.body
},
data: {
chatId: data.chatId,
type: data.type
},
tokens: tokens
};
return await admin.messaging().sendMulticast(message);
};
Real-Time Updates
Message Listener
The setupMessageListener
function listens for real-time updates in a chat, ensuring users receive new messages instantly.
const setupMessageListener = (chatId) => {
const q = query(
collection(db, "messages"),
where("chatId", "==", chatId),
orderBy("timestamp", "desc"),
limit(50)
);
return onSnapshot(q, (snapshot) => {
snapshot.docChanges().forEach((change) => {
if (change.type === "added") {
handleNewMessage(change.doc.data());
}
});
});
};
User Status Tracking
To show accurate user availability, FireChat tracks user status in real-time.
const updateUserStatus = async (status) => {
const userStatusRef = doc(db, "users", currentUser.uid);
await setDoc(userStatusRef, {
status,
lastSeen: serverTimestamp()
}, { merge: true });
};
Media Handling
File Upload System
Uploading media in chats is handled with Firebase Storage.
const uploadChatMedia = async (file, chatId) => {
const storageRef = ref(storage, `chats/${chatId}/${Date.now()}_${file.name}`);
const uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on('state_changed', (snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
updateUploadProgress(progress);
});
const downloadURL = await getDownloadURL(storageRef);
return downloadURL;
};
Group Chat Management
Create Group
FireChat supports private groups with member management capabilities.
const createGroup = async (groupData) => {
const groupRef = await addDoc(collection(db, "groups"), {
name: groupData.name,
description: groupData.description,
creator: currentUser.uid,
members: [currentUser.uid],
admins: [currentUser.uid],
created: serverTimestamp(),
photoURL: groupData.photoURL || null
});
return groupRef.id;
};
Message Encryption
End-to-End Encryption
Messages are encrypted for secure communication using RSA-OAEP.
const encryptMessage = async (message, recipientPublicKey) => {
const encryptedData = await window.crypto.subtle.encrypt(
{
name: "RSA-OAEP"
},
recipientPublicKey,
new TextEncoder().encode(message)
);
return arrayBufferToBase64(encryptedData);
};
Notification System
Push Notification Handler
FireChat uses browser notifications to alert users of new messages.
const handlePushNotification = async (message) => {
if (!("Notification" in window)) return;
const permission = await Notification.requestPermission();
if (permission === "granted") {
const notification = new Notification(message.title, {
body: message.body,
icon: message.icon,
tag: message.chatId
});
notification.onclick = () => {
window.focus();
navigateToChat(message.chatId);
};
}
};
Data Syncing
Offline Support
FireChat ensures usability during network interruptions by enabling offline persistence.
const enableOfflineSupport = () => {
enableNetwork(db).then(() => {
enablePersistence(db, {
synchronizeTabs: true
}).catch((err) => {
if (err.code == 'failed-precondition') {
// Multiple tabs open
} else if (err.code == 'unimplemented') {
// Browser doesn't support persistence
}
});
});
};
Performance Optimizations
Message Pagination
Efficiently load large chat histories with message pagination.
const fetchMoreMessages = async (chatId, lastMessageId, limit = 25) => {
const lastMessageDoc = await getDoc(doc(db, "messages", lastMessageId));
const messages = await getDocs(
query(
collection(db, "messages"),
where("chatId", "==", chatId),
orderBy("timestamp", "desc"),
startAfter(lastMessageDoc),
limit(limit)
)
);
return messages.docs.map(doc => ({
id: doc.id,
...doc.data()
}));
};
Best Practices
- Error Handling: Handle errors gracefully.
- Security: Use proper encryption and secure APIs.
- Optimization: Use pagination for heavy data loads.
- Notifications: Implement fallback mechanisms for notifications.
- Documentation: Ensure proper code documentation for maintainability.
This documentation provides a solid foundation for developers to understand and extend FireChat’s functionality. With these robust systems in place, FireChat ensures a secure, efficient, and feature-rich chat experience.
Posted on November 30, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.