diff --git a/.drone.yml b/.drone.yml index 172457a..f1b7944 100644 --- a/.drone.yml +++ b/.drone.yml @@ -18,7 +18,6 @@ trigger: event: include: - tag - - push volumes: - name: drone-shared diff --git a/backend/README.md b/backend/README.md index 3286061..3b0a281 100644 --- a/backend/README.md +++ b/backend/README.md @@ -3,8 +3,7 @@ ## Development `stack build` - -`stack run` +`stack stack run` ## Debug @@ -13,44 +12,3 @@ Using websocat `websocat ws://127.0.0.1:9160` `curl --data 'body data' localhost:8081` - -``` -curl -X POST localhost:8081/roomdata \ - -H "Content-Type: application/json" \ - -d '[ - { - "roomName": "ConferenceRoom1", - "participants": [ - { - "jid": "participant1@example.com", - "email": "participant1@example.com", - "displayName": "Alice", - "avatarURL": "https://example.com/avatars/alice.png" - }, - { - "jid": "participant2@example.com", - "email": "participant2@example.com", - "displayName": "Bob", - "avatarURL": "https://example.com/avatars/bob.png" - } - ] - }, - { - "roomName": "ConferenceRoom2", - "participants": [ - { - "jid": "participant3@example.com", - "email": "participant3@example.com", - "displayName": "Charlie", - "avatarURL": "https://example.com/avatars/charlie.png" - }, - { - "jid": "participant4@example.com", - "email": "participant4@example.com", - "displayName": "Dana", - "avatarURL": "https://example.com/avatars/dana.png" - } - ] - } - ]' -``` diff --git a/backend/app/Main.hs b/backend/app/Main.hs index aee6c9a..7dce4e5 100644 --- a/backend/app/Main.hs +++ b/backend/app/Main.hs @@ -1,27 +1,7 @@ module Main (main) where import ClassyPrelude -import GHC.IO.Encoding (setLocaleEncoding) -import GHC.IO.Encoding.UTF8 (utf8) import Lib (runBothServers) -import Options.Applicative -import Types.Config (ServerOptions, serverOptionsParser) main :: IO () -main = do - setLocaleEncoding utf8 - hSetBuffering stdout LineBuffering - hSetBuffering stderr LineBuffering - - opts <- execParser serverOptions - - runBothServers opts - -serverOptions :: ParserInfo ServerOptions -serverOptions = - info - (serverOptionsParser <**> helper) - ( fullDesc - <> progDesc "Run the server with specified options" - <> header "Haskell Server - A configurable server application" - ) +main = runBothServers diff --git a/backend/converted.nix b/backend/converted.nix index 9432f5c..584d831 100644 --- a/backend/converted.nix +++ b/backend/converted.nix @@ -1,20 +1,17 @@ -{ - mkDerivation, - aeson, - base, - bytestring, - classy-prelude, - http-types, - lib, - lifted-base, - mtl, - text, - uuid, - wai, - wai-extra, - warp, - websockets, - optparse-applicative, +{ mkDerivation +, aeson +, base +, bytestring +, classy-prelude +, http-types +, lib +, lifted-base +, mtl +, text +, uuid +, wai +, warp +, websockets }: mkDerivation { pname = "jitsi-rooms"; @@ -33,10 +30,8 @@ mkDerivation { text uuid wai - wai-extra warp websockets - optparse-applicative ]; executableHaskellDepends = [ aeson @@ -49,10 +44,8 @@ mkDerivation { text uuid wai - wai-extra warp websockets - optparse-applicative ]; homepage = "https://github.com/githubuser/jitsi-rooms#readme"; license = lib.licenses.bsd3; diff --git a/backend/default.nix b/backend/default.nix index 87e6b37..7a10366 100644 --- a/backend/default.nix +++ b/backend/default.nix @@ -1,4 +1,34 @@ -{ pkgs ? import { } }: +let + config = { + packageOverrides = pkgs: rec { + haskellPackages = pkgs.haskellPackages.override { + overrides = haskellPackagesNew: haskellPackagesOld: rec { + jitsi-rooms = + haskellPackagesNew.callPackage ./converted.nix { }; + }; + }; + }; + }; + pkgs = import { inherit config; }; -pkgs.haskellPackages.callPackage ./converted.nix { } +in +pkgs.dockerTools.buildImage { + name = "jitsi-rooms"; + tag = "latest"; + copyToRoot = pkgs.buildEnv { + name = "image-root"; + paths = [ + # pkgs.bash + # pkgs.coreutils + ]; + pathsToLink = [ "/bin" ]; + }; + config = { + Cmd = [ "${pkgs.haskellPackages.jitsi-rooms}/bin/jitsi-rooms-exe" ]; + ExposedPorts = { + "9160/tcp" = { }; + "8081/tcp" = { }; + }; + }; +} diff --git a/backend/docker.nix b/backend/docker.nix deleted file mode 100644 index 4a8ecbc..0000000 --- a/backend/docker.nix +++ /dev/null @@ -1,37 +0,0 @@ -let - config = { - packageOverrides = pkgs: rec { - haskellPackages = pkgs.haskellPackages.override { - overrides = haskellPackagesNew: haskellPackagesOld: rec { - jitsi-rooms = - haskellPackagesNew.callPackage ./converted.nix { }; - }; - }; - }; - }; - pkgs = import { inherit config; }; - - -in -pkgs.dockerTools.buildImage { - name = "jitsi-rooms"; - tag = "latest"; - copyToRoot = pkgs.buildEnv { - name = "image-root"; - paths = [ - # pkgs.bash - # pkgs.coreutils - ]; - pathsToLink = [ "/bin" ]; - }; - config = { - Cmd = [ "${pkgs.haskellPackages.jitsi-rooms}/bin/jitsi-rooms-exe" ]; - ExposedPorts = { - "9160/tcp" = { }; - "8081/tcp" = { }; - }; - Env = [ - "LANG=en_US.UTF-8" - ]; - }; -} diff --git a/backend/jitsi-rooms.cabal b/backend/jitsi-rooms.cabal index 2f4d9fc..51a353c 100644 --- a/backend/jitsi-rooms.cabal +++ b/backend/jitsi-rooms.cabal @@ -1,6 +1,6 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.37.0. +-- This file has been generated from package.yaml by hpack version 0.35.0. -- -- see: https://github.com/sol/hpack @@ -29,14 +29,12 @@ library Lib RoomDataHandler State.ConnectedClientsState - State.GenericTVarState State.RoomDataState - State.RoomsState Types.AppTypes - Types.Config Types.ConnectionState Types.Participant Types.RoomData + Types.RoomsState Types.User Types.UsersData Types.WebEnv @@ -63,13 +61,10 @@ library , http-types , lifted-base , mtl - , optparse-applicative - , process , text , time , uuid , wai - , wai-extra , warp , websockets default-language: Haskell2010 @@ -92,13 +87,10 @@ executable jitsi-rooms-exe , jitsi-rooms , lifted-base , mtl - , optparse-applicative - , process , text , time , uuid , wai - , wai-extra , warp , websockets default-language: Haskell2010 diff --git a/backend/nix/sources.json b/backend/nix/sources.json deleted file mode 100644 index 6ce8996..0000000 --- a/backend/nix/sources.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "nixpkgs": { - "branch": "nixpkgs-unstable", - "description": "Nix Packages collection", - "homepage": "https://github.com/NixOS/nixpkgs", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "abfd31179174133ab8131139d650297bf4da63b7", - "sha256": "1jmkz6l7sj876wzyn5niyfaxshbmw9fp3g8r41k1wbjvmm5xrnsn", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/abfd31179174133ab8131139d650297bf4da63b7.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - } -} diff --git a/backend/nix/sources.nix b/backend/nix/sources.nix deleted file mode 100644 index 9a01c8a..0000000 --- a/backend/nix/sources.nix +++ /dev/null @@ -1,194 +0,0 @@ -# This file has been generated by Niv. - -let - - # - # The fetchers. fetch_ fetches specs of type . - # - - fetch_file = pkgs: name: spec: - let - name' = sanitizeName name + "-src"; - in - if spec.builtin or true then - builtins_fetchurl { inherit (spec) url sha256; name = name'; } - else - pkgs.fetchurl { inherit (spec) url sha256; name = name'; }; - - fetch_tarball = pkgs: name: spec: - let - name' = sanitizeName name + "-src"; - in - if spec.builtin or true then - builtins_fetchTarball { name = name'; inherit (spec) url sha256; } - else - pkgs.fetchzip { name = name'; inherit (spec) url sha256; }; - - fetch_git = name: spec: - let - ref = - if spec ? ref then spec.ref else - if spec ? branch then "refs/heads/${spec.branch}" else - if spec ? tag then "refs/tags/${spec.tag}" else - abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!"; - submodules = if spec ? submodules then spec.submodules else false; - submoduleArg = - let - nixSupportsSubmodules = builtins.compareVersions builtins.nixVersion "2.4" >= 0; - emptyArgWithWarning = - if submodules == true - then - builtins.trace - ( - "The niv input \"${name}\" uses submodules " - + "but your nix's (${builtins.nixVersion}) builtins.fetchGit " - + "does not support them" - ) - {} - else {}; - in - if nixSupportsSubmodules - then { inherit submodules; } - else emptyArgWithWarning; - in - builtins.fetchGit - ({ url = spec.repo; inherit (spec) rev; inherit ref; } // submoduleArg); - - fetch_local = spec: spec.path; - - fetch_builtin-tarball = name: throw - ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`. - $ niv modify ${name} -a type=tarball -a builtin=true''; - - fetch_builtin-url = name: throw - ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`. - $ niv modify ${name} -a type=file -a builtin=true''; - - # - # Various helpers - # - - # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695 - sanitizeName = name: - ( - concatMapStrings (s: if builtins.isList s then "-" else s) - ( - builtins.split "[^[:alnum:]+._?=-]+" - ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name) - ) - ); - - # The set of packages used when specs are fetched using non-builtins. - mkPkgs = sources: system: - let - sourcesNixpkgs = - import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; }; - hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; - hasThisAsNixpkgsPath = == ./.; - in - if builtins.hasAttr "nixpkgs" sources - then sourcesNixpkgs - else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then - import {} - else - abort - '' - Please specify either (through -I or NIX_PATH=nixpkgs=...) or - add a package called "nixpkgs" to your sources.json. - ''; - - # The actual fetching function. - fetch = pkgs: name: spec: - - if ! builtins.hasAttr "type" spec then - abort "ERROR: niv spec ${name} does not have a 'type' attribute" - else if spec.type == "file" then fetch_file pkgs name spec - else if spec.type == "tarball" then fetch_tarball pkgs name spec - else if spec.type == "git" then fetch_git name spec - else if spec.type == "local" then fetch_local spec - else if spec.type == "builtin-tarball" then fetch_builtin-tarball name - else if spec.type == "builtin-url" then fetch_builtin-url name - else - abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; - - # If the environment variable NIV_OVERRIDE_${name} is set, then use - # the path directly as opposed to the fetched source. - replace = name: drv: - let - saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name; - ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}"; - in - if ersatz == "" then drv else - # this turns the string into an actual Nix path (for both absolute and - # relative paths) - if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}"; - - # Ports of functions for older nix versions - - # a Nix version of mapAttrs if the built-in doesn't exist - mapAttrs = builtins.mapAttrs or ( - f: set: with builtins; - listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)) - ); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295 - range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257 - stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269 - stringAsChars = f: s: concatStrings (map f (stringToCharacters s)); - concatMapStrings = f: list: concatStrings (map f list); - concatStrings = builtins.concatStringsSep ""; - - # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331 - optionalAttrs = cond: as: if cond then as else {}; - - # fetchTarball version that is compatible between all the versions of Nix - builtins_fetchTarball = { url, name ? null, sha256 }@attrs: - let - inherit (builtins) lessThan nixVersion fetchTarball; - in - if lessThan nixVersion "1.12" then - fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) - else - fetchTarball attrs; - - # fetchurl version that is compatible between all the versions of Nix - builtins_fetchurl = { url, name ? null, sha256 }@attrs: - let - inherit (builtins) lessThan nixVersion fetchurl; - in - if lessThan nixVersion "1.12" then - fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) - else - fetchurl attrs; - - # Create the final "sources" from the config - mkSources = config: - mapAttrs ( - name: spec: - if builtins.hasAttr "outPath" spec - then abort - "The values in sources.json should not have an 'outPath' attribute" - else - spec // { outPath = replace name (fetch config.pkgs name spec); } - ) config.sources; - - # The "config" used by the fetchers - mkConfig = - { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null - , sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile) - , system ? builtins.currentSystem - , pkgs ? mkPkgs sources system - }: rec { - # The sources, i.e. the attribute set of spec name to spec - inherit sources; - - # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers - inherit pkgs; - }; - -in -mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); } diff --git a/backend/nix/stack-integration.nix b/backend/nix/stack-integration.nix deleted file mode 100644 index 68376c6..0000000 --- a/backend/nix/stack-integration.nix +++ /dev/null @@ -1,16 +0,0 @@ -let - sources = import ./sources.nix; - pkgs = import sources.nixpkgs { }; -in - -# See https://docs.haskellstack.org/en/stable/nix_integration/#using-a-custom-shellnix-file -{ ghc }: - -pkgs.haskell.lib.buildStackProject { - inherit ghc; - name = "haskell-stack-nix"; - # System dependencies needed at compilation time - buildInputs = [ - pkgs.zlib - ]; -} diff --git a/backend/package.yaml b/backend/package.yaml index a2df9ff..2e64954 100644 --- a/backend/package.yaml +++ b/backend/package.yaml @@ -33,9 +33,6 @@ dependencies: - lifted-base - mtl - time - - wai-extra - - process - - optparse-applicative ghc-options: - -Wall diff --git a/backend/shell.nix b/backend/shell.nix deleted file mode 100644 index a24dad2..0000000 --- a/backend/shell.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ pkgs ? import { } }: - -pkgs.mkShell { - buildInputs = with pkgs; [ - haskell-language-server - stack - stylish-haskell - - libnotify - ]; - -} diff --git a/backend/src/BroadcastUserData.hs b/backend/src/BroadcastUserData.hs index 4aa652d..bc00f48 100644 --- a/backend/src/BroadcastUserData.hs +++ b/backend/src/BroadcastUserData.hs @@ -8,9 +8,9 @@ where import ClassyPrelude import Data.Aeson (encode) import Network.WebSockets qualified as WS -import State.ConnectedClientsState (ConnectedClients, MonadConnectedClientsRead (getConnctedClients)) +import State.ConnectedClientsState (MonadConnectedClientsRead (getConnctedClients)) import State.RoomDataState (MonadRoomDataStateRead (getRoomDataState)) -import Types.ConnectionState (Client (..)) +import Types.ConnectionState (Client (..), ConnectedClients) import Types.User (User, clientToUser) import Types.UsersData (UsersData (..)) @@ -41,10 +41,10 @@ broadCastToClientsGeneric :: Text -> m () broadCastToClientsGeneric message = do - connectedClients <- getConnctedClients - liftIO (broadcast message connectedClients) + state <- getConnctedClients + liftIO $ broadcast message state broadcast :: Text -> ConnectedClients -> IO () broadcast message clients = do - putStrLn $ "Broadcasting: " ++ message + putStrLn message forM_ clients $ \client -> WS.sendTextData (conn client) message diff --git a/backend/src/Lib.hs b/backend/src/Lib.hs index 0a01244..b468739 100644 --- a/backend/src/Lib.hs +++ b/backend/src/Lib.hs @@ -6,15 +6,14 @@ module Lib where import ClassyPrelude -import State.ConnectedClientsState (initConnectionsState) -import State.RoomsState (initRoomsState) import Types.AppTypes -import Types.Config (ServerOptions) +import Types.ConnectionState (initConnectionsState) +import Types.RoomsState (initRoomsState) import WebServer (runWebServer) import WebSocket.Server (runWebSocketServer) -runBothServers :: ServerOptions -> IO () -runBothServers serverOptions = do +runBothServers :: IO () +runBothServers = do connectedClientsState <- initConnectionsState roomsState <- initRoomsState @@ -22,8 +21,7 @@ runBothServers serverOptions = do Env { connectedClientsState = connectedClientsState, profile = Dev, - roomsState = roomsState, - config = serverOptions + roomsState = roomsState } _ <- concurrently (unApp runWebSocketServer env) (unApp runWebServer env) diff --git a/backend/src/RoomDataHandler.hs b/backend/src/RoomDataHandler.hs index 5741201..e78fb1c 100644 --- a/backend/src/RoomDataHandler.hs +++ b/backend/src/RoomDataHandler.hs @@ -10,26 +10,23 @@ import ClassyPrelude import Control.Monad.Except (MonadError, throwError) import Data.Aeson (eitherDecodeStrict) import Data.Aeson.Types (FromJSON) -import GHC.IO.Exception (ExitCode (ExitSuccess)) import Network.HTTP.Types (status200, status500) import Network.Wai ( ResponseReceived, consumeRequestBodyStrict, responseLBS, ) +import State.ConnectedClientsState (MonadConnectedClientsRead) import State.RoomDataState ( MonadRoomDataStateModify (setRoomDataState), MonadRoomDataStateRead, ) -import State.RoomsState - ( roomStateDiffInOpenRooms, +import Types.AppTypes (HasConnectedClientState) +import Types.RoomsState + ( HasRoomsState, roomStateDiffers, + updateRoomState, ) -import System.Process -import Text.Printf (printf) -import Types.AppTypes (HasConfig (getConfig)) -import Types.Config (ServerOptions (..)) -import Types.RoomData (RoomData, prettyPrintOpenedRoom) import Types.WebEnv ( HasWebEnv (getRequest), getRespond, @@ -42,19 +39,15 @@ roomDataHandler :: MonadError ResponseReceived m, MonadRoomDataStateRead m, MonadRoomDataStateModify m, - MonadBroadcast m, - HasConfig env + MonadBroadcast m ) => m ResponseReceived roomDataHandler = do newRoomData <- parseBodyOrBadRequest - liftIO $ putStrLn "Got triggered from prosody" - (openedRooms, closedRooms) <- setRoomDataState newRoomData - - mapM_ notifyRoomOpend openedRooms - mapM_ notifyRoomClosed closedRooms - - broadcastUserData + liftIO $ putStrLn "Got triggered form prosody" + whenM (roomStateDiffers newRoomData) $ do + setRoomDataState newRoomData + broadcastUserData success parseBodyOrBadRequest :: @@ -66,7 +59,6 @@ parseBodyOrBadRequest :: ) => m a parseBodyOrBadRequest = do - liftIO $ putStrLn "Parsing body" body <- getRequestBody case eitherDecodeStrict body of Left errorMessage -> do @@ -115,22 +107,3 @@ success = do status200 [("Content-Type", "text/plain")] "" - -notifyRoomOpend :: (MonadIO m, HasConfig a0, MonadReader a0 m) => RoomData -> m () -notifyRoomOpend room = do - config' <- getConfig <$> ask - let ServerOptions {notifyExecutable = notifyExecutable'} = config' - let (name, user) = prettyPrintOpenedRoom room - liftIO $ printf "Room %s opened by %s\n" name user - let command = printf "%s open '%s' '%s'" notifyExecutable' name user - exitCode <- liftIO $ system command - when (exitCode /= ExitSuccess) $ liftIO $ printf "Failed to notify room %s opened by %s running command %s\n" name user command - -notifyRoomClosed :: (MonadIO m, HasConfig a0, MonadReader a0 m) => RoomData -> m () -notifyRoomClosed room = do - config' <- getConfig <$> ask - let ServerOptions {notifyExecutable = notifyExecutable'} = config' - let (name, _) = prettyPrintOpenedRoom room - liftIO $ printf "Room %s closed\n" name - exitCode <- liftIO $ system $ printf "%s closed '%s'" notifyExecutable' name - when (exitCode /= ExitSuccess) $ liftIO $ printf "Failed to notify room %s closed\n" name diff --git a/backend/src/State/ConnectedClientsState.hs b/backend/src/State/ConnectedClientsState.hs index 1d09bb5..e2ff726 100644 --- a/backend/src/State/ConnectedClientsState.hs +++ b/backend/src/State/ConnectedClientsState.hs @@ -1,10 +1,6 @@ module State.ConnectedClientsState ( MonadConnectedClientsModify (..), MonadConnectedClientsRead (..), - ConnectedClients, - ConnectedClientsState, - HasConnectedClientState (..), - initConnectionsState, addWSClientGeneric, updateWSClientGeneric, removeWSClientGeneric, @@ -14,24 +10,14 @@ where import ClassyPrelude import Data.UUID +import Types.AppTypes import Types.ConnectionState -type ConnectedClientsState = TVar ConnectedClients - -initConnectionsState :: IO ConnectedClientsState -initConnectionsState = newTVarIO newConnectedClients - -newConnectedClients :: ConnectedClients -newConnectedClients = [] - class Monad m => MonadConnectedClientsModify m where addWSClient :: Client -> m () removeWSClient :: UUID -> m () updateWSClient :: UUID -> (Client -> Client) -> m () -class HasConnectedClientState a where - getConnectedClientState :: a -> ConnectedClientsState - addWSClientGeneric :: ( HasConnectedClientState env, MonadReader env m, @@ -86,7 +72,9 @@ modifyState :: m () modifyState modifyFunc = do state <- getConnectedClientState <$> ask - atomically $ modifyTVar state modifyFunc + modifyMVar_ state $ \s -> + let s' = modifyFunc s + in return s' class Monad m => MonadConnectedClientsRead m where getConnctedClients :: m ConnectedClients @@ -98,4 +86,4 @@ getConnctedClientsGeneric :: ) => m ConnectedClients getConnctedClientsGeneric = do - ask >>= readTVarIO . getConnectedClientState + ask >>= readMVar . getConnectedClientState diff --git a/backend/src/State/GenericTVarState.hs b/backend/src/State/GenericTVarState.hs deleted file mode 100644 index 0793468..0000000 --- a/backend/src/State/GenericTVarState.hs +++ /dev/null @@ -1,17 +0,0 @@ -module State.GenericTVarState (GenericTVarState, updateGenericTVarState, updateGenericTVarStateWithQuery, getGenericTVarState) where - -import ClassyPrelude - -type GenericTVarState a = TVar a - -updateGenericTVarState :: (MonadIO m) => GenericTVarState a -> a -> m () -updateGenericTVarState tv a = atomically $ writeTVar tv a - -updateGenericTVarStateWithQuery :: (MonadIO m) => GenericTVarState a -> (a -> a -> b) -> a -> m b -updateGenericTVarStateWithQuery tv f a = atomically $ do - b <- readTVar tv - writeTVar tv a - return $ f b a - -getGenericTVarState :: (MonadIO m) => GenericTVarState a -> m a -getGenericTVarState = readTVarIO diff --git a/backend/src/State/RoomDataState.hs b/backend/src/State/RoomDataState.hs index 9ef5a09..35140df 100644 --- a/backend/src/State/RoomDataState.hs +++ b/backend/src/State/RoomDataState.hs @@ -7,8 +7,8 @@ where import ClassyPrelude import Types.RoomData -class (Monad m) => MonadRoomDataStateModify m where - setRoomDataState :: RoomsData -> m RoomsStateDiff +class Monad m => MonadRoomDataStateModify m where + setRoomDataState :: RoomsData -> m () -class (Monad m) => MonadRoomDataStateRead m where +class Monad m => MonadRoomDataStateRead m where getRoomDataState :: m RoomsData diff --git a/backend/src/State/RoomsState.hs b/backend/src/State/RoomsState.hs deleted file mode 100644 index 62a9edc..0000000 --- a/backend/src/State/RoomsState.hs +++ /dev/null @@ -1,88 +0,0 @@ -module State.RoomsState - ( RoomsState, - initRoomsState, - HasRoomsState (..), - roomStateDiffers, - RoomsStateDiff, - roomStateDiffInOpenRooms, - updateRoomState, - getRoomState, - ) -where - -import ClassyPrelude -import State.GenericTVarState -import State.RoomDataState (MonadRoomDataStateRead (getRoomDataState)) -import Types.RoomData (RoomsData, RoomsStateDiff, roomNotEmpty, sameName) - -type RoomsState = GenericTVarState RoomsData - -initRoomsState :: IO RoomsState -initRoomsState = newTVarIO [] - -class HasRoomsState a where - getRoomsState :: a -> RoomsState - -updateRoomState :: - ( HasRoomsState env, - MonadIO m, - MonadReader env m, - MonadRoomDataStateRead m - ) => - RoomsData -> - m RoomsStateDiff -updateRoomState newData = do - state <- getRoomsState <$> ask - current <- getRoomDataState - if not $ eqIgnoreOrdering newData current - then - ( do - liftIO $ putStrLn "Upating room state" - diff <- updateGenericTVarStateWithQuery state roomStateDiff newData - liftIO $ putStrLn "Done Upating room state" - return diff - ) - else return ([], []) - -getRoomState :: - ( HasRoomsState env, - MonadIO m, - MonadReader env m - ) => - m RoomsData -getRoomState = do - state <- getRoomsState <$> ask - getGenericTVarState state - -roomStateDiffers :: - ( MonadRoomDataStateRead m - ) => - RoomsData -> - m Bool -roomStateDiffers newData = do - not . eqIgnoreOrdering newData <$> getRoomDataState - -roomStateDiffInOpenRooms :: - ( MonadRoomDataStateRead m, - MonadIO m - ) => - RoomsData -> - m (RoomsData, RoomsData) -roomStateDiffInOpenRooms newData = do - current <- getRoomDataState - - liftIO $ putStrLn $ pack $ "Current rooms: " ++ show current - liftIO $ putStrLn $ pack $ "New rooms: " ++ show newData - let newRooms = filter roomNotEmpty $ filter (\newRoom -> isNothing $ find (sameName newRoom) (filter roomNotEmpty current)) newData - let oldRooms = filter (\oldRoom -> isNothing $ find (sameName oldRoom) newData) current - - return (newRooms, oldRooms) - -roomStateDiff :: RoomsData -> RoomsData -> RoomsStateDiff -roomStateDiff newData current = (newRooms, oldRooms) - where - newRooms = filter roomNotEmpty $ filter (\newRoom -> isNothing $ find (sameName newRoom) (filter roomNotEmpty current)) newData - oldRooms = filter (\oldRoom -> isNothing $ find (sameName oldRoom) newData) current - -eqIgnoreOrdering :: (Eq a) => [a] -> [a] -> Bool -eqIgnoreOrdering a b = length a == length b && all (`elem` b) a diff --git a/backend/src/Types/AppTypes.hs b/backend/src/Types/AppTypes.hs index 112f480..49338c5 100644 --- a/backend/src/Types/AppTypes.hs +++ b/backend/src/Types/AppTypes.hs @@ -1,36 +1,31 @@ {-# LANGUAGE DerivingVia #-} -module Types.AppTypes (Env (..), App (..), HasConfig (getConfig), getConnectedClientState, AppProfile (Prod, Dev)) where +module Types.AppTypes (Env (..), App (..), getConnectedClientState, HasConnectedClientState, AppProfile (Prod, Dev)) where import ClassyPrelude -import State.ConnectedClientsState -import State.RoomsState +import Types.ConnectionState (ConnectedClientsState) +import Types.RoomsState ( HasRoomsState (getRoomsState), RoomsState, ) -import Types.Config (ServerOptions) data AppProfile = Prod | Dev data Env = Env { connectedClientsState :: ConnectedClientsState, roomsState :: RoomsState, - profile :: AppProfile, - config :: ServerOptions + profile :: AppProfile } +class HasConnectedClientState a where + getConnectedClientState :: a -> ConnectedClientsState + instance HasConnectedClientState Env where getConnectedClientState = connectedClientsState instance HasRoomsState Env where getRoomsState = roomsState -class HasConfig a where - getConfig :: a -> ServerOptions - -instance HasConfig Env where - getConfig = config - newtype App env a = App {unApp :: env -> IO a} deriving ( Functor, diff --git a/backend/src/Types/Config.hs b/backend/src/Types/Config.hs deleted file mode 100644 index 7211e51..0000000 --- a/backend/src/Types/Config.hs +++ /dev/null @@ -1,61 +0,0 @@ -module Types.Config - ( ServerOptions (..), - serverOptionsParser, - ) -where - -import ClassyPrelude - ( Applicative ((<*>)), - Int, - Semigroup ((<>)), - Show, - String, - (<$>), - ) -import Options.Applicative (Parser, auto, help, long, metavar, option, short, showDefault, strOption, value) - -data ServerOptions = ServerOptions - { port :: Int, -- Main server port - websocketPort :: Int, -- WebSocket server port - listenAddress :: String, -- Address to bind the server - notifyExecutable :: String -- Path to the notify executable - } - deriving (Show) - -serverOptionsParser :: Parser ServerOptions -serverOptionsParser = - ServerOptions - <$> option - auto - ( long "port" - <> short 'p' - <> metavar "PORT" - <> help "Port number for the main server (default: 8081)" - <> value 8081 - <> showDefault - ) - <*> option - auto - ( long "websocketPort" - <> short 'w' - <> metavar "WS_PORT" - <> help "Port number for the WebSocket server (default: 9160)" - <> value 9160 - <> showDefault - ) - <*> strOption - ( long "listenAddress" - <> short 'l' - <> metavar "ADDRESS" - <> help "IP address or hostname to bind the server (default: 127.0.0.1)" - <> value "127.0.0.1" - <> showDefault - ) - <*> strOption - ( long "notifyExecutable" - <> short 'n' - <> metavar "EXECUTABLE" - <> help "Path to the notify executable (default: /usr/bin/notify)" - <> value "/usr/bin/notify" - <> showDefault - ) diff --git a/backend/src/Types/ConnectionState.hs b/backend/src/Types/ConnectionState.hs index 799ca76..a787c9e 100644 --- a/backend/src/Types/ConnectionState.hs +++ b/backend/src/Types/ConnectionState.hs @@ -1,6 +1,8 @@ module Types.ConnectionState ( Client (..), + ConnectedClientsState, ConnectedClients, + initConnectionsState, ) where @@ -15,4 +17,12 @@ data Client = Client joinedRoom :: Bool } +type ConnectedClientsState = MVar ConnectedClients + type ConnectedClients = [Client] + +initConnectionsState :: IO ConnectedClientsState +initConnectionsState = newMVar newConnectedClients + +newConnectedClients :: ConnectedClients +newConnectedClients = [] diff --git a/backend/src/Types/Participant.hs b/backend/src/Types/Participant.hs index 960ec48..70dbbce 100644 --- a/backend/src/Types/Participant.hs +++ b/backend/src/Types/Participant.hs @@ -1,6 +1,6 @@ {-# LANGUAGE DeriveGeneric #-} -module Types.Participant (Participant (Participant, displayName)) where +module Types.Participant (Participant) where import ClassyPrelude import Data.Aeson (FromJSON, ToJSON) diff --git a/backend/src/Types/RoomData.hs b/backend/src/Types/RoomData.hs index 2354257..6186ae1 100644 --- a/backend/src/Types/RoomData.hs +++ b/backend/src/Types/RoomData.hs @@ -1,10 +1,10 @@ {-# LANGUAGE DeriveGeneric #-} -module Types.RoomData (RoomData, RoomsStateDiff, RoomsData, sameName, roomNotEmpty, prettyPrintOpenedRoom) where +module Types.RoomData (RoomData, RoomsData) where import ClassyPrelude import Data.Aeson (FromJSON, ToJSON) -import Types.Participant (Participant (Participant, displayName)) +import Types.Participant (Participant) data RoomData = RoomData { roomName :: RoomName, @@ -12,22 +12,10 @@ data RoomData = RoomData } deriving (Generic, Show, Eq) -sameName :: RoomData -> RoomData -> Bool -sameName RoomData {roomName = name1} RoomData {roomName = name2} = name1 == name2 - -roomNotEmpty :: RoomData -> Bool -roomNotEmpty RoomData {participants = participants} = not $ null participants - -prettyPrintOpenedRoom :: RoomData -> (Text, Text) -prettyPrintOpenedRoom RoomData {roomName = roomName, participants = participants} = - (roomName, fromMaybe "" (headMay (map (\Participant {displayName = displayName} -> displayName) participants))) - type RoomName = Text type RoomsData = [RoomData] -type RoomsStateDiff = (RoomsData, RoomsData) - instance ToJSON RoomData instance FromJSON RoomData diff --git a/backend/src/Types/RoomsState.hs b/backend/src/Types/RoomsState.hs new file mode 100644 index 0000000..df5ae71 --- /dev/null +++ b/backend/src/Types/RoomsState.hs @@ -0,0 +1,54 @@ +module Types.RoomsState + ( RoomsState, + initRoomsState, + HasRoomsState (..), + roomStateDiffers, + updateRoomState, + getRoomState, + ) +where + +import ClassyPrelude +import State.RoomDataState (MonadRoomDataStateRead (getRoomDataState)) +import Types.RoomData (RoomsData) + +type RoomsState = MVar RoomsData + +initRoomsState :: IO RoomsState +initRoomsState = newMVar [] + +class HasRoomsState a where + getRoomsState :: a -> RoomsState + +updateRoomState :: + ( HasRoomsState env, + MonadIO m, + MonadReader env m + ) => + RoomsData -> + m () +updateRoomState newData = do + state <- getRoomsState <$> ask + _ <- swapMVar state newData + return () + +getRoomState :: + ( HasRoomsState env, + MonadIO m, + MonadReader env m + ) => + m RoomsData +getRoomState = do + state <- getRoomsState <$> ask + readMVar state + +roomStateDiffers :: + ( MonadRoomDataStateRead m + ) => + RoomsData -> + m Bool +roomStateDiffers newData = do + not . eqIgnoreOrdering newData <$> getRoomDataState + +eqIgnoreOrdering :: (Eq a) => [a] -> [a] -> Bool +eqIgnoreOrdering a b = length a == length b && all (`elem` b) a diff --git a/backend/src/Types/WebEnv.hs b/backend/src/Types/WebEnv.hs index f27d348..eff4d4d 100644 --- a/backend/src/Types/WebEnv.hs +++ b/backend/src/Types/WebEnv.hs @@ -6,12 +6,11 @@ where import ClassyPrelude import Network.Wai (Request, Response, ResponseReceived) -import State.ConnectedClientsState (HasConnectedClientState (getConnectedClientState)) -import State.RoomsState (HasRoomsState (getRoomsState)) import Types.AppTypes ( Env (..), - HasConfig (getConfig), + HasConnectedClientState (getConnectedClientState), ) +import Types.RoomsState (HasRoomsState (getRoomsState)) class HasWebEnv a where getRequest :: a -> Request @@ -32,6 +31,3 @@ instance HasRoomsState WebEnv where instance HasWebEnv WebEnv where getRequest = request getRespond = respond - -instance HasConfig WebEnv where - getConfig = getConfig . appEnv diff --git a/backend/src/Types/WebSocketMessages/WebSocketMessages.hs b/backend/src/Types/WebSocketMessages/WebSocketMessages.hs index 66afebc..641bc5d 100644 --- a/backend/src/Types/WebSocketMessages/WebSocketMessages.hs +++ b/backend/src/Types/WebSocketMessages/WebSocketMessages.hs @@ -1,6 +1,5 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DuplicateRecordFields #-} -{-# LANGUAGE GADTs #-} module Types.WebSocketMessages.WebSocketMessages ( WebSocketMessage (..), @@ -30,22 +29,23 @@ data WebSocketMessage = ClientInfoMessage SetClientInfo | JoinRoomMessage JoinRo instance FromJSON WebSocketMessage where parseJSON = genericParseJSON defaultOptions {sumEncoding = UntaggedValue} -data SetClientInfo where - SetClientInfo :: {displayName :: Text} -> SetClientInfo +data SetClientInfo = SetClientInfo + { displayName :: Text + } deriving (Generic, Show) instance FromJSON SetClientInfo -data JoinRoom where - JoinRoom :: {roomName :: Text} -> JoinRoom +data JoinRoom = JoinRoom + { roomName :: Text + } deriving (Generic, Show) instance FromJSON JoinRoom -data AllChatMessageIncoming where - AllChatMessageIncoming :: - {content :: Text} -> - AllChatMessageIncoming +data AllChatMessageIncoming = AllChatMessageIncoming + { content :: Text + } deriving (Generic, Show) instance FromJSON AllChatMessageIncoming diff --git a/backend/src/WebServer.hs b/backend/src/WebServer.hs index 5981ee7..c32a14d 100644 --- a/backend/src/WebServer.hs +++ b/backend/src/WebServer.hs @@ -15,7 +15,6 @@ import Control.Monad.Except import Network.HTTP.Types import Network.Wai import Network.Wai.Handler.Warp (run) -import Network.Wai.Middleware.RequestLogger (logStdout) import RoomDataHandler (roomDataHandler) import State.ConnectedClientsState ( MonadConnectedClientsRead (..), @@ -25,13 +24,13 @@ import State.RoomDataState ( MonadRoomDataStateModify (..), MonadRoomDataStateRead (getRoomDataState), ) -import State.RoomsState - ( getRoomState, +import Types.AppTypes (Env (..)) +import Types.RoomsState + ( HasRoomsState (getRoomsState), + getRoomState, + roomStateDiffers, updateRoomState, ) -import Text.Printf (printf) -import Types.AppTypes (Env (..), HasConfig (getConfig)) -import Types.Config (ServerOptions (..)) import Types.WebEnv newtype ExceptTApp e a = E {unExceptTApp :: IO (Either e a)} @@ -84,8 +83,7 @@ app :: MonadError ResponseReceived m, MonadRoomDataStateModify m, MonadRoomDataStateRead m, - MonadBroadcast m, - HasConfig env + MonadBroadcast m ) => m ResponseReceived app = requestPathHandler @@ -97,8 +95,7 @@ requestPathHandler :: MonadError ResponseReceived m, MonadRoomDataStateModify m, MonadRoomDataStateRead m, - MonadBroadcast m, - HasConfig env + MonadBroadcast m ) => m ResponseReceived requestPathHandler = do @@ -126,9 +123,7 @@ notFound = do runWebApp :: ( MonadIO m, - MonadReader Env m, - HasConfig Env, - HasConfig WebEnv + MonadReader Env m ) => m Application runWebApp = do @@ -147,14 +142,10 @@ runWebApp = do runWebServer :: ( MonadIO m, - MonadReader Env m, - HasConfig Env, - HasConfig WebEnv + MonadReader Env m ) => m () runWebServer = do - config' <- getConfig <$> ask - let ServerOptions {port = webPort, listenAddress = address} = config' - putStrLn $ pack $ printf "Webserver up and running at http://%s:%d/" address webPort - runWebApp >>= liftIO . (run webPort . logStdout) + putStrLn "http://localhost:8081/" + runWebApp >>= liftIO . run 8081 return () diff --git a/backend/src/WebSocket/Server.hs b/backend/src/WebSocket/Server.hs index 14c6e66..666a8e0 100644 --- a/backend/src/WebSocket/Server.hs +++ b/backend/src/WebSocket/Server.hs @@ -1,5 +1,4 @@ {-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE MonoLocalBinds #-} module WebSocket.Server ( runWebSocketServer, @@ -10,27 +9,22 @@ where import ClassyPrelude import Data.UUID.V4 (nextRandom) import Network.WebSockets qualified as WS -import Text.Printf -import Types.AppTypes (Env, HasConfig (getConfig)) -import Types.Config (ServerOptions (..)) +import Types.AppTypes import WebSocket.WSApp (WSApp (..), WSEnv (..), wsApp) runWebSocketServer :: ( MonadIO m, - Types.AppTypes.HasConfig Types.AppTypes.Env, - MonadReader Types.AppTypes.Env m + MonadReader Env m ) => m () runWebSocketServer = do - config' <- getConfig <$> ask - let ServerOptions {websocketPort = wsPort, listenAddress = address} = config' - putStrLn $ pack $ printf "WebSocket server up and running at ws://%s:%d/" address wsPort + putStrLn "Websocket up at 0.0.0.0:9160" wsApp' <- runWSApp - liftIO $ WS.runServer address wsPort wsApp' + liftIO $ WS.runServer "0.0.0.0" 9160 wsApp' runWSApp :: ( MonadIO m, - MonadReader Types.AppTypes.Env m + MonadReader Env m ) => m WS.ServerApp runWSApp = do diff --git a/backend/src/WebSocket/WSApp.hs b/backend/src/WebSocket/WSApp.hs index 85a0786..6d613ad 100644 --- a/backend/src/WebSocket/WSApp.hs +++ b/backend/src/WebSocket/WSApp.hs @@ -33,11 +33,11 @@ wsApp = do broadcastUserData withCleanUp $ forever $ do handleWSAction + broadcastUserData handleWSAction :: ( MonadWebSocketSession m, MonadConnectedClientsModify m, - MonadRoomDataStateRead m, MonadBroadcast m, MonadAllChat m ) => @@ -47,10 +47,8 @@ handleWSAction = do case msg of JoinRoomMessage _ -> do joinRoom - broadcastUserData ClientInfoMessage clientInfo -> do updateClientName clientInfo - broadcastUserData AllChatMessageIncomingMessage incomingMessage -> do broadCastAllChatMessage incomingMessage diff --git a/backend/src/WebSocket/WSReaderTApp.hs b/backend/src/WebSocket/WSReaderTApp.hs index d997065..3ea6ef3 100644 --- a/backend/src/WebSocket/WSReaderTApp.hs +++ b/backend/src/WebSocket/WSReaderTApp.hs @@ -17,8 +17,7 @@ import ClassyPrelude import Data.UUID import Network.WebSockets qualified as WS import State.ConnectedClientsState - ( HasConnectedClientState, - MonadConnectedClientsModify (..), + ( MonadConnectedClientsModify (..), MonadConnectedClientsRead (..), addWSClientGeneric, getConnctedClientsGeneric, @@ -26,8 +25,8 @@ import State.ConnectedClientsState updateWSClientGeneric, ) import State.RoomDataState -import State.RoomsState (HasRoomsState (..), getRoomState) import Types.AppTypes +import Types.RoomsState (HasRoomsState (..), getRoomState) data WSEnv = WSEnv { appEnv :: Env, diff --git a/backend/stack.yaml b/backend/stack.yaml index e142431..99c2ab2 100644 --- a/backend/stack.yaml +++ b/backend/stack.yaml @@ -14,10 +14,9 @@ # Use the latest resolver that uses the same ghc version # as build for nixos # this way we can use prebuild binaries for hls -# go to -# https://www.stackage.org/ -# and select the lts that is matching you hls version -resolver: lts-22.43 +#resolver: nightly-2022-11-12 +#resolver: ghc-9.2.4 +resolver: lts-20.16 # # The location of a snapshot can be provided as a file or url. Stack assumes # a snapshot provided as a file might change, whereas a url resource does not. @@ -74,3 +73,5 @@ packages: # compiler-check: newer-minor ghc-options: "$everything": -haddock + + diff --git a/backend/stack.yaml.lock b/backend/stack.yaml.lock index f9829eb..08fa9b8 100644 --- a/backend/stack.yaml.lock +++ b/backend/stack.yaml.lock @@ -6,7 +6,7 @@ packages: [] snapshots: - completed: - sha256: 08bd13ce621b41a8f5e51456b38d5b46d7783ce114a50ab604d6bbab0d002146 - size: 720271 - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/43.yaml - original: lts-22.43 + sha256: dad15e2ec0c09280a5c2e07190fb18710fc54472f029f34f861f686540824d81 + size: 649592 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/20/16.yaml + original: lts-20.16 diff --git a/frontend/default.nix b/frontend/default.nix deleted file mode 100644 index e5c4960..0000000 --- a/frontend/default.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ - pkgs ? import { }, -}: - -pkgs.buildNpmPackage { - pname = "jitsi-rooms-backendd"; - version = "1.0.0"; - - # Source files (usually the current directory) - src = pkgs.lib.cleanSource ./.; - - # Optionally, you can provide a package-lock.json or yarn.lock file - # This ensures dependencies are installed reproducibly. - packageLock = ./package-lock.json; # Use this for npm - - # Node.js version (optional, defaults to pkgs.nodejs) - nodejs = pkgs.nodejs_24; - npmDepsHash = "sha256-n9SpPPRvu92RwNPDKZ3f1Splbux2IVGhSazJ4DM2IrA="; - - # Add any additional arguments for the build process - buildInputs = [ ]; - - # Specify the build phase, if needed - buildPhase = '' - echo "Building the app..." - npm run build - ''; - - # Specify the install phase (what to copy to the output) - installPhase = '' - mkdir -p $out - cp -r dist/* $out/ - ''; -} diff --git a/frontend/index.html b/frontend/index.html index d6b1c17..db6a78f 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -2,7 +2,7 @@ - + FF Jitsi Rooms diff --git a/frontend/package-lock.json b/frontend/package-lock.json deleted file mode 100644 index bb7a441..0000000 --- a/frontend/package-lock.json +++ /dev/null @@ -1,1632 +0,0 @@ -{ - "name": "jitsi-roomsv2", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "jitsi-roomsv2", - "version": "0.0.0", - "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" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.20.10", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz", - "integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", - "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helpers": "^7.20.7", - "@babel/parser": "^7.20.7", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.12", - "@babel/types": "^7.20.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz", - "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.20.7", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", - "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.10", - "@babel/types": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz", - "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", - "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==", - "dev": true, - "license": "MIT", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.18.6.tgz", - "integrity": "sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.19.6.tgz", - "integrity": "sha512-RpAi004QyMNisst/pvSanoRdJ4q+jMCWyk9zdw/CyLB9j8RXEahodR6l2GyttDRyEVWZtbN+TpLiHJ3t34LbsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz", - "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.15.tgz", - "integrity": "sha512-JsJtmadyWcR+DEtHLixM7bAQsfi1s0Xotv9kVOoXbCLyhKPOHvMEyh3kJBuTbCPSE4c2jQkQVmarwc9Mg9k3bA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.15.tgz", - "integrity": "sha512-OdbkUv7468dSsgoFtHIwTaYAuI5lDEv/v+dlfGBUbVa2xSDIIuSOHXawynw5N9+5lygo/JdXa5/sgGjiEU18gQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.15.tgz", - "integrity": "sha512-dPUOBiNNWAm+/bxoA75o7R7qqqfcEzXaYlb5uJk2xGHmUMNKSAnDCtRYLgx9/wfE4sXyn8H948OrDyUAHhPOuA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.15.tgz", - "integrity": "sha512-AksarYV85Hxgwh5/zb6qGl4sYWxIXPQGBAZ+jUro1ZpINy3EWumK+/4DPOKUBPnsrOIvnNXy7Rq4mTeCsMQDNA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.15.tgz", - "integrity": "sha512-qqrKJxoohceZGGP+sZ5yXkzW9ZiyFZJ1gWSEfuYdOWzBSL18Uy3w7s/IvnDYHo++/cxwqM0ch3HQVReSZy7/4Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.15.tgz", - "integrity": "sha512-LBWaep6RvJm5KnsKkocdVEzuwnGMjz54fcRVZ9d3R7FSEWOtPBxMhuxeA1n98JVbCLMkTPFmKN6xSnfhnM9WXQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.15.tgz", - "integrity": "sha512-LE8mKC6JPR04kPLRP9A6k7ZmG0k2aWF4ru79Sde6UeWCo7yDby5f48uJNFQ2pZqzUUkLrHL8xNdIHerJeZjHXg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.15.tgz", - "integrity": "sha512-+1sGlqtMJTOnJUXwLUGnDhPaGRKqxT0UONtYacS+EjdDOrSgpQ/1gUXlnze45Z/BogwYaswQM19Gu1YD1T19/w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.15.tgz", - "integrity": "sha512-mRYpuQGbzY+XLczy3Sk7fMJ3DRKLGDIuvLKkkUkyecDGQMmil6K/xVKP9IpKO7JtNH477qAiMjjX7jfKae8t4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.15.tgz", - "integrity": "sha512-puXVFvY4m8EB6/fzu3LdgjiNnEZ3gZMSR7NmKoQe51l3hyQalvTjab3Dt7aX4qGf+8Pj7dsCOBNzNzkSlr/4Aw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.15.tgz", - "integrity": "sha512-ATMGb3eg8T6ZTGZFldlGeFEcevBiVq6SBHvRAO04HMfUjZWneZ/U+JJb3YzlNZxuscJ4Tmzq+JrYxlk7ro4dRg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.15.tgz", - "integrity": "sha512-3SEA4L82OnoSATW+Ve8rPgLaKjC8WMt8fnx7De9kvi/NcVbkj8W+J7qnu/tK2P9pUPQP7Au/0sjPEqZtFeyKQQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.15.tgz", - "integrity": "sha512-8PgbeX+N6vmqeySzyxO0NyDOltCEW13OS5jUHTvCHmCgf4kNXZtAWJ+zEfJxjRGYhVezQ1FdIm7WfN1R27uOyg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.15.tgz", - "integrity": "sha512-U+coqH+89vbPVoU30no1Fllrn6gvEeO5tfEArBhjYZ+dQ3Gv7ciQXYf5nrT1QdlIFwEjH4Is1U1iiaGWW+tGpQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.15.tgz", - "integrity": "sha512-M0nKLFMdyFGBoitxG42kq6Xap0CPeDC6gfF9lg7ZejzGF6kqYUGT+pQGl2QCQoxJBeat/LzTma1hG8C3dq2ocg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.15.tgz", - "integrity": "sha512-t7/fOXBUKfigvhJLGKZ9TPHHgqNgpIpYaAbcXQk1X+fPeUG7x0tpAbXJ2wST9F/gJ02+CLETPMnhG7Tra2wqsQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.15.tgz", - "integrity": "sha512-0k0Nxi6DOJmTnLtKD/0rlyqOPpcqONXY53vpkoAsue8CfyhNPWtwzba1ICFNCfCY1dqL3Ho/xEzujJhmdXq1rg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.15.tgz", - "integrity": "sha512-3SkckazfIbdSjsGpuIYT3d6n2Hx0tck3MS1yVsbahhWiLvdy4QozTpvlbjqO3GmvtvhxY4qdyhFOO2wiZKeTAQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.15.tgz", - "integrity": "sha512-8PNvBC+O8X5EnyIGqE8St2bOjjrXMR17NOLenIrzolvwWnJXvwPo0tE/ahOeiAJmTOS/eAcN8b4LAZcn17Uj7w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.15.tgz", - "integrity": "sha512-YPaSgm/mm7kNcATB53OxVGVfn6rDNbImTn330ZlF3hKej1e9ktCaljGjn2vH08z2dlHEf3kdt57tNjE6zs8SzA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.15.tgz", - "integrity": "sha512-0movUXbSNrTeNf5ZXT0avklEvlJD0hNGZsrrXHfsp9z4tK5xC+apCqmUEZeE9mqrb84Z8XbgGr/MS9LqafTP2A==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.15.tgz", - "integrity": "sha512-27h5GCcbfomVAqAnMJWvR1LqEY0dFqIq4vTe5nY3becnZNu0SX8F0+gTk3JPvgWQHzaGc6VkPzlOiMkdSUunUA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@fortawesome/fontawesome-common-types": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz", - "integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==", - "hasInstallScript": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz", - "integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@fortawesome/fontawesome-common-types": "6.4.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/free-regular-svg-icons": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.0.tgz", - "integrity": "sha512-ZfycI7D0KWPZtf7wtMFnQxs8qjBXArRzczABuMQqecA/nXohquJ5J/RCR77PmY5qGWkxAZDxpnUFVXKwtY/jPw==", - "hasInstallScript": true, - "license": "(CC-BY-4.0 AND MIT)", - "dependencies": { - "@fortawesome/fontawesome-common-types": "6.4.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/react-fontawesome": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", - "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", - "license": "MIT", - "dependencies": { - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "@fortawesome/fontawesome-svg-core": "~1 || ~6", - "react": ">=16.3" - } - }, - "node_modules/@jitsi/react-sdk": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@jitsi/react-sdk/-/react-sdk-1.3.0.tgz", - "integrity": "sha512-f+xtk/j0iXIMJscJeGt3OXnocFeG1pX6OMjv7H/9AaTnCUNsDc/jfDSPme+h0RmdymzJdkSwyHjmkhDK9aehzw==", - "license": "Apache-2.0", - "peerDependencies": { - "react": "16 || 17 || 18", - "react-dom": "16 || 17 || 18" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "18.0.26", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz", - "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.0.10", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz", - "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vitejs/plugin-react": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-3.0.1.tgz", - "integrity": "sha512-mx+QvYwIbbpOIJw+hypjnW1lAbKDHtWK5ibkF/V1/oMBu8HU/chb+SnqJDAsLq1+7rGqjktCEomMTM5KShzUKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.20.7", - "@babel/plugin-transform-react-jsx-self": "^7.18.6", - "@babel/plugin-transform-react-jsx-source": "^7.19.6", - "magic-string": "^0.27.0", - "react-refresh": "^0.14.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.0.0" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001442", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001442.tgz", - "integrity": "sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true, - "license": "MIT" - }, - "node_modules/csstype": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", - "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", - "dev": true, - "license": "ISC" - }, - "node_modules/esbuild": { - "version": "0.16.15", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.15.tgz", - "integrity": "sha512-v+3ozjy9wyj8cOElzx3//Lsb4TCxPfZxRmdsfm0YaEkvZu7y6rKH7Zi1UpDx4JI7dSQui+U1Qxhfij9KBbHfrA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.16.15", - "@esbuild/android-arm64": "0.16.15", - "@esbuild/android-x64": "0.16.15", - "@esbuild/darwin-arm64": "0.16.15", - "@esbuild/darwin-x64": "0.16.15", - "@esbuild/freebsd-arm64": "0.16.15", - "@esbuild/freebsd-x64": "0.16.15", - "@esbuild/linux-arm": "0.16.15", - "@esbuild/linux-arm64": "0.16.15", - "@esbuild/linux-ia32": "0.16.15", - "@esbuild/linux-loong64": "0.16.15", - "@esbuild/linux-mips64el": "0.16.15", - "@esbuild/linux-ppc64": "0.16.15", - "@esbuild/linux-riscv64": "0.16.15", - "@esbuild/linux-s390x": "0.16.15", - "@esbuild/linux-x64": "0.16.15", - "@esbuild/netbsd-x64": "0.16.15", - "@esbuild/openbsd-x64": "0.16.15", - "@esbuild/sunos-x64": "0.16.15", - "@esbuild/win32-arm64": "0.16.15", - "@esbuild/win32-ia32": "0.16.15", - "@esbuild/win32-x64": "0.16.15" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true, - "license": "MIT" - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/jotai": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.0.3.tgz", - "integrity": "sha512-MMjhSPAL3RoeZD9WbObufRT2quThEAEknHHridf2ma8Ml7ZVQmUiHk0ssdbR3F0h3kcwhYqSGJ59OjhPge7RRg==", - "license": "MIT", - "engines": { - "node": ">=12.20.0" - }, - "peerDependencies": { - "react": ">=17.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - } - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/just-curry-it": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/just-curry-it/-/just-curry-it-5.3.0.tgz", - "integrity": "sha512-silMIRiFjUWlfaDhkgSzpuAyQ6EX/o09Eu8ZBfmFwQMbax7+LQzeIU2CBrICT6Ne4l86ITCGvUCBpCubWYy0Yw==", - "license": "MIT" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/magic-string": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", - "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.13" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true, - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-releases": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", - "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", - "dev": true, - "license": "MIT" - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" - }, - "peerDependencies": { - "react": "^18.2.0" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT" - }, - "node_modules/react-refresh": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", - "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/rollup": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.9.1.tgz", - "integrity": "sha512-GswCYHXftN8ZKGVgQhTFUJB/NBXxrRGgO2NCy6E8s1rwEJ4Q9/VttNqcYfEvx4dTo4j58YqdC3OVztPzlKSX8w==", - "dev": true, - "license": "MIT", - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist-lint": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/vite": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.0.4.tgz", - "integrity": "sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.16.3", - "postcss": "^8.4.20", - "resolve": "^1.22.1", - "rollup": "^3.7.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - } - } -} diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico deleted file mode 100755 index 425b15a..0000000 Binary files a/frontend/public/favicon.ico and /dev/null differ diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/frontend/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/result b/frontend/result deleted file mode 120000 index 3053c75..0000000 --- a/frontend/result +++ /dev/null @@ -1 +0,0 @@ -/nix/store/x3fqdrf05dcg52s7x6dkzql551g0bfxw-my-node-app-1.0.0 \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 7206931..8fde18d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -20,7 +20,6 @@ function App() { conferenceData={conferenceData} setConferenceData={setConferenceData} userInfo={userInfo} - usersData={roomData} /> ) diff --git a/frontend/src/background/constants.ts b/frontend/src/background/constants.ts index 46f6bd8..2da5e5d 100644 --- a/frontend/src/background/constants.ts +++ b/frontend/src/background/constants.ts @@ -1,9 +1,9 @@ const ISPROD = window.location.protocol == 'https:' -const JITSI_DOMAIN = 'meet.filefighter.de' +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://' + 'treffen.filefighter.de/ws' + if (USE_REMOTE_BACKEND) return 'wss://' + 'discord.filefighter.de/ws' return 'ws://' + 'localhost:9160/ws' } const WEBSOCKET_URL = getWebsocketUrl() diff --git a/frontend/src/components/jitsi/JitsiEntrypoint.tsx b/frontend/src/components/jitsi/JitsiEntrypoint.tsx index 54a46e5..9975e78 100644 --- a/frontend/src/components/jitsi/JitsiEntrypoint.tsx +++ b/frontend/src/components/jitsi/JitsiEntrypoint.tsx @@ -27,7 +27,7 @@ function JitsiEntrypoint({ roomName, userInfo, conferenceData, setConferenceData domain={JITSI_DOMAIN} roomName={roomName} configOverwrite={{ - startWithAudioMuted: false, + startWithAudioMuted: true, disableModeratorIndicator: true, startScreenSharing: true, enableEmailInStats: false, diff --git a/frontend/src/components/meeting/Meeting.css b/frontend/src/components/meeting/Meeting.css deleted file mode 100644 index a63af6c..0000000 --- a/frontend/src/components/meeting/Meeting.css +++ /dev/null @@ -1,7 +0,0 @@ -.meeting-quickjoin { - text-align: center -} - -.meeting { - flex-grow: 3; -} diff --git a/frontend/src/components/meeting/Meeting.tsx b/frontend/src/components/meeting/Meeting.tsx index eb0e3b3..ccc2b1f 100644 --- a/frontend/src/components/meeting/Meeting.tsx +++ b/frontend/src/components/meeting/Meeting.tsx @@ -1,27 +1,19 @@ import { ConferenceData } from '../../background/jitsi/eventListeners' -import { UsersData } from '../../background/types/roomData' 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 './Meeting.css' -import React from 'react' interface Props { conferenceData: ConferenceData | undefined setConferenceData: (newData: ConferenceData) => void userInfo: UserInfo - usersData: UsersData } -function Meeting(props: Props) { - const { conferenceData, setConferenceData, userInfo, usersData } = props - console.log("[Rooms] meeting usersData", props) +function Meeting({ conferenceData, setConferenceData, userInfo }: Props) { const [meetingStarted] = useMeetingStarted() const { roomName } = useRoomName() - const [_, setMeetingStarted] = useMeetingStarted() - const { updateAndSubmitRoomName: updateAndSubmitRoomName } = useRoomName() if (meetingStarted) { return ( @@ -34,32 +26,7 @@ function Meeting(props: Props) { ) } - return ( -
- -
- {usersData?.roomsData.map((roomData) => { - return ( - -

- { - updateAndSubmitRoomName(roomData.roomName) - setMeetingStarted(true) - }} - > - {decodeURI(roomData.roomName)} - -

- {roomData.participants.map((participant) => ( -
{participant.displayName}
- ))} -
- ) - })} -
-
) + return } export default Meeting diff --git a/frontend/src/components/meeting/MeetingNameInput.tsx b/frontend/src/components/meeting/MeetingNameInput.tsx index 3c498be..0da3d15 100644 --- a/frontend/src/components/meeting/MeetingNameInput.tsx +++ b/frontend/src/components/meeting/MeetingNameInput.tsx @@ -8,7 +8,7 @@ function MeetingNameInput(props: { roomName: string; currentUser: string }) { const [_, setMeetingStarted] = useMeetingStarted() const onInput: React.ChangeEventHandler = (event) => { - updateRoomName(encodeURI(event.target.value)) + updateRoomName(event.target.value) event.preventDefault() } @@ -23,7 +23,7 @@ function MeetingNameInput(props: { roomName: string; currentUser: string }) {

Greetings {props.currentUser}

- +
diff --git a/frontend/src/components/sidebar/Sidebar.css b/frontend/src/components/sidebar/Sidebar.css index d74aba8..40a20cb 100644 --- a/frontend/src/components/sidebar/Sidebar.css +++ b/frontend/src/components/sidebar/Sidebar.css @@ -1,5 +1,4 @@ .sidebar { - resize: horizontal; display: flex; flex-direction: column; white-space: nowrap; diff --git a/frontend/src/components/sidebar/Sidebar.tsx b/frontend/src/components/sidebar/Sidebar.tsx index b5440b5..e67f381 100644 --- a/frontend/src/components/sidebar/Sidebar.tsx +++ b/frontend/src/components/sidebar/Sidebar.tsx @@ -5,7 +5,6 @@ import { UsersData } from '../../background/types/roomData' import useMeetingStarted from '../../hooks/useMeetingStarted' import { useRoomName } from '../../hooks/useRoomName' import Chat from '../chat/Chat' -import React from 'react' interface Props { usersData: UsersData @@ -23,7 +22,7 @@ function Sidebar(props: Props) {
{props.usersData.roomsData.map((roomData) => { return ( - + <>

- {decodeURI(roomData.roomName)} + {roomData.roomName}

{roomData.participants.map((participant) => (
{participant.displayName}
))} -
+ ) })}
-

No room

+

No room

{props.usersData.usersWithOutRoom.map((user) => (
{user.name}
))} diff --git a/frontend/src/components/sidebar/useSidebarVisibility.ts b/frontend/src/components/sidebar/useSidebarVisibility.ts index 8a1589f..2cbdbff 100644 --- a/frontend/src/components/sidebar/useSidebarVisibility.ts +++ b/frontend/src/components/sidebar/useSidebarVisibility.ts @@ -20,7 +20,7 @@ function useSidebarVisibility() { return { sidebarVisibility, toggleSidebarVisibility, sidebarToggleText } } const getSidebarToggleText = (sidebarVisibility: sidebarVisibilityOptions) => { - if (sidebarVisibility === 'full') return '<--' + if (sidebarVisibility === 'full') return '<-' if (sidebarVisibility === 'small') return '<-' if (sidebarVisibility === 'hidden') return '->' } diff --git a/frontend/src/hooks/useBackendData.ts b/frontend/src/hooks/useBackendData.ts index a69ac5e..43be19c 100644 --- a/frontend/src/hooks/useBackendData.ts +++ b/frontend/src/hooks/useBackendData.ts @@ -7,23 +7,20 @@ import useWebSocketConnection from './useWebSocketConnection' function useBackendData(userInfo: UserInfo) { console.log('[Rooms] useBackendData') - const { onMessage, cleanUpOnMessage, sendMessage, disconnect } = useWebSocketConnection(userInfo) + const { onMessage, sendMessage, disconnect } = useWebSocketConnection(userInfo) const { roomData, setRoomData } = useRoomData() const { addChatMessage } = useAllChat() useEffect(() => { - console.log('[Rooms] add onMessage Listener') - const messageCallback = (messageString: string) => { + 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(messageCallback) - return () => cleanUpOnMessage(messageCallback) - }, []) + }) + }, [onMessage, setRoomData, disconnect]) return { roomData, sendMessage } } diff --git a/frontend/src/hooks/useRoomData.ts b/frontend/src/hooks/useRoomData.ts index ccef5b3..f8a66f4 100644 --- a/frontend/src/hooks/useRoomData.ts +++ b/frontend/src/hooks/useRoomData.ts @@ -2,15 +2,7 @@ import { useState } from 'react' import { UsersData } from '../background/types/roomData' function useRoomData() { - const [roomData, setRoomDataInternal] = useState() - - const setRoomData = (usersData: UsersData) => { - usersData.roomsData = usersData.roomsData.map((roomData) => { - roomData.roomName = decodeURI(roomData.roomName) - return roomData - }) - setRoomDataInternal(usersData) - } + const [roomData, setRoomData] = useState() return { roomData, setRoomData } } diff --git a/frontend/src/hooks/useRoomName.ts b/frontend/src/hooks/useRoomName.ts index 14e3c1f..459b201 100644 --- a/frontend/src/hooks/useRoomName.ts +++ b/frontend/src/hooks/useRoomName.ts @@ -1,5 +1,5 @@ import { atom, useAtom } from 'jotai' -import { useCallback } from 'react' +import { useCallback, useState } from 'react' const roomNameAtom = atom(getRoomNameFromUrl()) @@ -46,7 +46,7 @@ function setRoomNameInUrl(roomName: string) { function setRoomNameInTitle(roomName: string) { if (!!roomName) { - document.title = decodeURI(roomName) + document.title = roomName } } diff --git a/frontend/src/hooks/useWebSocketConnection.ts b/frontend/src/hooks/useWebSocketConnection.ts index 33ba89c..77aa0b1 100644 --- a/frontend/src/hooks/useWebSocketConnection.ts +++ b/frontend/src/hooks/useWebSocketConnection.ts @@ -1,19 +1,19 @@ -import { atom, useAtom } from 'jotai' -import { useCallback, useEffect } from 'react' +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) -const webSocketConnectionAtom = atom(webSocket) + return webSocket +} function useWebSocketConnection(userInfo: UserInfo) { console.log('[Rooms] useWebSocketConnection') - const [webSocketConnection] = useAtom(webSocketConnectionAtom) - useEffect(() => { - sendMessageNowOrLater(webSocketConnection, JSON.stringify(userInfo)) - }, [webSocketConnection, userInfo]); + const [webSocketConnection] = useState(() => createWebSocketConnection(userInfo)) const sendMessage = useCallback( (message: string) => { @@ -37,19 +37,8 @@ function useWebSocketConnection(userInfo: UserInfo) { ) const disconnect = useCallback(webSocketConnection.close, [webSocketConnection]) - const cleanUpOnMessage = useCallback((callbackToRemove: any) => { - console.log('[Rooms] cleanUpOnMessage') - webSocketConnection.removeEventListener('message', callbackToRemove) - }, [webSocketConnection]) - return { onMessage, cleanUpOnMessage, sendMessage, disconnect } -} - -const sendMessageNowOrLater = (webSocket: WebSocket, message: string) => { - if (webSocket.readyState !== WebSocket.OPEN) { - return webSocket.addEventListener('open', (_: Event) => webSocket.send(message)) - } - webSocket.send(message) + return { onMessage, sendMessage, disconnect } } export default useWebSocketConnection diff --git a/frontend/src/index.css b/frontend/src/index.css index 7b35201..a51a5c0 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -51,9 +51,7 @@ button { background-color: #1a1a1a; cursor: pointer; transition: border-color 0.25s; - color: white; } - button:hover { border-color: #646cff; } @@ -62,6 +60,19 @@ button:focus-visible { 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 { height: 100%; width: 100%; @@ -81,5 +92,4 @@ input { background-color: #2b2a33; border-color: #646cff; border-radius: 8px; - color: white; } diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 3153213..d389464 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -22,7 +22,7 @@ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz" integrity sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg== -"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.20.7": +"@babel/core@^7.20.7": version "7.20.12" resolved "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz" integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg== @@ -209,17 +209,122 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@esbuild/android-arm64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.16.15.tgz#d58b9efe279b553b377395318d21e360058b3622" + integrity sha512-OdbkUv7468dSsgoFtHIwTaYAuI5lDEv/v+dlfGBUbVa2xSDIIuSOHXawynw5N9+5lygo/JdXa5/sgGjiEU18gQ== + +"@esbuild/android-arm@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.16.15.tgz#6a8ad3016fd9c89bb419bd21605fba242c051809" + integrity sha512-JsJtmadyWcR+DEtHLixM7bAQsfi1s0Xotv9kVOoXbCLyhKPOHvMEyh3kJBuTbCPSE4c2jQkQVmarwc9Mg9k3bA== + +"@esbuild/android-x64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.16.15.tgz#94b0589b6bec5eaf7e8ea2fe6368427899676f21" + integrity sha512-dPUOBiNNWAm+/bxoA75o7R7qqqfcEzXaYlb5uJk2xGHmUMNKSAnDCtRYLgx9/wfE4sXyn8H948OrDyUAHhPOuA== + +"@esbuild/darwin-arm64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.16.15.tgz#525e5603a82837a1e7c8265d3b14433aa869e9b6" + integrity sha512-AksarYV85Hxgwh5/zb6qGl4sYWxIXPQGBAZ+jUro1ZpINy3EWumK+/4DPOKUBPnsrOIvnNXy7Rq4mTeCsMQDNA== + +"@esbuild/darwin-x64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.16.15.tgz#38ec324a3653ade5acc5c190a7a27185caa6223e" + integrity sha512-qqrKJxoohceZGGP+sZ5yXkzW9ZiyFZJ1gWSEfuYdOWzBSL18Uy3w7s/IvnDYHo++/cxwqM0ch3HQVReSZy7/4Q== + +"@esbuild/freebsd-arm64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.15.tgz#05c19bf6e4e56387f6a56bd6933839e889146726" + integrity sha512-LBWaep6RvJm5KnsKkocdVEzuwnGMjz54fcRVZ9d3R7FSEWOtPBxMhuxeA1n98JVbCLMkTPFmKN6xSnfhnM9WXQ== + +"@esbuild/freebsd-x64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.16.15.tgz#68855666ecf1616e2a927154148d4409cd8bc55b" + integrity sha512-LE8mKC6JPR04kPLRP9A6k7ZmG0k2aWF4ru79Sde6UeWCo7yDby5f48uJNFQ2pZqzUUkLrHL8xNdIHerJeZjHXg== + +"@esbuild/linux-arm64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.16.15.tgz#93e8630d19f3a25d31c6467e2b136438391a3ca9" + integrity sha512-mRYpuQGbzY+XLczy3Sk7fMJ3DRKLGDIuvLKkkUkyecDGQMmil6K/xVKP9IpKO7JtNH477qAiMjjX7jfKae8t4g== + +"@esbuild/linux-arm@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.16.15.tgz#9343c9d0e18d15ca5b4e293154e4beae2598b5db" + integrity sha512-+1sGlqtMJTOnJUXwLUGnDhPaGRKqxT0UONtYacS+EjdDOrSgpQ/1gUXlnze45Z/BogwYaswQM19Gu1YD1T19/w== + +"@esbuild/linux-ia32@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.16.15.tgz#2c63615bb87cb2d080f3dc7dd0e3174b9b977233" + integrity sha512-puXVFvY4m8EB6/fzu3LdgjiNnEZ3gZMSR7NmKoQe51l3hyQalvTjab3Dt7aX4qGf+8Pj7dsCOBNzNzkSlr/4Aw== + +"@esbuild/linux-loong64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.16.15.tgz#85a245672709ce60895baf93b1ad3fb4b3cdab4f" + integrity sha512-ATMGb3eg8T6ZTGZFldlGeFEcevBiVq6SBHvRAO04HMfUjZWneZ/U+JJb3YzlNZxuscJ4Tmzq+JrYxlk7ro4dRg== + +"@esbuild/linux-mips64el@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.16.15.tgz#41e325ccd6432f952c674d763d9e5acc25a00267" + integrity sha512-3SEA4L82OnoSATW+Ve8rPgLaKjC8WMt8fnx7De9kvi/NcVbkj8W+J7qnu/tK2P9pUPQP7Au/0sjPEqZtFeyKQQ== + +"@esbuild/linux-ppc64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.16.15.tgz#51c7ed8fec6f9860716cdb1bb86835bdb9206108" + integrity sha512-8PgbeX+N6vmqeySzyxO0NyDOltCEW13OS5jUHTvCHmCgf4kNXZtAWJ+zEfJxjRGYhVezQ1FdIm7WfN1R27uOyg== + +"@esbuild/linux-riscv64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.16.15.tgz#44cb5ad5318d72f52378fa666b2010551c67f333" + integrity sha512-U+coqH+89vbPVoU30no1Fllrn6gvEeO5tfEArBhjYZ+dQ3Gv7ciQXYf5nrT1QdlIFwEjH4Is1U1iiaGWW+tGpQ== + +"@esbuild/linux-s390x@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.16.15.tgz#69572a26c2120ddd446d8207d30ae8f94a801a72" + integrity sha512-M0nKLFMdyFGBoitxG42kq6Xap0CPeDC6gfF9lg7ZejzGF6kqYUGT+pQGl2QCQoxJBeat/LzTma1hG8C3dq2ocg== + "@esbuild/linux-x64@0.16.15": version "0.16.15" resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.15.tgz" integrity sha512-t7/fOXBUKfigvhJLGKZ9TPHHgqNgpIpYaAbcXQk1X+fPeUG7x0tpAbXJ2wST9F/gJ02+CLETPMnhG7Tra2wqsQ== +"@esbuild/netbsd-x64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.16.15.tgz#cba5674608c197bee9d25451ae458ab76a770a45" + integrity sha512-0k0Nxi6DOJmTnLtKD/0rlyqOPpcqONXY53vpkoAsue8CfyhNPWtwzba1ICFNCfCY1dqL3Ho/xEzujJhmdXq1rg== + +"@esbuild/openbsd-x64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.16.15.tgz#4ea4394d5b9c67bac6dcd1e527b47c64990d7d92" + integrity sha512-3SkckazfIbdSjsGpuIYT3d6n2Hx0tck3MS1yVsbahhWiLvdy4QozTpvlbjqO3GmvtvhxY4qdyhFOO2wiZKeTAQ== + +"@esbuild/sunos-x64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.16.15.tgz#91174f7058dfc6cfafdf2251330f6767506db7a7" + integrity sha512-8PNvBC+O8X5EnyIGqE8St2bOjjrXMR17NOLenIrzolvwWnJXvwPo0tE/ahOeiAJmTOS/eAcN8b4LAZcn17Uj7w== + +"@esbuild/win32-arm64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.16.15.tgz#3fa7189ec92d1de87563ab9e73b3e0a4adbfd203" + integrity sha512-YPaSgm/mm7kNcATB53OxVGVfn6rDNbImTn330ZlF3hKej1e9ktCaljGjn2vH08z2dlHEf3kdt57tNjE6zs8SzA== + +"@esbuild/win32-ia32@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.16.15.tgz#a114e4878e74fa6b5453cb407be4f2a28b72809d" + integrity sha512-0movUXbSNrTeNf5ZXT0avklEvlJD0hNGZsrrXHfsp9z4tK5xC+apCqmUEZeE9mqrb84Z8XbgGr/MS9LqafTP2A== + +"@esbuild/win32-x64@0.16.15": + version "0.16.15" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.16.15.tgz#e28277cdbc1c9cde2b982c814d05f44d4b1f0580" + integrity sha512-27h5GCcbfomVAqAnMJWvR1LqEY0dFqIq4vTe5nY3becnZNu0SX8F0+gTk3JPvgWQHzaGc6VkPzlOiMkdSUunUA== + "@fortawesome/fontawesome-common-types@6.4.0": version "6.4.0" resolved "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz" integrity sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ== -"@fortawesome/fontawesome-svg-core@^6.4.0", "@fortawesome/fontawesome-svg-core@~1 || ~6": +"@fortawesome/fontawesome-svg-core@^6.4.0": version "6.4.0" resolved "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz" integrity sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw== @@ -272,7 +377,7 @@ resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13", "@jridgewell/sourcemap-codec@1.4.14": +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13": version "1.4.14" resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== @@ -329,7 +434,7 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -browserslist@^4.21.3, "browserslist@>= 4.21.0": +browserslist@^4.21.3: version "4.21.4" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz" integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== @@ -425,6 +530,11 @@ escape-string-regexp@^1.0.5: resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" @@ -553,7 +663,7 @@ prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" -react-dom@^18.2.0, "react-dom@16 || 17 || 18": +react-dom@^18.2.0: version "18.2.0" resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz" integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== @@ -571,7 +681,7 @@ react-refresh@^0.14.0: resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz" integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ== -react@^18.2.0, react@>=16.3, react@>=17.0.0, "react@16 || 17 || 18": +react@^18.2.0: version "18.2.0" resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz" integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== diff --git a/nixos.nix b/nixos.nix deleted file mode 100644 index a9751b5..0000000 --- a/nixos.nix +++ /dev/null @@ -1,68 +0,0 @@ -{ - lib, - pkgs, - config, - ... -}: -with lib; -let - cfg = config.services.jitsi-rooms; - backendPort = 8081; - wsPort = 9160; - address = "127.0.0.1"; - backend = (pkgs.callPackage ./backend/default.nix { }); - frontend = (pkgs.callPackage ./frontend/default.nix { }); - prodsodyPackage = (pkgs.callPackage ./prodsody/default.nix { }); - notifyScript = "/run/current-system/sw/bin/send-signal-jitsi-notify"; -in -{ - options.services.jitsi-rooms = { - enable = mkEnableOption "jitsi-rooms service"; - nginxHostname = mkOption { - type = types.str; - default = "treffen.filefighter.de"; - }; - }; - - config = mkIf cfg.enable { - systemd.services.jitsi-rooms = { - description = "jitsi-rooms"; - - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - - serviceConfig = { - ExecStart = "${backend}/bin/jitsi-rooms-exe -n ${notifyScript}"; - DynamicUser = true; - User = "jitsi-rooms-backend"; - }; - }; - - users.users.jitsi-rooms-backend = { - isSystemUser = true; - group = "jitsi-rooms-backend"; - extraGroups = [ "dbus" ]; - }; - users.groups.jitsi-rooms-backend = { }; - - services.nginx.virtualHosts.${cfg.nginxHostname} = { - forceSSL = true; - enableACME = true; - - locations = { - "/" = { - root = frontend; - tryFiles = "$uri $uri/ /index.html"; - }; - "/ws" = { - proxyPass = "http://${address}:${toString wsPort}"; - }; - }; - }; - services.prosody = { - extraPluginPaths = [ "${prodsodyPackage}/share" ]; - extraModules = [ "jitsi_rooms" ]; - }; - }; - -} diff --git a/prodsody/Readme.md b/prodsody/Readme.md index 299f8dc..65ebf87 100644 --- a/prodsody/Readme.md +++ b/prodsody/Readme.md @@ -10,7 +10,7 @@ ### Get started - run `./run_dev.sh` -- open [https://localhost:8443/](https://localhost:8443/) (accept the risk about self-signed certs) +- open [https://localhost:8443/](https://localhost:8443/) - make changes to mod_jitsi_rooms.lua and save the file - prosody will be restarted - join a room in jitsi @@ -19,8 +19,3 @@ ## Deploying - all required changes to the [jitsi meet docker setup](https://github.com/jitsi/docker-jitsi-meet) are marked with a "custom" comment - -## ? - -Maybe we could just use https://github.com/jitsi-contrib/prosody-plugins/tree/dd1cb9098f5fbd281f2b62c1e2cf30e220ff14b0/event_sync -=> This does not include the whole participants list diff --git a/prodsody/default.nix b/prodsody/default.nix deleted file mode 100644 index 1f15f09..0000000 --- a/prodsody/default.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ - pkgs ? import { }, -}: - -pkgs.stdenv.mkDerivation { - pname = "jitsi-room-prosody"; - version = "1.0.0"; - - src = pkgs.lib.cleanSource ./.; - dontBuild = true; - - installPhase = '' - runHook preInstall - mkdir -p $out/share - mv *.lua $out/share/ - runHook postInstall - ''; - - meta = { - name = "Jitsi Rooms Prosody Plugin"; - description = "Prosody configuration for Jitsi Rooms"; - }; -} diff --git a/prodsody/docker-compose.yml b/prodsody/docker-compose.yml index 0c4a04b..08feefc 100644 --- a/prodsody/docker-compose.yml +++ b/prodsody/docker-compose.yml @@ -347,7 +347,7 @@ services: meet.jitsi: jitsi-rooms: - image: jitsi-rooms + image: jitsi-rooms:67y5d9y2zbi7wkqm2jpcjj1k2614qwx2 restart: ${RESTART_POLICY:-unless-stopped} ports: - '9160:9160' diff --git a/prodsody/fix-permissions.sh b/prodsody/fix-permissions.sh old mode 100755 new mode 100644 diff --git a/prodsody/jitsi-meet-cfg/prosody/prosody-plugins-custom/mod_jitsi_rooms.lua b/prodsody/jitsi-meet-cfg/prosody/prosody-plugins-custom/mod_jitsi_rooms.lua index cfe138b..dde9499 100644 --- a/prodsody/jitsi-meet-cfg/prosody/prosody-plugins-custom/mod_jitsi_rooms.lua +++ b/prodsody/jitsi-meet-cfg/prosody/prosody-plugins-custom/mod_jitsi_rooms.lua @@ -4,7 +4,6 @@ local json = require "util.json"; local array = require "util.array"; local iterators = require "util.iterators"; local jid = require "util.jid"; -local http = require "util.http"; local async_handler_wrapper = module:require "util".async_handler_wrapper; local get_room_from_jid = module:require "util".get_room_from_jid; @@ -13,9 +12,9 @@ local domain_name = "meet.jitsi" function get_participants_for_room(room_name) + local room_address = jid.join(room_name, muc_domain_prefix .. "." .. domain_name); - local decoded_room_address = http.urldecode(room_address); - local room = get_room_from_jid(decoded_room_address); + local room = get_room_from_jid(room_address); local occupants_json = array(); if room then local occupants = room._occupants; @@ -48,6 +47,7 @@ function get_participants_for_room(room_name) end function get_all_rooms_with_participants() + local sessions = prosody.full_sessions; local someTable = (it.join(it.keys(sessions))); @@ -74,7 +74,7 @@ end -- @return GET response, containing a json with participants details function handle_get_sessions(event) handle_room_event() - return { status_code = 200, body = get_all_rooms_with_participants() }; + return { status_code = 200; body = get_all_rooms_with_participants() }; end function module.load() @@ -86,9 +86,9 @@ function module.load() module:log("info", "Hello! You can reach me at: %s", module:http_url()); module:provides("http", { route = { - ["GET"] = function(event) return async_handler_wrapper(event, handle_get_sessions) end, + ["GET"] = function(event) return async_handler_wrapper(event, handle_get_sessions) end; - }, + }; }); end @@ -125,6 +125,7 @@ end --- Checks if event is triggered by healthchecks or focus user. function is_system_event(event) + if event == nil or event.room == nil or event.room.jid == nil then return true; end @@ -146,11 +147,12 @@ function handle_room_event(event) return; end - async_http_request("http://jitsi-rooms:8081/roomdata", + async_http_request("http://192.168.2.116:8081/roomdata", { method = "POST", body = get_all_rooms_with_participants() }) + end --Helper function to wait till a component is loaded before running the given callback diff --git a/prodsody/mod_jitsi_rooms.lua b/prodsody/mod_jitsi_rooms.lua index 470f7f7..dde9499 100644 --- a/prodsody/mod_jitsi_rooms.lua +++ b/prodsody/mod_jitsi_rooms.lua @@ -1,94 +1,95 @@ ---@diagnostic disable: deprecated -local it = require("util.iterators") -local json = require("util.json") -local array = require("util.array") -local iterators = require("util.iterators") -local jid = require("util.jid") -local http = require("util.http") +local it = require "util.iterators"; +local json = require "util.json"; +local array = require "util.array"; +local iterators = require "util.iterators"; +local jid = require "util.jid"; + +local async_handler_wrapper = module:require "util".async_handler_wrapper; +local get_room_from_jid = module:require "util".get_room_from_jid; +local muc_domain_prefix = module:get_option_string("muc_mapper_domain_prefix", "conference"); +local domain_name = "meet.jitsi" -local async_handler_wrapper = module:require("util").async_handler_wrapper -local get_room_from_jid = module:require("util").get_room_from_jid -local muc_domain_prefix = module:get_option_string("muc_mapper_domain_prefix", "conference") -local domain_name = "meet.filefighter.de" function get_participants_for_room(room_name) - local room_address = jid.join(room_name, muc_domain_prefix .. "." .. domain_name) - local decoded_room_address = http.urldecode(room_address) - local room = get_room_from_jid(decoded_room_address) - local occupants_json = array() - if room then - local occupants = room._occupants - if occupants then - participant_count = iterators.count(room:each_occupant()) - for _, occupant in room:each_occupant() do - -- filter focus as we keep it as hidden participant - if string.sub(occupant.nick, -string.len("/focus")) ~= "/focus" then - for _, pr in occupant:each_session() do - local nick = pr:get_child_text("nick", "http://jabber.org/protocol/nick") or "" - local email = pr:get_child_text("email") or "" - local avatarURL = pr:get_child_text("avatarURL") or "" -- does not work :( - occupants_json:push({ - jid = tostring(occupant.nick), - email = tostring(email), - displayName = tostring(nick), - avatarURL = tostring(avatarURL), - }) - end - end - end - end - log("debug", "there are %s occupants in room", tostring(participant_count)) - return occupants_json - else - log("debug", "no such room exists") - end - return occupants_json + + local room_address = jid.join(room_name, muc_domain_prefix .. "." .. domain_name); + local room = get_room_from_jid(room_address); + local occupants_json = array(); + if room then + local occupants = room._occupants; + if occupants then + participant_count = iterators.count(room:each_occupant()); + for _, occupant in room:each_occupant() do + -- filter focus as we keep it as hidden participant + if string.sub(occupant.nick, -string.len("/focus")) ~= "/focus" then + for _, pr in occupant:each_session() do + local nick = pr:get_child_text("nick", "http://jabber.org/protocol/nick") or ""; + local email = pr:get_child_text("email") or ""; + local avatarURL = pr:get_child_text("avatarURL") or "" -- does not work :( + occupants_json:push({ + jid = tostring(occupant.nick), + email = tostring(email), + displayName = tostring(nick), + avatarURL = tostring(avatarURL) + }); + end + end + end + end + log("debug", + "there are %s occupants in room", tostring(participant_count)); + return occupants_json + else + log("debug", "no such room exists"); + end + return occupants_json end function get_all_rooms_with_participants() - local sessions = prosody.full_sessions - local someTable = (it.join(it.keys(sessions))) - local actual_rooms = someTable[1][2] + local sessions = prosody.full_sessions; - local roomNames = {} - for _, v in pairs(actual_rooms) do - local roomName = v["jitsi_web_query_room"] - if roomName ~= nil then - roomNames[roomName] = true - end - end + local someTable = (it.join(it.keys(sessions))); + local actual_rooms = someTable[1][2] - local rooms_with_participants = array() - for room_name, _ in pairs(roomNames) do - local room = { roomName = room_name, participants = get_participants_for_room(room_name) } - rooms_with_participants:push(room) - end - return json.encode(rooms_with_participants) + local roomNames = {} + for _, v in pairs(actual_rooms) do + local roomName = v["jitsi_web_query_room"] + if (roomName ~= nil) then + roomNames[roomName] = true; + end + end + + local rooms_with_participants = array(); + for room_name, _ in pairs(roomNames) do + local room = { roomName = room_name, participants = get_participants_for_room(room_name) } + rooms_with_participants:push(room) + end + return json.encode(rooms_with_participants) end --- Handles request for retrieving the room participants details -- @param event the http event, holds the request query -- @return GET response, containing a json with participants details function handle_get_sessions(event) - handle_room_event() - return { status_code = 200, body = get_all_rooms_with_participants() } + handle_room_event() + return { status_code = 200; body = get_all_rooms_with_participants() }; end function module.load() - -- Ensure that mod_http is loaded: - -- - module:depends("http") + -- Ensure that mod_http is loaded: + -- + module:depends("http"); - -- Now publish our HTTP 'app': - module:log("info", "Hello! You can reach me at: %s", module:http_url()) - module:provides("http", { - route = { - ["GET"] = function(event) - return async_handler_wrapper(event, handle_get_sessions) - end, - }, - }) + -- Now publish our HTTP 'app': + module:log("info", "Hello! You can reach me at: %s", module:http_url()); + module:provides("http", { + route = { + ["GET"] = function(event) return async_handler_wrapper(event, handle_get_sessions) end; + + }; + }); end -------- event stuff @@ -102,104 +103,106 @@ end -- -- -local http = require("net.http") -local is_healthcheck_room = module:require("util").is_healthcheck_room +local http = require "net.http"; +local is_healthcheck_room = module:require "util".is_healthcheck_room; --- Start non-blocking HTTP call -- @param url URL to call -- @param options options table as expected by net.http where we provide optional headers, body or method. local function async_http_request(url, options) - local completed = false - local timed_out = false + local completed = false; + local timed_out = false; - local function cb_(response_body, response_code) - if not timed_out then -- request completed before timeout - completed = true + local function cb_(response_body, response_code) + if not timed_out then -- request completed before timeout + completed = true; - module:log("debug", "%s %s returned code %s", options.method, url, response_code) - end - end + module:log("debug", "%s %s returned code %s", options.method, url, response_code); + end + end - http.request(url, options, cb_) + http.request(url, options, cb_); end --- Checks if event is triggered by healthchecks or focus user. function is_system_event(event) - if event == nil or event.room == nil or event.room.jid == nil then - return true - end - if is_healthcheck_room(event.room.jid) then - return true - end + if event == nil or event.room == nil or event.room.jid == nil then + return true; + end - if event.occupant and jid.node(event.occupant.jid) == "focus" then - return true - end + if is_healthcheck_room(event.room.jid) then + return true; + end - return false + if event.occupant and jid.node(event.occupant.jid) == "focus" then + return true; + end + + return false; end function handle_room_event(event) - module:log("info", "hallo irgendwas ist passiert") - if is_system_event(event) then - return - end + module:log('info', "hallo irgendwas ist passiert"); + if is_system_event(event) then + return; + end + + async_http_request("http://192.168.2.116:8081/roomdata", + { + method = "POST", + body = get_all_rooms_with_participants() + }) - async_http_request("http://localhost:8081/roomdata", { - method = "POST", - body = get_all_rooms_with_participants(), - }) end --Helper function to wait till a component is loaded before running the given callback function run_when_component_loaded(component_host_name, callback) - local function trigger_callback() - module:log("info", "Component loaded %s", component_host_name) - callback(module:context(component_host_name), component_host_name) - end + local function trigger_callback() + module:log('info', 'Component loaded %s', component_host_name); + callback(module:context(component_host_name), component_host_name); + end - if prosody.hosts[component_host_name] == nil then - module:log("debug", "Host %s not yet loaded. Will trigger when it is loaded.", component_host_name) - prosody.events.add_handler("host-activated", function(host) - if host == component_host_name then - trigger_callback() - end - end) - else - trigger_callback() - end + if prosody.hosts[component_host_name] == nil then + module:log('debug', 'Host %s not yet loaded. Will trigger when it is loaded.', component_host_name); + prosody.events.add_handler('host-activated', function(host) + if host == component_host_name then + trigger_callback(); + end + end); + else + trigger_callback(); + end end -- Helper function to wait till a component's muc module is loaded before running the given callback function run_when_muc_module_loaded(component_host_module, component_host_name, callback) - local function trigger_callback() - module:log("info", "MUC module loaded for %s", component_host_name) - callback(prosody.hosts[component_host_name].modules.muc, component_host_module) - end + local function trigger_callback() + module:log('info', 'MUC module loaded for %s', component_host_name); + callback(prosody.hosts[component_host_name].modules.muc, component_host_module); + end - if prosody.hosts[component_host_name].modules.muc == nil then - module:log("debug", "MUC module for %s not yet loaded. Will trigger when it is loaded.", component_host_name) - prosody.hosts[component_host_name].events.add_handler("module-loaded", function(event) - if event.module == "muc" then - trigger_callback() - end - end) - else - trigger_callback() - end + if prosody.hosts[component_host_name].modules.muc == nil then + module:log('debug', 'MUC module for %s not yet loaded. Will trigger when it is loaded.', component_host_name); + prosody.hosts[component_host_name].events.add_handler('module-loaded', function(event) + if (event.module == 'muc') then + trigger_callback(); + end + end); + else + trigger_callback() + end end local main_muc_component_host = muc_domain_prefix .. "." .. domain_name --- local main_muc_component_host = module:get_option_string("muc_component") -- Handle events on main muc module run_when_component_loaded(main_muc_component_host, function(host_module, host_name) - run_when_muc_module_loaded(host_module, host_name, function(main_muc, main_module) - main_muc_service = main_muc -- so it can be accessed from breakout muc event handlers + run_when_muc_module_loaded(host_module, host_name, function(main_muc, main_module) + main_muc_service = main_muc; -- so it can be accessed from breakout muc event handlers - -- the following must run after speakerstats (priority -1) - main_module:hook("muc-room-created", handle_room_event, -3) -- must run after handle_main_room_created - main_module:hook("muc-occupant-joined", handle_room_event, -2) - main_module:hook("muc-occupant-left", handle_room_event, -2) -- see also https://issues.prosody.im/1743 - main_module:hook("muc-room-destroyed", handle_room_event, -2) - end) -end) + -- the following must run after speakerstats (priority -1) + main_module:hook("muc-room-created", handle_room_event, -3); -- must run after handle_main_room_created + main_module:hook("muc-occupant-joined", handle_room_event, -2); + main_module:hook("muc-occupant-left", handle_room_event, -2); + main_module:hook("muc-room-destroyed", handle_room_event, -2); + end); +end); diff --git a/prodsody/result b/prodsody/result deleted file mode 120000 index 437c8d3..0000000 --- a/prodsody/result +++ /dev/null @@ -1 +0,0 @@ -/nix/store/88ak9a0jwp38h95kb3hpd3965pmbhnjx-jitsi-room-prosody-1.0.0 \ No newline at end of file