Compare commits
2 Commits
34cdf4aea1
...
d620dc7d5e
Author | SHA1 | Date |
---|---|---|
open-schnick | d620dc7d5e | |
open-schnick | 1aa7914289 |
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"useTabs": false,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"jsxSingleQuote": false,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"bracketSameLine": false,
|
||||||
|
"arrowParens": "always",
|
||||||
|
"embeddedLanguageFormatting": "auto",
|
||||||
|
"endOfLine": "lf",
|
||||||
|
"printWidth": 100,
|
||||||
|
"vueIndentScriptAndStyle": false
|
||||||
|
}
|
|
@ -6,7 +6,6 @@ Using vite and react plus the jitsi react sdk for the frontend.
|
||||||
|
|
||||||
Use yarn:
|
Use yarn:
|
||||||
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
yarn run dev
|
yarn run dev
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
|
||||||
yarn build
|
yarn build
|
||||||
scp -r dist/* ffs:/home/ffsys/apps/static/jitsi-rooms
|
scp -r dist/* ffs:/home/ffsys/apps/static/jitsi-rooms
|
||||||
|
|
|
@ -22,6 +22,12 @@
|
||||||
"@types/react": "^18.0.26",
|
"@types/react": "^18.0.26",
|
||||||
"@types/react-dom": "^18.0.9",
|
"@types/react-dom": "^18.0.9",
|
||||||
"@vitejs/plugin-react": "^3.0.0",
|
"@vitejs/plugin-react": "^3.0.0",
|
||||||
|
"eslint": "^8.38.0",
|
||||||
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
|
"eslint-plugin-import": "^2.27.5",
|
||||||
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||||
|
"eslint-plugin-react": "^7.32.2",
|
||||||
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"typescript": "^4.9.3",
|
"typescript": "^4.9.3",
|
||||||
"vite": "^4.0.0"
|
"vite": "^4.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,30 @@
|
||||||
import { Provider } from "jotai";
|
import './App.css'
|
||||||
import { useState } from "react";
|
import Meeting from './components/meeting/Meeting'
|
||||||
import "./App.css";
|
import Sidebar from './components/sidebar/Sidebar'
|
||||||
import Meeting from "./components/meeting/Meeting";
|
import useBackendData from './hooks/useBackendData'
|
||||||
import Sidebar from "./components/sidebar/Sidebar";
|
import useConferenceData from './hooks/useConferenceData'
|
||||||
import useBackendData from "./hooks/useBackendData";
|
import useLocalUser from './hooks/useLocalUser'
|
||||||
import useConferenceData from "./hooks/useConferenceData";
|
|
||||||
import useLocalUser from "./hooks/useLocalUser";
|
|
||||||
import { useRoomName } from "./hooks/useRoomName";
|
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const { userInfo, setUserInfo } = useLocalUser();
|
const { userInfo, setUserInfo } = useLocalUser()
|
||||||
const { roomData, sendMessage } = useBackendData(userInfo);
|
const { roomData, sendMessage } = useBackendData(userInfo)
|
||||||
const { conferenceData, setConferenceData } = useConferenceData(
|
const { conferenceData, setConferenceData } = useConferenceData(sendMessage, setUserInfo)
|
||||||
sendMessage,
|
|
||||||
setUserInfo
|
|
||||||
);
|
|
||||||
const [meetingStarted, setMeetingStarted] = useState(false);
|
|
||||||
|
|
||||||
console.log(roomData);
|
console.log('[App] [Room Data]', roomData)
|
||||||
|
|
||||||
if (roomData && userInfo) {
|
if (roomData && userInfo) {
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<Sidebar usersData={roomData}
|
<Sidebar usersData={roomData} sendMessage={sendMessage} />
|
||||||
sendMessage={sendMessage}
|
|
||||||
/>
|
|
||||||
<Meeting
|
<Meeting
|
||||||
conferenceData={conferenceData}
|
conferenceData={conferenceData}
|
||||||
setConferenceData={setConferenceData}
|
setConferenceData={setConferenceData}
|
||||||
userInfo={userInfo}
|
userInfo={userInfo}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
return <h2>🌀 Loading...</h2>;
|
return <h2>🌀 Loading...</h2>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
const ISPROD = window.location.protocol == "https:";
|
const ISPROD = window.location.protocol == 'https:'
|
||||||
const JITSI_DOMAIN = "thisisnotajitsi.filefighter.de";
|
const JITSI_DOMAIN = 'thisisnotajitsi.filefighter.de'
|
||||||
const USE_REMOTE_BACKEND = true;
|
const USE_REMOTE_BACKEND = true
|
||||||
const getWebsocketUrl = () => {
|
const getWebsocketUrl = () => {
|
||||||
if (ISPROD) return "wss://" + window.location.host + "/ws"
|
if (ISPROD) return 'wss://' + window.location.host + '/ws'
|
||||||
if (USE_REMOTE_BACKEND) return "wss://" + "discord.filefighter.de/ws"
|
if (USE_REMOTE_BACKEND) return 'wss://' + 'discord.filefighter.de/ws'
|
||||||
return "ws://" + "localhost:9160/ws"
|
return 'ws://' + 'localhost:9160/ws'
|
||||||
}
|
}
|
||||||
const WEBSOCKET_URL = getWebsocketUrl();
|
const WEBSOCKET_URL = getWebsocketUrl()
|
||||||
|
|
||||||
const USER_COOKIE_NAME = "jitsi-rooms-user";
|
const USER_COOKIE_NAME = 'jitsi-rooms-user'
|
||||||
|
|
||||||
export { JITSI_DOMAIN, WEBSOCKET_URL, USER_COOKIE_NAME };
|
export { JITSI_DOMAIN, WEBSOCKET_URL, USER_COOKIE_NAME }
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
function getCookie(cname: string) {
|
function getCookie(cname: string) {
|
||||||
let name = cname + "=";
|
let name = cname + '='
|
||||||
let decodedCookie = decodeURIComponent(document.cookie);
|
let decodedCookie = decodeURIComponent(document.cookie)
|
||||||
let ca = decodedCookie.split(";");
|
let ca = decodedCookie.split(';')
|
||||||
for (let i = 0; i < ca.length; i++) {
|
for (let i = 0; i < ca.length; i++) {
|
||||||
let c = ca[i];
|
let c = ca[i]
|
||||||
while (c.charAt(0) == " ") {
|
while (c.charAt(0) == ' ') {
|
||||||
c = c.substring(1);
|
c = c.substring(1)
|
||||||
}
|
}
|
||||||
if (c.indexOf(name) == 0) {
|
if (c.indexOf(name) == 0) {
|
||||||
return c.substring(name.length, c.length);
|
return c.substring(name.length, c.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCookie(cname: string, cvalue: string, exdays = 30) {
|
function setCookie(cname: string, cvalue: string, exdays = 30) {
|
||||||
const d = new Date();
|
const d = new Date()
|
||||||
d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000);
|
d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000)
|
||||||
let expires = "expires=" + d.toUTCString();
|
let expires = 'expires=' + d.toUTCString()
|
||||||
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
|
document.cookie = cname + '=' + cvalue + ';' + expires + ';path=/'
|
||||||
}
|
}
|
||||||
|
|
||||||
export { getCookie, setCookie };
|
export { getCookie, setCookie }
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
export interface ConferenceData {
|
export interface ConferenceData {
|
||||||
roomName: string; // the room name of the conference
|
roomName: string // the room name of the conference
|
||||||
id: string; // the id of the local participant
|
id: string // the id of the local participant
|
||||||
displayName: string; // the display name of the local participant
|
displayName: string // the display name of the local participant
|
||||||
avatarURL: string; // the avatar URL of the local participant
|
avatarURL: string // the avatar URL of the local participant
|
||||||
breakoutRoom: boolean; // whether the current room is a breakout room
|
breakoutRoom: boolean // whether the current room is a breakout room
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DisplayNameChangeEvent {
|
export interface DisplayNameChangeEvent {
|
||||||
id: string; // the id of the participant that changed their display name
|
id: string // the id of the participant that changed their display name
|
||||||
displayname: string; // the new display name (WTF why is capilization different)
|
displayname: string // the new display name (WTF why is capilization different)
|
||||||
}
|
}
|
||||||
|
|
||||||
function videoConferenceJoinedListener(
|
function videoConferenceJoinedListener(
|
||||||
setConferenceData: (newData: ConferenceData) => void,
|
setConferenceData: (newData: ConferenceData) => void,
|
||||||
videoConferenceJoinedEvent: ConferenceData
|
videoConferenceJoinedEvent: ConferenceData
|
||||||
) {
|
) {
|
||||||
setConferenceData(videoConferenceJoinedEvent);
|
setConferenceData(videoConferenceJoinedEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayNameChangeListenerWrapper(
|
function displayNameChangeListenerWrapper(
|
||||||
setDisplayNameChangedEvent: (newData: DisplayNameChangeEvent) => void,
|
setDisplayNameChangedEvent: (newData: DisplayNameChangeEvent) => void,
|
||||||
displayNameChangeEvent: DisplayNameChangeEvent
|
displayNameChangeEvent: DisplayNameChangeEvent
|
||||||
) {
|
) {
|
||||||
setDisplayNameChangedEvent(displayNameChangeEvent);
|
setDisplayNameChangedEvent(displayNameChangeEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayNameChangeListener(
|
function displayNameChangeListener(
|
||||||
|
@ -30,20 +30,16 @@ function displayNameChangeListener(
|
||||||
setConferenceData: (newData: ConferenceData) => void,
|
setConferenceData: (newData: ConferenceData) => void,
|
||||||
displayNameChangeEvent: DisplayNameChangeEvent
|
displayNameChangeEvent: DisplayNameChangeEvent
|
||||||
) {
|
) {
|
||||||
console.log(
|
console.log('[Rooms] displayNameChangeListener', displayNameChangeEvent, conferenceData)
|
||||||
"[Rooms] displayNameChangeListener",
|
|
||||||
displayNameChangeEvent,
|
|
||||||
conferenceData
|
|
||||||
);
|
|
||||||
if (conferenceData && conferenceData.id == displayNameChangeEvent.id)
|
if (conferenceData && conferenceData.id == displayNameChangeEvent.id)
|
||||||
setConferenceData({
|
setConferenceData({
|
||||||
...conferenceData,
|
...conferenceData,
|
||||||
displayName: displayNameChangeEvent.displayname,
|
displayName: displayNameChangeEvent.displayname,
|
||||||
} as ConferenceData);
|
} as ConferenceData)
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
videoConferenceJoinedListener,
|
videoConferenceJoinedListener,
|
||||||
displayNameChangeListenerWrapper,
|
displayNameChangeListenerWrapper,
|
||||||
displayNameChangeListener,
|
displayNameChangeListener,
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
function getHslColor(i: number) {
|
function getHslColor(i: number) {
|
||||||
return "hsl(" + i % 360 + ',' +
|
return 'hsl(' + (i % 360) + ',' + '70%,' + '72%)'
|
||||||
'70%,' +
|
|
||||||
'72%)'
|
|
||||||
}
|
}
|
||||||
function hashCode(str: string) { // java String#hashCode
|
function hashCode(str: string) {
|
||||||
var hash = 0;
|
// java String#hashCode
|
||||||
|
var hash = 0
|
||||||
for (var i = 0; i < str.length; i++) {
|
for (var i = 0; i < str.length; i++) {
|
||||||
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
hash = str.charCodeAt(i) + ((hash << 5) - hash)
|
||||||
}
|
}
|
||||||
return hash;
|
return hash
|
||||||
}
|
}
|
||||||
|
|
||||||
// function intToRGB(i: number) {
|
// function intToRGB(i: number) {
|
||||||
|
@ -22,8 +21,6 @@ function hashCode(str: string) { // java String#hashCode
|
||||||
function getColorForUserName(userName: string) {
|
function getColorForUserName(userName: string) {
|
||||||
const hash = hashCode(userName)
|
const hash = hashCode(userName)
|
||||||
return getHslColor(hash)
|
return getHslColor(hash)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { getColorForUserName }
|
export { getColorForUserName }
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
export interface RoomData {
|
export interface RoomData {
|
||||||
roomName: string;
|
roomName: string
|
||||||
participants: Participant[];
|
participants: Participant[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Participant {
|
export interface Participant {
|
||||||
avatarURL: string;
|
avatarURL: string
|
||||||
displayName: string;
|
displayName: string
|
||||||
jid: string;
|
jid: string
|
||||||
email: string;
|
email: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface User {
|
export interface User {
|
||||||
uuid: string,
|
uuid: string
|
||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UsersData {
|
export interface UsersData {
|
||||||
roomsData: RoomData[];
|
roomsData: RoomData[]
|
||||||
usersWithOutRoom: User[];
|
usersWithOutRoom: User[]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +1,43 @@
|
||||||
.chat-input{
|
.chat-input {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat{
|
.chat {
|
||||||
background-color: #181c25;
|
background-color: #181c25;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 0.5em 0;
|
padding: 0.5em 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 -3px;
|
margin: 0 -3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-sender{
|
.chat-sender {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
/* color: #213547; */
|
/* color: #213547; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-input-form{
|
.chat-input-form {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-messages {
|
||||||
.chat-messages{
|
max-height: 220px;
|
||||||
max-height: 220px;
|
overflow-y: scroll;
|
||||||
overflow-y: scroll;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
}
|
}
|
||||||
.chat-bubble{
|
.chat-bubble {
|
||||||
background-color: #2b2a33;
|
background-color: #2b2a33;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
margin-bottom: 7px;
|
margin-bottom: 7px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 3px 4px ;
|
padding: 3px 4px;
|
||||||
|
|
||||||
|
white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
|
||||||
white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
|
white-space: -pre-wrap; /* Opera 4-6 */
|
||||||
white-space: -pre-wrap; /* Opera 4-6 */
|
white-space: -o-pre-wrap; /* Opera 7 */
|
||||||
white-space: -o-pre-wrap; /* Opera 7 */
|
white-space: pre-wrap; /* css-3 */
|
||||||
white-space: pre-wrap; /* css-3 */
|
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
white-space: -webkit-pre-wrap; /* Newer versions of Chrome/Safari*/
|
||||||
white-space: -webkit-pre-wrap; /* Newer versions of Chrome/Safari*/
|
word-break: break-all;
|
||||||
word-break: break-all;
|
white-space: normal;
|
||||||
white-space: normal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
import { useState } from "react";
|
import { useState } from 'react'
|
||||||
import { FormEventHandler } from "react";
|
import { FormEventHandler } from 'react'
|
||||||
import useAllChat from "../../hooks/useAllChat";
|
import useAllChat from '../../hooks/useAllChat'
|
||||||
import "./Chat.css"
|
import './Chat.css'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
import { faPaperPlane } from "@fortawesome/free-regular-svg-icons";
|
import { faPaperPlane } from '@fortawesome/free-regular-svg-icons'
|
||||||
import { getColorForUserName } from "../../background/style/colorednames";
|
import { getColorForUserName } from '../../background/style/colorednames'
|
||||||
interface Props {
|
interface Props {
|
||||||
sendMessage: Function
|
sendMessage: Function
|
||||||
}
|
}
|
||||||
|
|
||||||
function Chat({ sendMessage }: Props) {
|
function Chat({ sendMessage }: Props) {
|
||||||
const [chatInput, setChatInput] = useState("")
|
const [chatInput, setChatInput] = useState('')
|
||||||
const { chatMesages } = useAllChat()
|
const { chatMesages } = useAllChat()
|
||||||
|
|
||||||
const onInput: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
const onInput: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
||||||
setChatInput(event.target.value);
|
setChatInput(event.target.value)
|
||||||
event.preventDefault();
|
event.preventDefault()
|
||||||
};
|
}
|
||||||
|
|
||||||
const onSubmit: FormEventHandler<HTMLFormElement> = (event) => {
|
const onSubmit: FormEventHandler<HTMLFormElement> = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault()
|
||||||
sendMessage(JSON.stringify({ content: chatInput }));
|
sendMessage(JSON.stringify({ content: chatInput }))
|
||||||
setChatInput("")
|
setChatInput('')
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -30,15 +30,20 @@ function Chat({ sendMessage }: Props) {
|
||||||
{chatMesages
|
{chatMesages
|
||||||
.slice()
|
.slice()
|
||||||
.reverse() // reverse because of css, don't aks me
|
.reverse() // reverse because of css, don't aks me
|
||||||
.map(message => {
|
.map((message) => {
|
||||||
const nameStyle = {
|
const nameStyle = {
|
||||||
color: getColorForUserName(message.sender.name)
|
color: getColorForUserName(message.sender.name),
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="chat-bubble" key={message.uuid}> <span className="chat-sender" style={nameStyle}>{message.sender.name} <br /> </span> {message.content} </div>
|
<div className="chat-bubble" key={message.uuid}>
|
||||||
);
|
{' '}
|
||||||
})
|
<span className="chat-sender" style={nameStyle}>
|
||||||
}
|
{message.sender.name} <br />{' '}
|
||||||
|
</span>{' '}
|
||||||
|
{message.content}{' '}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
<form className="chat-input-form" onSubmit={onSubmit}>
|
<form className="chat-input-form" onSubmit={onSubmit}>
|
||||||
<input
|
<input
|
||||||
|
@ -48,10 +53,12 @@ function Chat({ sendMessage }: Props) {
|
||||||
value={chatInput}
|
value={chatInput}
|
||||||
onChange={onInput}
|
onChange={onInput}
|
||||||
/>
|
/>
|
||||||
<button type="submit"><FontAwesomeIcon icon={faPaperPlane} /></button>
|
<button type="submit">
|
||||||
|
<FontAwesomeIcon icon={faPaperPlane} />
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Chat
|
export default Chat
|
||||||
|
|
|
@ -1,61 +1,56 @@
|
||||||
import { JitsiMeeting } from "@jitsi/react-sdk";
|
import { JitsiMeeting } from '@jitsi/react-sdk'
|
||||||
import { JITSI_DOMAIN } from "../../background/constants";
|
import { JITSI_DOMAIN } from '../../background/constants'
|
||||||
import { UserInfo } from "./types";
|
import { UserInfo } from './types'
|
||||||
import curry from "just-curry-it";
|
import curry from 'just-curry-it'
|
||||||
import {
|
import {
|
||||||
ConferenceData,
|
ConferenceData,
|
||||||
displayNameChangeListener,
|
displayNameChangeListener,
|
||||||
displayNameChangeListenerWrapper,
|
displayNameChangeListenerWrapper,
|
||||||
videoConferenceJoinedListener,
|
videoConferenceJoinedListener,
|
||||||
} from "../../background/jitsi/eventListeners";
|
} from '../../background/jitsi/eventListeners'
|
||||||
import useJitsiEventCapture from "../../hooks/useJitsiEventCapture";
|
import useJitsiEventCapture from '../../hooks/useJitsiEventCapture'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
roomName: string;
|
roomName: string
|
||||||
userInfo: UserInfo;
|
userInfo: UserInfo
|
||||||
conferenceData: ConferenceData | undefined;
|
conferenceData: ConferenceData | undefined
|
||||||
setConferenceData: (newData: ConferenceData) => void;
|
setConferenceData: (newData: ConferenceData) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
function JitsiEntrypoint({
|
function JitsiEntrypoint({ roomName, userInfo, conferenceData, setConferenceData }: Props) {
|
||||||
roomName,
|
const { setDisplayNameChangeEvent } = useJitsiEventCapture(
|
||||||
userInfo,
|
curry(displayNameChangeListener)(conferenceData)(setConferenceData)
|
||||||
conferenceData,
|
)
|
||||||
setConferenceData,
|
|
||||||
}: Props) {
|
|
||||||
const { setDisplayNameChangeEvent } = useJitsiEventCapture(
|
|
||||||
curry(displayNameChangeListener)(conferenceData)(setConferenceData)
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<JitsiMeeting
|
<JitsiMeeting
|
||||||
domain={JITSI_DOMAIN}
|
domain={JITSI_DOMAIN}
|
||||||
roomName={roomName}
|
roomName={roomName}
|
||||||
configOverwrite={{
|
configOverwrite={{
|
||||||
startWithAudioMuted: true,
|
startWithAudioMuted: true,
|
||||||
disableModeratorIndicator: true,
|
disableModeratorIndicator: true,
|
||||||
startScreenSharing: true,
|
startScreenSharing: true,
|
||||||
enableEmailInStats: false,
|
enableEmailInStats: false,
|
||||||
prejoinConfig: { enabled: false },
|
prejoinConfig: { enabled: false },
|
||||||
}}
|
}}
|
||||||
interfaceConfigOverwrite={{}}
|
interfaceConfigOverwrite={{}}
|
||||||
userInfo={userInfo}
|
userInfo={userInfo}
|
||||||
onApiReady={(externalApi) => {
|
onApiReady={(externalApi) => {
|
||||||
externalApi.addEventListener(
|
externalApi.addEventListener(
|
||||||
"videoConferenceJoined",
|
'videoConferenceJoined',
|
||||||
curry(videoConferenceJoinedListener)(setConferenceData)
|
curry(videoConferenceJoinedListener)(setConferenceData)
|
||||||
);
|
)
|
||||||
externalApi.addEventListener(
|
externalApi.addEventListener(
|
||||||
"displayNameChange",
|
'displayNameChange',
|
||||||
curry(displayNameChangeListenerWrapper)(setDisplayNameChangeEvent)
|
curry(displayNameChangeListenerWrapper)(setDisplayNameChangeEvent)
|
||||||
);
|
)
|
||||||
}}
|
}}
|
||||||
getIFrameRef={(iframeRef) => {
|
getIFrameRef={(iframeRef) => {
|
||||||
iframeRef.style.height = "100%";
|
iframeRef.style.height = '100%'
|
||||||
iframeRef.style.width = "100%";
|
iframeRef.style.width = '100%'
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default JitsiEntrypoint;
|
export default JitsiEntrypoint
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export interface UserInfo {
|
export interface UserInfo {
|
||||||
displayName: string;
|
displayName: string
|
||||||
email: string;
|
email: string
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
import { useCallback, useState } from "react";
|
import { ConferenceData } from '../../background/jitsi/eventListeners'
|
||||||
import { ConferenceData } from "../../background/jitsi/eventListeners";
|
import useMeetingStarted from '../../hooks/useMeetingStarted'
|
||||||
import useMeetingStarted from "../../hooks/useMeetingStarted";
|
import { useRoomName } from '../../hooks/useRoomName'
|
||||||
import { useRoomName } from "../../hooks/useRoomName";
|
import JitsiEntrypoint from '../jitsi/JitsiEntrypoint'
|
||||||
import JitsiEntrypoint from "../jitsi/JitsiEntrypoint";
|
import { UserInfo } from '../jitsi/types'
|
||||||
import { UserInfo } from "../jitsi/types";
|
import MeetingNameInput from './MeetingNameInput'
|
||||||
import MeetingNameInput from "./MeetingNameInput";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
conferenceData: ConferenceData | undefined;
|
conferenceData: ConferenceData | undefined
|
||||||
setConferenceData: (newData: ConferenceData) => void;
|
setConferenceData: (newData: ConferenceData) => void
|
||||||
userInfo: UserInfo;
|
userInfo: UserInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
function Meeting({ conferenceData, setConferenceData, userInfo }: Props) {
|
function Meeting({ conferenceData, setConferenceData, userInfo }: Props) {
|
||||||
|
const [meetingStarted] = useMeetingStarted()
|
||||||
const [meetingStarted, setMeetingStarted] = useMeetingStarted()
|
|
||||||
const { roomName } = useRoomName()
|
const { roomName } = useRoomName()
|
||||||
|
|
||||||
if (meetingStarted) {
|
if (meetingStarted) {
|
||||||
|
@ -25,15 +23,10 @@ function Meeting({ conferenceData, setConferenceData, userInfo }: Props) {
|
||||||
userInfo={userInfo}
|
userInfo={userInfo}
|
||||||
setConferenceData={setConferenceData}
|
setConferenceData={setConferenceData}
|
||||||
/>
|
/>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return <MeetingNameInput roomName={roomName} currentUser={userInfo.displayName} />
|
||||||
<MeetingNameInput
|
|
||||||
roomName={roomName}
|
|
||||||
currentUser={userInfo.displayName}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Meeting;
|
export default Meeting
|
||||||
|
|
|
@ -1,41 +1,33 @@
|
||||||
import { FormEventHandler } from "react";
|
import { FormEventHandler } from 'react'
|
||||||
import useMeetingStarted from "../../hooks/useMeetingStarted";
|
import useMeetingStarted from '../../hooks/useMeetingStarted'
|
||||||
import { useRoomName } from "../../hooks/useRoomName";
|
import { useRoomName } from '../../hooks/useRoomName'
|
||||||
import "./MeetingNameInput.css";
|
import './MeetingNameInput.css'
|
||||||
|
|
||||||
function MeetingNameInput(props: {
|
|
||||||
roomName: string; currentUser: string;
|
|
||||||
}) {
|
|
||||||
|
|
||||||
|
function MeetingNameInput(props: { roomName: string; currentUser: string }) {
|
||||||
const { roomName, updateRoomName, updateAndSubmitRoomName, submitRoomName } = useRoomName()
|
const { roomName, updateRoomName, updateAndSubmitRoomName, submitRoomName } = useRoomName()
|
||||||
const [_, setMeetingStarted] = useMeetingStarted()
|
const [_, setMeetingStarted] = useMeetingStarted()
|
||||||
|
|
||||||
const onInput: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
const onInput: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
||||||
updateRoomName(event.target.value);
|
updateRoomName(event.target.value)
|
||||||
event.preventDefault();
|
event.preventDefault()
|
||||||
};
|
}
|
||||||
|
|
||||||
const onSubmit: FormEventHandler<HTMLFormElement> = (event) => {
|
const onSubmit: FormEventHandler<HTMLFormElement> = (event) => {
|
||||||
submitRoomName()
|
submitRoomName()
|
||||||
setMeetingStarted(true)
|
setMeetingStarted(true)
|
||||||
event.preventDefault();
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("[Rooms] MeetingName input comp");
|
console.log('[Rooms] MeetingName input comp')
|
||||||
return (
|
return (
|
||||||
<div className="meeting-name-input">
|
<div className="meeting-name-input">
|
||||||
<h1>Greetings {props.currentUser}</h1>
|
<h1>Greetings {props.currentUser}</h1>
|
||||||
<form onSubmit={onSubmit}>
|
<form onSubmit={onSubmit}>
|
||||||
<input
|
<input placeholder="Roomname" type="text" value={roomName} onChange={onInput} />
|
||||||
placeholder="Roomname"
|
|
||||||
type="text"
|
|
||||||
value={roomName}
|
|
||||||
onChange={onInput}
|
|
||||||
/>
|
|
||||||
<button type="submit">Enter the adventure</button>
|
<button type="submit">Enter the adventure</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MeetingNameInput;
|
export default MeetingNameInput
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
import SidebarHeader from "./SidebarHeader";
|
import SidebarHeader from './SidebarHeader'
|
||||||
import useSidebarVisibility from "./useSidebarVisibility";
|
import useSidebarVisibility from './useSidebarVisibility'
|
||||||
import "./Sidebar.css";
|
import './Sidebar.css'
|
||||||
import { UsersData } from "../../background/types/roomData";
|
import { UsersData } from '../../background/types/roomData'
|
||||||
import useMeetingStarted from "../../hooks/useMeetingStarted";
|
import useMeetingStarted from '../../hooks/useMeetingStarted'
|
||||||
import { useRoomName } from "../../hooks/useRoomName";
|
import { useRoomName } from '../../hooks/useRoomName'
|
||||||
import Chat from "../chat/Chat";
|
import Chat from '../chat/Chat'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
usersData: UsersData;
|
usersData: UsersData
|
||||||
sendMessage: Function
|
sendMessage: Function
|
||||||
}
|
}
|
||||||
|
|
||||||
function Sidebar(props: Props) {
|
function Sidebar(props: Props) {
|
||||||
const { sidebarVisibility, toggleSidebarVisibility, sidebarToggleText } =
|
const { sidebarVisibility, toggleSidebarVisibility, sidebarToggleText } = useSidebarVisibility()
|
||||||
useSidebarVisibility();
|
|
||||||
const [_, setMeetingStarted] = useMeetingStarted()
|
const [_, setMeetingStarted] = useMeetingStarted()
|
||||||
const { updateAndSubmitRoomName: updateAndSubmitRoomName } = useRoomName();
|
const { updateAndSubmitRoomName: updateAndSubmitRoomName } = useRoomName()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`sidebar sidebar-${sidebarVisibility}`}>
|
<div className={`sidebar sidebar-${sidebarVisibility}`}>
|
||||||
|
@ -25,10 +24,13 @@ function Sidebar(props: Props) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h3>
|
<h3>
|
||||||
<a href="#" onClick={() => {
|
<a
|
||||||
updateAndSubmitRoomName(roomData.roomName)
|
href="#"
|
||||||
setMeetingStarted(true)
|
onClick={() => {
|
||||||
}}>
|
updateAndSubmitRoomName(roomData.roomName)
|
||||||
|
setMeetingStarted(true)
|
||||||
|
}}
|
||||||
|
>
|
||||||
{roomData.roomName}
|
{roomData.roomName}
|
||||||
</a>
|
</a>
|
||||||
</h3>
|
</h3>
|
||||||
|
@ -36,7 +38,7 @@ function Sidebar(props: Props) {
|
||||||
<div key={participant.jid}> {participant.displayName} </div>
|
<div key={participant.jid}> {participant.displayName} </div>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -46,11 +48,13 @@ function Sidebar(props: Props) {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="sidebar-footer">
|
<div className="sidebar-footer">
|
||||||
{sidebarVisibility === "full" && <Chat sendMessage={props.sendMessage} />}
|
{sidebarVisibility === 'full' && <Chat sendMessage={props.sendMessage} />}
|
||||||
<button className="sidebar-toggle" onClick={toggleSidebarVisibility}>{sidebarToggleText}</button>
|
<button className="sidebar-toggle" onClick={toggleSidebarVisibility}>
|
||||||
|
{sidebarToggleText}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Sidebar;
|
export default Sidebar
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { sidebarVisibilityOptions } from "./useSidebarVisibility";
|
import { sidebarVisibilityOptions } from './useSidebarVisibility'
|
||||||
|
|
||||||
interface props {
|
interface props {
|
||||||
sidebarVisibility: sidebarVisibilityOptions;
|
sidebarVisibility: sidebarVisibilityOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarHeader({ sidebarVisibility }: props) {
|
function SidebarHeader({ sidebarVisibility }: props) {
|
||||||
if (sidebarVisibility == "full") {
|
if (sidebarVisibility == 'full') {
|
||||||
return <h2>hi there :)</h2>;
|
return <h2>hi there :)</h2>
|
||||||
} else if (sidebarVisibility == "small") {
|
} else if (sidebarVisibility == 'small') {
|
||||||
return <h2>hi</h2>;
|
return <h2>hi</h2>
|
||||||
}
|
}
|
||||||
return <></>;
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SidebarHeader;
|
export default SidebarHeader
|
||||||
|
|
|
@ -1,28 +1,27 @@
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from 'react'
|
||||||
|
|
||||||
export type sidebarVisibilityOptions = "full" | "small" | "hidden";
|
export type sidebarVisibilityOptions = 'full' | 'small' | 'hidden'
|
||||||
|
|
||||||
function useSidebarVisibility() {
|
function useSidebarVisibility() {
|
||||||
const [sidebarVisibility, setSideBarVisibility] =
|
const [sidebarVisibility, setSideBarVisibility] = useState<sidebarVisibilityOptions>('full')
|
||||||
useState<sidebarVisibilityOptions>("full");
|
|
||||||
|
|
||||||
const sidebarToggleText = getSidebarToggleText(sidebarVisibility);
|
const sidebarToggleText = getSidebarToggleText(sidebarVisibility)
|
||||||
|
|
||||||
const toggleSidebarVisibility = useCallback(() => {
|
const toggleSidebarVisibility = useCallback(() => {
|
||||||
if (sidebarVisibility === "full") {
|
if (sidebarVisibility === 'full') {
|
||||||
setSideBarVisibility("small");
|
setSideBarVisibility('small')
|
||||||
} else if (sidebarVisibility === "small") {
|
} else if (sidebarVisibility === 'small') {
|
||||||
setSideBarVisibility("hidden");
|
setSideBarVisibility('hidden')
|
||||||
} else if (sidebarVisibility === "hidden") {
|
} else if (sidebarVisibility === 'hidden') {
|
||||||
setSideBarVisibility("full");
|
setSideBarVisibility('full')
|
||||||
}
|
}
|
||||||
}, [setSideBarVisibility, sidebarVisibility, sidebarToggleText]);
|
}, [setSideBarVisibility, sidebarVisibility, sidebarToggleText])
|
||||||
|
|
||||||
return { sidebarVisibility, toggleSidebarVisibility, sidebarToggleText };
|
return { sidebarVisibility, toggleSidebarVisibility, sidebarToggleText }
|
||||||
}
|
}
|
||||||
const getSidebarToggleText = (sidebarVisibility: sidebarVisibilityOptions) => {
|
const getSidebarToggleText = (sidebarVisibility: sidebarVisibilityOptions) => {
|
||||||
if (sidebarVisibility === "full") return "<-";
|
if (sidebarVisibility === 'full') return '<-'
|
||||||
if (sidebarVisibility === "small") return "<-";
|
if (sidebarVisibility === 'small') return '<-'
|
||||||
if (sidebarVisibility === "hidden") return "->";
|
if (sidebarVisibility === 'hidden') return '->'
|
||||||
};
|
}
|
||||||
export default useSidebarVisibility;
|
export default useSidebarVisibility
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { atom, useAtom } from "jotai";
|
import { atom, useAtom } from 'jotai'
|
||||||
import { atomWithReducer, useReducerAtom } from 'jotai/utils'
|
import { atomWithReducer, useReducerAtom } from 'jotai/utils'
|
||||||
import { User } from "../background/types/roomData";
|
import { User } from '../background/types/roomData'
|
||||||
|
|
||||||
interface ChatMessage {
|
interface ChatMessage {
|
||||||
content: string
|
content: string
|
||||||
|
@ -9,7 +9,9 @@ interface ChatMessage {
|
||||||
timestamp: number
|
timestamp: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export const allChatMessagesAtom = atomWithReducer([], (list: ChatMessage[], item: ChatMessage) => list.concat(item))
|
export const allChatMessagesAtom = atomWithReducer([], (list: ChatMessage[], item: ChatMessage) =>
|
||||||
|
list.concat(item)
|
||||||
|
)
|
||||||
|
|
||||||
const useAllChat = () => {
|
const useAllChat = () => {
|
||||||
const [chatMessages, addChatMessage] = useAtom(allChatMessagesAtom)
|
const [chatMessages, addChatMessage] = useAtom(allChatMessagesAtom)
|
||||||
|
@ -17,5 +19,3 @@ const useAllChat = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useAllChat
|
export default useAllChat
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,28 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from 'react'
|
||||||
import { UserInfo } from "../components/jitsi/types";
|
import { UserInfo } from '../components/jitsi/types'
|
||||||
import useAllChat from "./useAllChat";
|
import useAllChat from './useAllChat'
|
||||||
import useRoomData from "./useRoomData";
|
import useRoomData from './useRoomData'
|
||||||
import useWebSocketConnection from "./useWebSocketConnection";
|
import useWebSocketConnection from './useWebSocketConnection'
|
||||||
|
|
||||||
function useBackendData(userInfo: UserInfo) {
|
function useBackendData(userInfo: UserInfo) {
|
||||||
console.log("[Rooms] useBackendData");
|
console.log('[Rooms] useBackendData')
|
||||||
const { onMessage, sendMessage, disconnect } =
|
|
||||||
useWebSocketConnection(userInfo);
|
|
||||||
|
|
||||||
const { roomData, setRoomData } = useRoomData();
|
const { onMessage, sendMessage, disconnect } = useWebSocketConnection(userInfo)
|
||||||
|
const { roomData, setRoomData } = useRoomData()
|
||||||
const { chatMesages, addChatMessage } = useAllChat()
|
const { addChatMessage } = useAllChat()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onMessage((messageString) => {
|
onMessage((messageString) => {
|
||||||
console.log("[Rooms] message from ws", messageString);
|
console.log('[Rooms] message from ws', messageString)
|
||||||
const messageObject = JSON.parse(messageString);
|
const messageObject = JSON.parse(messageString)
|
||||||
|
|
||||||
!!messageObject.roomsData && setRoomData(messageObject);
|
!!messageObject.roomsData && setRoomData(messageObject)
|
||||||
!!messageObject.content && addChatMessage(messageObject);
|
!!messageObject.content && addChatMessage(messageObject)
|
||||||
return disconnect;
|
return disconnect
|
||||||
});
|
})
|
||||||
}, [onMessage, setRoomData, disconnect]);
|
}, [onMessage, setRoomData, disconnect])
|
||||||
|
|
||||||
return { roomData, sendMessage };
|
return { roomData, sendMessage }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useBackendData;
|
export default useBackendData
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
import { useState } from "react";
|
import { useState } from 'react'
|
||||||
import { ConferenceData } from "../background/jitsi/eventListeners";
|
import { ConferenceData } from '../background/jitsi/eventListeners'
|
||||||
import { UserInfo } from "../components/jitsi/types";
|
import { UserInfo } from '../components/jitsi/types'
|
||||||
|
|
||||||
function useConferenceData(
|
function useConferenceData(
|
||||||
sendMessage: (message: string) => void,
|
sendMessage: (message: string) => void,
|
||||||
setUserInfo: (newData: UserInfo) => void
|
setUserInfo: (newData: UserInfo) => void
|
||||||
) {
|
) {
|
||||||
const [conferenceData, setConferenceDataLocal] = useState<ConferenceData>();
|
const [conferenceData, setConferenceDataLocal] = useState<ConferenceData>()
|
||||||
|
|
||||||
const setConferenceData = (newData: ConferenceData) => {
|
const setConferenceData = (newData: ConferenceData) => {
|
||||||
console.log("[Rooms] set conferenceData", conferenceData);
|
console.log('[Rooms] set conferenceData', conferenceData)
|
||||||
if (conferenceData?.roomName !== newData.roomName) {
|
if (conferenceData?.roomName !== newData.roomName) {
|
||||||
// We joined a meeting
|
// We joined a meeting
|
||||||
sendMessage(JSON.stringify({ roomName: newData.roomName }));
|
sendMessage(JSON.stringify({ roomName: newData.roomName }))
|
||||||
}
|
}
|
||||||
if (conferenceData?.displayName !== newData.displayName) {
|
if (conferenceData?.displayName !== newData.displayName) {
|
||||||
// We updated the username
|
// We updated the username
|
||||||
sendMessage(JSON.stringify({ displayName: newData.displayName }));
|
sendMessage(JSON.stringify({ displayName: newData.displayName }))
|
||||||
}
|
}
|
||||||
setConferenceDataLocal(newData);
|
setConferenceDataLocal(newData)
|
||||||
setUserInfo({ displayName: newData.displayName, email: "" });
|
setUserInfo({ displayName: newData.displayName, email: '' })
|
||||||
};
|
}
|
||||||
|
|
||||||
return { conferenceData, setConferenceData };
|
return { conferenceData, setConferenceData }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useConferenceData;
|
export default useConferenceData
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
import { useCallback, useEffect, useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import { DisplayNameChangeEvent } from "../background/jitsi/eventListeners";
|
import { DisplayNameChangeEvent } from '../background/jitsi/eventListeners'
|
||||||
|
|
||||||
function useJitsiEventCapture(displayNameChangeHandler: Function) {
|
function useJitsiEventCapture(displayNameChangeHandler: Function) {
|
||||||
const [displayNameChangeEvent, setDisplayNameChangeEventLocal] =
|
const [displayNameChangeEvent, setDisplayNameChangeEventLocal] =
|
||||||
useState<DisplayNameChangeEvent>();
|
useState<DisplayNameChangeEvent>()
|
||||||
|
|
||||||
const setDisplayNameChangeEvent = useCallback(
|
const setDisplayNameChangeEvent = useCallback(
|
||||||
(newValue: DisplayNameChangeEvent) => {
|
(newValue: DisplayNameChangeEvent) => {
|
||||||
console.log("[Rooms] newValue", newValue, displayNameChangeEvent);
|
console.log('[Rooms] newValue', newValue, displayNameChangeEvent)
|
||||||
if (displayNameChangeEvent != newValue) {
|
if (displayNameChangeEvent != newValue) {
|
||||||
setDisplayNameChangeEventLocal(newValue);
|
setDisplayNameChangeEventLocal(newValue)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[setDisplayNameChangeEventLocal]
|
[setDisplayNameChangeEventLocal]
|
||||||
);
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("[Rooms] displayNameChangeHandler", displayNameChangeEvent);
|
console.log('[Rooms] displayNameChangeHandler', displayNameChangeEvent)
|
||||||
displayNameChangeHandler &&
|
displayNameChangeHandler &&
|
||||||
displayNameChangeEvent &&
|
displayNameChangeEvent &&
|
||||||
displayNameChangeHandler(displayNameChangeEvent);
|
displayNameChangeHandler(displayNameChangeEvent)
|
||||||
}, [displayNameChangeEvent]);
|
}, [displayNameChangeEvent])
|
||||||
|
|
||||||
return { setDisplayNameChangeEvent };
|
return { setDisplayNameChangeEvent }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useJitsiEventCapture;
|
export default useJitsiEventCapture
|
||||||
|
|
|
@ -1,34 +1,32 @@
|
||||||
import { useState } from "react";
|
import { useState } from 'react'
|
||||||
import { USER_COOKIE_NAME } from "../background/constants";
|
import { USER_COOKIE_NAME } from '../background/constants'
|
||||||
import { getCookie, setCookie } from "../background/cookies";
|
import { getCookie, setCookie } from '../background/cookies'
|
||||||
import { UserInfo } from "../components/jitsi/types";
|
import { UserInfo } from '../components/jitsi/types'
|
||||||
|
|
||||||
function useLocalUser() {
|
function useLocalUser() {
|
||||||
const [userInfo, setUserInfoLocal] = useState<UserInfo>(() =>
|
const [userInfo, setUserInfoLocal] = useState<UserInfo>(() => getUserInfoFromCookie())
|
||||||
getUserInfoFromCookie()
|
|
||||||
);
|
|
||||||
|
|
||||||
const setUserInfo = (newData: UserInfo) => {
|
const setUserInfo = (newData: UserInfo) => {
|
||||||
storeUserInfoInCookie(newData);
|
storeUserInfoInCookie(newData)
|
||||||
setUserInfoLocal(newData);
|
setUserInfoLocal(newData)
|
||||||
};
|
}
|
||||||
|
|
||||||
return { userInfo, setUserInfo };
|
return { userInfo, setUserInfo }
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUserInfoFromCookie(): UserInfo {
|
function getUserInfoFromCookie(): UserInfo {
|
||||||
let cookie = getCookie(USER_COOKIE_NAME);
|
let cookie = getCookie(USER_COOKIE_NAME)
|
||||||
console.log("[Rooms] getUserNameFromCookie", cookie);
|
console.log('[Rooms] getUserNameFromCookie', cookie)
|
||||||
if (cookie) return JSON.parse(cookie);
|
if (cookie) return JSON.parse(cookie)
|
||||||
return {
|
return {
|
||||||
displayName: "Unknown traveller",
|
displayName: 'Unknown traveller',
|
||||||
email: "",
|
email: '',
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function storeUserInfoInCookie(userInfo: UserInfo) {
|
function storeUserInfoInCookie(userInfo: UserInfo) {
|
||||||
console.log("[Rooms] storeUserInfoInCookie", userInfo);
|
console.log('[Rooms] storeUserInfoInCookie', userInfo)
|
||||||
setCookie(USER_COOKIE_NAME, JSON.stringify(userInfo));
|
setCookie(USER_COOKIE_NAME, JSON.stringify(userInfo))
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useLocalUser;
|
export default useLocalUser
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { atom, useAtom } from "jotai";
|
import { atom, useAtom } from 'jotai'
|
||||||
|
|
||||||
const meetingStarted = atom(false)
|
const meetingStarted = atom(false)
|
||||||
|
|
||||||
const useMeetingStarted = () => useAtom(meetingStarted);
|
const useMeetingStarted = () => useAtom(meetingStarted)
|
||||||
|
|
||||||
export default useMeetingStarted
|
export default useMeetingStarted
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { useState } from "react";
|
import { useState } from 'react'
|
||||||
import { UsersData } from "../background/types/roomData";
|
import { UsersData } from '../background/types/roomData'
|
||||||
|
|
||||||
function useRoomData() {
|
function useRoomData() {
|
||||||
const [roomData, setRoomData] = useState<UsersData>();
|
const [roomData, setRoomData] = useState<UsersData>()
|
||||||
|
|
||||||
return { roomData, setRoomData };
|
return { roomData, setRoomData }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useRoomData;
|
export default useRoomData
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { atom, useAtom } from "jotai";
|
import { atom, useAtom } from 'jotai'
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from 'react'
|
||||||
|
|
||||||
const roomNameAtom = atom(getRoomNameFromUrl())
|
const roomNameAtom = atom(getRoomNameFromUrl())
|
||||||
|
|
||||||
|
@ -8,48 +8,46 @@ function useRoomName() {
|
||||||
|
|
||||||
const updateRoomName = useCallback(
|
const updateRoomName = useCallback(
|
||||||
(newName: string) => {
|
(newName: string) => {
|
||||||
setRoomName(newName);
|
setRoomName(newName)
|
||||||
console.log("[Rooms] update room name", newName);
|
console.log('[Rooms] update room name', newName)
|
||||||
},
|
},
|
||||||
[setRoomName]
|
[setRoomName]
|
||||||
);
|
)
|
||||||
|
|
||||||
const updateAndSubmitRoomName = useCallback(
|
const updateAndSubmitRoomName = useCallback(
|
||||||
(newName: string) => {
|
(newName: string) => {
|
||||||
setRoomName(newName);
|
setRoomName(newName)
|
||||||
setRoomNameInUrl(newName);
|
setRoomNameInUrl(newName)
|
||||||
setRoomNameInTitle(newName);
|
setRoomNameInTitle(newName)
|
||||||
console.log("[Rooms] update and submit room name", newName);
|
console.log('[Rooms] update and submit room name', newName)
|
||||||
},
|
},
|
||||||
[setRoomName]
|
[setRoomName]
|
||||||
)
|
)
|
||||||
|
|
||||||
const submitRoomName = useCallback(() => {
|
const submitRoomName = useCallback(() => {
|
||||||
setRoomNameInUrl(roomName);
|
setRoomNameInUrl(roomName)
|
||||||
setRoomNameInTitle(roomName);
|
setRoomNameInTitle(roomName)
|
||||||
}, [roomName]);
|
}, [roomName])
|
||||||
|
|
||||||
return { roomName, updateRoomName, updateAndSubmitRoomName, submitRoomName };
|
return { roomName, updateRoomName, updateAndSubmitRoomName, submitRoomName }
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRoomNameFromUrl(): string {
|
function getRoomNameFromUrl(): string {
|
||||||
const pathName = location.pathname;
|
const pathName = location.pathname
|
||||||
const roomName = pathName
|
const roomName = pathName.substring(pathName.lastIndexOf('/'), pathName.length).replace('/', '')
|
||||||
.substring(pathName.lastIndexOf("/"), pathName.length)
|
console.log('[Rooms] Got roomName from url', roomName)
|
||||||
.replace("/", "");
|
setRoomNameInTitle(roomName)
|
||||||
console.log("[Rooms] Got roomName from url", roomName);
|
return roomName
|
||||||
setRoomNameInTitle(roomName);
|
|
||||||
return roomName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setRoomNameInUrl(roomName: string) {
|
function setRoomNameInUrl(roomName: string) {
|
||||||
history.pushState(history.state, "_", roomName);
|
history.pushState(history.state, '_', roomName)
|
||||||
}
|
}
|
||||||
|
|
||||||
function setRoomNameInTitle(roomName: string) {
|
function setRoomNameInTitle(roomName: string) {
|
||||||
if (!!roomName) {
|
if (!!roomName) {
|
||||||
document.title = roomName;
|
document.title = roomName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { useRoomName };
|
export { useRoomName }
|
||||||
|
|
|
@ -1,50 +1,44 @@
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from 'react'
|
||||||
import { WEBSOCKET_URL } from "../background/constants";
|
import { WEBSOCKET_URL } from '../background/constants'
|
||||||
import { UserInfo } from "../components/jitsi/types";
|
import { UserInfo } from '../components/jitsi/types'
|
||||||
|
|
||||||
const createWebSocketConnection = (userInfo: UserInfo) => {
|
const createWebSocketConnection = (userInfo: UserInfo) => {
|
||||||
const webSocket = new WebSocket(WEBSOCKET_URL);
|
const webSocket = new WebSocket(WEBSOCKET_URL)
|
||||||
console.log("[Rooms] createWebSocketConnection");
|
console.log('[Rooms] createWebSocketConnection')
|
||||||
webSocket.addEventListener("open", (_: Event) =>
|
webSocket.addEventListener('open', (_: Event) => webSocket.send(JSON.stringify(userInfo)))
|
||||||
webSocket.send(JSON.stringify(userInfo))
|
|
||||||
);
|
|
||||||
|
|
||||||
return webSocket;
|
return webSocket
|
||||||
};
|
}
|
||||||
|
|
||||||
function useWebSocketConnection(userInfo: UserInfo) {
|
function useWebSocketConnection(userInfo: UserInfo) {
|
||||||
console.log("[Rooms] useWebSocketConnection");
|
console.log('[Rooms] useWebSocketConnection')
|
||||||
|
|
||||||
const [webSocketConnection] = useState<WebSocket>(() =>
|
const [webSocketConnection] = useState<WebSocket>(() => createWebSocketConnection(userInfo))
|
||||||
createWebSocketConnection(userInfo)
|
|
||||||
);
|
|
||||||
|
|
||||||
const sendMessage = useCallback(
|
const sendMessage = useCallback(
|
||||||
(message: string) => {
|
(message: string) => {
|
||||||
//if the socket's open, send a message:
|
//if the socket's open, send a message:
|
||||||
if (webSocketConnection.readyState === WebSocket.OPEN) {
|
if (webSocketConnection.readyState === WebSocket.OPEN) {
|
||||||
console.log("[Rooms] sending to ws", message);
|
console.log('[Rooms] sending to ws', message)
|
||||||
webSocketConnection.send(message);
|
webSocketConnection.send(message)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[webSocketConnection]
|
[webSocketConnection]
|
||||||
);
|
)
|
||||||
|
|
||||||
const onMessage = useCallback(
|
const onMessage = useCallback(
|
||||||
(messageHandler: (messageHandler: string) => void) => {
|
(messageHandler: (messageHandler: string) => void) => {
|
||||||
const wsMessageHandler = (ev: MessageEvent<any>) => {
|
const wsMessageHandler = (ev: MessageEvent<any>) => {
|
||||||
messageHandler(ev.data);
|
messageHandler(ev.data)
|
||||||
};
|
}
|
||||||
webSocketConnection.addEventListener("message", wsMessageHandler);
|
webSocketConnection.addEventListener('message', wsMessageHandler)
|
||||||
},
|
},
|
||||||
[webSocketConnection]
|
[webSocketConnection]
|
||||||
);
|
)
|
||||||
|
|
||||||
const disconnect = useCallback(webSocketConnection.close, [
|
const disconnect = useCallback(webSocketConnection.close, [webSocketConnection])
|
||||||
webSocketConnection,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return { onMessage, sendMessage, disconnect };
|
return { onMessage, sendMessage, disconnect }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useWebSocketConnection;
|
export default useWebSocketConnection
|
||||||
|
|
|
@ -78,7 +78,6 @@ button:focus-visible {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
input {
|
input {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
margin: 0.3em;
|
margin: 0.3em;
|
||||||
|
@ -88,7 +87,7 @@ input {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
font-family: "Oxygen", sans-serif;
|
font-family: 'Oxygen', sans-serif;
|
||||||
transition: top 0.1s ease-in-out;
|
transition: top 0.1s ease-in-out;
|
||||||
background-color: #2b2a33;
|
background-color: #2b2a33;
|
||||||
border-color: #646cff;
|
border-color: #646cff;
|
||||||
|
|
|
@ -9,5 +9,5 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||||
<Provider>
|
<Provider>
|
||||||
<App />
|
<App />
|
||||||
</Provider>
|
</Provider>
|
||||||
</React.StrictMode>,
|
</React.StrictMode>
|
||||||
)
|
)
|
||||||
|
|
1683
frontend/yarn.lock
1683
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue