Fix components rerendering unnecessarily

Before, some providers (WebRtcProvider, CallProvider...) were rendered conditionally.
This was causing all their children to re-render when the provider rendered.

Instead of using conditional rendering, these providers now use `ConditionalContextProvider`.
It always renders the provider, but sets its value to `initialValue` if the dependencies are not all defined.
If all dependencies are defined, the value is the result of the `useProviderValue` hook.

Changes:
- New file: `ConditionalContextProvider`
- New file: `HookComponent` - Component that calls a hook when mounted and calls a `callback` function with the hook result as argument
- For `WebRtcProvider` and `CallProvider`, use `createOptionalContext` to create the context and `ConditionalContextProvider` to provide their value only when the conditions are met
- In `WebRtcProvider`, set the webRtcConnection to undefined when not in a call
- For all providers, wrap their `value` prop in `useMemo` to avoid unnecessary rerenders

Change-Id: Ide947e216d54599aabc71cf4bd026bd20d6e0daf
16 files changed
tree: 7125c6636cb5f5bf31776fe5c4a81030e3a05f9b
  1. .hooks/
  2. client/
  3. common/
  4. server/
  5. .dockerignore
  6. .eslintrc.cjs
  7. .gitignore
  8. .gitmodules
  9. .gitreview
  10. .prettierrc.json
  11. docker-compose.yml
  12. Dockerfile
  13. Jenkinsfile
  14. package-lock.json
  15. package.json
  16. README.md
README.md

Jami Web

The web version of Jami.

The repo is structured as 4 subprojects:

  • client: the web front-end made with React
  • server: the back-end server made with Express.js, which starts a daemon instance
  • common: the common code used by both client and server
  • daemon: a submodule containing the Jami daemon

Prerequisites

  • Linux

  • Node.js 16

  • npm

  • SWIG 4.1.0:

    • Build from source with the following instructions: https://swig.org/svn.html

      Note: you will need have Bison installed. On Ubuntu, this can be installed using sudo apt install bison.

      git clone https://github.com/swig/swig.git
      cd swig
      ./autogen.sh
      ./configure
      make
      sudo make install
      

Setup

Build the Jami daemon with Node.js bindings

  1. Install the required dependencies: https://docs.jami.net/build/dependencies.html

    Note: for Ubuntu, the minimally needed dependencies are:

    sudo apt install git build-essential cmake automake autoconf autopoint libtool pkg-config libdbus-1-dev libva-dev libvdpau-dev libasound2-dev libpulse-dev libudev-dev libexpat1-dev ssnasm yasm yasm nasm
    
  2. Compile the dependencies:

    cd daemon/contrib
    mkdir native
    cd native
    ../bootstrap
    make -j$(nproc)
    
  3. Install node-gyp to build the daemon with Node.js bindings:

    npm install -g node-gyp
    
  4. Compile the daemon with Node.js bindings:

    cd ../..
    ./autogen.sh
    ./configure --with-nodejs
    make -j$(nproc)
    
  5. Create a symlink to jamid.node in server:

    cd ../server
    ln -s ../daemon/bin/nodejs/build/Release/jamid.node jamid.node
    cd ..
    

Install npm dependencies and set up Git hooks

npm install

This will install the relevant dependencies for all subprojects and configure Git hooks.

Usage

Run with hot-reload for development

Start both the client and server:

LD_LIBRARY_PATH="${PWD}/daemon/src/.libs" npm start

You can also start the client and server individually:

npm start --workspace client
LD_LIBRARY_PATH="${PWD}/daemon/src/.libs" npm start --workspace server

Open http://localhost:3000 in your browser to view the app.

Build for production

npm run build

Preview the production build

LD_LIBRARY_PATH="${PWD}/daemon/src/.libs" npm run start:prod

Lint files

npm run lint

Lint and fix files:

npm run lint:fix

Format files

npm run format

Clean build output

npm run clean

Using a Docker container for development

You may instead wish to use a Docker container for development.

This allows you to avoid having to install all the dependencies needed to build the daemon on your computer. The container is meant for development: it uses bind mounts to mount the source code from your computer into the container, so that the container rebuilds the project whenever changes are made locally.

With Docker Compose

  1. Build the Docker image for the daemon:

    docker-compose build jami-daemon
    
  2. Build the Docker image for Jami web:

    docker-compose build
    
  3. Run the Docker container:

    docker-compose up
    

Without Docker Compose

  1. Build the Docker image for the daemon:

    cd daemon
    docker build --build-arg config_args="--with-nodejs" -t jami-daemon .
    cd ..
    
  2. Build the Docker image for Jami web:

    docker build --target development --t jami-web .
    
  3. Run the Docker container:

    docker run -it \
        -p 3000:3000 \
        -p 5000:5000 \
        --volume ${PWD}/client/src:/web-client/client/src \
        --volume ${PWD}/server/src:/web-client/server/src \
        --volume ${PWD}/client/.env.development:/web-client/client/.env.development \
        --volume ${PWD}/server/.env:/web-client/server/.env \
        jami-web