moved chats to realtime database

pull/3/head
Simon Huang 5 years ago
parent fe1934d7b3
commit 92489bd96b

@ -8,19 +8,6 @@
// Firestore // Firestore
const collection = { const collection = {
chats: [
{
roomId: {
messages: [
{
content: 'Message content',
createdAt: 'timestamp',
senderId: 'userId',
},
],
},
},
],
playlists: [ playlists: [
{ {
roomId: { roomId: {
@ -71,6 +58,17 @@ const turtle = {
}, },
}, },
// Keep chats in Realtime DB could potentially lower cost
chats: {
roomId: {
messageId: {
content: 'Message content',
senderId: 'userId',
createdAt: 'timestamp',
},
},
},
// Keeping track of which users are present in a room // Keeping track of which users are present in a room
rooms: { rooms: {
roomId: { roomId: {

@ -1,7 +1,7 @@
import { IonCard, IonFabButton, IonFooter, IonIcon, IonInput, IonToolbar } from '@ionic/react'; import { IonCard, IonFabButton, IonFooter, IonIcon, IonInput, IonToolbar } from '@ionic/react';
import { sendOutline } from 'ionicons/icons'; import { sendOutline } from 'ionicons/icons';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { db, arrayUnion } from '../services/firebase'; import { rtdb } from '../services/firebase';
import './Chatbox.css'; import './Chatbox.css';
import Messages from './Messages'; import Messages from './Messages';
import OnlineList from './OnlineList'; import OnlineList from './OnlineList';
@ -19,16 +19,11 @@ const Chat: React.FC<ChatboxProps> = ({ ownerId, roomId, userId, userList }) =>
// Send message to database // Send message to database
const sendMessage = async () => { const sendMessage = async () => {
if (message !== '') { if (message !== '') {
await db await rtdb.ref('/chats/' + roomId).push({
.collection('chats') content: message,
.doc(roomId) createdAt: Date.now(),
.update({ senderId: userId,
messages: arrayUnion({ });
createdAt: Date.now(),
senderId: userId,
content: message,
}),
});
// Reset textarea field // Reset textarea field
setMessage(''); setMessage('');

@ -1,6 +1,6 @@
import { IonCol, IonContent, IonGrid, IonRow } from '@ionic/react'; import { IonCol, IonContent, IonGrid, IonRow } from '@ionic/react';
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { db, arrayUnion } from '../services/firebase'; import { db, arrayUnion, rtdb } from '../services/firebase';
import './Messages.css'; import './Messages.css';
import { secondsToTimestamp } from '../services/utilities'; import { secondsToTimestamp } from '../services/utilities';
@ -37,31 +37,22 @@ const Messages: React.FC<MessagesProps> = ({ ownerId, roomId, userId, userList }
// Listen for new chat messages // Listen for new chat messages
useEffect(() => { useEffect(() => {
const chatUnsubscribe = db rtdb.ref('/chats/' + roomId).on('value', (snapshot) => {
.collection('chats') let arr: Message[] = [];
.doc(roomId) snapshot.forEach((child) => {
.onSnapshot((docSnapshot) => { const msg = child.val();
const data = docSnapshot.data(); arr.push({
if (data !== undefined) { content: msg.content,
const messages = data.messages; createdAt: msg.createdAt,
id: msg.senderId + msg.createdAt,
let arr: Message[] = []; senderId: msg.senderId,
for (const msg of messages) { });
if (msg.createdAt > joinTime) {
arr.push({
content: msg.content,
createdAt: msg.createdAt,
id: msg.senderId + msg.createdAt,
senderId: msg.senderId,
});
}
}
setChats(arr);
}
}); });
setChats(arr);
});
return () => { return () => {
chatUnsubscribe(); rtdb.ref('/chats/' + roomId).off('value');
}; };
}, [roomId, joinTime]); }, [roomId, joinTime]);
@ -142,22 +133,24 @@ const Messages: React.FC<MessagesProps> = ({ ownerId, roomId, userId, userList }
return name; return name;
}; };
const renderMessages = () => {
return allMessages
.sort((msg1, msg2) => msg1.createdAt - msg2.createdAt)
.map((msg) => {
return (
<IonRow key={msg.id} class={msg.senderId === userId ? 'right-align' : ''}>
<IonCol size="auto" class={msg.senderId === userId ? 'my-msg' : 'other-msg'}>
{getName(msg.senderId) !== '' ? <b>{getName(msg.senderId)}: </b> : <></>}
<span>{msg.content}</span>
</IonCol>
</IonRow>
);
});
};
return ( return (
<IonContent class="message-card" ref={contentRef}> <IonContent class="message-card" ref={contentRef}>
<IonGrid class="message-grid"> <IonGrid class="message-grid">{userList.size === 0 ? <span>Loading...</span> : renderMessages()}</IonGrid>
{allMessages
.sort((msg1, msg2) => msg1.createdAt - msg2.createdAt)
.map((msg) => {
return (
<IonRow key={msg.id} class={msg.senderId === userId ? 'right-align' : ''}>
<IonCol size="auto" class={msg.senderId === userId ? 'my-msg' : 'other-msg'}>
{getName(msg.senderId) !== '' ? <b>{getName(msg.senderId)}: </b> : <></>}
<span>{msg.content}</span>
</IonCol>
</IonRow>
);
})}
</IonGrid>
</IonContent> </IonContent>
); );
}; };

@ -20,9 +20,6 @@ const Home: React.FC = () => {
requests: [], requests: [],
state: { time: 0, isPlaying: false }, state: { time: 0, isPlaying: false },
}); });
await db.collection('chats').doc(roomId.id).set({
messages: [],
});
await db.collection('playlists').doc(roomId.id).set({ await db.collection('playlists').doc(roomId.id).set({
createdAt: timestamp, createdAt: timestamp,
url: 'https://www.youtube.com/watch?v=XEfDYMngJeE', url: 'https://www.youtube.com/watch?v=XEfDYMngJeE',
@ -35,6 +32,7 @@ const Home: React.FC = () => {
// RealTimeDB preparations // RealTimeDB preparations
await rtdb.ref('/rooms/' + roomId.id).set({ userCount: 0 }); await rtdb.ref('/rooms/' + roomId.id).set({ userCount: 0 });
await rtdb.ref('/available/' + roomId.id).set({ name: 'Room Name', createdAt: new Date().toISOString() }); await rtdb.ref('/available/' + roomId.id).set({ name: 'Room Name', createdAt: new Date().toISOString() });
await rtdb.ref('/chats/' + roomId.id).set({ content: 'created a room.', createdAt: Date.now(), senderId: userId });
const path = '/room/' + roomId.id; const path = '/room/' + roomId.id;
return history.push(path); return history.push(path);

@ -114,10 +114,11 @@ const Room: React.FC<RouteComponentProps<{ roomId: string }>> = ({ match }) => {
// Handle disconnect events // Handle disconnect events
useEffect(() => { useEffect(() => {
if (!loading && userId !== '' && validRoom) { if (!loading && userId !== '' && validRoom) {
const depopulateRoom = async () => { const depopulate = async () => {
const refUser = rtdb.ref('/rooms/' + roomId + '/' + userId); const refUser = rtdb.ref('/rooms/' + roomId + '/' + userId);
const refRoom = rtdb.ref('/rooms/' + roomId); const refRoom = rtdb.ref('/rooms/' + roomId);
const refAvailable = rtdb.ref('/available/' + roomId); const refAvailable = rtdb.ref('/available/' + roomId);
const refChat = rtdb.ref('/chats/' + roomId);
// Always remove user from room on disconnect // Always remove user from room on disconnect
await refRoom.onDisconnect().update({ userCount: decrement }); await refRoom.onDisconnect().update({ userCount: decrement });
@ -127,15 +128,17 @@ const Room: React.FC<RouteComponentProps<{ roomId: string }>> = ({ match }) => {
if (userCount <= 1) { if (userCount <= 1) {
await refRoom.onDisconnect().remove(); await refRoom.onDisconnect().remove();
await refAvailable.onDisconnect().remove(); await refAvailable.onDisconnect().remove();
await refChat.onDisconnect().remove();
} else { } else {
await refRoom.onDisconnect().cancel(); // Cancels all disconnect actions at and under refRoom await refRoom.onDisconnect().cancel(); // Cancel all disconnect actions
await refAvailable.onDisconnect().cancel(); await refAvailable.onDisconnect().cancel();
await refChat.onDisconnect().cancel();
await refRoom.onDisconnect().update({ userCount: decrement }); // User disconnect still needs to be handled await refRoom.onDisconnect().update({ userCount: decrement }); // User disconnect still needs to be handled
await refUser.onDisconnect().remove(); await refUser.onDisconnect().remove();
} }
}; };
depopulateRoom(); depopulate();
} }
}, [userId, validRoom, roomId, loading, userCount]); }, [userId, validRoom, roomId, loading, userCount]);

Loading…
Cancel
Save