diff --git a/.eslintrc b/.eslintrc index fd7f3ff54c..0da4fde6e2 100644 --- a/.eslintrc +++ b/.eslintrc @@ -101,5 +101,5 @@ } } ], - "ignorePatterns": ["**/dist/**", "**/src/models/Noise.js", "playwright/**"] + "ignorePatterns": ["**/dist/**", "playwright/**"] } diff --git a/.github/workflows/create-release-pr.yml b/.github/workflows/create-release-pr.yml index 798f79409b..cbf2e1c972 100644 --- a/.github/workflows/create-release-pr.yml +++ b/.github/workflows/create-release-pr.yml @@ -34,27 +34,15 @@ jobs: yarn global add lerna@5 lerna -v echo $(lerna version $BUMP --no-git-tag-version --exact --yes --no-private) - lerna add @100mslive/hms-video --peer --scope=@100mslive/hms-virtual-background --exact - lerna add @100mslive/react-sdk --scope=@100mslive/roomkit-react --exact - lerna add @100mslive/react-icons --scope=@100mslive/roomkit-react --exact - lerna add @100mslive/hms-virtual-background --scope=@100mslive/roomkit-react --exact - lerna add @100mslive/hls-player --scope=@100mslive/roomkit-react --exact + lerna add @100mslive/hms-video-store --peer --scope=@100mslive/hms-virtual-background --exact lerna add @100mslive/react-icons --scope=100ms-custom-app --exact lerna add @100mslive/roomkit-react --scope=100ms-custom-app --exact - lerna add @100mslive/roomkit-react --scope=100ms_edtech_template --exact - lerna add @100mslive/hls-player --scope=100ms_edtech_template --exact - lerna add @100mslive/hms-virtual-background --scope=100ms_edtech_template --exact - lerna add @100mslive/react-icons --scope=100ms_edtech_template --exact - lerna add @100mslive/react-sdk --scope=100ms_edtech_template --exact - name: Get current version id: version run: | - SDK_VERSION=$(cd packages/hms-video-web && node -p -e "require('./package.json').version") - echo $SDK_VERSION STORE_VERSION=$(cd packages/hms-video-store && node -p -e "require('./package.json').version") echo $STORE_VERSION - echo "::set-output name=sdk_version::$(echo $SDK_VERSION)" echo "::set-output name=store_version::$(echo $STORE_VERSION)" - uses: peter-evans/create-pull-request@v4 diff --git a/.github/workflows/deploy-beam-prod.yml b/.github/workflows/deploy-beam-prod.yml deleted file mode 100644 index f4c7f67438..0000000000 --- a/.github/workflows/deploy-beam-prod.yml +++ /dev/null @@ -1,135 +0,0 @@ -name: Deploy Beam Prod -on: - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - env: - REACT_APP_TILE_SHAPE: '1-1' - REACT_APP_THEME: 'dark' - REACT_APP_COLOR: '#2F80FF' - REACT_APP_LOGO: '' - REACT_APP_FONT: 'Roboto' - REACT_APP_POLICY_CONFIG: '' - REACT_APP_WEBINAR_PROPS: '{}' - REACT_APP_DEFAULT_APP_DETAILS: '{}' - ENABLE_ROOT_PATH_BUILD_CACHE: '1' - REACT_APP_PUSHER_APP_KEY: ${{ secrets.PUSHER_KEY }} - REACT_APP_AMBIENT_MUSIC: 'https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/Together+With+You.mp3' - REACT_APP_PUSHER_AUTHENDPOINT: 'https://whiteboard-server.vercel.app/api/pusher/auth' - REACT_APP_ZIPY_BLACKLIST: 'peakperformerapp.app.100ms.live,callrockethealth.app.100ms.live,buyume1.app.100ms.live,automation.app.100ms.live,juniorkoder.app.100ms.live,kluster.app.100ms.live,pankhuriapp.app.100ms.live,leancrop.app.100ms.live,routes2roots-class.app.100ms.live,liveholofy.app.100ms.live,ulesson.app.100ms.live,truyoga.app.100ms.live,livelink.app.100ms.live,indiaclan.app.100ms.live,slice_test.app.100ms.live,epitomeai.app.100ms.live,jkoder.app.100ms.live,huddleatjf.app.100ms.live,napo-academy.app.100ms.live,alineahealth-prd.app.100ms.live,tutordebbie.app.100ms.live,womensday.app.100ms.live,gaga-live1.app.100ms.live,mypandit.app.100ms.live,allo-prod.app.100ms.live,ganeshaspeaks.app.100ms.live' - REACT_APP_PORTRAIT_MODE_DOMAINS: 'whatmorelive-stage.app.100ms.live,arjun.app.100ms.live,koo.app.100ms.live,socialjawn.app.100ms.live' - REACT_APP_AUDIO_PLAYLIST: '[{"name":"Audio1","id":"audio1","metadata":{"description":"Artist1"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/audio1.mp3","type":"audio"},{"name":"Audio2","id":"audio2","metadata":{"description":"Artist2"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/audio2.mp3","type":"audio"},{"name":"Audio3","id":"audio3","metadata":{"description":"Artist3"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/audio3.mp3","type":"audio"},{"name":"Audio4","id":"audio4","metadata":{"description":"Artist4"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/audio4.mp3","type":"audio"}]' - REACT_APP_VIDEO_PLAYLIST: '[{"name":"100ms-360P","id":"video1","metadata":{"description":"100ms"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/100ms-360p.mp4","type":"video"},{"name":"100ms-720P","id":"video2","metadata":{"description":"100ms"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/100ms-720p.mp4","type":"video"},{"name":"Big Buck Bunny","id":"video3","metadata":{"description":"Bunny"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/video2.mp4","type":"video"}]' - REACT_APP_HEADLESS_JOIN: false - REACT_APP_ENABLE_STATS_FOR_NERDS: 'true' - REACT_APP_ENABLE_WHITEBOARD: 'true' - REACT_APP_PDFJS_IFRAME_URL: 'https://pdf-annotation.100ms.live/generic/web/viewer.html' - REACT_APP_ZIPY_KEY: ${{ secrets.PROD_ZIPY_KEY }} - REACT_APP_ENV: 'prod' - REACT_APP_ENABLE_BEAM_SPEAKERS_LOGGING: 'true' - - steps: - - name: log inputs - run: | - echo "env: prod, branch: ${{ github.ref_name }}" - - #prod app can only be deployed to from a branch starting with production in its name - - name: Validate branch - if: ${{ (!startsWith(github.ref_name, 'beam-production')) }} - run: exit 1 - - - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - with: - access_token: ${{ github.token }} - - - name: Checkout repo - uses: actions/checkout@v3 - - - name: Install packages - run: yarn install --frozen-lockfile - - - name: Build for Production - run: yarn build - - - name: 'Upload Build Artifact' - uses: actions/upload-artifact@v3 - with: - name: build-artifact - path: apps/100ms-custom-app/build - - deploy: - needs: build - runs-on: ubuntu-latest - - steps: - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }} - aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }} - aws-region: ${{ secrets.S3_BUCKET_REGION }} - - - name: Download Build artifact - uses: actions/download-artifact@v3 - with: - name: build-artifact - path: build - - - name: Deploy to Staging - env: - BUCKET: ${{ secrets.S3_BEAM_BUCKET_STAGING }} - # upload static folder first and then upload the rest to ensure index.html assets are all present - run: | - aws s3 sync ./build s3://$BUCKET --exclude "index.html" - aws s3 sync ./build s3://$BUCKET --include "index.html" - - deploy-prod: - environment: - name: ProductionWithPermissions - needs: deploy - runs-on: ubuntu-latest - - steps: - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }} - aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }} - aws-region: ${{ secrets.S3_BUCKET_REGION }} - - - name: Download Build artifact - uses: actions/download-artifact@v3 - with: - name: build-artifact - path: build - - - name: Deploy to Production - env: - BUCKET: ${{ secrets.S3_BEAM_BUCKET_PROD }} - # upload static folder first and then upload the rest to ensure index.html assets are all present - run: | - aws s3 sync ./build s3://$BUCKET --exclude "index.html" - aws s3 sync ./build s3://$BUCKET --include "index.html" - - - name: Notify slack success - if: success() - env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_DEPLOY_BOT_TOKEN }} - uses: voxmedia/github-action-slack-notify-build@v1 - with: - channel_id: ${{ secrets.SLACK_DEPLOY_PROD_CHANNEL_ID }} - status: Beam deploy successful - color: good - - - name: Notify slack fail - if: failure() - env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_DEPLOY_BOT_TOKEN }} - uses: voxmedia/github-action-slack-notify-build@v1 - with: - channel_id: ${{ secrets.SLACK_DEPLOY_PROD_CHANNEL_ID }} - status: Beam deploy failed - color: danger diff --git a/.github/workflows/deploy-beam-qa.yml b/.github/workflows/deploy-beam-qa.yml deleted file mode 100644 index 46ccac4a1b..0000000000 --- a/.github/workflows/deploy-beam-qa.yml +++ /dev/null @@ -1,109 +0,0 @@ -name: Deploy Beam QA -on: - workflow_dispatch: - push: - branches: - - beam-main - paths-ignore: - - 'cypress/**' - - 'playwright/**' - - 'internal-docs/**' - - '.github/**' - -jobs: - build: - runs-on: ubuntu-latest - env: - REACT_APP_TILE_SHAPE: '1-1' - REACT_APP_THEME: 'dark' - REACT_APP_COLOR: '#2F80FF' - REACT_APP_LOGO: '' - REACT_APP_FONT: 'Roboto' - REACT_APP_POLICY_CONFIG: '' - REACT_APP_WEBINAR_PROPS: '{}' - REACT_APP_DEFAULT_APP_DETAILS: '{}' - ENABLE_ROOT_PATH_BUILD_CACHE: '1' - REACT_APP_PUSHER_APP_KEY: ${{ secrets.PUSHER_KEY }} - REACT_APP_AMBIENT_MUSIC: 'https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/Together+With+You.mp3' - REACT_APP_PUSHER_AUTHENDPOINT: 'https://whiteboard-server.vercel.app/api/pusher/auth' - REACT_APP_ZIPY_BLACKLIST: 'peakperformerapp.app.100ms.live,callrockethealth.app.100ms.live,buyume1.app.100ms.live,automation.app.100ms.live,juniorkoder.app.100ms.live,qaroy1.qa-app.100ms.live,kluster.app.100ms.live,pankhuriapp.app.100ms.live,leancrop.app.100ms.live,routes2roots-class.app.100ms.live,liveholofy.app.100ms.live,ulesson.app.100ms.live,truyoga.app.100ms.live' - REACT_APP_PORTRAIT_MODE_DOMAINS: 'whatmorelive-stage.app.100ms.live,arjun.app.100ms.live,koo.app.100ms.live,socialjawn.app.100ms.live' - REACT_APP_AUDIO_PLAYLIST: '[{"name":"Audio1","id":"audio1","metadata":{"description":"Artist1"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/audio1.mp3","type":"audio"},{"name":"Audio2","id":"audio2","metadata":{"description":"Artist2"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/audio2.mp3","type":"audio"},{"name":"Audio3","id":"audio3","metadata":{"description":"Artist3"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/audio3.mp3","type":"audio"},{"name":"Audio4","id":"audio4","metadata":{"description":"Artist4"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/audio4.mp3","type":"audio"}]' - REACT_APP_VIDEO_PLAYLIST: '[{"name":"100ms-360P","id":"video1","metadata":{"description":"100ms"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/100ms-360p.mp4","type":"video"},{"name":"100ms-720P","id":"video2","metadata":{"description":"100ms"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/100ms-720p.mp4","type":"video"},{"name":"Big Buck Bunny","id":"video3","metadata":{"description":"Bunny"},"url":"https://d2qi07yyjujoxr.cloudfront.net/webapp/playlist/video2.mp4","type":"video"}]' - REACT_APP_HEADLESS_JOIN: false - REACT_APP_ENABLE_STATS_FOR_NERDS: 'true' - REACT_APP_ENABLE_WHITEBOARD: 'true' - REACT_APP_ENV: 'qa' - REACT_APP_ZIPY_KEY: ${{ secrets.ZIPY_KEY }} - REACT_APP_ENABLE_BEAM_SPEAKERS_LOGGING: 'true' - REACT_APP_ENABLE_TRANSCRIPTION: 'true' - REACT_APP_TRANSCRIPTION_PUSHER_AUTHENDPOINT: 'https://whiteboard-server.vercel.app/api/pusher/auth' - REACT_APP_TRANSCRIPTION_PUSHER_APP_KEY: ${{ secrets.PUSHER_KEY }} - REACT_APP_DYNAMIC_STT_TOKEN_GENERATION_ENDPOINT: ${{ secrets.ASSEMBLY_AI_TOKEN_ENDPOINT }} - REACT_APP_TRANSCRIPTION_ROOM_ID: '644df1027cebfa471fcc52fd' - REACT_APP_PDFJS_IFRAME_URL: 'https://pdf-annotation-qa.100ms.live/generic/web/viewer.html' - - steps: - - name: log inputs - run: | - echo "env: qa, branch: ${{ github.ref_name }}" - - - name: Validate branch - if: ${{ (!startsWith(github.ref_name, 'beam-main')) }} - run: exit 1 - - - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - with: - access_token: ${{ github.token }} - - - name: Checkout repo - uses: actions/checkout@v3 - - - name: yarn packages cache - uses: actions/cache@v3 - with: - path: | - node_modules - */*/node_modules - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - - name: Install packages - run: yarn install --frozen-lockfile - - - name: Build for QA - run: yarn build - - - name: 'Upload Build Artifact' - uses: actions/upload-artifact@v3 - with: - name: build-artifact - path: apps/100ms-custom-app/build - - deploy: - needs: build - runs-on: ubuntu-latest - - steps: - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }} - aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }} - aws-region: ${{ secrets.S3_BUCKET_REGION }} - - - name: Download Build artifact - uses: actions/download-artifact@v3 - with: - name: build-artifact - path: build - - - name: Deploy to QA - env: - BUCKET: ${{ secrets.S3_BEAM_BUCKET }} - # upload static folder first and then upload the rest to ensure index.html assets are all present - run: | - aws s3 sync ./build s3://$BUCKET --exclude "index.html" - aws s3 sync ./build s3://$BUCKET --include "index.html" diff --git a/.github/workflows/push-to-webapp.yml b/.github/workflows/push-to-webapp.yml deleted file mode 100644 index e82636d532..0000000000 --- a/.github/workflows/push-to-webapp.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Push to webapp -on: - push: - branches: - - main - -jobs: - push-to-webapp: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - token: ${{ secrets.DOCKER_GIT_TOKEN }} - fetch-depth: 0 - ref: main - - run: | - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git config user.name "github-actions[bot]" - git remote add webapp https://github.com/100mslive/100ms-web.git - git remote update - git subtree push --prefix=apps/100ms-web webapp sync-webapp diff --git a/.github/workflows/slash-command.yml b/.github/workflows/slash-command.yml deleted file mode 100644 index 322020c888..0000000000 --- a/.github/workflows/slash-command.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Slash Command Dispatch -on: - issue_comment: - types: [created] -jobs: - slashCommandDispatch: - runs-on: ubuntu-latest - steps: - - name: Slash Command Dispatch - uses: peter-evans/slash-command-dispatch@v2 - with: - token: ${{ secrets.DOCKER_GIT_TOKEN }} - commands: | - version - publish diff --git a/.github/workflows/update-version.yml b/.github/workflows/update-version.yml deleted file mode 100644 index 1c8048c4df..0000000000 --- a/.github/workflows/update-version.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Size and Version Update -on: - pull_request: - branches: - - main - -jobs: - changes: - runs-on: ubuntu-latest - if: github.event.pull_request.draft != true - outputs: - hms-video-web: ${{ steps.filter.outputs.hms-video-web }} - hms-video-store: ${{ steps.filter.outputs.hms-video-store }} - react-sdk: ${{ steps.filter.outputs.react-sdk }} - roomkit-react: ${{ steps.filter.outputs.roomkit-react }} - react-icons: ${{ steps.filter.outputs.react-icons }} - steps: - - uses: actions/checkout@v2 - - uses: dorny/paths-filter@v2 - id: filter - with: - filters: | - hms-video-web: - - 'packages/hms-video-web/src/**/!(*.test.ts)' - hms-video-store: - - 'packages/hms-video-store/src/!(test)**/!(*.test.ts)' - react-sdk: - - 'packages/react-sdk/src/**' - roomkit-react: - - 'packages/roomkit-react/src/**' - react-icons: - - 'packages/react-icons/src/**' - hls-stats: - - 'packages/hls-stats/src/**' - hls-player: - - 'packages/hls-player/src/**' - - size: - runs-on: ubuntu-latest - needs: changes - if: needs.changes.outputs.hms-video-web == 'true' || needs.changes.outputs.hms-video-store == 'true' || needs.changes.outputs.roomkit-react == 'true' - steps: - - uses: actions/checkout@v1 - - name: Check packages size - uses: andresz1/size-limit-action@v1 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - build_script: build --no-private diff --git a/README.md b/README.md index fe15a5e990..d4c8231c49 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Web sdks -This monorepo will contain all packages related to core sdk and store. +This monorepo contains all the packages required to integrate 100ms on web ## Before doing any code change please take time to go through the [guidelines](./DEVELOPER.MD) line by line. @@ -8,7 +8,7 @@ This monorepo will contain all packages related to core sdk and store. To setup locally, install lerna globally -`npm install -g lerna` +`npm install -g lerna@5` Clone the repo locally and run yarn install @@ -42,6 +42,8 @@ yarn install ### Lint +Runs eslint across all packages + ``` yarn lint ``` @@ -52,96 +54,27 @@ Run whatever things you're changing in below in different terminal instances. Fo the folder directly and run `yarn start`. ``` -# for webapp -> yarn app - -# for hms-video-web -> yarn sdk - # for hms-video-store > yarn store # for react-sdk > yarn reactsdk -``` - -> Note: run yarn start in sdk first and then in store - -### Custom App in Dev +# for roomkit-react +> yarn prebuilt -This is useful when you want to see changes from `100ms-web` app being reflected in custom app in dev. Run `yarn dev` in `100ms-web` & `yarn start` in `custom-app` +``` ### Update a packages version Run [this](https://github.com/100mslive/web-sdks/actions/workflows/create-release-pr.yml) to update all versions. -#### Updating single ones - -Go to the path of the package ex: cd packages/hms-video-web and run the following command -`npm version prerelease --preid=alpha --git-tag-version=false` - -To update the same in dependent packages run -`lerna add @100mslive/hms-video --scope=@100mslive/hms-video-store --exact` ### Publishing Alpha/Experimental versions -To publish an alpha/experimental from your `experimental` branch, run the '[Create Release PR](https://github.com/100mslive/web-sdks/actions/workflows/publish.yml)' action on the `experimental` branch. +To publish an alpha/experimental from your `experimental` branch, run the '[Create Release PR](https://github.com/100mslive/web-sdks/actions/workflows/publish.yml)' action on the `experimental` branch with `prerelease` as input. This bumps the version of all the packages and creates a PR against your `experimental` branch. -Merge this PR into your `experimental` branch and run the 'Publish Packages' on your branch to publish the packages. - -### Syncing with webapp - -check the existing remotes with `git remote -v`; -if there is only one remote, add webapp as a new remote. -`git remote add -f webapp https://github.com/100mslive/100ms-web.git` - -## push to webapp - -`git subtree push --prefix=apps/100ms-web webapp sync-webapp` - -## pull from webapp - -`git subtree pull --prefix=apps/100ms-web webapp main` - -## Adding a new repo into the monorepo - -**To add an existing repo** - -`git clone ` - -- if commit history is not need directly copy the files. - `cd repo` - `rm -rf .git` - `git rm -r --cached` - `cp -r repo path-to-web-sdks/packages` -- if commit history is needed - `lerna import path-to-repo --flatten --preserve-commit` (to be run at root level) - -**To Create a new repo** - -Follow the documentation [here](https://github.com/lerna/lerna/tree/main/commands/create#readme) - -> Note: Don't forget to update mapping in `scripts/constants.js`. Also update`lernaCommands` in `versioning.js` depending on the new repo's dependencies and dependents - -## Setup Cypress - -- Create a .env file to the root folder and add the following variables. - -``` -CYPRESS_TOKEN_ENDPOINT=https://qa-in2.100ms.live/hmsapi/ravi.qa-app.100ms.live/api/token -CYPRESS_ROOM_ID=60f26ab342a997a1ff49c5c2 -CYPRESS_ROLE=student -CYPRESS_API_ENV=qa -CYPRESS_INIT_ENDPOINT=https://qa-init.100ms.live/init -``` - -- Run `yarn cypress:open` at the root level to open the cypress app. - -## Tips and Tricks +Merge this PR into your `experimental` branch and run the `Publish Packages` workflow on your branch with `alpha` as input to publish the packages. -- `window.toggleUiTheme()` in console to switch between dark and light themes -- Set directJoin to true in PreviewScreen.jsx to not have to click on join after - page reload. diff --git a/apps/100ms-custom-app/package.json b/apps/100ms-custom-app/package.json index 3312a74db9..655bfb968d 100644 --- a/apps/100ms-custom-app/package.json +++ b/apps/100ms-custom-app/package.json @@ -3,8 +3,8 @@ "version": "0.1.0", "private": true, "dependencies": { - "@100mslive/react-icons": "0.8.29-alpha.1", - "@100mslive/roomkit-react": "0.1.20-alpha.1", + "@100mslive/react-icons": "0.9.0", + "@100mslive/roomkit-react": "0.2.0", "axios": "^0.21.1", "js-cookies": "^1.0.4", "lodash.merge": "^4.6.2", @@ -16,7 +16,6 @@ }, "scripts": { "start": "webpack serve", - "prebuild": "cd ../100ms-web && yarn esbuild", "build": "webpack --node-env production", "lint": "eslint -c .eslintrc --no-error-on-unmatched-pattern src --ext .js --ext jsx", "lint:fix": "yarn lint --fix", diff --git a/apps/100ms-custom-app/src/App.jsx b/apps/100ms-custom-app/src/App.jsx index 6580393ad6..9646b2d33c 100644 --- a/apps/100ms-custom-app/src/App.jsx +++ b/apps/100ms-custom-app/src/App.jsx @@ -22,6 +22,7 @@ const App = () => { const { roomId, role } = getRoomIdRoleFromUrl(); const { overrideLayout, isHeadless } = useOverridePrebuiltLayout(); const paramUserName = useSearchParam('name'); + const paramUserId = useSearchParam('userId'); const hmsPrebuiltRef = useRef(); useEffect(() => { @@ -85,6 +86,7 @@ const App = () => { screens={overrideLayout ? overrideLayout : undefined} options={{ userName: isHeadless && !paramUserName ? 'Beam' : paramUserName, + userId: paramUserId, endpoints: { tokenByRoomCode: process.env.REACT_APP_TOKEN_BY_ROOM_CODE_ENDPOINT, diff --git a/apps/100ms-web/.dockerignore b/apps/100ms-web/.dockerignore deleted file mode 100644 index b512c09d47..0000000000 --- a/apps/100ms-web/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -node_modules \ No newline at end of file diff --git a/apps/100ms-web/.eslintrc b/apps/100ms-web/.eslintrc deleted file mode 100644 index 02cb786564..0000000000 --- a/apps/100ms-web/.eslintrc +++ /dev/null @@ -1,81 +0,0 @@ -{ - "extends": [ - "eslint:recommended", - "plugin:import/recommended", - "react-app", - "react-app/jest" - ], - "plugins": ["prettier", "simple-import-sort"], - "rules": { - "no-unused-vars": [ - "error", - { - "vars": "all", - "args": "none", - "ignoreRestSiblings": false - } - ], - "react/jsx-curly-brace-presence": [ - 2, - { - "props": "never" - } - ], - "react/self-closing-comp": [ - "error", - { - "component": true, - "html": false - } - ], - "prettier/prettier": [ - "error", - { - "endOfLine": "auto" // This is need to handle different end-of-line in windows/mac - } - ], - "import/first": "error", - "import/no-duplicates": "error", - "simple-import-sort/imports": [ - "error", - { - "groups": [ - [ - // Packages `react` related packages come first. - "^react", - "^@?\\w", - // Internal packages. - "^@100mslive/react-sdk", - "^@100mslive/react-icons", - "^@100mslive/roomkit-react", - // Side effect imports. - "^\\u0000", - - "(components)", - // Other relative imports. Put same-folder imports and `.`. - "^\\./(?=.*/)(?!/?$)", - "^\\.(?!/?$)", - "^\\./?$", - "(plugins)", - "(components)?(.*)(/use.*)", - ".*(hooks)", - "(common)", - "(services)", - "(utils)", - "(constants)", - // Style imports. - "^.+\\.?(css)$" - ] - ] - } - ] - }, - "settings": { - "import/resolver": { - "node": { - "extensions": [".js", ".jsx"] - } - } - }, - "ignorePatterns": ["src/*.css", "src/images/*"] -} diff --git a/apps/100ms-web/.github/ISSUE_TEMPLATE/bug_report.md b/apps/100ms-web/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index dd84ea7824..0000000000 --- a/apps/100ms-web/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] - -**Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] - -**Additional context** -Add any other context about the problem here. diff --git a/apps/100ms-web/.github/ISSUE_TEMPLATE/feature_request.md b/apps/100ms-web/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index bbcbbe7d61..0000000000 --- a/apps/100ms-web/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/apps/100ms-web/.github/workflows/build.yml b/apps/100ms-web/.github/workflows/build.yml deleted file mode 100644 index 252c2fd2d3..0000000000 --- a/apps/100ms-web/.github/workflows/build.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Build -on: - push: - branches: - - main - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: 14 - registry-url: https://registry.npmjs.org/ - - - name: Install packages - run: yarn install - - - name: Build - run: yarn build diff --git a/apps/100ms-web/.github/workflows/codeql-analysis.yml b/apps/100ms-web/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 0df356e274..0000000000 --- a/apps/100ms-web/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,71 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ main, develop, infra-test ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ main ] - schedule: - - cron: '31 4 * * 4' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'javascript' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] - # Learn more: - # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 diff --git a/apps/100ms-web/.github/workflows/npm-update.yml b/apps/100ms-web/.github/workflows/npm-update.yml deleted file mode 100644 index dd75803dbe..0000000000 --- a/apps/100ms-web/.github/workflows/npm-update.yml +++ /dev/null @@ -1,25 +0,0 @@ -on: - workflow_dispatch: - inputs: - target: - description: 'target-newest/latest' - required: true - default: 'newest' - -name: Update sdk packages -jobs: - release: - name: Update sdk npm packages - runs-on: ubuntu-latest - steps: - - name: Update sdk packages - uses: technote-space/create-pr-action@v2 - with: - EXECUTE_COMMANDS: | - npx --yes npm-check-updates --upgrade --packageManager yarn --filter "/@100mslive.*/" --target ${{ github.event.inputs.target }} - yarn install - COMMIT_MESSAGE: 'chore: update sdk npm dependencies' - COMMIT_NAME: 'github-actions[bot]' - COMMIT_EMAIL: '41898282+github-actions[bot]@users.noreply.github.com' - PR_BRANCH_NAME: 'chore-sdk-update-${PR_ID}' - PR_TITLE: 'chore: update sdk npm dependencies' \ No newline at end of file diff --git a/apps/100ms-web/.gitignore b/apps/100ms-web/.gitignore deleted file mode 100644 index 741fe30a4e..0000000000 --- a/apps/100ms-web/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -.vscode -.cache -.idea/ -hs_*.log -.env \ No newline at end of file diff --git a/apps/100ms-web/.prettierignore b/apps/100ms-web/.prettierignore deleted file mode 100644 index 1bd048240a..0000000000 --- a/apps/100ms-web/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -src/images/* \ No newline at end of file diff --git a/apps/100ms-web/.prettierrc b/apps/100ms-web/.prettierrc deleted file mode 100644 index a472579a9a..0000000000 --- a/apps/100ms-web/.prettierrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "printWidth": 80, - "tabWidth": 2, - "trailingComma": "es5", - "semi": true, - "singleQuote": false, - "arrowParens": "avoid" -} diff --git a/apps/100ms-web/CODEOWNERS b/apps/100ms-web/CODEOWNERS deleted file mode 100644 index dced0be276..0000000000 --- a/apps/100ms-web/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @triptu @eswarclynn @raviteja83 diff --git a/apps/100ms-web/Dockerfile b/apps/100ms-web/Dockerfile deleted file mode 100644 index 4b8220041a..0000000000 --- a/apps/100ms-web/Dockerfile +++ /dev/null @@ -1,46 +0,0 @@ - -FROM node:18-alpine AS builder -# Add a work directory -WORKDIR /100ms-web - -# Copy app files -COPY . . - -RUN yarn install - -ENV NODE_ENV production - -# set environment variables. -# These are the bare minimum needed for running -# the app. Feel free to add more as per your needs. -ENV REACT_APP_TILE_SHAPE=1-1 -ENV REACT_APP_THEME=dark -ENV REACT_APP_COLOR=#2F80FF -ENV REACT_APP_LOGO='provide your logo img url here' -ENV REACT_APP_FONT=Inter -ENV REACT_APP_ENABLE_HLS_QUALITY_LVL='true' -ENV REACT_APP_TOKEN_GENERATION_ENDPOINT='' -ENV REACT_APP_ENV=prod -ENV REACT_APP_LOGROCKET_ID='' -ENV REACT_APP_POLICY_CONFIG='' -ENV REACT_APP_DEFAULT_APP_DETAILS='{}' -ENV REACT_APP_ENABLE_STATS_FOR_NERDS='false' -ENV REACT_APP_PUSHER_APP_KEY='' -ENV REACT_APP_PUSHER_AUTHENDPOINT='' -ENV REACT_APP_HEADLESS_JOIN='false' - -# Build the app -RUN yarn build - -# Bundle static assets with nginx -FROM nginx:1.23.1-alpine AS production -# Copy built assets from builder -COPY --from=builder /100ms-web/build /usr/share/nginx/html - -# Add your nginx.conf -COPY nginx.conf /etc/nginx/conf.d/default.conf -# Expose port -EXPOSE 80 -# Start nginx -CMD ["nginx", "-g", "daemon off;"] - diff --git a/apps/100ms-web/Dockerfile.dev b/apps/100ms-web/Dockerfile.dev deleted file mode 100644 index 19b13ce8dd..0000000000 --- a/apps/100ms-web/Dockerfile.dev +++ /dev/null @@ -1,13 +0,0 @@ -FROM node:18-alpine - -WORKDIR /100ms-web - -COPY . . - -RUN yarn install - -ENV PORT=8080 - -EXPOSE 8080 - -CMD [ "yarn", "start" ] diff --git a/apps/100ms-web/LICENSE b/apps/100ms-web/LICENSE deleted file mode 100644 index b5d5feaab1..0000000000 --- a/apps/100ms-web/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2021 100ms - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/apps/100ms-web/README.md b/apps/100ms-web/README.md deleted file mode 100644 index 217c81115b..0000000000 --- a/apps/100ms-web/README.md +++ /dev/null @@ -1,22 +0,0 @@ -

- - - -

- - -# 100ms 2.0 Sample React App - -[![Documentation](https://img.shields.io/badge/Read-Documentation-blue)](https://docs.100ms.live/javascript/v2/foundation/basics) -[![Discord](https://img.shields.io/badge/Community-Join%20on%20Discord-blue)](https://discord.gg/F8cNgbjSaQ) -[![Email](https://img.shields.io/badge/Contact-Know%20More-blue)](mailto:founders@100ms.live) - -This is an example React app to demo [100ms' React SDK](https://www.npmjs.com/package/@100mslive/react-sdk). -Not using React? Find the [Javascript Quickstart here](https://docs.100ms.live/javascript/v2/guides/javascript-quickstart). - -# Table of Contents -* [Getting Started](https://github.com/100mslive/100ms-web/wiki/Getting-Started) -* [Creating and Joining a Room](https://github.com/100mslive/100ms-web/wiki/Creating-and-joining-a-room) -* [Customizing your app](https://github.com/100mslive/100ms-web/wiki/Customizing-your-app) -* [Building and deployment](https://github.com/100mslive/100ms-web/wiki/Building-and-deployment) -* [Further Reading](https://github.com/100mslive/100ms-web/wiki/Further-reading) \ No newline at end of file diff --git a/apps/100ms-web/app.json b/apps/100ms-web/app.json deleted file mode 100644 index 5a2bc1d75a..0000000000 --- a/apps/100ms-web/app.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "100ms conference app", - "website": "https://100ms.live", - "env": { - "REACT_APP_TILE_SHAPE": { - "description": "Video Tile Shape, takes values of format 1-2" - }, - "REACT_APP_THEME": { - "description": "Light or Dark, takes value Ligth|Dark" - }, - "REACT_APP_COLOR": { - "description": "Brand Color, takes hex value" - }, - "REACT_APP_LOGO": { - "description": "Brand Logo, Take any image url" - }, - "REACT_APP_FONT": { - "description": "Font to be used, Takes value Inter|Roboto|Lato|OpenSans|MontSerrat|IBMPlexSans" - }, - "REACT_APP_SHOW_CHAT": { - "description": "Allow Chat or not, Takes value True|False" - }, - "REACT_APP_SHOW_SCREENSHARE": { - "description": "Allow Screenshare or not , Takes value True|False" - }, - "REACT_APP_VIDEO_AVATAR": { - "description": "Takes value None|Initial" - }, - "REACT_APP_TOKEN_GENERATION_ENDPOINT": { - "description": "API url where your 100ms token generation service is hosted" - }, - "REACT_APP_ENV": { - "description": "Internal env variable for 100ms" - } - } -} diff --git a/apps/100ms-web/docker-compose.yml b/apps/100ms-web/docker-compose.yml deleted file mode 100644 index bc9fc5e3e3..0000000000 --- a/apps/100ms-web/docker-compose.yml +++ /dev/null @@ -1,11 +0,0 @@ -version: "3.9" - -services: - app: - container_name: 100ms-web-prod - image: 100ms-web-prod - ports: - - 80:80 - build: - context: . - target: production \ No newline at end of file diff --git a/apps/100ms-web/example.env b/apps/100ms-web/example.env deleted file mode 100644 index 709532df86..0000000000 --- a/apps/100ms-web/example.env +++ /dev/null @@ -1,18 +0,0 @@ -REACT_APP_TILE_SHAPE=1-1 -REACT_APP_THEME=dark -REACT_APP_COLOR='#2F80FF' -REACT_APP_LOGO= -REACT_APP_FONT=Roboto -REACT_APP_TOKEN_GENERATION_ENDPOINT= -REACT_APP_ENV=prod -REACT_APP_ENABLE_HLS_QUALITY_LVL='true' -REACT_APP_LOGROCKET_ID= -REACT_APP_POLICY_CONFIG='' -REACT_APP_DEFAULT_APP_DETAILS='{}' -REACT_APP_ENABLE_STATS_FOR_NERDS='false' -REACT_APP_PUSHER_APP_KEY='' -REACT_APP_PUSHER_AUTHENDPOINT='' -REACT_APP_PUSHER_CLUSTER='' -REACT_APP_HEADLESS_JOIN='false' -REACT_APP_ZIPY_KEY= -REACT_APP_TITLE='100ms App' diff --git a/apps/100ms-web/nginx.conf b/apps/100ms-web/nginx.conf deleted file mode 100644 index fa7507d9f8..0000000000 --- a/apps/100ms-web/nginx.conf +++ /dev/null @@ -1,10 +0,0 @@ -server { - listen 80; - #listen 443 ssl; - - location / { - root /usr/share/nginx/html/; - include /etc/nginx/mime.types; - try_files $uri $uri/ /index.html; - } -} \ No newline at end of file diff --git a/apps/100ms-web/package.json b/apps/100ms-web/package.json deleted file mode 100644 index 74a6bb86f8..0000000000 --- a/apps/100ms-web/package.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "name": "100ms_edtech_template", - "version": "0.1.4", - "private": true, - "main": "dist/index.cjs.js", - "module": "dist/index.js", - "files": [ - "dist", - "src" - ], - "dependencies": { - "@100mslive/hls-player": "0.1.29-alpha.1", - "@100mslive/hms-virtual-background": "1.11.29-alpha.1", - "@100mslive/react-icons": "0.8.29-alpha.1", - "@100mslive/react-sdk": "0.8.29-alpha.1", - "@100mslive/roomkit-react": "0.1.20-alpha.1", - "@emoji-mart/data": "^1.0.6", - "@emoji-mart/react": "^1.0.1", - "@tldraw/tldraw": "^1.18.4", - "emoji-mart": "^5.2.2", - "eventemitter2": "^6.4.7", - "js-confetti": "^0.10.2", - "mobx": "^6.3.12", - "pusher-js": "^7.0.3", - "react": "^18.1.0", - "react-dom": "^18.1.0", - "react-draggable": "^4.4.5", - "react-intersection-observer": "^9.4.3", - "react-router-dom": "^6.3.0", - "react-use": "^17.4.0", - "react-virtualized-auto-sizer": "^1.0.7", - "react-window": "^1.8.7", - "recordrtc": "^5.6.2", - "screenfull": "^5.1.0", - "uuid": "^8.3.2", - "web-vitals": "^1.0.1", - "worker-timers": "^7.0.40", - "zipyai": "^1.3.24" - }, - "scripts": { - "prebuild": "rm -rf build", - "build": "webpack --node-env production", - "start": "webpack serve", - "esbuild": "node ../../scripts/build-webapp", - "dev": "node ../../scripts/dev-webapp", - "format": "prettier -w src", - "lint": "eslint -c ./.eslintrc --no-error-on-unmatched-pattern src --ext .js --ext jsx", - "lint:fix": "yarn lint --fix" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - }, - "devDependencies": { - "@babel/eslint-parser": "^7.17.0", - "autoprefixer": "^10.4.2", - "copy-webpack-plugin": "^10.2.1", - "css-loader": "^6.5.1", - "cssnano": "^5.0.15", - "dotenv": "^14.2.0", - "esbuild-loader": "^3.0.0", - "esbuild-plugin-postcss2": "0.1.1", - "eslint": "^8.9.0", - "eslint-config-react-app": "^7.0.0", - "eslint-plugin-import": "^2.25.4", - "eslint-plugin-prettier": "^4.0.0", - "eslint-plugin-simple-import-sort": "^8.0.0", - "eslint-webpack-plugin": "^3.1.1", - "html-webpack-plugin": "^5.5.0", - "mini-css-extract-plugin": "^2.5.2", - "postcss": "^8.4.5", - "postcss-loader": "^6.2.1", - "prettier": "^2.5.1", - "source-map-loader": "^3.0.1", - "terser-webpack-plugin": "^5.3.1", - "webpack": "^5.76.0", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.7.4", - "webpack-manifest-plugin": "^4.1.1" - }, - "resolutions": { - "loader-utils": "^2.0.4" - } -} diff --git a/apps/100ms-web/postcss.config.js b/apps/100ms-web/postcss.config.js deleted file mode 100644 index df1774888a..0000000000 --- a/apps/100ms-web/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - autoprefixer: {}, - cssnano: {}, - }, -}; diff --git a/apps/100ms-web/public/.well-known/apple-app-site-association b/apps/100ms-web/public/.well-known/apple-app-site-association deleted file mode 100644 index dfe30d0896..0000000000 --- a/apps/100ms-web/public/.well-known/apple-app-site-association +++ /dev/null @@ -1,21 +0,0 @@ -{ - "applinks": { - "apps": [ - - ], - "details": [ - { - "appID": "5N85PP82A9.live.100ms.videoapp", - "paths": [ - "*" - ] - }, - { - "appID": "5N85PP82A9.com.brytecam.app", - "paths": [ - "*" - ] - } - ] - } -} \ No newline at end of file diff --git a/apps/100ms-web/public/_redirects b/apps/100ms-web/public/_redirects deleted file mode 100644 index 50a463356b..0000000000 --- a/apps/100ms-web/public/_redirects +++ /dev/null @@ -1 +0,0 @@ -/* /index.html 200 \ No newline at end of file diff --git a/apps/100ms-web/public/favicon.ico b/apps/100ms-web/public/favicon.ico deleted file mode 100644 index 3ff2e3ea23..0000000000 Binary files a/apps/100ms-web/public/favicon.ico and /dev/null differ diff --git a/apps/100ms-web/public/index.html b/apps/100ms-web/public/index.html deleted file mode 100644 index 75888e509c..0000000000 --- a/apps/100ms-web/public/index.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - 100ms Teacher App - - - -
- - - diff --git a/apps/100ms-web/public/logo192.png b/apps/100ms-web/public/logo192.png deleted file mode 100644 index fc44b0a379..0000000000 Binary files a/apps/100ms-web/public/logo192.png and /dev/null differ diff --git a/apps/100ms-web/public/logo512.png b/apps/100ms-web/public/logo512.png deleted file mode 100644 index a4e47a6545..0000000000 Binary files a/apps/100ms-web/public/logo512.png and /dev/null differ diff --git a/apps/100ms-web/public/manifest.json b/apps/100ms-web/public/manifest.json deleted file mode 100644 index 080d6c77ac..0000000000 --- a/apps/100ms-web/public/manifest.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" -} diff --git a/apps/100ms-web/public/robots.txt b/apps/100ms-web/public/robots.txt deleted file mode 100644 index e9e57dc4d4..0000000000 --- a/apps/100ms-web/public/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Disallow: diff --git a/apps/100ms-web/public/share-audio.png b/apps/100ms-web/public/share-audio.png deleted file mode 100644 index de8b1ee084..0000000000 Binary files a/apps/100ms-web/public/share-audio.png and /dev/null differ diff --git a/apps/100ms-web/public/test-audio.wav b/apps/100ms-web/public/test-audio.wav deleted file mode 100644 index e18b28d032..0000000000 Binary files a/apps/100ms-web/public/test-audio.wav and /dev/null differ diff --git a/apps/100ms-web/src/App.js b/apps/100ms-web/src/App.js deleted file mode 100644 index 45e477a443..0000000000 --- a/apps/100ms-web/src/App.js +++ /dev/null @@ -1,279 +0,0 @@ -import React, { Suspense, useEffect } from "react"; -import { - BrowserRouter as Router, - Navigate, - Route, - Routes, - useParams, -} from "react-router-dom"; -import { - HMSRoomProvider, - selectIsConnectedToRoom, - useHMSActions, - useHMSStore, -} from "@100mslive/react-sdk"; -import { Box, globalStyles, HMSThemeProvider } from "@100mslive/roomkit-react"; -import { AppData } from "./components/AppData/AppData.jsx"; -import { BeamSpeakerLabelsLogging } from "./components/AudioLevel/BeamSpeakerLabelsLogging"; -import { ErrorBoundary } from "./components/ErrorBoundary"; -import ErrorPage from "./components/ErrorPage"; -import FullPageProgress from "./components/FullPageProgress"; -import { Init } from "./components/init/Init"; -import { KeyboardHandler } from "./components/Input/KeyboardInputManager"; -import { Notifications } from "./components/Notifications"; -import PostLeave from "./components/PostLeave"; -import { ToastContainer } from "./components/Toast/ToastContainer"; -import { palette } from "./theme.js"; -import { Confetti } from "./plugins/confetti"; -import { FlyingEmoji } from "./plugins/FlyingEmoji.jsx"; -import { RemoteStopScreenshare } from "./plugins/RemoteStopScreenshare"; -import { getRoutePrefix, shadeColor } from "./common/utils"; -import { FeatureFlags } from "./services/FeatureFlags"; - -const Conference = React.lazy(() => import("./components/conference")); -const PreviewScreen = React.lazy(() => import("./components/PreviewScreen")); - -const defaultTokenEndpoint = process.env.REACT_APP_TOKEN_GENERATION_ENDPOINT; -const envPolicyConfig = JSON.parse(process.env.REACT_APP_POLICY_CONFIG || "{}"); - -let appName; -if (window.location.host.includes("localhost")) { - appName = "localhost"; -} else { - appName = window.location.host.split(".")[0]; -} - -document.title = - process.env.REACT_APP_TITLE || `${appName}'s ${document.title}`; - -// TODO: remove now that there are options to change to portrait -const getAspectRatio = ({ width, height }) => { - const host = process.env.REACT_APP_HOST_NAME || window.location.hostname; - const portraitDomains = ( - process.env.REACT_APP_PORTRAIT_MODE_DOMAINS || "" - ).split(","); - if (portraitDomains.includes(host) && width > height) { - return { width: height, height: width }; - } - return { width, height }; -}; - -export function EdtechComponent({ - tokenEndpoint = defaultTokenEndpoint, - themeConfig: { - aspectRatio = "1-1", - font = "Roboto", - color = "#2F80FF", - theme = "dark", - logo = "", - headerPresent = "false", - metadata = "", - }, - policyConfig = envPolicyConfig, - getDetails = () => {}, - authTokenByRoomCodeEndpoint = "", -}) { - const { 0: width, 1: height } = aspectRatio - .split("-") - .map(el => parseInt(el)); - globalStyles(); - - return ( - - - - - - - - - - - - - ); -} - -const RedirectToPreview = ({ getDetails }) => { - const { roomId, role } = useParams(); - useEffect(() => { - getDetails(); - }, [roomId]); //eslint-disable-line - - console.error({ roomId, role }); - - if (!roomId && !role) { - return ; - } - if (!roomId) { - return ; - } - if (["streaming", "preview", "meeting", "leave"].includes(roomId) && !role) { - return ; - } - - return ( - - ); -}; - -const RouteList = ({ getDetails, authTokenByRoomCodeEndpoint }) => { - return ( - - - }> - - - } - /> - }> - - - } - /> - - - }> - - - } - /> - }> - - - } - /> - - - } /> - } /> - - } - /> - } - /> - } /> - - ); -}; - -const BackSwipe = () => { - const isConnectedToRoom = useHMSStore(selectIsConnectedToRoom); - const hmsActions = useHMSActions(); - useEffect(() => { - const onRouteLeave = async () => { - if (isConnectedToRoom) { - await hmsActions.leave(); - } - }; - window.addEventListener("popstate", onRouteLeave); - return () => { - window.removeEventListener("popstate", onRouteLeave); - }; - }, [hmsActions, isConnectedToRoom]); - return null; -}; - -function AppRoutes({ getDetails, authTokenByRoomCodeEndpoint }) { - return ( - - - - - - - - - - - - } - /> - - } - /> - - - ); -} - -export default function App() { - return ( - - ); -} diff --git a/apps/100ms-web/src/IconButton.jsx b/apps/100ms-web/src/IconButton.jsx deleted file mode 100644 index 9455d0107a..0000000000 --- a/apps/100ms-web/src/IconButton.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import { IconButton as BaseIconButton, styled } from "@100mslive/roomkit-react"; - -const IconButton = styled(BaseIconButton, { - width: "$14", - height: "$14", - border: "1px solid $border_bright", - r: "$1", - variants: { - active: { - false: { - border: "1px solid transparent", - color: "$on_primary_high", - }, - }, - }, -}); - -export default IconButton; diff --git a/apps/100ms-web/src/common/PeersSorter.js b/apps/100ms-web/src/common/PeersSorter.js deleted file mode 100644 index 855277c9f2..0000000000 --- a/apps/100ms-web/src/common/PeersSorter.js +++ /dev/null @@ -1,97 +0,0 @@ -import { selectDominantSpeaker } from "@100mslive/hms-video-store"; - -class PeersSorter { - listeners = new Set(); - storeUnsubscribe; - - constructor(store) { - this.store = store; - this.peers = new Map(); - this.lruPeers = new Set(); - this.speaker = undefined; - } - - setPeersAndTilesPerPage = ({ peers, tilesPerPage }) => { - this.tilesPerPage = tilesPerPage; - const peerIds = new Set(peers.map(peer => peer.id)); - // remove existing peers which are no longer provided - this.peers.forEach((_, key) => { - if (!peerIds.has(key)) { - this.peers.delete(key); - } - }); - this.lruPeers = new Set( - [...this.lruPeers].filter(peerId => peerIds.has(peerId)) - ); - peers.forEach(peer => { - this.peers.set(peer.id, peer); - if (this.lruPeers.size < tilesPerPage) { - this.lruPeers.add(peer.id); - } - }); - if (!this.storeUnsubscribe) { - this.storeUnsubscribe = this.store.subscribe( - this.onDominantSpeakerChange, - selectDominantSpeaker - ); - } - this.moveSpeakerToFront(this.speaker); - }; - - onUpdate = cb => { - this.listeners.add(cb); - }; - - stop = () => { - this.updateListeners(); - this.listeners.clear(); - this.storeUnsubscribe?.(); - }; - - moveSpeakerToFront = speaker => { - if (!speaker) { - this.updateListeners(); - return; - } - if ( - this.lruPeers.has(speaker.id) && - this.lruPeers.size <= this.tilesPerPage - ) { - this.updateListeners(); - return; - } - // delete to insert at beginning - this.lruPeers.delete(speaker.id); - let lruPeerArray = Array.from(this.lruPeers); - while (lruPeerArray.length >= this.tilesPerPage) { - lruPeerArray.pop(); - } - this.lruPeers = new Set([speaker.id, ...lruPeerArray]); - this.updateListeners(); - }; - - onDominantSpeakerChange = speaker => { - if (speaker && speaker.id !== this?.speaker?.id) { - this.speaker = speaker; - this.moveSpeakerToFront(speaker); - } - }; - - updateListeners = () => { - const orderedPeers = []; - this.lruPeers.forEach(key => { - const peer = this.peers.get(key); - if (peer) { - orderedPeers.push(peer); - } - }); - this.peers.forEach(peer => { - if (!this.lruPeers.has(peer.id) && peer) { - orderedPeers.push(peer); - } - }); - this.listeners.forEach(listener => listener?.(orderedPeers)); - }; -} - -export default PeersSorter; diff --git a/apps/100ms-web/src/common/constants.js b/apps/100ms-web/src/common/constants.js deleted file mode 100644 index e4d78f0714..0000000000 --- a/apps/100ms-web/src/common/constants.js +++ /dev/null @@ -1,251 +0,0 @@ -import { parsedUserAgent } from "@100mslive/react-sdk"; - -export const defaultAudioList = [ - { - name: "Audio1", - id: "audio1", - metadata: { - description: "Artist1", - }, - url: "https://bc-public-static-assets.s3.ap-south-1.amazonaws.com/webapp/playlist/audio1.mp3", - type: "audio", - }, - { - name: "Audio2", - id: "audio2", - metadata: { - description: "Artist2", - }, - url: "https://bc-public-static-assets.s3.ap-south-1.amazonaws.com/webapp/playlist/audio2.mp3", - type: "audio", - }, - { - name: "Audio3", - id: "audio3", - metadata: { - description: "Artist3", - }, - url: "https://bc-public-static-assets.s3.ap-south-1.amazonaws.com/webapp/playlist/audio3.mp3", - type: "audio", - }, - { - name: "Audio4", - id: "audio4", - metadata: { - description: "Artist4", - }, - url: "https://bc-public-static-assets.s3.ap-south-1.amazonaws.com/webapp/playlist/audio4.mp3", - type: "audio", - }, - { - name: "Audio5", - id: "audio5", - metadata: { - description: "Artist5", - }, - url: "https://bc-public-static-assets.s3.ap-south-1.amazonaws.com/webapp/playlist/audio5.mp3", - type: "audio", - }, - { - name: "Audio6", - id: "audio6", - metadata: { - description: "Artist6", - }, - url: "https://bc-public-static-assets.s3.ap-south-1.amazonaws.com/webapp/playlist/audio6.mp3", - type: "audio", - }, -]; - -export const defaultVideoList = [ - { - name: "Video1", - id: "video1", - metadata: { - description: "Artist1", - }, - url: "https://bc-public-static-assets.s3.ap-south-1.amazonaws.com/webapp/playlist/video1.mp4", - type: "video", - }, - { - name: "Video2", - id: "video2", - metadata: { - description: "Artist2", - }, - url: "https://bc-public-static-assets.s3.ap-south-1.amazonaws.com/webapp/playlist/video2.mp4", - type: "video", - }, - { - name: "Video3", - id: "video3", - metadata: { - description: "Artist2", - }, - url: "https://bc-public-static-assets.s3.ap-south-1.amazonaws.com/webapp/playlist/video3.mp4", - type: "video", - }, -]; - -export const DEFAULT_HLS_ROLE_KEY = "HLS_VIEWER_ROLE"; -export const DEFAULT_HLS_VIEWER_ROLE = "hls-viewer"; -export const DEFAULT_WAITING_VIEWER_ROLE = "waiting-room"; -export const QUERY_PARAM_SKIP_PREVIEW = "skip_preview"; -export const QUERY_PARAM_SKIP_PREVIEW_HEADFUL = "skip_preview_headful"; -export const QUERY_PARAM_NAME = "name"; -export const QUERY_PARAM_VIEW_MODE = "ui_mode"; -export const QUERY_PARAM_AUTH_TOKEN = "auth_token"; -export const QUERY_PARAM_PREVIEW_AS_ROLE = "preview_as_role"; -export const UI_MODE_ACTIVE_SPEAKER = "activespeaker"; -export const UI_MODE_GRID = "grid"; -export const MAX_TOASTS = 5; -export const RTMP_RECORD_RESOLUTION_MIN = 480; -export const RTMP_RECORD_RESOLUTION_MAX = 1280; -export const RTMP_RECORD_DEFAULT_RESOLUTION = { - width: 1280, - height: 720, -}; -export const EMOJI_REACTION_TYPE = "EMOJI_REACTION"; - -export const CHAT_SELECTOR = { - PEER_ID: "peer_id", - ROLE: "role", -}; - -export const APP_DATA = { - uiSettings: "uiSettings", - chatOpen: "chatOpen", - chatSelector: "chatSelector", - chatDraft: "chatDraft", - appConfig: "appConfig", - sidePane: "sidePane", - hlsStats: "hlsStats", - hlsViewerRole: "hlsViewerRole", - waitingViewerRole: "waitingViewerRole", - subscribedNotifications: "subscribedNotifications", - logo: "logo", - tokenEndpoint: "tokenEndpoint", - appLayout: "appLayout", - hlsStarted: "hlsStarted", - rtmpStarted: "rtmpStarted", - recordingStarted: "recordingStarted", - embedConfig: "embedConfig", - pdfConfig: "pdfConfig", - pinnedTrackId: "pinnedTrackId", - dropdownList: "dropdownList", - widgetState: "widgetState", -}; - -export const UI_SETTINGS = { - isAudioOnly: "isAudioOnly", - isHeadless: "isHeadless", - maxTileCount: "maxTileCount", - uiViewMode: "uiViewMode", - showStatsOnTiles: "showStatsOnTiles", - enableAmbientMusic: "enableAmbientMusic", - mirrorLocalVideo: "mirrorLocalVideo", - activeSpeakerSorting: "activeSpeakerSorting", - hideLocalVideo: "hideLocalVideo", -}; - -export const WIDGET_STATE = { - pollInView: "pollInView", - view: "view", -}; - -export const WIDGET_VIEWS = { - LANDING: "LANDING", - CREATE_POLL_QUIZ: "CREATE_POLL_QUIZ", - CREATE_QUESTIONS: "CREATE_QUESTIONS", - VOTE: "VOTE", - RESULTS: "RESULTS", -}; - -export const SIDE_PANE_OPTIONS = { - PARTICIPANTS: "Participants", - CHAT: "Chat", - STREAMING: "STREAMING", - TILES: "TILES", - SCREEN_TILES: "SCREEN_TILES", - WIDGET: "WIDGET", -}; - -export const SUBSCRIBED_NOTIFICATIONS = { - PEER_JOINED: "PEER_JOINED", - PEER_LEFT: "PEER_LEFT", - METADATA_UPDATED: "METADATA_UPDATED", - NEW_MESSAGE: "NEW_MESSAGE", - ERROR: "ERROR", -}; - -export const CREATE_ROOM_DOC_URL = - "https://github.com/100mslive/100ms-web/wiki/Creating-and-joining-a-room"; -export const HLS_TIMED_METADATA_DOC_URL = - "https://www.100ms.live/docs/javascript/v2/how--to-guides/record-and-live-stream/hls/hls-timed-metadata"; - -export const REMOTE_STOP_SCREENSHARE_TYPE = "REMOTE_STOP_SCREENSHARE"; - -export const isChrome = - parsedUserAgent.getBrowser()?.name?.toLowerCase() === "chrome"; -export const isFirefox = - parsedUserAgent.getBrowser()?.name?.toLowerCase() === "firefox"; -export const isSafari = - parsedUserAgent.getBrowser()?.name?.toLowerCase() === "safari"; -export const isIOS = parsedUserAgent.getOS()?.name?.toLowerCase() === "ios"; -export const isMacOS = - parsedUserAgent.getOS()?.name?.toLowerCase() === "mac os"; -export const isAndroid = - parsedUserAgent.getOS()?.name?.toLowerCase() === "android"; -export const isIPadOS = - navigator?.maxTouchPoints && - navigator?.maxTouchPoints > 2 && - navigator?.userAgent?.match(/Mac/); - -export const FEATURE_LIST = { - AUDIO_ONLY_SCREENSHARE: "audioscreenshare", - AUDIO_PLAYLIST: "audioplaylist", - VIDEO_PLAYLIST: "videoplaylist", - EMOJI_REACTION: "emojireaction", - AUDIO_PLUGINS: "audioplugins", - VIDEO_PLUGINS: "videoplugins", - WHITEBOARD: "whiteboard", - CHANGE_NAME: "changename", - FULLSCREEN: "fullscreen", - PICTURE_IN_PICTURE: "pip", - STARTS_FOR_NERDS: "statsfornerds", - EMBED_URL: "embedurl", - BRB: "brb", - HAND_RAISE: "handraise", - CHAT: "chat", - PIN_TILE: "pintile", -}; - -export const SESSION_STORE_KEY = { - TRANSCRIPTION_STATE: "transcriptionState", - PINNED_MESSAGE: "pinnedMessage", - SPOTLIGHT: "spotlight", -}; - -export const INTERACTION_TYPE = { - POLL: "Poll", - QUIZ: "Quiz", -}; - -export const QUESTION_TYPE_TITLE = { - "single-choice": "Single Choice", - "multiple-choice": "Multiple Choice", - // "short-answer": "Short Answer", - // "long-answer": "Long Answer", -}; - -export const QUESTION_TYPE = { - SINGLE_CHOICE: "single-choice", - MULTIPLE_CHOICE: "multiple-choice", - // SHORT_ANSWER: "short-answer", - // LONG_ANSWER: "long-answer", -}; - -export const PDF_SHARING_OPTIONS = { - FROM_YOUR_COMPUTER: "From your Computer", - FROM_A_URL: "From a URL", -}; diff --git a/apps/100ms-web/src/common/hooks.js b/apps/100ms-web/src/common/hooks.js deleted file mode 100644 index 9f41bb409c..0000000000 --- a/apps/100ms-web/src/common/hooks.js +++ /dev/null @@ -1,53 +0,0 @@ -// @ts-check -import { useEffect, useRef, useState } from "react"; -import { - selectAvailableRoleNames, - selectIsConnectedToRoom, - selectPeerCount, - useHMSStore, -} from "@100mslive/react-sdk"; -import { isInternalRole } from "./utils"; - -/** - * Hook to execute a callback when alone in room(after a certain 5d of time) - * @param {number} thresholdMs The threshold(in ms) after which the callback is executed, - * starting from the instant when alone in room. - * note: the cb is not called when another peer joins during this period. - */ -export const useWhenAloneInRoom = (thresholdMs = 5 * 60 * 1000) => { - const isConnected = useHMSStore(selectIsConnectedToRoom); - const peerCount = useHMSStore(selectPeerCount); - const [aloneForLong, setAloneForLong] = useState(false); - const cbTimeout = useRef(null); - const alone = isConnected && peerCount === 1; - - useEffect(() => { - if (alone && !cbTimeout.current) { - // @ts-ignore - cbTimeout.current = setTimeout(() => { - setAloneForLong(true); - }, thresholdMs); - } else if (!alone) { - cbTimeout.current && clearTimeout(cbTimeout.current); - cbTimeout.current = null; - setAloneForLong(false); - } - }, [alone, thresholdMs]); - - useEffect(() => { - return () => { - if (cbTimeout.current) { - clearTimeout(cbTimeout.current); - } - }; - }, []); - - return { alone, aloneForLong }; -}; - -export const useFilteredRoles = () => { - const roles = useHMSStore(selectAvailableRoleNames).filter( - role => !isInternalRole(role) - ); - return roles; -}; diff --git a/apps/100ms-web/src/common/roles.js b/apps/100ms-web/src/common/roles.js deleted file mode 100644 index 939501beaf..0000000000 --- a/apps/100ms-web/src/common/roles.js +++ /dev/null @@ -1,4 +0,0 @@ -export const ROLES = { - TEACHER: "teacher", - STUDENT: "student", -}; diff --git a/apps/100ms-web/src/common/useSortedPeers.js b/apps/100ms-web/src/common/useSortedPeers.js deleted file mode 100644 index adb248bf71..0000000000 --- a/apps/100ms-web/src/common/useSortedPeers.js +++ /dev/null @@ -1,28 +0,0 @@ -import { useEffect, useRef, useState } from "react"; -import { useHMSVanillaStore } from "@100mslive/react-sdk"; -import PeersSorter from "./PeersSorter"; -import { useActiveSpeakerSorting } from "../components/AppData/useUISettings"; - -function useSortedPeers({ peers, maxTileCount = 9 }) { - const [sortedPeers, setSortedPeers] = useState([]); - const store = useHMSVanillaStore(); - const activeSpeakerSorting = useActiveSpeakerSorting(); - const peerSortedRef = useRef(new PeersSorter(store)); - peerSortedRef.current.onUpdate(setSortedPeers); - - useEffect(() => { - const peersSorter = peerSortedRef.current; - if (peers?.length > 0 && maxTileCount && activeSpeakerSorting) { - peersSorter.setPeersAndTilesPerPage({ - peers, - tilesPerPage: maxTileCount, - }); - } else if (!activeSpeakerSorting) { - peersSorter.stop(); - } - }, [maxTileCount, peers, activeSpeakerSorting]); - - return activeSpeakerSorting ? sortedPeers : peers; -} - -export default useSortedPeers; diff --git a/apps/100ms-web/src/common/utils.js b/apps/100ms-web/src/common/utils.js deleted file mode 100644 index c9f794a3ef..0000000000 --- a/apps/100ms-web/src/common/utils.js +++ /dev/null @@ -1,115 +0,0 @@ -import { QUESTION_TYPE } from "./constants"; - -export function shadeColor(color, percent) { - let R = parseInt(color.substring(1, 3), 16); - let G = parseInt(color.substring(3, 5), 16); - let B = parseInt(color.substring(5, 7), 16); - - R = Math.floor((R * (100 + percent)) / 100); - G = Math.floor((G * (100 + percent)) / 100); - B = Math.floor((B * (100 + percent)) / 100); - - R = R < 255 ? R : 255; - G = G < 255 ? G : 255; - B = B < 255 ? B : 255; - - const RR = - R.toString(16).length === 1 ? "0" + R.toString(16) : R.toString(16); - const GG = - G.toString(16).length === 1 ? "0" + G.toString(16) : G.toString(16); - const BB = - B.toString(16).length === 1 ? "0" + B.toString(16) : B.toString(16); - - return "#" + RR + GG + BB; -} - -/** - * TODO: this is currently an O(N**2) function, don't use with peer lists, it's currently - * being used to find intersection between list of role names where the complexity shouldn't matter much. - */ -export const arrayIntersection = (a, b) => { - if (a === undefined || b === undefined) { - return []; - } - // ensure "a" is the bigger array - if (b.length > a.length) { - let t = b; - b = a; - a = t; - } - return a.filter(function (e) { - return b.indexOf(e) > -1; - }); -}; - -export const getMetadata = metadataString => { - try { - return metadataString === "" ? {} : JSON.parse(metadataString); - } catch (error) { - return {}; - } -}; - -export const metadataProps = function (peer) { - return { - isHandRaised: getMetadata(peer.metadata)?.isHandRaised, - }; -}; - -export const isScreenshareSupported = () => { - return typeof navigator.mediaDevices.getDisplayMedia !== "undefined"; -}; - -export const getRoutePrefix = () => { - return window.location.pathname.startsWith("/streaming") ? "/streaming" : ""; -}; - -export const isStreamingKit = () => { - return window.location.pathname.startsWith("/streaming"); -}; - -export const isInternalRole = role => role && role.startsWith("__internal"); - -export const metadataPayloadParser = payload => { - try { - const data = window.atob(payload); - const parsedData = JSON.parse(data); - return parsedData; - } catch (e) { - return { payload }; - } -}; - -export const isValidURL = url => { - const urlPattern = new RegExp(/^(ftp|http|https):\/\/[^ "]+$/); - return !!urlPattern.test(url); -}; - -const compareArrays = (a, b) => { - if (a.length !== b.length) return false; - else { - // Comparing each element of your array - for (var i = 0; i < a.length; i++) { - if (a[i] !== b[i]) { - return false; - } - } - return true; - } -}; - -export const checkCorrectAnswer = (answer, localPeerResponse, type) => { - if (type === QUESTION_TYPE.SINGLE_CHOICE) { - return answer?.option === localPeerResponse?.option; - } else if (type === QUESTION_TYPE.MULTIPLE_CHOICE) { - return ( - answer?.options && - localPeerResponse?.options && - compareArrays(answer?.options, localPeerResponse?.options) - ); - } -}; - -export const isValidTextInput = (text, minLength = 2, maxLength = 100) => { - return text && text.length >= minLength && text.length <= maxLength; -}; diff --git a/apps/100ms-web/src/components/AppData/AppData.jsx b/apps/100ms-web/src/components/AppData/AppData.jsx deleted file mode 100644 index 156112b849..0000000000 --- a/apps/100ms-web/src/components/AppData/AppData.jsx +++ /dev/null @@ -1,240 +0,0 @@ -import React, { useEffect } from "react"; -import { useSearchParam } from "react-use"; -import { - HMSRoomState, - selectAvailableRoleNames, - selectHLSState, - selectIsConnectedToRoom, - selectLocalPeerRoleName, - selectRolesMap, - selectRoomState, - selectRTMPState, - useHMSActions, - useHMSStore, - useRecordingStreaming, -} from "@100mslive/react-sdk"; -import { normalizeAppPolicyConfig } from "../init/initUtils"; -import { - UserPreferencesKeys, - useUserPreferences, -} from "../hooks/useUserPreferences"; -import { - useIsSidepaneTypeOpen, - useSidepaneReset, - useSidepaneState, - useSidepaneToggle, -} from "./useSidepane"; -import { useSetAppDataByKey } from "./useUISettings"; -import { getMetadata } from "../../common/utils"; -import { - APP_DATA, - CHAT_SELECTOR, - DEFAULT_HLS_ROLE_KEY, - DEFAULT_HLS_VIEWER_ROLE, - DEFAULT_WAITING_VIEWER_ROLE, - QUERY_PARAM_VIEW_MODE, - SIDE_PANE_OPTIONS, - UI_MODE_ACTIVE_SPEAKER, - UI_MODE_GRID, - UI_SETTINGS, - WIDGET_STATE, -} from "../../common/constants"; - -export const getAppDetails = appDetails => { - try { - return !appDetails ? {} : JSON.parse(appDetails); - } catch (error) { - return {}; - } -}; - -const initialAppData = { - [APP_DATA.uiSettings]: { - [UI_SETTINGS.isAudioOnly]: false, - [UI_SETTINGS.isHeadless]: false, - [UI_SETTINGS.maxTileCount]: 9, - [UI_SETTINGS.showStatsOnTiles]: false, - [UI_SETTINGS.enableAmbientMusic]: false, - [UI_SETTINGS.uiViewMode]: UI_MODE_GRID, - [UI_SETTINGS.mirrorLocalVideo]: true, - [UI_SETTINGS.activeSpeakerSorting]: process.env.REACT_APP_ENV === "qa", - [UI_SETTINGS.hideLocalVideo]: false, - }, - [APP_DATA.subscribedNotifications]: { - PEER_JOINED: false, - PEER_LEFT: false, - NEW_MESSAGE: true, - ERROR: true, - METADATA_UPDATED: true, - }, - [APP_DATA.chatOpen]: false, - [APP_DATA.chatSelector]: { - [CHAT_SELECTOR.ROLE]: "", - [CHAT_SELECTOR.PEER_ID]: "", - }, - [APP_DATA.chatDraft]: "", - [APP_DATA.sidePane]: "", - [APP_DATA.hlsStarted]: false, - [APP_DATA.rtmpStarted]: false, - [APP_DATA.recordingStarted]: false, - [APP_DATA.hlsViewerRole]: DEFAULT_HLS_VIEWER_ROLE, - [APP_DATA.waitingViewerRole]: DEFAULT_WAITING_VIEWER_ROLE, - [APP_DATA.dropdownList]: [], - [APP_DATA.widgetState]: { - [WIDGET_STATE.pollInView]: "", - [WIDGET_STATE.view]: "", - }, -}; - -export const AppData = React.memo( - ({ appDetails, logo, tokenEndpoint, policyConfig, uiMode }) => { - const hmsActions = useHMSActions(); - const isConnected = useHMSStore(selectIsConnectedToRoom); - const sidePane = useSidepaneState(); - const resetSidePane = useSidepaneReset(); - const [preferences = {}] = useUserPreferences( - UserPreferencesKeys.UI_SETTINGS - ); - const roleNames = useHMSStore(selectAvailableRoleNames); - const rolesMap = useHMSStore(selectRolesMap); - const localPeerRole = useHMSStore(selectLocalPeerRoleName); - const isDefaultModeActiveSpeaker = - useSearchParam(QUERY_PARAM_VIEW_MODE) === UI_MODE_ACTIVE_SPEAKER; - - useEffect(() => { - if ( - !isConnected && - sidePane && - sidePane !== SIDE_PANE_OPTIONS.PARTICIPANTS - ) { - resetSidePane(); - } - }, [isConnected, sidePane, resetSidePane]); - - useEffect(() => { - hmsActions.initAppData(initialAppData); - }, [hmsActions]); - - useEffect(() => { - const uiSettings = preferences || {}; - const updatedSettings = { - ...uiSettings, - [UI_SETTINGS.uiViewMode]: isDefaultModeActiveSpeaker - ? UI_MODE_ACTIVE_SPEAKER - : uiSettings.uiViewMode || UI_MODE_GRID, - }; - hmsActions.setAppData(APP_DATA.uiSettings, updatedSettings, true); - }, [preferences, isDefaultModeActiveSpeaker, hmsActions]); - - useEffect(() => { - const appData = { - [APP_DATA.tokenEndpoint]: tokenEndpoint, - [APP_DATA.logo]: logo, - [APP_DATA.hlsViewerRole]: - getMetadata(appDetails)[DEFAULT_HLS_ROLE_KEY] || - DEFAULT_HLS_VIEWER_ROLE, - [APP_DATA.appConfig]: getAppDetails(appDetails), - [APP_DATA.uiMode]: uiMode, - }; - for (const key in appData) { - hmsActions.setAppData([key], appData[key]); - } - }, [appDetails, logo, tokenEndpoint, uiMode, hmsActions]); - - useEffect(() => { - if (!preferences.subscribedNotifications) { - return; - } - hmsActions.setAppData( - APP_DATA.subscribedNotifications, - preferences.subscribedNotifications, - true - ); - }, [preferences.subscribedNotifications, hmsActions]); - - useEffect(() => { - if (localPeerRole) { - const config = normalizeAppPolicyConfig( - roleNames, - rolesMap, - policyConfig - ); - hmsActions.setAppData(APP_DATA.appLayout, config[localPeerRole]); - } - }, [roleNames, policyConfig, rolesMap, localPeerRole, hmsActions]); - - return ; - } -); - -/** - * reset hlsStarted, rtmpStarted values when streaming starts - */ -const ResetStreamingStart = () => { - const { isHLSRunning, isRTMPRunning, isBrowserRecordingOn } = - useRecordingStreaming(); - const hlsError = useHMSStore(selectHLSState).error; - const rtmpError = useHMSStore(selectRTMPState).error; - const roomState = useHMSStore(selectRoomState); - const [hlsStarted, setHLSStarted] = useSetAppDataByKey(APP_DATA.hlsStarted); - const [recordingStarted, setRecordingStarted] = useSetAppDataByKey( - APP_DATA.recordingStarted - ); - const [rtmpStarted, setRTMPStarted] = useSetAppDataByKey( - APP_DATA.rtmpStarted - ); - const toggleStreaming = useSidepaneToggle(SIDE_PANE_OPTIONS.STREAMING); - const isStreamingOpen = useIsSidepaneTypeOpen(SIDE_PANE_OPTIONS.STREAMING); - - useEffect(() => { - if (isBrowserRecordingOn && recordingStarted) { - setRecordingStarted(false); - } - }, [isBrowserRecordingOn, recordingStarted, setRecordingStarted]); - /** - * Reset on leave - */ - useEffect(() => { - if (roomState === HMSRoomState.Disconnected) { - setHLSStarted(false); - setRecordingStarted(false); - setRTMPStarted(false); - } - }, [roomState, setHLSStarted, setRTMPStarted, setRecordingStarted]); - useEffect(() => { - if (isHLSRunning || hlsError) { - if (hlsStarted) { - setHLSStarted(false); - if (isStreamingOpen) { - toggleStreaming(); - } - } - } - }, [ - isHLSRunning, - hlsStarted, - setHLSStarted, - hlsError, - isStreamingOpen, - toggleStreaming, - ]); - useEffect(() => { - if (isRTMPRunning || rtmpError || isBrowserRecordingOn) { - if (rtmpStarted) { - setRTMPStarted(false); - if (isStreamingOpen) { - toggleStreaming(); - } - } - } - }, [ - isRTMPRunning, - setRTMPStarted, - rtmpStarted, - rtmpError, - isBrowserRecordingOn, - isStreamingOpen, - toggleStreaming, - ]); - return null; -}; diff --git a/apps/100ms-web/src/components/AppData/useAppConfig.js b/apps/100ms-web/src/components/AppData/useAppConfig.js deleted file mode 100644 index 9c2685513c..0000000000 --- a/apps/100ms-web/src/components/AppData/useAppConfig.js +++ /dev/null @@ -1,9 +0,0 @@ -import { selectAppDataByPath, useHMSStore } from "@100mslive/react-sdk"; -import { APP_DATA } from "../../common/constants"; - -export const useAppConfig = (...path) => { - const appConfig = useHMSStore( - selectAppDataByPath(APP_DATA.appConfig, ...path) - ); - return appConfig; -}; diff --git a/apps/100ms-web/src/components/AppData/useAppLayout.js b/apps/100ms-web/src/components/AppData/useAppLayout.js deleted file mode 100644 index 4a44c61ff7..0000000000 --- a/apps/100ms-web/src/components/AppData/useAppLayout.js +++ /dev/null @@ -1,6 +0,0 @@ -import { selectAppDataByPath, useHMSStore } from "@100mslive/react-sdk"; -import { APP_DATA } from "../../common/constants"; - -export const useAppLayout = path => { - return useHMSStore(selectAppDataByPath(APP_DATA.appLayout, path)); -}; diff --git a/apps/100ms-web/src/components/AppData/useChatState.js b/apps/100ms-web/src/components/AppData/useChatState.js deleted file mode 100644 index 6264b8b26d..0000000000 --- a/apps/100ms-web/src/components/AppData/useChatState.js +++ /dev/null @@ -1,22 +0,0 @@ -import { useCallback } from "react"; -import { - selectAppData, - useHMSActions, - useHMSStore, -} from "@100mslive/react-sdk"; -import { APP_DATA } from "../../common/constants"; - -export const useChatDraftMessage = () => { - const hmsActions = useHMSActions(); - let chatDraftMessage = useHMSStore(selectAppData(APP_DATA.chatDraft)); - if (chatDraftMessage === undefined || chatDraftMessage === null) { - chatDraftMessage = ""; - } - const setDraftMessage = useCallback( - message => { - hmsActions.setAppData(APP_DATA.chatDraft, message, true); - }, - [hmsActions] - ); - return [chatDraftMessage, setDraftMessage]; -}; diff --git a/apps/100ms-web/src/components/AppData/useSidepane.js b/apps/100ms-web/src/components/AppData/useSidepane.js deleted file mode 100644 index 007508a5ae..0000000000 --- a/apps/100ms-web/src/components/AppData/useSidepane.js +++ /dev/null @@ -1,81 +0,0 @@ -import { useCallback } from "react"; -import { - selectAppData, - useHMSActions, - useHMSStore, - useHMSVanillaStore, -} from "@100mslive/react-sdk"; -import { useWidgetState } from "./useUISettings"; -import { APP_DATA, WIDGET_STATE, WIDGET_VIEWS } from "../../common/constants"; - -/** - * Gives a boolean value if the sidepaneType matches current sidepane value in store - * @param {string} sidepaneType - * @returns {boolean} - if the sidepaneType is passed returns boolean else the current value - */ -export const useIsSidepaneTypeOpen = sidepaneType => { - if (!sidepaneType) { - throw Error("Pass one of the side pane options"); - } - return useHMSStore(selectAppData(APP_DATA.sidePane)) === sidepaneType; -}; - -/** - * Gives the current value of sidepane in store - * @returns {string} - if the sidepaneType is passed returns boolean else the current value - */ -export const useSidepaneState = () => { - const sidePane = useHMSStore(selectAppData(APP_DATA.sidePane)); - return sidePane; -}; - -/** - * Toggle the sidepane value between passed sidePaneType and ''; - * @param {string} sidepaneType - */ -export const useSidepaneToggle = sidepaneType => { - const hmsActions = useHMSActions(); - const vanillaStore = useHMSVanillaStore(); - const toggleSidepane = useCallback(() => { - const isOpen = - vanillaStore.getState(selectAppData(APP_DATA.sidePane)) === sidepaneType; - hmsActions.setAppData(APP_DATA.sidePane, !isOpen ? sidepaneType : ""); - }, [vanillaStore, hmsActions, sidepaneType]); - return toggleSidepane; -}; - -export const useWidgetToggle = () => { - const { widgetView, setWidgetState } = useWidgetState(); - - const toggleWidget = useCallback( - id => { - id = typeof id === "string" ? id : undefined; - setWidgetState({ - [WIDGET_STATE.pollInView]: id, - [WIDGET_STATE.view]: id - ? WIDGET_VIEWS.VOTE - : widgetView - ? null - : WIDGET_VIEWS.LANDING, - }); - }, - [widgetView, setWidgetState] - ); - - return toggleWidget; -}; - -/** - * reset's the sidepane value - */ -export const useSidepaneReset = () => { - const hmsActions = useHMSActions(); - const resetSidepane = useCallback(() => { - hmsActions.setAppData(APP_DATA.sidePane, ""); - hmsActions.setAppData(APP_DATA.widgetState, { - [WIDGET_STATE.pollInView]: "", - [WIDGET_STATE.view]: "", - }); - }, [hmsActions]); - return resetSidepane; -}; diff --git a/apps/100ms-web/src/components/AppData/useUISettings.js b/apps/100ms-web/src/components/AppData/useUISettings.js deleted file mode 100644 index f39c484e4c..0000000000 --- a/apps/100ms-web/src/components/AppData/useUISettings.js +++ /dev/null @@ -1,286 +0,0 @@ -import { useCallback, useMemo } from "react"; -import { - selectAppData, - selectAppDataByPath, - selectAudioTrackByPeerID, - selectIsAllowedToPublish, - selectLocalPeerRoleName, - selectPermissions, - selectPolls, - selectSessionStore, - selectTrackByID, - selectVideoTrackByPeerID, - useHMSActions, - useHMSStore, - useHMSVanillaStore, -} from "@100mslive/react-sdk"; -import { useWhiteboardMetadata } from "../../plugins/whiteboard/useWhiteboardMetadata"; -import { useIsFeatureEnabled } from "../hooks/useFeatures"; -import { - UserPreferencesKeys, - useUserPreferences, -} from "../hooks/useUserPreferences"; -import { isScreenshareSupported } from "../../common/utils"; -import { - APP_DATA, - FEATURE_LIST, - SESSION_STORE_KEY, - UI_SETTINGS, - WIDGET_STATE, -} from "../../common/constants"; - -/** - * fields saved related to UI settings in store's app data can be - * accessed using this hook. key is optional if not passed - * the whole UI settings object is returned. Usage - - * 1. val = useUiSettings("isAudioOnly"); - * console.log(val); // false - * 2. val = useUISettings(); - * console.log(val); // {isAudioOnly: false} - * @param {string | undefined} uiSettingKey - */ -export const useUISettings = uiSettingKey => { - const uiSettings = useHMSStore( - selectAppDataByPath(APP_DATA.uiSettings, uiSettingKey) - ); - return uiSettings; -}; - -/** - * fields saved related to UI settings in store's app data can be - * accessed using this hook. key is optional if not passed - * the whole UI settings object is returned. Usage - - * [val, setVal] = useUiSettings("isAudioOnly"); - * console.log(val); // false - * setVal(true); - * @param {string} uiSettingKey - */ -export const useSetUiSettings = uiSettingKey => { - const value = useUISettings(uiSettingKey); - const setValue = useSetAppData({ - key1: APP_DATA.uiSettings, - key2: uiSettingKey, - }); - return [value, setValue]; -}; - -export const useIsHeadless = () => { - const isHeadless = useUISettings(UI_SETTINGS.isHeadless); - return isHeadless; -}; - -export const useActiveSpeakerSorting = () => { - const activeSpeakerSorting = useUISettings(UI_SETTINGS.activeSpeakerSorting); - return activeSpeakerSorting; -}; - -export const useHLSViewerRole = () => { - return useHMSStore(selectAppData(APP_DATA.hlsViewerRole)); -}; - -export const useWaitingViewerRole = () => { - return useHMSStore(selectAppData(APP_DATA.waitingViewerRole)); -}; -export const useIsHLSStartedFromUI = () => { - return useHMSStore(selectAppData(APP_DATA.hlsStarted)); -}; - -export const useIsRTMPStartedFromUI = () => { - return useHMSStore(selectAppData(APP_DATA.rtmpStarted)); -}; - -export const useTokenEndpoint = () => { - return useHMSStore(selectAppData(APP_DATA.tokenEndpoint)); -}; - -export const useLogo = () => { - return useHMSStore(selectAppData(APP_DATA.logo)); -}; - -export const useUrlToEmbed = () => { - return useHMSStore(selectAppData(APP_DATA.embedConfig)); -}; - -export const usePDFConfig = () => { - return useHMSStore(selectAppData(APP_DATA.pdfConfig)); -}; -export const useResetPDFConfig = () => { - const [, setPDFConfig] = useSetAppDataByKey(APP_DATA.pdfConfig); - return useCallback(() => setPDFConfig(), [setPDFConfig]); -}; -export const useResetEmbedConfig = () => { - const [, setEmbedConfig] = useSetAppDataByKey(APP_DATA.embedConfig); - return () => setEmbedConfig(); -}; -export const usePinnedTrack = () => { - const pinnedTrackId = useHMSStore(selectAppData(APP_DATA.pinnedTrackId)); - const spotlightPeerId = useHMSStore( - selectSessionStore(SESSION_STORE_KEY.SPOTLIGHT) - ); - const spotlightVideoTrackId = useHMSStore( - selectVideoTrackByPeerID(spotlightPeerId) - )?.id; - const spotlightAudioTrackId = useHMSStore( - selectAudioTrackByPeerID(spotlightPeerId) - )?.id; - return useHMSStore( - selectTrackByID( - pinnedTrackId || spotlightVideoTrackId || spotlightAudioTrackId - ) - ); -}; - -export const useSubscribedNotifications = notificationKey => { - const notificationPreference = useHMSStore( - selectAppDataByPath(APP_DATA.subscribedNotifications, notificationKey) - ); - return notificationPreference; -}; - -export const useSetSubscribedNotifications = notificationKey => { - const value = useSubscribedNotifications(notificationKey); - const setValue = useSetAppData({ - key1: APP_DATA.subscribedNotifications, - key2: notificationKey, - }); - return [value, setValue]; -}; - -export const useSubscribeChatSelector = chatSelectorKey => { - const chatSelectorPreference = useHMSStore( - selectAppDataByPath(APP_DATA.chatSelector, chatSelectorKey) - ); - return chatSelectorPreference; -}; - -export const useSetSubscribedChatSelector = chatSelectorKey => { - const value = useSubscribeChatSelector(chatSelectorKey); - const setValue = useSetAppData({ - key1: APP_DATA.chatSelector, - key2: chatSelectorKey, - }); - return [value, setValue]; -}; - -export const useSetAppDataByKey = appDataKey => { - const value = useHMSStore(selectAppData(appDataKey)); - const actions = useHMSActions(); - const setValue = useCallback( - value => { - actions.setAppData(appDataKey, value); - }, - [actions, appDataKey] - ); - return [value, setValue]; -}; - -const useSetAppData = ({ key1, key2 }) => { - const actions = useHMSActions(); - const store = useHMSVanillaStore(); - const [, setPreferences] = useUserPreferences( - UserPreferencesKeys.UI_SETTINGS - ); - const setValue = useCallback( - value => { - if (!key1) { - return; - } - actions.setAppData( - key1, - key2 - ? { - [key2]: value, - } - : value, - true - ); - const appData = store.getState(selectAppData()); - setPreferences({ - ...appData.uiSettings, - subscribedNotifications: appData.subscribedNotifications, - }); - }, - [actions, key1, key2, store, setPreferences] - ); - return setValue; -}; - -export const useWidgetState = () => { - const [widgetState, setWidgetState] = useSetAppDataByKey( - APP_DATA.widgetState - ); - - const setWidgetView = useCallback( - view => { - setWidgetState({ - [WIDGET_STATE.pollInView]: widgetState?.pollInView, - [WIDGET_STATE.view]: view, - }); - }, - [widgetState?.pollInView, setWidgetState] - ); - - return { - setWidgetState, - setWidgetView, - pollInView: widgetState?.pollInView, - widgetView: widgetState?.view, - }; -}; -export const useShowWhiteboard = () => { - const { whiteboardEnabled } = useWhiteboardMetadata(); - const hlsViewerRole = useHLSViewerRole(); - const localPeerRole = useHMSStore(selectLocalPeerRoleName); - const isWhiteboardFeatureEnabled = useIsFeatureEnabled( - FEATURE_LIST.WHITEBOARD - ); - const showWhiteboard = useMemo(() => { - return !( - !whiteboardEnabled || - hlsViewerRole === localPeerRole || - !isWhiteboardFeatureEnabled - ); - }, [ - hlsViewerRole, - isWhiteboardFeatureEnabled, - localPeerRole, - whiteboardEnabled, - ]); - return { - showWhiteboard: showWhiteboard, - }; -}; -export const useShowAudioShare = () => { - const isAllowedToPublish = useHMSStore(selectIsAllowedToPublish); - const isAudioShareFeatureEnabled = useIsFeatureEnabled( - FEATURE_LIST.AUDIO_ONLY_SCREENSHARE - ); - - const showAudioShare = useMemo(() => { - return !( - !isAudioShareFeatureEnabled || - !isAllowedToPublish.screen || - !isScreenshareSupported() - ); - }, [isAllowedToPublish.screen, isAudioShareFeatureEnabled]); - - return { - showAudioShare: showAudioShare, - }; -}; -export const useShowPolls = () => { - const permissions = useHMSStore(selectPermissions); - const polls = useHMSStore(selectPolls)?.filter( - poll => poll.state === "started" || poll.state === "stopped" - ); - - const showPolls = useMemo(() => { - return ( - permissions?.pollWrite || (permissions?.pollRead && polls?.length > 0) - ); - }, [permissions?.pollRead, permissions?.pollWrite, polls?.length]); - - return { - showPolls: showPolls, - }; -}; diff --git a/apps/100ms-web/src/components/AudioLevel/BeamSpeakerLabelsLogging.jsx b/apps/100ms-web/src/components/AudioLevel/BeamSpeakerLabelsLogging.jsx deleted file mode 100644 index a17107d6e2..0000000000 --- a/apps/100ms-web/src/components/AudioLevel/BeamSpeakerLabelsLogging.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import { useEffect } from "react"; -import { useHMSActions } from "@100mslive/react-sdk"; -import { useIsHeadless } from "../AppData/useUISettings"; -import { FeatureFlags } from "../../services/FeatureFlags"; - -export function BeamSpeakerLabelsLogging() { - const hmsActions = useHMSActions(); - const isHeadless = useIsHeadless(); - - useEffect(() => { - if (FeatureFlags.enableBeamSpeakersLogging && isHeadless) { - hmsActions.enableBeamSpeakerLabelsLogging(); - } - }, [hmsActions, isHeadless]); - return null; -} diff --git a/apps/100ms-web/src/components/AudioVideoToggle.jsx b/apps/100ms-web/src/components/AudioVideoToggle.jsx deleted file mode 100644 index fa4dc674cb..0000000000 --- a/apps/100ms-web/src/components/AudioVideoToggle.jsx +++ /dev/null @@ -1,92 +0,0 @@ -import React, { Fragment } from "react"; -import { - selectIsConnectedToRoom, - selectLocalVideoTrackID, - selectVideoTrackByID, - useAVToggle, - useHMSActions, - useHMSStore, -} from "@100mslive/react-sdk"; -import { - CameraFlipIcon, - MicOffIcon, - MicOnIcon, - VideoOffIcon, - VideoOnIcon, -} from "@100mslive/react-icons"; -import { Tooltip } from "@100mslive/roomkit-react"; -import { ToastManager } from "./Toast/ToastManager"; -import IconButton from "../IconButton"; -import { isMacOS } from "../common/constants"; - -export const AudioVideoToggle = () => { - const { isLocalVideoEnabled, isLocalAudioEnabled, toggleAudio, toggleVideo } = - useAVToggle(); - const actions = useHMSActions(); - const videoTracKId = useHMSStore(selectLocalVideoTrackID); - const localVideoTrack = useHMSStore(selectVideoTrackByID(videoTracKId)); - const isConnectedToRoom = useHMSStore(selectIsConnectedToRoom); - - return ( - - {toggleAudio ? ( - - - {!isLocalAudioEnabled ? ( - - ) : ( - - )} - - - ) : null} - {toggleVideo ? ( - - - {!isLocalVideoEnabled ? ( - - ) : ( - - )} - - - ) : null} - {localVideoTrack?.facingMode && isConnectedToRoom ? ( - - { - try { - await actions.switchCamera(); - } catch (e) { - ToastManager.addToast({ - title: `Error while flipping camera ${e.message || ""}`, - variant: "error", - }); - } - }} - > - - - - ) : null} - - ); -}; diff --git a/apps/100ms-web/src/components/Chat/Chat.js b/apps/100ms-web/src/components/Chat/Chat.js deleted file mode 100644 index 78fe29ff68..0000000000 --- a/apps/100ms-web/src/components/Chat/Chat.js +++ /dev/null @@ -1,188 +0,0 @@ -import React, { useCallback, useEffect, useRef, useState } from "react"; -import { - HMSNotificationTypes, - selectHMSMessagesCount, - selectPeerNameByID, - selectPermissions, - selectSessionStore, - useHMSActions, - useHMSNotifications, - useHMSStore, -} from "@100mslive/react-sdk"; -import { ChevronDownIcon, CrossIcon, PinIcon } from "@100mslive/react-icons"; -import { Box, Button, Flex, IconButton, Text } from "@100mslive/roomkit-react"; -import { AnnotisedMessage, ChatBody } from "./ChatBody"; -import { ChatFooter } from "./ChatFooter"; -import { ChatHeader } from "./ChatHeader"; -import { useSetSubscribedChatSelector } from "../AppData/useUISettings"; -import { useSetPinnedMessage } from "../hooks/useSetPinnedMessage"; -import { useUnreadCount } from "./useUnreadCount"; -import { CHAT_SELECTOR, SESSION_STORE_KEY } from "../../common/constants"; - -const PinnedMessage = ({ clearPinnedMessage }) => { - const permissions = useHMSStore(selectPermissions); - const pinnedMessage = useHMSStore( - selectSessionStore(SESSION_STORE_KEY.PINNED_MESSAGE) - ); - - return pinnedMessage ? ( - - - - - - - - - - {permissions.removeOthers && ( - clearPinnedMessage()}> - - - )} - - ) : null; -}; - -export const Chat = () => { - const notification = useHMSNotifications(HMSNotificationTypes.PEER_LEFT); - const [peerSelector, setPeerSelector] = useSetSubscribedChatSelector( - CHAT_SELECTOR.PEER_ID - ); - const [roleSelector, setRoleSelector] = useSetSubscribedChatSelector( - CHAT_SELECTOR.ROLE - ); - const peerName = useHMSStore(selectPeerNameByID(peerSelector)); - const [chatOptions, setChatOptions] = useState({ - role: roleSelector || "", - peerId: peerSelector && peerName ? peerSelector : "", - selection: roleSelector - ? roleSelector - : peerSelector && peerName - ? peerName - : "Everyone", - }); - const [isSelectorOpen, setSelectorOpen] = useState(false); - const listRef = useRef(null); - const hmsActions = useHMSActions(); - const { setPinnedMessage } = useSetPinnedMessage(); - useEffect(() => { - if ( - notification && - notification.data && - peerSelector === notification.data.id - ) { - setPeerSelector(""); - setChatOptions({ - role: "", - peerId: "", - selection: "Everyone", - }); - } - }, [notification, peerSelector, setPeerSelector]); - - const storeMessageSelector = selectHMSMessagesCount; - - const messagesCount = useHMSStore(storeMessageSelector) || 0; - const scrollToBottom = useCallback( - (unreadCount = 0) => { - if (listRef.current && listRef.current.scrollToItem && unreadCount > 0) { - listRef.current?.scrollToItem(messagesCount, "end"); - requestAnimationFrame(() => { - listRef.current?.scrollToItem(messagesCount, "end"); - }); - hmsActions.setMessageRead(true); - } - }, - [hmsActions, messagesCount] - ); - - return ( - - { - setChatOptions({ - role, - peerId, - selection, - }); - setPeerSelector(peerId); - setRoleSelector(role); - }} - role={chatOptions.role} - peerId={chatOptions.peerId} - onToggle={() => { - setSelectorOpen(value => !value); - }} - /> - - - - scrollToBottom(1)} - > - {!isSelectorOpen && ( - - )} - - - ); -}; - -const NewMessageIndicator = ({ role, peerId, scrollToBottom }) => { - const unreadCount = useUnreadCount({ role, peerId }); - if (!unreadCount) { - return null; - } - return ( - - - - ); -}; diff --git a/apps/100ms-web/src/components/Chat/ChatBody.jsx b/apps/100ms-web/src/components/Chat/ChatBody.jsx deleted file mode 100644 index 5675e4b6b2..0000000000 --- a/apps/100ms-web/src/components/Chat/ChatBody.jsx +++ /dev/null @@ -1,415 +0,0 @@ -import React, { - Fragment, - useCallback, - useEffect, - useLayoutEffect, - useRef, - useState, -} from "react"; -import { useInView } from "react-intersection-observer"; -import AutoSizer from "react-virtualized-auto-sizer"; -import { VariableSizeList } from "react-window"; -import { - selectHMSMessages, - selectLocalPeerID, - selectLocalPeerRoleName, - selectMessagesByPeerID, - selectMessagesByRole, - selectPeerNameByID, - selectPermissions, - useHMSActions, - useHMSStore, -} from "@100mslive/react-sdk"; -import { HorizontalMenuIcon, PinIcon } from "@100mslive/react-icons"; -import { - Box, - Dropdown, - Flex, - IconButton, - styled, - Text, - Tooltip, -} from "@100mslive/roomkit-react"; -import { useSetPinnedMessage } from "../hooks/useSetPinnedMessage"; - -const formatTime = date => { - if (!(date instanceof Date)) { - return ""; - } - let hours = date.getHours(); - let mins = date.getMinutes(); - const suffix = hours > 11 ? "PM" : "AM"; - if (hours < 10) { - hours = "0" + hours; - } - if (mins < 10) { - mins = "0" + mins; - } - return `${hours}:${mins} ${suffix}`; -}; - -const MessageTypeContainer = ({ left, right }) => { - return ( - - {left && ( - - {left} - - )} - {left && right && ( - - )} - {right && ( - - {right} - - )} - - ); -}; - -const MessageType = ({ roles, hasCurrentUserSent, receiver }) => { - const peerName = useHMSStore(selectPeerNameByID(receiver)); - const localPeerRoleName = useHMSStore(selectLocalPeerRoleName); - if (receiver) { - return ( - - ); - } - - if (roles && roles.length) { - return ( - - ); - } - return null; -}; - -const URL_REGEX = - /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/; - -const Link = styled("a", { - color: "$primary_default", - wordBreak: "break-word", - "&:hover": { - textDecoration: "underline", - }, -}); - -export const AnnotisedMessage = ({ message }) => { - if (!message) { - return ; - } - - return ( - - {message - .trim() - .split(/(\s)/) - .map(part => - URL_REGEX.test(part) ? ( - - {part} - - ) : ( - part - ) - )} - - ); -}; - -const getMessageType = ({ roles, receiver }) => { - if (roles && roles.length > 0) { - return "role"; - } - return receiver ? "private" : ""; -}; - -const ChatActions = ({ onPin }) => { - const [open, setOpen] = useState(false); - - return ( - - - - - - - - - - - - - - - - Pin Message - - - - - - ); -}; - -const SenderName = styled(Text, { - overflow: "hidden", - textOverflow: "ellipsis", - whiteSpace: "nowrap", - maxWidth: "24ch", - minWidth: 0, -}); - -const ChatMessage = React.memo( - ({ index, style = {}, message, setRowHeight, onPin }) => { - const { ref, inView } = useInView({ threshold: 0.5, triggerOnce: true }); - const rowRef = useRef(null); - useEffect(() => { - if (rowRef.current) { - setRowHeight(index, rowRef.current.clientHeight); - } - }, [index, setRowHeight]); - - const hmsActions = useHMSActions(); - const localPeerId = useHMSStore(selectLocalPeerID); - const permissions = useHMSStore(selectPermissions); - const messageType = getMessageType({ - roles: message.recipientRoles, - receiver: message.recipientPeer, - }); - // show pin action only if peer has remove others permission and the message is of broadcast type - const showPinAction = permissions.removeOthers && !messageType; - - useEffect(() => { - if (message.id && !message.read && inView) { - hmsActions.setMessageRead(true, message.id); - } - }, [message.read, hmsActions, inView, message.id]); - - return ( - - - - - {message.senderName === "You" || !message.senderName ? ( - - {message.senderName || "Anonymous"} - - ) : ( - - {message.senderName} - - )} - - {formatTime(message.time)} - - - - {showPinAction && } - - e.stopPropagation()} - > - - - - - ); - } -); -const ChatList = React.forwardRef( - ( - { width, height, setRowHeight, getRowHeight, messages, scrollToBottom }, - listRef - ) => { - const { setPinnedMessage } = useSetPinnedMessage(); - useLayoutEffect(() => { - if (listRef.current && listRef.current.scrollToItem) { - scrollToBottom(1); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [listRef]); - - return ( - - {({ index, style }) => ( - setPinnedMessage(messages[index])} - /> - )} - - ); - } -); -const VirtualizedChatMessages = React.forwardRef( - ({ messages, setPinnedMessage, scrollToBottom }, listRef) => { - const rowHeights = useRef({}); - - function getRowHeight(index) { - // 72 will be default row height for any message length - // 16 will add margin value as clientHeight don't include margin - return rowHeights.current[index] + 16 || 72; - } - - const setRowHeight = useCallback( - (index, size) => { - listRef.current.resetAfterIndex(0); - rowHeights.current = { ...rowHeights.current, [index]: size }; - }, - [listRef] - ); - - return ( - - - {({ height, width }) => ( - - )} - - - ); - } -); - -export const ChatBody = React.forwardRef( - ({ role, peerId, scrollToBottom }, listRef) => { - const storeMessageSelector = role - ? selectMessagesByRole(role) - : peerId - ? selectMessagesByPeerID(peerId) - : selectHMSMessages; - const messages = useHMSStore(storeMessageSelector) || []; - - if (messages.length === 0) { - return ( - - There are no messages here - - ); - } - - return ( - - - - ); - } -); diff --git a/apps/100ms-web/src/components/Chat/ChatFooter.jsx b/apps/100ms-web/src/components/Chat/ChatFooter.jsx deleted file mode 100644 index a109369595..0000000000 --- a/apps/100ms-web/src/components/Chat/ChatFooter.jsx +++ /dev/null @@ -1,159 +0,0 @@ -import React, { useCallback, useEffect, useRef, useState } from "react"; -import data from "@emoji-mart/data"; -import Picker from "@emoji-mart/react"; -import { useHMSActions } from "@100mslive/react-sdk"; -import { EmojiIcon, SendIcon } from "@100mslive/react-icons"; -import { - Box, - Flex, - IconButton, - Popover, - styled, -} from "@100mslive/roomkit-react"; -import { ToastManager } from "../Toast/ToastManager"; -import { useChatDraftMessage } from "../AppData/useChatState"; -import { useEmojiPickerStyles } from "./useEmojiPickerStyles"; - -const TextArea = styled("textarea", { - width: "100%", - fontFamily: "$sans", - bg: "transparent", - color: "$on_surface_high", - resize: "none", - lineHeight: "1rem", - position: "relative", - top: "$3", - "&:focus": { - boxShadow: "none", - outline: "none", - }, -}); - -function EmojiPicker({ onSelect }) { - const [showEmoji, setShowEmoji] = useState(false); - const ref = useEmojiPickerStyles(showEmoji); - return ( - - - - - - - - - - - - - - - ); -} - -export const ChatFooter = ({ role, peerId, onSend, children }) => { - const hmsActions = useHMSActions(); - const inputRef = useRef(null); - const [draftMessage, setDraftMessage] = useChatDraftMessage(); - - const sendMessage = useCallback(async () => { - const message = inputRef.current.value; - if (!message || !message.trim().length) { - return; - } - try { - if (role) { - await hmsActions.sendGroupMessage(message, [role]); - } else if (peerId) { - await hmsActions.sendDirectMessage(message, peerId); - } else { - await hmsActions.sendBroadcastMessage(message); - } - inputRef.current.value = ""; - setTimeout(() => { - onSend(); - }, 0); - } catch (error) { - ToastManager.addToast({ title: error.message }); - } - }, [role, peerId, hmsActions, onSend]); - - useEffect(() => { - const messageElement = inputRef.current; - if (messageElement) { - messageElement.value = draftMessage; - } - }, [draftMessage]); - - useEffect(() => { - const messageElement = inputRef.current; - return () => { - setDraftMessage(messageElement?.value || ""); - }; - }, [setDraftMessage]); - - return ( - - {children} -