@100mslive/roomkit-react 0.2.8-alpha.5 → 0.2.8-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{HLSView-CVNJNDUQ.js → HLSView-MYKM5AXS.js} +239 -144
- package/dist/HLSView-MYKM5AXS.js.map +7 -0
- package/dist/Prebuilt/components/Chat/MwebChatOption.d.ts +1 -1
- package/dist/Prebuilt/components/HMSVideo/PlayPauseButton.d.ts +6 -0
- package/dist/Prebuilt/components/HMSVideo/SeekControls.d.ts +7 -0
- package/dist/Prebuilt/components/HMSVideo/VideoProgress.d.ts +3 -1
- package/dist/Prebuilt/components/HMSVideo/index.d.ts +10 -2
- package/dist/Prebuilt/layouts/SidePane.d.ts +1 -1
- package/dist/{chunk-25HZFDG5.js → chunk-DRBTAFKN.js} +356 -222
- package/dist/chunk-DRBTAFKN.js.map +7 -0
- package/dist/index.cjs.js +949 -712
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +1 -1
- package/dist/meta.cjs.json +217 -78
- package/dist/meta.esbuild.json +227 -87
- package/package.json +7 -6
- package/src/Prebuilt/components/AppData/useSidepane.js +34 -7
- package/src/Prebuilt/components/AuthToken.jsx +1 -1
- package/src/Prebuilt/components/Chat/ChatFooter.tsx +1 -1
- package/src/Prebuilt/components/Chat/MwebChatOption.tsx +1 -1
- package/src/Prebuilt/components/ConferenceScreen.tsx +11 -14
- package/src/Prebuilt/components/Footer/RoleOptions.tsx +32 -15
- package/src/Prebuilt/components/HMSVideo/HLSAutoplayBlockedPrompt.tsx +31 -1
- package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +7 -1
- package/src/Prebuilt/components/HMSVideo/PlayPauseButton.tsx +27 -0
- package/src/Prebuilt/components/HMSVideo/SeekControls.tsx +22 -0
- package/src/Prebuilt/components/HMSVideo/VideoProgress.tsx +4 -3
- package/src/Prebuilt/components/HMSVideo/VolumeControl.tsx +1 -1
- package/src/Prebuilt/components/HMSVideo/index.ts +4 -2
- package/src/Prebuilt/components/Header/StreamActions.tsx +1 -1
- package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx +37 -31
- package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +6 -5
- package/src/Prebuilt/components/Notifications/HandRaisedNotifications.tsx +2 -2
- package/src/Prebuilt/components/Notifications/PeerNotifications.tsx +1 -1
- package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +19 -8
- package/src/Prebuilt/components/SidePaneTabs.tsx +27 -35
- package/src/Prebuilt/components/StatsForNerds.jsx +14 -6
- package/src/Prebuilt/components/Streaming/Common.jsx +1 -1
- package/src/Prebuilt/components/TileMenu/TileMenuContent.tsx +2 -2
- package/src/Prebuilt/components/Toast/ToastBatcher.js +8 -1
- package/src/Prebuilt/components/Toast/ToastConfig.jsx +17 -0
- package/src/Prebuilt/layouts/HLSView.jsx +109 -69
- package/src/Prebuilt/layouts/SidePane.tsx +125 -67
- package/src/Prebuilt/layouts/VideoStreamingSection.tsx +2 -1
- package/src/Prebuilt/provider/roomLayoutProvider/index.tsx +1 -1
- package/src/Sheet/Sheet.tsx +4 -0
- package/dist/HLSView-CVNJNDUQ.js.map +0 -7
- package/dist/chunk-25HZFDG5.js.map +0 -7
- package/src/Prebuilt/components/HMSVideo/PlayButton.jsx +0 -13
    
        package/package.json
    CHANGED
    
    | @@ -10,7 +10,7 @@ | |
| 10 10 | 
             
                "prebuilt",
         | 
| 11 11 | 
             
                "roomkit"
         | 
| 12 12 | 
             
              ],
         | 
| 13 | 
            -
              "version": "0.2.8-alpha. | 
| 13 | 
            +
              "version": "0.2.8-alpha.7",
         | 
| 14 14 | 
             
              "author": "100ms",
         | 
| 15 15 | 
             
              "license": "MIT",
         | 
| 16 16 | 
             
              "repository": {
         | 
| @@ -82,11 +82,11 @@ | |
| 82 82 | 
             
                "react": ">=17.0.2 <19.0.0"
         | 
| 83 83 | 
             
              },
         | 
| 84 84 | 
             
              "dependencies": {
         | 
| 85 | 
            -
                "@100mslive/hls-player": "0.2.8-alpha. | 
| 85 | 
            +
                "@100mslive/hls-player": "0.2.8-alpha.7",
         | 
| 86 86 | 
             
                "@100mslive/hms-noise-cancellation": "0.0.0-alpha.1",
         | 
| 87 | 
            -
                "@100mslive/hms-virtual-background": "1.12.8-alpha. | 
| 88 | 
            -
                "@100mslive/react-icons": "0.9.8-alpha. | 
| 89 | 
            -
                "@100mslive/react-sdk": "0.9.8-alpha. | 
| 87 | 
            +
                "@100mslive/hms-virtual-background": "1.12.8-alpha.7",
         | 
| 88 | 
            +
                "@100mslive/react-icons": "0.9.8-alpha.7",
         | 
| 89 | 
            +
                "@100mslive/react-sdk": "0.9.8-alpha.7",
         | 
| 90 90 | 
             
                "@100mslive/types-prebuilt": "0.12.7",
         | 
| 91 91 | 
             
                "@emoji-mart/data": "^1.0.6",
         | 
| 92 92 | 
             
                "@emoji-mart/react": "^1.0.1",
         | 
| @@ -118,8 +118,9 @@ | |
| 118 118 | 
             
                "react-window": "^1.8.7",
         | 
| 119 119 | 
             
                "recordrtc": "^5.6.2",
         | 
| 120 120 | 
             
                "screenfull": "^5.1.0",
         | 
| 121 | 
            +
                "ts-pattern": "4.3.0",
         | 
| 121 122 | 
             
                "uuid": "^8.3.2",
         | 
| 122 123 | 
             
                "worker-timers": "^7.0.40"
         | 
| 123 124 | 
             
              },
         | 
| 124 | 
            -
              "gitHead": " | 
| 125 | 
            +
              "gitHead": "48bc1b57113a4245b79055a80f4f1f5d3b8795aa"
         | 
| 125 126 | 
             
            }
         | 
| @@ -1,4 +1,5 @@ | |
| 1 1 | 
             
            import { useCallback } from 'react';
         | 
| 2 | 
            +
            import { match, P } from 'ts-pattern';
         | 
| 2 3 | 
             
            import { selectAppData, useHMSActions, useHMSStore, useHMSVanillaStore } from '@100mslive/react-sdk';
         | 
| 3 4 | 
             
            import { usePollViewState } from './useUISettings';
         | 
| 4 5 | 
             
            import { APP_DATA, POLL_STATE, POLL_VIEWS, SIDE_PANE_OPTIONS } from '../../common/constants';
         | 
| @@ -45,13 +46,39 @@ export const usePollViewToggle = () => { | |
| 45 46 |  | 
| 46 47 | 
             
              const togglePollView = useCallback(
         | 
| 47 48 | 
             
                id => {
         | 
| 48 | 
            -
                   | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 49 | 
            +
                  match({ id, isOpen, view })
         | 
| 50 | 
            +
                    .with(
         | 
| 51 | 
            +
                      {
         | 
| 52 | 
            +
                        id: P.string,
         | 
| 53 | 
            +
                      },
         | 
| 54 | 
            +
                      () => {
         | 
| 55 | 
            +
                        setPollState({
         | 
| 56 | 
            +
                          [POLL_STATE.pollInView]: id,
         | 
| 57 | 
            +
                          [POLL_STATE.view]: POLL_VIEWS.VOTE,
         | 
| 58 | 
            +
                        });
         | 
| 59 | 
            +
                        hmsActions.setAppData(APP_DATA.sidePane, SIDE_PANE_OPTIONS.POLLS);
         | 
| 60 | 
            +
                      },
         | 
| 61 | 
            +
                    )
         | 
| 62 | 
            +
                    .with(
         | 
| 63 | 
            +
                      {
         | 
| 64 | 
            +
                        isOpen: true,
         | 
| 65 | 
            +
                        view: P.when(view => !!view),
         | 
| 66 | 
            +
                      },
         | 
| 67 | 
            +
                      () => {
         | 
| 68 | 
            +
                        setPollState({
         | 
| 69 | 
            +
                          [POLL_STATE.pollInView]: undefined,
         | 
| 70 | 
            +
                          [POLL_STATE.view]: null,
         | 
| 71 | 
            +
                        });
         | 
| 72 | 
            +
                        hmsActions.setAppData(APP_DATA.sidePane, '');
         | 
| 73 | 
            +
                      },
         | 
| 74 | 
            +
                    )
         | 
| 75 | 
            +
                    .otherwise(() => {
         | 
| 76 | 
            +
                      setPollState({
         | 
| 77 | 
            +
                        [POLL_STATE.pollInView]: undefined,
         | 
| 78 | 
            +
                        [POLL_STATE.view]: POLL_VIEWS.CREATE_POLL_QUIZ,
         | 
| 79 | 
            +
                      });
         | 
| 80 | 
            +
                      hmsActions.setAppData(APP_DATA.sidePane, SIDE_PANE_OPTIONS.POLLS);
         | 
| 81 | 
            +
                    });
         | 
| 55 82 | 
             
                },
         | 
| 56 83 | 
             
                [hmsActions, view, setPollState, isOpen],
         | 
| 57 84 | 
             
              );
         | 
| @@ -70,7 +70,7 @@ const AuthToken = React.memo(({ authTokenByRoomCodeEndpoint, defaultAuthToken }) | |
| 70 70 | 
             
                        alignItems: 'center',
         | 
| 71 71 | 
             
                      }}
         | 
| 72 72 | 
             
                    >
         | 
| 73 | 
            -
                      <img src={errorImage} height={80} width={80} />
         | 
| 73 | 
            +
                      <img src={errorImage} height={80} width={80} alt="Token Error" />
         | 
| 74 74 | 
             
                      <Text variant="h4" css={{ textAlign: 'center', mb: '$4', mt: '$10' }}>
         | 
| 75 75 | 
             
                        {error.title}
         | 
| 76 76 | 
             
                      </Text>
         | 
| @@ -99,7 +99,7 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo | |
| 99 99 | 
             
                  setRoleSelector(defaultSelection);
         | 
| 100 100 | 
             
                } else {
         | 
| 101 101 | 
             
                  // @ts-ignore
         | 
| 102 | 
            -
                  if (!(isMobile || isLandscapeHLSStream)  | 
| 102 | 
            +
                  if (!(isMobile || isLandscapeHLSStream) && !elements?.chat?.disable_autofocus) {
         | 
| 103 103 | 
             
                    inputRef.current?.focus();
         | 
| 104 104 | 
             
                  }
         | 
| 105 105 | 
             
                }
         | 
| @@ -11,7 +11,6 @@ import { | |
| 11 11 | 
             
              useHMSStore,
         | 
| 12 12 | 
             
            } from '@100mslive/react-sdk';
         | 
| 13 13 | 
             
            import { Footer } from './Footer/Footer';
         | 
| 14 | 
            -
            import { LeaveRoom } from './Leave/LeaveRoom';
         | 
| 15 14 | 
             
            import { MoreSettings } from './MoreSettings/MoreSettings';
         | 
| 16 15 | 
             
            import { HLSFailureModal } from './Notifications/HLSFailureModal';
         | 
| 17 16 | 
             
            // @ts-ignore: No implicit Any
         | 
| @@ -57,16 +56,17 @@ export const ConferenceScreen = () => { | |
| 57 56 | 
             
              const noAVPermissions = !(toggleAudio || toggleVideo);
         | 
| 58 57 | 
             
              // using it in hls stream to show action button when chat is disabled
         | 
| 59 58 | 
             
              const showChat = !!screenProps.elements?.chat;
         | 
| 60 | 
            -
              const toggleControls = () => {
         | 
| 61 | 
            -
                if (dropdownListRef.current?.length === 0 && isMobileDevice) {
         | 
| 62 | 
            -
                  setHideControls(value => !value);
         | 
| 63 | 
            -
                }
         | 
| 64 | 
            -
              };
         | 
| 65 59 | 
             
              const autoRoomJoined = useRef(isPreviewScreenEnabled);
         | 
| 66 60 | 
             
              const isMobileHLSStream = useMobileHLSStream();
         | 
| 67 61 | 
             
              const isLandscapeHLSStream = useLandscapeHLSStream();
         | 
| 68 62 | 
             
              const isMwebHLSStream = isMobileHLSStream || isLandscapeHLSStream;
         | 
| 69 63 |  | 
| 64 | 
            +
              const toggleControls = () => {
         | 
| 65 | 
            +
                if (dropdownListRef.current?.length === 0 && isMobileDevice && !isMwebHLSStream) {
         | 
| 66 | 
            +
                  setHideControls(value => !value);
         | 
| 67 | 
            +
                }
         | 
| 68 | 
            +
              };
         | 
| 69 | 
            +
             | 
| 70 70 | 
             
              useEffect(() => {
         | 
| 71 71 | 
             
                let timeout: undefined | ReturnType<typeof setTimeout>;
         | 
| 72 72 | 
             
                dropdownListRef.current = dropdownList || [];
         | 
| @@ -118,6 +118,8 @@ export const ConferenceScreen = () => { | |
| 118 118 | 
             
                return <FullPageProgress text={roomState === HMSRoomState.Connecting ? 'Joining...' : ''} />;
         | 
| 119 119 | 
             
              }
         | 
| 120 120 |  | 
| 121 | 
            +
              const hideControlsForStreaming = isMwebHLSStream ? true : hideControls;
         | 
| 122 | 
            +
             | 
| 121 123 | 
             
              return (
         | 
| 122 124 | 
             
                <>
         | 
| 123 125 | 
             
                  {isHLSStarted ? (
         | 
| @@ -132,7 +134,7 @@ export const ConferenceScreen = () => { | |
| 132 134 | 
             
                        css={{
         | 
| 133 135 | 
             
                          h: '$18',
         | 
| 134 136 | 
             
                          transition: 'margin 0.3s ease-in-out',
         | 
| 135 | 
            -
                          marginTop:  | 
| 137 | 
            +
                          marginTop: hideControlsForStreaming ? `-${headerRef.current?.clientHeight}px` : 'none',
         | 
| 136 138 | 
             
                          '@md': {
         | 
| 137 139 | 
             
                            h: '$17',
         | 
| 138 140 | 
             
                          },
         | 
| @@ -142,11 +144,6 @@ export const ConferenceScreen = () => { | |
| 142 144 | 
             
                        <Header />
         | 
| 143 145 | 
             
                      </Box>
         | 
| 144 146 | 
             
                    )}
         | 
| 145 | 
            -
                    {isMwebHLSStream && (
         | 
| 146 | 
            -
                      <Flex align="center" gap="2" css={{ position: 'absolute', left: '$4', top: '$4', zIndex: 1 }}>
         | 
| 147 | 
            -
                        <LeaveRoom screenType={screenProps.screenType} />
         | 
| 148 | 
            -
                      </Flex>
         | 
| 149 | 
            -
                    )}
         | 
| 150 147 | 
             
                    <Box
         | 
| 151 148 | 
             
                      css={{
         | 
| 152 149 | 
             
                        w: '100%',
         | 
| @@ -169,7 +166,7 @@ export const ConferenceScreen = () => { | |
| 169 166 | 
             
                        <VideoStreamingSection
         | 
| 170 167 | 
             
                          screenType={screenProps.screenType}
         | 
| 171 168 | 
             
                          elements={screenProps.elements}
         | 
| 172 | 
            -
                          hideControls={ | 
| 169 | 
            +
                          hideControls={hideControlsForStreaming}
         | 
| 173 170 | 
             
                        />
         | 
| 174 171 | 
             
                      ) : null}
         | 
| 175 172 | 
             
                    </Box>
         | 
| @@ -181,7 +178,7 @@ export const ConferenceScreen = () => { | |
| 181 178 | 
             
                          maxHeight: '$24',
         | 
| 182 179 | 
             
                          transition: 'margin 0.3s ease-in-out',
         | 
| 183 180 | 
             
                          bg: '$background_dim',
         | 
| 184 | 
            -
                          marginBottom:  | 
| 181 | 
            +
                          marginBottom: hideControlsForStreaming ? `-${footerRef.current?.clientHeight}px` : undefined,
         | 
| 185 182 | 
             
                          '@md': {
         | 
| 186 183 | 
             
                            maxHeight: 'unset',
         | 
| 187 184 | 
             
                            bg: screenProps.screenType === 'hls_live_streaming' ? 'transparent' : '$background_dim',
         | 
| @@ -25,7 +25,12 @@ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvid | |
| 25 25 | 
             
            import { getMetadata } from '../../common/utils';
         | 
| 26 26 |  | 
| 27 27 | 
             
            const dropdownItemCSS = { backgroundColor: '$surface_default', gap: '$4', p: '$8' };
         | 
| 28 | 
            -
            const optionTextCSS = { | 
| 28 | 
            +
            const optionTextCSS = {
         | 
| 29 | 
            +
              fontWeight: '$semiBold',
         | 
| 30 | 
            +
              color: '$on_surface_high',
         | 
| 31 | 
            +
              textTransform: 'none',
         | 
| 32 | 
            +
              whiteSpace: 'nowrap',
         | 
| 33 | 
            +
            };
         | 
| 29 34 |  | 
| 30 35 | 
             
            const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleName: string }) => {
         | 
| 31 36 | 
             
              const vanillaStore = useHMSVanillaStore();
         | 
| @@ -34,8 +39,8 @@ const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleNam | |
| 34 39 | 
             
              const permissions = useHMSStore(selectPermissions);
         | 
| 35 40 | 
             
              const role = useHMSStore(selectRoleByRoleName(roleName));
         | 
| 36 41 |  | 
| 37 | 
            -
              let  | 
| 38 | 
            -
              let  | 
| 42 | 
            +
              let isVideoOnForSomePeers = false;
         | 
| 43 | 
            +
              let isAudioOnForSomePeers = false;
         | 
| 39 44 |  | 
| 40 45 | 
             
              peerList.forEach(peer => {
         | 
| 41 46 | 
             
                if (peer.isLocal) {
         | 
| @@ -43,8 +48,8 @@ const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleNam | |
| 43 48 | 
             
                }
         | 
| 44 49 | 
             
                const isAudioOn = !!peer.audioTrack && store.tracks[peer.audioTrack]?.enabled;
         | 
| 45 50 | 
             
                const isVideoOn = !!peer.videoTrack && store.tracks[peer.videoTrack]?.enabled;
         | 
| 46 | 
            -
                 | 
| 47 | 
            -
                 | 
| 51 | 
            +
                isAudioOnForSomePeers = isAudioOnForSomePeers || isAudioOn;
         | 
| 52 | 
            +
                isVideoOnForSomePeers = isVideoOnForSomePeers || isVideoOn;
         | 
| 48 53 | 
             
              });
         | 
| 49 54 |  | 
| 50 55 | 
             
              const setTrackEnabled = async (type: 'audio' | 'video', enabled = false) => {
         | 
| @@ -55,11 +60,15 @@ const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleNam | |
| 55 60 | 
             
                }
         | 
| 56 61 | 
             
              };
         | 
| 57 62 |  | 
| 63 | 
            +
              if (!role) {
         | 
| 64 | 
            +
                return null;
         | 
| 65 | 
            +
              }
         | 
| 66 | 
            +
             | 
| 58 67 | 
             
              return (
         | 
| 59 68 | 
             
                <>
         | 
| 60 | 
            -
                  {role.publishParams.allowed | 
| 69 | 
            +
                  {role.publishParams.allowed.includes('audio') && (
         | 
| 61 70 | 
             
                    <>
         | 
| 62 | 
            -
                      { | 
| 71 | 
            +
                      {isAudioOnForSomePeers && permissions?.mute ? (
         | 
| 63 72 | 
             
                        <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('audio', false)}>
         | 
| 64 73 | 
             
                          <MicOffIcon />
         | 
| 65 74 | 
             
                          <Text variant="sm" css={optionTextCSS}>
         | 
| @@ -68,20 +77,20 @@ const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleNam | |
| 68 77 | 
             
                        </Dropdown.Item>
         | 
| 69 78 | 
             
                      ) : null}
         | 
| 70 79 |  | 
| 71 | 
            -
                      {! | 
| 80 | 
            +
                      {!isAudioOnForSomePeers && permissions?.unmute ? (
         | 
| 72 81 | 
             
                        <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('audio', true)}>
         | 
| 73 82 | 
             
                          <MicOnIcon />
         | 
| 74 83 | 
             
                          <Text variant="sm" css={optionTextCSS}>
         | 
| 75 | 
            -
                            Unmute Audio for All
         | 
| 84 | 
            +
                            Request to Unmute Audio for All
         | 
| 76 85 | 
             
                          </Text>
         | 
| 77 86 | 
             
                        </Dropdown.Item>
         | 
| 78 87 | 
             
                      ) : null}
         | 
| 79 88 | 
             
                    </>
         | 
| 80 89 | 
             
                  )}
         | 
| 81 90 |  | 
| 82 | 
            -
                  {role.publishParams.allowed | 
| 91 | 
            +
                  {role.publishParams.allowed.includes('video') && (
         | 
| 83 92 | 
             
                    <>
         | 
| 84 | 
            -
                      { | 
| 93 | 
            +
                      {isVideoOnForSomePeers && permissions?.mute ? (
         | 
| 85 94 | 
             
                        <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('video', false)}>
         | 
| 86 95 | 
             
                          <VideoOffIcon />
         | 
| 87 96 | 
             
                          <Text variant="sm" css={optionTextCSS}>
         | 
| @@ -90,11 +99,11 @@ const MuteUnmuteOption = ({ roleName, peerList }: { peerList: HMSPeer[]; roleNam | |
| 90 99 | 
             
                        </Dropdown.Item>
         | 
| 91 100 | 
             
                      ) : null}
         | 
| 92 101 |  | 
| 93 | 
            -
                      {! | 
| 102 | 
            +
                      {!isVideoOnForSomePeers && permissions?.unmute ? (
         | 
| 94 103 | 
             
                        <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('video', true)}>
         | 
| 95 104 | 
             
                          <VideoOnIcon />
         | 
| 96 105 | 
             
                          <Text variant="sm" css={optionTextCSS}>
         | 
| 97 | 
            -
                            Unmute Video for All
         | 
| 106 | 
            +
                            Request to Unmute Video for All
         | 
| 98 107 | 
             
                          </Text>
         | 
| 99 108 | 
             
                        </Dropdown.Item>
         | 
| 100 109 | 
             
                      ) : null}
         | 
| @@ -112,11 +121,19 @@ export const RoleOptions = ({ roleName, peerList }: { roleName: string; peerList | |
| 112 121 | 
             
              const { on_stage_role, off_stage_roles = [] } = (elements as DefaultConferencingScreen_Elements)?.on_stage_exp || {};
         | 
| 113 122 | 
             
              const canMuteOrUnmute = permissions?.mute || permissions?.unmute;
         | 
| 114 123 | 
             
              const canRemoveRoleFromStage = permissions?.changeRole && roleName === on_stage_role;
         | 
| 124 | 
            +
              const role = useHMSStore(selectRoleByRoleName(roleName));
         | 
| 125 | 
            +
             | 
| 115 126 | 
             
              // on stage and off stage roles
         | 
| 116 127 | 
             
              const canRemoveRoleFromRoom =
         | 
| 117 128 | 
             
                permissions?.removeOthers && (on_stage_role === roleName || off_stage_roles?.includes(roleName));
         | 
| 118 129 |  | 
| 119 | 
            -
              if ( | 
| 130 | 
            +
              if (
         | 
| 131 | 
            +
                !(canMuteOrUnmute || canRemoveRoleFromStage || canRemoveRoleFromRoom) ||
         | 
| 132 | 
            +
                peerList.length === 0 ||
         | 
| 133 | 
            +
                // if only local peer is present no need to show any options
         | 
| 134 | 
            +
                (peerList.length === 1 && peerList[0].isLocal) ||
         | 
| 135 | 
            +
                !role
         | 
| 136 | 
            +
              ) {
         | 
| 120 137 | 
             
                return null;
         | 
| 121 138 | 
             
              }
         | 
| 122 139 |  | 
| @@ -165,7 +182,7 @@ export const RoleOptions = ({ roleName, peerList }: { roleName: string; peerList | |
| 165 182 | 
             
                  </Dropdown.Trigger>
         | 
| 166 183 | 
             
                  <Dropdown.Content
         | 
| 167 184 | 
             
                    onClick={e => e.stopPropagation()}
         | 
| 168 | 
            -
                    css={{ w: 'max-content',  | 
| 185 | 
            +
                    css={{ w: 'max-content', bg: '$surface_default', py: 0 }}
         | 
| 169 186 | 
             
                    align="end"
         | 
| 170 187 | 
             
                  >
         | 
| 171 188 | 
             
                    {canRemoveRoleFromStage && (
         | 
| @@ -1,7 +1,10 @@ | |
| 1 1 | 
             
            import React from 'react';
         | 
| 2 | 
            -
            import {  | 
| 2 | 
            +
            import { useMedia } from 'react-use';
         | 
| 3 | 
            +
            import { VolumeTwoIcon } from '@100mslive/react-icons';
         | 
| 4 | 
            +
            import { Button, config, Dialog, IconButton, Text } from '../../..';
         | 
| 3 5 | 
             
            // @ts-ignore
         | 
| 4 6 | 
             
            import { DialogContent, DialogRow } from '../../primitives/DialogContent';
         | 
| 7 | 
            +
            import { useIsLandscape } from '../../common/hooks';
         | 
| 5 8 |  | 
| 6 9 | 
             
            export function HLSAutoplayBlockedPrompt({
         | 
| 7 10 | 
             
              open,
         | 
| @@ -10,6 +13,33 @@ export function HLSAutoplayBlockedPrompt({ | |
| 10 13 | 
             
              open: boolean;
         | 
| 11 14 | 
             
              unblockAutoPlay: () => Promise<void>;
         | 
| 12 15 | 
             
            }) {
         | 
| 16 | 
            +
              const isLandscape = useIsLandscape();
         | 
| 17 | 
            +
              const isMobile = useMedia(config.media.md);
         | 
| 18 | 
            +
              if ((isMobile || isLandscape) && open) {
         | 
| 19 | 
            +
                return (
         | 
| 20 | 
            +
                  <IconButton
         | 
| 21 | 
            +
                    css={{
         | 
| 22 | 
            +
                      border: '1px solid white',
         | 
| 23 | 
            +
                      bg: 'white',
         | 
| 24 | 
            +
                      color: '#000',
         | 
| 25 | 
            +
                      r: '$2',
         | 
| 26 | 
            +
                    }}
         | 
| 27 | 
            +
                    onClick={async () => await unblockAutoPlay()}
         | 
| 28 | 
            +
                  >
         | 
| 29 | 
            +
                    <VolumeTwoIcon width="32" height="32" />
         | 
| 30 | 
            +
                    <Text
         | 
| 31 | 
            +
                      variant="body1"
         | 
| 32 | 
            +
                      css={{
         | 
| 33 | 
            +
                        fontWeight: '$semiBold',
         | 
| 34 | 
            +
                        px: '$2',
         | 
| 35 | 
            +
                        color: '#000',
         | 
| 36 | 
            +
                      }}
         | 
| 37 | 
            +
                    >
         | 
| 38 | 
            +
                      Tap To Unmute
         | 
| 39 | 
            +
                    </Text>
         | 
| 40 | 
            +
                  </IconButton>
         | 
| 41 | 
            +
                );
         | 
| 42 | 
            +
              }
         | 
| 13 43 | 
             
              return (
         | 
| 14 44 | 
             
                <Dialog.Root
         | 
| 15 45 | 
             
                  open={open}
         | 
| @@ -1,7 +1,11 @@ | |
| 1 1 | 
             
            import React, { forwardRef } from 'react';
         | 
| 2 | 
            -
            import {  | 
| 2 | 
            +
            import { useMedia } from 'react-use';
         | 
| 3 | 
            +
            import { config, Flex } from '../../../';
         | 
| 4 | 
            +
            import { useIsLandscape } from '../../common/hooks';
         | 
| 3 5 |  | 
| 4 6 | 
             
            export const HMSVideo = forwardRef(({ children, ...props }, videoRef) => {
         | 
| 7 | 
            +
              const isLandscape = useIsLandscape();
         | 
| 8 | 
            +
              const isMobile = useMedia(config.media.md);
         | 
| 5 9 | 
             
              return (
         | 
| 6 10 | 
             
                <Flex
         | 
| 7 11 | 
             
                  data-testid="hms-video"
         | 
| @@ -36,6 +40,8 @@ export const HMSVideo = forwardRef(({ children, ...props }, videoRef) => { | |
| 36 40 | 
             
                      minHeight: '0',
         | 
| 37 41 | 
             
                      objectFit: 'contain',
         | 
| 38 42 | 
             
                      width: 'inherit',
         | 
| 43 | 
            +
                      height: isLandscape || isMobile ? '100%' : '',
         | 
| 44 | 
            +
                      position: isLandscape || isMobile ? 'absolute' : '',
         | 
| 39 45 | 
             
                    }}
         | 
| 40 46 | 
             
                    ref={videoRef}
         | 
| 41 47 | 
             
                    playsInline
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            import React, { MouseEvent } from 'react';
         | 
| 2 | 
            +
            import { PauseIcon, PlayIcon } from '@100mslive/react-icons';
         | 
| 3 | 
            +
            import { IconButton, Tooltip } from '../../..';
         | 
| 4 | 
            +
            import { useHMSPlayerContext } from './PlayerContext';
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            export const PlayPauseButton = ({
         | 
| 7 | 
            +
              isPaused,
         | 
| 8 | 
            +
              width = 20,
         | 
| 9 | 
            +
              height = 20,
         | 
| 10 | 
            +
            }: {
         | 
| 11 | 
            +
              isPaused: boolean;
         | 
| 12 | 
            +
              width: number;
         | 
| 13 | 
            +
              height: number;
         | 
| 14 | 
            +
            }) => {
         | 
| 15 | 
            +
              const { hlsPlayer } = useHMSPlayerContext();
         | 
| 16 | 
            +
              const onClick = async (event: MouseEvent) => {
         | 
| 17 | 
            +
                event?.stopPropagation();
         | 
| 18 | 
            +
                isPaused ? await hlsPlayer?.play() : hlsPlayer?.pause();
         | 
| 19 | 
            +
              };
         | 
| 20 | 
            +
              return (
         | 
| 21 | 
            +
                <Tooltip title={isPaused ? 'Play' : 'Pause'} side="top">
         | 
| 22 | 
            +
                  <IconButton onClick={onClick} data-testid="play_pause_btn">
         | 
| 23 | 
            +
                    {isPaused ? <PlayIcon width={width} height={height} /> : <PauseIcon width={width} height={height} />}
         | 
| 24 | 
            +
                  </IconButton>
         | 
| 25 | 
            +
                </Tooltip>
         | 
| 26 | 
            +
              );
         | 
| 27 | 
            +
            };
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            import React, { MouseEventHandler } from 'react';
         | 
| 2 | 
            +
            import { IconButton, Tooltip } from '../../..';
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            export const SeekControls = ({
         | 
| 5 | 
            +
              title,
         | 
| 6 | 
            +
              onClick,
         | 
| 7 | 
            +
              children,
         | 
| 8 | 
            +
              css,
         | 
| 9 | 
            +
            }: {
         | 
| 10 | 
            +
              title: string;
         | 
| 11 | 
            +
              onClick?: MouseEventHandler<HTMLButtonElement>;
         | 
| 12 | 
            +
              css: any;
         | 
| 13 | 
            +
              children: React.ReactNode;
         | 
| 14 | 
            +
            }) => {
         | 
| 15 | 
            +
              return (
         | 
| 16 | 
            +
                <Tooltip title={title} side="top">
         | 
| 17 | 
            +
                  <IconButton onClick={onClick} data-testid="backward_forward_arrow_btn" css={css}>
         | 
| 18 | 
            +
                    {children}
         | 
| 19 | 
            +
                  </IconButton>
         | 
| 20 | 
            +
                </Tooltip>
         | 
| 21 | 
            +
              );
         | 
| 22 | 
            +
            };
         | 
| @@ -3,7 +3,7 @@ import { Box, Flex, Slider } from '../../..'; | |
| 3 3 | 
             
            import { useHMSPlayerContext } from './PlayerContext';
         | 
| 4 4 | 
             
            import { getPercentage } from './utils';
         | 
| 5 5 |  | 
| 6 | 
            -
            export const VideoProgress = () => {
         | 
| 6 | 
            +
            export const VideoProgress = ({ isDvr = true }: { isDvr: boolean }) => {
         | 
| 7 7 | 
             
              const { hlsPlayer } = useHMSPlayerContext();
         | 
| 8 8 | 
             
              const [videoProgress, setVideoProgress] = useState<number>(0);
         | 
| 9 9 | 
             
              const [bufferProgress, setBufferProgress] = useState(0);
         | 
| @@ -48,7 +48,7 @@ export const VideoProgress = () => { | |
| 48 48 | 
             
                return null;
         | 
| 49 49 | 
             
              }
         | 
| 50 50 | 
             
              return (
         | 
| 51 | 
            -
                <Flex align="center" css={{ cursor: 'pointer', h: '$2', alignSelf: 'stretch' }}>
         | 
| 51 | 
            +
                <Flex align="center" css={{ cursor: 'pointer', h: '$2', alignSelf: 'stretch', pointerEvents: isDvr ? '' : 'none' }}>
         | 
| 52 52 | 
             
                  <Slider
         | 
| 53 53 | 
             
                    id="video-actual-rest"
         | 
| 54 54 | 
             
                    css={{
         | 
| @@ -56,6 +56,7 @@ export const VideoProgress = () => { | |
| 56 56 | 
             
                      h: '$2',
         | 
| 57 57 | 
             
                      zIndex: 1,
         | 
| 58 58 | 
             
                      transition: `all .2s ease .5s`,
         | 
| 59 | 
            +
                      pointerEvents: isDvr ? '' : 'none',
         | 
| 59 60 | 
             
                    }}
         | 
| 60 61 | 
             
                    min={0}
         | 
| 61 62 | 
             
                    max={100}
         | 
| @@ -63,7 +64,7 @@ export const VideoProgress = () => { | |
| 63 64 | 
             
                    value={[videoProgress]}
         | 
| 64 65 | 
             
                    showTooltip={false}
         | 
| 65 66 | 
             
                    onValueChange={onProgress}
         | 
| 66 | 
            -
                    thumbStyles={{ w: '$6', h: '$6' }}
         | 
| 67 | 
            +
                    thumbStyles={{ w: '$6', h: '$6', display: isDvr ? '' : 'none' }}
         | 
| 67 68 | 
             
                  />
         | 
| 68 69 | 
             
                  <Box
         | 
| 69 70 | 
             
                    id="video-buffer"
         | 
| @@ -5,7 +5,7 @@ import { useHMSPlayerContext } from './PlayerContext'; | |
| 5 5 |  | 
| 6 6 | 
             
            export const VolumeControl = () => {
         | 
| 7 7 | 
             
              const { hlsPlayer } = useHMSPlayerContext();
         | 
| 8 | 
            -
              const [volume, setVolume] = useState(hlsPlayer?.volume  | 
| 8 | 
            +
              const [volume, setVolume] = useState(hlsPlayer?.volume ?? 100);
         | 
| 9 9 | 
             
              const [showSlider, setShowSlider] = useState(false);
         | 
| 10 10 |  | 
| 11 11 | 
             
              return (
         | 
| @@ -2,14 +2,15 @@ | |
| 2 2 | 
             
            import { LeftControls, RightControls, VideoControls } from './Controls';
         | 
| 3 3 | 
             
            // @ts-ignore
         | 
| 4 4 | 
             
            import { HMSVideo } from './HMSVideo';
         | 
| 5 | 
            -
            import {  | 
| 5 | 
            +
            import { PlayPauseButton } from './PlayPauseButton';
         | 
| 6 | 
            +
            import { SeekControls } from './SeekControls';
         | 
| 6 7 | 
             
            import { VideoProgress } from './VideoProgress';
         | 
| 7 8 | 
             
            import { VideoTime } from './VideoTime';
         | 
| 8 9 | 
             
            import { VolumeControl } from './VolumeControl';
         | 
| 9 10 |  | 
| 10 11 | 
             
            export const HMSVideoPlayer = {
         | 
| 11 12 | 
             
              Root: HMSVideo,
         | 
| 12 | 
            -
               | 
| 13 | 
            +
              PlayPauseButton: PlayPauseButton,
         | 
| 13 14 | 
             
              Progress: VideoProgress,
         | 
| 14 15 | 
             
              Duration: VideoTime,
         | 
| 15 16 | 
             
              Volume: VolumeControl,
         | 
| @@ -18,4 +19,5 @@ export const HMSVideoPlayer = { | |
| 18 19 | 
             
                Left: LeftControls,
         | 
| 19 20 | 
             
                Right: RightControls,
         | 
| 20 21 | 
             
              },
         | 
| 22 | 
            +
              Seeker: SeekControls,
         | 
| 21 23 | 
             
            };
         | 
| @@ -42,7 +42,7 @@ export const LiveStatus = () => { | |
| 42 42 | 
             
                    setLiveTime(Date.now() - timeStamp.getTime());
         | 
| 43 43 | 
             
                  }
         | 
| 44 44 | 
             
                }, 1000);
         | 
| 45 | 
            -
              }, [hlsState?.running, hlsState?.variants]);
         | 
| 45 | 
            +
              }, [hlsState?.running, hlsState?.variants, screenType]);
         | 
| 46 46 |  | 
| 47 47 | 
             
              useEffect(() => {
         | 
| 48 48 | 
             
                if (hlsState?.running) {
         | 
| @@ -5,6 +5,7 @@ import { | |
| 5 5 | 
             
              DefaultConferencingScreen_Elements,
         | 
| 6 6 | 
             
              HLSLiveStreamingScreen_Elements,
         | 
| 7 7 | 
             
            } from '@100mslive/types-prebuilt';
         | 
| 8 | 
            +
            import { match } from 'ts-pattern';
         | 
| 8 9 | 
             
            import { selectAppData, selectLocalPeerID, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
         | 
| 9 10 | 
             
            import { BrbIcon, CheckIcon, HamburgerMenuIcon, InfoIcon, PipIcon, SettingsIcon } from '@100mslive/react-icons';
         | 
| 10 11 | 
             
            import { Checkbox, Dropdown, Flex, Text, Tooltip } from '../../../..';
         | 
| @@ -143,41 +144,46 @@ export const DesktopOptions = ({ | |
| 143 144 | 
             
                          Settings
         | 
| 144 145 | 
             
                        </Text>
         | 
| 145 146 | 
             
                      </Dropdown.Item>
         | 
| 147 | 
            +
                      {match({ screenType, isSupported: HMSHLSPlayer.isSupported() })
         | 
| 148 | 
            +
                        .with({ screenType: 'hls_live_streaming', isSupported: false }, () => null)
         | 
| 149 | 
            +
                        .with({ screenType: 'hls_live_streaming', isSupported: true }, () => {
         | 
| 150 | 
            +
                          return (
         | 
| 151 | 
            +
                            <Dropdown.Item
         | 
| 152 | 
            +
                              onClick={() => hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)}
         | 
| 153 | 
            +
                              data-testid="hls_stats"
         | 
| 154 | 
            +
                            >
         | 
| 155 | 
            +
                              <Checkbox.Root
         | 
| 156 | 
            +
                                css={{ margin: '$2' }}
         | 
| 157 | 
            +
                                checked={enablHlsStats}
         | 
| 158 | 
            +
                                onCheckedChange={() => hmsActions.setAppData(APP_DATA.hlsStats, !enablHlsStats)}
         | 
| 159 | 
            +
                              >
         | 
| 160 | 
            +
                                <Checkbox.Indicator>
         | 
| 161 | 
            +
                                  <CheckIcon width={16} height={16} />
         | 
| 162 | 
            +
                                </Checkbox.Indicator>
         | 
| 163 | 
            +
                              </Checkbox.Root>
         | 
| 164 | 
            +
                              <Flex justify="between" css={{ width: '100%' }}>
         | 
| 165 | 
            +
                                <Text variant="sm" css={{ ml: '$4' }}>
         | 
| 166 | 
            +
                                  Show HLS Stats
         | 
| 167 | 
            +
                                </Text>
         | 
| 146 168 |  | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 169 | 
            +
                                <Text variant="sm" css={{ ml: '$4' }}>
         | 
| 170 | 
            +
                                  {`${isMacOS ? '⌘' : 'ctrl'} + ]`}
         | 
| 171 | 
            +
                                </Text>
         | 
| 172 | 
            +
                              </Flex>
         | 
| 173 | 
            +
                            </Dropdown.Item>
         | 
| 174 | 
            +
                          );
         | 
| 175 | 
            +
                        })
         | 
| 176 | 
            +
                        .otherwise(() => (
         | 
| 149 177 | 
             
                          <Dropdown.Item
         | 
| 150 | 
            -
                            onClick={() =>  | 
| 151 | 
            -
                            data-testid=" | 
| 178 | 
            +
                            onClick={() => updateState(MODALS.STATS_FOR_NERDS, true)}
         | 
| 179 | 
            +
                            data-testid="stats_for_nerds_btn"
         | 
| 152 180 | 
             
                          >
         | 
| 153 | 
            -
                            < | 
| 154 | 
            -
             | 
| 155 | 
            -
                               | 
| 156 | 
            -
             | 
| 157 | 
            -
                            >
         | 
| 158 | 
            -
                              <Checkbox.Indicator>
         | 
| 159 | 
            -
                                <CheckIcon width={16} height={16} />
         | 
| 160 | 
            -
                              </Checkbox.Indicator>
         | 
| 161 | 
            -
                            </Checkbox.Root>
         | 
| 162 | 
            -
                            <Flex justify="between" css={{ width: '100%' }}>
         | 
| 163 | 
            -
                              <Text variant="sm" css={{ ml: '$4' }}>
         | 
| 164 | 
            -
                                Show HLS Stats
         | 
| 165 | 
            -
                              </Text>
         | 
| 166 | 
            -
             | 
| 167 | 
            -
                              <Text variant="sm" css={{ ml: '$4' }}>
         | 
| 168 | 
            -
                                {`${isMacOS ? '⌘' : 'ctrl'} + ]`}
         | 
| 169 | 
            -
                              </Text>
         | 
| 170 | 
            -
                            </Flex>
         | 
| 181 | 
            +
                            <InfoIcon />
         | 
| 182 | 
            +
                            <Text variant="sm" css={{ ml: '$4' }}>
         | 
| 183 | 
            +
                              Stats for Nerds
         | 
| 184 | 
            +
                            </Text>
         | 
| 171 185 | 
             
                          </Dropdown.Item>
         | 
| 172 | 
            -
                        ) | 
| 173 | 
            -
                      ) : (
         | 
| 174 | 
            -
                        <Dropdown.Item onClick={() => updateState(MODALS.STATS_FOR_NERDS, true)} data-testid="stats_for_nreds_btn">
         | 
| 175 | 
            -
                          <InfoIcon />
         | 
| 176 | 
            -
                          <Text variant="sm" css={{ ml: '$4' }}>
         | 
| 177 | 
            -
                            Stats for Nerds
         | 
| 178 | 
            -
                          </Text>
         | 
| 179 | 
            -
                        </Dropdown.Item>
         | 
| 180 | 
            -
                      )}
         | 
| 186 | 
            +
                        ))}
         | 
| 181 187 | 
             
                    </Dropdown.Content>
         | 
| 182 188 | 
             
                  </Dropdown.Root>
         | 
| 183 189 | 
             
                  {openModals.has(MODALS.BULK_ROLE_CHANGE) && (
         | 
| @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            import React, { useRef, useState } from 'react';
         | 
| 2 2 | 
             
            import { useClickAway } from 'react-use';
         | 
| 3 3 | 
             
            import { ConferencingScreen, DefaultConferencingScreen_Elements } from '@100mslive/types-prebuilt';
         | 
| 4 | 
            +
            import { match } from 'ts-pattern';
         | 
| 4 5 | 
             
            import {
         | 
| 5 6 | 
             
              selectIsConnectedToRoom,
         | 
| 6 7 | 
             
              selectPeerCount,
         | 
| @@ -287,11 +288,11 @@ export const MwebOptions = ({ | |
| 287 288 | 
             
                          >
         | 
| 288 289 | 
             
                            {isRecordingLoading ? <Loading /> : <RecordIcon />}
         | 
| 289 290 | 
             
                            <ActionTile.Title>
         | 
| 290 | 
            -
                              {isBrowserRecordingOn
         | 
| 291 | 
            -
                                 | 
| 292 | 
            -
                                :  | 
| 293 | 
            -
                                 | 
| 294 | 
            -
                                 | 
| 291 | 
            +
                              {match({ isBrowserRecordingOn, isRecordingLoading })
         | 
| 292 | 
            +
                                .with({ isBrowserRecordingOn: true, isRecordingLoading: false }, () => 'Recording On')
         | 
| 293 | 
            +
                                .with({ isRecordingLoading: true }, () => 'Starting Recording')
         | 
| 294 | 
            +
                                .with({ isRecordingLoading: false }, () => 'Start Recording')
         | 
| 295 | 
            +
                                .otherwise(() => null)}
         | 
| 295 296 | 
             
                            </ActionTile.Title>
         | 
| 296 297 | 
             
                          </ActionTile.Root>
         | 
| 297 298 | 
             
                        ) : null}
         | 
| @@ -28,12 +28,12 @@ export const HandRaisedNotifications = () => { | |
| 28 28 | 
             
                }
         | 
| 29 29 |  | 
| 30 30 | 
             
                // Don't show toast message in case of local peer.
         | 
| 31 | 
            -
                if (roomState !== HMSRoomState.Connected || notification.data.isLocal || ! | 
| 31 | 
            +
                if (roomState !== HMSRoomState.Connected || notification.data.isLocal || !isSubscribing) {
         | 
| 32 32 | 
             
                  return;
         | 
| 33 33 | 
             
                }
         | 
| 34 34 | 
             
                const hasPeerHandRaised = vanillaStore.getState(selectHasPeerHandRaised(notification.data.id));
         | 
| 35 35 | 
             
                if (hasPeerHandRaised) {
         | 
| 36 | 
            -
                  ToastBatcher.showToast({ notification, type: 'RAISE_HAND' });
         | 
| 36 | 
            +
                  ToastBatcher.showToast({ notification, type: on_stage_exp ? 'RAISE_HAND_HLS' : 'RAISE_HAND' });
         | 
| 37 37 | 
             
                  console.debug('Metadata updated', notification.data);
         | 
| 38 38 | 
             
                }
         | 
| 39 39 | 
             
              }, [isSubscribing, notification, on_stage_exp, roomState, vanillaStore]);
         | 
| @@ -49,7 +49,7 @@ export const PeerNotifications = () => { | |
| 49 49 | 
             
                }
         | 
| 50 50 |  | 
| 51 51 | 
             
                ToastBatcher.showToast({ notification });
         | 
| 52 | 
            -
              }, [notification, isPeerJoinSubscribed, isPeerLeftSubscribed]);
         | 
| 52 | 
            +
              }, [notification, isPeerJoinSubscribed, isPeerLeftSubscribed, selectedPeer.id, setPeerSelector]);
         | 
| 53 53 |  | 
| 54 54 | 
             
              return null;
         | 
| 55 55 | 
             
            };
         |