From a326c7dc871d111f76058ae7eb0ca84e04ed4caf Mon Sep 17 00:00:00 2001 From: Simon Huang Date: Sat, 8 Aug 2020 18:44:16 -0400 Subject: [PATCH] maintain user presence in rooms with Realtime Database --- src/pages/Home.tsx | 24 +++++++++++++++++------ src/pages/Room.tsx | 47 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 7136932..7043eaa 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,7 +1,7 @@ import { IonButton, IonContent, IonGrid, IonHeader, IonPage, IonRow, IonTitle, IonToolbar } from '@ionic/react'; import React, { useEffect, useState } from 'react'; import { useHistory } from 'react-router'; -import { db, timestamp } from '../services/firebase'; +import { db, timestamp, auth, rtdb } from '../services/firebase'; import './Home.css'; const Home: React.FC = () => { @@ -10,20 +10,32 @@ const Home: React.FC = () => { let history = useHistory(); - const handleClick = async () => { + // Populate both Firestore and RealTimeDB before navigating to room + const createRoom = async () => { const roomId = await db.collection('rooms').add({ createdAt: timestamp, ownerId: userId, }); + await rtdb.ref('/rooms/' + roomId.id).set({ [userId]: 'placeholder', exists: true }); const path = '/room/' + roomId.id; return history.push(path); }; + // Sign in anonymously before showing Create Room button useEffect(() => { - console.log('Hook fired'); - setUserId('placeholder'); - setLoading(false); + const authUnsubscribe = auth.onAuthStateChanged((user) => { + if (user) { + setUserId(user.uid); + setLoading(false); + } else { + auth.signInAnonymously(); + } + }); + + return () => { + authUnsubscribe(); + }; }, []); return ( @@ -39,7 +51,7 @@ const Home: React.FC = () => { {loading ? ( Loading... ) : ( - Create Room + Create Room )} diff --git a/src/pages/Room.tsx b/src/pages/Room.tsx index 4d548d4..fb4d075 100644 --- a/src/pages/Room.tsx +++ b/src/pages/Room.tsx @@ -1,13 +1,14 @@ import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react'; import React, { useEffect, useState } from 'react'; import { RouteComponentProps, useHistory } from 'react-router'; -import { db } from '../services/firebase'; +import { auth, db, rtdb } from '../services/firebase'; const Room: React.FC> = ({ match }) => { const history = useHistory(); const roomId = match.params.roomId; - const [loading, setLoading] = useState(true); + const [validRoom, setValidRoom] = useState(false); + const [userId, setUserId] = useState(''); // Verify that the roomId exists in db useEffect(() => { @@ -16,14 +17,50 @@ const Room: React.FC> = ({ match }) => { if (!room.exists) { history.push('/'); } else { - setLoading(false); + setValidRoom(true); } }; - console.log('Hook fired'); fetchRoom(); }, [history, roomId]); + // Handle logging in + useEffect(() => { + const authUnsubscribe = auth.onAuthStateChanged((user) => { + if (user) { + setUserId(user.uid); + } else { + auth.signInAnonymously(); + } + }); + + return () => { + authUnsubscribe(); + }; + }, []); + + // Keep track of user presence in realtime database rooms + useEffect(() => { + if (userId !== '' && validRoom) { + const populateRoom = async () => { + // Keep userId in the room as long as a connection from the client exists + rtdb.ref('/rooms/' + roomId).on('value', async (snapshot) => { + if (snapshot.val()) { + await rtdb.ref('/rooms/' + roomId).update({ [userId]: 'placeholder' }); + } + }); + + // Remove userId from the room on disconnect (closing a browser window/tab) + await rtdb + .ref('/rooms/' + roomId + '/' + userId) + .onDisconnect() + .remove(); + }; + + populateRoom(); + } + }, [userId, validRoom, roomId]); + return ( @@ -31,7 +68,7 @@ const Room: React.FC> = ({ match }) => { Turtle - {!loading ? ( + {validRoom ? ( Video and chat ) : ( Loading...