add prettier and reformat project
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
c86873fc28
commit
7d17cfa28c
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"useTabs": false,
|
||||
"tabWidth": 4,
|
||||
"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:
|
||||
|
||||
|
||||
```sh
|
||||
yarn run dev
|
||||
```
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
|
||||
yarn build
|
||||
scp -r dist/* ffs:/home/ffsys/apps/static/jitsi-rooms
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>FF Jitsi Rooms</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>FF Jitsi Rooms</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,28 +1,34 @@
|
|||
{
|
||||
"name": "jitsi-roomsv2",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.4.0",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@jitsi/react-sdk": "^1.3.0",
|
||||
"jotai": "^2.0.3",
|
||||
"just-curry-it": "^5.3.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/react-dom": "^18.0.9",
|
||||
"@vitejs/plugin-react": "^3.0.0",
|
||||
"typescript": "^4.9.3",
|
||||
"vite": "^4.0.0"
|
||||
}
|
||||
"name": "jitsi-roomsv2",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.4.0",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@jitsi/react-sdk": "^1.3.0",
|
||||
"jotai": "^2.0.3",
|
||||
"just-curry-it": "^5.3.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/react-dom": "^18.0.9",
|
||||
"@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",
|
||||
"vite": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.App {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
@ -1,39 +1,34 @@
|
|||
import { Provider } from "jotai";
|
||||
import { useState } from "react";
|
||||
import "./App.css";
|
||||
import Meeting from "./components/meeting/Meeting";
|
||||
import Sidebar from "./components/sidebar/Sidebar";
|
||||
import useBackendData from "./hooks/useBackendData";
|
||||
import useConferenceData from "./hooks/useConferenceData";
|
||||
import useLocalUser from "./hooks/useLocalUser";
|
||||
import { useRoomName } from "./hooks/useRoomName";
|
||||
import { Provider } from 'jotai'
|
||||
import { useState } from 'react'
|
||||
import './App.css'
|
||||
import Meeting from './components/meeting/Meeting'
|
||||
import Sidebar from './components/sidebar/Sidebar'
|
||||
import useBackendData from './hooks/useBackendData'
|
||||
import useConferenceData from './hooks/useConferenceData'
|
||||
import useLocalUser from './hooks/useLocalUser'
|
||||
import { useRoomName } from './hooks/useRoomName'
|
||||
|
||||
function App() {
|
||||
const { userInfo, setUserInfo } = useLocalUser();
|
||||
const { roomData, sendMessage } = useBackendData(userInfo);
|
||||
const { conferenceData, setConferenceData } = useConferenceData(
|
||||
sendMessage,
|
||||
setUserInfo
|
||||
);
|
||||
const [meetingStarted, setMeetingStarted] = useState(false);
|
||||
const { userInfo, setUserInfo } = useLocalUser()
|
||||
const { roomData, sendMessage } = useBackendData(userInfo)
|
||||
const { conferenceData, setConferenceData } = useConferenceData(sendMessage, setUserInfo)
|
||||
const [meetingStarted, setMeetingStarted] = useState(false)
|
||||
|
||||
console.log(roomData);
|
||||
console.log(roomData)
|
||||
|
||||
if (roomData && userInfo) {
|
||||
return (
|
||||
<div className="App">
|
||||
<Sidebar usersData={roomData}
|
||||
sendMessage={sendMessage}
|
||||
/>
|
||||
<Meeting
|
||||
conferenceData={conferenceData}
|
||||
setConferenceData={setConferenceData}
|
||||
userInfo={userInfo}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <h2>🌀 Loading...</h2>;
|
||||
if (roomData && userInfo) {
|
||||
return (
|
||||
<div className="App">
|
||||
<Sidebar usersData={roomData} sendMessage={sendMessage} />
|
||||
<Meeting
|
||||
conferenceData={conferenceData}
|
||||
setConferenceData={setConferenceData}
|
||||
userInfo={userInfo}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return <h2>🌀 Loading...</h2>
|
||||
}
|
||||
|
||||
export default App;
|
||||
export default App
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
const ISPROD = window.location.protocol == "https:";
|
||||
const JITSI_DOMAIN = "thisisnotajitsi.filefighter.de";
|
||||
const USE_REMOTE_BACKEND = true;
|
||||
const ISPROD = window.location.protocol == 'https:'
|
||||
const JITSI_DOMAIN = 'thisisnotajitsi.filefighter.de'
|
||||
const USE_REMOTE_BACKEND = true
|
||||
const getWebsocketUrl = () => {
|
||||
if (ISPROD) return "wss://" + window.location.host + "/ws"
|
||||
if (USE_REMOTE_BACKEND) return "wss://" + "discord.filefighter.de/ws"
|
||||
return "ws://" + "localhost:9160/ws"
|
||||
if (ISPROD) return 'wss://' + window.location.host + '/ws'
|
||||
if (USE_REMOTE_BACKEND) return 'wss://' + 'discord.filefighter.de/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) {
|
||||
let name = cname + "=";
|
||||
let decodedCookie = decodeURIComponent(document.cookie);
|
||||
let ca = decodedCookie.split(";");
|
||||
for (let i = 0; i < ca.length; i++) {
|
||||
let c = ca[i];
|
||||
while (c.charAt(0) == " ") {
|
||||
c = c.substring(1);
|
||||
let name = cname + '='
|
||||
let decodedCookie = decodeURIComponent(document.cookie)
|
||||
let ca = decodedCookie.split(';')
|
||||
for (let i = 0; i < ca.length; i++) {
|
||||
let c = ca[i]
|
||||
while (c.charAt(0) == ' ') {
|
||||
c = c.substring(1)
|
||||
}
|
||||
if (c.indexOf(name) == 0) {
|
||||
return c.substring(name.length, c.length)
|
||||
}
|
||||
}
|
||||
if (c.indexOf(name) == 0) {
|
||||
return c.substring(name.length, c.length);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
return ''
|
||||
}
|
||||
|
||||
function setCookie(cname: string, cvalue: string, exdays = 30) {
|
||||
const d = new Date();
|
||||
d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000);
|
||||
let expires = "expires=" + d.toUTCString();
|
||||
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
|
||||
const d = new Date()
|
||||
d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000)
|
||||
let expires = 'expires=' + d.toUTCString()
|
||||
document.cookie = cname + '=' + cvalue + ';' + expires + ';path=/'
|
||||
}
|
||||
|
||||
export { getCookie, setCookie };
|
||||
export { getCookie, setCookie }
|
||||
|
|
|
@ -1,49 +1,45 @@
|
|||
export interface ConferenceData {
|
||||
roomName: string; // the room name of the conference
|
||||
id: string; // the id of the local participant
|
||||
displayName: string; // the display name of the local participant
|
||||
avatarURL: string; // the avatar URL of the local participant
|
||||
breakoutRoom: boolean; // whether the current room is a breakout room
|
||||
roomName: string // the room name of the conference
|
||||
id: string // the id of the local participant
|
||||
displayName: string // the display name of the local participant
|
||||
avatarURL: string // the avatar URL of the local participant
|
||||
breakoutRoom: boolean // whether the current room is a breakout room
|
||||
}
|
||||
|
||||
export interface DisplayNameChangeEvent {
|
||||
id: string; // the id of the participant that changed their display name
|
||||
displayname: string; // the new display name (WTF why is capilization different)
|
||||
id: string // the id of the participant that changed their display name
|
||||
displayname: string // the new display name (WTF why is capilization different)
|
||||
}
|
||||
|
||||
function videoConferenceJoinedListener(
|
||||
setConferenceData: (newData: ConferenceData) => void,
|
||||
videoConferenceJoinedEvent: ConferenceData
|
||||
setConferenceData: (newData: ConferenceData) => void,
|
||||
videoConferenceJoinedEvent: ConferenceData
|
||||
) {
|
||||
setConferenceData(videoConferenceJoinedEvent);
|
||||
setConferenceData(videoConferenceJoinedEvent)
|
||||
}
|
||||
|
||||
function displayNameChangeListenerWrapper(
|
||||
setDisplayNameChangedEvent: (newData: DisplayNameChangeEvent) => void,
|
||||
displayNameChangeEvent: DisplayNameChangeEvent
|
||||
setDisplayNameChangedEvent: (newData: DisplayNameChangeEvent) => void,
|
||||
displayNameChangeEvent: DisplayNameChangeEvent
|
||||
) {
|
||||
setDisplayNameChangedEvent(displayNameChangeEvent);
|
||||
setDisplayNameChangedEvent(displayNameChangeEvent)
|
||||
}
|
||||
|
||||
function displayNameChangeListener(
|
||||
conferenceData: ConferenceData | undefined,
|
||||
setConferenceData: (newData: ConferenceData) => void,
|
||||
displayNameChangeEvent: DisplayNameChangeEvent
|
||||
conferenceData: ConferenceData | undefined,
|
||||
setConferenceData: (newData: ConferenceData) => void,
|
||||
displayNameChangeEvent: DisplayNameChangeEvent
|
||||
) {
|
||||
console.log(
|
||||
"[Rooms] displayNameChangeListener",
|
||||
displayNameChangeEvent,
|
||||
conferenceData
|
||||
);
|
||||
if (conferenceData && conferenceData.id == displayNameChangeEvent.id)
|
||||
setConferenceData({
|
||||
...conferenceData,
|
||||
displayName: displayNameChangeEvent.displayname,
|
||||
} as ConferenceData);
|
||||
console.log('[Rooms] displayNameChangeListener', displayNameChangeEvent, conferenceData)
|
||||
if (conferenceData && conferenceData.id == displayNameChangeEvent.id)
|
||||
setConferenceData({
|
||||
...conferenceData,
|
||||
displayName: displayNameChangeEvent.displayname,
|
||||
} as ConferenceData)
|
||||
}
|
||||
|
||||
export {
|
||||
videoConferenceJoinedListener,
|
||||
displayNameChangeListenerWrapper,
|
||||
displayNameChangeListener,
|
||||
};
|
||||
videoConferenceJoinedListener,
|
||||
displayNameChangeListenerWrapper,
|
||||
displayNameChangeListener,
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
function getHslColor(i: number) {
|
||||
return "hsl(" + i % 360 + ',' +
|
||||
'70%,' +
|
||||
'72%)'
|
||||
return 'hsl(' + (i % 360) + ',' + '70%,' + '72%)'
|
||||
}
|
||||
function hashCode(str: string) { // java String#hashCode
|
||||
var hash = 0;
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
||||
}
|
||||
return hash;
|
||||
function hashCode(str: string) {
|
||||
// java String#hashCode
|
||||
var hash = 0
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
hash = str.charCodeAt(i) + ((hash << 5) - hash)
|
||||
}
|
||||
return hash
|
||||
}
|
||||
|
||||
// function intToRGB(i: number) {
|
||||
|
@ -20,10 +19,8 @@ function hashCode(str: string) { // java String#hashCode
|
|||
// }
|
||||
|
||||
function getColorForUserName(userName: string) {
|
||||
const hash = hashCode(userName)
|
||||
return getHslColor(hash)
|
||||
|
||||
|
||||
const hash = hashCode(userName)
|
||||
return getHslColor(hash)
|
||||
}
|
||||
|
||||
export { getColorForUserName }
|
||||
export { getColorForUserName }
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
export interface RoomData {
|
||||
roomName: string;
|
||||
participants: Participant[];
|
||||
roomName: string
|
||||
participants: Participant[]
|
||||
}
|
||||
|
||||
export interface Participant {
|
||||
avatarURL: string;
|
||||
displayName: string;
|
||||
jid: string;
|
||||
email: string;
|
||||
avatarURL: string
|
||||
displayName: string
|
||||
jid: string
|
||||
email: string
|
||||
}
|
||||
|
||||
export interface User {
|
||||
uuid: string,
|
||||
name: string
|
||||
uuid: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface UsersData {
|
||||
roomsData: RoomData[];
|
||||
usersWithOutRoom: User[];
|
||||
roomsData: RoomData[]
|
||||
usersWithOutRoom: User[]
|
||||
}
|
||||
|
|
|
@ -1,46 +1,43 @@
|
|||
.chat-input{
|
||||
min-width: 0;
|
||||
.chat-input {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.chat{
|
||||
background-color: #181c25;
|
||||
border-radius: 8px;
|
||||
padding: 0.5em 0;
|
||||
width: 100%;
|
||||
margin: 0 -3px;
|
||||
.chat {
|
||||
background-color: #181c25;
|
||||
border-radius: 8px;
|
||||
padding: 0.5em 0;
|
||||
width: 100%;
|
||||
margin: 0 -3px;
|
||||
}
|
||||
|
||||
.chat-sender{
|
||||
font-size: 0.9em;
|
||||
/* color: #213547; */
|
||||
.chat-sender {
|
||||
font-size: 0.9em;
|
||||
/* color: #213547; */
|
||||
}
|
||||
|
||||
.chat-input-form{
|
||||
display: flex;
|
||||
.chat-input-form {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
|
||||
.chat-messages{
|
||||
max-height: 220px;
|
||||
overflow-y: scroll;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
.chat-messages {
|
||||
max-height: 220px;
|
||||
overflow-y: scroll;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
.chat-bubble{
|
||||
background-color: #2b2a33;
|
||||
overflow-wrap: break-word;
|
||||
margin-bottom: 7px;
|
||||
border-radius: 8px;
|
||||
padding: 3px 4px ;
|
||||
.chat-bubble {
|
||||
background-color: #2b2a33;
|
||||
overflow-wrap: break-word;
|
||||
margin-bottom: 7px;
|
||||
border-radius: 8px;
|
||||
padding: 3px 4px;
|
||||
|
||||
|
||||
white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
white-space: pre-wrap; /* css-3 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
white-space: -webkit-pre-wrap; /* Newer versions of Chrome/Safari*/
|
||||
word-break: break-all;
|
||||
white-space: normal;
|
||||
white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
white-space: pre-wrap; /* css-3 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
white-space: -webkit-pre-wrap; /* Newer versions of Chrome/Safari*/
|
||||
word-break: break-all;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,57 +1,64 @@
|
|||
import { useState } from "react";
|
||||
import { FormEventHandler } from "react";
|
||||
import useAllChat from "../../hooks/useAllChat";
|
||||
import "./Chat.css"
|
||||
import { useState } from 'react'
|
||||
import { FormEventHandler } from 'react'
|
||||
import useAllChat from '../../hooks/useAllChat'
|
||||
import './Chat.css'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faPaperPlane } from "@fortawesome/free-regular-svg-icons";
|
||||
import { getColorForUserName } from "../../background/style/colorednames";
|
||||
import { faPaperPlane } from '@fortawesome/free-regular-svg-icons'
|
||||
import { getColorForUserName } from '../../background/style/colorednames'
|
||||
interface Props {
|
||||
sendMessage: Function
|
||||
sendMessage: Function
|
||||
}
|
||||
|
||||
function Chat({ sendMessage }: Props) {
|
||||
const [chatInput, setChatInput] = useState("")
|
||||
const { chatMesages } = useAllChat()
|
||||
const [chatInput, setChatInput] = useState('')
|
||||
const { chatMesages } = useAllChat()
|
||||
|
||||
const onInput: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
||||
setChatInput(event.target.value);
|
||||
event.preventDefault();
|
||||
};
|
||||
const onInput: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
||||
setChatInput(event.target.value)
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
const onSubmit: FormEventHandler<HTMLFormElement> = (event) => {
|
||||
event.preventDefault();
|
||||
sendMessage(JSON.stringify({ content: chatInput }));
|
||||
setChatInput("")
|
||||
}
|
||||
const onSubmit: FormEventHandler<HTMLFormElement> = (event) => {
|
||||
event.preventDefault()
|
||||
sendMessage(JSON.stringify({ content: chatInput }))
|
||||
setChatInput('')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="chat">
|
||||
<div className="chat-messages">
|
||||
{chatMesages
|
||||
.slice()
|
||||
.reverse() // reverse because of css, don't aks me
|
||||
.map(message => {
|
||||
const nameStyle = {
|
||||
color: getColorForUserName(message.sender.name)
|
||||
}
|
||||
return (
|
||||
<div className="chat-bubble" key={message.uuid}> <span className="chat-sender" style={nameStyle}>{message.sender.name} <br /> </span> {message.content} </div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
<form className="chat-input-form" onSubmit={onSubmit}>
|
||||
<input
|
||||
className="chat-input"
|
||||
placeholder="Say something funny :D"
|
||||
type="text"
|
||||
value={chatInput}
|
||||
onChange={onInput}
|
||||
/>
|
||||
<button type="submit"><FontAwesomeIcon icon={faPaperPlane} /></button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className="chat">
|
||||
<div className="chat-messages">
|
||||
{chatMesages
|
||||
.slice()
|
||||
.reverse() // reverse because of css, don't aks me
|
||||
.map((message) => {
|
||||
const nameStyle = {
|
||||
color: getColorForUserName(message.sender.name),
|
||||
}
|
||||
return (
|
||||
<div className="chat-bubble" key={message.uuid}>
|
||||
{' '}
|
||||
<span className="chat-sender" style={nameStyle}>
|
||||
{message.sender.name} <br />{' '}
|
||||
</span>{' '}
|
||||
{message.content}{' '}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<form className="chat-input-form" onSubmit={onSubmit}>
|
||||
<input
|
||||
className="chat-input"
|
||||
placeholder="Say something funny :D"
|
||||
type="text"
|
||||
value={chatInput}
|
||||
onChange={onInput}
|
||||
/>
|
||||
<button type="submit">
|
||||
<FontAwesomeIcon icon={faPaperPlane} />
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Chat
|
||||
|
|
|
@ -1,31 +1,26 @@
|
|||
import { JitsiMeeting } from "@jitsi/react-sdk";
|
||||
import { JITSI_DOMAIN } from "../../background/constants";
|
||||
import { UserInfo } from "./types";
|
||||
import curry from "just-curry-it";
|
||||
import { JitsiMeeting } from '@jitsi/react-sdk'
|
||||
import { JITSI_DOMAIN } from '../../background/constants'
|
||||
import { UserInfo } from './types'
|
||||
import curry from 'just-curry-it'
|
||||
import {
|
||||
ConferenceData,
|
||||
displayNameChangeListener,
|
||||
displayNameChangeListenerWrapper,
|
||||
videoConferenceJoinedListener,
|
||||
} from "../../background/jitsi/eventListeners";
|
||||
import useJitsiEventCapture from "../../hooks/useJitsiEventCapture";
|
||||
} from '../../background/jitsi/eventListeners'
|
||||
import useJitsiEventCapture from '../../hooks/useJitsiEventCapture'
|
||||
|
||||
interface Props {
|
||||
roomName: string;
|
||||
userInfo: UserInfo;
|
||||
conferenceData: ConferenceData | undefined;
|
||||
setConferenceData: (newData: ConferenceData) => void;
|
||||
roomName: string
|
||||
userInfo: UserInfo
|
||||
conferenceData: ConferenceData | undefined
|
||||
setConferenceData: (newData: ConferenceData) => void
|
||||
}
|
||||
|
||||
function JitsiEntrypoint({
|
||||
roomName,
|
||||
userInfo,
|
||||
conferenceData,
|
||||
setConferenceData,
|
||||
}: Props) {
|
||||
function JitsiEntrypoint({ roomName, userInfo, conferenceData, setConferenceData }: Props) {
|
||||
const { setDisplayNameChangeEvent } = useJitsiEventCapture(
|
||||
curry(displayNameChangeListener)(conferenceData)(setConferenceData)
|
||||
);
|
||||
)
|
||||
|
||||
return (
|
||||
<JitsiMeeting
|
||||
|
@ -42,20 +37,20 @@ function JitsiEntrypoint({
|
|||
userInfo={userInfo}
|
||||
onApiReady={(externalApi) => {
|
||||
externalApi.addEventListener(
|
||||
"videoConferenceJoined",
|
||||
'videoConferenceJoined',
|
||||
curry(videoConferenceJoinedListener)(setConferenceData)
|
||||
);
|
||||
)
|
||||
externalApi.addEventListener(
|
||||
"displayNameChange",
|
||||
'displayNameChange',
|
||||
curry(displayNameChangeListenerWrapper)(setDisplayNameChangeEvent)
|
||||
);
|
||||
)
|
||||
}}
|
||||
getIFrameRef={(iframeRef) => {
|
||||
iframeRef.style.height = "100%";
|
||||
iframeRef.style.width = "100%";
|
||||
iframeRef.style.height = '100%'
|
||||
iframeRef.style.width = '100%'
|
||||
}}
|
||||
/>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
export default JitsiEntrypoint;
|
||||
export default JitsiEntrypoint
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export interface UserInfo {
|
||||
displayName: string;
|
||||
email: string;
|
||||
displayName: string
|
||||
email: string
|
||||
}
|
||||
|
|
|
@ -1,39 +1,33 @@
|
|||
import { useCallback, useState } from "react";
|
||||
import { ConferenceData } from "../../background/jitsi/eventListeners";
|
||||
import useMeetingStarted from "../../hooks/useMeetingStarted";
|
||||
import { useRoomName } from "../../hooks/useRoomName";
|
||||
import JitsiEntrypoint from "../jitsi/JitsiEntrypoint";
|
||||
import { UserInfo } from "../jitsi/types";
|
||||
import MeetingNameInput from "./MeetingNameInput";
|
||||
import { useCallback, useState } from 'react'
|
||||
import { ConferenceData } from '../../background/jitsi/eventListeners'
|
||||
import useMeetingStarted from '../../hooks/useMeetingStarted'
|
||||
import { useRoomName } from '../../hooks/useRoomName'
|
||||
import JitsiEntrypoint from '../jitsi/JitsiEntrypoint'
|
||||
import { UserInfo } from '../jitsi/types'
|
||||
import MeetingNameInput from './MeetingNameInput'
|
||||
|
||||
interface Props {
|
||||
conferenceData: ConferenceData | undefined;
|
||||
setConferenceData: (newData: ConferenceData) => void;
|
||||
userInfo: UserInfo;
|
||||
conferenceData: ConferenceData | undefined
|
||||
setConferenceData: (newData: ConferenceData) => void
|
||||
userInfo: UserInfo
|
||||
}
|
||||
|
||||
function Meeting({ conferenceData, setConferenceData, userInfo }: Props) {
|
||||
const [meetingStarted, setMeetingStarted] = useMeetingStarted()
|
||||
const { roomName } = useRoomName()
|
||||
|
||||
const [meetingStarted, setMeetingStarted] = useMeetingStarted()
|
||||
const { roomName } = useRoomName()
|
||||
if (meetingStarted) {
|
||||
return (
|
||||
<JitsiEntrypoint
|
||||
conferenceData={conferenceData}
|
||||
roomName={roomName}
|
||||
userInfo={userInfo}
|
||||
setConferenceData={setConferenceData}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
if (meetingStarted) {
|
||||
return (
|
||||
<JitsiEntrypoint
|
||||
conferenceData={conferenceData}
|
||||
roomName={roomName}
|
||||
userInfo={userInfo}
|
||||
setConferenceData={setConferenceData}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<MeetingNameInput
|
||||
roomName={roomName}
|
||||
currentUser={userInfo.displayName}
|
||||
/>
|
||||
);
|
||||
return <MeetingNameInput roomName={roomName} currentUser={userInfo.displayName} />
|
||||
}
|
||||
|
||||
export default Meeting;
|
||||
export default Meeting
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.meeting-name-input {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
@ -1,41 +1,33 @@
|
|||
import { FormEventHandler } from "react";
|
||||
import useMeetingStarted from "../../hooks/useMeetingStarted";
|
||||
import { useRoomName } from "../../hooks/useRoomName";
|
||||
import "./MeetingNameInput.css";
|
||||
import { FormEventHandler } from 'react'
|
||||
import useMeetingStarted from '../../hooks/useMeetingStarted'
|
||||
import { useRoomName } from '../../hooks/useRoomName'
|
||||
import './MeetingNameInput.css'
|
||||
|
||||
function MeetingNameInput(props: {
|
||||
roomName: string; currentUser: string;
|
||||
}) {
|
||||
function MeetingNameInput(props: { roomName: string; currentUser: string }) {
|
||||
const { roomName, updateRoomName, updateAndSubmitRoomName, submitRoomName } = useRoomName()
|
||||
const [_, setMeetingStarted] = useMeetingStarted()
|
||||
|
||||
const { roomName, updateRoomName, updateAndSubmitRoomName, submitRoomName } = useRoomName()
|
||||
const [_, setMeetingStarted] = useMeetingStarted()
|
||||
const onInput: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
||||
updateRoomName(event.target.value)
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
const onInput: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
||||
updateRoomName(event.target.value);
|
||||
event.preventDefault();
|
||||
};
|
||||
const onSubmit: FormEventHandler<HTMLFormElement> = (event) => {
|
||||
submitRoomName()
|
||||
setMeetingStarted(true)
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
const onSubmit: FormEventHandler<HTMLFormElement> = (event) => {
|
||||
submitRoomName()
|
||||
setMeetingStarted(true)
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
console.log("[Rooms] MeetingName input comp");
|
||||
return (
|
||||
<div className="meeting-name-input">
|
||||
<h1>Greetings {props.currentUser}</h1>
|
||||
<form onSubmit={onSubmit}>
|
||||
<input
|
||||
placeholder="Roomname"
|
||||
type="text"
|
||||
value={roomName}
|
||||
onChange={onInput}
|
||||
/>
|
||||
<button type="submit">Enter the adventure</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
console.log('[Rooms] MeetingName input comp')
|
||||
return (
|
||||
<div className="meeting-name-input">
|
||||
<h1>Greetings {props.currentUser}</h1>
|
||||
<form onSubmit={onSubmit}>
|
||||
<input placeholder="Roomname" type="text" value={roomName} onChange={onInput} />
|
||||
<button type="submit">Enter the adventure</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default MeetingNameInput;
|
||||
export default MeetingNameInput
|
||||
|
|
|
@ -1,39 +1,39 @@
|
|||
.sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
background-color: #121115;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
background-color: #121115;
|
||||
}
|
||||
|
||||
.sidebar h3 {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.sidebar-footer {
|
||||
margin-top: auto;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.sidebar-small {
|
||||
min-width: 60px;
|
||||
max-width: 60px;
|
||||
min-width: 60px;
|
||||
max-width: 60px;
|
||||
}
|
||||
|
||||
.sidebar-full {
|
||||
width: 220px;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.sidebar-hidden {
|
||||
width: 0;
|
||||
padding: 0;
|
||||
width: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sidebar-hidden > .sidebar-footer > .sidebar-toggle {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
|
|
|
@ -1,56 +1,60 @@
|
|||
import SidebarHeader from "./SidebarHeader";
|
||||
import useSidebarVisibility from "./useSidebarVisibility";
|
||||
import "./Sidebar.css";
|
||||
import { UsersData } from "../../background/types/roomData";
|
||||
import useMeetingStarted from "../../hooks/useMeetingStarted";
|
||||
import { useRoomName } from "../../hooks/useRoomName";
|
||||
import Chat from "../chat/Chat";
|
||||
import SidebarHeader from './SidebarHeader'
|
||||
import useSidebarVisibility from './useSidebarVisibility'
|
||||
import './Sidebar.css'
|
||||
import { UsersData } from '../../background/types/roomData'
|
||||
import useMeetingStarted from '../../hooks/useMeetingStarted'
|
||||
import { useRoomName } from '../../hooks/useRoomName'
|
||||
import Chat from '../chat/Chat'
|
||||
|
||||
interface Props {
|
||||
usersData: UsersData;
|
||||
sendMessage: Function
|
||||
usersData: UsersData
|
||||
sendMessage: Function
|
||||
}
|
||||
|
||||
function Sidebar(props: Props) {
|
||||
const { sidebarVisibility, toggleSidebarVisibility, sidebarToggleText } =
|
||||
useSidebarVisibility();
|
||||
const [_, setMeetingStarted] = useMeetingStarted()
|
||||
const { updateAndSubmitRoomName: updateAndSubmitRoomName } = useRoomName();
|
||||
const { sidebarVisibility, toggleSidebarVisibility, sidebarToggleText } = useSidebarVisibility()
|
||||
const [_, setMeetingStarted] = useMeetingStarted()
|
||||
const { updateAndSubmitRoomName: updateAndSubmitRoomName } = useRoomName()
|
||||
|
||||
return (
|
||||
<div className={`sidebar sidebar-${sidebarVisibility}`}>
|
||||
<SidebarHeader sidebarVisibility={sidebarVisibility} />
|
||||
<div className="sidebar-body">
|
||||
{props.usersData.roomsData.map((roomData) => {
|
||||
return (
|
||||
<>
|
||||
<h3>
|
||||
<a href="#" onClick={() => {
|
||||
updateAndSubmitRoomName(roomData.roomName)
|
||||
setMeetingStarted(true)
|
||||
}}>
|
||||
{roomData.roomName}
|
||||
</a>
|
||||
</h3>
|
||||
{roomData.participants.map((participant) => (
|
||||
<div key={participant.jid}> {participant.displayName} </div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div>
|
||||
<h3> No room</h3>
|
||||
{props.usersData.usersWithOutRoom.map((user) => (
|
||||
<div key={user.uuid}>{user.name}</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="sidebar-footer">
|
||||
{sidebarVisibility === "full" && <Chat sendMessage={props.sendMessage} />}
|
||||
<button className="sidebar-toggle" onClick={toggleSidebarVisibility}>{sidebarToggleText}</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className={`sidebar sidebar-${sidebarVisibility}`}>
|
||||
<SidebarHeader sidebarVisibility={sidebarVisibility} />
|
||||
<div className="sidebar-body">
|
||||
{props.usersData.roomsData.map((roomData) => {
|
||||
return (
|
||||
<>
|
||||
<h3>
|
||||
<a
|
||||
href="#"
|
||||
onClick={() => {
|
||||
updateAndSubmitRoomName(roomData.roomName)
|
||||
setMeetingStarted(true)
|
||||
}}
|
||||
>
|
||||
{roomData.roomName}
|
||||
</a>
|
||||
</h3>
|
||||
{roomData.participants.map((participant) => (
|
||||
<div key={participant.jid}> {participant.displayName} </div>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<div>
|
||||
<h3> No room</h3>
|
||||
{props.usersData.usersWithOutRoom.map((user) => (
|
||||
<div key={user.uuid}>{user.name}</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="sidebar-footer">
|
||||
{sidebarVisibility === 'full' && <Chat sendMessage={props.sendMessage} />}
|
||||
<button className="sidebar-toggle" onClick={toggleSidebarVisibility}>
|
||||
{sidebarToggleText}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Sidebar;
|
||||
export default Sidebar
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import { sidebarVisibilityOptions } from "./useSidebarVisibility";
|
||||
import { sidebarVisibilityOptions } from './useSidebarVisibility'
|
||||
|
||||
interface props {
|
||||
sidebarVisibility: sidebarVisibilityOptions;
|
||||
sidebarVisibility: sidebarVisibilityOptions
|
||||
}
|
||||
|
||||
function SidebarHeader({ sidebarVisibility }: props) {
|
||||
if (sidebarVisibility == "full") {
|
||||
return <h2>hi there :)</h2>;
|
||||
} else if (sidebarVisibility == "small") {
|
||||
return <h2>hi</h2>;
|
||||
}
|
||||
return <></>;
|
||||
if (sidebarVisibility == 'full') {
|
||||
return <h2>hi there :)</h2>
|
||||
} else if (sidebarVisibility == 'small') {
|
||||
return <h2>hi</h2>
|
||||
}
|
||||
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() {
|
||||
const [sidebarVisibility, setSideBarVisibility] =
|
||||
useState<sidebarVisibilityOptions>("full");
|
||||
const [sidebarVisibility, setSideBarVisibility] = useState<sidebarVisibilityOptions>('full')
|
||||
|
||||
const sidebarToggleText = getSidebarToggleText(sidebarVisibility);
|
||||
const sidebarToggleText = getSidebarToggleText(sidebarVisibility)
|
||||
|
||||
const toggleSidebarVisibility = useCallback(() => {
|
||||
if (sidebarVisibility === "full") {
|
||||
setSideBarVisibility("small");
|
||||
} else if (sidebarVisibility === "small") {
|
||||
setSideBarVisibility("hidden");
|
||||
} else if (sidebarVisibility === "hidden") {
|
||||
setSideBarVisibility("full");
|
||||
}
|
||||
}, [setSideBarVisibility, sidebarVisibility, sidebarToggleText]);
|
||||
const toggleSidebarVisibility = useCallback(() => {
|
||||
if (sidebarVisibility === 'full') {
|
||||
setSideBarVisibility('small')
|
||||
} else if (sidebarVisibility === 'small') {
|
||||
setSideBarVisibility('hidden')
|
||||
} else if (sidebarVisibility === 'hidden') {
|
||||
setSideBarVisibility('full')
|
||||
}
|
||||
}, [setSideBarVisibility, sidebarVisibility, sidebarToggleText])
|
||||
|
||||
return { sidebarVisibility, toggleSidebarVisibility, sidebarToggleText };
|
||||
return { sidebarVisibility, toggleSidebarVisibility, sidebarToggleText }
|
||||
}
|
||||
const getSidebarToggleText = (sidebarVisibility: sidebarVisibilityOptions) => {
|
||||
if (sidebarVisibility === "full") return "<-";
|
||||
if (sidebarVisibility === "small") return "<-";
|
||||
if (sidebarVisibility === "hidden") return "->";
|
||||
};
|
||||
export default useSidebarVisibility;
|
||||
if (sidebarVisibility === 'full') return '<-'
|
||||
if (sidebarVisibility === 'small') return '<-'
|
||||
if (sidebarVisibility === 'hidden') return '->'
|
||||
}
|
||||
export default useSidebarVisibility
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
import { atom, useAtom } from "jotai";
|
||||
import { atom, useAtom } from 'jotai'
|
||||
import { atomWithReducer, useReducerAtom } from 'jotai/utils'
|
||||
import { User } from "../background/types/roomData";
|
||||
import { User } from '../background/types/roomData'
|
||||
|
||||
interface ChatMessage {
|
||||
content: string
|
||||
sender: User
|
||||
uuid: string
|
||||
timestamp: number
|
||||
content: string
|
||||
sender: User
|
||||
uuid: string
|
||||
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 [chatMessages, addChatMessage] = useAtom(allChatMessagesAtom)
|
||||
return { chatMesages: chatMessages, addChatMessage }
|
||||
const [chatMessages, addChatMessage] = useAtom(allChatMessagesAtom)
|
||||
return { chatMesages: chatMessages, addChatMessage }
|
||||
}
|
||||
|
||||
export default useAllChat
|
||||
|
||||
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
import { useEffect } from "react";
|
||||
import { UserInfo } from "../components/jitsi/types";
|
||||
import useAllChat from "./useAllChat";
|
||||
import useRoomData from "./useRoomData";
|
||||
import useWebSocketConnection from "./useWebSocketConnection";
|
||||
import { useEffect } from 'react'
|
||||
import { UserInfo } from '../components/jitsi/types'
|
||||
import useAllChat from './useAllChat'
|
||||
import useRoomData from './useRoomData'
|
||||
import useWebSocketConnection from './useWebSocketConnection'
|
||||
|
||||
function useBackendData(userInfo: UserInfo) {
|
||||
console.log("[Rooms] useBackendData");
|
||||
const { onMessage, sendMessage, disconnect } =
|
||||
useWebSocketConnection(userInfo);
|
||||
console.log('[Rooms] useBackendData')
|
||||
const { onMessage, sendMessage, disconnect } = useWebSocketConnection(userInfo)
|
||||
|
||||
const { roomData, setRoomData } = useRoomData();
|
||||
const { roomData, setRoomData } = useRoomData()
|
||||
|
||||
const { chatMesages, addChatMessage } = useAllChat()
|
||||
const { chatMesages, addChatMessage } = useAllChat()
|
||||
|
||||
useEffect(() => {
|
||||
onMessage((messageString) => {
|
||||
console.log("[Rooms] message from ws", messageString);
|
||||
const messageObject = JSON.parse(messageString);
|
||||
useEffect(() => {
|
||||
onMessage((messageString) => {
|
||||
console.log('[Rooms] message from ws', messageString)
|
||||
const messageObject = JSON.parse(messageString)
|
||||
|
||||
!!messageObject.roomsData && setRoomData(messageObject);
|
||||
!!messageObject.content && addChatMessage(messageObject);
|
||||
return disconnect;
|
||||
});
|
||||
}, [onMessage, setRoomData, disconnect]);
|
||||
!!messageObject.roomsData && setRoomData(messageObject)
|
||||
!!messageObject.content && addChatMessage(messageObject)
|
||||
return 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 { ConferenceData } from "../background/jitsi/eventListeners";
|
||||
import { UserInfo } from "../components/jitsi/types";
|
||||
import { useState } from 'react'
|
||||
import { ConferenceData } from '../background/jitsi/eventListeners'
|
||||
import { UserInfo } from '../components/jitsi/types'
|
||||
|
||||
function useConferenceData(
|
||||
sendMessage: (message: string) => void,
|
||||
setUserInfo: (newData: UserInfo) => void
|
||||
sendMessage: (message: string) => void,
|
||||
setUserInfo: (newData: UserInfo) => void
|
||||
) {
|
||||
const [conferenceData, setConferenceDataLocal] = useState<ConferenceData>();
|
||||
const [conferenceData, setConferenceDataLocal] = useState<ConferenceData>()
|
||||
|
||||
const setConferenceData = (newData: ConferenceData) => {
|
||||
console.log("[Rooms] set conferenceData", conferenceData);
|
||||
if (conferenceData?.roomName !== newData.roomName) {
|
||||
// We joined a meeting
|
||||
sendMessage(JSON.stringify({ roomName: newData.roomName }));
|
||||
const setConferenceData = (newData: ConferenceData) => {
|
||||
console.log('[Rooms] set conferenceData', conferenceData)
|
||||
if (conferenceData?.roomName !== newData.roomName) {
|
||||
// We joined a meeting
|
||||
sendMessage(JSON.stringify({ roomName: newData.roomName }))
|
||||
}
|
||||
if (conferenceData?.displayName !== newData.displayName) {
|
||||
// We updated the username
|
||||
sendMessage(JSON.stringify({ displayName: newData.displayName }))
|
||||
}
|
||||
setConferenceDataLocal(newData)
|
||||
setUserInfo({ displayName: newData.displayName, email: '' })
|
||||
}
|
||||
if (conferenceData?.displayName !== newData.displayName) {
|
||||
// We updated the username
|
||||
sendMessage(JSON.stringify({ displayName: newData.displayName }));
|
||||
}
|
||||
setConferenceDataLocal(newData);
|
||||
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 { DisplayNameChangeEvent } from "../background/jitsi/eventListeners";
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { DisplayNameChangeEvent } from '../background/jitsi/eventListeners'
|
||||
|
||||
function useJitsiEventCapture(displayNameChangeHandler: Function) {
|
||||
const [displayNameChangeEvent, setDisplayNameChangeEventLocal] =
|
||||
useState<DisplayNameChangeEvent>();
|
||||
const [displayNameChangeEvent, setDisplayNameChangeEventLocal] =
|
||||
useState<DisplayNameChangeEvent>()
|
||||
|
||||
const setDisplayNameChangeEvent = useCallback(
|
||||
(newValue: DisplayNameChangeEvent) => {
|
||||
console.log("[Rooms] newValue", newValue, displayNameChangeEvent);
|
||||
if (displayNameChangeEvent != newValue) {
|
||||
setDisplayNameChangeEventLocal(newValue);
|
||||
}
|
||||
},
|
||||
[setDisplayNameChangeEventLocal]
|
||||
);
|
||||
const setDisplayNameChangeEvent = useCallback(
|
||||
(newValue: DisplayNameChangeEvent) => {
|
||||
console.log('[Rooms] newValue', newValue, displayNameChangeEvent)
|
||||
if (displayNameChangeEvent != newValue) {
|
||||
setDisplayNameChangeEventLocal(newValue)
|
||||
}
|
||||
},
|
||||
[setDisplayNameChangeEventLocal]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
console.log("[Rooms] displayNameChangeHandler", displayNameChangeEvent);
|
||||
displayNameChangeHandler &&
|
||||
displayNameChangeEvent &&
|
||||
displayNameChangeHandler(displayNameChangeEvent);
|
||||
}, [displayNameChangeEvent]);
|
||||
useEffect(() => {
|
||||
console.log('[Rooms] displayNameChangeHandler', displayNameChangeEvent)
|
||||
displayNameChangeHandler &&
|
||||
displayNameChangeEvent &&
|
||||
displayNameChangeHandler(displayNameChangeEvent)
|
||||
}, [displayNameChangeEvent])
|
||||
|
||||
return { setDisplayNameChangeEvent };
|
||||
return { setDisplayNameChangeEvent }
|
||||
}
|
||||
|
||||
export default useJitsiEventCapture;
|
||||
export default useJitsiEventCapture
|
||||
|
|
|
@ -1,34 +1,32 @@
|
|||
import { useState } from "react";
|
||||
import { USER_COOKIE_NAME } from "../background/constants";
|
||||
import { getCookie, setCookie } from "../background/cookies";
|
||||
import { UserInfo } from "../components/jitsi/types";
|
||||
import { useState } from 'react'
|
||||
import { USER_COOKIE_NAME } from '../background/constants'
|
||||
import { getCookie, setCookie } from '../background/cookies'
|
||||
import { UserInfo } from '../components/jitsi/types'
|
||||
|
||||
function useLocalUser() {
|
||||
const [userInfo, setUserInfoLocal] = useState<UserInfo>(() =>
|
||||
getUserInfoFromCookie()
|
||||
);
|
||||
const [userInfo, setUserInfoLocal] = useState<UserInfo>(() => getUserInfoFromCookie())
|
||||
|
||||
const setUserInfo = (newData: UserInfo) => {
|
||||
storeUserInfoInCookie(newData);
|
||||
setUserInfoLocal(newData);
|
||||
};
|
||||
const setUserInfo = (newData: UserInfo) => {
|
||||
storeUserInfoInCookie(newData)
|
||||
setUserInfoLocal(newData)
|
||||
}
|
||||
|
||||
return { userInfo, setUserInfo };
|
||||
return { userInfo, setUserInfo }
|
||||
}
|
||||
|
||||
function getUserInfoFromCookie(): UserInfo {
|
||||
let cookie = getCookie(USER_COOKIE_NAME);
|
||||
console.log("[Rooms] getUserNameFromCookie", cookie);
|
||||
if (cookie) return JSON.parse(cookie);
|
||||
return {
|
||||
displayName: "Unknown traveller",
|
||||
email: "",
|
||||
};
|
||||
let cookie = getCookie(USER_COOKIE_NAME)
|
||||
console.log('[Rooms] getUserNameFromCookie', cookie)
|
||||
if (cookie) return JSON.parse(cookie)
|
||||
return {
|
||||
displayName: 'Unknown traveller',
|
||||
email: '',
|
||||
}
|
||||
}
|
||||
|
||||
function storeUserInfoInCookie(userInfo: UserInfo) {
|
||||
console.log("[Rooms] storeUserInfoInCookie", userInfo);
|
||||
setCookie(USER_COOKIE_NAME, JSON.stringify(userInfo));
|
||||
console.log('[Rooms] storeUserInfoInCookie', 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 useMeetingStarted = () => useAtom(meetingStarted);
|
||||
const useMeetingStarted = () => useAtom(meetingStarted)
|
||||
|
||||
export default useMeetingStarted
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { useState } from "react";
|
||||
import { UsersData } from "../background/types/roomData";
|
||||
import { useState } from 'react'
|
||||
import { UsersData } from '../background/types/roomData'
|
||||
|
||||
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,55 +1,53 @@
|
|||
import { atom, useAtom } from "jotai";
|
||||
import { useCallback, useState } from "react";
|
||||
import { atom, useAtom } from 'jotai'
|
||||
import { useCallback, useState } from 'react'
|
||||
|
||||
const roomNameAtom = atom(getRoomNameFromUrl())
|
||||
|
||||
function useRoomName() {
|
||||
const [roomName, setRoomName] = useAtom(roomNameAtom)
|
||||
const [roomName, setRoomName] = useAtom(roomNameAtom)
|
||||
|
||||
const updateRoomName = useCallback(
|
||||
(newName: string) => {
|
||||
setRoomName(newName);
|
||||
console.log("[Rooms] update room name", newName);
|
||||
},
|
||||
[setRoomName]
|
||||
);
|
||||
const updateRoomName = useCallback(
|
||||
(newName: string) => {
|
||||
setRoomName(newName)
|
||||
console.log('[Rooms] update room name', newName)
|
||||
},
|
||||
[setRoomName]
|
||||
)
|
||||
|
||||
const updateAndSubmitRoomName = useCallback(
|
||||
(newName: string) => {
|
||||
setRoomName(newName);
|
||||
setRoomNameInUrl(newName);
|
||||
setRoomNameInTitle(newName);
|
||||
console.log("[Rooms] update and submit room name", newName);
|
||||
},
|
||||
[setRoomName]
|
||||
)
|
||||
const updateAndSubmitRoomName = useCallback(
|
||||
(newName: string) => {
|
||||
setRoomName(newName)
|
||||
setRoomNameInUrl(newName)
|
||||
setRoomNameInTitle(newName)
|
||||
console.log('[Rooms] update and submit room name', newName)
|
||||
},
|
||||
[setRoomName]
|
||||
)
|
||||
|
||||
const submitRoomName = useCallback(() => {
|
||||
setRoomNameInUrl(roomName);
|
||||
setRoomNameInTitle(roomName);
|
||||
}, [roomName]);
|
||||
const submitRoomName = useCallback(() => {
|
||||
setRoomNameInUrl(roomName)
|
||||
setRoomNameInTitle(roomName)
|
||||
}, [roomName])
|
||||
|
||||
return { roomName, updateRoomName, updateAndSubmitRoomName, submitRoomName };
|
||||
return { roomName, updateRoomName, updateAndSubmitRoomName, submitRoomName }
|
||||
}
|
||||
|
||||
function getRoomNameFromUrl(): string {
|
||||
const pathName = location.pathname;
|
||||
const roomName = pathName
|
||||
.substring(pathName.lastIndexOf("/"), pathName.length)
|
||||
.replace("/", "");
|
||||
console.log("[Rooms] Got roomName from url", roomName);
|
||||
setRoomNameInTitle(roomName);
|
||||
return roomName;
|
||||
const pathName = location.pathname
|
||||
const roomName = pathName.substring(pathName.lastIndexOf('/'), pathName.length).replace('/', '')
|
||||
console.log('[Rooms] Got roomName from url', roomName)
|
||||
setRoomNameInTitle(roomName)
|
||||
return roomName
|
||||
}
|
||||
|
||||
function setRoomNameInUrl(roomName: string) {
|
||||
history.pushState(history.state, "_", roomName);
|
||||
history.pushState(history.state, '_', roomName)
|
||||
}
|
||||
|
||||
function setRoomNameInTitle(roomName: string) {
|
||||
if (!!roomName) {
|
||||
document.title = roomName;
|
||||
}
|
||||
if (!!roomName) {
|
||||
document.title = roomName
|
||||
}
|
||||
}
|
||||
|
||||
export { useRoomName };
|
||||
export { useRoomName }
|
||||
|
|
|
@ -1,50 +1,44 @@
|
|||
import { useCallback, useState } from "react";
|
||||
import { WEBSOCKET_URL } from "../background/constants";
|
||||
import { UserInfo } from "../components/jitsi/types";
|
||||
import { useCallback, useState } from 'react'
|
||||
import { WEBSOCKET_URL } from '../background/constants'
|
||||
import { UserInfo } from '../components/jitsi/types'
|
||||
|
||||
const createWebSocketConnection = (userInfo: UserInfo) => {
|
||||
const webSocket = new WebSocket(WEBSOCKET_URL);
|
||||
console.log("[Rooms] createWebSocketConnection");
|
||||
webSocket.addEventListener("open", (_: Event) =>
|
||||
webSocket.send(JSON.stringify(userInfo))
|
||||
);
|
||||
const webSocket = new WebSocket(WEBSOCKET_URL)
|
||||
console.log('[Rooms] createWebSocketConnection')
|
||||
webSocket.addEventListener('open', (_: Event) => webSocket.send(JSON.stringify(userInfo)))
|
||||
|
||||
return webSocket;
|
||||
};
|
||||
|
||||
function useWebSocketConnection(userInfo: UserInfo) {
|
||||
console.log("[Rooms] useWebSocketConnection");
|
||||
|
||||
const [webSocketConnection] = useState<WebSocket>(() =>
|
||||
createWebSocketConnection(userInfo)
|
||||
);
|
||||
|
||||
const sendMessage = useCallback(
|
||||
(message: string) => {
|
||||
//if the socket's open, send a message:
|
||||
if (webSocketConnection.readyState === WebSocket.OPEN) {
|
||||
console.log("[Rooms] sending to ws", message);
|
||||
webSocketConnection.send(message);
|
||||
}
|
||||
},
|
||||
[webSocketConnection]
|
||||
);
|
||||
|
||||
const onMessage = useCallback(
|
||||
(messageHandler: (messageHandler: string) => void) => {
|
||||
const wsMessageHandler = (ev: MessageEvent<any>) => {
|
||||
messageHandler(ev.data);
|
||||
};
|
||||
webSocketConnection.addEventListener("message", wsMessageHandler);
|
||||
},
|
||||
[webSocketConnection]
|
||||
);
|
||||
|
||||
const disconnect = useCallback(webSocketConnection.close, [
|
||||
webSocketConnection,
|
||||
]);
|
||||
|
||||
return { onMessage, sendMessage, disconnect };
|
||||
return webSocket
|
||||
}
|
||||
|
||||
export default useWebSocketConnection;
|
||||
function useWebSocketConnection(userInfo: UserInfo) {
|
||||
console.log('[Rooms] useWebSocketConnection')
|
||||
|
||||
const [webSocketConnection] = useState<WebSocket>(() => createWebSocketConnection(userInfo))
|
||||
|
||||
const sendMessage = useCallback(
|
||||
(message: string) => {
|
||||
//if the socket's open, send a message:
|
||||
if (webSocketConnection.readyState === WebSocket.OPEN) {
|
||||
console.log('[Rooms] sending to ws', message)
|
||||
webSocketConnection.send(message)
|
||||
}
|
||||
},
|
||||
[webSocketConnection]
|
||||
)
|
||||
|
||||
const onMessage = useCallback(
|
||||
(messageHandler: (messageHandler: string) => void) => {
|
||||
const wsMessageHandler = (ev: MessageEvent<any>) => {
|
||||
messageHandler(ev.data)
|
||||
}
|
||||
webSocketConnection.addEventListener('message', wsMessageHandler)
|
||||
},
|
||||
[webSocketConnection]
|
||||
)
|
||||
|
||||
const disconnect = useCallback(webSocketConnection.close, [webSocketConnection])
|
||||
|
||||
return { onMessage, sendMessage, disconnect }
|
||||
}
|
||||
|
||||
export default useWebSocketConnection
|
||||
|
|
|
@ -1,96 +1,95 @@
|
|||
:root {
|
||||
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #181c25;
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #181c25;
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
overflow-y: hidden;
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
min-width: 320px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
border-radius: 8px;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.6em 1.2em;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
font-family: inherit;
|
||||
background-color: #1a1a1a;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
button:hover {
|
||||
border-color: #646cff;
|
||||
border-color: #646cff;
|
||||
}
|
||||
button:focus,
|
||||
button:focus-visible {
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
outline: 4px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
button {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
input {
|
||||
font-size: 1em;
|
||||
margin: 0.3em;
|
||||
border: 0;
|
||||
height: 2.3em;
|
||||
padding-left: 0.4em;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
font-size: 17px;
|
||||
font-family: "Oxygen", sans-serif;
|
||||
transition: top 0.1s ease-in-out;
|
||||
background-color: #2b2a33;
|
||||
border-color: #646cff;
|
||||
border-radius: 8px;
|
||||
font-size: 1em;
|
||||
margin: 0.3em;
|
||||
border: 0;
|
||||
height: 2.3em;
|
||||
padding-left: 0.4em;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
font-size: 17px;
|
||||
font-family: 'Oxygen', sans-serif;
|
||||
transition: top 0.1s ease-in-out;
|
||||
background-color: #2b2a33;
|
||||
border-color: #646cff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ import App from './App'
|
|||
import './index.css'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||
<React.StrictMode>
|
||||
<Provider>
|
||||
<App />
|
||||
</Provider>
|
||||
</React.StrictMode>,
|
||||
<React.StrictMode>
|
||||
<Provider>
|
||||
<App />
|
||||
</Provider>
|
||||
</React.StrictMode>
|
||||
)
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
|
|
|
@ -3,5 +3,5 @@ import react from '@vitejs/plugin-react'
|
|||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
plugins: [react()],
|
||||
})
|
||||
|
|
1683
frontend/yarn.lock
1683
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue