add prettier and reformat project
continuous-integration/drone/push Build is passing Details

This commit is contained in:
open-schnick 2023-04-10 23:28:28 +02:00
parent c86873fc28
commit 1aa7914289
No known key found for this signature in database
GPG Key ID: B1FA75F86D28E80E
31 changed files with 1894 additions and 576 deletions

15
frontend/.prettierrc Normal file
View File

@ -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
}

View File

@ -6,7 +6,6 @@ Using vite and react plus the jitsi react sdk for the frontend.
Use yarn:
```sh
yarn run dev
```

View File

@ -1,5 +1,4 @@
#!/usr/bin/env sh
yarn build
scp -r dist/* ffs:/home/ffsys/apps/static/jitsi-rooms

View File

@ -22,6 +22,12 @@
"@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"
}

View File

@ -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}
/>
<Sidebar usersData={roomData} sendMessage={sendMessage} />
<Meeting
conferenceData={conferenceData}
setConferenceData={setConferenceData}
userInfo={userInfo}
/>
</div>
);
)
}
return <h2>🌀 Loading...</h2>;
return <h2>🌀 Loading...</h2>
}
export default App;
export default App

View File

@ -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 }

View File

@ -1,24 +1,24 @@
function getCookie(cname: string) {
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(";");
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 c = ca[i]
while (c.charAt(0) == ' ') {
c = c.substring(1)
}
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) {
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 }

View File

@ -1,28 +1,28 @@
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(videoConferenceJoinedEvent);
setConferenceData(videoConferenceJoinedEvent)
}
function displayNameChangeListenerWrapper(
setDisplayNameChangedEvent: (newData: DisplayNameChangeEvent) => void,
displayNameChangeEvent: DisplayNameChangeEvent
) {
setDisplayNameChangedEvent(displayNameChangeEvent);
setDisplayNameChangedEvent(displayNameChangeEvent)
}
function displayNameChangeListener(
@ -30,20 +30,16 @@ function displayNameChangeListener(
setConferenceData: (newData: ConferenceData) => void,
displayNameChangeEvent: DisplayNameChangeEvent
) {
console.log(
"[Rooms] displayNameChangeListener",
displayNameChangeEvent,
conferenceData
);
console.log('[Rooms] displayNameChangeListener', displayNameChangeEvent, conferenceData)
if (conferenceData && conferenceData.id == displayNameChangeEvent.id)
setConferenceData({
...conferenceData,
displayName: displayNameChangeEvent.displayname,
} as ConferenceData);
} as ConferenceData)
}
export {
videoConferenceJoinedListener,
displayNameChangeListenerWrapper,
displayNameChangeListener,
};
}

View File

@ -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;
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);
hash = str.charCodeAt(i) + ((hash << 5) - hash)
}
return hash;
return hash
}
// function intToRGB(i: number) {
@ -22,8 +21,6 @@ function hashCode(str: string) { // java String#hashCode
function getColorForUserName(userName: string) {
const hash = hashCode(userName)
return getHslColor(hash)
}
export { getColorForUserName }

View File

@ -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,
uuid: string
name: string
}
export interface UsersData {
roomsData: RoomData[];
usersWithOutRoom: User[];
roomsData: RoomData[]
usersWithOutRoom: User[]
}

View File

@ -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;
.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;
}

View File

@ -1,27 +1,27 @@
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
}
function Chat({ sendMessage }: Props) {
const [chatInput, setChatInput] = useState("")
const [chatInput, setChatInput] = useState('')
const { chatMesages } = useAllChat()
const onInput: React.ChangeEventHandler<HTMLInputElement> = (event) => {
setChatInput(event.target.value);
event.preventDefault();
};
setChatInput(event.target.value)
event.preventDefault()
}
const onSubmit: FormEventHandler<HTMLFormElement> = (event) => {
event.preventDefault();
sendMessage(JSON.stringify({ content: chatInput }));
setChatInput("")
event.preventDefault()
sendMessage(JSON.stringify({ content: chatInput }))
setChatInput('')
}
return (
@ -30,15 +30,20 @@ function Chat({ sendMessage }: Props) {
{chatMesages
.slice()
.reverse() // reverse because of css, don't aks me
.map(message => {
.map((message) => {
const nameStyle = {
color: getColorForUserName(message.sender.name)
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 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
@ -48,10 +53,12 @@ function Chat({ sendMessage }: Props) {
value={chatInput}
onChange={onInput}
/>
<button type="submit"><FontAwesomeIcon icon={faPaperPlane} /></button>
<button type="submit">
<FontAwesomeIcon icon={faPaperPlane} />
</button>
</form>
</div>
);
)
}
export default Chat

View File

@ -1,61 +1,56 @@
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";
ConferenceData,
displayNameChangeListener,
displayNameChangeListenerWrapper,
videoConferenceJoinedListener,
} 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) {
const { setDisplayNameChangeEvent } = useJitsiEventCapture(
curry(displayNameChangeListener)(conferenceData)(setConferenceData)
);
function JitsiEntrypoint({ roomName, userInfo, conferenceData, setConferenceData }: Props) {
const { setDisplayNameChangeEvent } = useJitsiEventCapture(
curry(displayNameChangeListener)(conferenceData)(setConferenceData)
)
return (
<JitsiMeeting
domain={JITSI_DOMAIN}
roomName={roomName}
configOverwrite={{
startWithAudioMuted: true,
disableModeratorIndicator: true,
startScreenSharing: true,
enableEmailInStats: false,
prejoinConfig: { enabled: false },
}}
interfaceConfigOverwrite={{}}
userInfo={userInfo}
onApiReady={(externalApi) => {
externalApi.addEventListener(
"videoConferenceJoined",
curry(videoConferenceJoinedListener)(setConferenceData)
);
externalApi.addEventListener(
"displayNameChange",
curry(displayNameChangeListenerWrapper)(setDisplayNameChangeEvent)
);
}}
getIFrameRef={(iframeRef) => {
iframeRef.style.height = "100%";
iframeRef.style.width = "100%";
}}
/>
);
return (
<JitsiMeeting
domain={JITSI_DOMAIN}
roomName={roomName}
configOverwrite={{
startWithAudioMuted: true,
disableModeratorIndicator: true,
startScreenSharing: true,
enableEmailInStats: false,
prejoinConfig: { enabled: false },
}}
interfaceConfigOverwrite={{}}
userInfo={userInfo}
onApiReady={(externalApi) => {
externalApi.addEventListener(
'videoConferenceJoined',
curry(videoConferenceJoinedListener)(setConferenceData)
)
externalApi.addEventListener(
'displayNameChange',
curry(displayNameChangeListenerWrapper)(setDisplayNameChangeEvent)
)
}}
getIFrameRef={(iframeRef) => {
iframeRef.style.height = '100%'
iframeRef.style.width = '100%'
}}
/>
)
}
export default JitsiEntrypoint;
export default JitsiEntrypoint

View File

@ -1,4 +1,4 @@
export interface UserInfo {
displayName: string;
email: string;
displayName: string
email: string
}

View File

@ -1,19 +1,18 @@
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()
@ -25,15 +24,10 @@ function Meeting({ conferenceData, setConferenceData, userInfo }: Props) {
userInfo={userInfo}
setConferenceData={setConferenceData}
/>
);
)
}
return (
<MeetingNameInput
roomName={roomName}
currentUser={userInfo.displayName}
/>
);
return <MeetingNameInput roomName={roomName} currentUser={userInfo.displayName} />
}
export default Meeting;
export default Meeting

View File

@ -1,41 +1,33 @@
import { FormEventHandler } from "react";
import useMeetingStarted from "../../hooks/useMeetingStarted";
import { useRoomName } from "../../hooks/useRoomName";
import "./MeetingNameInput.css";
function MeetingNameInput(props: {
roomName: string; currentUser: string;
}) {
import { FormEventHandler } from 'react'
import useMeetingStarted from '../../hooks/useMeetingStarted'
import { useRoomName } from '../../hooks/useRoomName'
import './MeetingNameInput.css'
function MeetingNameInput(props: { roomName: string; currentUser: string }) {
const { roomName, updateRoomName, updateAndSubmitRoomName, submitRoomName } = useRoomName()
const [_, setMeetingStarted] = useMeetingStarted()
const onInput: React.ChangeEventHandler<HTMLInputElement> = (event) => {
updateRoomName(event.target.value);
event.preventDefault();
};
updateRoomName(event.target.value)
event.preventDefault()
}
const onSubmit: FormEventHandler<HTMLFormElement> = (event) => {
submitRoomName()
setMeetingStarted(true)
event.preventDefault();
event.preventDefault()
}
console.log("[Rooms] MeetingName input comp");
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}
/>
<input placeholder="Roomname" type="text" value={roomName} onChange={onInput} />
<button type="submit">Enter the adventure</button>
</form>
</div>
);
)
}
export default MeetingNameInput;
export default MeetingNameInput

View File

@ -1,21 +1,20 @@
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;
usersData: UsersData
sendMessage: Function
}
function Sidebar(props: Props) {
const { sidebarVisibility, toggleSidebarVisibility, sidebarToggleText } =
useSidebarVisibility();
const { sidebarVisibility, toggleSidebarVisibility, sidebarToggleText } = useSidebarVisibility()
const [_, setMeetingStarted] = useMeetingStarted()
const { updateAndSubmitRoomName: updateAndSubmitRoomName } = useRoomName();
const { updateAndSubmitRoomName: updateAndSubmitRoomName } = useRoomName()
return (
<div className={`sidebar sidebar-${sidebarVisibility}`}>
@ -25,10 +24,13 @@ function Sidebar(props: Props) {
return (
<>
<h3>
<a href="#" onClick={() => {
updateAndSubmitRoomName(roomData.roomName)
setMeetingStarted(true)
}}>
<a
href="#"
onClick={() => {
updateAndSubmitRoomName(roomData.roomName)
setMeetingStarted(true)
}}
>
{roomData.roomName}
</a>
</h3>
@ -36,7 +38,7 @@ function Sidebar(props: Props) {
<div key={participant.jid}> {participant.displayName} </div>
))}
</>
);
)
})}
</div>
<div>
@ -46,11 +48,13 @@ function Sidebar(props: Props) {
))}
</div>
<div className="sidebar-footer">
{sidebarVisibility === "full" && <Chat sendMessage={props.sendMessage} />}
<button className="sidebar-toggle" onClick={toggleSidebarVisibility}>{sidebarToggleText}</button>
{sidebarVisibility === 'full' && <Chat sendMessage={props.sendMessage} />}
<button className="sidebar-toggle" onClick={toggleSidebarVisibility}>
{sidebarToggleText}
</button>
</div>
</div>
);
)
}
export default Sidebar;
export default Sidebar

View File

@ -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>;
if (sidebarVisibility == 'full') {
return <h2>hi there :)</h2>
} else if (sidebarVisibility == 'small') {
return <h2>hi</h2>
}
return <></>;
return <></>
}
export default SidebarHeader;
export default SidebarHeader

View File

@ -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");
if (sidebarVisibility === 'full') {
setSideBarVisibility('small')
} else if (sidebarVisibility === 'small') {
setSideBarVisibility('hidden')
} else if (sidebarVisibility === 'hidden') {
setSideBarVisibility('full')
}
}, [setSideBarVisibility, sidebarVisibility, sidebarToggleText]);
}, [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

View File

@ -1,6 +1,6 @@
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
@ -9,7 +9,9 @@ interface ChatMessage {
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)
@ -17,5 +19,3 @@ const useAllChat = () => {
}
export default useAllChat

View File

@ -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()
useEffect(() => {
onMessage((messageString) => {
console.log("[Rooms] message from ws", messageString);
const messageObject = JSON.parse(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

View File

@ -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
) {
const [conferenceData, setConferenceDataLocal] = useState<ConferenceData>();
const [conferenceData, setConferenceDataLocal] = useState<ConferenceData>()
const setConferenceData = (newData: ConferenceData) => {
console.log("[Rooms] set conferenceData", conferenceData);
console.log('[Rooms] set conferenceData', conferenceData)
if (conferenceData?.roomName !== newData.roomName) {
// We joined a meeting
sendMessage(JSON.stringify({ roomName: newData.roomName }));
sendMessage(JSON.stringify({ roomName: newData.roomName }))
}
if (conferenceData?.displayName !== newData.displayName) {
// We updated the username
sendMessage(JSON.stringify({ displayName: newData.displayName }));
sendMessage(JSON.stringify({ displayName: newData.displayName }))
}
setConferenceDataLocal(newData);
setUserInfo({ displayName: newData.displayName, email: "" });
};
setConferenceDataLocal(newData)
setUserInfo({ displayName: newData.displayName, email: '' })
}
return { conferenceData, setConferenceData };
return { conferenceData, setConferenceData }
}
export default useConferenceData;
export default useConferenceData

View File

@ -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>();
useState<DisplayNameChangeEvent>()
const setDisplayNameChangeEvent = useCallback(
(newValue: DisplayNameChangeEvent) => {
console.log("[Rooms] newValue", newValue, displayNameChangeEvent);
console.log('[Rooms] newValue', newValue, displayNameChangeEvent)
if (displayNameChangeEvent != newValue) {
setDisplayNameChangeEventLocal(newValue);
setDisplayNameChangeEventLocal(newValue)
}
},
[setDisplayNameChangeEventLocal]
);
)
useEffect(() => {
console.log("[Rooms] displayNameChangeHandler", displayNameChangeEvent);
console.log('[Rooms] displayNameChangeHandler', displayNameChangeEvent)
displayNameChangeHandler &&
displayNameChangeEvent &&
displayNameChangeHandler(displayNameChangeEvent);
}, [displayNameChangeEvent]);
displayNameChangeHandler(displayNameChangeEvent)
}, [displayNameChangeEvent])
return { setDisplayNameChangeEvent };
return { setDisplayNameChangeEvent }
}
export default useJitsiEventCapture;
export default useJitsiEventCapture

View File

@ -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);
};
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);
let cookie = getCookie(USER_COOKIE_NAME)
console.log('[Rooms] getUserNameFromCookie', cookie)
if (cookie) return JSON.parse(cookie)
return {
displayName: "Unknown traveller",
email: "",
};
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

View File

@ -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

View File

@ -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

View File

@ -1,5 +1,5 @@
import { atom, useAtom } from "jotai";
import { useCallback, useState } from "react";
import { atom, useAtom } from 'jotai'
import { useCallback, useState } from 'react'
const roomNameAtom = atom(getRoomNameFromUrl())
@ -8,48 +8,46 @@ function useRoomName() {
const updateRoomName = useCallback(
(newName: string) => {
setRoomName(newName);
console.log("[Rooms] update room name", newName);
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(newName)
setRoomNameInUrl(newName)
setRoomNameInTitle(newName)
console.log('[Rooms] update and submit room name', newName)
},
[setRoomName]
)
const submitRoomName = useCallback(() => {
setRoomNameInUrl(roomName);
setRoomNameInTitle(roomName);
}, [roomName]);
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;
document.title = roomName
}
}
export { useRoomName };
export { useRoomName }

View File

@ -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;
};
return webSocket
}
function useWebSocketConnection(userInfo: UserInfo) {
console.log("[Rooms] useWebSocketConnection");
console.log('[Rooms] useWebSocketConnection')
const [webSocketConnection] = useState<WebSocket>(() =>
createWebSocketConnection(userInfo)
);
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);
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);
messageHandler(ev.data)
}
webSocketConnection.addEventListener('message', wsMessageHandler)
},
[webSocketConnection]
);
)
const disconnect = useCallback(webSocketConnection.close, [
webSocketConnection,
]);
const disconnect = useCallback(webSocketConnection.close, [webSocketConnection])
return { onMessage, sendMessage, disconnect };
return { onMessage, sendMessage, disconnect }
}
export default useWebSocketConnection;
export default useWebSocketConnection

View File

@ -78,7 +78,6 @@ button:focus-visible {
width: 100%;
}
input {
font-size: 1em;
margin: 0.3em;
@ -88,7 +87,7 @@ input {
box-shadow: none;
box-sizing: border-box;
font-size: 17px;
font-family: "Oxygen", sans-serif;
font-family: 'Oxygen', sans-serif;
transition: top 0.1s ease-in-out;
background-color: #2b2a33;
border-color: #646cff;

View File

@ -9,5 +9,5 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<Provider>
<App />
</Provider>
</React.StrictMode>,
</React.StrictMode>
)

File diff suppressed because it is too large Load Diff