@100mslive/roomkit-react 0.3.18 → 0.3.19-alpha.1

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "prebuilt",
11
11
  "roomkit"
12
12
  ],
13
- "version": "0.3.18",
13
+ "version": "0.3.19-alpha.1",
14
14
  "author": "100ms",
15
15
  "license": "MIT",
16
16
  "repository": {
@@ -75,12 +75,12 @@
75
75
  "react": ">=17.0.2 <19.0.0"
76
76
  },
77
77
  "dependencies": {
78
- "@100mslive/hls-player": "0.3.18",
78
+ "@100mslive/hls-player": "0.3.19-alpha.1",
79
79
  "@100mslive/hms-noise-cancellation": "0.0.1",
80
- "@100mslive/hms-virtual-background": "1.13.18",
81
- "@100mslive/hms-whiteboard": "0.0.8",
82
- "@100mslive/react-icons": "0.10.18",
83
- "@100mslive/react-sdk": "0.10.18",
80
+ "@100mslive/hms-virtual-background": "1.13.19-alpha.1",
81
+ "@100mslive/hms-whiteboard": "0.0.9-alpha.1",
82
+ "@100mslive/react-icons": "0.10.19-alpha.1",
83
+ "@100mslive/react-sdk": "0.10.19-alpha.1",
84
84
  "@100mslive/types-prebuilt": "0.12.11",
85
85
  "@emoji-mart/data": "^1.0.6",
86
86
  "@emoji-mart/react": "^1.0.1",
@@ -117,5 +117,5 @@
117
117
  "uuid": "^8.3.2",
118
118
  "worker-timers": "^7.0.40"
119
119
  },
120
- "gitHead": "66b20cd5cadc16107232710e32830df7a0685771"
120
+ "gitHead": "4e76816ac6791d45d6099d5ecf81b9b730bbb9db"
121
121
  }
@@ -303,7 +303,11 @@ function AppRoutes({
303
303
  {!isNotificationsDisabled && <FlyingEmoji />}
304
304
  <RemoteStopScreenshare />
305
305
  <KeyboardHandler />
306
- <AuthToken authTokenByRoomCodeEndpoint={authTokenByRoomCodeEndpoint} defaultAuthToken={defaultAuthToken} />
306
+ <AuthToken
307
+ authTokenByRoomCodeEndpoint={authTokenByRoomCodeEndpoint}
308
+ defaultAuthToken={defaultAuthToken}
309
+ activeState={activeState}
310
+ />
307
311
  {roomLayout && activeState && <AppStates activeState={activeState} />}
308
312
  </>
309
313
  </AppStateContext.Provider>
@@ -1,7 +1,7 @@
1
1
  import React, { useContext, useEffect } from 'react';
2
2
  import { usePreviousDistinct } from 'react-use';
3
3
  import { match, P } from 'ts-pattern';
4
- import { HMSRoomState, selectRoomState, useHMSStore } from '@100mslive/react-sdk';
4
+ import { HMSRoomState, selectRoomState, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
5
5
  import { VBHandler } from './components/VirtualBackground/VBHandler';
6
6
  import { useRoomLayout, useSetOriginalLayout } from './provider/roomLayoutProvider';
7
7
  import { useRedirectToLeave } from './components/hooks/useRedirectToLeave';
@@ -9,6 +9,7 @@ import {
9
9
  useRoomLayoutLeaveScreen,
10
10
  useRoomLayoutPreviewScreen,
11
11
  } from './provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
12
+ import { APP_DATA } from './common/constants';
12
13
 
13
14
  export enum PrebuiltStates {
14
15
  MEETING = 'meeting',
@@ -42,12 +43,14 @@ export const useAppStateManager = () => {
42
43
  const [activeState, setActiveState] = React.useState<PrebuiltStates | undefined>();
43
44
  const roomState = useHMSStore(selectRoomState);
44
45
  const prevRoomState = usePreviousDistinct(roomState);
46
+ const hmsActions = useHMSActions();
45
47
  const { isLeaveScreenEnabled } = useRoomLayoutLeaveScreen();
46
48
  const { isPreviewScreenEnabled } = useRoomLayoutPreviewScreen();
47
49
  const { redirectToLeave } = useRedirectToLeave();
48
50
 
49
51
  const rejoin = () => {
50
52
  setOriginalLayout?.();
53
+ hmsActions.setAppData(APP_DATA.authToken, '');
51
54
  setActiveState(isPreviewScreenEnabled ? PrebuiltStates.PREVIEW : PrebuiltStates.MEETING);
52
55
  };
53
56
 
@@ -81,7 +84,7 @@ export const useAppStateManager = () => {
81
84
  .otherwise(() => {
82
85
  // do nothing
83
86
  });
84
- }, [roomLayout, roomState, isLeaveScreenEnabled, isPreviewScreenEnabled, prevRoomState, redirectToLeave]);
87
+ }, [roomLayout, roomState, isLeaveScreenEnabled, isPreviewScreenEnabled, prevRoomState, redirectToLeave, hmsActions]);
85
88
 
86
89
  return { activeState, rejoin };
87
90
  };
@@ -1,13 +1,17 @@
1
- import React, { useEffect, useState } from 'react';
1
+ import React, { useEffect, useRef, useState } from 'react';
2
2
  import { useSessionStorage } from 'react-use';
3
3
  import { match } from 'ts-pattern';
4
4
  import { v4 as uuid } from 'uuid';
5
- import { useHMSActions } from '@100mslive/react-sdk';
5
+ import { HMSException, useHMSActions } from '@100mslive/react-sdk';
6
6
  import { Dialog } from '../../Modal';
7
7
  import { Text } from '../../Text';
8
8
  import { useHMSPrebuiltContext } from '../AppContext';
9
+ import { PrebuiltStates } from '../AppStateContext';
10
+ // @ts-ignore: No implicit Any
9
11
  import errorImage from '../images/transaction_error.svg';
12
+ // @ts-ignore: No implicit Any
10
13
  import { useSetAppDataByKey } from './AppData/useUISettings';
14
+ // @ts-ignore: No implicit Any
11
15
  import { UserPreferencesKeys } from './hooks/useUserPreferences';
12
16
  import { APP_DATA } from '../common/constants';
13
17
 
@@ -20,13 +24,18 @@ import { APP_DATA } from '../common/constants';
20
24
  * auth_token=123 => uses the passed in token to join instead of fetching from token endpoint
21
25
  * ui_mode=activespeaker => lands in active speaker mode after joining the room
22
26
  */
23
- const AuthToken = React.memo(({ authTokenByRoomCodeEndpoint, defaultAuthToken }) => {
27
+ const AuthToken = React.memo<{
28
+ authTokenByRoomCodeEndpoint: string;
29
+ defaultAuthToken?: string;
30
+ activeState?: PrebuiltStates;
31
+ }>(({ authTokenByRoomCodeEndpoint, defaultAuthToken, activeState }) => {
24
32
  const hmsActions = useHMSActions();
25
33
  const { roomCode, userId } = useHMSPrebuiltContext();
26
34
  const [error, setError] = useState({ title: '', body: '' });
27
- let authToken = defaultAuthToken;
28
- const [, setAuthTokenInAppData] = useSetAppDataByKey(APP_DATA.authToken);
29
- const [savedUserId, setSavedUserId] = useSessionStorage(UserPreferencesKeys.USER_ID);
35
+ const authToken = defaultAuthToken;
36
+ const [tokenInAppData, setAuthTokenInAppData] = useSetAppDataByKey(APP_DATA.authToken);
37
+ const [savedUserId, setSavedUserId] = useSessionStorage<string>(UserPreferencesKeys.USER_ID);
38
+ const progressRef = useRef<boolean | null>(null);
30
39
 
31
40
  useEffect(() => {
32
41
  if (authToken) {
@@ -34,19 +43,29 @@ const AuthToken = React.memo(({ authTokenByRoomCodeEndpoint, defaultAuthToken })
34
43
  return;
35
44
  }
36
45
 
37
- if (!roomCode) {
46
+ if (tokenInAppData || progressRef.current || activeState === PrebuiltStates.LEAVE) {
38
47
  return;
39
48
  }
40
49
 
41
- if (!savedUserId && !userId) {
42
- setSavedUserId(uuid());
50
+ if (!roomCode) {
51
+ console.error('room code not provided');
43
52
  return;
44
53
  }
45
54
 
55
+ let userIdForAuthToken = userId || savedUserId;
56
+ if (!userIdForAuthToken) {
57
+ userIdForAuthToken = uuid();
58
+ setSavedUserId(userIdForAuthToken);
59
+ }
60
+
61
+ progressRef.current = true;
46
62
  hmsActions
47
- .getAuthTokenByRoomCode({ roomCode, userId: userId || savedUserId }, { endpoint: authTokenByRoomCodeEndpoint })
63
+ .getAuthTokenByRoomCode({ roomCode, userId: userIdForAuthToken }, { endpoint: authTokenByRoomCodeEndpoint })
48
64
  .then(token => setAuthTokenInAppData(token))
49
- .catch(error => setError(convertError(error)));
65
+ .catch(error => setError(convertError(error)))
66
+ .finally(() => {
67
+ progressRef.current = false;
68
+ });
50
69
  }, [
51
70
  hmsActions,
52
71
  authToken,
@@ -55,7 +74,9 @@ const AuthToken = React.memo(({ authTokenByRoomCodeEndpoint, defaultAuthToken })
55
74
  roomCode,
56
75
  userId,
57
76
  savedUserId,
77
+ tokenInAppData,
58
78
  setSavedUserId,
79
+ activeState,
59
80
  ]);
60
81
 
61
82
  if (error.title) {
@@ -83,7 +104,7 @@ const AuthToken = React.memo(({ authTokenByRoomCodeEndpoint, defaultAuthToken })
83
104
  return null;
84
105
  });
85
106
 
86
- const convertError = error => {
107
+ const convertError = (error: HMSException) => {
87
108
  console.error('[error]', { error });
88
109
  console.warn(
89
110
  'If you think this is a mistake on our side, please reach out to us over Discord:',
@@ -104,6 +125,7 @@ const convertError = error => {
104
125
  body: `Endpoint is not reachable. ${error.description}.`,
105
126
  }))
106
127
  .otherwise(() =>
128
+ // @ts-ignore
107
129
  match(error.response?.status)
108
130
  .with(404, () => ({
109
131
  title: 'Room does not exist',
@@ -17,13 +17,35 @@ import { Box, Button, config as cssConfig, Flex, HorizontalDivider, Loading, Pop
17
17
  import { Sheet } from '../../../Sheet';
18
18
  // @ts-ignore
19
19
  import { ToastManager } from '../Toast/ToastManager';
20
- // @ts-ignore
21
- import { AdditionalRoomState, getRecordingText } from './AdditionalRoomState';
22
20
  import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
23
21
  import { useRecordingHandler } from '../../common/hooks';
24
22
  // @ts-ignore
25
23
  import { formatTime } from '../../common/utils';
26
24
 
25
+ export const getRecordingText = (
26
+ {
27
+ isBrowserRecordingOn,
28
+ isServerRecordingOn,
29
+ isHLSRecordingOn,
30
+ }: { isBrowserRecordingOn: boolean; isServerRecordingOn: boolean; isHLSRecordingOn: boolean },
31
+ delimiter = ', ',
32
+ ) => {
33
+ if (!isBrowserRecordingOn && !isServerRecordingOn && !isHLSRecordingOn) {
34
+ return '';
35
+ }
36
+ const title: string[] = [];
37
+ if (isBrowserRecordingOn) {
38
+ title.push('Browser');
39
+ }
40
+ if (isServerRecordingOn) {
41
+ title.push('Server');
42
+ }
43
+ if (isHLSRecordingOn) {
44
+ title.push('HLS');
45
+ }
46
+ return title.join(delimiter);
47
+ };
48
+
27
49
  export const LiveStatus = () => {
28
50
  const { isHLSRunning, isRTMPRunning } = useRecordingStreaming();
29
51
  const hlsState = useHMSStore(selectHLSState);
@@ -219,7 +241,6 @@ export const StreamActions = () => {
219
241
 
220
242
  return (
221
243
  <Flex align="center" css={{ gap: '$4' }}>
222
- <AdditionalRoomState />
223
244
  {!isMobile && (
224
245
  <Flex align="center" css={{ gap: '$4' }}>
225
246
  <RecordingPauseStatus />
@@ -89,7 +89,8 @@ export const DesktopOptions = ({
89
89
  const { isSupported, pipWindow, requestPipWindow } = usePIPChat();
90
90
  const isChatOpen = useIsSidepaneTypeOpen(SIDE_PANE_OPTIONS.CHAT);
91
91
  const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
92
- const showPipChatOption = !!elements?.chat && isSupported;
92
+ // Hide if pip chat is already open
93
+ const showPipChatOption = !!elements?.chat && isSupported && !pipWindow;
93
94
 
94
95
  useDropdownList({ open: openModals.size > 0, name: 'MoreSettings' });
95
96
 
@@ -102,9 +102,21 @@ export const PIPChat = () => {
102
102
  )}
103
103
  {filteredMessages.length === 0 ? (
104
104
  <div
105
- style={{ display: 'flex', height: '100%', width: '100%', alignItems: 'center', justifyContent: 'center' }}
105
+ style={{
106
+ display: 'flex',
107
+ flexDirection: 'column',
108
+ height: '100%',
109
+ width: '100%',
110
+ alignItems: 'center',
111
+ justifyContent: 'center',
112
+ }}
106
113
  >
107
- <Text>No messages here yet</Text>
114
+ <Text variant="h5" css={{ mt: '$8', c: '$on_surface_high' }}>
115
+ {canSendChatMessages ? 'Start a conversation' : 'No messages yet'}
116
+ </Text>
117
+ <Text variant="sm" style={{ maxWidth: '80%', textAlign: 'center', marginTop: '4px' }}>
118
+ There are no messages here yet. Start a conversation by sending a message.
119
+ </Text>
108
120
  </div>
109
121
  ) : (
110
122
  filteredMessages.map(message => (
@@ -9,7 +9,7 @@ export const PIPChatOption = ({ openChat, showPIPChat }: { openChat: () => void;
9
9
  }
10
10
  return (
11
11
  <Dropdown.Item onClick={openChat} data-testid="pip_chat_btn">
12
- <ExternalLinkIcon height={18} width={18} style={{ padding: '0 $2' }} />
12
+ <ExternalLinkIcon />
13
13
  <Text variant="sm" css={{ ml: '$4', color: '$on_surface_high' }}>
14
14
  Pop out Chat
15
15
  </Text>
@@ -1,15 +1,19 @@
1
- import React from 'react';
1
+ import React, { useEffect } from 'react';
2
+ import { HMSVirtualBackgroundTypes } from '@100mslive/hms-virtual-background';
2
3
  import {
3
4
  selectAppData,
4
5
  selectIsEffectsEnabled,
5
6
  selectIsLocalVideoEnabled,
6
7
  selectIsVBEnabled,
8
+ useAVToggle,
9
+ useHMSActions,
7
10
  useHMSStore,
8
11
  } from '@100mslive/react-sdk';
9
12
  import { VirtualBackgroundIcon } from '@100mslive/react-icons';
10
13
  import { Loading } from '../../../Loading';
11
14
  import { Tooltip } from '../../../Tooltip';
12
15
  import IconButton from '../../IconButton';
16
+ import { VBHandler } from './VBHandler';
13
17
  // @ts-ignore
14
18
  import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane';
15
19
  import { APP_DATA, isSafari, SIDE_PANE_OPTIONS } from '../../common/constants';
@@ -21,6 +25,15 @@ export const VBToggle = () => {
21
25
  const isVBEnabled = useHMSStore(selectIsVBEnabled);
22
26
  const isEffectsEnabled = useHMSStore(selectIsEffectsEnabled);
23
27
  const loadingEffects = useHMSStore(selectAppData(APP_DATA.loadingEffects));
28
+ const hmsActions = useHMSActions();
29
+ const { toggleVideo } = useAVToggle();
30
+
31
+ useEffect(() => {
32
+ if (!toggleVideo) {
33
+ VBHandler?.reset();
34
+ hmsActions.setAppData(APP_DATA.background, HMSVirtualBackgroundTypes.NONE);
35
+ }
36
+ }, [hmsActions, toggleVideo]);
24
37
 
25
38
  if (!isVideoOn || (!isEffectsEnabled && isSafari) || !isVBEnabled) {
26
39
  return null;