diff --git a/schema.ts b/schema.ts index 80b231e..7473112 100644 --- a/schema.ts +++ b/schema.ts @@ -76,6 +76,7 @@ const turtle = { userId: { name: 'Username', }, + userCount: 0, }, }, }; diff --git a/src/assets/OpenSans-Light.ttf b/src/assets/OpenSans-Light.ttf new file mode 100644 index 0000000..6580d3a Binary files /dev/null and b/src/assets/OpenSans-Light.ttf differ diff --git a/src/assets/OpenSans-Regular.ttf b/src/assets/OpenSans-Regular.ttf new file mode 100644 index 0000000..29bfd35 Binary files /dev/null and b/src/assets/OpenSans-Regular.ttf differ diff --git a/src/assets/OpenSans-SemiBold.ttf b/src/assets/OpenSans-SemiBold.ttf new file mode 100644 index 0000000..54e7059 Binary files /dev/null and b/src/assets/OpenSans-SemiBold.ttf differ diff --git a/src/assets/PathwayGothicOne-Regular.ttf b/src/assets/PathwayGothicOne-Regular.ttf new file mode 100644 index 0000000..c698c6f Binary files /dev/null and b/src/assets/PathwayGothicOne-Regular.ttf differ diff --git a/src/components/Chatbox.css b/src/components/Chatbox.css index 7cb97e2..b45dde6 100644 --- a/src/components/Chatbox.css +++ b/src/components/Chatbox.css @@ -3,38 +3,43 @@ ion-textarea { } .chat-card { + background: var(--ion-color-light); height: 100%; width: 100%; float: right; margin: 0; } +.message-toolbar { + padding-left: 5px; + --background: var(--ion-color-light); +} + +.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; + --box-shadow: 0 3px 2px -1px rgba(0, 0, 0, 0.2), 0 2px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } .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/Messages.css b/src/components/Messages.css index 9c7a011..bb1e88f 100644 --- a/src/components/Messages.css +++ b/src/components/Messages.css @@ -7,7 +7,7 @@ .message-grid { margin-right: 0; height: 100%; - user-select: auto; + user-select: text; } .right-align { diff --git a/src/components/OnlineList.css b/src/components/OnlineList.css new file mode 100644 index 0000000..a7f27f8 --- /dev/null +++ b/src/components/OnlineList.css @@ -0,0 +1,29 @@ +.online-button { + margin: 0 4px 0 0; + align-self: center; + --box-shadow: 0 3px 2px -1px rgba(0, 0, 0, 0.2), 0 2px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12); +} + +.popover-list { + padding-top: 2px; +} + +.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/components/RoomHeader.css b/src/components/RoomHeader.css index 465baa5..fd7e378 100644 --- a/src/components/RoomHeader.css +++ b/src/components/RoomHeader.css @@ -1,11 +1,9 @@ .title { text-align: left; - max-width: 100px; + max-width: 110px; padding-left: 15px; padding-right: 15px; color: var(--ion-color-primary); - font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; - font-size: 24px; cursor: pointer; } diff --git a/src/components/RoomHeader.tsx b/src/components/RoomHeader.tsx index cb3efc9..355a6cd 100644 --- a/src/components/RoomHeader.tsx +++ b/src/components/RoomHeader.tsx @@ -33,14 +33,14 @@ const RoomHeader: React.FC = ({ roomId, userId, ownerId }) => { }; const toHome = () => { - history.replace('/'); + history.push('/'); history.go(0); }; return ( - Turtle + TURTLE {userId === ownerId ? ( <> @@ -49,7 +49,7 @@ const RoomHeader: React.FC = ({ roomId, userId, ownerId }) => { type="url" inputmode="search" class="input-bar" - placeholder="Upload new video by URL" + placeholder="Upload video by URL" onIonChange={(e) => setVideoUrl(e.detail.value!)} value={videoUrl} onSubmit={onSubmit} diff --git a/src/pages/Home.css b/src/pages/Home.css index 09fc8f7..ef8971f 100644 --- a/src/pages/Home.css +++ b/src/pages/Home.css @@ -2,11 +2,14 @@ width: 50%; } +.home-content { + --background: var(--ion-color-light-shade); +} + .home-grid { max-width: 500px; - font-family: Verdana, Geneva, Tahoma, sans-serif; - font-size: 30px; - color: var(--ion-color-secondary); + font-size: 26px; + color: var(--ion-color-primary); text-align: center; } @@ -15,8 +18,8 @@ ion-toolbar { } ion-title { - font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; - font-size: 24px; + font-size: 28px; + font-style: oblique; color: var(--ion-color-primary); } @@ -30,7 +33,6 @@ ion-title { } .share-col { - margin-top: 10px; + margin-top: 8px; font-size: 20px; - color: var(--ion-color-primary); } diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 0151061..7cd8372 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -57,10 +57,10 @@ const Home: React.FC = () => { - Turtle + TURTLE - + {loading ? ( Loading... ) : ( diff --git a/src/pages/Room.css b/src/pages/Room.css index 37d9478..a9502f5 100644 --- a/src/pages/Room.css +++ b/src/pages/Room.css @@ -1,4 +1,5 @@ .room-grid { + background: var(--ion-color-light-shade); margin-inline-start: 0; margin-inline-end: 0; height: 100%; diff --git a/src/pages/Room.tsx b/src/pages/Room.tsx index cb57ed8..d947d1b 100644 --- a/src/pages/Room.tsx +++ b/src/pages/Room.tsx @@ -17,6 +17,7 @@ const Room: React.FC> = ({ match }) => { const [ownerId, setOwnerId] = useState('undefined'); const [loading, setLoading] = useState(true); const [userCount, setUserCount] = useState(0); + const [userList, setUserList] = useState(['']); // Handle logging in useEffect(() => { @@ -61,9 +62,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 }); } }); @@ -142,7 +153,7 @@ const Room: React.FC> = ({ match }) => { - + diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 8ce538d..0e05329 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1,24 +1,34 @@ const adjectives = [ - 'Adamant', - 'Instinctive', + 'Abaft', 'Actually', - 'Husky', + 'Adamant', + 'Adorable', + 'Anxious', 'Bent', - 'Fascinated', - 'Sexual', - 'Mute', - 'Silent', + 'Bright', 'Coherent', + 'Curious', + 'Diligent', + 'Earthy', + 'Fascinated', + 'Foreign', + 'Hateful', + 'Husky', + 'Instinctive', + 'Jagged', 'Juvenile', + 'Military', + 'Mute', 'Naughty', - 'Foreign', - 'Earthy', - 'Diligent', - 'Anxious', - 'Adorable', + 'Neat', + 'Nifty', + 'Parallel', 'Quack', - 'Unequal', + 'Roomy', + 'Sedate', 'Sharp', + 'Silent', + 'Unequal', ]; const animals = [ @@ -59,7 +69,7 @@ const animals = [ // }; export const generateAnonName = (): string => { - const adj: string = adjectives[Math.floor(Math.random() * 20)]; + const adj: string = adjectives[Math.floor(Math.random() * 30)]; const animal: string = animals[Math.floor(Math.random() * 20)]; return adj + ' ' + animal; }; diff --git a/src/theme/variables.css b/src/theme/variables.css index 8d6ebdc..ac60c7a 100644 --- a/src/theme/variables.css +++ b/src/theme/variables.css @@ -72,8 +72,31 @@ http://ionicframework.com/docs/theming/ */ --ion-color-light-rgb: 244, 245, 248; --ion-color-light-contrast: #000000; --ion-color-light-contrast-rgb: 0, 0, 0; - --ion-color-light-shade: #d7d8da; + --ion-color-light-shade: #edeeef; --ion-color-light-tint: #f5f6f9; + + --ion-font-family: 'custom'; +} + +@font-face { + font-family: 'custom'; + font-style: normal; + font-weight: normal; + src: url('../assets/OpenSans-Regular.ttf'); +} + +@font-face { + font-family: 'custom'; + font-style: normal; + font-weight: bold; + src: url('../assets/OpenSans-SemiBold.ttf'); +} + +@font-face { + font-family: 'custom'; + font-style: oblique; + font-weight: normal; + src: url('../assets/PathwayGothicOne-Regular.ttf'); } @media (prefers-color-scheme: dark) { @@ -84,65 +107,65 @@ http://ionicframework.com/docs/theming/ */ body { --ion-color-primary: #428cff; - --ion-color-primary-rgb: 66,140,255; + --ion-color-primary-rgb: 66, 140, 255; --ion-color-primary-contrast: #ffffff; - --ion-color-primary-contrast-rgb: 255,255,255; + --ion-color-primary-contrast-rgb: 255, 255, 255; --ion-color-primary-shade: #3a7be0; --ion-color-primary-tint: #5598ff; --ion-color-secondary: #50c8ff; - --ion-color-secondary-rgb: 80,200,255; + --ion-color-secondary-rgb: 80, 200, 255; --ion-color-secondary-contrast: #ffffff; - --ion-color-secondary-contrast-rgb: 255,255,255; + --ion-color-secondary-contrast-rgb: 255, 255, 255; --ion-color-secondary-shade: #46b0e0; --ion-color-secondary-tint: #62ceff; --ion-color-tertiary: #6a64ff; - --ion-color-tertiary-rgb: 106,100,255; + --ion-color-tertiary-rgb: 106, 100, 255; --ion-color-tertiary-contrast: #ffffff; - --ion-color-tertiary-contrast-rgb: 255,255,255; + --ion-color-tertiary-contrast-rgb: 255, 255, 255; --ion-color-tertiary-shade: #5d58e0; --ion-color-tertiary-tint: #7974ff; --ion-color-success: #2fdf75; - --ion-color-success-rgb: 47,223,117; + --ion-color-success-rgb: 47, 223, 117; --ion-color-success-contrast: #000000; - --ion-color-success-contrast-rgb: 0,0,0; + --ion-color-success-contrast-rgb: 0, 0, 0; --ion-color-success-shade: #29c467; --ion-color-success-tint: #44e283; --ion-color-warning: #ffd534; - --ion-color-warning-rgb: 255,213,52; + --ion-color-warning-rgb: 255, 213, 52; --ion-color-warning-contrast: #000000; - --ion-color-warning-contrast-rgb: 0,0,0; + --ion-color-warning-contrast-rgb: 0, 0, 0; --ion-color-warning-shade: #e0bb2e; --ion-color-warning-tint: #ffd948; --ion-color-danger: #ff4961; - --ion-color-danger-rgb: 255,73,97; + --ion-color-danger-rgb: 255, 73, 97; --ion-color-danger-contrast: #ffffff; - --ion-color-danger-contrast-rgb: 255,255,255; + --ion-color-danger-contrast-rgb: 255, 255, 255; --ion-color-danger-shade: #e04055; --ion-color-danger-tint: #ff5b71; --ion-color-dark: #f4f5f8; - --ion-color-dark-rgb: 244,245,248; + --ion-color-dark-rgb: 244, 245, 248; --ion-color-dark-contrast: #000000; - --ion-color-dark-contrast-rgb: 0,0,0; + --ion-color-dark-contrast-rgb: 0, 0, 0; --ion-color-dark-shade: #d7d8da; --ion-color-dark-tint: #f5f6f9; --ion-color-medium: #989aa2; - --ion-color-medium-rgb: 152,154,162; + --ion-color-medium-rgb: 152, 154, 162; --ion-color-medium-contrast: #000000; - --ion-color-medium-contrast-rgb: 0,0,0; + --ion-color-medium-contrast-rgb: 0, 0, 0; --ion-color-medium-shade: #86888f; --ion-color-medium-tint: #a2a4ab; --ion-color-light: #222428; - --ion-color-light-rgb: 34,36,40; + --ion-color-light-rgb: 34, 36, 40; --ion-color-light-contrast: #ffffff; - --ion-color-light-contrast-rgb: 255,255,255; + --ion-color-light-contrast-rgb: 255, 255, 255; --ion-color-light-shade: #1e2023; --ion-color-light-tint: #383a3e; } @@ -154,10 +177,10 @@ http://ionicframework.com/docs/theming/ */ .ios body { --ion-background-color: #000000; - --ion-background-color-rgb: 0,0,0; + --ion-background-color-rgb: 0, 0, 0; --ion-text-color: #ffffff; - --ion-text-color-rgb: 255,255,255; + --ion-text-color-rgb: 255, 255, 255; --ion-color-step-50: #0d0d0d; --ion-color-step-100: #1a1a1a; @@ -186,7 +209,6 @@ http://ionicframework.com/docs/theming/ */ --ion-card-background: #1c1c1d; } - /* * Material Design Dark Theme * ------------------------------------------- @@ -194,10 +216,10 @@ http://ionicframework.com/docs/theming/ */ .md body { --ion-background-color: #121212; - --ion-background-color-rgb: 18,18,18; + --ion-background-color-rgb: 18, 18, 18; --ion-text-color: #ffffff; - --ion-text-color-rgb: 255,255,255; + --ion-text-color-rgb: 255, 255, 255; --ion-border-color: #222222;