@100mslive/roomkit-react 0.3.11 → 0.3.12-alpha.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,9 +6,25 @@ import {
6
6
  HLSLiveStreamingScreen_Elements,
7
7
  } from '@100mslive/types-prebuilt';
8
8
  import { match } from 'ts-pattern';
9
- import { selectAppData, selectLocalPeerID, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
10
- import { BrbIcon, CheckIcon, HamburgerMenuIcon, InfoIcon, PipIcon, SettingsIcon } from '@100mslive/react-icons';
11
- import { Checkbox, Dropdown, Flex, Text, Tooltip } from '../../../..';
9
+ import {
10
+ HMSTranscriptionMode,
11
+ selectAppData,
12
+ selectIsTranscriptionAllowedByMode,
13
+ selectIsTranscriptionEnabled,
14
+ selectLocalPeerID,
15
+ useHMSActions,
16
+ useHMSStore,
17
+ } from '@100mslive/react-sdk';
18
+ import {
19
+ BrbIcon,
20
+ CheckIcon,
21
+ HamburgerMenuIcon,
22
+ InfoIcon,
23
+ OpenCaptionIcon,
24
+ PipIcon,
25
+ SettingsIcon,
26
+ } from '@100mslive/react-icons';
27
+ import { Checkbox, Dropdown, Flex, Switch, Text, Tooltip } from '../../../..';
12
28
  import IconButton from '../../../IconButton';
13
29
  // @ts-ignore: No implicit any
14
30
  import { PIP } from '../../PIP';
@@ -61,6 +77,8 @@ export const DesktopOptions = ({
61
77
  const { isBRBOn, toggleBRB } = useMyMetadata();
62
78
  const isPipOn = PictureInPicture.isOn();
63
79
  const isBRBEnabled = !!elements?.brb;
80
+ const isTranscriptionAllowed = useHMSStore(selectIsTranscriptionAllowedByMode(HMSTranscriptionMode.CAPTION));
81
+ const isTranscriptionEnabled = useHMSStore(selectIsTranscriptionEnabled);
64
82
 
65
83
  useDropdownList({ open: openModals.size > 0, name: 'MoreSettings' });
66
84
 
@@ -116,6 +134,25 @@ export const DesktopOptions = ({
116
134
  </Flex>
117
135
  </Dropdown.Item>
118
136
  ) : null}
137
+ {isTranscriptionAllowed ? (
138
+ <Dropdown.Item
139
+ data-testid="closed_caption_admin"
140
+ onClick={() => {
141
+ updateState(MODALS.CAPTION, true);
142
+ }}
143
+ >
144
+ <OpenCaptionIcon />
145
+ <Flex direction="column" css={{ flexGrow: '1' }}>
146
+ <Text variant="sm" css={{ ml: '$4', color: '$on_surface_high' }}>
147
+ Closed Captions
148
+ </Text>
149
+ <Text variant="caption" css={{ ml: '$4', color: '$on_surface_medium' }}>
150
+ {isTranscriptionEnabled ? 'Enabled' : 'Disabled'}
151
+ </Text>
152
+ </Flex>
153
+ <Switch id="closed_caption_start_stop" checked={isTranscriptionEnabled} disabled={false} />
154
+ </Dropdown.Item>
155
+ ) : null}
119
156
  {screenType !== 'hls_live_streaming' ? (
120
157
  <Dropdown.Item css={{ p: 0, '&:empty': { display: 'none' } }}>
121
158
  <PIP
@@ -3,8 +3,11 @@ import { useClickAway } from 'react-use';
3
3
  import { ConferencingScreen, DefaultConferencingScreen_Elements } from '@100mslive/types-prebuilt';
4
4
  import { match } from 'ts-pattern';
5
5
  import {
6
+ HMSTranscriptionMode,
6
7
  selectIsConnectedToRoom,
7
8
  selectIsLocalVideoEnabled,
9
+ selectIsTranscriptionAllowedByMode,
10
+ selectIsTranscriptionEnabled,
8
11
  selectPeerCount,
9
12
  selectPermissions,
10
13
  useHMSActions,
@@ -13,12 +16,14 @@ import {
13
16
  } from '@100mslive/react-sdk';
14
17
  import {
15
18
  BrbIcon,
19
+ ClosedCaptionIcon,
16
20
  CrossIcon,
17
21
  EmojiIcon,
18
22
  HamburgerMenuIcon,
19
23
  HandIcon,
20
24
  HandRaiseSlashedIcon,
21
25
  InfoIcon,
26
+ OpenCaptionIcon,
22
27
  PeopleIcon,
23
28
  QuizActiveIcon,
24
29
  QuizIcon,
@@ -50,7 +55,7 @@ import { useSheetToggle } from '../../AppData/useSheet';
50
55
  // @ts-ignore: No implicit any
51
56
  import { usePollViewToggle, useSidepaneToggle } from '../../AppData/useSidepane';
52
57
  // @ts-ignore: No implicit Any
53
- import { useShowPolls } from '../../AppData/useUISettings';
58
+ import { useSetIsCaptionEnabled, useShowPolls } from '../../AppData/useUISettings';
54
59
  // @ts-ignore: No implicit any
55
60
  import { useDropdownList } from '../../hooks/useDropdownList';
56
61
  import { useMyMetadata } from '../../hooks/useMetadata';
@@ -104,7 +109,10 @@ export const MwebOptions = ({
104
109
  const toggleVB = useSidepaneToggle(SIDE_PANE_OPTIONS.VB);
105
110
  const isLocalVideoEnabled = useHMSStore(selectIsLocalVideoEnabled);
106
111
  const { startRecording, isRecordingLoading } = useRecordingHandler();
112
+ const isTranscriptionAllowed = useHMSStore(selectIsTranscriptionAllowedByMode(HMSTranscriptionMode.CAPTION));
113
+ const isTranscriptionEnabled = useHMSStore(selectIsTranscriptionEnabled);
107
114
 
115
+ const [isCaptionEnabled] = useSetIsCaptionEnabled();
108
116
  useDropdownList({ open: openModals.size > 0 || openOptionsSheet || openSettingsSheet, name: 'MoreSettings' });
109
117
 
110
118
  const updateState = (modalName: string, value: boolean) => {
@@ -189,6 +197,17 @@ export const MwebOptions = ({
189
197
  <ActionTile.Title>{isHandRaised ? 'Lower' : 'Raise'} Hand</ActionTile.Title>
190
198
  </ActionTile.Root>
191
199
  ) : null}
200
+ {isTranscriptionAllowed ? (
201
+ <ActionTile.Root
202
+ onClick={() => {
203
+ setOpenOptionsSheet(false);
204
+ updateState(MODALS.CAPTION, true);
205
+ }}
206
+ >
207
+ {isTranscriptionEnabled && isCaptionEnabled ? <ClosedCaptionIcon /> : <OpenCaptionIcon />}
208
+ <ActionTile.Title>Closed Caption</ActionTile.Title>
209
+ </ActionTile.Root>
210
+ ) : null}
192
211
  {isLocalVideoEnabled && !!elements?.virtual_background ? (
193
212
  <ActionTile.Root
194
213
  onClick={() => {
@@ -1,9 +1,11 @@
1
1
  /* eslint-disable no-case-declarations */
2
2
  import React, { useCallback, useEffect } from 'react';
3
+ import { match } from 'ts-pattern';
3
4
  import {
4
5
  HMSNotificationTypes,
5
6
  HMSRoleChangeRequest,
6
7
  HMSRoomState,
8
+ HMSTranscriptionState,
7
9
  selectIsLocalScreenShared,
8
10
  selectLocalPeerID,
9
11
  selectPeerNameByID,
@@ -14,7 +16,7 @@ import {
14
16
  useHMSStore,
15
17
  useHMSVanillaStore,
16
18
  } from '@100mslive/react-sdk';
17
- import { GroupIcon } from '@100mslive/react-icons';
19
+ import { AlertTriangleIcon, ClosedCaptionIcon, GroupIcon, OpenCaptionIcon } from '@100mslive/react-icons';
18
20
  import { Box, Button } from '../../..';
19
21
  import { useRoomLayout, useUpdateRoomLayout } from '../../provider/roomLayoutProvider';
20
22
  // @ts-ignore: No implicit Any
@@ -33,8 +35,8 @@ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvid
33
35
  // @ts-ignore: No implicit Any
34
36
  import { usePollViewToggle } from '../AppData/useSidepane';
35
37
  // @ts-ignore: No implicit Any
36
- import { useIsNotificationDisabled, useSubscribedNotifications } from '../AppData/useUISettings';
37
- import { ROLE_CHANGE_DECLINED } from '../../common/constants';
38
+ import { useIsNotificationDisabled, useSetAppDataByKey, useSubscribedNotifications } from '../AppData/useUISettings';
39
+ import { CAPTION_TOAST, ROLE_CHANGE_DECLINED } from '../../common/constants';
38
40
 
39
41
  const pollToastKey: Record<string, string> = {};
40
42
 
@@ -51,6 +53,7 @@ export function Notifications() {
51
53
  const { showNotification } = useAwayNotifications();
52
54
  const amIScreenSharing = useHMSStore(selectIsLocalScreenShared);
53
55
  const logoURL = useRoomLayout()?.logo?.url;
56
+ const [toastId, setToastId] = useSetAppDataByKey(CAPTION_TOAST.captionToast);
54
57
 
55
58
  const handleRoleChangeDenied = useCallback((request: HMSRoleChangeRequest & { peerName: string }) => {
56
59
  ToastManager.addToast({
@@ -178,6 +181,44 @@ export function Notifications() {
178
181
  });
179
182
  }
180
183
  break;
184
+ case HMSNotificationTypes.TRANSCRIPTION_STATE_UPDATED:
185
+ const transcriptionStates = notification.data;
186
+ if (transcriptionStates && transcriptionStates.length > 0) {
187
+ let id = '';
188
+ match({ state: transcriptionStates[0].state, error: transcriptionStates[0].error })
189
+ .when(
190
+ ({ error }) => !!error,
191
+ () => {
192
+ ToastManager.removeToast(toastId);
193
+ id = ToastManager.addToast({
194
+ title: `Failed to enable Closed Caption`,
195
+ variant: 'error',
196
+ icon: <AlertTriangleIcon style={{ marginRight: '0.5rem' }} />,
197
+ });
198
+ },
199
+ )
200
+ .with({ state: HMSTranscriptionState.STARTED }, () => {
201
+ ToastManager.removeToast(toastId);
202
+ id = ToastManager.addToast({
203
+ title: `Closed Captioning enabled for everyone`,
204
+ variant: 'standard',
205
+ duration: 2000,
206
+ icon: <OpenCaptionIcon style={{ marginRight: '0.5rem' }} />,
207
+ });
208
+ })
209
+ .with({ state: HMSTranscriptionState.STOPPED }, () => {
210
+ ToastManager.removeToast(toastId);
211
+ id = ToastManager.addToast({
212
+ title: `Closed Captioning disabled for everyone`,
213
+ variant: 'standard',
214
+ duration: 2000,
215
+ icon: <ClosedCaptionIcon style={{ marginRight: '0.5rem' }} />,
216
+ });
217
+ })
218
+ .otherwise(() => null);
219
+ setToastId(id);
220
+ }
221
+ break;
181
222
  default:
182
223
  break;
183
224
  }
@@ -1,19 +1,15 @@
1
1
  import React, { useEffect, useMemo, useState } from 'react';
2
2
  import { GridVideoTileLayout } from '@100mslive/types-prebuilt/elements/video_tile_layout';
3
3
  import {
4
- HMSTranscriptionInfo,
5
4
  selectLocalPeerID,
6
5
  selectLocalPeerRoleName,
7
6
  selectPeers,
8
7
  selectPeerScreenSharing,
9
- selectTranscriptionsState,
10
8
  selectWhiteboard,
11
9
  useHMSStore,
12
10
  useHMSVanillaStore,
13
11
  } from '@100mslive/react-sdk';
14
- import { AlertTriangleIcon } from '@100mslive/react-icons';
15
12
  // @ts-ignore: No implicit Any
16
- import { ToastManager } from '../Toast/ToastManager';
17
13
  import { EqualProminence } from './EqualProminence';
18
14
  import { RoleProminence } from './RoleProminence';
19
15
  import { ScreenshareLayout } from './ScreenshareLayout';
@@ -99,18 +95,6 @@ export const GridLayout = ({
99
95
  objectFit: video_object_fit,
100
96
  };
101
97
 
102
- const transcriptionStates: HMSTranscriptionInfo[] | undefined = useHMSStore(selectTranscriptionsState);
103
-
104
- useEffect(() => {
105
- if (transcriptionStates && transcriptionStates.length > 0 && transcriptionStates[0].error) {
106
- ToastManager.addToast({
107
- title: `Failed to enable Closed Caption`,
108
- variant: 'error',
109
- icon: <AlertTriangleIcon style={{ marginRight: '0.5rem' }} />,
110
- });
111
- }
112
- }, [transcriptionStates]);
113
-
114
98
  useEffect(() => {
115
99
  if (mainPage !== 0) {
116
100
  return;
@@ -1,6 +1,12 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { useMedia } from 'react-use';
3
- import { HMSTranscript, selectPeerNameByID, useHMSStore, useTranscript } from '@100mslive/react-sdk';
3
+ import {
4
+ HMSTranscript,
5
+ selectIsTranscriptionEnabled,
6
+ selectPeerNameByID,
7
+ useHMSStore,
8
+ useTranscript,
9
+ } from '@100mslive/react-sdk';
4
10
  import { Box, Flex } from '../../Layout';
5
11
  import { Text } from '../../Text';
6
12
  import { config } from '../../Theme';
@@ -170,6 +176,8 @@ export const CaptionsViewer = () => {
170
176
 
171
177
  const isCaptionEnabled = useIsCaptionEnabled();
172
178
 
179
+ const isTranscriptionEnabled = useHMSStore(selectIsTranscriptionEnabled);
180
+
173
181
  useEffect(() => {
174
182
  const timeInterval = setInterval(() => {
175
183
  if (!captionQueue) {
@@ -193,7 +201,7 @@ export const CaptionsViewer = () => {
193
201
  }
194
202
  return false;
195
203
  });
196
- if (dataToShow.length <= 0 || screenType === 'hls_live_streaming' || !isCaptionEnabled) {
204
+ if (dataToShow.length <= 0 || screenType === 'hls_live_streaming' || !isCaptionEnabled || !isTranscriptionEnabled) {
197
205
  return null;
198
206
  }
199
207
  return (