@100mslive/roomkit-react 0.3.20 → 0.3.21-alpha.0

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-E242LM6X.css → HLSView-OGAGRBO5.css} +3 -3
  2. package/dist/{HLSView-E242LM6X.css.map → HLSView-OGAGRBO5.css.map} +1 -1
  3. package/dist/{HLSView-6QAHWMQF.js → HLSView-ZKLIDQML.js} +63 -47
  4. package/dist/HLSView-ZKLIDQML.js.map +7 -0
  5. package/dist/Prebuilt/AppContext.d.ts +1 -1
  6. package/dist/Prebuilt/components/AuthToken.d.ts +1 -1
  7. package/dist/Prebuilt/components/VirtualBackground/VBHandler.d.ts +1 -0
  8. package/dist/Prebuilt/components/peerTileUtils.d.ts +7 -0
  9. package/dist/{chunk-ACEDLM3B.js → chunk-3TFNJ7FA.js} +541 -510
  10. package/dist/chunk-3TFNJ7FA.js.map +7 -0
  11. package/dist/index.cjs.css +2 -2
  12. package/dist/index.cjs.css.map +1 -1
  13. package/dist/index.cjs.js +608 -561
  14. package/dist/index.cjs.js.map +4 -4
  15. package/dist/index.css +2 -2
  16. package/dist/index.css.map +1 -1
  17. package/dist/index.js +1 -1
  18. package/dist/meta.cjs.json +89 -69
  19. package/dist/meta.esbuild.json +101 -81
  20. package/package.json +7 -7
  21. package/src/Prebuilt/App.tsx +5 -5
  22. package/src/Prebuilt/AppContext.tsx +1 -1
  23. package/src/Prebuilt/components/AuthToken.tsx +1 -1
  24. package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +24 -4
  25. package/src/Prebuilt/components/Header/common.jsx +5 -3
  26. package/src/Prebuilt/components/MoreSettings/ChangeNameContent.tsx +13 -3
  27. package/src/Prebuilt/components/MoreSettings/ChangeNameModal.tsx +1 -1
  28. package/src/Prebuilt/components/Notifications/TrackUnmuteModal.tsx +1 -1
  29. package/src/Prebuilt/components/ScreenshareTile.tsx +2 -2
  30. package/src/Prebuilt/components/Settings/SettingsModal.jsx +1 -2
  31. package/src/Prebuilt/components/TileMenu/TileMenu.tsx +7 -6
  32. package/src/Prebuilt/components/TileMenu/TileMenuContent.tsx +3 -3
  33. package/src/Prebuilt/components/VideoLayouts/EqualProminence.tsx +4 -2
  34. package/src/Prebuilt/components/VideoTile.tsx +2 -2
  35. package/src/Prebuilt/components/VirtualBackground/VBHandler.tsx +13 -1
  36. package/src/Prebuilt/components/VirtualBackground/VBPicker.tsx +3 -2
  37. package/src/Prebuilt/components/{peerTileUtils.jsx → peerTileUtils.tsx} +21 -6
  38. package/src/Prebuilt/layouts/HLSView.jsx +2 -5
  39. package/dist/HLSView-6QAHWMQF.js.map +0 -7
  40. package/dist/chunk-ACEDLM3B.js.map +0 -7
@@ -1,7 +1,28 @@
1
- import React, { forwardRef } from 'react';
1
+ import React, { forwardRef, useEffect, useState } from 'react';
2
2
  import { Flex } from '../../../Layout';
3
3
 
4
4
  export const HMSVideo = forwardRef(({ children, ...props }, videoRef) => {
5
+ const [width, setWidth] = useState('auto');
6
+
7
+ useEffect(() => {
8
+ const updatingVideoWidth = () => {
9
+ const videoEl = videoRef.current;
10
+ if (!videoEl) {
11
+ return;
12
+ }
13
+ if (videoEl.videoWidth > videoEl.videoHeight && width !== '100%') {
14
+ setWidth('100%');
15
+ }
16
+ };
17
+ const videoEl = videoRef.current;
18
+ if (!videoEl) {
19
+ return;
20
+ }
21
+ videoEl.addEventListener('loadedmetadata', updatingVideoWidth);
22
+ return () => {
23
+ videoEl.removeEventListener('loadedmetadata', updatingVideoWidth);
24
+ };
25
+ }, []);
5
26
  return (
6
27
  <Flex
7
28
  data-testid="hms-video"
@@ -11,9 +32,8 @@ export const HMSVideo = forwardRef(({ children, ...props }, videoRef) => {
11
32
  justifyContent: 'center',
12
33
  transition: 'all 0.3s ease-in-out',
13
34
  '@md': {
14
- height: 'auto',
15
35
  '& video': {
16
- height: '$60 !important',
36
+ height: props.isFullScreen ? '' : '$60 !important',
17
37
  },
18
38
  },
19
39
  '& video::cue': {
@@ -41,7 +61,7 @@ export const HMSVideo = forwardRef(({ children, ...props }, videoRef) => {
41
61
  style={{
42
62
  margin: '0 auto',
43
63
  objectFit: 'contain',
44
- width: 'auto',
64
+ width: width,
45
65
  height: '100%',
46
66
  maxWidth: '100%',
47
67
  }}
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import {
3
3
  DeviceType,
4
+ getAudioDeviceCategory,
4
5
  selectIsLocalVideoEnabled,
5
6
  selectLocalVideoTrackID,
6
7
  selectVideoTrackByID,
@@ -78,12 +79,13 @@ export const AudioActions = () => {
78
79
  if (!audioFiltered) {
79
80
  return null;
80
81
  }
82
+ const deviceCategory = getAudioDeviceCategory(currentSelection.label);
81
83
  let AudioIcon = <SpeakerIcon />;
82
- if (currentSelection && currentSelection.label.toLowerCase().includes('bluetooth')) {
84
+ if (deviceCategory === 'bluetooth') {
83
85
  AudioIcon = <BluetoothIcon />;
84
- } else if (currentSelection && currentSelection.label.toLowerCase().includes('wired')) {
86
+ } else if (deviceCategory === 'wired') {
85
87
  AudioIcon = <HeadphonesIcon />;
86
- } else if (currentSelection && currentSelection.label.toLowerCase().includes('earpiece')) {
88
+ } else if (deviceCategory === 'earpiece') {
87
89
  AudioIcon = <TelePhoneIcon />;
88
90
  }
89
91
  return (
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef } from 'react';
2
2
  import { ChevronLeftIcon, CrossIcon } from '@100mslive/react-icons';
3
3
  import { Button } from '../../../Button';
4
4
  import { Input } from '../../../Input';
@@ -22,6 +22,16 @@ export const ChangeNameContent = ({
22
22
  onExit: () => void;
23
23
  onBackClick: () => void;
24
24
  }) => {
25
+ const inputRef = useRef<HTMLInputElement>(null);
26
+
27
+ useEffect(() => {
28
+ if (isMobile) {
29
+ setTimeout(() => {
30
+ inputRef.current?.focus();
31
+ }, 200);
32
+ }
33
+ }, [isMobile]);
34
+
25
35
  return (
26
36
  <form
27
37
  onSubmit={async e => {
@@ -53,10 +63,10 @@ export const ChangeNameContent = ({
53
63
  </Text>
54
64
  <Flex justify="center" align="center" css={{ my: '$8', w: '100%', '@md': { px: '$8' } }}>
55
65
  <Input
66
+ ref={inputRef}
56
67
  css={{ width: '100%', bg: '$surface_default' }}
57
68
  value={currentName}
58
- // Prevents popup from showing up on chrome mweb
59
- type={isMobile ? 'search' : 'text'}
69
+ type="text"
60
70
  onChange={e => {
61
71
  setCurrentName(e.target.value);
62
72
  }}
@@ -58,7 +58,7 @@ export const ChangeNameModal = ({
58
58
  if (isMobile) {
59
59
  return (
60
60
  <Sheet.Root defaultOpen onOpenChange={onOpenChange}>
61
- <Sheet.Content css={{ bg: '$surface_dim', p: '$8 0' }}>
61
+ <Sheet.Content css={{ bg: '$surface_dim', p: '$8 0' }} onOpenAutoFocus={e => e.preventDefault()}>
62
62
  <ChangeNameContent {...props} />
63
63
  </Sheet.Content>
64
64
  </Sheet.Root>
@@ -44,7 +44,7 @@ export const TrackUnmuteModal = () => {
44
44
  <RequestDialog
45
45
  title={`Unmute your ${track.type}?`}
46
46
  onOpenChange={(value: boolean) => !value && setMuteNotification(null)}
47
- body={`${peer?.name}is requesting you to unmute your ${track?.type}.`}
47
+ body={`${peer?.name} is requesting you to unmute your ${track?.type}.`}
48
48
  onAction={() => {
49
49
  hmsActions.setEnabledTrack(track.id, enabled);
50
50
  setMuteNotification(null);
@@ -16,7 +16,6 @@ import { config as cssConfig, useTheme } from '../../Theme';
16
16
  import { Video } from '../../Video';
17
17
  import { StyledVideoTile } from '../../VideoTile';
18
18
  import { LayoutModeSelector } from './LayoutModeSelector';
19
- // @ts-ignore: No implicit Any
20
19
  import { getVideoTileLabel } from './peerTileUtils';
21
20
  import { ScreenshareDisplay } from './ScreenshareDisplay';
22
21
  // @ts-ignore: No implicit Any
@@ -62,7 +61,8 @@ const Tile = ({ peerId, width = '100%', height = '100%' }: { peerId: string; wid
62
61
  const label = getVideoTileLabel({
63
62
  peerName: peer?.name,
64
63
  isLocal: false,
65
- track,
64
+ videoTrack: track,
65
+ audioTrack,
66
66
  });
67
67
 
68
68
  return (
@@ -140,7 +140,6 @@ const MobileSettingModal = ({
140
140
  <Flex
141
141
  direction="column"
142
142
  css={{
143
- px: '$8',
144
143
  pb: '$8',
145
144
  overflowY: 'auto',
146
145
  }}
@@ -159,7 +158,7 @@ const MobileSettingModal = ({
159
158
  css={{
160
159
  all: 'unset',
161
160
  fontFamily: '$sans',
162
- py: '$10',
161
+ p: '$10 $8',
163
162
  display: 'flex',
164
163
  alignItems: 'center',
165
164
  fontSize: '$sm',
@@ -1,6 +1,7 @@
1
1
  import React, { useState } from 'react';
2
2
  import { useMedia } from 'react-use';
3
3
  import {
4
+ HMSAudioTrack,
4
5
  HMSVideoTrack,
5
6
  selectLocalPeerID,
6
7
  selectPeerByID,
@@ -17,6 +18,7 @@ import { Text } from '../../../Text';
17
18
  import { config as cssConfig, useTheme } from '../../../Theme';
18
19
  import { StyledMenuTile } from '../../../TileMenu';
19
20
  import { ChangeNameModal } from '../MoreSettings/ChangeNameModal';
21
+ import { getVideoTileLabel } from '../peerTileUtils';
20
22
  import { RoleChangeModal } from '../RoleChangeModal';
21
23
  import { TileMenuContent } from './TileMenuContent';
22
24
  import { useDropdownList } from '../hooks/useDropdownList';
@@ -52,7 +54,8 @@ const TileMenu = ({
52
54
  const isPrimaryVideoTrack = useHMSStore(selectVideoTrackByPeerID(peerID))?.id === videoTrackID;
53
55
  const showPinAction = !!(audioTrackID || (videoTrackID && isPrimaryVideoTrack));
54
56
 
55
- const track = useHMSStore(selectTrackByID(videoTrackID)) as HMSVideoTrack;
57
+ const track = useHMSStore(selectTrackByID(videoTrackID)) as HMSVideoTrack | null;
58
+ const audioTrack = useHMSStore(selectTrackByID(audioTrackID)) as HMSAudioTrack | null;
56
59
  const hideSimulcastLayers = !track?.layerDefinitions?.length || track.degraded || !track.enabled;
57
60
  const isMobile = useMedia(cssConfig.media.md);
58
61
  const peer = useHMSStore(selectPeerByID(peerID));
@@ -61,20 +64,19 @@ const TileMenu = ({
61
64
  useDropdownList({ open, name: 'TileMenu' });
62
65
  const dragClassName = getDragClassName();
63
66
 
64
- if (!(removeOthers || toggleAudio || toggleVideo || setVolume || showPinAction) && hideSimulcastLayers) {
67
+ if (!peer || (!(removeOthers || toggleAudio || toggleVideo || setVolume || showPinAction) && hideSimulcastLayers)) {
65
68
  return null;
66
69
  }
67
70
 
68
71
  const openNameChangeModal = () => setShowNameChangeModal(true);
69
72
  const openRoleChangeModal = () => setShowRoleChangeModal(true);
70
73
 
71
- const props = {
74
+ const props: React.ComponentPropsWithoutRef<typeof TileMenuContent> = {
72
75
  isLocal,
73
76
  isScreenshare,
74
77
  audioTrackID,
75
78
  videoTrackID,
76
79
  peerID,
77
- isPrimaryVideoTrack,
78
80
  showSpotlight,
79
81
  showPinAction,
80
82
  canMinimise,
@@ -111,8 +113,7 @@ const TileMenu = ({
111
113
  >
112
114
  <Box>
113
115
  <Text css={{ color: '$on_surface_high', fontWeight: '$semiBold' }}>
114
- {peer?.name}
115
- {isLocal ? ` (You)` : null}
116
+ {getVideoTileLabel({ peerName: peer?.name, isLocal, audioTrack, videoTrack: track })}
116
117
  </Text>
117
118
  {peer?.roleName ? (
118
119
  <Text variant="xs" css={{ color: '$on_surface_low', mt: '$2' }}>
@@ -41,7 +41,7 @@ import { useSetAppDataByKey } from '../AppData/useUISettings';
41
41
  // @ts-ignore
42
42
  import { useDropdownSelection } from '../hooks/useDropdownSelection';
43
43
  import { getDragClassName } from './utils';
44
- import { APP_DATA, REMOTE_STOP_SCREENSHARE_TYPE, SESSION_STORE_KEY } from '../../common/constants';
44
+ import { APP_DATA, isIOS, REMOTE_STOP_SCREENSHARE_TYPE, SESSION_STORE_KEY } from '../../common/constants';
45
45
 
46
46
  export const isSameTile = ({
47
47
  trackId,
@@ -317,7 +317,7 @@ export const TileMenuContent = ({
317
317
  </StyledMenuTile.ItemButton>
318
318
  ) : null}
319
319
 
320
- {canChangeRole && roles.length > 1 ? (
320
+ {!isScreenshare && canChangeRole && roles.length > 1 ? (
321
321
  <StyledMenuTile.ItemButton
322
322
  className={dragClassName}
323
323
  css={spacingCSS}
@@ -332,7 +332,7 @@ export const TileMenuContent = ({
332
332
  </StyledMenuTile.ItemButton>
333
333
  ) : null}
334
334
 
335
- {audioTrackID ? (
335
+ {!isIOS && audioTrackID ? (
336
336
  <StyledMenuTile.VolumeItem data-testid="participant_volume_slider" css={{ ...spacingCSS, mb: '$0' }}>
337
337
  <Flex align="center" gap={1}>
338
338
  <SpeakerIcon height={20} width={20} />
@@ -1,5 +1,6 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { useMedia } from 'react-use';
3
+ import { selectPeerCount, useHMSStore } from '@100mslive/react-sdk';
3
4
  import { PeopleAddIcon } from '@100mslive/react-icons';
4
5
  import { Flex } from '../../../Layout';
5
6
  import { config as cssConfig } from '../../../Theme';
@@ -17,6 +18,7 @@ export function EqualProminence({ isInsetEnabled = false, peers, onPageChange, o
17
18
  const isMobile = useMedia(cssConfig.media.md);
18
19
  let maxTileCount = useUISettings(UI_SETTINGS.maxTileCount);
19
20
  maxTileCount = isMobile ? Math.min(maxTileCount, 6) : maxTileCount;
21
+ const peerCount = useHMSStore(selectPeerCount);
20
22
  const pageList = usePagesWithTiles({
21
23
  peers,
22
24
  maxTileCount,
@@ -51,8 +53,8 @@ export function EqualProminence({ isInsetEnabled = false, peers, onPageChange, o
51
53
  )}
52
54
  {pageList.length === 0 ? (
53
55
  <WaitingView
54
- title="You're the first to join"
55
- subtitle="Sit back and relax till others join"
56
+ title={peerCount <= 1 ? "You're the only one here" : 'Glad to have you here'}
57
+ subtitle={peerCount <= 1 ? 'Sit back and relax till others join' : ''}
56
58
  icon={<PeopleAddIcon width="56px" height="56px" style={{ color: 'white' }} />}
57
59
  />
58
60
  ) : null}
@@ -20,7 +20,6 @@ import { VideoTileStats } from '../../Stats';
20
20
  import { CSS } from '../../Theme';
21
21
  import { Video } from '../../Video';
22
22
  import { StyledVideoTile } from '../../VideoTile';
23
- // @ts-ignore: No implicit Any
24
23
  import { getVideoTileLabel } from './peerTileUtils';
25
24
  // @ts-ignore: No implicit Any
26
25
  import { useSetAppDataByKey, useUISettings } from './AppData/useUISettings';
@@ -101,8 +100,9 @@ const Tile = ({
101
100
  });
102
101
  const label = getVideoTileLabel({
103
102
  peerName,
104
- track,
105
103
  isLocal,
104
+ videoTrack: track,
105
+ audioTrack,
106
106
  });
107
107
  const onHoverHandler = useCallback((event: React.MouseEvent) => {
108
108
  setIsMouseHovered(event.type === 'mouseenter');
@@ -2,7 +2,7 @@
2
2
  // eslint-disable-next-line
3
3
  import { HMSVBPlugin, HMSVirtualBackgroundTypes } from '@100mslive/hms-virtual-background/hmsvbplugin';
4
4
  import { parsedUserAgent } from '@100mslive/react-sdk';
5
- import { isSafari } from '../../common/constants';
5
+ import { isIOS, isSafari } from '../../common/constants';
6
6
  export class VBPlugin {
7
7
  private hmsPlugin?: HMSVBPlugin;
8
8
  private effectsPlugin?: any;
@@ -103,6 +103,18 @@ export class VBPlugin {
103
103
  this.hmsPlugin = undefined;
104
104
  };
105
105
 
106
+ isBlurSupported = () => {
107
+ if ((isSafari || isIOS) && this.hmsPlugin) {
108
+ return false;
109
+ }
110
+
111
+ if (this.effectsPlugin) {
112
+ return true;
113
+ }
114
+
115
+ return false;
116
+ };
117
+
106
118
  isEffectsSupported = () => {
107
119
  if (!isSafari) {
108
120
  return true;
@@ -57,6 +57,7 @@ export const VBPicker = ({ backgroundMedia = [] }: { backgroundMedia: VirtualBac
57
57
  const background = useHMSStore(selectAppData(APP_DATA.background));
58
58
  const mediaList = backgroundMedia.map((media: VirtualBackgroundMedia) => media.url || '');
59
59
  const pluginLoadingRef = useRef(false);
60
+ const isBlurSupported = VBHandler?.isBlurSupported();
60
61
 
61
62
  const inPreview = roomState === HMSRoomState.Preview;
62
63
  // Hidden in preview as the effect will be visible in the preview tile
@@ -190,7 +191,7 @@ export const VBPicker = ({ backgroundMedia = [] }: { backgroundMedia: VirtualBac
190
191
  await VBHandler?.setBlur(blurAmount);
191
192
  hmsActions.setAppData(APP_DATA.background, HMSVirtualBackgroundTypes.BLUR);
192
193
  },
193
- supported: isEffectsSupported && isEffectsEnabled,
194
+ supported: isBlurSupported,
194
195
  },
195
196
  ]}
196
197
  activeBackground={background}
@@ -198,7 +199,7 @@ export const VBPicker = ({ backgroundMedia = [] }: { backgroundMedia: VirtualBac
198
199
 
199
200
  {/* Slider */}
200
201
  <Flex direction="column" css={{ w: '100%', gap: '$8', mt: '$8' }}>
201
- {background === HMSVirtualBackgroundTypes.BLUR && isEffectsEnabled && effectsKey ? (
202
+ {background === HMSVirtualBackgroundTypes.BLUR && isBlurSupported ? (
202
203
  <Box>
203
204
  <Text variant="sm" css={{ color: '$on_surface_high', fontWeight: '$semiBold', mb: '$4' }}>
204
205
  Blur intensity
@@ -1,4 +1,8 @@
1
+ import { HMSAudioTrack, HMSVideoTrack } from '@100mslive/react-sdk';
2
+
1
3
  const PEER_NAME_PLACEHOLDER = 'peerName';
4
+
5
+ // Map [isLocal, videoSource] to the label to be displayed.
2
6
  const labelMap = new Map([
3
7
  [[true, 'screen'].toString(), 'Your Screen'],
4
8
  [[true, 'regular'].toString(), `You (${PEER_NAME_PLACEHOLDER})`],
@@ -8,19 +12,30 @@ const labelMap = new Map([
8
12
  [[false, undefined].toString(), `${PEER_NAME_PLACEHOLDER}`],
9
13
  ]);
10
14
 
11
- export const getVideoTileLabel = ({ peerName, isLocal, track }) => {
15
+ export const getVideoTileLabel = ({
16
+ peerName,
17
+ isLocal,
18
+ videoTrack,
19
+ audioTrack,
20
+ }: {
21
+ isLocal: boolean;
22
+ peerName?: string;
23
+ videoTrack?: HMSVideoTrack | null;
24
+ audioTrack?: HMSAudioTrack | null;
25
+ }) => {
12
26
  const isPeerPresent = peerName !== undefined;
13
- if (!isPeerPresent || !track) {
27
+ if (!isPeerPresent || !videoTrack) {
14
28
  // for peers with only audio track
15
- return isPeerPresent ? labelMap.get([isLocal, undefined].toString()).replace(PEER_NAME_PLACEHOLDER, peerName) : '';
29
+ const label = labelMap.get([isLocal, undefined].toString());
30
+ return isPeerPresent && label ? label.replace(PEER_NAME_PLACEHOLDER, peerName) : '';
16
31
  }
17
- const isLocallyMuted = track.volume === 0;
32
+ const isLocallyMuted = audioTrack?.volume === 0;
18
33
  // Map [isLocal, videoSource] to the label to be displayed.
19
- let label = labelMap.get([isLocal, track.source].toString());
34
+ let label = labelMap.get([isLocal, videoTrack.source].toString());
20
35
  if (label) {
21
36
  label = label.replace(PEER_NAME_PLACEHOLDER, peerName);
22
37
  } else {
23
- label = `${peerName} ${track.source}`;
38
+ label = `${peerName} ${videoTrack.source}`;
24
39
  }
25
40
  // label = `${label}${track.degraded ? '(Degraded)' : ''}`;
26
41
  return `${label}${isLocallyMuted ? ' (Muted for you)' : ''}`;
@@ -485,11 +485,6 @@ const HLSView = () => {
485
485
  css={{
486
486
  flex: isLandscape ? '2 1 0' : '1 1 0',
487
487
  transition: 'all 0.3s ease-in-out',
488
- '&:fullscreen': {
489
- '& video': {
490
- height: 'unset !important',
491
- },
492
- },
493
488
  }}
494
489
  >
495
490
  {hlsViewRef.current && (isMobile || isLandscape) && (
@@ -541,6 +536,7 @@ const HLSView = () => {
541
536
  onMouseMove={onHoverHandler}
542
537
  onMouseLeave={onHoverHandler}
543
538
  onClick={onClickHandler}
539
+ isFullScreen={isFullScreen}
544
540
  onDoubleClick={e => {
545
541
  onDoubleClickHandler(e);
546
542
  }}
@@ -728,6 +724,7 @@ const HLSView = () => {
728
724
  selection={currentSelectedQuality}
729
725
  onQualityChange={handleQuality}
730
726
  isAuto={isUserSelectedAuto}
727
+ containerRef={hlsViewRef.current}
731
728
  />
732
729
  ) : null}
733
730
  {isFullScreenSupported ? (