@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.
Files changed (40) hide show
  1. package/dist/{HLSView-CTZXD762.js → HLSView-XZDT3RRC.js} +2 -2
  2. package/dist/Prebuilt/common/constants.d.ts +2 -0
  3. package/dist/Prebuilt/common/hooks.d.ts +10 -0
  4. package/dist/Prebuilt/components/CaptionIcon.d.ts +2 -0
  5. package/dist/Prebuilt/components/FullPageProgress.d.ts +8 -0
  6. package/dist/Prebuilt/components/VirtualBackground/VBHandler.d.ts +3 -3
  7. package/dist/Prebuilt/plugins/CaptionsViewer.d.ts +2 -0
  8. package/dist/Text/Text.d.ts +1 -1
  9. package/dist/{chunk-NDLMRKFR.js → chunk-SQPIZNW2.js} +2367 -2128
  10. package/dist/chunk-SQPIZNW2.js.map +7 -0
  11. package/dist/index.cjs.js +3254 -2998
  12. package/dist/index.cjs.js.map +4 -4
  13. package/dist/index.js +1 -1
  14. package/dist/meta.cjs.json +244 -86
  15. package/dist/meta.esbuild.json +250 -92
  16. package/package.json +6 -6
  17. package/src/Prebuilt/common/constants.ts +2 -0
  18. package/src/Prebuilt/common/hooks.ts +72 -1
  19. package/src/Prebuilt/components/AppData/AppData.tsx +2 -0
  20. package/src/Prebuilt/components/AppData/useUISettings.js +10 -0
  21. package/src/Prebuilt/components/CaptionIcon.tsx +27 -0
  22. package/src/Prebuilt/components/ConferenceScreen.tsx +34 -4
  23. package/src/Prebuilt/components/Footer/Footer.tsx +2 -0
  24. package/src/Prebuilt/components/Footer/RoleAccordion.tsx +1 -1
  25. package/src/Prebuilt/components/{FullPageProgress.jsx → FullPageProgress.tsx} +10 -1
  26. package/src/Prebuilt/components/Header/StreamActions.tsx +3 -25
  27. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +25 -26
  28. package/src/Prebuilt/components/Notifications/PeerNotifications.tsx +1 -11
  29. package/src/Prebuilt/components/Preview/PreviewJoin.tsx +4 -9
  30. package/src/Prebuilt/components/Preview/PreviewScreen.tsx +0 -3
  31. package/src/Prebuilt/components/Settings/StartRecording.jsx +4 -37
  32. package/src/Prebuilt/components/Toast/ToastConfig.jsx +0 -22
  33. package/src/Prebuilt/components/VirtualBackground/VBHandler.tsx +3 -3
  34. package/src/Prebuilt/components/VirtualBackground/VBOption.tsx +3 -1
  35. package/src/Prebuilt/components/VirtualBackground/VBPicker.tsx +23 -7
  36. package/src/Prebuilt/components/VirtualBackground/VBToggle.tsx +5 -3
  37. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +0 -3
  38. package/src/Prebuilt/plugins/CaptionsViewer.tsx +191 -0
  39. package/dist/chunk-NDLMRKFR.js.map +0 -7
  40. /package/dist/{HLSView-CTZXD762.js.map → HLSView-XZDT3RRC.js.map} +0 -0
@@ -72,28 +72,6 @@ const HandRaiseAction = React.forwardRef(({ id = '', isSingleHandRaise = true },
72
72
  });
73
73
 
74
74
  export const ToastConfig = {
75
- PEER_LIST: {
76
- single: function (notification) {
77
- if (notification.data.length === 1) {
78
- return {
79
- title: `${notification.data[0]?.name} joined`,
80
- icon: <PeopleAddIcon />,
81
- };
82
- }
83
- return {
84
- title: `${notification.data[notification.data.length - 1]?.name} and ${
85
- notification.data.length - 1
86
- } others joined`,
87
- icon: <PeopleAddIcon />,
88
- };
89
- },
90
- multiple: notifications => {
91
- return {
92
- title: `${notifications[0].data.name} and ${notifications.length - 1} others joined`,
93
- icon: <PeopleAddIcon />,
94
- };
95
- },
96
- },
97
75
  PEER_JOINED: {
98
76
  single: function (notification) {
99
77
  return {
@@ -4,12 +4,12 @@ export class VBPlugin {
4
4
  private hmsPlugin?: HMSVBPlugin;
5
5
  private effectsPlugin?: HMSEffectsPlugin | undefined;
6
6
 
7
- initialisePlugin = (effectsSDKKey?: string) => {
7
+ initialisePlugin = (effectsSDKKey?: string, onInit?: () => void) => {
8
8
  if (this.getVBObject()) {
9
9
  return;
10
10
  }
11
11
  if (effectsSDKKey) {
12
- this.effectsPlugin = new HMSEffectsPlugin(effectsSDKKey);
12
+ this.effectsPlugin = new HMSEffectsPlugin(effectsSDKKey, onInit);
13
13
  } else {
14
14
  this.hmsPlugin = new HMSVBPlugin(HMSVirtualBackgroundTypes.NONE, HMSVirtualBackgroundTypes.NONE);
15
15
  }
@@ -70,7 +70,7 @@ export class VBPlugin {
70
70
  }
71
71
  };
72
72
 
73
- setPreset = async (preset: string) => {
73
+ setPreset = async (preset: 'quality' | 'balanced') => {
74
74
  if (this.effectsPlugin) {
75
75
  await this.effectsPlugin.setPreset(preset);
76
76
  }
@@ -28,7 +28,9 @@ const Root = ({
28
28
  '&:hover': { border: '4px solid $primary_dim' },
29
29
  ...(mediaURL ? { height: '$20', backgroundImage: `url(${mediaURL})`, backgroundSize: 'cover' } : {}),
30
30
  }}
31
- onClick={async () => await onClick?.()}
31
+ onClick={async () => {
32
+ await onClick?.();
33
+ }}
32
34
  >
33
35
  {children}
34
36
  </Flex>
@@ -1,4 +1,5 @@
1
1
  import React, { useEffect, useState } from 'react';
2
+ import { useMedia } from 'react-use';
2
3
  import {
3
4
  selectAppData,
4
5
  selectEffectsKey,
@@ -19,14 +20,14 @@ import {
19
20
  useHMSStore,
20
21
  } from '@100mslive/react-sdk';
21
22
  import { BlurPersonHighIcon, CrossCircleIcon, CrossIcon } from '@100mslive/react-icons';
22
- import { Box, Flex, Slider, Video } from '../../../index';
23
+ import { Box, config as cssConfig, Flex, Loading, Slider, Video } from '../../../index';
23
24
  import { Text } from '../../../Text';
24
25
  import { VBCollection } from './VBCollection';
25
26
  import { VBHandler } from './VBHandler';
26
27
  // @ts-ignore
27
28
  import { useSidepaneToggle } from '../AppData/useSidepane';
28
29
  // @ts-ignore
29
- import { useUISettings } from '../AppData/useUISettings';
30
+ import { useSetAppDataByKey, useUISettings } from '../AppData/useUISettings';
30
31
  import { APP_DATA, SIDE_PANE_OPTIONS, UI_SETTINGS } from '../../common/constants';
31
32
  import { defaultMedia } from './constants';
32
33
 
@@ -46,6 +47,8 @@ export const VBPicker = ({ backgroundMedia = [] }: { backgroundMedia: VirtualBac
46
47
  const isLargeRoom = useHMSStore(selectIsLargeRoom);
47
48
  const isEffectsEnabled = useHMSStore(selectIsEffectsEnabled);
48
49
  const effectsKey = useHMSStore(selectEffectsKey);
50
+ const isMobile = useMedia(cssConfig.media.md);
51
+ const [loadingEffects, setLoadingEffects] = useSetAppDataByKey(APP_DATA.loadingEffects);
49
52
  const isPluginAdded = useHMSStore(selectIsLocalVideoPluginPresent(VBHandler?.getName() || ''));
50
53
  const background = useHMSStore(selectAppData(APP_DATA.background));
51
54
  const mediaList = backgroundMedia.length
@@ -61,13 +64,15 @@ export const VBPicker = ({ backgroundMedia = [] }: { backgroundMedia: VirtualBac
61
64
  return;
62
65
  }
63
66
  if (!isPluginAdded) {
67
+ setLoadingEffects(true);
64
68
  let vbObject = VBHandler.getVBObject();
65
69
  if (!vbObject) {
66
- VBHandler.initialisePlugin(isEffectsEnabled && effectsKey ? effectsKey : '');
70
+ VBHandler.initialisePlugin(isEffectsEnabled && effectsKey ? effectsKey : '', () => setLoadingEffects(false));
67
71
  vbObject = VBHandler.getVBObject();
68
72
  if (isEffectsEnabled && effectsKey) {
69
73
  hmsActions.addPluginsToVideoStream([vbObject as HMSEffectsPlugin]);
70
74
  } else {
75
+ setLoadingEffects(false);
71
76
  if (!role) {
72
77
  return;
73
78
  }
@@ -89,19 +94,30 @@ export const VBPicker = ({ backgroundMedia = [] }: { backgroundMedia: VirtualBac
89
94
  };
90
95
  handleDefaultBackground();
91
96
  }
92
- }, [hmsActions, role, isPluginAdded, isEffectsEnabled, effectsKey, track?.id, background, blurAmount]);
97
+ }, [
98
+ hmsActions,
99
+ role,
100
+ isPluginAdded,
101
+ isEffectsEnabled,
102
+ effectsKey,
103
+ track?.id,
104
+ background,
105
+ blurAmount,
106
+ setLoadingEffects,
107
+ ]);
93
108
 
94
109
  useEffect(() => {
95
110
  if (!isVideoOn) {
96
111
  toggleVB();
97
112
  }
98
- }, [isVideoOn, toggleVB]);
113
+ return () => setLoadingEffects(false);
114
+ }, [isVideoOn, setLoadingEffects, toggleVB]);
99
115
 
100
116
  return (
101
117
  <Flex css={{ pr: '$6', size: '100%' }} direction="column">
102
118
  <Flex align="center" justify="between" css={{ w: '100%', background: '$surface_dim', pb: '$4' }}>
103
- <Text variant="h6" css={{ color: '$on_surface_high' }}>
104
- Virtual Background
119
+ <Text variant="h6" css={{ color: '$on_surface_high', display: 'flex', alignItems: 'center' }}>
120
+ Virtual Background {isMobile && loadingEffects ? <Loading size={18} style={{ marginLeft: '0.5rem' }} /> : ''}
105
121
  </Text>
106
122
  <Box
107
123
  css={{ color: '$on_surface_high', '&:hover': { color: '$on_surface_medium' }, cursor: 'pointer' }}
@@ -1,17 +1,19 @@
1
1
  import React from 'react';
2
- import { selectIsEffectsEnabled, selectIsLocalVideoEnabled, useHMSStore } from '@100mslive/react-sdk';
2
+ import { selectAppData, selectIsEffectsEnabled, selectIsLocalVideoEnabled, useHMSStore } from '@100mslive/react-sdk';
3
3
  import { VirtualBackgroundIcon } from '@100mslive/react-icons';
4
+ import { Loading } from '../../../Loading';
4
5
  import { Tooltip } from '../../../Tooltip';
5
6
  import IconButton from '../../IconButton';
6
7
  // @ts-ignore
7
8
  import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane';
8
- import { isSafari, SIDE_PANE_OPTIONS } from '../../common/constants';
9
+ import { APP_DATA, isSafari, SIDE_PANE_OPTIONS } from '../../common/constants';
9
10
 
10
11
  export const VBToggle = () => {
11
12
  const toggleVB = useSidepaneToggle(SIDE_PANE_OPTIONS.VB);
12
13
  const isVBOpen = useIsSidepaneTypeOpen(SIDE_PANE_OPTIONS.VB);
13
14
  const isVideoOn = useHMSStore(selectIsLocalVideoEnabled);
14
15
  const isEffectsEnabled = useHMSStore(selectIsEffectsEnabled);
16
+ const loadingEffects = useHMSStore(selectAppData(APP_DATA.loadingEffects));
15
17
 
16
18
  if (!isVideoOn || (!isEffectsEnabled && isSafari)) {
17
19
  return null;
@@ -20,7 +22,7 @@ export const VBToggle = () => {
20
22
  return (
21
23
  <Tooltip side="top" disabled={isVBOpen} title="Configure Virtual Background">
22
24
  <IconButton active={!isVBOpen} onClick={toggleVB} data-testid="virtual_bg_btn">
23
- <VirtualBackgroundIcon />
25
+ {loadingEffects ? <Loading size={18} /> : <VirtualBackgroundIcon />}
24
26
  </IconButton>
25
27
  </Tooltip>
26
28
  );
@@ -6,7 +6,6 @@ import {
6
6
  } from '@100mslive/types-prebuilt';
7
7
  import { match } from 'ts-pattern';
8
8
  import { selectIsConnectedToRoom, selectLocalPeerRoleName, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
9
- // @ts-ignore: No implicit Any
10
9
  import FullPageProgress from '../components/FullPageProgress';
11
10
  import { GridLayout } from '../components/VideoLayouts/GridLayout';
12
11
  import { Box, Flex } from '../../Layout';
@@ -25,7 +24,6 @@ import {
25
24
  } from '../components/AppData/useUISettings';
26
25
  import { useCloseScreenshareWhiteboard } from '../components/hooks/useCloseScreenshareWhiteboard';
27
26
  import { useLandscapeHLSStream, useMobileHLSStream } from '../common/hooks';
28
- // @ts-ignore: No implicit Any
29
27
  import { SESSION_STORE_KEY } from '../common/constants';
30
28
 
31
29
  // @ts-ignore: No implicit Any
@@ -107,7 +105,6 @@ export const VideoStreamingSection = ({
107
105
  // @ts-ignore
108
106
  return <GridLayout {...(elements as DefaultConferencingScreen_Elements)?.video_tile_layout?.grid} />;
109
107
  })}
110
-
111
108
  <Box
112
109
  css={{
113
110
  flex: match({ isLandscapeHLSStream, isMobileHLSStream })
@@ -0,0 +1,191 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { HMSTranscript, selectPeerNameByID, useHMSStore, useTranscript } from '@100mslive/react-sdk';
3
+ import { Flex } from '../../Layout';
4
+ import { Text } from '../../Text';
5
+
6
+ interface CaptionQueueData extends HMSTranscript {
7
+ transcriptQueue: SimpleQueue;
8
+ }
9
+
10
+ interface TranscriptData extends HMSTranscript {
11
+ timeout?: NodeJS.Timeout | undefined;
12
+ }
13
+ class SimpleQueue {
14
+ private storage: TranscriptData[] = [];
15
+ constructor(private capacity: number = 3, private MAX_STORAGE_TIME: number = 5000) {}
16
+ enqueue(data: TranscriptData): void {
17
+ if (this.size() === this.capacity && this.storage[this.size() - 1].final) {
18
+ this.dequeue(this.storage[this.size() - 1]);
19
+ }
20
+ if (this.size() === 0) {
21
+ this.storage.push(data);
22
+ this.addTimeout(this.storage[this.size() - 1], data.final);
23
+ return;
24
+ }
25
+ if (this.size() > 0 && this.storage[this.size() - 1]?.final === true) {
26
+ this.storage.push(data);
27
+ this.addTimeout(this.storage[this.size() - 1], data.final);
28
+ return;
29
+ }
30
+ this.storage[this.size() - 1].transcript = data.transcript;
31
+ this.storage[this.size() - 1].final = data.final;
32
+ this.storage[this.size() - 1].end = data.end;
33
+ this.addTimeout(this.storage[this.size() - 1], data.final);
34
+ }
35
+ addTimeout(item: TranscriptData, isFinal: boolean) {
36
+ if (!isFinal) {
37
+ return;
38
+ }
39
+ item.timeout = setTimeout(() => {
40
+ this.dequeue(item);
41
+ }, this.MAX_STORAGE_TIME);
42
+ }
43
+ dequeue(item: TranscriptData): TranscriptData | undefined {
44
+ const index = this.storage.indexOf(item);
45
+ if (index === -1) {
46
+ return undefined;
47
+ }
48
+ const removedItem = this.storage.splice(index, 1);
49
+ if (removedItem.length <= 0) {
50
+ return undefined;
51
+ }
52
+ this.clearTimeout(removedItem[0]);
53
+ return item;
54
+ }
55
+ clearTimeout(item: TranscriptData) {
56
+ if (!item.timeout) {
57
+ return;
58
+ }
59
+ clearTimeout(item.timeout);
60
+ }
61
+ peek(): TranscriptData | undefined {
62
+ if (this.size() <= 0) {
63
+ return undefined;
64
+ }
65
+ return this.storage[0];
66
+ }
67
+ getTranscription(): string {
68
+ let script = '';
69
+ this.storage.forEach((value: TranscriptData) => (script += value.transcript + ' '));
70
+ return script;
71
+ }
72
+ reset() {
73
+ this.storage.length = 0;
74
+ }
75
+ size(): number {
76
+ return this.storage.length;
77
+ }
78
+ }
79
+ class Queue {
80
+ private storage: Record<string, CaptionQueueData> = {};
81
+ constructor(private capacity: number = 3) {}
82
+
83
+ enqueue(data: HMSTranscript): void {
84
+ if (this.size() === this.capacity) {
85
+ this.dequeue();
86
+ }
87
+ if (!this.storage[data.peer_id]) {
88
+ this.storage[data.peer_id] = {
89
+ peer_id: data.peer_id,
90
+ transcript: data.transcript,
91
+ final: data.final,
92
+ transcriptQueue: new SimpleQueue(),
93
+ start: data.start,
94
+ end: data.end,
95
+ };
96
+ this.storage[data.peer_id].transcriptQueue.enqueue(data as TranscriptData);
97
+ return;
98
+ }
99
+ this.storage[data.peer_id].transcriptQueue.enqueue(data as TranscriptData);
100
+ }
101
+ dequeue(): CaptionQueueData {
102
+ const key: string = Object.keys(this.storage).shift() || '';
103
+ const captionData = this.storage[key];
104
+ captionData.transcriptQueue.reset();
105
+ delete this.storage[key];
106
+ return captionData;
107
+ }
108
+
109
+ peek(): CaptionQueueData | undefined {
110
+ if (this.size() <= 0) return undefined;
111
+ const key: string = Object.keys(this.storage).shift() || '';
112
+ return this.storage[key];
113
+ }
114
+
115
+ findPeerData(): { [key: string]: string }[] {
116
+ const keys = Object.keys(this.storage);
117
+ const data = keys.map((key: string) => {
118
+ const data = this.storage[key];
119
+ const word = data.transcriptQueue.getTranscription();
120
+ return { [key]: word };
121
+ });
122
+ return data;
123
+ }
124
+ size(): number {
125
+ return Object.keys(this.storage).length;
126
+ }
127
+ }
128
+
129
+ class CaptionMaintainerQueue {
130
+ captionData: Queue = new Queue();
131
+ push(data: HMSTranscript[] = []) {
132
+ data.forEach((value: HMSTranscript) => {
133
+ this.captionData.enqueue(value);
134
+ });
135
+ }
136
+ }
137
+ const TranscriptView = ({ peer_id, data }: { peer_id: string; data: string }) => {
138
+ const peerName = useHMSStore(selectPeerNameByID(peer_id));
139
+ data = data.trim();
140
+ if (!data) return null;
141
+ return (
142
+ <Text
143
+ variant="body2"
144
+ css={{
145
+ fontWeight: '$normal',
146
+ }}
147
+ >
148
+ {`${peerName}: ${data}`}
149
+ </Text>
150
+ );
151
+ };
152
+
153
+ export const CaptionsViewer = () => {
154
+ const [captionQueue] = useState<CaptionMaintainerQueue>(new CaptionMaintainerQueue());
155
+ const [currentData, setCurrentData] = useState<{ [key: string]: string }[]>([]);
156
+
157
+ useEffect(() => {
158
+ const timeInterval = setInterval(() => {
159
+ if (!captionQueue) {
160
+ return;
161
+ }
162
+ const data = captionQueue.captionData?.findPeerData();
163
+ setCurrentData(data);
164
+ }, 1000);
165
+ return () => clearInterval(timeInterval);
166
+ }, [captionQueue]);
167
+
168
+ useTranscript({
169
+ onTranscript: (data: HMSTranscript[]) => {
170
+ captionQueue && captionQueue.push(data as HMSTranscript[]);
171
+ },
172
+ });
173
+ const dataToShow = currentData.filter((data: { [key: string]: string }) => {
174
+ const key = Object.keys(data)[0];
175
+ if (data[key]) {
176
+ return true;
177
+ }
178
+ return false;
179
+ });
180
+ if (dataToShow.length <= 0) {
181
+ return null;
182
+ }
183
+ return (
184
+ <Flex direction="column" gap={1}>
185
+ {dataToShow.map((data: { [key: string]: string }, index: number) => {
186
+ const key = Object.keys(data)[0];
187
+ return <TranscriptView key={index} peer_id={key} data={data[key]} />;
188
+ })}
189
+ </Flex>
190
+ );
191
+ };