@100mslive/roomkit-react 0.3.8-alpha.0 → 0.3.8-alpha.2
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/{HLSView-CTZXD762.js → HLSView-XZDT3RRC.js} +2 -2
- package/dist/Prebuilt/common/constants.d.ts +2 -0
- package/dist/Prebuilt/common/hooks.d.ts +10 -0
- package/dist/Prebuilt/components/CaptionIcon.d.ts +2 -0
- package/dist/Prebuilt/components/FullPageProgress.d.ts +8 -0
- package/dist/Prebuilt/components/VirtualBackground/VBHandler.d.ts +3 -3
- package/dist/Prebuilt/plugins/CaptionsViewer.d.ts +2 -0
- package/dist/Text/Text.d.ts +1 -1
- package/dist/{chunk-NDLMRKFR.js → chunk-SQPIZNW2.js} +2367 -2128
- package/dist/chunk-SQPIZNW2.js.map +7 -0
- package/dist/index.cjs.js +3254 -2998
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +1 -1
- package/dist/meta.cjs.json +244 -86
- package/dist/meta.esbuild.json +250 -92
- package/package.json +6 -6
- package/src/Prebuilt/common/constants.ts +2 -0
- package/src/Prebuilt/common/hooks.ts +72 -1
- package/src/Prebuilt/components/AppData/AppData.tsx +2 -0
- package/src/Prebuilt/components/AppData/useUISettings.js +10 -0
- package/src/Prebuilt/components/CaptionIcon.tsx +27 -0
- package/src/Prebuilt/components/ConferenceScreen.tsx +34 -4
- package/src/Prebuilt/components/Footer/Footer.tsx +2 -0
- package/src/Prebuilt/components/Footer/RoleAccordion.tsx +1 -1
- package/src/Prebuilt/components/{FullPageProgress.jsx → FullPageProgress.tsx} +10 -1
- package/src/Prebuilt/components/Header/StreamActions.tsx +3 -25
- package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +25 -26
- package/src/Prebuilt/components/Notifications/PeerNotifications.tsx +1 -11
- package/src/Prebuilt/components/Preview/PreviewJoin.tsx +4 -9
- package/src/Prebuilt/components/Preview/PreviewScreen.tsx +0 -3
- package/src/Prebuilt/components/Settings/StartRecording.jsx +4 -37
- package/src/Prebuilt/components/Toast/ToastConfig.jsx +0 -22
- package/src/Prebuilt/components/VirtualBackground/VBHandler.tsx +3 -3
- package/src/Prebuilt/components/VirtualBackground/VBOption.tsx +3 -1
- package/src/Prebuilt/components/VirtualBackground/VBPicker.tsx +23 -7
- package/src/Prebuilt/components/VirtualBackground/VBToggle.tsx +5 -3
- package/src/Prebuilt/layouts/VideoStreamingSection.tsx +0 -3
- package/src/Prebuilt/plugins/CaptionsViewer.tsx +191 -0
- package/dist/chunk-NDLMRKFR.js.map +0 -7
- /package/dist/{HLSView-CTZXD762.js.map → HLSView-XZDT3RRC.js.map} +0 -0
package/package.json
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
"prebuilt",
|
11
11
|
"roomkit"
|
12
12
|
],
|
13
|
-
"version": "0.3.8-alpha.
|
13
|
+
"version": "0.3.8-alpha.2",
|
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.3.8-alpha.
|
85
|
+
"@100mslive/hls-player": "0.3.8-alpha.2",
|
86
86
|
"@100mslive/hms-noise-cancellation": "0.0.1",
|
87
|
-
"@100mslive/hms-virtual-background": "1.13.8-alpha.
|
88
|
-
"@100mslive/react-icons": "0.10.8-alpha.
|
89
|
-
"@100mslive/react-sdk": "0.10.8-alpha.
|
87
|
+
"@100mslive/hms-virtual-background": "1.13.8-alpha.2",
|
88
|
+
"@100mslive/react-icons": "0.10.8-alpha.2",
|
89
|
+
"@100mslive/react-sdk": "0.10.8-alpha.2",
|
90
90
|
"@100mslive/types-prebuilt": "0.12.8",
|
91
91
|
"@emoji-mart/data": "^1.0.6",
|
92
92
|
"@emoji-mart/react": "^1.0.1",
|
@@ -122,5 +122,5 @@
|
|
122
122
|
"uuid": "^8.3.2",
|
123
123
|
"worker-timers": "^7.0.40"
|
124
124
|
},
|
125
|
-
"gitHead": "
|
125
|
+
"gitHead": "43ee35cc85faabb5a827f7f41a5affebffcfca18"
|
126
126
|
}
|
@@ -3,20 +3,27 @@ import { useMedia } from 'react-use';
|
|
3
3
|
import { HMSHLSPlayer } from '@100mslive/hls-player';
|
4
4
|
import { JoinForm_JoinBtnType } from '@100mslive/types-prebuilt/elements/join_form';
|
5
5
|
import {
|
6
|
+
HMSRecording,
|
6
7
|
parsedUserAgent,
|
7
8
|
selectAvailableRoleNames,
|
8
9
|
selectIsConnectedToRoom,
|
9
10
|
selectPeerCount,
|
10
11
|
selectPeerMetadata,
|
11
12
|
selectPeers,
|
13
|
+
selectRecordingState,
|
12
14
|
selectRemotePeers,
|
15
|
+
useHMSActions,
|
13
16
|
useHMSStore,
|
14
17
|
useHMSVanillaStore,
|
15
18
|
} from '@100mslive/react-sdk';
|
19
|
+
// @ts-ignore: No implicit any
|
20
|
+
import { ToastManager } from '../components/Toast/ToastManager';
|
16
21
|
import { config } from '../../Theme';
|
17
22
|
import { useRoomLayout } from '../provider/roomLayoutProvider';
|
23
|
+
// @ts-ignore
|
24
|
+
import { useSetAppDataByKey } from '../components/AppData/useUISettings';
|
18
25
|
import { useRoomLayoutConferencingScreen } from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
19
|
-
import { CHAT_SELECTOR } from './constants';
|
26
|
+
import { APP_DATA, CHAT_SELECTOR, RTMP_RECORD_DEFAULT_RESOLUTION } from './constants';
|
20
27
|
/**
|
21
28
|
* Hook to execute a callback when alone in room(after a certain 5d of time)
|
22
29
|
* @param {number} thresholdMs The threshold(in ms) after which the callback is executed,
|
@@ -147,3 +154,67 @@ export const useKeyboardHandler = (isPaused: boolean, hlsPlayer: HMSHLSPlayer) =
|
|
147
154
|
|
148
155
|
return handleKeyEvent;
|
149
156
|
};
|
157
|
+
export interface RTMPRecordingResolution {
|
158
|
+
width: number;
|
159
|
+
height: number;
|
160
|
+
}
|
161
|
+
export const useRecordingHandler = () => {
|
162
|
+
const hmsActions = useHMSActions();
|
163
|
+
const recordingState: HMSRecording = useHMSStore(selectRecordingState);
|
164
|
+
const [isRecordingLoading, setIsRecordingLoading] = useState(false);
|
165
|
+
const [recordingStarted, setRecordingState] = useSetAppDataByKey(APP_DATA.recordingStarted);
|
166
|
+
useEffect(() => {
|
167
|
+
if (recordingState.browser.error && recordingStarted) {
|
168
|
+
setRecordingState(false);
|
169
|
+
}
|
170
|
+
}, [recordingStarted, recordingState.browser.error, setRecordingState]);
|
171
|
+
const startRecording = useCallback(
|
172
|
+
async (resolution: RTMPRecordingResolution | null = null) => {
|
173
|
+
try {
|
174
|
+
setRecordingState(true);
|
175
|
+
setIsRecordingLoading(true);
|
176
|
+
await hmsActions.startRTMPOrRecording({
|
177
|
+
resolution: getResolution(resolution),
|
178
|
+
record: true,
|
179
|
+
});
|
180
|
+
} catch (error) {
|
181
|
+
const err = error as Error;
|
182
|
+
if (err.message.includes('stream already running')) {
|
183
|
+
ToastManager.addToast({
|
184
|
+
title: 'Recording already running',
|
185
|
+
variant: 'error',
|
186
|
+
});
|
187
|
+
} else {
|
188
|
+
ToastManager.addToast({
|
189
|
+
title: err.message,
|
190
|
+
variant: 'error',
|
191
|
+
});
|
192
|
+
}
|
193
|
+
setRecordingState(false);
|
194
|
+
}
|
195
|
+
setIsRecordingLoading(false);
|
196
|
+
},
|
197
|
+
[hmsActions, setRecordingState],
|
198
|
+
);
|
199
|
+
return {
|
200
|
+
recordingStarted,
|
201
|
+
startRecording,
|
202
|
+
isRecordingLoading,
|
203
|
+
};
|
204
|
+
};
|
205
|
+
|
206
|
+
export function getResolution(
|
207
|
+
recordingResolution: RTMPRecordingResolution | null,
|
208
|
+
): RTMPRecordingResolution | undefined {
|
209
|
+
if (!recordingResolution) {
|
210
|
+
return undefined;
|
211
|
+
}
|
212
|
+
const resolution: RTMPRecordingResolution = RTMP_RECORD_DEFAULT_RESOLUTION;
|
213
|
+
if (recordingResolution.width) {
|
214
|
+
resolution.width = recordingResolution.width;
|
215
|
+
}
|
216
|
+
if (recordingResolution.height) {
|
217
|
+
resolution.height = recordingResolution.height;
|
218
|
+
}
|
219
|
+
return resolution;
|
220
|
+
}
|
@@ -62,11 +62,13 @@ const initialAppData = {
|
|
62
62
|
[APP_DATA.minimiseInset]: false,
|
63
63
|
[APP_DATA.activeScreensharePeerId]: '',
|
64
64
|
[APP_DATA.disableNotifications]: false,
|
65
|
+
[APP_DATA.loadingEffects]: false,
|
65
66
|
[APP_DATA.background]: 'none',
|
66
67
|
[APP_DATA.pollState]: {
|
67
68
|
[POLL_STATE.pollInView]: '',
|
68
69
|
[POLL_STATE.view]: '',
|
69
70
|
},
|
71
|
+
[APP_DATA.caption]: true,
|
70
72
|
};
|
71
73
|
|
72
74
|
export const AppData = React.memo(() => {
|
@@ -107,6 +107,16 @@ export const useSetSubscribedNotifications = notificationKey => {
|
|
107
107
|
return [value, setValue];
|
108
108
|
};
|
109
109
|
|
110
|
+
export const useIsCaptionEnabled = () => {
|
111
|
+
const isCaptionEnabled = useHMSStore(selectAppDataByPath(APP_DATA.caption));
|
112
|
+
return isCaptionEnabled;
|
113
|
+
};
|
114
|
+
|
115
|
+
export const useSetIsCaptionEnabled = () => {
|
116
|
+
const [value, setValue] = useSetAppDataByKey(APP_DATA.caption);
|
117
|
+
return [value, setValue];
|
118
|
+
};
|
119
|
+
|
110
120
|
export const useSubscribeChatSelector = chatSelectorKey => {
|
111
121
|
const chatSelectorPreference = useHMSStore(selectAppDataByPath(APP_DATA.chatSelector, chatSelectorKey));
|
112
122
|
return chatSelectorPreference;
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { selectIsTranscriptionEnabled, useHMSStore } from '@100mslive/react-sdk';
|
3
|
+
import { ClosedCaptionIcon, OpenCaptionIcon } from '@100mslive/react-icons';
|
4
|
+
import { Tooltip } from '../../Tooltip';
|
5
|
+
// @ts-ignore: No implicit Any
|
6
|
+
import IconButton from '../IconButton';
|
7
|
+
// @ts-ignore: No implicit Any
|
8
|
+
import { useSetIsCaptionEnabled } from './AppData/useUISettings.js';
|
9
|
+
|
10
|
+
export const CaptionIcon = () => {
|
11
|
+
const isCaptionPresent = useHMSStore(selectIsTranscriptionEnabled);
|
12
|
+
const [isCaption, setIsCaption] = useSetIsCaptionEnabled();
|
13
|
+
|
14
|
+
const onClick = () => {
|
15
|
+
setIsCaption(!isCaption);
|
16
|
+
};
|
17
|
+
if (!isCaptionPresent) {
|
18
|
+
return null;
|
19
|
+
}
|
20
|
+
return (
|
21
|
+
<Tooltip title={isCaption ? 'Disable caption' : 'Enable caption'}>
|
22
|
+
<IconButton data-testid="caption_btn" onClick={onClick}>
|
23
|
+
{isCaption ? <ClosedCaptionIcon width="20" height="20px" /> : <OpenCaptionIcon width="20" height="20px" />}
|
24
|
+
</IconButton>
|
25
|
+
</Tooltip>
|
26
|
+
);
|
27
|
+
};
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react';
|
2
|
+
import { useMedia } from 'react-use';
|
2
3
|
import { DefaultConferencingScreen_Elements } from '@100mslive/types-prebuilt';
|
3
4
|
import { v4 as uuid } from 'uuid';
|
4
5
|
import {
|
@@ -18,27 +19,30 @@ import { ActivatedPIP } from './PIP/PIPComponent';
|
|
18
19
|
import { PictureInPicture } from './PIP/PIPManager';
|
19
20
|
import { RoleChangeRequestModal } from './RoleChangeRequest/RoleChangeRequestModal';
|
20
21
|
import { Box, Flex } from '../../Layout';
|
22
|
+
import { config } from '../../Theme';
|
21
23
|
import { useHMSPrebuiltContext } from '../AppContext';
|
22
24
|
import { VideoStreamingSection } from '../layouts/VideoStreamingSection';
|
23
25
|
// @ts-ignore: No implicit Any
|
24
26
|
import { EmojiReaction } from './EmojiReaction';
|
25
|
-
// @ts-ignore: No implicit Any
|
26
27
|
import FullPageProgress from './FullPageProgress';
|
27
28
|
import { Header } from './Header';
|
28
29
|
import { PreviousRoleInMetadata } from './PreviousRoleInMetadata';
|
29
30
|
import { RaiseHand } from './RaiseHand';
|
31
|
+
import { CaptionsViewer } from '../plugins/CaptionsViewer';
|
30
32
|
import {
|
31
33
|
useRoomLayoutConferencingScreen,
|
32
34
|
useRoomLayoutPreviewScreen,
|
33
35
|
} from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
34
36
|
// @ts-ignore: No implicit Any
|
35
|
-
import {
|
36
|
-
import { useLandscapeHLSStream, useMobileHLSStream } from '../common/hooks';
|
37
|
+
import { useIsSidepaneTypeOpen } from './AppData/useSidepane';
|
37
38
|
// @ts-ignore: No implicit Any
|
38
|
-
import {
|
39
|
+
import { useAuthToken, useIsCaptionEnabled, useSetAppDataByKey } from './AppData/useUISettings';
|
40
|
+
import { useLandscapeHLSStream, useMobileHLSStream } from '../common/hooks';
|
41
|
+
import { APP_DATA, isAndroid, isIOS, isIPadOS, SIDE_PANE_OPTIONS } from '../common/constants';
|
39
42
|
|
40
43
|
export const ConferenceScreen = () => {
|
41
44
|
const { userName, endpoints, onJoin: onJoinFunc } = useHMSPrebuiltContext();
|
45
|
+
const isMobile = useMedia(config.media.md);
|
42
46
|
const screenProps = useRoomLayoutConferencingScreen();
|
43
47
|
const { isPreviewScreenEnabled } = useRoomLayoutPreviewScreen();
|
44
48
|
const roomState = useHMSStore(selectRoomState);
|
@@ -59,6 +63,10 @@ export const ConferenceScreen = () => {
|
|
59
63
|
const isMobileHLSStream = useMobileHLSStream();
|
60
64
|
const isLandscapeHLSStream = useLandscapeHLSStream();
|
61
65
|
const isMwebHLSStream = isMobileHLSStream || isLandscapeHLSStream;
|
66
|
+
const isCaptionEnabled = useIsCaptionEnabled();
|
67
|
+
const isChatOpen = useIsSidepaneTypeOpen(SIDE_PANE_OPTIONS.CHAT);
|
68
|
+
|
69
|
+
const showCaptionAtTop = screenProps.elements?.chat?.is_overlay && isChatOpen;
|
62
70
|
|
63
71
|
const toggleControls = () => {
|
64
72
|
if (dropdownListRef.current?.length === 0 && isMobileDevice && !isMwebHLSStream) {
|
@@ -126,6 +134,28 @@ export const ConferenceScreen = () => {
|
|
126
134
|
<FullPageProgress text="Starting live stream..." css={{ opacity: 0.8, bg: '$background_dim' }} />
|
127
135
|
</Box>
|
128
136
|
) : null}
|
137
|
+
{isCaptionEnabled && screenProps.screenType !== 'hls_live_streaming' && (
|
138
|
+
<Box
|
139
|
+
css={{
|
140
|
+
position: 'fixed',
|
141
|
+
maxWidth: isMobile ? '100%' : '40%',
|
142
|
+
bottom: showCaptionAtTop ? '' : hideControlsForStreaming ? '5%' : '10%',
|
143
|
+
top: showCaptionAtTop ? (hideControlsForStreaming ? '5%' : '10%') : '',
|
144
|
+
left: isMobile ? 0 : '50%',
|
145
|
+
transform: isMobile ? '' : 'translateX(-50%)',
|
146
|
+
background: '#000000A3',
|
147
|
+
overflow: 'clip',
|
148
|
+
zIndex: 10,
|
149
|
+
height: 'fit-content',
|
150
|
+
r: '$1',
|
151
|
+
p: '$6',
|
152
|
+
transition: 'bottom 0.3s ease-in-out',
|
153
|
+
'&:empty': { display: 'none' },
|
154
|
+
}}
|
155
|
+
>
|
156
|
+
<CaptionsViewer />
|
157
|
+
</Box>
|
158
|
+
)}
|
129
159
|
<Flex css={{ size: '100%', overflow: 'hidden' }} direction="column">
|
130
160
|
{!(screenProps.hideSections.includes('header') || isMwebHLSStream) && (
|
131
161
|
<Box
|
@@ -5,6 +5,7 @@ import { Chat_ChatState } from '@100mslive/types-prebuilt/elements/chat';
|
|
5
5
|
import { config as cssConfig, Footer as AppFooter } from '../../..';
|
6
6
|
// @ts-ignore: No implicit Any
|
7
7
|
import { AudioVideoToggle } from '../AudioVideoToggle';
|
8
|
+
import { CaptionIcon } from '../CaptionIcon';
|
8
9
|
// @ts-ignore: No implicit Any
|
9
10
|
import { EmojiReaction } from '../EmojiReaction';
|
10
11
|
// @ts-ignore: No implicit Any
|
@@ -96,6 +97,7 @@ export const Footer = ({
|
|
96
97
|
<>
|
97
98
|
<ScreenshareToggle />
|
98
99
|
<RaiseHand />
|
100
|
+
{screenType !== 'hls_live_streaming' && <CaptionIcon />}
|
99
101
|
{elements?.emoji_reactions && <EmojiReaction />}
|
100
102
|
<LeaveRoom screenType={screenType} />
|
101
103
|
</>
|
@@ -109,7 +109,7 @@ export const RoleAccordion = ({
|
|
109
109
|
},
|
110
110
|
}}
|
111
111
|
>
|
112
|
-
<Flex justify="between" css={{ flexGrow: 1, pr: '$6' }}>
|
112
|
+
<Flex justify="between" align="center" css={{ flexGrow: 1, pr: '$6' }}>
|
113
113
|
<Text
|
114
114
|
variant="sm"
|
115
115
|
css={{ fontWeight: '$semiBold', textTransform: 'capitalize', color: '$on_surface_medium' }}
|
@@ -2,8 +2,17 @@ import React from 'react';
|
|
2
2
|
import { Flex } from '../../Layout';
|
3
3
|
import { Loading } from '../../Loading';
|
4
4
|
import { Text } from '../../Text';
|
5
|
+
import { CSS } from '../../Theme';
|
5
6
|
|
6
|
-
const FullPageProgress = ({
|
7
|
+
const FullPageProgress = ({
|
8
|
+
loaderColor = '$primary_default',
|
9
|
+
text = '',
|
10
|
+
css = {},
|
11
|
+
}: {
|
12
|
+
loaderColor?: string;
|
13
|
+
text?: string;
|
14
|
+
css?: CSS;
|
15
|
+
}) => (
|
7
16
|
<Flex direction="column" justify="center" align="center" css={{ size: '100%', color: loaderColor, ...css }}>
|
8
17
|
<Loading color="currentColor" size={100} />
|
9
18
|
{text ? <Text css={{ mt: '$10', color: '$on_surface_high' }}>{text}</Text> : null}
|
@@ -20,12 +20,9 @@ import { ToastManager } from '../Toast/ToastManager';
|
|
20
20
|
// @ts-ignore
|
21
21
|
import { AdditionalRoomState, getRecordingText } from './AdditionalRoomState';
|
22
22
|
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
23
|
-
|
24
|
-
import { useSetAppDataByKey } from '../AppData/useUISettings';
|
23
|
+
import { useRecordingHandler } from '../../common/hooks';
|
25
24
|
// @ts-ignore
|
26
25
|
import { formatTime } from '../../common/utils';
|
27
|
-
// @ts-ignore
|
28
|
-
import { APP_DATA } from '../../common/constants';
|
29
26
|
|
30
27
|
export const LiveStatus = () => {
|
31
28
|
const { isHLSRunning, isRTMPRunning } = useRecordingStreaming();
|
@@ -147,7 +144,7 @@ export const RecordingPauseStatus = () => {
|
|
147
144
|
const StartRecording = () => {
|
148
145
|
const permissions = useHMSStore(selectPermissions);
|
149
146
|
const [open, setOpen] = useState(false);
|
150
|
-
const
|
147
|
+
const { startRecording, recordingStarted } = useRecordingHandler();
|
151
148
|
const { isBrowserRecordingOn, isStreamingOn, isHLSRunning } = useRecordingStreaming();
|
152
149
|
const hmsActions = useHMSActions();
|
153
150
|
if (!permissions?.browserRecording || isHLSRunning) {
|
@@ -201,26 +198,7 @@ const StartRecording = () => {
|
|
201
198
|
icon
|
202
199
|
disabled={recordingStarted || isStreamingOn}
|
203
200
|
onClick={async () => {
|
204
|
-
|
205
|
-
setRecordingState(true);
|
206
|
-
await hmsActions.startRTMPOrRecording({
|
207
|
-
record: true,
|
208
|
-
});
|
209
|
-
} catch (error) {
|
210
|
-
const err = error as Error;
|
211
|
-
if (err.message.includes('stream already running')) {
|
212
|
-
ToastManager.addToast({
|
213
|
-
title: 'Recording already running',
|
214
|
-
variant: 'error',
|
215
|
-
});
|
216
|
-
} else {
|
217
|
-
ToastManager.addToast({
|
218
|
-
title: err.message,
|
219
|
-
variant: 'error',
|
220
|
-
});
|
221
|
-
}
|
222
|
-
setRecordingState(false);
|
223
|
-
}
|
201
|
+
await startRecording();
|
224
202
|
}}
|
225
203
|
>
|
226
204
|
{recordingStarted ? <Loading size={24} color="currentColor" /> : <RecordIcon />}
|
@@ -5,6 +5,7 @@ import { match } from 'ts-pattern';
|
|
5
5
|
import {
|
6
6
|
selectIsConnectedToRoom,
|
7
7
|
selectIsLocalVideoEnabled,
|
8
|
+
selectIsTranscriptionEnabled,
|
8
9
|
selectPeerCount,
|
9
10
|
selectPermissions,
|
10
11
|
useHMSActions,
|
@@ -13,12 +14,14 @@ import {
|
|
13
14
|
} from '@100mslive/react-sdk';
|
14
15
|
import {
|
15
16
|
BrbIcon,
|
17
|
+
ClosedCaptionIcon,
|
16
18
|
CrossIcon,
|
17
19
|
EmojiIcon,
|
18
20
|
HamburgerMenuIcon,
|
19
21
|
HandIcon,
|
20
22
|
HandRaiseSlashedIcon,
|
21
23
|
InfoIcon,
|
24
|
+
OpenCaptionIcon,
|
22
25
|
PeopleIcon,
|
23
26
|
QuizActiveIcon,
|
24
27
|
QuizIcon,
|
@@ -49,12 +52,12 @@ import { useSheetToggle } from '../../AppData/useSheet';
|
|
49
52
|
// @ts-ignore: No implicit any
|
50
53
|
import { usePollViewToggle, useSidepaneToggle } from '../../AppData/useSidepane';
|
51
54
|
// @ts-ignore: No implicit Any
|
52
|
-
import { useShowPolls } from '../../AppData/useUISettings';
|
55
|
+
import { useSetIsCaptionEnabled, useShowPolls } from '../../AppData/useUISettings';
|
53
56
|
// @ts-ignore: No implicit any
|
54
57
|
import { useDropdownList } from '../../hooks/useDropdownList';
|
55
58
|
import { useMyMetadata } from '../../hooks/useMetadata';
|
56
59
|
import { useUnreadPollQuizPresent } from '../../hooks/useUnreadPollQuizPresent';
|
57
|
-
import { useLandscapeHLSStream, useMobileHLSStream } from '../../../common/hooks';
|
60
|
+
import { useLandscapeHLSStream, useMobileHLSStream, useRecordingHandler } from '../../../common/hooks';
|
58
61
|
// @ts-ignore: No implicit any
|
59
62
|
import { getFormattedCount } from '../../../common/utils';
|
60
63
|
// @ts-ignore: No implicit any
|
@@ -88,7 +91,6 @@ export const MwebOptions = ({
|
|
88
91
|
const [openSettingsSheet, setOpenSettingsSheet] = useState(false);
|
89
92
|
const [showEmojiCard, setShowEmojiCard] = useState(false);
|
90
93
|
const [showRecordingOn, setShowRecordingOn] = useState(false);
|
91
|
-
const [isRecordingLoading, setIsRecordingLoading] = useState(false);
|
92
94
|
const toggleParticipants = useSidepaneToggle(SIDE_PANE_OPTIONS.PARTICIPANTS);
|
93
95
|
const { showPolls } = useShowPolls();
|
94
96
|
const togglePollView = usePollViewToggle();
|
@@ -102,7 +104,11 @@ export const MwebOptions = ({
|
|
102
104
|
const isLandscapeHLSStream = useLandscapeHLSStream();
|
103
105
|
const toggleVB = useSidepaneToggle(SIDE_PANE_OPTIONS.VB);
|
104
106
|
const isLocalVideoEnabled = useHMSStore(selectIsLocalVideoEnabled);
|
107
|
+
const { startRecording, isRecordingLoading } = useRecordingHandler();
|
105
108
|
|
109
|
+
const isCaptionPresent = useHMSStore(selectIsTranscriptionEnabled);
|
110
|
+
|
111
|
+
const [isCaptionEnabled, setIsCaptionEnabled] = useSetIsCaptionEnabled();
|
106
112
|
useDropdownList({ open: openModals.size > 0 || openOptionsSheet || openSettingsSheet, name: 'MoreSettings' });
|
107
113
|
|
108
114
|
const updateState = (modalName: string, value: boolean) => {
|
@@ -187,6 +193,20 @@ export const MwebOptions = ({
|
|
187
193
|
<ActionTile.Title>{isHandRaised ? 'Lower' : 'Raise'} Hand</ActionTile.Title>
|
188
194
|
</ActionTile.Root>
|
189
195
|
) : null}
|
196
|
+
{isCaptionPresent && screenType !== 'hls_live_streaming' ? (
|
197
|
+
<ActionTile.Root
|
198
|
+
onClick={() => {
|
199
|
+
setIsCaptionEnabled(!isCaptionEnabled);
|
200
|
+
}}
|
201
|
+
>
|
202
|
+
{isCaptionEnabled ? (
|
203
|
+
<ClosedCaptionIcon width="20" height="20px" />
|
204
|
+
) : (
|
205
|
+
<OpenCaptionIcon width="20" height="20px" />
|
206
|
+
)}
|
207
|
+
<ActionTile.Title>{isCaptionEnabled ? 'Hide Captions' : 'Captions Disabled'}</ActionTile.Title>
|
208
|
+
</ActionTile.Root>
|
209
|
+
) : null}
|
190
210
|
|
191
211
|
{isLocalVideoEnabled && !!elements?.virtual_background ? (
|
192
212
|
<ActionTile.Root
|
@@ -260,29 +280,8 @@ export const MwebOptions = ({
|
|
260
280
|
setShowRecordingOn(true);
|
261
281
|
} else {
|
262
282
|
// start recording
|
263
|
-
|
264
|
-
|
265
|
-
await hmsActions.startRTMPOrRecording({
|
266
|
-
record: true,
|
267
|
-
});
|
268
|
-
setOpenOptionsSheet(false);
|
269
|
-
setIsRecordingLoading(false);
|
270
|
-
} catch (error) {
|
271
|
-
// @ts-ignore
|
272
|
-
if (error.message.includes('stream already running')) {
|
273
|
-
ToastManager.addToast({
|
274
|
-
title: 'Recording already running',
|
275
|
-
variant: 'error',
|
276
|
-
});
|
277
|
-
} else {
|
278
|
-
ToastManager.addToast({
|
279
|
-
// @ts-ignore
|
280
|
-
title: error.message,
|
281
|
-
variant: 'error',
|
282
|
-
});
|
283
|
-
}
|
284
|
-
setIsRecordingLoading(false);
|
285
|
-
}
|
283
|
+
await startRecording();
|
284
|
+
setOpenOptionsSheet(false);
|
286
285
|
}
|
287
286
|
if (isHLSRunning) {
|
288
287
|
setOpenOptionsSheet(false);
|
@@ -7,11 +7,7 @@ import { useSetSubscribedChatSelector, useSubscribedNotifications } from '../App
|
|
7
7
|
// @ts-ignore: No implicit Any
|
8
8
|
import { CHAT_SELECTOR, SUBSCRIBED_NOTIFICATIONS } from '../../common/constants';
|
9
9
|
|
10
|
-
const notificationTypes = [
|
11
|
-
HMSNotificationTypes.PEER_LIST,
|
12
|
-
HMSNotificationTypes.PEER_JOINED,
|
13
|
-
HMSNotificationTypes.PEER_LEFT,
|
14
|
-
];
|
10
|
+
const notificationTypes = [HMSNotificationTypes.PEER_JOINED, HMSNotificationTypes.PEER_LEFT];
|
15
11
|
|
16
12
|
export const PeerNotifications = () => {
|
17
13
|
const notification = useHMSNotifications(notificationTypes);
|
@@ -26,11 +22,6 @@ export const PeerNotifications = () => {
|
|
26
22
|
|
27
23
|
console.debug(`[${notification.type}]`, notification);
|
28
24
|
switch (notification.type) {
|
29
|
-
case HMSNotificationTypes.PEER_LIST:
|
30
|
-
if (!isPeerJoinSubscribed || notification.data.length === 0) {
|
31
|
-
return;
|
32
|
-
}
|
33
|
-
break;
|
34
25
|
case HMSNotificationTypes.PEER_JOINED:
|
35
26
|
if (!isPeerJoinSubscribed) {
|
36
27
|
return;
|
@@ -47,7 +38,6 @@ export const PeerNotifications = () => {
|
|
47
38
|
default:
|
48
39
|
return;
|
49
40
|
}
|
50
|
-
|
51
41
|
ToastBatcher.showToast({ notification });
|
52
42
|
}, [notification, isPeerJoinSubscribed, isPeerLeftSubscribed, selectedPeer.id, setPeerSelector]);
|
53
43
|
|
@@ -2,6 +2,7 @@ import React, { Fragment, useCallback, useEffect, useMemo, useState } from 'reac
|
|
2
2
|
import { useMeasure, useMedia } from 'react-use';
|
3
3
|
import {
|
4
4
|
HMSRoomState,
|
5
|
+
selectAppData,
|
5
6
|
selectIsLocalVideoEnabled,
|
6
7
|
selectLocalPeer,
|
7
8
|
selectRoomState,
|
@@ -16,24 +17,17 @@ import { MicOffIcon, SettingsIcon } from '@100mslive/react-icons';
|
|
16
17
|
import { Avatar, Box, config as cssConfig, Flex, flexCenter, styled, StyledVideoTile, Text, Video } from '../../..';
|
17
18
|
import { AudioLevel } from '../../../AudioLevel';
|
18
19
|
import { useHMSPrebuiltContext } from '../../AppContext';
|
19
|
-
// @ts-ignore: No implicit Any
|
20
20
|
import IconButton from '../../IconButton';
|
21
21
|
import SidePane from '../../layouts/SidePane';
|
22
|
-
// @ts-ignore: No implicit Any
|
23
22
|
import { AudioVideoToggle } from '../AudioVideoToggle';
|
24
|
-
// @ts-ignore: No implicit Any
|
25
23
|
import Chip from '../Chip';
|
26
|
-
// @ts-ignore: No implicit Any
|
27
24
|
import TileConnection from '../Connection/TileConnection';
|
28
|
-
// @ts-ignore: No implicit Any
|
29
25
|
import FullPageProgress from '../FullPageProgress';
|
30
26
|
// @ts-ignore: No implicit Any
|
31
27
|
import { Logo } from '../Header/HeaderComponents';
|
32
28
|
// @ts-ignore: No implicit Any
|
33
29
|
import SettingsModal from '../Settings/SettingsModal';
|
34
|
-
// @ts-ignore: No implicit Any
|
35
30
|
import { VBToggle } from '../VirtualBackground/VBToggle';
|
36
|
-
// @ts-ignore: No implicit Any
|
37
31
|
import PreviewForm from './PreviewForm';
|
38
32
|
import { useRoomLayoutPreviewScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
39
33
|
// @ts-ignore: No implicit Any
|
@@ -42,7 +36,7 @@ import { useAuthToken, useUISettings } from '../AppData/useUISettings';
|
|
42
36
|
import { defaultPreviewPreference, UserPreferencesKeys, useUserPreferences } from '../hooks/useUserPreferences';
|
43
37
|
// @ts-ignore: No implicit Any
|
44
38
|
import { calculateAvatarAndAttribBoxSize, getFormattedCount } from '../../common/utils';
|
45
|
-
import { UI_SETTINGS } from '../../common/constants';
|
39
|
+
import { APP_DATA, UI_SETTINGS } from '../../common/constants';
|
46
40
|
|
47
41
|
const getParticipantChipContent = (peerCount = 0) => {
|
48
42
|
if (peerCount === 0) {
|
@@ -85,6 +79,7 @@ const PreviewJoin = ({
|
|
85
79
|
const [previewError, setPreviewError] = useState(false);
|
86
80
|
const { endpoints } = useHMSPrebuiltContext();
|
87
81
|
const { peerCount } = useParticipants();
|
82
|
+
const loadingEffects = useHMSStore(selectAppData(APP_DATA.loadingEffects));
|
88
83
|
const { enableJoin, preview, join } = usePreviewJoin({
|
89
84
|
name,
|
90
85
|
token: authToken,
|
@@ -166,7 +161,7 @@ const PreviewJoin = ({
|
|
166
161
|
name={name}
|
167
162
|
disabled={!!initialName}
|
168
163
|
onChange={setName}
|
169
|
-
enableJoin={enableJoin}
|
164
|
+
enableJoin={enableJoin && !loadingEffects}
|
170
165
|
onJoin={savePreferenceAndJoin}
|
171
166
|
cannotPublishVideo={!toggleVideo}
|
172
167
|
cannotPublishAudio={!toggleAudio}
|
@@ -3,14 +3,11 @@ import { useSearchParam } from 'react-use';
|
|
3
3
|
import { Flex } from '../../..';
|
4
4
|
import { useHMSPrebuiltContext } from '../../AppContext';
|
5
5
|
import { useRoomLayout } from '../../provider/roomLayoutProvider';
|
6
|
-
// @ts-ignore: No implicit Any
|
7
6
|
import FullPageProgress from '../FullPageProgress';
|
8
|
-
// @ts-ignore: No implicit Any
|
9
7
|
import PreviewJoin from './PreviewJoin';
|
10
8
|
import { useRoomLayoutPreviewScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
11
9
|
// @ts-ignore: No implicit Any
|
12
10
|
import { useAuthToken } from '../AppData/useUISettings';
|
13
|
-
// @ts-ignore: No implicit Any
|
14
11
|
import { QUERY_PARAM_PREVIEW_AS_ROLE } from '../../common/constants';
|
15
12
|
|
16
13
|
export const PreviewScreen = () => {
|
@@ -4,27 +4,13 @@ import { AlertTriangleIcon } from '@100mslive/react-icons';
|
|
4
4
|
import { Button, Dialog, Flex, Text } from '../../../';
|
5
5
|
import { ResolutionInput } from '../Streaming/ResolutionInput';
|
6
6
|
import { ToastManager } from '../Toast/ToastManager';
|
7
|
-
import {
|
8
|
-
import {
|
9
|
-
|
10
|
-
export function getResolution(recordingResolution) {
|
11
|
-
const resolution = {};
|
12
|
-
if (recordingResolution.width) {
|
13
|
-
resolution.width = recordingResolution.width;
|
14
|
-
}
|
15
|
-
if (recordingResolution.height) {
|
16
|
-
resolution.height = recordingResolution.height;
|
17
|
-
}
|
18
|
-
if (Object.keys(resolution).length > 0) {
|
19
|
-
return resolution;
|
20
|
-
}
|
21
|
-
}
|
7
|
+
import { useRecordingHandler } from '../../common/hooks';
|
8
|
+
import { RTMP_RECORD_DEFAULT_RESOLUTION } from '../../common/constants';
|
22
9
|
|
23
10
|
const StartRecording = ({ open, onOpenChange }) => {
|
24
11
|
const permissions = useHMSStore(selectPermissions);
|
25
12
|
const [resolution, setResolution] = useState(RTMP_RECORD_DEFAULT_RESOLUTION);
|
26
|
-
|
27
|
-
const [recordingStarted, setRecordingState] = useSetAppDataByKey(APP_DATA.recordingStarted);
|
13
|
+
const { startRecording, recordingStarted } = useRecordingHandler();
|
28
14
|
const { isBrowserRecordingOn, isStreamingOn, isHLSRunning } = useRecordingStreaming();
|
29
15
|
const hmsActions = useHMSActions();
|
30
16
|
if (!permissions?.browserRecording || isHLSRunning) {
|
@@ -101,26 +87,7 @@ const StartRecording = ({ open, onOpenChange }) => {
|
|
101
87
|
type="submit"
|
102
88
|
disabled={recordingStarted || isStreamingOn}
|
103
89
|
onClick={async () => {
|
104
|
-
|
105
|
-
setRecordingState(true);
|
106
|
-
await hmsActions.startRTMPOrRecording({
|
107
|
-
resolution: getResolution(resolution),
|
108
|
-
record: true,
|
109
|
-
});
|
110
|
-
} catch (error) {
|
111
|
-
if (error.message.includes('stream already running')) {
|
112
|
-
ToastManager.addToast({
|
113
|
-
title: 'Recording already running',
|
114
|
-
variant: 'error',
|
115
|
-
});
|
116
|
-
} else {
|
117
|
-
ToastManager.addToast({
|
118
|
-
title: error.message,
|
119
|
-
variant: 'error',
|
120
|
-
});
|
121
|
-
}
|
122
|
-
setRecordingState(false);
|
123
|
-
}
|
90
|
+
await startRecording(resolution);
|
124
91
|
onOpenChange(false);
|
125
92
|
}}
|
126
93
|
>
|