From e28f849632b44facf3b2b9af9045a8ec1092abfd Mon Sep 17 00:00:00 2001 From: Simon Huang Date: Wed, 2 Sep 2020 10:11:13 -0400 Subject: [PATCH] added basic online list --- schema.ts | 1 + src/components/Chatbox.css | 22 ++++++++-------- src/components/Chatbox.tsx | 38 +++++++++++++-------------- src/components/OnlineList.css | 32 +++++++++++++++++++++++ src/components/OnlineList.tsx | 48 +++++++++++++++++++++++++++++++++++ src/pages/Room.tsx | 15 +++++++++-- 6 files changed, 125 insertions(+), 31 deletions(-) create mode 100644 src/components/OnlineList.css create mode 100644 src/components/OnlineList.tsx diff --git a/schema.ts b/schema.ts index a32413f..7eb4e60 100644 --- a/schema.ts +++ b/schema.ts @@ -60,6 +60,7 @@ const turtle = { userId: { name: 'Username', }, + userCount: 0, }, }, }; diff --git a/src/components/Chatbox.css b/src/components/Chatbox.css index 7cb97e2..d54147e 100644 --- a/src/components/Chatbox.css +++ b/src/components/Chatbox.css @@ -9,32 +9,34 @@ ion-textarea { margin: 0; } +.message-toolbar { + padding-left: 5px; +} + +.footer-ios ion-toolbar:first-of-type { + padding-top: 5px; +} + .send-msg { - align-items: center; - justify-content: center; - display: flex; padding-left: 0; } .send-button { - width: 100%; -} - -.message-col { - white-space: normal; - padding: 10px; + align-self: center; + margin: 0 2px 0 5px; } .message-input { + width: 100%; height: 100%; border: 1px solid #999; border-radius: 5px; + text-align: left; } @media (max-width: 576px) { .message-input { border-radius: 10px; - height: 35px; } .send-msg { diff --git a/src/components/Chatbox.tsx b/src/components/Chatbox.tsx index 6a18cd2..31b80dc 100644 --- a/src/components/Chatbox.tsx +++ b/src/components/Chatbox.tsx @@ -1,16 +1,19 @@ -import { IonButton, IonCard, IonCol, IonFooter, IonInput, IonRow } from '@ionic/react'; +import { IonCard, IonFabButton, IonFooter, IonIcon, IonInput, IonToolbar } from '@ionic/react'; +import { sendOutline } from 'ionicons/icons'; import React, { useState } from 'react'; import { db, timestamp } from '../services/firebase'; import './Chatbox.css'; import Messages from './Messages'; +import OnlineList from './OnlineList'; type ChatboxProps = { ownerId: string; roomId: string; userId: string; + userList: string[]; }; -const Chat: React.FC = ({ ownerId, roomId, userId }) => { +const Chat: React.FC = ({ ownerId, roomId, userId, userList }) => { const [message, setMessage] = useState(''); // Message to be sent // Send message to database @@ -38,23 +41,20 @@ const Chat: React.FC = ({ ownerId, roomId, userId }) => { - - - setMessage(e.detail.value!)} - onKeyDown={(e) => onEnter(e)} - value={message} - placeholder="Send message" - enterkeyhint="send" - class="message-input" - > - - - - Send - - - + + setMessage(e.detail.value!)} + onKeyDown={(e) => onEnter(e)} + value={message} + placeholder="Send message" + enterkeyhint="send" + class="message-input" + > + + + + + ); diff --git a/src/components/OnlineList.css b/src/components/OnlineList.css new file mode 100644 index 0000000..a3ff405 --- /dev/null +++ b/src/components/OnlineList.css @@ -0,0 +1,32 @@ +.online-button { + margin: 0 4px 0 0; + align-self: center; +} + +.popover-list { + padding-top: 2px; +} + +.online-popover .popover-content { + font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; +} + +.list-header { + font-size: 24px; + color: var(--ion-color-primary); + border-bottom: 1px solid #999; +} + +.online-item { + --padding-start: 12px; + --min-height: 0; +} + +.online-label { + margin-top: 8px; + margin-bottom: 0; +} + +ion-backdrop { + cursor: default; +} diff --git a/src/components/OnlineList.tsx b/src/components/OnlineList.tsx new file mode 100644 index 0000000..7659cec --- /dev/null +++ b/src/components/OnlineList.tsx @@ -0,0 +1,48 @@ +import React, { useState } from 'react'; +import { IonPopover, IonFabButton, IonIcon, IonList, IonListHeader, IonItem, IonLabel } from '@ionic/react'; +import { peopleOutline } from 'ionicons/icons'; +import './OnlineList.css'; + +type OnlineListProps = { + userList: string[]; +}; + +const OnlineList: React.FC = ({ userList }) => { + const [showPopover, setShowPopover] = useState<{ open: boolean; event: Event | undefined }>({ + open: false, + event: undefined, + }); + + return ( + <> + setShowPopover({ open: false, event: undefined })} + > + + Online + {userList.map((user) => { + return ( + + {user} + + ); + })} + + + setShowPopover({ open: true, event: e.nativeEvent })} + > + + + + ); +}; + +export default OnlineList; diff --git a/src/pages/Room.tsx b/src/pages/Room.tsx index b001439..6c967e5 100644 --- a/src/pages/Room.tsx +++ b/src/pages/Room.tsx @@ -19,6 +19,7 @@ const Room: React.FC> = ({ match }) => { const [userCount, setUserCount] = useState(0); const [videoId, setVideoId] = useState(''); const [stateId, setStateId] = useState(''); + const [userList, setUserList] = useState(['']); // Verify that the roomId exists in db useEffect(() => { @@ -73,9 +74,19 @@ const Room: React.FC> = ({ match }) => { // Keep track of online user presence in realtime database rooms roomRef.on('value', async (snapshot) => { + // Populate list of users in a room + const set: string[] = []; + snapshot.forEach((childSnapshot) => { + if (childSnapshot.key !== 'userCount') { + set.push(childSnapshot.child('name').val()); + } + }); + setUserList(set); + if (!snapshot.hasChild(userId)) { // Keep userId in the room as long as a connection from the client exists - await roomRef.child(userId).set({ name: 'placeholder' }); + const username = (await db.collection('users').doc(userId).get()).data()?.name; + await roomRef.child(userId).set({ name: username }); await roomRef.update({ userCount: increment }); } }); @@ -154,7 +165,7 @@ const Room: React.FC> = ({ match }) => { - +