diff --git a/.github/workflows/auto-pr-dev-to-main.yml b/.github/workflows/auto-pr-dev-to-main.yml new file mode 100644 index 0000000000..cb3be1d24b --- /dev/null +++ b/.github/workflows/auto-pr-dev-to-main.yml @@ -0,0 +1,22 @@ +name: Create PR from dev to main +on: + pull_request: + types: [closed] + branches: + - dev + +jobs: + pull-request: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: pull-request + uses: repo-sync/pull-request@v2 + if: github.event.pull_request.merged == true + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + source_branch: '' + destination_branch: 'main' + pr_title: 'QA Handover PR' + pr_body: ':robot: Automated PR from **${{ github.ref }}** to **main**' + pr_label: 'release' diff --git a/.github/workflows/auto-pr-prebuilt-branch.yml b/.github/workflows/auto-pr-main-to-dev.yml similarity index 66% rename from .github/workflows/auto-pr-prebuilt-branch.yml rename to .github/workflows/auto-pr-main-to-dev.yml index fa6b42d019..482d5df6ea 100644 --- a/.github/workflows/auto-pr-prebuilt-branch.yml +++ b/.github/workflows/auto-pr-main-to-dev.yml @@ -1,4 +1,4 @@ -name: Create PR from main to main-prebuilt +name: Create PR from main to dev on: pull_request: types: [closed] @@ -16,7 +16,7 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} source_branch: '' - destination_branch: 'main-prebuilt' - pr_title: 'PR for Prebuilt Link QA deployment' - pr_body: ':robot: Automated PR from **${{ github.ref }}** to **main-prebuilt**' - pr_label: 'Prebuilt Link QA deployment' + destination_branch: 'dev' + pr_title: 'PR for main to dev backmerge' + pr_body: ':robot: Automated PR from **${{ github.ref }}** to **dev**' + pr_label: 'backmerge' diff --git a/.github/workflows/auto-pr-main-to-production.yml b/.github/workflows/auto-pr-main-to-production.yml new file mode 100644 index 0000000000..3beffc66e0 --- /dev/null +++ b/.github/workflows/auto-pr-main-to-production.yml @@ -0,0 +1,22 @@ +name: Create PR from main to production +on: + pull_request: + types: [closed] + branches: + - main + +jobs: + pull-request: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: pull-request + uses: repo-sync/pull-request@v2 + if: github.event.pull_request.merged == true + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + source_branch: '' + destination_branch: 'production' + pr_title: 'Production release PR' + pr_body: ':robot: Automated PR from **${{ github.ref }}** to **production**' + pr_label: 'release' diff --git a/.github/workflows/auto-pr-production-to-main.yml b/.github/workflows/auto-pr-production-to-main.yml new file mode 100644 index 0000000000..010122df82 --- /dev/null +++ b/.github/workflows/auto-pr-production-to-main.yml @@ -0,0 +1,22 @@ +name: Create PR from production to main +on: + pull_request: + types: [closed] + branches: + - production + +jobs: + pull-request: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: pull-request + uses: repo-sync/pull-request@v2 + if: github.event.pull_request.merged == true + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + source_branch: '' + destination_branch: 'main' + pr_title: 'Hotfix backmerge to main' + pr_body: ':robot: Automated PR from **${{ github.ref }}** to **main**' + pr_label: 'backmerge' diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 1f0e915081..ee61e44764 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -1,15 +1,14 @@ name: Deploy Dev on: workflow_dispatch: - inputs: - buildEnvForDev: - description: 'which env to build - qa/prod for dev-app, applies only if env is dev' - type: 'choice' - required: false - default: prod - options: - - prod - - qa + push: + branches: + - dev + paths-ignore: + - 'cypress/**' + - 'playwright/**' + - 'internal-docs/**' + - '.github/**' jobs: build: @@ -38,6 +37,9 @@ jobs: REACT_APP_ENV: ${{ github.event.inputs.buildEnvForDev }} REACT_APP_ZIPY_KEY: ${{ secrets.ZIPY_KEY }} REACT_APP_ENABLE_BEAM_SPEAKERS_LOGGING: 'true' + REACT_APP_INIT_ENDPOINT: https://prod-in3.100ms.live/init + REACT_APP_ROOM_LAYOUT_ENDPOINT: https://api.100ms.live/v2/layouts/ui + REACT_APP_TOKEN_BY_ROOM_CODE_ENDPOINT: https://auth.100ms.live/v2/token steps: - name: log inputs run: | diff --git a/.github/workflows/deploy-qa.yml b/.github/workflows/deploy-qa.yml index 391cbd4bb4..cc6f02aaee 100644 --- a/.github/workflows/deploy-qa.yml +++ b/.github/workflows/deploy-qa.yml @@ -42,6 +42,9 @@ jobs: 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' + REACT_APP_INIT_ENDPOINT: https://qa-init.100ms.live/init + REACT_APP_ROOM_LAYOUT_ENDPOINT: https://api-nonprod.100ms.live/v2/layouts/ui + REACT_APP_TOKEN_BY_ROOM_CODE_ENDPOINT: https://auth-nonprod.100ms.live/v2/token steps: - name: log inputs diff --git a/apps/100ms-custom-app/example.env b/apps/100ms-custom-app/example.env index ce01452611..61037c4a06 100644 --- a/apps/100ms-custom-app/example.env +++ b/apps/100ms-custom-app/example.env @@ -1,2 +1,5 @@ REACT_APP_ENV= -REACT_APP_HOST_NAME= \ No newline at end of file +REACT_APP_HOST_NAME= +REACT_APP_TOKEN_BY_ROOM_CODE_ENDPOINT= +REACT_APP_ROOM_LAYOUT_ENDPOINT= +REACT_APP_INIT_ENDPOINT= \ No newline at end of file diff --git a/apps/100ms-custom-app/package.json b/apps/100ms-custom-app/package.json index aa4929cb85..6a6465ad34 100644 --- a/apps/100ms-custom-app/package.json +++ b/apps/100ms-custom-app/package.json @@ -3,9 +3,8 @@ "version": "0.1.0", "private": true, "dependencies": { - "100ms_edtech_template": "0.1.4", - "@100mslive/react-icons": "0.8.14", - "@100mslive/roomkit-react": "0.1.5", + "@100mslive/react-icons": "0.8.15-alpha.0", + "@100mslive/roomkit-react": "0.1.6-alpha.0", "axios": "^0.21.1", "js-cookies": "^1.0.4", "lodash.merge": "^4.6.2", diff --git a/apps/100ms-custom-app/src/App.jsx b/apps/100ms-custom-app/src/App.jsx index 074f7c6c0d..4e9ccb3bcd 100644 --- a/apps/100ms-custom-app/src/App.jsx +++ b/apps/100ms-custom-app/src/App.jsx @@ -1,284 +1,58 @@ -import React, { Suspense, useEffect, useRef, useState } from 'react'; -import merge from 'lodash.merge'; -import { logError } from 'zipyai'; -import { Flex, Loading } from '@100mslive/roomkit-react'; +import React, { useEffect, useState } from 'react'; +import { Flex, HMSPrebuilt } from '@100mslive/roomkit-react'; +import { useOverridePrebuiltLayout } from './hooks/useOverridePrebuiltLayout'; +import { useSearchParam } from './hooks/useSearchParam'; import { - apiBasePath, - getAuthInfo, - getAuthTokenByRoomCodeEndpoint, + getAuthTokenUsingRoomIdRole, getRoomCodeFromUrl, - getWithRetry, - mapFromBackend, - mapTileShape, - storeRoomSettings, + getRoomIdRoleFromUrl, } from './utils/utils'; -import logoDark from './assets/images/logo-on-black.png'; -import logoLight from './assets/images/logo-on-white.png'; - -const Header = React.lazy(() => import('./components/Header')); -const RoomSettings = React.lazy(() => import('./components/RoomSettings')); -const ErrorModal = React.lazy(() => import('./components/ErrorModal')); -const HMSEdtechTemplate = React.lazy(() => - // eslint-disable-next-line import/no-unresolved - import('100ms_edtech_template').then(module => ({ - default: module.EdtechComponent, - })) -); -let hostname = window.location.hostname; -if (!hostname.endsWith('app.100ms.live')) { - hostname = process.env.REACT_APP_HOST_NAME || hostname; -} else if (hostname.endsWith('dev-app.100ms.live')) { - // route dev-app appropriately to qa or prod - const envSuffix = - process.env.REACT_APP_ENV === 'prod' - ? 'app.100ms.live' - : 'qa-app.100ms.live'; - hostname = hostname.replace('dev-app.100ms.live', envSuffix); -} else if (hostname.endsWith('staging-app.100ms.live')) { - // route staging-app appropriately to qa or prod - const envSuffix = - process.env.REACT_APP_ENV === 'prod' - ? 'app.100ms.live' - : 'qa-app.100ms.live'; - hostname = hostname.replace('staging-app.100ms.live', envSuffix); -} else if ( - hostname.endsWith('qa-app.100ms.live') && - process.env.REACT_APP_ENV === 'prod' -) { - hostname = hostname.replace('qa-app.100ms.live', 'app.100ms.live'); -} const App = () => { - const prevSavedSettings = useRef({}); - const appInfo = useRef({ app_type: '', app_name: '' }); - const [showSettingsModal, setShowSettingsModal] = useState(false); - const [savingSettings, setSavingSettings] = useState(false); - const [onlyEmail, setOnlyEmail] = useState(false); - const [error, setError] = useState(''); - const [roomLinks, setRoomLinks] = useState({}); - const [settings, setSettings] = useState({ - theme: 'dark', - tile_shape: '1-1', - font: 'Inter', - avatars: 'initial', - brand_color: '#2F80FF', - logo_obj: null, - logo_url: null, - logo_name: null, - recording_url: '', - metadataFields: { - clicks: 0, - metadata: '', - }, - }); + const roomCode = getRoomCodeFromUrl(); + const [authToken, setAuthToken] = useState(useSearchParam('auth_token')); + // added subdomain in query param for easy testing in vercel links + const subdomain = useSearchParam('subdomain') || window.location.hostname; + const { roomId, role } = getRoomIdRoleFromUrl(); + const { overrideLayout, isHeadless } = useOverridePrebuiltLayout(); useEffect(() => { - const code = getRoomCodeFromUrl(); - if (code) { - fetchData(); - } - }, []); - useEffect(() => { - setUpdateMetadataOnWindow(); - }, [settings]); //eslint-disable-line - - const setUpdateMetadataOnWindow = () => { - if (!window.__hmsApp) { - window.__hmsApp = {}; - } - window.__hmsApp.updateMetadata = async metadata => { - try { - const currentMetadata = !settings.metadataFields.metadata - ? {} - : JSON.parse(settings.metadataFields.metadata); - const metaUpdate = JSON.stringify(merge(currentMetadata, metadata)); - console.log(metaUpdate); - await storeRoomSettings({ - hostname, - appInfo: appInfo.current, - settings: { - ...settings, - metadataFields: { - ...settings.metadataFields, - metadata: metaUpdate, - }, - }, + if (!roomCode && !authToken) { + (async function getAuthToken() { + const token = await getAuthTokenUsingRoomIdRole({ + subdomain, + roomId, + role, + userId: 'beam', }); - changeSettings('metadataFields', { - ...settings.metadataFields, - metadata: metaUpdate, - }); - } catch (error) { - console.error(error); - } - }; - }; - - const fetchData = async () => { - const jwt = getAuthInfo().token; - const code = getRoomCodeFromUrl(); - const url = `${apiBasePath}apps/get-details?domain=${hostname}&room_id=${code}`; - const headers = {}; - if (jwt) { - headers['Authorization'] = `Bearer ${jwt}`; + setAuthToken(token); + })(); } - headers['Content-Type'] = 'application/json'; - - getWithRetry(url, headers) - .then(res => { - if (res.data.success) { - let prevSettings = res.data; - const { app_type, app_name } = res.data; - prevSettings = mapFromBackend(prevSettings); - prevSettings = { - theme: prevSettings.theme.toLowerCase(), - tile_shape: mapTileShape(prevSettings.tile_shape), - font: prevSettings.font, - avatars: prevSettings.video_off_avatars, - brand_color: prevSettings.color, - logo_obj: null, - logo_url: prevSettings.logo, - recording_url: prevSettings.recording_url, - logo_name: null, - metadataFields: { - clicks: 0, - metadata: prevSettings.metadata, - }, - }; - setOnlyEmail(res.data.same_user); - prevSavedSettings.current = Object.assign({}, prevSettings); - appInfo.current = { app_name, app_type }; - setRoomLinks(res.data.room_links); - setSettings(prevSettings); - } - }) - .catch(err => { - const errorMessage = `[Get Details] ${err.message}`; - let error = { - title: 'Something went wrong', - body: errorMessage, - }; - logError('getDetailsError', error.body); - if (err.response && err.response.status === 404) { - error = { - title: 'Link is invalid', - body: - err.response.data?.msg || 'Please make sure that link is valid.', - }; - } - setError(error); - console.error(errorMessage); - }); - }; - - const storeSettings = async () => { - setSavingSettings(true); - await storeRoomSettings({ - hostname, - appInfo: appInfo.current, - settings, - }); - setSavingSettings(false); - }; - - const changeSettings = (key, value) => { - setSettings(prevSettings => ({ - ...prevSettings, - [key]: value, - })); - }; - - const toggleModal = () => { - setShowSettingsModal(value => !value); - changeSettings('metadataFields', { - ...settings.metadataFields, - clicks: 0, - }); - }; - - const handleLogoChange = e => { - if (e.target.files && e.target.files[0]) { - const logo_name = e.target.files[0].name; - const logo_url = URL.createObjectURL(e.target.files[0]); - const logo_obj = e.target.files[0]; - setSettings(value => ({ - ...value, - logo_obj, - logo_url, - logo_name, - })); - } - }; - - const saveDetails = () => { - prevSavedSettings.current = settings; - setShowSettingsModal(false); - storeSettings(); - }; + }, [authToken, role, roomCode, roomId, subdomain]); return ( - {error && ( - - - - )} - {onlyEmail && ( - -
- - )} - - {!error && ( - - - - } - > - - - )} - {showSettingsModal && ( - - { - setSettings(Object.assign({}, prevSavedSettings.current)); - setShowSettingsModal(false); - }} - /> - + {(authToken || roomCode) && ( + )} ); diff --git a/apps/100ms-custom-app/src/hooks/useOverridePrebuiltLayout.js b/apps/100ms-custom-app/src/hooks/useOverridePrebuiltLayout.js new file mode 100644 index 0000000000..7c94b461aa --- /dev/null +++ b/apps/100ms-custom-app/src/hooks/useOverridePrebuiltLayout.js @@ -0,0 +1,52 @@ +import { useSearchParam } from './useSearchParam'; + +export const QUERY_PARAM_SKIP_PREVIEW = 'skip_preview'; +export const QUERY_PARAM_SKIP_PREVIEW_HEADFUL = 'skip_preview_headful'; + +export const useOverridePrebuiltLayout = () => { + // way to skip preview for automated tests, beam recording and streaming + const beamInToken = useSearchParam('token') === 'beam_recording'; // old format to remove + // use this field to join directly for quick testing while in local + const directJoinHeadfulFromEnv = + process.env.REACT_APP_HEADLESS_JOIN === 'true'; + const directJoinHeadful = + useSearchParam(QUERY_PARAM_SKIP_PREVIEW_HEADFUL) === 'true' || + directJoinHeadfulFromEnv; + let skipPreview = useSearchParam(QUERY_PARAM_SKIP_PREVIEW) === 'true'; + + let overrideLayout = undefined; + + if (skipPreview || beamInToken) { + overrideLayout = { + preview: null, + }; + overrideLayout.conferencing = { + default: { + hideSections: ['footer', 'header'], + elements: { + video_tile_layout: { + grid: { + enable_local_tile_inset: false, + hide_participant_name_on_tile: true, + hide_audio_level_on_tile: true, + rounded_video_tile: false, + hide_audio_mute_on_tile: true, + video_object_fit: 'cover', + }, + }, + }, + }, + }; + } + + if (directJoinHeadful) { + overrideLayout = { + preview: null, + }; + } + + return { + overrideLayout, + isHeadless: skipPreview || beamInToken || directJoinHeadful, + }; +}; diff --git a/apps/100ms-custom-app/src/hooks/useSearchParam.js b/apps/100ms-custom-app/src/hooks/useSearchParam.js new file mode 100644 index 0000000000..e795f284c0 --- /dev/null +++ b/apps/100ms-custom-app/src/hooks/useSearchParam.js @@ -0,0 +1,7 @@ +export function useSearchParam(param) { + if (typeof window === 'undefined') { + return ''; + } + const url = new URL(window.location.href); + return url.searchParams.get(param); +} diff --git a/apps/100ms-custom-app/src/utils/utils.js b/apps/100ms-custom-app/src/utils/utils.js index a36861cf41..8c89b98f34 100644 --- a/apps/100ms-custom-app/src/utils/utils.js +++ b/apps/100ms-custom-app/src/utils/utils.js @@ -1,10 +1,28 @@ import axios from 'axios'; import cookies from 'js-cookies'; +function isRoomCode(str) { + const regex = /^[A-Za-z]{3}(-[A-Za-z]{3,4}){2}$/; + return regex.test(str); +} + export const getRoomCodeFromUrl = () => { const path = window.location.pathname; const regex = /(\/streaming)?\/(preview|meeting)\/(?[^/]+)/; - return path.match(regex)?.groups?.code || null; + const roomCode = path.match(regex)?.groups?.code || null; + return isRoomCode(roomCode) ? roomCode : null; +}; + +export const getRoomIdRoleFromUrl = () => { + const path = window.location.pathname; + const regex = + /(\/streaming)?\/(preview|meeting)\/(?[^/]+)\/(?[^/]+)/; + const roomId = path.match(regex)?.groups?.roomId || null; + const role = path.match(regex)?.groups?.role || null; + return { + roomId, + role, + }; }; export const getAuthInfo = () => { @@ -32,14 +50,6 @@ const tileShapeMapping = { const env = process.env.REACT_APP_ENV || 'prod'; export const apiBasePath = `https://${env}-in2.100ms.live/hmsapi/`; -const authTokenEndpointByRoomCode = { - qa: 'https://auth-nonprod.100ms.live/v2/token', - dev: 'https://auth-nonprod.100ms.live/v2/token', -}; - -export const getAuthTokenByRoomCodeEndpoint = () => { - return authTokenEndpointByRoomCode[env] || ''; -}; export const storeRoomSettings = async ({ hostname, settings, appInfo }) => { const jwt = getAuthInfo().token; @@ -150,3 +160,26 @@ export const getWithRetry = async (url, headers) => { console.error('max retry done for get-details', error); throw error; }; + +export const getAuthTokenUsingRoomIdRole = async function ({ + subdomain = '', + roomId = '', + role = '', + userId = '', +}) { + try { + const resp = await fetch(`${apiBasePath}${subdomain}/api/token`, { + method: 'POST', + body: JSON.stringify({ + room_id: roomId, + role, + user_id: userId, + }), + }); + const { token = '' } = await resp.json(); + return token; + } catch (e) { + console.error('failed to getAuthTokenUsingRoomIdRole', e); + throw Error('failed to get auth token using roomid and role'); + } +}; diff --git a/apps/100ms-web/package.json b/apps/100ms-web/package.json index 74bcf71318..78f3bae108 100644 --- a/apps/100ms-web/package.json +++ b/apps/100ms-web/package.json @@ -9,11 +9,11 @@ "src" ], "dependencies": { - "@100mslive/hls-player": "0.1.14", - "@100mslive/hms-virtual-background": "1.11.14", - "@100mslive/react-icons": "0.8.14", - "@100mslive/react-sdk": "0.8.14", - "@100mslive/roomkit-react": "0.1.5", + "@100mslive/hls-player": "0.1.15-alpha.0", + "@100mslive/hms-virtual-background": "1.11.15-alpha.0", + "@100mslive/react-icons": "0.8.15-alpha.0", + "@100mslive/react-sdk": "0.8.15-alpha.0", + "@100mslive/roomkit-react": "0.1.6-alpha.0", "@emoji-mart/data": "^1.0.6", "@emoji-mart/react": "^1.0.1", "@tldraw/tldraw": "^1.18.4", diff --git a/packages/hls-player/package.json b/packages/hls-player/package.json index dd8c15b110..30efad914e 100644 --- a/packages/hls-player/package.json +++ b/packages/hls-player/package.json @@ -1,6 +1,6 @@ { "name": "@100mslive/hls-player", - "version": "0.1.14", + "version": "0.1.15-alpha.0", "description": "HLS client library which uses HTML5 Video element and Media Source Extension for playback", "main": "dist/index.cjs.js", "module": "dist/index.js", @@ -31,7 +31,7 @@ "author": "100ms", "license": "MIT", "dependencies": { - "@100mslive/hls-stats": "0.2.14", + "@100mslive/hls-stats": "0.2.15-alpha.0", "eventemitter2": "^6.4.7", "hls.js": "^1.3.0" } diff --git a/packages/hls-stats/package.json b/packages/hls-stats/package.json index 86d62d20d5..4a3bfeff90 100644 --- a/packages/hls-stats/package.json +++ b/packages/hls-stats/package.json @@ -1,6 +1,6 @@ { "name": "@100mslive/hls-stats", - "version": "0.2.14", + "version": "0.2.15-alpha.0", "description": "A simple library that provides stats for your hls stream", "main": "dist/index.cjs.js", "module": "dist/index.js", diff --git a/packages/hms-noise-suppression/package.json b/packages/hms-noise-suppression/package.json index 6dbf4ab7ff..5f47b872db 100644 --- a/packages/hms-noise-suppression/package.json +++ b/packages/hms-noise-suppression/package.json @@ -1,5 +1,5 @@ { - "version": "0.9.14", + "version": "0.9.15-alpha.0", "license": "MIT", "main": "dist/index.cjs.js", "typings": "dist/index.d.ts", @@ -37,6 +37,6 @@ "author": "vishaldhull09", "module": "dist/index.js", "devDependencies": { - "@100mslive/hms-video": "0.9.14" + "@100mslive/hms-video": "0.9.15-alpha.0" } } diff --git a/packages/hms-video-store/package.json b/packages/hms-video-store/package.json index d81bc4962e..76e089b20d 100644 --- a/packages/hms-video-store/package.json +++ b/packages/hms-video-store/package.json @@ -1,5 +1,5 @@ { - "version": "0.10.14", + "version": "0.10.15-alpha.0", "license": "MIT", "main": "dist/index.cjs.js", "module": "dist/index.js", @@ -41,7 +41,7 @@ "author": "100ms", "sideEffects": false, "dependencies": { - "@100mslive/hms-video": "0.9.14", + "@100mslive/hms-video": "0.9.15-alpha.0", "eventemitter2": "^6.4.7", "immer": "^9.0.6", "reselect": "4.0.0", diff --git a/packages/hms-video-web/package.json b/packages/hms-video-web/package.json index cf81374253..f2b9e6298f 100644 --- a/packages/hms-video-web/package.json +++ b/packages/hms-video-web/package.json @@ -1,6 +1,6 @@ { "name": "@100mslive/hms-video", - "version": "0.9.14", + "version": "0.9.15-alpha.0", "license": "MIT", "main": "dist/index.cjs.js", "typings": "dist/index.d.ts", diff --git a/packages/hms-virtual-background/package.json b/packages/hms-virtual-background/package.json index b6d2d7dd47..6b2bcc80f9 100755 --- a/packages/hms-virtual-background/package.json +++ b/packages/hms-virtual-background/package.json @@ -1,5 +1,5 @@ { - "version": "1.11.14", + "version": "1.11.15-alpha.0", "license": "MIT", "main": "dist/index.cjs.js", "typings": "dist/index.d.ts", @@ -30,7 +30,7 @@ "author": "ashish17", "module": "dist/index.js", "devDependencies": { - "@100mslive/hms-video": "0.9.14" + "@100mslive/hms-video": "0.9.15-alpha.0" }, "dependencies": { "@mediapipe/selfie_segmentation": "^0.1.1632777926", diff --git a/packages/react-icons/package.json b/packages/react-icons/package.json index 0fec0462fd..4bebe690c8 100644 --- a/packages/react-icons/package.json +++ b/packages/react-icons/package.json @@ -4,7 +4,7 @@ "main": "dist/index.cjs.js", "module": "dist/index.js", "typings": "dist/index.d.ts", - "version": "0.8.14", + "version": "0.8.15-alpha.0", "author": "100ms", "license": "MIT", "files": [ diff --git a/packages/react-sdk/package.json b/packages/react-sdk/package.json index 861efbf2cd..b1f7503388 100644 --- a/packages/react-sdk/package.json +++ b/packages/react-sdk/package.json @@ -4,7 +4,7 @@ "main": "dist/index.cjs.js", "module": "dist/index.js", "typings": "dist/index.d.ts", - "version": "0.8.14", + "version": "0.8.15-alpha.0", "author": "100ms", "license": "MIT", "files": [ @@ -43,7 +43,7 @@ "react": ">=16.8 <19.0.0" }, "dependencies": { - "@100mslive/hms-video-store": "0.10.14", + "@100mslive/hms-video-store": "0.10.15-alpha.0", "react-resize-detector": "^7.0.0", "zustand": "^3.6.2" } diff --git a/packages/roomkit-react/package.json b/packages/roomkit-react/package.json index 59a48e337b..be17910c6e 100644 --- a/packages/roomkit-react/package.json +++ b/packages/roomkit-react/package.json @@ -10,7 +10,7 @@ "prebuilt", "roomkit" ], - "version": "0.1.5", + "version": "0.1.6-alpha.0", "author": "100ms", "license": "MIT", "files": [ @@ -75,11 +75,11 @@ "react": ">=17.0.2 <19.0.0" }, "dependencies": { - "@100mslive/hls-player": "0.1.14", - "@100mslive/hms-virtual-background": "1.11.14", - "@100mslive/react-icons": "0.8.14", - "@100mslive/react-sdk": "0.8.14", - "@100mslive/types-prebuilt": "0.10.0", + "@100mslive/hls-player": "0.1.15-alpha.0", + "@100mslive/hms-virtual-background": "1.11.15-alpha.0", + "@100mslive/react-icons": "0.8.15-alpha.0", + "@100mslive/react-sdk": "0.8.15-alpha.0", + "@100mslive/types-prebuilt": "0.11.0", "@emoji-mart/data": "^1.0.6", "@emoji-mart/react": "^1.0.1", "@radix-ui/react-accordion": "1.0.0", diff --git a/packages/roomkit-react/src/Prebuilt/App.tsx b/packages/roomkit-react/src/Prebuilt/App.tsx index 6f4e96909a..416136df7e 100644 --- a/packages/roomkit-react/src/Prebuilt/App.tsx +++ b/packages/roomkit-react/src/Prebuilt/App.tsx @@ -32,17 +32,18 @@ import PostLeave from './components/PostLeave'; import PreviewContainer from './components/Preview/PreviewContainer'; // @ts-ignore: No implicit Any import { ToastContainer } from './components/Toast/ToastContainer'; -import { RoomLayoutContext, RoomLayoutProvider } from './provider/roomLayoutProvider'; +import { RoomLayoutContext, RoomLayoutProvider, useRoomLayout } from './provider/roomLayoutProvider'; import { Box } from '../Layout'; import { globalStyles, HMSThemeProvider } from '../Theme'; -// @ts-ignore: No implicit Any import { HMSPrebuiltContext, useHMSPrebuiltContext } from './AppContext'; // @ts-ignore: No implicit Any import { FlyingEmoji } from './plugins/FlyingEmoji'; // @ts-ignore: No implicit Any import { RemoteStopScreenshare } from './plugins/RemoteStopScreenshare'; -// @ts-ignore: No implicit Any -import { getRoutePrefix } from './common/utils'; +import { + useRoomLayoutLeaveScreen, + useRoomLayoutPreviewScreen, +} from './provider/roomLayoutProvider/hooks/useRoomLayoutScreen'; // @ts-ignore: No implicit Any import { FeatureFlags } from './services/FeatureFlags'; @@ -62,6 +63,9 @@ export type HMSPrebuiltProps = { themes?: Theme[]; options?: HMSPrebuiltOptions; screens?: Screens; + authToken?: string; + roomId?: string; + role?: string; onLeave?: () => void; }; @@ -86,6 +90,9 @@ export const HMSPrebuilt = React.forwardRef - {layout => { + {data => { + const layout = data?.layout; const theme: Theme = layout?.themes?.[0] || ({} as Theme); const { typography } = layout || {}; let fontFamily = ['sans-serif']; @@ -219,7 +237,7 @@ export const HMSPrebuilt = React.forwardRef - + ); @@ -237,26 +255,15 @@ HMSPrebuilt.displayName = 'HMSPrebuilt'; const Redirector = ({ showPreview }: { showPreview: boolean }) => { const { roomId, role } = useParams(); - - if (!roomId && !role) { - return ; - } - if (!roomId) { - return ; - } - if (['streaming', 'preview', 'meeting', 'leave'].includes(roomId) && !role) { - return ; - } - - return ; + return ; }; const RouteList = () => { - const { showPreview, showLeave } = useHMSPrebuiltContext(); - + const { isPreviewScreenEnabled } = useRoomLayoutPreviewScreen(); + const { isLeaveScreenEnabled } = useRoomLayoutLeaveScreen(); return ( - {showPreview && ( + {isPreviewScreenEnabled ? ( { } /> - )} + ) : null} { } /> - {showLeave && ( + {isLeaveScreenEnabled ? ( } /> } /> - )} + ) : null} - } /> - } /> + } /> + } /> ); }; @@ -335,7 +342,14 @@ const Router = ({ children }: { children: ReactElement }) => { ); }; -function AppRoutes({ authTokenByRoomCodeEndpoint }: { authTokenByRoomCodeEndpoint: string }) { +function AppRoutes({ + authTokenByRoomCodeEndpoint, + defaultAuthToken, +}: { + authTokenByRoomCodeEndpoint: string; + defaultAuthToken?: string; +}) { + const roomLayout = useRoomLayout(); return ( <> @@ -346,10 +360,12 @@ function AppRoutes({ authTokenByRoomCodeEndpoint }: { authTokenByRoomCodeEndpoin - - - } /> - + + {roomLayout && ( + + } /> + + )} ); diff --git a/packages/roomkit-react/src/Prebuilt/AppContext.jsx b/packages/roomkit-react/src/Prebuilt/AppContext.tsx similarity index 62% rename from packages/roomkit-react/src/Prebuilt/AppContext.jsx rename to packages/roomkit-react/src/Prebuilt/AppContext.tsx index bdae5d1957..ae3df08daf 100644 --- a/packages/roomkit-react/src/Prebuilt/AppContext.jsx +++ b/packages/roomkit-react/src/Prebuilt/AppContext.tsx @@ -1,8 +1,16 @@ import React, { useContext } from 'react'; -export const HMSPrebuiltContext = React.createContext({ - showPreview: true, - showLeave: true, +type HMSPrebuiltContextType = { + roomCode: string; + roomId?: string; + role?: string; + userName?: string; + userId?: string; + endpoints?: object; + onLeave?: () => void; +}; + +export const HMSPrebuiltContext = React.createContext({ roomCode: '', userName: '', userId: '', diff --git a/packages/roomkit-react/src/Prebuilt/common/constants.js b/packages/roomkit-react/src/Prebuilt/common/constants.js index 17c1ca8273..13840befed 100644 --- a/packages/roomkit-react/src/Prebuilt/common/constants.js +++ b/packages/roomkit-react/src/Prebuilt/common/constants.js @@ -1,13 +1,10 @@ import { parsedUserAgent } from '@100mslive/react-sdk'; -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_GRID = 'grid'; export const MAX_TOASTS = 5; diff --git a/packages/roomkit-react/src/Prebuilt/common/hooks.js b/packages/roomkit-react/src/Prebuilt/common/hooks.js index a97c404178..73ef301c8e 100644 --- a/packages/roomkit-react/src/Prebuilt/common/hooks.js +++ b/packages/roomkit-react/src/Prebuilt/common/hooks.js @@ -4,7 +4,6 @@ import { JoinForm_JoinBtnType } from '@100mslive/types-prebuilt/elements/join_fo import { selectAvailableRoleNames, selectIsConnectedToRoom, - selectLocalPeerRoleName, selectPeerCount, selectPeerMetadata, selectPeers, @@ -13,7 +12,6 @@ import { useHMSVanillaStore, } from '@100mslive/react-sdk'; import { useRoomLayout } from '../provider/roomLayoutProvider'; -import { useHLSViewerRole } from '../components/AppData/useUISettings'; import { isInternalRole } from './utils'; /** @@ -65,12 +63,6 @@ export const useShowStreamingUI = () => { return join_form?.join_btn_type === JoinForm_JoinBtnType.JOIN_BTN_TYPE_JOIN_AND_GO_LIVE; }; -export const useIsLocalPeerHLSViewer = () => { - const localPeerRoleName = useHMSStore(selectLocalPeerRoleName); - const hlsViewerRole = useHLSViewerRole(); - return localPeerRoleName === hlsViewerRole; -}; - // The search results should not have role name matches export const useParticipants = params => { const isConnected = useHMSStore(selectIsConnectedToRoom); diff --git a/packages/roomkit-react/src/Prebuilt/common/utils.js b/packages/roomkit-react/src/Prebuilt/common/utils.js index 819f001fda..af285abfae 100644 --- a/packages/roomkit-react/src/Prebuilt/common/utils.js +++ b/packages/roomkit-react/src/Prebuilt/common/utils.js @@ -56,14 +56,6 @@ 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 => { diff --git a/packages/roomkit-react/src/Prebuilt/components/AppData/AppData.jsx b/packages/roomkit-react/src/Prebuilt/components/AppData/AppData.jsx index 519adbfb70..14d96ee75a 100644 --- a/packages/roomkit-react/src/Prebuilt/components/AppData/AppData.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/AppData/AppData.jsx @@ -16,12 +16,9 @@ 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, SIDE_PANE_OPTIONS, UI_MODE_GRID, @@ -63,7 +60,6 @@ const initialAppData = { [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.authToken]: '', @@ -108,7 +104,6 @@ export const AppData = React.memo(({ appDetails, tokenEndpoint }) => { useEffect(() => { const appData = { [APP_DATA.tokenEndpoint]: tokenEndpoint, - [APP_DATA.hlsViewerRole]: getMetadata(appDetails)[DEFAULT_HLS_ROLE_KEY] || DEFAULT_HLS_VIEWER_ROLE, [APP_DATA.appConfig]: getAppDetails(appDetails), }; for (const key in appData) { diff --git a/packages/roomkit-react/src/Prebuilt/components/AppData/useUISettings.js b/packages/roomkit-react/src/Prebuilt/components/AppData/useUISettings.js index f381035919..9ba927c737 100644 --- a/packages/roomkit-react/src/Prebuilt/components/AppData/useUISettings.js +++ b/packages/roomkit-react/src/Prebuilt/components/AppData/useUISettings.js @@ -51,10 +51,6 @@ export const useIsHeadless = () => { return isHeadless; }; -export const useHLSViewerRole = () => { - return useHMSStore(selectAppData(APP_DATA.hlsViewerRole)); -}; - export const useWaitingViewerRole = () => { return useHMSStore(selectAppData(APP_DATA.waitingViewerRole)); }; diff --git a/packages/roomkit-react/src/Prebuilt/components/AuthToken.jsx b/packages/roomkit-react/src/Prebuilt/components/AuthToken.jsx index 666d3ccfd8..2cc6050479 100644 --- a/packages/roomkit-react/src/Prebuilt/components/AuthToken.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/AuthToken.jsx @@ -1,14 +1,10 @@ -import React, { useEffect, useMemo, useState } from 'react'; -import { matchPath, useLocation } from 'react-router-dom'; -import { useSearchParam } from 'react-use'; -import { v4 as uuid } from 'uuid'; +import React, { useEffect, useState } from 'react'; import { useHMSActions } from '@100mslive/react-sdk'; import { styled } from '../../Theme'; import { useHMSPrebuiltContext } from '../AppContext'; import { ErrorDialog } from '../primitives/DialogContent'; import { useSetAppDataByKey, useTokenEndpoint } from './AppData/useUISettings'; -import getToken from '../services/tokenService'; -import { APP_DATA, QUERY_PARAM_AUTH_TOKEN } from '../common/constants'; +import { APP_DATA } from '../common/constants'; /** * query params exposed - @@ -19,20 +15,12 @@ import { APP_DATA, QUERY_PARAM_AUTH_TOKEN } from '../common/constants'; * auth_token=123 => uses the passed in token to join instead of fetching from token endpoint * ui_mode=activespeaker => lands in active speaker mode after joining the room */ -const AuthToken = React.memo(({ authTokenByRoomCodeEndpoint }) => { +const AuthToken = React.memo(({ authTokenByRoomCodeEndpoint, defaultAuthToken }) => { const hmsActions = useHMSActions(); const tokenEndpoint = useTokenEndpoint(); - const { showPreview, roomCode, userId } = useHMSPrebuiltContext(); - const location = useLocation(); - const matches = useMemo( - () => - matchPath(`${showPreview ? 'preview' : 'meeting'}/:roomId/:role`, location.pathname) || - matchPath(`${showPreview ? 'preview' : 'meeting'}/:roomCode/`, location.pathname), - [location, showPreview], - ); - const { roomCode: urlRoomCode, roomId: urlRoomId, role: userRole } = matches?.params || {}; + const { roomCode, userId } = useHMSPrebuiltContext(); const [error, setError] = useState({ title: '', body: '' }); - let authToken = useSearchParam(QUERY_PARAM_AUTH_TOKEN); + let authToken = defaultAuthToken; const [, setAuthTokenInAppData] = useSetAppDataByKey(APP_DATA.authToken); useEffect(() => { @@ -40,34 +28,15 @@ const AuthToken = React.memo(({ authTokenByRoomCodeEndpoint }) => { setAuthTokenInAppData(authToken); return; } - if (!tokenEndpoint && !urlRoomId && !roomCode && !urlRoomCode) { + if (!tokenEndpoint && !roomCode) { return; } - const code = !userRole && (roomCode || urlRoomCode); - const getTokenFn = code - ? () => hmsActions.getAuthTokenByRoomCode({ roomCode: code, userId }, { endpoint: authTokenByRoomCodeEndpoint }) - : () => getToken(tokenEndpoint, uuid(), userRole, urlRoomId); - - getTokenFn() - .then(token => { - setAuthTokenInAppData(token); - }) - .catch(error => { - setError(convertError(error)); - }); - }, [ - hmsActions, - tokenEndpoint, - urlRoomId, - urlRoomCode, - userRole, - authToken, - authTokenByRoomCodeEndpoint, - setAuthTokenInAppData, - roomCode, - userId, - ]); + hmsActions + .getAuthTokenByRoomCode({ roomCode, userId }, { endpoint: authTokenByRoomCodeEndpoint }) + .then(token => setAuthTokenInAppData(token)) + .catch(error => setError(convertError(error))); + }, [hmsActions, tokenEndpoint, authToken, authTokenByRoomCodeEndpoint, setAuthTokenInAppData, roomCode, userId]); if (error.title) { return {error.body}; diff --git a/packages/roomkit-react/src/Prebuilt/components/Chat/Chat.jsx b/packages/roomkit-react/src/Prebuilt/components/Chat/Chat.jsx index 33f50e86b4..55dddb4bf2 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Chat/Chat.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Chat/Chat.jsx @@ -21,7 +21,6 @@ import { ChatParticipantHeader } from './ChatParticipantHeader'; import { useSetSubscribedChatSelector } from '../AppData/useUISettings'; import { useSetPinnedMessage } from '../hooks/useSetPinnedMessage'; import { useUnreadCount } from './useUnreadCount'; -import { useIsLocalPeerHLSViewer, useShowStreamingUI } from '../../common/hooks'; import { CHAT_SELECTOR, SESSION_STORE_KEY } from '../../common/constants'; const PINNED_MESSAGE_LENGTH = 80; @@ -67,7 +66,7 @@ const PinnedMessage = ({ clearPinnedMessage }) => { ) : null; }; -export const Chat = () => { +export const Chat = ({ screenType }) => { const notification = useHMSNotifications(HMSNotificationTypes.PEER_LEFT); const [peerSelector, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.PEER_ID); const [roleSelector, setRoleSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.ROLE); @@ -94,9 +93,6 @@ export const Chat = () => { const storeMessageSelector = selectHMSMessagesCount; const isMobile = useMedia(cssConfig.media.md); - const showStreamingUI = useShowStreamingUI(); - const isHLSViewer = useIsLocalPeerHLSViewer(); - const mwebStreaming = isMobile && (showStreamingUI || isHLSViewer); const messagesCount = useHMSStore(storeMessageSelector) || 0; const scrollToBottom = useCallback( @@ -113,8 +109,8 @@ export const Chat = () => { ); return ( - - {!mwebStreaming ? ( + + {!isMobile ? ( <> setSelectorOpen(value => !value)} /> @@ -126,12 +122,13 @@ export const Chat = () => { peerId={chatOptions.peerId} ref={listRef} scrollToBottom={scrollToBottom} - mwebStreaming={mwebStreaming} + screenType={screenType} /> scrollToBottom(1)} selection={chatOptions.selection} + screenType={screenType} onSelect={({ role, peerId, selection }) => { setChatOptions({ role, diff --git a/packages/roomkit-react/src/Prebuilt/components/Chat/ChatBody.jsx b/packages/roomkit-react/src/Prebuilt/components/Chat/ChatBody.jsx index 7a82997abe..861f91f3cf 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Chat/ChatBody.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Chat/ChatBody.jsx @@ -1,4 +1,4 @@ -import React, { Fragment, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'; +import React, { Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { useInView } from 'react-intersection-observer'; import { useMedia } from 'react-use'; import AutoSizer from 'react-virtualized-auto-sizer'; @@ -24,7 +24,6 @@ import { Tooltip } from '../../../Tooltip'; import emptyChat from '../../images/empty-chat.svg'; import { ToastManager } from '../Toast/ToastManager'; import { useSetPinnedMessage } from '../hooks/useSetPinnedMessage'; -import { useIsLocalPeerHLSViewer, useShowStreamingUI } from '../../common/hooks'; const formatTime = date => { if (!(date instanceof Date)) { @@ -204,9 +203,6 @@ const ChatMessage = React.memo(({ index, style = {}, message, setRowHeight, onPi } }, [index, setRowHeight]); const isMobile = useMedia(cssConfig.media.md); - const isHLSViewer = useIsLocalPeerHLSViewer(); - const showStreamingUI = useShowStreamingUI(); - const mwebStreaming = isMobile && (showStreamingUI || isHLSViewer); const hmsActions = useHMSActions(); const localPeerId = useHMSStore(selectLocalPeerID); @@ -237,7 +233,7 @@ const ChatMessage = React.memo(({ index, style = {}, message, setRowHeight, onPi css={{ flexWrap: 'wrap', // Theme independent color, token should not be used for transparent chat - bg: messageType ? (mwebStreaming ? 'rgba(0, 0, 0, 0.64)' : '$surface_default') : undefined, + bg: messageType ? (isMobile ? 'rgba(0, 0, 0, 0.64)' : '$surface_default') : undefined, r: messageType ? '$1' : undefined, px: messageType ? '$4' : '$2', py: messageType ? '$4' : 0, @@ -269,7 +265,7 @@ const ChatMessage = React.memo(({ index, style = {}, message, setRowHeight, onPi )} - {!mwebStreaming ? ( + {!isMobile ? ( - {!mwebStreaming ? ( + {!isMobile ? ( ) : null} @@ -390,20 +386,22 @@ const VirtualizedChatMessages = React.forwardRef(({ messages, scrollToBottom }, ); }); -export const ChatBody = React.forwardRef(({ role, peerId, scrollToBottom, mwebStreaming }, listRef) => { +export const ChatBody = React.forwardRef(({ role, peerId, scrollToBottom }, listRef) => { const storeMessageSelector = role ? selectMessagesByRole(role) : peerId ? selectMessagesByPeerID(peerId) : selectHMSMessages; - const messages = useHMSStore(storeMessageSelector) || []; + let messages = useHMSStore(storeMessageSelector); + messages = useMemo(() => messages?.filter(message => message.type === 'chat') || [], [messages]); + const isMobile = useMedia(cssConfig.media.md); - if (messages.length === 0 && !mwebStreaming) { + if (messages.length === 0 && !isMobile) { return ( { +export const ChatFooter = ({ role, peerId, onSend, children /* onSelect, selection, screenType */ }) => { const hmsActions = useHMSActions(); const inputRef = useRef(null); const [draftMessage, setDraftMessage] = useChatDraftMessage(); const isMobile = useMedia(cssConfig.media.md); - const isHLSViewer = useIsLocalPeerHLSViewer(); - const showStreamingUI = useShowStreamingUI(); const sendMessage = useCallback(async () => { const message = inputRef.current.value; @@ -109,14 +106,14 @@ export const ChatFooter = ({ role, peerId, onSend, children, onSelect, selection return ( <> - {!isHLSViewer ? ( + {/* {screenType !== 'hls_live_streaming' ? ( - ) : null} + ) : null} */} diff --git a/packages/roomkit-react/src/Prebuilt/components/Chat/ChatSelectorContainer.jsx b/packages/roomkit-react/src/Prebuilt/components/Chat/ChatSelectorContainer.jsx index e6d6d31f87..4655b9edd2 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Chat/ChatSelectorContainer.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Chat/ChatSelectorContainer.jsx @@ -7,13 +7,11 @@ import { Sheet } from '../../../Sheet'; import { Text } from '../../../Text'; import { config as cssConfig } from '../../../Theme'; import { ChatSelector } from './ChatSelector'; -import { useShowStreamingUI } from '../../common/hooks'; import { textEllipsis } from '../../../utils'; export const ChatSelectorContainer = ({ onSelect, role, peerId, selection }) => { const [open, setOpen] = useState(false); const isMobile = useMedia(cssConfig.media.md); - const showStreamingUI = useShowStreamingUI(); return ( @@ -51,7 +49,7 @@ export const ChatSelectorContainer = ({ onSelect, role, peerId, selection }) => align="start" sideOffset={8} > - {isMobile && showStreamingUI ? ( + {isMobile ? ( setOpen(value)}> {!hideLabel ? ( - - {pinned && ( - - - - )} - {spotlighted && ( - - - - )} - - {name} - - + <> + + {pinned && ( + + + + )} + {spotlighted && ( + + + + )} + + {name} + + + + ) : null} - ); }; diff --git a/packages/roomkit-react/src/Prebuilt/components/EmojiReaction.jsx b/packages/roomkit-react/src/Prebuilt/components/EmojiReaction.jsx index b5e2191f63..760559df6a 100644 --- a/packages/roomkit-react/src/Prebuilt/components/EmojiReaction.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/EmojiReaction.jsx @@ -1,4 +1,4 @@ -import React, { Fragment, useCallback, useMemo, useState } from 'react'; +import React, { Fragment, useCallback, useState } from 'react'; import { useMedia } from 'react-use'; import data from '@emoji-mart/data/sets/14/apple.json'; import { init } from 'emoji-mart'; @@ -7,19 +7,18 @@ import { selectIsConnectedToRoom, selectLocalPeerID, useCustomEvent, - useHMSActions, + // useHMSActions, useHMSStore, - useRecordingStreaming, + // useRecordingStreaming, } from '@100mslive/react-sdk'; import { EmojiIcon } from '@100mslive/react-icons'; import { EmojiCard } from './Footer/EmojiCard'; -import { ToastManager } from './Toast/ToastManager'; +// import { ToastManager } from './Toast/ToastManager'; import { Dropdown } from '../../Dropdown'; import { Box } from '../../Layout'; import { config as cssConfig } from '../../Theme'; import { Tooltip } from '../../Tooltip'; import IconButton from '../IconButton'; -import { useHLSViewerRole } from './AppData/useUISettings'; import { useDropdownList } from './hooks/useDropdownList'; import { EMOJI_REACTION_TYPE } from '../common/constants'; @@ -29,12 +28,10 @@ export const EmojiReaction = () => { const [open, setOpen] = useState(false); const isConnected = useHMSStore(selectIsConnectedToRoom); useDropdownList({ open: open, name: 'EmojiReaction' }); - const hmsActions = useHMSActions(); + // const hmsActions = useHMSActions(); const roles = useHMSStore(selectAvailableRoleNames); const localPeerId = useHMSStore(selectLocalPeerID); - const hlsViewerRole = useHLSViewerRole(); - const { isStreamingOn } = useRecordingStreaming(); - const filteredRoles = useMemo(() => roles.filter(role => role !== hlsViewerRole), [roles, hlsViewerRole]); + // const { isStreamingOn } = useRecordingStreaming(); const isMobile = useMedia(cssConfig.media.md); const onEmojiEvent = useCallback(data => { @@ -52,8 +49,9 @@ export const EmojiReaction = () => { emojiId: emojiId, senderId: localPeerId, }; - sendEvent(data, { roleNames: filteredRoles }); - if (isStreamingOn) { + // TODO: RT find a way to figure out hls-viewer roles + sendEvent(data, { roleNames: roles }); + /* if (isStreamingOn) { try { await hmsActions.sendHLSTimedMetadata([ { @@ -65,7 +63,7 @@ export const EmojiReaction = () => { console.log(error); ToastManager.addToast({ title: error.message }); } - } + } */ }; if (!isConnected) { diff --git a/packages/roomkit-react/src/Prebuilt/components/FirstPersonDisplay.jsx b/packages/roomkit-react/src/Prebuilt/components/FirstPersonDisplay.jsx deleted file mode 100644 index 1cd20609b2..0000000000 --- a/packages/roomkit-react/src/Prebuilt/components/FirstPersonDisplay.jsx +++ /dev/null @@ -1,50 +0,0 @@ -import React from 'react'; -import { Box, Flex } from '../../Layout'; -import { Text } from '../../Text'; -import PlaceholderBg from '../images/first_person.png'; - -export const FirstPersonDisplay = React.memo(() => { - return ( - - - - Welcome! - - - You’re the first one here. - - - Sit back and relax till the others join. - - - - ); -}); diff --git a/packages/roomkit-react/src/Prebuilt/components/Footer/Footer.jsx b/packages/roomkit-react/src/Prebuilt/components/Footer/Footer.tsx similarity index 53% rename from packages/roomkit-react/src/Prebuilt/components/Footer/Footer.jsx rename to packages/roomkit-react/src/Prebuilt/components/Footer/Footer.tsx index fe356c2006..c2c8ee3ab9 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Footer/Footer.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Footer/Footer.tsx @@ -1,22 +1,36 @@ import React from 'react'; import { useMedia } from 'react-use'; -import { selectLocalPeerRoleName, useHMSStore } from '@100mslive/react-sdk'; -import { config as cssConfig, Footer as AppFooter } from '../../../'; +import { + ConferencingScreen, + DefaultConferencingScreen_Elements, + HLSLiveStreamingScreen_Elements, +} from '@100mslive/types-prebuilt'; +import { config as cssConfig, Footer as AppFooter } from '../../..'; +// @ts-ignore: No implicit Any import { AudioVideoToggle } from '../AudioVideoToggle'; +// @ts-ignore: No implicit Any import { EmojiReaction } from '../EmojiReaction'; -import { LeaveRoom } from '../LeaveRoom'; +// @ts-ignore: No implicit Any +import { LeaveRoom } from '../Leave/LeaveRoom'; +// @ts-ignore: No implicit Any import { MoreSettings } from '../MoreSettings/MoreSettings'; +// @ts-ignore: No implicit Any import { RaiseHand } from '../RaiseHand'; +// @ts-ignore: No implicit Any import { ScreenshareToggle } from '../ScreenShareToggle'; +// @ts-ignore: No implicit Any import { ChatToggle } from './ChatToggle'; +// @ts-ignore: No implicit Any import { ParticipantCount } from './ParticipantList'; -import { useHLSViewerRole } from '../AppData/useUISettings'; -export const Footer = () => { +export const Footer = ({ + screenType, + elements, +}: { + screenType: keyof ConferencingScreen; + elements: DefaultConferencingScreen_Elements | HLSLiveStreamingScreen_Elements; +}) => { const isMobile = useMedia(cssConfig.media.md); - const localPeerRole = useHMSStore(selectLocalPeerRoleName); - const hlsViewerRole = useHLSViewerRole(); - const isHlsViewer = hlsViewerRole === localPeerRole; return ( { }, }} > - {isMobile ? : null} + {isMobile ? : null} { > {isMobile ? ( <> - {isHlsViewer ? : null} - - + {screenType === 'hls_live_streaming' ? : null} + {elements?.chat && } + ) : ( <> - {isHlsViewer ? : null} - - + {screenType === 'hls_live_streaming' ? : null} + {elements?.emoji_reactions && } + )} - + {elements?.chat && } - + ); diff --git a/packages/roomkit-react/src/Prebuilt/components/Footer/ParticipantList.jsx b/packages/roomkit-react/src/Prebuilt/components/Footer/ParticipantList.jsx index 0a472bf126..b91d6ac266 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Footer/ParticipantList.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Footer/ParticipantList.jsx @@ -28,7 +28,7 @@ import { RoleChangeModal } from '../RoleChangeModal'; import { ToastManager } from '../Toast/ToastManager'; import { RoleAccordion } from './RoleAccordion'; import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane'; -import { useParticipants, useShowStreamingUI } from '../../common/hooks'; +import { useParticipants } from '../../common/hooks'; import { isInternalRole } from '../../common/utils'; import { SIDE_PANE_OPTIONS } from '../../common/constants'; @@ -62,7 +62,7 @@ export const ParticipantList = () => { return ( - + {!filter?.search && participants.length === 0 ? null : } {participants.length === 0 ? ( @@ -138,7 +138,6 @@ const VirtualizedParticipants = ({ direction="column" css={{ gap: '$8', - mt: '$4', maxHeight: '100%', overflowY: 'auto', overflowX: 'hidden', @@ -339,7 +338,6 @@ const ParticipantMoreActions = ({ onRoleChange, peerId, role }) => { export const ParticipantSearch = ({ onSearch, placeholder, inSidePane = false }) => { const [value, setValue] = React.useState(''); const isMobile = useMedia(cssConfig.media.md); - const showStreamingUI = useShowStreamingUI(); useDebounce( () => { @@ -352,18 +350,18 @@ export const ParticipantSearch = ({ onSearch, placeholder, inSidePane = false }) - + { event.stopPropagation(); diff --git a/packages/roomkit-react/src/Prebuilt/components/Header/Header.jsx b/packages/roomkit-react/src/Prebuilt/components/Header/Header.jsx deleted file mode 100644 index 316239de3f..0000000000 --- a/packages/roomkit-react/src/Prebuilt/components/Header/Header.jsx +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import { ConferencingHeader } from './ConferencingHeader'; -import { StreamingHeader } from './StreamingHeader'; -import { isStreamingKit } from '../../common/utils'; - -export const Header = () => { - return isStreamingKit() ? : ; -}; diff --git a/packages/roomkit-react/src/Prebuilt/components/Header/ConferencingHeader.jsx b/packages/roomkit-react/src/Prebuilt/components/Header/Header.tsx similarity index 88% rename from packages/roomkit-react/src/Prebuilt/components/Header/ConferencingHeader.jsx rename to packages/roomkit-react/src/Prebuilt/components/Header/Header.tsx index 291b3911bf..a93c98ff11 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Header/ConferencingHeader.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Header/Header.tsx @@ -1,12 +1,15 @@ import React from 'react'; import { useMedia } from 'react-use'; import { HMSRoomState, selectRoomState, useHMSStore } from '@100mslive/react-sdk'; -import { config as cssConfig, Flex } from '../../../'; +import { config as cssConfig, Flex } from '../../..'; +// @ts-ignore: No implicit any import { Logo, SpeakerTag } from './HeaderComponents'; +// @ts-ignore: No implicit any import { LiveStatus, RecordingStatus, StreamActions } from './StreamActions'; +// @ts-ignore: No implicit any import { AudioOutputActions, CamaraFlipActions } from './common'; -export const ConferencingHeader = () => { +export const Header = () => { const roomState = useHMSStore(selectRoomState); const isMobile = useMedia(cssConfig.media.md); // Header should be present only inside the call - not in preview, leave room states diff --git a/packages/roomkit-react/src/Prebuilt/components/Header/HeaderComponents.jsx b/packages/roomkit-react/src/Prebuilt/components/Header/HeaderComponents.jsx index 36f542768f..278fe08271 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Header/HeaderComponents.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Header/HeaderComponents.jsx @@ -4,7 +4,6 @@ import { selectDominantSpeaker, selectIsConnectedToRoom, useHMSStore } from '@10 import { VolumeOneIcon } from '@100mslive/react-icons'; import { config as cssConfig, Flex, styled, Text, textEllipsis, VerticalDivider } from '../../../'; import { useRoomLayout } from '../../provider/roomLayoutProvider'; -import { isStreamingKit } from '../../common/utils'; export const SpeakerTag = () => { const dominantSpeaker = useHMSStore(selectDominantSpeaker); @@ -42,7 +41,7 @@ export const Logo = () => { const isConnected = useHMSStore(selectIsConnectedToRoom); const [hideImage, setHideImage] = useState(false); // Hide logo for now as there is not enough space - if (isConnected && isMobile && isStreamingKit()) { + if (isConnected && isMobile) { return null; } return logo && !hideImage ? ( diff --git a/packages/roomkit-react/src/Prebuilt/components/Header/StreamingHeader.jsx b/packages/roomkit-react/src/Prebuilt/components/Header/StreamingHeader.jsx deleted file mode 100644 index de16f09399..0000000000 --- a/packages/roomkit-react/src/Prebuilt/components/Header/StreamingHeader.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react'; -import { useMedia } from 'react-use'; -import { config as cssConfig, Flex } from '../../../'; -import { EmojiReaction } from '../EmojiReaction'; -import { ParticipantCount } from '../Footer/ParticipantList'; -import { LeaveRoom } from '../LeaveRoom'; -import MetaActions from '../MetaActions'; -import { SpeakerTag } from './HeaderComponents'; -import { LiveStatus, RecordingStatus, StreamActions } from './StreamActions'; - -export const StreamingHeader = () => { - const isMobile = useMedia(cssConfig.media.md); - return ( - - - {isMobile ? ( - - - - - - ) : null} - - - - - {isMobile ? ( - <> - - - - ) : ( - - - - )} - - - - ); -}; diff --git a/packages/roomkit-react/src/Prebuilt/components/Header/index.jsx b/packages/roomkit-react/src/Prebuilt/components/Header/index.tsx similarity index 100% rename from packages/roomkit-react/src/Prebuilt/components/Header/index.jsx rename to packages/roomkit-react/src/Prebuilt/components/Header/index.tsx diff --git a/packages/roomkit-react/src/Prebuilt/components/InsetTile.tsx b/packages/roomkit-react/src/Prebuilt/components/InsetTile.tsx index 48a34d1147..df1366a170 100644 --- a/packages/roomkit-react/src/Prebuilt/components/InsetTile.tsx +++ b/packages/roomkit-react/src/Prebuilt/components/InsetTile.tsx @@ -89,7 +89,7 @@ export const InsetTile = () => { position: 'absolute', bottom: 0, right: 0, - zIndex: 20, + zIndex: 11, boxShadow: '0 0 8px 0 rgba(0,0,0,0.3)', r: '$2', ...(!minimised diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopLeaveRoom.jsx b/packages/roomkit-react/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx similarity index 83% rename from packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopLeaveRoom.jsx rename to packages/roomkit-react/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx index 8772f52926..a74f390fe4 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopLeaveRoom.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx @@ -1,21 +1,26 @@ import React, { Fragment, useState } from 'react'; +import { ConferencingScreen } from '@100mslive/types-prebuilt'; import { selectIsConnectedToRoom, selectPermissions, useHMSStore, useRecordingStreaming } from '@100mslive/react-sdk'; import { ExitIcon, StopIcon, VerticalMenuIcon } from '@100mslive/react-icons'; -import { Dropdown } from '../../../../Dropdown'; -import { Box, Flex } from '../../../../Layout'; -import { Dialog } from '../../../../Modal'; -import { Tooltip } from '../../../../Tooltip'; -import { EndSessionContent } from '../../EndSessionContent'; -import { LeaveCard } from '../../LeaveCard'; -import { LeaveSessionContent } from '../../LeaveSessionContent'; -import { useDropdownList } from '../../hooks/useDropdownList'; -import { useIsLocalPeerHLSViewer, useShowStreamingUI } from '../../../common/hooks'; +import { Dropdown } from '../../../Dropdown'; +import { Box, Flex } from '../../../Layout'; +import { Dialog } from '../../../Modal'; +import { Tooltip } from '../../../Tooltip'; +import { EndSessionContent } from './EndSessionContent'; +import { LeaveIconButton, MenuTriggerButton } from './LeaveAtoms'; +import { LeaveCard } from './LeaveCard'; +import { LeaveSessionContent } from './LeaveSessionContent'; +// @ts-ignore: No implicit Any +import { useDropdownList } from '../hooks/useDropdownList'; export const DesktopLeaveRoom = ({ - menuTriggerButton: MenuTriggerButton, - leaveIconButton: LeaveIconButton, leaveRoom, stopStream, + screenType, +}: { + leaveRoom: () => void; + stopStream: () => Promise; + screenType: keyof ConferencingScreen; }) => { const [open, setOpen] = useState(false); const [showLeaveRoomAlert, setShowLeaveRoomAlert] = useState(false); @@ -23,9 +28,7 @@ export const DesktopLeaveRoom = ({ const isConnected = useHMSStore(selectIsConnectedToRoom); const permissions = useHMSStore(selectPermissions); const { isStreamingOn } = useRecordingStreaming(); - const showStreamingUI = useShowStreamingUI(); - const isHLSViewer = useIsLocalPeerHLSViewer(); - const showStream = showStreamingUI && isStreamingOn; + const showStream = permissions?.hlsStreaming && isStreamingOn; useDropdownList({ open: open || showEndStreamAlert || showLeaveRoomAlert, name: 'LeaveRoom' }); @@ -38,7 +41,6 @@ export const DesktopLeaveRoom = ({ {permissions.hlsStreaming ? ( { - if (isHLSViewer) { + if (screenType === 'hls_live_streaming') { setShowLeaveRoomAlert(true); } else { leaveRoom(); @@ -68,7 +70,7 @@ export const DesktopLeaveRoom = ({ }, }} > - + @@ -112,13 +114,12 @@ export const DesktopLeaveRoom = ({ ) : ( { - if (isHLSViewer) { + if (screenType === 'hls_live_streaming') { setShowLeaveRoomAlert(true); } else { leaveRoom(); } }} - variant="danger" key="LeaveRoom" data-testid="leave_room_btn" > @@ -138,13 +139,14 @@ export const DesktopLeaveRoom = ({ setShowEndStreamAlert={setShowEndStreamAlert} stopStream={stopStream} leaveRoom={leaveRoom} + isStreamingOn={isStreamingOn} isModal /> - {isHLSViewer ? ( + {screenType === 'hls_live_streaming' ? ( diff --git a/packages/roomkit-react/src/Prebuilt/components/EndSessionContent.jsx b/packages/roomkit-react/src/Prebuilt/components/Leave/EndSessionContent.tsx similarity index 68% rename from packages/roomkit-react/src/Prebuilt/components/EndSessionContent.jsx rename to packages/roomkit-react/src/Prebuilt/components/Leave/EndSessionContent.tsx index b06e95a29a..86801fb8ba 100644 --- a/packages/roomkit-react/src/Prebuilt/components/EndSessionContent.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Leave/EndSessionContent.tsx @@ -1,12 +1,22 @@ import React from 'react'; import { AlertTriangleIcon, CrossIcon } from '@100mslive/react-icons'; -import { Button } from '../../Button'; -import { Box, Flex } from '../../Layout'; -import { Text } from '../../Text'; -import { useShowStreamingUI } from '../common/hooks'; +import { Button } from '../../../Button'; +import { Box, Flex } from '../../../Layout'; +import { Text } from '../../../Text'; -export const EndSessionContent = ({ setShowEndStreamAlert, stopStream, leaveRoom, isModal = false }) => { - const showStreamingUI = useShowStreamingUI(); +export const EndSessionContent = ({ + setShowEndStreamAlert, + stopStream, + leaveRoom, + isModal = false, + isStreamingOn = false, +}: { + setShowEndStreamAlert: (value: boolean) => void; + stopStream: () => Promise; + leaveRoom: () => void; + isModal?: boolean; + isStreamingOn: boolean; +}) => { return ( - End {showStreamingUI ? 'Stream' : 'Session'} + End {isStreamingOn ? 'Stream' : 'Session'} {isModal ? null : ( setShowEndStreamAlert(false)}> @@ -27,7 +37,7 @@ export const EndSessionContent = ({ setShowEndStreamAlert, stopStream, leaveRoom )} - The {showStreamingUI ? 'stream' : 'session'} will end for everyone. You can't undo this action. + The {isStreamingOn ? 'stream' : 'session'} will end for everyone. You can't undo this action. diff --git a/packages/roomkit-react/src/Prebuilt/components/Leave/LeaveAtoms.tsx b/packages/roomkit-react/src/Prebuilt/components/Leave/LeaveAtoms.tsx new file mode 100644 index 0000000000..d4925b7c03 --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/Leave/LeaveAtoms.tsx @@ -0,0 +1,26 @@ +import { IconButton } from '../../../IconButton'; +import { styled } from '../../../Theme'; + +export const LeaveIconButton = styled(IconButton, { + color: '$on_primary_high', + h: '$14', + px: '$4', + r: '$1', + bg: '$alert_error_default', + '&:not([disabled]):hover': { + bg: '$alert_error_bright', + }, + '&:not([disabled]):active': { + bg: '$alert_error_default', + }, + '@md': { + mx: 0, + }, +}); + +export const MenuTriggerButton = styled(LeaveIconButton, { + borderLeft: '1px solid $alert_error_dim', + borderTopLeftRadius: 0, + borderBottomLeftRadius: 0, + px: '$2', +}); diff --git a/packages/roomkit-react/src/Prebuilt/components/LeaveCard.jsx b/packages/roomkit-react/src/Prebuilt/components/Leave/LeaveCard.tsx similarity index 50% rename from packages/roomkit-react/src/Prebuilt/components/LeaveCard.jsx rename to packages/roomkit-react/src/Prebuilt/components/Leave/LeaveCard.tsx index 32beacc46e..bc6882170d 100644 --- a/packages/roomkit-react/src/Prebuilt/components/LeaveCard.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Leave/LeaveCard.tsx @@ -1,8 +1,27 @@ import React from 'react'; -import { Box, Flex } from '../../Layout'; -import { Text } from '../../Text'; +import { Box, Flex } from '../../../Layout'; +import { Text } from '../../../Text'; +import { CSS } from '../../../Theme'; -export const LeaveCard = ({ icon, title, subtitle, onClick, bg, titleColor, subtitleColor, css = {} }) => { +export const LeaveCard = ({ + icon, + title, + subtitle, + onClick, + bg, + titleColor, + subtitleColor, + css = {}, +}: { + icon: React.JSX.Element; + title: string; + subtitle: string; + onClick: () => void; + titleColor: string; + subtitleColor: string; + bg: string; + css?: CSS; +}) => { return ( {icon} diff --git a/packages/roomkit-react/src/Prebuilt/components/Leave/LeaveRoom.tsx b/packages/roomkit-react/src/Prebuilt/components/Leave/LeaveRoom.tsx new file mode 100644 index 0000000000..634d503d06 --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/Leave/LeaveRoom.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; +import { useMedia } from 'react-use'; +import { ConferencingScreen } from '@100mslive/types-prebuilt'; +import { selectIsConnectedToRoom, selectPermissions, useHMSActions, useHMSStore } from '@100mslive/react-sdk'; +import { config as cssConfig } from '../../../Theme'; +// @ts-ignore: No implicit Any +import { useHMSPrebuiltContext } from '../../AppContext'; +// @ts-ignore: No implicit Any +import { PictureInPicture } from '../PIP/PIPManager'; +// @ts-ignore: No implicit Any +import { ToastManager } from '../Toast/ToastManager'; +import { DesktopLeaveRoom } from './DesktopLeaveRoom'; +import { MwebLeaveRoom } from './MwebLeaveRoom'; +import { useRoomLayoutLeaveScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen'; + +export const LeaveRoom = ({ screenType }: { screenType: keyof ConferencingScreen }) => { + const navigate = useNavigate(); + const params = useParams(); + const isConnected = useHMSStore(selectIsConnectedToRoom); + const permissions = useHMSStore(selectPermissions); + const isMobile = useMedia(cssConfig.media.md); + const hmsActions = useHMSActions(); + const { onLeave } = useHMSPrebuiltContext(); + const { isLeaveScreenEnabled } = useRoomLayoutLeaveScreen(); + + const stopStream = async () => { + try { + console.log('Stopping HLS stream'); + await hmsActions.stopHLSStreaming(); + ToastManager.addToast({ title: 'Stopping the stream' }); + } catch (e) { + console.error('Error stopping stream', e); + ToastManager.addToast({ title: 'Error in stopping the stream', type: 'error' }); + } + }; + + const redirectToLeavePage = () => { + const prefix = isLeaveScreenEnabled ? '/leave/' : '/'; + if (params.role) { + navigate(prefix + params.roomId + '/' + params.role); + } else { + navigate(prefix + params.roomId); + } + PictureInPicture.stop().catch(() => console.error('stopping pip')); + ToastManager.clearAllToast(); + onLeave?.(); + }; + + const leaveRoom = () => { + hmsActions.leave(); + redirectToLeavePage(); + }; + + if (!permissions || !isConnected) { + return null; + } + return isMobile ? ( + + ) : ( + + ); +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/LeaveSessionContent.jsx b/packages/roomkit-react/src/Prebuilt/components/Leave/LeaveSessionContent.tsx similarity index 79% rename from packages/roomkit-react/src/Prebuilt/components/LeaveSessionContent.jsx rename to packages/roomkit-react/src/Prebuilt/components/Leave/LeaveSessionContent.tsx index c3f65e69fd..8b0002de16 100644 --- a/packages/roomkit-react/src/Prebuilt/components/LeaveSessionContent.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Leave/LeaveSessionContent.tsx @@ -1,10 +1,18 @@ import React from 'react'; import { AlertTriangleIcon, CrossIcon } from '@100mslive/react-icons'; -import { Button } from '../../Button'; -import { Box, Flex } from '../../Layout'; -import { Text } from '../../Text'; +import { Button } from '../../../Button'; +import { Box, Flex } from '../../../Layout'; +import { Text } from '../../../Text'; -export const LeaveSessionContent = ({ setShowLeaveRoomAlert, leaveRoom, isModal = false }) => { +export const LeaveSessionContent = ({ + setShowLeaveRoomAlert, + leaveRoom, + isModal = false, +}: { + setShowLeaveRoomAlert: (value: boolean) => void; + leaveRoom: () => void; + isModal?: boolean; +}) => { return ( { +export const MwebLeaveRoom = ({ + leaveRoom, + stopStream, + screenType, +}: { + leaveRoom: () => void; + stopStream: () => Promise; + screenType: keyof ConferencingScreen; +}) => { const [open, setOpen] = useState(false); const [showLeaveRoomAlert, setShowLeaveRoomAlert] = useState(false); const [showEndStreamAlert, setShowEndStreamAlert] = useState(false); const isConnected = useHMSStore(selectIsConnectedToRoom); const permissions = useHMSStore(selectPermissions); const { isStreamingOn } = useRecordingStreaming(); - const isHlsViewer = useIsLocalPeerHLSViewer(); - const showStreamingUI = useShowStreamingUI(); - const showStream = showStreamingUI && isStreamingOn; + const showStream = permissions?.hlsStreaming && isStreamingOn; useDropdownList({ open, name: 'LeaveRoom' }); if (!permissions || !isConnected) { @@ -33,7 +41,6 @@ export const MwebLeaveRoom = ({ leaveIconButton: LeaveIconButton, leaveRoom, sto ) : ( { - if (isHlsViewer) { + if (screenType === 'hls_live_streaming') { setShowLeaveRoomAlert(true); } }} @@ -103,10 +109,11 @@ export const MwebLeaveRoom = ({ leaveIconButton: LeaveIconButton, leaveRoom, sto setShowEndStreamAlert={setShowEndStreamAlert} stopStream={stopStream} leaveRoom={leaveRoom} + isStreamingOn={isStreamingOn} /> - {isHlsViewer ? ( + {screenType === 'hls_live_streaming' ? ( diff --git a/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx b/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx deleted file mode 100644 index 923c895227..0000000000 --- a/packages/roomkit-react/src/Prebuilt/components/LeaveRoom.jsx +++ /dev/null @@ -1,94 +0,0 @@ -import React from 'react'; -import { useParams } from 'react-router-dom'; -import { useMedia } from 'react-use'; -import { selectIsConnectedToRoom, selectPermissions, useHMSActions, useHMSStore } from '@100mslive/react-sdk'; -import { DesktopLeaveRoom } from './MoreSettings/SplitComponents/DesktopLeaveRoom'; -import { MwebLeaveRoom } from './MoreSettings/SplitComponents/MwebLeaveRoom'; -import { PictureInPicture } from './PIP/PIPManager'; -import { ToastManager } from './Toast/ToastManager'; -import { IconButton } from '../../IconButton'; -import { config as cssConfig, styled } from '../../Theme'; -import { useHMSPrebuiltContext } from '../AppContext'; -import { useNavigation } from './hooks/useNavigation'; - -export const LeaveRoom = () => { - const navigate = useNavigation(); - const params = useParams(); - const isConnected = useHMSStore(selectIsConnectedToRoom); - const permissions = useHMSStore(selectPermissions); - const isMobile = useMedia(cssConfig.media.md); - const hmsActions = useHMSActions(); - const { showLeave, onLeave } = useHMSPrebuiltContext(); - - const stopStream = async () => { - try { - console.log('Stopping HLS stream'); - await hmsActions.stopHLSStreaming(); - ToastManager.addToast({ title: 'Stopping the stream' }); - } catch (e) { - console.error('Error stopping stream', e); - ToastManager.addToast({ title: 'Error in stopping the stream', type: 'error' }); - } - }; - - const redirectToLeavePage = () => { - if (showLeave) { - if (params.role) { - navigate('/leave/' + params.roomId + '/' + params.role); - } else { - navigate('/leave/' + params.roomId); - } - } - PictureInPicture.stop().catch(() => console.error('stopping pip')); - ToastManager.clearAllToast(); - onLeave?.(); - }; - - const leaveRoom = () => { - hmsActions.leave(); - redirectToLeavePage(); - }; - - // const endRoom = () => { - // hmsActions.endRoom(false, 'End Room'); - // redirectToLeavePage(); - // }; - - if (!permissions || !isConnected) { - return null; - } - return isMobile ? ( - - ) : ( - - ); -}; - -const LeaveIconButton = styled(IconButton, { - color: '$on_primary_high', - h: '$14', - px: '$4', - r: '$1', - bg: '$alert_error_default', - '&:not([disabled]):hover': { - bg: '$alert_error_bright', - }, - '&:not([disabled]):active': { - bg: '$alert_error_default', - }, - '@md': { - mx: 0, - }, -}); - -const MenuTriggerButton = styled(LeaveIconButton, { - borderLeft: '1px solid $alert_error_dim', - borderTopLeftRadius: 0, - borderBottomLeftRadius: 0, - px: '$2', -}); diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx deleted file mode 100644 index 6ab8112628..0000000000 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import { useMedia } from 'react-use'; -import { DesktopOptions } from './SplitComponents/DesktopOptions'; -import { MwebOptions } from './SplitComponents/MwebOptions'; -import { config as cssConfig } from '../../../'; - -export const MoreSettings = () => { - const isMobile = useMedia(cssConfig.media.md); - return isMobile ? : ; -}; diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.tsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.tsx new file mode 100644 index 0000000000..34d4a354b4 --- /dev/null +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/MoreSettings.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { useMedia } from 'react-use'; +import { + ConferencingScreen, + DefaultConferencingScreen_Elements, + HLSLiveStreamingScreen_Elements, +} from '@100mslive/types-prebuilt'; +// @ts-ignore: No implicit Any +import { DesktopOptions } from './SplitComponents/DesktopOptions'; +// @ts-ignore: No implicit Any +import { MwebOptions } from './SplitComponents/MwebOptions'; +import { config as cssConfig } from '../../..'; + +export const MoreSettings = ({ + elements, + screenType, +}: { + elements: DefaultConferencingScreen_Elements | HLSLiveStreamingScreen_Elements; + screenType: keyof ConferencingScreen; +}) => { + const isMobile = useMedia(cssConfig.media.md); + return isMobile ? ( + + ) : ( + + ); +}; diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx similarity index 58% rename from packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.jsx rename to packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx index 1d63911692..0f75fb52e1 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx @@ -1,28 +1,38 @@ import React, { Fragment, useState } from 'react'; import { HMSHLSPlayer } from '@100mslive/hls-player'; import { - selectAppData, - selectLocalPeerID, - selectLocalPeerRoleName, - useHMSActions, - useHMSStore, -} from '@100mslive/react-sdk'; + ConferencingScreen, + DefaultConferencingScreen_Elements, + HLSLiveStreamingScreen_Elements, +} from '@100mslive/types-prebuilt'; +import { selectAppData, selectLocalPeerID, useHMSActions, useHMSStore } from '@100mslive/react-sdk'; import { BrbIcon, CheckIcon, DragHandleIcon, HandIcon, InfoIcon, PipIcon, SettingsIcon } from '@100mslive/react-icons'; -import { Checkbox, Dropdown, Flex, Text, Tooltip } from '../../../../'; +import { Checkbox, Dropdown, Flex, Text, Tooltip } from '../../../..'; +// @ts-ignore: No implicit any import IconButton from '../../../IconButton'; +// @ts-ignore: No implicit any import { PIP } from '../../PIP'; +// @ts-ignore: No implicit any import { PictureInPicture } from '../../PIP/PIPManager'; +// @ts-ignore: No implicit any import { RoleChangeModal } from '../../RoleChangeModal'; +// @ts-ignore: No implicit any import SettingsModal from '../../Settings/SettingsModal'; +// @ts-ignore: No implicit any import StartRecording from '../../Settings/StartRecording'; +// @ts-ignore: No implicit any import { StatsForNerds } from '../../StatsForNerds'; -import { BulkRoleChangeModal } from '.././BulkRoleChangeModal'; -import { FullScreenItem } from '.././FullScreenItem'; -import { MuteAllModal } from '.././MuteAllModal'; +// @ts-ignore: No implicit any +import { BulkRoleChangeModal } from '../BulkRoleChangeModal'; +// @ts-ignore: No implicit any +import { FullScreenItem } from '../FullScreenItem'; +// @ts-ignore: No implicit any +import { MuteAllModal } from '../MuteAllModal'; +// @ts-ignore: No implicit any import { useDropdownList } from '../../hooks/useDropdownList'; +// @ts-ignore: No implicit any import { useMyMetadata } from '../../hooks/useMetadata'; -import { useIsLocalPeerHLSViewer, useShowStreamingUI } from '../../../common/hooks'; -import { FeatureFlags } from '../../../services/FeatureFlags'; +// @ts-ignore: No implicit any import { APP_DATA, isMacOS } from '../../../common/constants'; const MODALS = { @@ -37,20 +47,24 @@ const MODALS = { EMBED_URL: 'embedUrl', }; -export const DesktopOptions = () => { +export const DesktopOptions = ({ + elements, + screenType, +}: { + elements: DefaultConferencingScreen_Elements & HLSLiveStreamingScreen_Elements; + screenType: keyof ConferencingScreen; +}) => { const localPeerId = useHMSStore(selectLocalPeerID); - const localPeerRole = useHMSStore(selectLocalPeerRoleName); const hmsActions = useHMSActions(); const enablHlsStats = useHMSStore(selectAppData(APP_DATA.hlsStats)); const [openModals, setOpenModals] = useState(new Set()); const { isHandRaised, isBRBOn, toggleHandRaise, toggleBRB } = useMyMetadata(); - const showStreamingUI = useShowStreamingUI(); - const isHlsViewer = useIsLocalPeerHLSViewer(); const isPipOn = PictureInPicture.isOn(); + const isBRBEnabled = !!elements?.brb; useDropdownList({ open: openModals.size > 0, name: 'MoreSettings' }); - const updateState = (modalName, value) => { + const updateState = (modalName: string, value: boolean) => { setOpenModals(modals => { const copy = new Set(modals); if (value) { @@ -91,7 +105,7 @@ export const DesktopOptions = () => { }, }} > - {!(showStreamingUI || isHlsViewer) ? ( + {screenType !== 'hls_live_streaming' ? ( @@ -103,7 +117,7 @@ export const DesktopOptions = () => { ) : null} - {!(showStreamingUI || isHlsViewer) ? ( + {isBRBEnabled && screenType === 'hls_live_streaming' ? ( @@ -115,9 +129,9 @@ export const DesktopOptions = () => { ) : null} - {!(showStreamingUI || isHlsViewer) ? : null} + {isBRBEnabled && screenType === 'hls_live_streaming' ? : null} - {!isHlsViewer ? ( + {screenType !== 'hls_live_streaming' ? ( { - {FeatureFlags.enableStatsForNerds && - (localPeerRole === 'hls-viewer' ? ( - HMSHLSPlayer.isSupported() ? ( - hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)} - data-testid="hls_stats" - > - hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)} - > - - - - - - - Show HLS Stats - - - - {`${isMacOS ? '⌘' : 'ctrl'} + ]`} - - - - ) : null - ) : ( + {screenType === 'hls_live_streaming' ? ( + HMSHLSPlayer.isSupported() ? ( updateState(MODALS.STATS_FOR_NERDS, true)} - data-testid="stats_for_nreds_btn" + onClick={() => hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)} + data-testid="hls_stats" > - - - Stats for Nerds - + hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)} + > + + + + + + + Show HLS Stats + + + + {`${isMacOS ? '⌘' : 'ctrl'} + ]`} + + - ))} + ) : null + ) : ( + updateState(MODALS.STATS_FOR_NERDS, true)} data-testid="stats_for_nreds_btn"> + + + Stats for Nerds + + + )} {openModals.has(MODALS.BULK_ROLE_CHANGE) && ( - updateState(MODALS.BULK_ROLE_CHANGE, value)} /> + updateState(MODALS.BULK_ROLE_CHANGE, value)} /> + )} + {openModals.has(MODALS.MUTE_ALL) && ( + updateState(MODALS.MUTE_ALL, value)} /> )} - {openModals.has(MODALS.MUTE_ALL) && updateState(MODALS.MUTE_ALL, value)} />} {openModals.has(MODALS.START_RECORDING) && ( - updateState(MODALS.START_RECORDING, value)} /> + updateState(MODALS.START_RECORDING, value)} /> )} {openModals.has(MODALS.DEVICE_SETTINGS) && ( - updateState(MODALS.DEVICE_SETTINGS, value)} /> + updateState(MODALS.DEVICE_SETTINGS, value)} + screenType={screenType} + /> )} - {FeatureFlags.enableStatsForNerds && openModals.has(MODALS.STATS_FOR_NERDS) && ( - updateState(MODALS.STATS_FOR_NERDS, value)} /> + {openModals.has(MODALS.STATS_FOR_NERDS) && ( + updateState(MODALS.STATS_FOR_NERDS, value)} /> )} {openModals.has(MODALS.SELF_ROLE_CHANGE) && ( - updateState(MODALS.SELF_ROLE_CHANGE, value)} /> + updateState(MODALS.SELF_ROLE_CHANGE, value)} + /> )} {/* {openModals.has(MODALS.EMBED_URL) && ( updateState(MODALS.EMBED_URL, value)} /> diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx index bfaeaca5bd..a1ab63580e 100644 --- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx @@ -1,8 +1,7 @@ -import React, { Suspense, useRef, useState } from 'react'; +import React, { useRef, useState } from 'react'; import { useClickAway } from 'react-use'; import { selectIsConnectedToRoom, - selectIsLocalVideoEnabled, selectPeerCount, selectPermissions, useHMSActions, @@ -25,7 +24,7 @@ import { useDropdownList } from '../../hooks/useDropdownList'; import { getFormattedCount } from '../../../common/utils'; import { SIDE_PANE_OPTIONS } from '../../../common/constants'; -const VirtualBackground = React.lazy(() => import('../../../plugins/VirtualBackground/VirtualBackground')); +// const VirtualBackground = React.lazy(() => import('../../../plugins/VirtualBackground/VirtualBackground')); const MODALS = { CHANGE_NAME: 'changeName', @@ -39,7 +38,7 @@ const MODALS = { EMBED_URL: 'embedUrl', }; -export const MwebOptions = () => { +export const MwebOptions = ({ elements }) => { const hmsActions = useHMSActions(); const permissions = useHMSStore(selectPermissions); const isConnected = useHMSStore(selectIsConnectedToRoom); @@ -55,7 +54,7 @@ export const MwebOptions = () => { const toggleParticipants = useSidepaneToggle(SIDE_PANE_OPTIONS.PARTICIPANTS); const peerCount = useHMSStore(selectPeerCount); const emojiCardRef = useRef(null); - const isVideoOn = useHMSStore(selectIsLocalVideoEnabled); + // const isVideoOn = useHMSStore(selectIsLocalVideoEnabled); useDropdownList({ open: openModals.size > 0 || openOptionsSheet || openSettingsSheet, name: 'MoreSettings' }); @@ -127,21 +126,23 @@ export const MwebOptions = () => { Participants - {isVideoOn ? ( + {/* {isVideoOn ? ( setOpenOptionsSheet(false)} /> - ) : null} + ) : null} */} - { - setShowEmojiCard(true); - setOpenOptionsSheet(false); - }} - > - - Emoji Reactions - + {elements?.emoji_reactions && ( + { + setShowEmojiCard(true); + setOpenOptionsSheet(false); + }} + > + + Emoji Reactions + + )} { diff --git a/packages/roomkit-react/src/Prebuilt/components/Notifications/Notifications.jsx b/packages/roomkit-react/src/Prebuilt/components/Notifications/Notifications.jsx index f556277e5a..f92686e8b5 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Notifications/Notifications.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Notifications/Notifications.jsx @@ -1,5 +1,6 @@ /* eslint-disable no-case-declarations */ import React, { useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; import { HMSNotificationTypes, HMSRoomState, @@ -8,6 +9,7 @@ import { useHMSStore, } from '@100mslive/react-sdk'; import { Button } from '../../../'; +import { useUpdateRoomLayout } from '../../provider/roomLayoutProvider'; import { ToastBatcher } from '../Toast/ToastBatcher'; import { ToastManager } from '../Toast/ToastManager'; import { AutoplayBlockedModal } from './AutoplayBlockedModal'; @@ -18,17 +20,16 @@ import { ReconnectNotifications } from './ReconnectNotifications'; import { TrackBulkUnmuteModal } from './TrackBulkUnmuteModal'; import { TrackNotifications } from './TrackNotifications'; import { TrackUnmuteModal } from './TrackUnmuteModal'; -import { useHLSViewerRole, useIsHeadless, useSubscribedNotifications } from '../AppData/useUISettings'; -import { useNavigation } from '../hooks/useNavigation'; +import { useIsHeadless, useSubscribedNotifications } from '../AppData/useUISettings'; import { getMetadata } from '../../common/utils'; export function Notifications() { const notification = useHMSNotifications(); - const navigate = useNavigation(); - const HLS_VIEWER_ROLE = useHLSViewerRole(); + const navigate = useNavigate(); const subscribedNotifications = useSubscribedNotifications() || {}; const isHeadless = useIsHeadless(); const roomState = useHMSStore(selectRoomState); + const updateRoomLayoutForRole = useUpdateRoomLayout(); useEffect(() => { if (!notification) { @@ -99,13 +100,11 @@ export function Notifications() { }); break; case HMSNotificationTypes.ROLE_UPDATED: - if (notification.data.roleName === HLS_VIEWER_ROLE) { - return; - } if (notification.data?.isLocal) { ToastManager.addToast({ title: `You are now a ${notification.data.roleName}`, }); + updateRoomLayoutForRole(notification.data.roleName); } break; case HMSNotificationTypes.CHANGE_TRACK_STATE_REQUEST: @@ -138,7 +137,7 @@ export function Notifications() { break; } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [notification, subscribedNotifications.ERROR, subscribedNotifications.METADATA_UPDATED, HLS_VIEWER_ROLE]); + }, [notification, subscribedNotifications.ERROR, subscribedNotifications.METADATA_UPDATED]); return ( <> diff --git a/packages/roomkit-react/src/Prebuilt/components/Notifications/PeerNotifications.jsx b/packages/roomkit-react/src/Prebuilt/components/Notifications/PeerNotifications.jsx index 1b4802e237..a7b6c03b0b 100644 --- a/packages/roomkit-react/src/Prebuilt/components/Notifications/PeerNotifications.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/Notifications/PeerNotifications.jsx @@ -52,7 +52,7 @@ export const PeerNotifications = () => { } ToastBatcher.showToast({ notification }); - }, [notification, isPeerJoinSubscribed, isPeerLeftSubscribed]); + }, [notification, isPeerJoinSubscribed, isPeerLeftSubscribed, roomState]); return null; }; diff --git a/packages/roomkit-react/src/Prebuilt/components/PIP/PIPComponent.jsx b/packages/roomkit-react/src/Prebuilt/components/PIP/PIPComponent.jsx index abdfee9511..6c7582ea13 100644 --- a/packages/roomkit-react/src/Prebuilt/components/PIP/PIPComponent.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/PIP/PIPComponent.jsx @@ -1,26 +1,17 @@ import React, { useCallback, useEffect, useState } from 'react'; -import { - selectLocalPeerRoleName, - selectPeers, - selectTracksMap, - useHMSActions, - useHMSStore, - useHMSVanillaStore, -} from '@100mslive/react-sdk'; +import { selectPeers, selectTracksMap, useHMSActions, useHMSStore, useHMSVanillaStore } from '@100mslive/react-sdk'; import { PipIcon } from '@100mslive/react-icons'; import { Flex, Tooltip } from '../../../'; import IconButton from '../../IconButton'; import { PictureInPicture } from './PIPManager'; import { MediaSession } from './SetupMediaSession'; import { usePinnedTrack } from '../AppData/useUISettings'; -import { DEFAULT_HLS_VIEWER_ROLE } from '../../common/constants'; /** * shows a button which when clicked shows some videos in PIP, clicking * again turns it off. */ const PIPComponent = ({ content = null }) => { - const localPeerRole = useHMSStore(selectLocalPeerRoleName); const [isPipOn, setIsPipOn] = useState(PictureInPicture.isOn()); const hmsActions = useHMSActions(); const store = useHMSVanillaStore(); @@ -34,7 +25,7 @@ const PIPComponent = ({ content = null }) => { } }, [hmsActions, isPipOn, store]); - if (!PictureInPicture.isSupported() || localPeerRole === DEFAULT_HLS_VIEWER_ROLE) { + if (!PictureInPicture.isSupported()) { return null; } return ( @@ -64,8 +55,8 @@ export const ActivatedPIP = () => { const pinnedTrack = usePinnedTrack(); useEffect(() => { - PictureInPicture.listenToStateChange(isPipOn => { - if (!isPipOn) { + function updatePIP() { + if (!PictureInPicture.isOn()) { return; } let pipPeers = storePeers; @@ -75,7 +66,9 @@ export const ActivatedPIP = () => { PictureInPicture.updatePeersAndTracks(pipPeers, tracksMap).catch(err => { console.error('error in updating pip', err); }); - }); + } + PictureInPicture.listenToStateChange(updatePIP); + updatePIP(); }, [storePeers, tracksMap, pinnedTrack]); return <>; diff --git a/packages/roomkit-react/src/Prebuilt/components/PIP/PIPManager.js b/packages/roomkit-react/src/Prebuilt/components/PIP/PIPManager.js index b2b585e037..84e78a5d8d 100644 --- a/packages/roomkit-react/src/Prebuilt/components/PIP/PIPManager.js +++ b/packages/roomkit-react/src/Prebuilt/components/PIP/PIPManager.js @@ -107,6 +107,7 @@ class PipManager { this.pipVideo?.removeEventListener(LEAVE_EVENT_NAME, this.stop); if (this.timeoutRef) { workerTimers.clearTimeout(this.timeoutRef); + this.timeoutRef = null; } if (this.isOn()) { this.exitPIP(); diff --git a/packages/roomkit-react/src/Prebuilt/components/PostLeave.jsx b/packages/roomkit-react/src/Prebuilt/components/PostLeave.jsx index 09087a5e75..4745c57cf0 100644 --- a/packages/roomkit-react/src/Prebuilt/components/PostLeave.jsx +++ b/packages/roomkit-react/src/Prebuilt/components/PostLeave.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useParams } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom'; import { ExitIcon } from '@100mslive/react-icons'; import { ToastManager } from './Toast/ToastManager'; import { Button } from '../../Button'; @@ -7,14 +7,14 @@ import { Box, Flex } from '../../Layout'; import { Text } from '../../Text'; import { useHMSPrebuiltContext } from '../AppContext'; import { Header } from './Header'; -import { useNavigation } from './hooks/useNavigation'; +import { useRoomLayoutPreviewScreen } from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen'; import { defaultPreviewPreference, UserPreferencesKeys, useUserPreferences } from './hooks/useUserPreferences'; -import { getRoutePrefix } from '../common/utils'; import { textEllipsis } from '../../utils'; const PostLeave = () => { - const navigate = useNavigation(); - const { showPreview, roomCode } = useHMSPrebuiltContext(); + const navigate = useNavigate(); + const { isPreviewScreenEnabled } = useRoomLayoutPreviewScreen(); + const { roomCode } = useHMSPrebuiltContext(); const { roomId, role } = useParams(); const [previewPreference] = useUserPreferences(UserPreferencesKeys.PREVIEW, defaultPreviewPreference); return ( @@ -32,7 +32,7 @@ const PostLeave = () => { 👋 - You left the {getRoutePrefix() ? 'stream' : 'room'} + You left the room {