@100mslive/roomkit-react 0.3.8-alpha.0 → 0.3.8-alpha.2

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.
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
+ };