@100mslive/roomkit-react 0.1.6-alpha.0 → 0.1.6-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 (136) hide show
  1. package/dist/{HLSView-PY2FKWX3.js → HLSView-QMU5JK7U.js} +208 -118
  2. package/dist/HLSView-QMU5JK7U.js.map +7 -0
  3. package/dist/Prebuilt/AppContext.d.ts +1 -1
  4. package/dist/Prebuilt/components/Chat/ChatFooter.d.ts +7 -0
  5. package/dist/Prebuilt/components/Connection/ConnectionIndicator.d.ts +6 -0
  6. package/dist/Prebuilt/components/Connection/TileConnection.d.ts +10 -0
  7. package/dist/Prebuilt/components/Footer/ChatToggle.d.ts +2 -0
  8. package/dist/Prebuilt/components/Footer/RoleAccordion.d.ts +14 -0
  9. package/dist/Prebuilt/components/Footer/RoleOptions.d.ts +6 -0
  10. package/dist/Prebuilt/components/Header/StreamActions.d.ts +11 -0
  11. package/dist/Prebuilt/components/Leave/DesktopLeaveRoom.d.ts +4 -3
  12. package/dist/Prebuilt/components/Leave/EndSessionContent.d.ts +4 -3
  13. package/dist/Prebuilt/components/Leave/LeaveCard.d.ts +1 -2
  14. package/dist/Prebuilt/components/Leave/LeaveSessionContent.d.ts +3 -1
  15. package/dist/Prebuilt/components/Leave/MwebLeaveRoom.d.ts +4 -3
  16. package/dist/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.d.ts +6 -0
  17. package/dist/Prebuilt/components/Preview/PreviewContainer.d.ts +3 -0
  18. package/dist/Prebuilt/components/Preview/PreviewJoin.d.ts +16 -0
  19. package/dist/Prebuilt/components/RoleChangeRequestModal.d.ts +2 -0
  20. package/dist/Prebuilt/components/SecondaryTiles.d.ts +1 -1
  21. package/dist/Prebuilt/components/SidePaneTabs.d.ts +7 -0
  22. package/dist/Prebuilt/components/VideoLayouts/EqualProminence.d.ts +1 -1
  23. package/dist/Prebuilt/components/VideoLayouts/Grid.d.ts +1 -0
  24. package/dist/Prebuilt/components/VideoLayouts/GridLayout.d.ts +5 -3
  25. package/dist/Prebuilt/components/VideoLayouts/ProminenceLayout.d.ts +6 -3
  26. package/dist/Prebuilt/components/VideoLayouts/RoleProminence.d.ts +1 -1
  27. package/dist/Prebuilt/components/VideoLayouts/ScreenshareLayout.d.ts +1 -1
  28. package/dist/Prebuilt/components/VideoLayouts/interface.d.ts +1 -0
  29. package/dist/Prebuilt/components/hooks/useAutoStartStreaming.d.ts +1 -0
  30. package/dist/Prebuilt/components/hooks/useRedirectToLeave.d.ts +3 -0
  31. package/dist/Prebuilt/components/hooks/useTileLayout.d.ts +2 -1
  32. package/dist/Prebuilt/components/hooks/useVideoTileLayout.d.ts +2 -0
  33. package/dist/Prebuilt/layouts/SidePane.d.ts +4 -1
  34. package/dist/Prebuilt/layouts/VideoStreamingSection.d.ts +2 -1
  35. package/dist/{VirtualBackground-AYDHYLIZ.js → VirtualBackground-37FXUPYO.js} +6 -6
  36. package/dist/VirtualBackground-37FXUPYO.js.map +7 -0
  37. package/dist/{chunk-GQD2AGWW.js → chunk-KBVIZGYW.js} +12 -2
  38. package/dist/{chunk-GQD2AGWW.js.map → chunk-KBVIZGYW.js.map} +2 -2
  39. package/dist/{chunk-RXTHJUMZ.js → chunk-WVGGQZK4.js} +986 -436
  40. package/dist/chunk-WVGGQZK4.js.map +7 -0
  41. package/dist/{chunk-E2M2ZSOL.js → chunk-ZKE2N5LH.js} +2 -2
  42. package/dist/{conference-V2XZGTKU.js → conference-FJJQ4TXX.js} +1136 -1301
  43. package/dist/conference-FJJQ4TXX.js.map +7 -0
  44. package/dist/index.cjs.js +3565 -3092
  45. package/dist/index.cjs.js.map +4 -4
  46. package/dist/index.js +2 -2
  47. package/dist/meta.cjs.json +773 -525
  48. package/dist/meta.esbuild.json +833 -579
  49. package/package.json +8 -7
  50. package/src/Prebuilt/App.tsx +10 -21
  51. package/src/Prebuilt/AppContext.tsx +1 -1
  52. package/src/Prebuilt/IconButton.jsx +10 -0
  53. package/src/Prebuilt/common/PeersSorter.ts +1 -1
  54. package/src/Prebuilt/common/constants.js +1 -2
  55. package/src/Prebuilt/common/utils.js +1 -1
  56. package/src/Prebuilt/components/AppData/AppData.jsx +8 -2
  57. package/src/Prebuilt/components/AppData/useUISettings.js +6 -6
  58. package/src/Prebuilt/components/AudioVideoToggle.jsx +8 -6
  59. package/src/Prebuilt/components/Chat/Chat.jsx +24 -11
  60. package/src/Prebuilt/components/Chat/ChatBody.jsx +20 -21
  61. package/src/Prebuilt/components/Chat/{ChatFooter.jsx → ChatFooter.tsx} +38 -13
  62. package/src/Prebuilt/components/Chat/useEmojiPickerStyles.js +5 -4
  63. package/src/Prebuilt/components/Connection/{ConnectionIndicator.jsx → ConnectionIndicator.tsx} +12 -4
  64. package/src/Prebuilt/components/Connection/{TileConnection.jsx → TileConnection.tsx} +20 -6
  65. package/src/Prebuilt/components/EmojiReaction.jsx +2 -6
  66. package/src/Prebuilt/components/Footer/{ChatToggle.jsx → ChatToggle.tsx} +4 -1
  67. package/src/Prebuilt/components/Footer/Footer.tsx +30 -5
  68. package/src/Prebuilt/components/Footer/ParticipantList.jsx +15 -49
  69. package/src/Prebuilt/components/Footer/{RoleAccordion.jsx → RoleAccordion.tsx} +33 -17
  70. package/src/Prebuilt/components/Footer/RoleOptions.tsx +155 -0
  71. package/src/Prebuilt/components/FullPageProgress.jsx +3 -3
  72. package/src/Prebuilt/components/HMSVideo/Controls.jsx +1 -0
  73. package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.jsx +39 -17
  74. package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +2 -2
  75. package/src/Prebuilt/components/HMSVideo/VideoProgress.jsx +5 -6
  76. package/src/Prebuilt/components/HMSVideo/VolumeControl.jsx +1 -1
  77. package/src/Prebuilt/components/Header/HeaderComponents.jsx +8 -1
  78. package/src/Prebuilt/components/Header/{StreamActions.jsx → StreamActions.tsx} +23 -9
  79. package/src/Prebuilt/components/Header/common.jsx +5 -2
  80. package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx +6 -1
  81. package/src/Prebuilt/components/InsetTile.tsx +15 -8
  82. package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +21 -11
  83. package/src/Prebuilt/components/Leave/EndSessionContent.tsx +2 -5
  84. package/src/Prebuilt/components/Leave/LeaveCard.tsx +1 -3
  85. package/src/Prebuilt/components/Leave/LeaveRoom.tsx +28 -25
  86. package/src/Prebuilt/components/Leave/LeaveSessionContent.tsx +8 -2
  87. package/src/Prebuilt/components/Leave/MwebLeaveRoom.tsx +8 -8
  88. package/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx +4 -0
  89. package/src/Prebuilt/components/MoreSettings/MoreSettings.tsx +1 -1
  90. package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx +9 -23
  91. package/src/Prebuilt/components/MoreSettings/SplitComponents/{MwebOptions.jsx → MwebOptions.tsx} +89 -28
  92. package/src/Prebuilt/components/Notifications/Notifications.jsx +44 -28
  93. package/src/Prebuilt/components/Notifications/ReconnectNotifications.jsx +5 -11
  94. package/src/Prebuilt/components/Pagination.tsx +14 -12
  95. package/src/Prebuilt/components/Preview/{PreviewContainer.jsx → PreviewContainer.tsx} +11 -2
  96. package/src/Prebuilt/components/Preview/PreviewForm.tsx +6 -8
  97. package/src/Prebuilt/components/Preview/{PreviewJoin.jsx → PreviewJoin.tsx} +44 -21
  98. package/src/Prebuilt/components/{RoleChangeRequestModal.jsx → RoleChangeRequestModal.tsx} +36 -17
  99. package/src/Prebuilt/components/ScreenshareTile.jsx +6 -7
  100. package/src/Prebuilt/components/SecondaryTiles.tsx +12 -10
  101. package/src/Prebuilt/components/SidePaneTabs.tsx +120 -0
  102. package/src/Prebuilt/components/TileMenu/TileMenu.jsx +1 -1
  103. package/src/Prebuilt/components/TileMenu/TileMenuContent.jsx +14 -10
  104. package/src/Prebuilt/components/Toast/ToastConfig.jsx +5 -4
  105. package/src/Prebuilt/components/VideoLayouts/EqualProminence.tsx +13 -10
  106. package/src/Prebuilt/components/VideoLayouts/Grid.tsx +36 -34
  107. package/src/Prebuilt/components/VideoLayouts/GridLayout.tsx +33 -15
  108. package/src/Prebuilt/components/VideoLayouts/ProminenceLayout.tsx +45 -31
  109. package/src/Prebuilt/components/VideoLayouts/RoleProminence.tsx +12 -9
  110. package/src/Prebuilt/components/VideoLayouts/ScreenshareLayout.tsx +25 -9
  111. package/src/Prebuilt/components/VideoLayouts/interface.ts +1 -0
  112. package/src/Prebuilt/components/VideoTile.jsx +45 -53
  113. package/src/Prebuilt/components/conference.jsx +71 -74
  114. package/src/Prebuilt/components/hooks/useAutoStartStreaming.tsx +57 -0
  115. package/src/Prebuilt/components/hooks/useMetadata.jsx +19 -28
  116. package/src/Prebuilt/components/hooks/useRedirectToLeave.tsx +34 -0
  117. package/src/Prebuilt/components/hooks/useRoleProminencePeers.tsx +1 -1
  118. package/src/Prebuilt/components/hooks/useTileLayout.tsx +24 -18
  119. package/src/Prebuilt/components/hooks/useVideoTileLayout.ts +4 -0
  120. package/src/Prebuilt/layouts/EmbedView.jsx +1 -11
  121. package/src/Prebuilt/layouts/HLSView.jsx +152 -82
  122. package/src/Prebuilt/layouts/SidePane.tsx +25 -11
  123. package/src/Prebuilt/layouts/VideoStreamingSection.tsx +11 -47
  124. package/src/Prebuilt/plugins/FlyingEmoji.jsx +14 -2
  125. package/src/Prebuilt/plugins/VirtualBackground/VirtualBackground.jsx +3 -3
  126. package/src/Prebuilt/provider/roomLayoutProvider/hooks/useFetchRoomLayout.ts +2 -2
  127. package/src/Prebuilt/services/FeatureFlags.jsx +0 -1
  128. package/src/VideoTile/StyledVideoTile.tsx +1 -0
  129. package/dist/HLSView-PY2FKWX3.js.map +0 -7
  130. package/dist/VirtualBackground-AYDHYLIZ.js.map +0 -7
  131. package/dist/chunk-RXTHJUMZ.js.map +0 -7
  132. package/dist/conference-V2XZGTKU.js.map +0 -7
  133. package/src/Prebuilt/components/AudioLevel/BeamSpeakerLabelsLogging.jsx +0 -16
  134. package/src/Prebuilt/components/Chat/ChatParticipantHeader.jsx +0 -73
  135. package/src/Prebuilt/components/VideoList.jsx +0 -73
  136. /package/dist/{chunk-E2M2ZSOL.js.map → chunk-ZKE2N5LH.js.map} +0 -0
@@ -0,0 +1,155 @@
1
+ import React, { useState } from 'react';
2
+ import { DefaultConferencingScreen_Elements } from '@100mslive/types-prebuilt';
3
+ import { HMSPeer, selectPermissions, useHMSActions, useHMSStore, useHMSVanillaStore } from '@100mslive/react-sdk';
4
+ import {
5
+ MicOffIcon,
6
+ MicOnIcon,
7
+ PersonRectangleIcon,
8
+ RemoveUserIcon,
9
+ VerticalMenuIcon,
10
+ VideoOffIcon,
11
+ VideoOnIcon,
12
+ } from '@100mslive/react-icons';
13
+ import { Dropdown } from '../../../Dropdown';
14
+ import { Flex } from '../../../Layout';
15
+ import { Text } from '../../../Text';
16
+ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
17
+ // @ts-ignore: No implicit Any
18
+ import { getMetadata } from '../../common/utils';
19
+
20
+ const dropdownItemCSS = { backgroundColor: '$surface_default', gap: '$4', p: '$8' };
21
+ const optionTextCSS = { fontWeight: '$semiBold', color: '$on_surface_high', textTransform: 'none' };
22
+
23
+ export const RoleOptions = ({ roleName, peerList }: { roleName: string; peerList: HMSPeer[] }) => {
24
+ const [openOptions, setOpenOptions] = useState(false);
25
+ const permissions = useHMSStore(selectPermissions);
26
+ const hmsActions = useHMSActions();
27
+ const { elements } = useRoomLayoutConferencingScreen();
28
+ const { on_stage_role, off_stage_roles = [] } = (elements as DefaultConferencingScreen_Elements)?.on_stage_exp || {};
29
+
30
+ const vanillaStore = useHMSVanillaStore();
31
+ const store = vanillaStore.getState();
32
+
33
+ let allPeersHaveVideoOn = true;
34
+ let allPeersHaveAudioOn = true;
35
+
36
+ peerList.forEach(peer => {
37
+ const isAudioOn = !!peer.audioTrack && store.tracks[peer.audioTrack]?.enabled;
38
+ const isVideoOn = !!peer.videoTrack && store.tracks[peer.videoTrack]?.enabled;
39
+ allPeersHaveAudioOn = allPeersHaveAudioOn && isAudioOn;
40
+ allPeersHaveVideoOn = allPeersHaveVideoOn && isVideoOn;
41
+ });
42
+
43
+ const canMuteRole = permissions?.mute && roleName === on_stage_role;
44
+ const canRemoveRoleFromStage = permissions?.changeRole && roleName === on_stage_role;
45
+ // on stage and off stage roles
46
+ const canRemoveRoleFromRoom =
47
+ permissions?.removeOthers && (on_stage_role === roleName || off_stage_roles?.includes(roleName));
48
+
49
+ if (!(canMuteRole || canRemoveRoleFromStage || canRemoveRoleFromRoom)) {
50
+ return null;
51
+ }
52
+
53
+ const removeAllFromStage = () => {
54
+ peerList.forEach(peer => {
55
+ const prevRole = getMetadata(peer.metadata).prevRole;
56
+ if (prevRole) {
57
+ hmsActions.changeRoleOfPeer(peer.id, prevRole, true);
58
+ }
59
+ });
60
+ };
61
+
62
+ const setTrackEnabled = async (type: 'audio' | 'video', enabled = false) => {
63
+ try {
64
+ await hmsActions.setRemoteTracksEnabled({ roles: [roleName], source: 'regular', type, enabled });
65
+ } catch (e) {
66
+ console.error(e);
67
+ }
68
+ };
69
+
70
+ const removePeersFromRoom = async () => {
71
+ try {
72
+ peerList.forEach(async peer => {
73
+ await hmsActions.removePeer(peer.id, '');
74
+ });
75
+ } catch (e) {
76
+ console.error(e);
77
+ }
78
+ };
79
+
80
+ return (
81
+ <Dropdown.Root open={openOptions} onOpenChange={setOpenOptions}>
82
+ <Dropdown.Trigger
83
+ onClick={e => e.stopPropagation()}
84
+ className="role_actions"
85
+ asChild
86
+ css={{
87
+ p: '$1',
88
+ r: '$0',
89
+ c: '$on_surface_high',
90
+ visibility: openOptions ? 'visible' : 'hidden',
91
+ '&:hover': {
92
+ c: '$on_surface_medium',
93
+ },
94
+ '@md': {
95
+ visibility: 'visible',
96
+ },
97
+ }}
98
+ >
99
+ <Flex>
100
+ <VerticalMenuIcon />
101
+ </Flex>
102
+ </Dropdown.Trigger>
103
+ <Dropdown.Content
104
+ onClick={e => e.stopPropagation()}
105
+ css={{ w: 'max-content', maxWidth: '$64', bg: '$surface_default', py: 0 }}
106
+ align="end"
107
+ >
108
+ {canRemoveRoleFromStage && (
109
+ <Dropdown.Item
110
+ css={{ ...dropdownItemCSS, borderBottom: '1px solid $border_bright' }}
111
+ onClick={removeAllFromStage}
112
+ >
113
+ <PersonRectangleIcon />
114
+ <Text variant="sm" css={optionTextCSS}>
115
+ Remove all from Stage
116
+ </Text>
117
+ </Dropdown.Item>
118
+ )}
119
+
120
+ {canMuteRole && (
121
+ <>
122
+ <Dropdown.Item css={dropdownItemCSS} onClick={() => setTrackEnabled('audio', !allPeersHaveAudioOn)}>
123
+ {allPeersHaveAudioOn ? <MicOffIcon /> : <MicOnIcon />}
124
+ <Text variant="sm" css={optionTextCSS}>
125
+ {allPeersHaveAudioOn ? 'Mute' : 'Unmute'} Audio
126
+ </Text>
127
+ </Dropdown.Item>
128
+
129
+ <Dropdown.Item
130
+ css={{ ...dropdownItemCSS, borderTop: '1px solid $border_bright' }}
131
+ onClick={() => setTrackEnabled('video', !allPeersHaveVideoOn)}
132
+ >
133
+ {allPeersHaveVideoOn ? <VideoOffIcon /> : <VideoOnIcon />}
134
+ <Text variant="sm" css={optionTextCSS}>
135
+ {allPeersHaveVideoOn ? 'Mute' : 'Unmute'} Video
136
+ </Text>
137
+ </Dropdown.Item>
138
+ </>
139
+ )}
140
+
141
+ {canRemoveRoleFromRoom && (
142
+ <Dropdown.Item
143
+ css={{ ...dropdownItemCSS, borderTop: '1px solid $border_bright', color: '$alert_error_default' }}
144
+ onClick={removePeersFromRoom}
145
+ >
146
+ <RemoveUserIcon />
147
+ <Text variant="sm" css={{ ...optionTextCSS, color: 'inherit' }}>
148
+ Remove all from Room
149
+ </Text>
150
+ </Dropdown.Item>
151
+ )}
152
+ </Dropdown.Content>
153
+ </Dropdown.Root>
154
+ );
155
+ };
@@ -3,10 +3,10 @@ import { Flex } from '../../Layout';
3
3
  import { Loading } from '../../Loading';
4
4
  import { Text } from '../../Text';
5
5
 
6
- const FullPageProgress = ({ loaderColor = '$primary_default', loadingText = '' }) => (
7
- <Flex direction="column" justify="center" align="center" css={{ size: '100%', color: loaderColor }}>
6
+ const FullPageProgress = ({ loaderColor = '$primary_default', text = '', css = {} }) => (
7
+ <Flex direction="column" justify="center" align="center" css={{ size: '100%', color: loaderColor, ...css }}>
8
8
  <Loading color="currentColor" size={100} />
9
- {loadingText ? <Text css={{ mt: '$10', color: '$on_surface_high' }}>{loadingText}</Text> : null}
9
+ {text ? <Text css={{ mt: '$10', color: '$on_surface_high' }}>{text}</Text> : null}
10
10
  </Flex>
11
11
  );
12
12
 
@@ -3,6 +3,7 @@ import { Flex, styled } from '../../../';
3
3
  export const VideoControls = styled(Flex, {
4
4
  justifyContent: 'center',
5
5
  alignItems: 'center',
6
+ alignSelf: 'stretch',
6
7
  width: '100%',
7
8
  gap: '$2',
8
9
  });
@@ -1,12 +1,10 @@
1
- import React, { useState } from 'react';
2
- import { CheckCircleIcon, SettingsIcon } from '@100mslive/react-icons';
1
+ import React from 'react';
2
+ import { CheckIcon, SettingsIcon } from '@100mslive/react-icons';
3
3
  import { Box, Dropdown, Flex, Text, Tooltip } from '../../../';
4
4
 
5
- export function HLSQualitySelector({ layers, onQualityChange, selection, isAuto }) {
6
- const [qualityDropDownOpen, setQualityDropDownOpen] = useState(false);
7
-
5
+ export function HLSQualitySelector({ open, onOpen, layers, onQualityChange, selection, isAuto }) {
8
6
  return (
9
- <Dropdown.Root open={qualityDropDownOpen} onOpenChange={value => setQualityDropDownOpen(value)}>
7
+ <Dropdown.Root open={open} onOpenChange={value => onOpen(value)}>
10
8
  <Dropdown.Trigger asChild data-testid="quality_selector">
11
9
  <Flex
12
10
  css={{
@@ -24,6 +22,7 @@ export function HLSQualitySelector({ layers, onQualityChange, selection, isAuto
24
22
  h: '$9',
25
23
  display: 'inline-flex',
26
24
  alignItems: 'center',
25
+ c: '$on_surface_high',
27
26
  }}
28
27
  >
29
28
  <SettingsIcon />
@@ -44,7 +43,7 @@ export function HLSQualitySelector({ layers, onQualityChange, selection, isAuto
44
43
  mx: '$2',
45
44
  w: '$2',
46
45
  h: '$2',
47
- background: '$on_primary_high',
46
+ background: '$on_surface_medium',
48
47
  r: '$1',
49
48
  }}
50
49
  />
@@ -60,7 +59,15 @@ export function HLSQualitySelector({ layers, onQualityChange, selection, isAuto
60
59
  <Dropdown.Content
61
60
  sideOffset={5}
62
61
  align="end"
63
- css={{ height: 'auto', maxHeight: '$96', w: '$64', bg: '$surface_bright' }}
62
+ css={{
63
+ height: 'auto',
64
+ maxHeight: '$52',
65
+ w: '$40',
66
+ bg: '$surface_bright',
67
+ py: '$4',
68
+ gap: '$4',
69
+ display: 'grid',
70
+ }}
64
71
  >
65
72
  {layers.map(layer => {
66
73
  return (
@@ -68,16 +75,26 @@ export function HLSQualitySelector({ layers, onQualityChange, selection, isAuto
68
75
  onClick={() => onQualityChange(layer)}
69
76
  key={layer.width}
70
77
  css={{
71
- bg: '$surface_bright',
78
+ bg:
79
+ !isAuto && layer.width === selection?.width && layer.height === selection?.height
80
+ ? '$surface_default'
81
+ : '$surface_bright',
72
82
  '&:hover': {
73
- bg: '$surface_default',
83
+ bg: '$surface_brighter',
74
84
  },
85
+ p: '$2 $4 $2 $8',
86
+ h: '$12',
87
+ gap: '$2',
75
88
  }}
76
89
  >
77
- <Text>{getQualityText(layer)}</Text>
78
- <Text css={{ flex: '1 1 0', c: '$on_surface_low', pl: '$2' }}>{getBitrateText(layer)}</Text>
90
+ <Text variant="caption" css={{ fontWeight: '$semiBold' }}>
91
+ {getQualityText(layer)}
92
+ </Text>
93
+ <Text variant="caption" css={{ flex: '1 1 0', c: '$on_surface_low', pl: '$2' }}>
94
+ {getBitrateText(layer)}
95
+ </Text>
79
96
  {!isAuto && layer.width === selection?.width && layer.height === selection?.height && (
80
- <CheckCircleIcon />
97
+ <CheckIcon width="16px" height="16px" />
81
98
  )}
82
99
  </Dropdown.Item>
83
100
  );
@@ -86,14 +103,19 @@ export function HLSQualitySelector({ layers, onQualityChange, selection, isAuto
86
103
  onClick={() => onQualityChange({ height: 'auto' })}
87
104
  key="auto"
88
105
  css={{
89
- bg: '$surface_bright',
106
+ bg: !isAuto ? '$surface_bright' : '$surface_default',
90
107
  '&:hover': {
91
- bg: '$surface_default',
108
+ bg: '$surface_brighter',
92
109
  },
110
+ p: '$2 $4 $2 $8',
111
+ h: '$12',
112
+ gap: '$2',
93
113
  }}
94
114
  >
95
- <Text css={{ flex: '1 1 0' }}>Auto</Text>
96
- {isAuto && <CheckCircleIcon />}
115
+ <Text variant="caption" css={{ fontWeight: '$semiBold', flex: '1 1 0' }}>
116
+ Auto
117
+ </Text>
118
+ {isAuto && <CheckIcon width="16px" height="16px" />}
97
119
  </Dropdown.Item>
98
120
  </Dropdown.Content>
99
121
  )}
@@ -1,9 +1,9 @@
1
1
  import React, { forwardRef } from 'react';
2
2
  import { Flex } from '../../../';
3
3
 
4
- export const HMSVideo = forwardRef(({ children }, videoRef) => {
4
+ export const HMSVideo = forwardRef(({ children, ...props }, videoRef) => {
5
5
  return (
6
- <Flex data-testid="hms-video" css={{ size: '100%' }} direction="column">
6
+ <Flex data-testid="hms-video" css={{ size: '100%', position: 'relative' }} direction="column" {...props}>
7
7
  <video style={{ flex: '1 1 0', margin: '0 auto', minHeight: '0' }} ref={videoRef} playsInline />
8
8
  {children}
9
9
  </Flex>
@@ -44,7 +44,7 @@ export const VideoProgress = ({ onValueChange, hlsPlayer }) => {
44
44
  return hlsPlayer.getVideoElement() ? (
45
45
  <Flex
46
46
  ref={progressRootRef}
47
- css={{ paddingLeft: '$8', paddingRight: '$8', cursor: 'pointer' }}
47
+ css={{ cursor: 'pointer', h: '$4', alignSelf: 'stretch' }}
48
48
  onClick={onProgressChangeHandler}
49
49
  >
50
50
  <Box
@@ -53,23 +53,22 @@ export const VideoProgress = ({ onValueChange, hlsPlayer }) => {
53
53
  display: 'inline',
54
54
  width: `${videoProgress}%`,
55
55
  background: '$primary_default',
56
- height: '0.3rem',
57
56
  }}
58
57
  />
59
58
  <Box
60
59
  id="video-buffer"
61
60
  css={{
62
61
  width: `${bufferProgress - videoProgress}%`,
63
- background: '$primary_dim',
64
- height: '0.3rem',
62
+ background: '$on_surface_high',
63
+ opacity: '25%',
65
64
  }}
66
65
  />
67
66
  <Box
68
67
  id="video-rest"
69
68
  css={{
70
69
  width: `${100 - bufferProgress}%`,
71
- background: '$surface_brighter',
72
- height: '0.3rem',
70
+ background: '$on_surface_high',
71
+ opacity: '10%',
73
72
  }}
74
73
  />
75
74
  </Flex>
@@ -9,7 +9,7 @@ export const VolumeControl = ({ hlsPlayer }) => {
9
9
  return (
10
10
  <Flex
11
11
  align="center"
12
- css={{ color: '$on_primary_high' }}
12
+ css={{ color: '$on_surface_high' }}
13
13
  onMouseOver={event => {
14
14
  event.stopPropagation();
15
15
  setShowSlider(true);
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import { useMedia } from 'react-use';
3
3
  import { selectDominantSpeaker, selectIsConnectedToRoom, useHMSStore } from '@100mslive/react-sdk';
4
4
  import { VolumeOneIcon } from '@100mslive/react-icons';
@@ -41,6 +41,13 @@ export const Logo = () => {
41
41
  const isConnected = useHMSStore(selectIsConnectedToRoom);
42
42
  const [hideImage, setHideImage] = useState(false);
43
43
  // Hide logo for now as there is not enough space
44
+ useEffect(() => {
45
+ if (hideImage) {
46
+ setHideImage(false);
47
+ }
48
+ // eslint-disable-next-line react-hooks/exhaustive-deps
49
+ }, [logo]);
50
+
44
51
  if (isConnected && isMobile) {
45
52
  return null;
46
53
  }
@@ -11,26 +11,31 @@ import {
11
11
  useRecordingStreaming,
12
12
  } from '@100mslive/react-sdk';
13
13
  import { AlertTriangleIcon, CrossIcon, RecordIcon } from '@100mslive/react-icons';
14
- import { Box, Button, config as cssConfig, Flex, HorizontalDivider, Loading, Popover, Text, Tooltip } from '../../../';
14
+ import { Box, Button, config as cssConfig, Flex, HorizontalDivider, Loading, Popover, Text, Tooltip } from '../../..';
15
15
  import { Sheet } from '../../../Sheet';
16
+ // @ts-ignore
16
17
  import { ToastManager } from '../Toast/ToastManager';
18
+ // @ts-ignore
17
19
  import { AdditionalRoomState, getRecordingText } from './AdditionalRoomState';
20
+ // @ts-ignore
18
21
  import { useSetAppDataByKey } from '../AppData/useUISettings';
22
+ // @ts-ignore
19
23
  import { formatTime } from '../../common/utils';
24
+ // @ts-ignore
20
25
  import { APP_DATA } from '../../common/constants';
21
26
 
22
27
  export const LiveStatus = () => {
23
28
  const { isHLSRunning, isRTMPRunning } = useRecordingStreaming();
24
29
  const hlsState = useHMSStore(selectHLSState);
25
30
  const isMobile = useMedia(cssConfig.media.md);
26
- const intervalRef = useRef(null);
31
+ const intervalRef = useRef<NodeJS.Timeout | null>(null);
27
32
 
28
33
  const [liveTime, setLiveTime] = useState(0);
29
34
 
30
35
  const startTimer = useCallback(() => {
31
36
  intervalRef.current = setInterval(() => {
32
- if (hlsState?.running) {
33
- setLiveTime(Date.now() - hlsState?.variants[0]?.startedAt.getTime());
37
+ if (hlsState?.running && hlsState?.variants[0]?.startedAt) {
38
+ setLiveTime(Date.now() - hlsState.variants[0].startedAt.getTime());
34
39
  }
35
40
  }, 1000);
36
41
  }, [hlsState?.running, hlsState?.variants]);
@@ -90,6 +95,7 @@ export const RecordingStatus = () => {
90
95
 
91
96
  return (
92
97
  <Tooltip
98
+ boxCss={{ zIndex: 1 }}
93
99
  title={getRecordingText({
94
100
  isBrowserRecordingOn,
95
101
  isServerRecordingOn,
@@ -130,7 +136,7 @@ const StartRecording = () => {
130
136
  </Popover.Trigger>
131
137
  <Popover.Portal>
132
138
  <Popover.Content align="end" sideOffset={8} css={{ w: '$64' }}>
133
- <Text variant="body" css={{ color: '$on_surface_medium' }}>
139
+ <Text variant="body1" css={{ color: '$on_surface_medium' }}>
134
140
  Are you sure you want to end the recording?
135
141
  </Text>
136
142
  <Button
@@ -142,8 +148,9 @@ const StartRecording = () => {
142
148
  try {
143
149
  await hmsActions.stopRTMPAndRecording();
144
150
  } catch (error) {
151
+ const err = error as Error;
145
152
  ToastManager.addToast({
146
- title: error.message,
153
+ title: err.message,
147
154
  variant: 'error',
148
155
  });
149
156
  }
@@ -170,14 +177,15 @@ const StartRecording = () => {
170
177
  record: true,
171
178
  });
172
179
  } catch (error) {
173
- if (error.message.includes('stream already running')) {
180
+ const err = error as Error;
181
+ if (err.message.includes('stream already running')) {
174
182
  ToastManager.addToast({
175
183
  title: 'Recording already running',
176
184
  variant: 'error',
177
185
  });
178
186
  } else {
179
187
  ToastManager.addToast({
180
- title: error.message,
188
+ title: err.message,
181
189
  variant: 'error',
182
190
  });
183
191
  }
@@ -215,7 +223,13 @@ export const StreamActions = () => {
215
223
  );
216
224
  };
217
225
 
218
- export const StopRecordingInSheet = ({ onStopRecording, onClose }) => {
226
+ export const StopRecordingInSheet = ({
227
+ onStopRecording,
228
+ onClose,
229
+ }: {
230
+ onStopRecording: () => void;
231
+ onClose: () => void;
232
+ }) => {
219
233
  return (
220
234
  <Sheet.Root open={true}>
221
235
  <Sheet.Content>
@@ -25,11 +25,13 @@ export const CamaraFlipActions = () => {
25
25
 
26
26
  const videoTrackId = useHMSStore(selectLocalVideoTrackID);
27
27
  const localVideoTrack = useHMSStore(selectVideoTrackByID(videoTrackId));
28
-
28
+ if (!videoInput || !videoInput?.length || !localVideoTrack?.facingMode) {
29
+ return null;
30
+ }
29
31
  return (
30
32
  <Box>
31
33
  <IconButton
32
- disabled={!videoInput?.length || !isVideoOn || !localVideoTrack?.facingMode}
34
+ disabled={!isVideoOn}
33
35
  onClick={async () => {
34
36
  try {
35
37
  await actions.switchCamera();
@@ -117,6 +119,7 @@ const AudioOutputSelectionSheet = ({ outputDevices, outputSelected, onChange, ch
117
119
  {outputDevices.map(audioDevice => {
118
120
  return (
119
121
  <SelectWithLabel
122
+ key={audioDevice.deviceId}
120
123
  label={audioDevice.label}
121
124
  id={audioDevice.deviceId}
122
125
  checked={audioDevice.deviceId === outputSelected}
@@ -14,6 +14,10 @@ const IconSection = styled(IconButton, {
14
14
  borderTopRightRadius: 0,
15
15
  borderColor: '$border_default',
16
16
  borderBottomRightRadius: 0,
17
+ position: 'relative',
18
+ '&:not([disabled]):focus-visible': {
19
+ zIndex: 1,
20
+ },
17
21
  '@md': {
18
22
  mx: 0,
19
23
  borderTopRightRadius: '$1',
@@ -30,8 +34,9 @@ const OptionsSection = styled(IconButton, {
30
34
  borderColor: '$border_default',
31
35
  borderBottomLeftRadius: 0,
32
36
  borderLeftWidth: 0,
37
+ position: 'relative',
33
38
  '&:not([disabled]):focus-visible': {
34
- boxShadow: 'none',
39
+ zIndex: 1,
35
40
  },
36
41
  '@md': {
37
42
  display: 'none',
@@ -14,6 +14,7 @@ import { AudioVideoToggle } from './AudioVideoToggle';
14
14
  import VideoTile from './VideoTile';
15
15
  // @ts-ignore: No implicit Any
16
16
  import { useSetAppDataByKey } from './AppData/useUISettings';
17
+ import { useVideoTileContext } from './hooks/useVideoTileLayout';
17
18
  // @ts-ignore: No implicit Any
18
19
  import { APP_DATA } from '../common/constants';
19
20
 
@@ -22,7 +23,11 @@ const MinimisedTile = ({ setMinimised }: { setMinimised: (value: boolean) => voi
22
23
  <Flex align="center" css={{ gap: '$6', r: '$1', bg: '$surface_default', p: '$4', color: '$on_surface_high' }}>
23
24
  <AudioVideoToggle hideOptions={true} />
24
25
  <Text>You</Text>
25
- <IconButton onClick={() => setMinimised(false)} css={{ bg: 'transparent', border: 'transparent' }}>
26
+ <IconButton
27
+ className="__cancel-drag-event"
28
+ onClick={() => setMinimised(false)}
29
+ css={{ bg: 'transparent', border: 'transparent' }}
30
+ >
26
31
  <ExpandIcon />
27
32
  </IconButton>
28
33
  </Flex>
@@ -41,12 +46,11 @@ export const InsetTile = () => {
41
46
  const [minimised, setMinimised] = useSetAppDataByKey(APP_DATA.minimiseInset);
42
47
  const videoTrack = useHMSStore(selectVideoTrackByID(localPeer?.videoTrack));
43
48
  const isAllowedToPublish = useHMSStore(selectIsAllowedToPublish);
44
- const aspectRatio =
45
- videoTrack?.width && videoTrack?.height
46
- ? videoTrack.width / videoTrack.height
47
- : isMobile
48
- ? defaultMobileAspectRatio
49
- : desktopAspectRatio;
49
+ const videoTileProps = useVideoTileContext();
50
+ let aspectRatio = isMobile ? defaultMobileAspectRatio : desktopAspectRatio;
51
+ if (videoTrack?.width && videoTrack?.height && !isMobile) {
52
+ aspectRatio = videoTrack.width / videoTrack.height;
53
+ }
50
54
  let height = insetHeightPx;
51
55
  let width = height * aspectRatio;
52
56
  // Convert to 16/9 in landscape mode with a max width of 240
@@ -82,7 +86,7 @@ export const InsetTile = () => {
82
86
  }
83
87
 
84
88
  return (
85
- <Draggable bounds="parent" nodeRef={nodeRef}>
89
+ <Draggable bounds="parent" nodeRef={nodeRef} cancel=".__cancel-drag-event">
86
90
  <Box
87
91
  ref={nodeRef}
88
92
  css={{
@@ -114,6 +118,9 @@ export const InsetTile = () => {
114
118
  height={height}
115
119
  containerCSS={{ background: '$surface_default' }}
116
120
  canMinimise
121
+ isDragabble
122
+ {...videoTileProps}
123
+ hideParticipantNameOnTile
117
124
  />
118
125
  )}
119
126
  </Box>
@@ -15,11 +15,9 @@ import { useDropdownList } from '../hooks/useDropdownList';
15
15
 
16
16
  export const DesktopLeaveRoom = ({
17
17
  leaveRoom,
18
- stopStream,
19
18
  screenType,
20
19
  }: {
21
- leaveRoom: () => void;
22
- stopStream: () => Promise<void>;
20
+ leaveRoom: (args: { endstream: boolean }) => void;
23
21
  screenType: keyof ConferencingScreen;
24
22
  }) => {
25
23
  const [open, setOpen] = useState(false);
@@ -51,7 +49,7 @@ export const DesktopLeaveRoom = ({
51
49
  if (screenType === 'hls_live_streaming') {
52
50
  setShowLeaveRoomAlert(true);
53
51
  } else {
54
- leaveRoom();
52
+ leaveRoom({ endstream: false });
55
53
  }
56
54
  }}
57
55
  >
@@ -75,7 +73,15 @@ export const DesktopLeaveRoom = ({
75
73
  </MenuTriggerButton>
76
74
  </Dropdown.Trigger>
77
75
  <Dropdown.Content css={{ p: 0, w: '$100' }} alignOffset={-50} sideOffset={10}>
78
- <Dropdown.Item css={{ bg: '$surface_default' }} onClick={leaveRoom} data-testid="just_leave_btn">
76
+ <Dropdown.Item
77
+ css={{
78
+ bg: '$surface_dim',
79
+ color: '$on_surface_low',
80
+ '&:hover': { bg: '$surface_default', color: '$on_surface_high' },
81
+ }}
82
+ onClick={() => leaveRoom({ endstream: false })}
83
+ data-testid="just_leave_btn"
84
+ >
79
85
  <LeaveCard
80
86
  title={showStream ? 'Leave Stream' : 'Leave Session'}
81
87
  subtitle={`Others will continue after you leave. You can join the ${
@@ -83,14 +89,20 @@ export const DesktopLeaveRoom = ({
83
89
  } again.`}
84
90
  bg=""
85
91
  titleColor="$on_surface_high"
86
- subtitleColor="$on_surface_low"
87
92
  icon={<ExitIcon height={24} width={24} style={{ transform: 'rotate(180deg)' }} />}
88
- onClick={leaveRoom}
93
+ onClick={() => leaveRoom({ endstream: false })}
89
94
  css={{ p: 0 }}
90
95
  />
91
96
  </Dropdown.Item>
92
97
  {isStreamingOn && permissions?.hlsStreaming ? (
93
- <Dropdown.Item css={{ bg: '$alert_error_dim' }} data-testid="end_room_btn">
98
+ <Dropdown.Item
99
+ css={{
100
+ bg: '$alert_error_dim',
101
+ color: '$alert_error_bright',
102
+ '&:hover': { bg: '$alert_error_dim', color: '$alert_error_brighter' },
103
+ }}
104
+ data-testid="end_room_btn"
105
+ >
94
106
  <LeaveCard
95
107
  title={showStream ? 'End Stream' : 'End Session'}
96
108
  subtitle={`The ${
@@ -98,7 +110,6 @@ export const DesktopLeaveRoom = ({
98
110
  } will end for everyone. You can't undo this action.`}
99
111
  bg=""
100
112
  titleColor="$alert_error_brighter"
101
- subtitleColor="$alert_error_bright"
102
113
  icon={<StopIcon height={24} width={24} />}
103
114
  onClick={() => {
104
115
  setOpen(false);
@@ -117,7 +128,7 @@ export const DesktopLeaveRoom = ({
117
128
  if (screenType === 'hls_live_streaming') {
118
129
  setShowLeaveRoomAlert(true);
119
130
  } else {
120
- leaveRoom();
131
+ leaveRoom({ endstream: false });
121
132
  }
122
133
  }}
123
134
  key="LeaveRoom"
@@ -137,7 +148,6 @@ export const DesktopLeaveRoom = ({
137
148
  <Dialog.Content css={{ w: 'min(420px, 90%)', p: '$8', bg: '$surface_dim' }}>
138
149
  <EndSessionContent
139
150
  setShowEndStreamAlert={setShowEndStreamAlert}
140
- stopStream={stopStream}
141
151
  leaveRoom={leaveRoom}
142
152
  isStreamingOn={isStreamingOn}
143
153
  isModal