@100mslive/roomkit-react 0.1.5 → 0.1.6-alpha.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (197) hide show
  1. package/dist/{HLSView-P57IRMAR.js → HLSView-PY2FKWX3.js} +191 -123
  2. package/dist/HLSView-PY2FKWX3.js.map +7 -0
  3. package/dist/Prebuilt/App.d.ts +3 -0
  4. package/dist/Prebuilt/AppContext.d.ts +13 -0
  5. package/dist/Prebuilt/common/PeersSorter.d.ts +21 -0
  6. package/dist/Prebuilt/components/Footer/Footer.d.ts +6 -0
  7. package/dist/Prebuilt/components/Header/Header.d.ts +2 -0
  8. package/dist/Prebuilt/components/InsetTile.d.ts +2 -0
  9. package/dist/Prebuilt/components/Leave/DesktopLeaveRoom.d.ts +7 -0
  10. package/dist/Prebuilt/components/Leave/EndSessionContent.d.ts +8 -0
  11. package/dist/Prebuilt/components/Leave/LeaveAtoms.d.ts +2196 -0
  12. package/dist/Prebuilt/components/Leave/LeaveCard.d.ts +12 -0
  13. package/dist/Prebuilt/components/Leave/LeaveRoom.d.ts +5 -0
  14. package/dist/Prebuilt/components/Leave/LeaveSessionContent.d.ts +6 -0
  15. package/dist/Prebuilt/components/Leave/MwebLeaveRoom.d.ts +7 -0
  16. package/dist/Prebuilt/components/MoreSettings/MoreSettings.d.ts +6 -0
  17. package/dist/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.d.ts +6 -0
  18. package/dist/Prebuilt/components/Pagination.d.ts +6 -0
  19. package/dist/Prebuilt/components/Preview/PreviewForm.d.ts +10 -0
  20. package/dist/Prebuilt/components/SecondaryTiles.d.ts +3 -0
  21. package/dist/Prebuilt/components/VideoLayouts/EqualProminence.d.ts +3 -0
  22. package/dist/Prebuilt/components/VideoLayouts/Grid.d.ts +5 -0
  23. package/dist/Prebuilt/components/VideoLayouts/GridLayout.d.ts +10 -0
  24. package/dist/Prebuilt/components/VideoLayouts/ProminenceLayout.d.ts +12 -0
  25. package/dist/Prebuilt/components/VideoLayouts/RoleProminence.d.ts +3 -0
  26. package/dist/Prebuilt/components/VideoLayouts/ScreenshareLayout.d.ts +3 -0
  27. package/dist/Prebuilt/components/VideoLayouts/interface.d.ts +8 -0
  28. package/dist/Prebuilt/components/hooks/useRoleProminencePeers.d.ts +5 -0
  29. package/dist/Prebuilt/components/hooks/useTileLayout.d.ts +12 -0
  30. package/dist/Prebuilt/components/hooks/useVideoTileLayout.d.ts +11 -0
  31. package/dist/Prebuilt/layouts/SidePane.d.ts +6 -0
  32. package/dist/Prebuilt/layouts/VideoStreamingSection.d.ts +6 -0
  33. package/dist/Prebuilt/plugins/whiteboard/ToggleWhiteboard.d.ts +5 -0
  34. package/dist/Prebuilt/provider/roomLayoutProvider/hooks/useFetchRoomLayout.d.ts +1 -0
  35. package/dist/Prebuilt/provider/roomLayoutProvider/hooks/useInsetEnabled.d.ts +1 -0
  36. package/dist/Prebuilt/provider/roomLayoutProvider/hooks/useRoomLayoutScreen.d.ts +17 -0
  37. package/dist/Prebuilt/provider/roomLayoutProvider/index.d.ts +6 -1
  38. package/dist/{VirtualBackground-GGCQJ5JM.js → VirtualBackground-AYDHYLIZ.js} +5 -11
  39. package/dist/VirtualBackground-AYDHYLIZ.js.map +7 -0
  40. package/dist/{chunk-P5X32KOD.js → chunk-E2M2ZSOL.js} +8 -5
  41. package/dist/chunk-E2M2ZSOL.js.map +7 -0
  42. package/dist/chunk-GQD2AGWW.js +888 -0
  43. package/dist/chunk-GQD2AGWW.js.map +7 -0
  44. package/dist/{chunk-OSM4QEQG.js → chunk-RXTHJUMZ.js} +2462 -4738
  45. package/dist/chunk-RXTHJUMZ.js.map +7 -0
  46. package/dist/conference-V2XZGTKU.js +5927 -0
  47. package/dist/conference-V2XZGTKU.js.map +7 -0
  48. package/dist/index.cjs.js +9414 -15534
  49. package/dist/index.cjs.js.map +4 -4
  50. package/dist/index.js +2 -2
  51. package/dist/meta.cjs.json +2156 -3347
  52. package/dist/meta.esbuild.json +2601 -3885
  53. package/package.json +7 -7
  54. package/src/Button/Button.tsx +2 -2
  55. package/src/Prebuilt/App.tsx +49 -33
  56. package/src/Prebuilt/{AppContext.jsx → AppContext.tsx} +11 -3
  57. package/src/Prebuilt/IconButton.jsx +1 -0
  58. package/src/Prebuilt/Prebuilt.stories.tsx +1 -0
  59. package/src/Prebuilt/common/{PeersSorter.js → PeersSorter.ts} +15 -10
  60. package/src/Prebuilt/common/constants.js +3 -112
  61. package/src/Prebuilt/common/hooks.js +34 -1
  62. package/src/Prebuilt/common/utils.js +0 -8
  63. package/src/Prebuilt/components/AppData/AppData.jsx +3 -13
  64. package/src/Prebuilt/components/AppData/useUISettings.js +0 -4
  65. package/src/Prebuilt/components/AudioVideoToggle.jsx +6 -0
  66. package/src/Prebuilt/components/AuthToken.jsx +11 -42
  67. package/src/Prebuilt/components/Chat/Chat.jsx +57 -26
  68. package/src/Prebuilt/components/Chat/ChatBody.jsx +92 -32
  69. package/src/Prebuilt/components/Chat/ChatFooter.jsx +72 -48
  70. package/src/Prebuilt/components/Chat/ChatParticipantHeader.jsx +73 -0
  71. package/src/Prebuilt/components/Chat/ChatSelector.jsx +16 -17
  72. package/src/Prebuilt/components/Chat/ChatSelectorContainer.jsx +81 -0
  73. package/src/Prebuilt/components/Connection/TileConnection.jsx +30 -12
  74. package/src/Prebuilt/components/EmojiReaction.jsx +18 -17
  75. package/src/Prebuilt/components/Footer/ChatToggle.jsx +1 -7
  76. package/src/Prebuilt/components/Footer/Footer.tsx +89 -0
  77. package/src/Prebuilt/components/Footer/ParticipantList.jsx +213 -173
  78. package/src/Prebuilt/components/Footer/RoleAccordion.jsx +78 -0
  79. package/src/Prebuilt/components/HMSVideo/Controls.jsx +2 -2
  80. package/src/Prebuilt/components/HMSVideo/HLSQualitySelector.jsx +33 -10
  81. package/src/Prebuilt/components/HMSVideo/PlayButton.jsx +1 -1
  82. package/src/Prebuilt/components/HMSVideo/VideoTime.jsx +3 -3
  83. package/src/Prebuilt/components/HMSVideo/VolumeControl.jsx +38 -9
  84. package/src/Prebuilt/components/Header/{ConferencingHeader.jsx → Header.tsx} +9 -7
  85. package/src/Prebuilt/components/Header/HeaderComponents.jsx +13 -4
  86. package/src/Prebuilt/components/Header/StreamActions.jsx +33 -60
  87. package/src/Prebuilt/components/Header/index.tsx +1 -0
  88. package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx +17 -3
  89. package/src/Prebuilt/components/InsetTile.tsx +122 -0
  90. package/src/Prebuilt/components/{MoreSettings/SplitComponents/DesktopLeaveRoom.jsx → Leave/DesktopLeaveRoom.tsx} +50 -18
  91. package/src/Prebuilt/components/{EndSessionContent.jsx → Leave/EndSessionContent.tsx} +19 -9
  92. package/src/Prebuilt/components/Leave/LeaveAtoms.tsx +26 -0
  93. package/src/Prebuilt/components/{LeaveCard.jsx → Leave/LeaveCard.tsx} +22 -3
  94. package/src/Prebuilt/components/Leave/LeaveRoom.tsx +63 -0
  95. package/src/Prebuilt/components/{LeaveSessionContent.jsx → Leave/LeaveSessionContent.tsx} +13 -5
  96. package/src/Prebuilt/components/{MoreSettings/SplitComponents/MwebLeaveRoom.jsx → Leave/MwebLeaveRoom.tsx} +38 -13
  97. package/src/Prebuilt/components/MetaActions.jsx +15 -23
  98. package/src/Prebuilt/components/MoreSettings/ActionTile.jsx +5 -0
  99. package/src/Prebuilt/components/MoreSettings/ChangeNameContent.jsx +12 -7
  100. package/src/Prebuilt/components/MoreSettings/ChangeNameModal.jsx +1 -1
  101. package/src/Prebuilt/components/MoreSettings/FullScreenItem.jsx +1 -4
  102. package/src/Prebuilt/components/MoreSettings/MoreSettings.tsx +27 -0
  103. package/src/Prebuilt/components/MoreSettings/SplitComponents/{DesktopOptions.jsx → DesktopOptions.tsx} +86 -75
  104. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.jsx +20 -19
  105. package/src/Prebuilt/components/Notifications/HLSFailureModal.jsx +3 -1
  106. package/src/Prebuilt/components/Notifications/Notifications.jsx +18 -11
  107. package/src/Prebuilt/components/Notifications/PeerNotifications.jsx +14 -2
  108. package/src/Prebuilt/components/Notifications/PermissionErrorModal.jsx +10 -4
  109. package/src/Prebuilt/components/PIP/PIPComponent.jsx +7 -16
  110. package/src/Prebuilt/components/PIP/PIPManager.js +1 -0
  111. package/src/Prebuilt/components/{Pagination.jsx → Pagination.tsx} +35 -6
  112. package/src/Prebuilt/components/Playlist/Playlist.jsx +1 -6
  113. package/src/Prebuilt/components/PostLeave.jsx +7 -7
  114. package/src/Prebuilt/components/Preview/PreviewContainer.jsx +5 -13
  115. package/src/Prebuilt/components/Preview/{PreviewForm.jsx → PreviewForm.tsx} +14 -4
  116. package/src/Prebuilt/components/Preview/PreviewJoin.jsx +9 -7
  117. package/src/Prebuilt/components/RaiseHand.jsx +0 -7
  118. package/src/Prebuilt/components/RoleChangeRequestModal.jsx +82 -6
  119. package/src/Prebuilt/components/ScreenshareDisplay.jsx +4 -10
  120. package/src/Prebuilt/components/ScreenshareTile.jsx +41 -33
  121. package/src/Prebuilt/components/SecondaryTiles.tsx +34 -0
  122. package/src/Prebuilt/components/Settings/LayoutSettings.jsx +2 -12
  123. package/src/Prebuilt/components/Settings/NotificationSettings.jsx +3 -9
  124. package/src/Prebuilt/components/Settings/SettingsModal.jsx +3 -9
  125. package/src/Prebuilt/components/StatsForNerds.jsx +3 -1
  126. package/src/Prebuilt/components/TileMenu/TileMenu.jsx +15 -16
  127. package/src/Prebuilt/components/TileMenu/TileMenuContent.jsx +21 -19
  128. package/src/Prebuilt/components/Toast/ToastConfig.jsx +53 -11
  129. package/src/Prebuilt/components/VideoLayouts/EqualProminence.tsx +62 -0
  130. package/src/Prebuilt/components/VideoLayouts/Grid.tsx +41 -0
  131. package/src/Prebuilt/components/VideoLayouts/GridLayout.tsx +92 -0
  132. package/src/Prebuilt/components/VideoLayouts/ProminenceLayout.tsx +60 -0
  133. package/src/Prebuilt/components/VideoLayouts/RoleProminence.tsx +56 -0
  134. package/src/Prebuilt/components/VideoLayouts/ScreenshareLayout.tsx +36 -0
  135. package/src/Prebuilt/components/VideoLayouts/interface.ts +9 -0
  136. package/src/Prebuilt/components/VideoTile.jsx +93 -43
  137. package/src/Prebuilt/components/conference.jsx +24 -20
  138. package/src/Prebuilt/components/hooks/useMetadata.jsx +7 -0
  139. package/src/Prebuilt/components/hooks/useRoleProminencePeers.tsx +38 -0
  140. package/src/Prebuilt/components/hooks/useTileLayout.tsx +121 -0
  141. package/src/Prebuilt/components/hooks/useVideoTileLayout.ts +22 -0
  142. package/src/Prebuilt/components/pdfAnnotator/pdfFileOptions.jsx +5 -72
  143. package/src/Prebuilt/components/pdfAnnotator/submitPdf.jsx +4 -45
  144. package/src/Prebuilt/components/pdfAnnotator/uploadedFile.jsx +2 -17
  145. package/src/Prebuilt/components/peerTileUtils.jsx +1 -1
  146. package/src/Prebuilt/images/empty-chat.svg +12 -0
  147. package/src/Prebuilt/layouts/EmbedView.jsx +17 -40
  148. package/src/Prebuilt/layouts/HLSView.jsx +83 -66
  149. package/src/Prebuilt/layouts/PDFView.jsx +1 -11
  150. package/src/Prebuilt/layouts/SidePane.tsx +96 -0
  151. package/src/Prebuilt/layouts/{mainView.jsx → VideoStreamingSection.tsx} +38 -47
  152. package/src/Prebuilt/layouts/WhiteboardView.jsx +10 -34
  153. package/src/Prebuilt/plugins/VirtualBackground/VirtualBackground.jsx +1 -4
  154. package/src/Prebuilt/plugins/whiteboard/{ToggleWhiteboard.jsx → ToggleWhiteboard.tsx} +5 -9
  155. package/src/Prebuilt/primitives/DialogContent.jsx +15 -11
  156. package/src/Prebuilt/provider/roomLayoutProvider/constants/index.ts +17 -2
  157. package/src/Prebuilt/provider/roomLayoutProvider/hooks/useFetchRoomLayout.ts +36 -13
  158. package/src/Prebuilt/provider/roomLayoutProvider/hooks/useInsetEnabled.ts +10 -0
  159. package/src/Prebuilt/provider/roomLayoutProvider/hooks/useRoomLayoutScreen.ts +65 -0
  160. package/src/Prebuilt/provider/roomLayoutProvider/index.tsx +17 -6
  161. package/dist/HLSView-P57IRMAR.js.map +0 -7
  162. package/dist/PinnedTrackView-4FYJEBTB.js +0 -102
  163. package/dist/PinnedTrackView-4FYJEBTB.js.map +0 -7
  164. package/dist/VirtualBackground-GGCQJ5JM.js.map +0 -7
  165. package/dist/chunk-IVTWKQI3.js +0 -827
  166. package/dist/chunk-IVTWKQI3.js.map +0 -7
  167. package/dist/chunk-OSM4QEQG.js.map +0 -7
  168. package/dist/chunk-P5X32KOD.js.map +0 -7
  169. package/dist/chunk-RVCZPPTL.js +0 -1100
  170. package/dist/chunk-RVCZPPTL.js.map +0 -7
  171. package/dist/conference-P6I6ESVF.js +0 -8995
  172. package/dist/conference-P6I6ESVF.js.map +0 -7
  173. package/src/Prebuilt/components/Chat/ChatHeader.jsx +0 -67
  174. package/src/Prebuilt/components/EqualProminence.jsx +0 -180
  175. package/src/Prebuilt/components/FirstPersonDisplay.jsx +0 -50
  176. package/src/Prebuilt/components/Footer/Footer.jsx +0 -73
  177. package/src/Prebuilt/components/Header/Header.jsx +0 -8
  178. package/src/Prebuilt/components/Header/StreamingHeader.jsx +0 -54
  179. package/src/Prebuilt/components/LeaveRoom.jsx +0 -94
  180. package/src/Prebuilt/components/MoreSettings/MoreSettings.jsx +0 -10
  181. package/src/Prebuilt/components/Notifications/MessageNotifications.jsx +0 -25
  182. package/src/Prebuilt/components/gridView.jsx +0 -85
  183. package/src/Prebuilt/components/hooks/useFeatures.js +0 -22
  184. package/src/Prebuilt/components/hooks/useNavigation.js +0 -19
  185. package/src/Prebuilt/components/hooks/useSkipPreview.jsx +0 -20
  186. package/src/Prebuilt/components/pdfAnnotator/pdfErrorView.jsx +0 -29
  187. package/src/Prebuilt/images/Logo.svg +0 -8
  188. package/src/Prebuilt/layouts/ActiveSpeakerView.jsx +0 -34
  189. package/src/Prebuilt/layouts/InsetView.jsx +0 -260
  190. package/src/Prebuilt/layouts/PinnedTrackView.jsx +0 -59
  191. package/src/Prebuilt/layouts/SidePane.jsx +0 -52
  192. package/src/Prebuilt/layouts/mainGridView.jsx +0 -98
  193. package/src/Prebuilt/layouts/screenShareView.jsx +0 -183
  194. /package/{src/Prebuilt/components/Header/index.jsx → dist/Prebuilt/components/Header/index.d.ts} +0 -0
  195. /package/src/Prebuilt/components/{ScreenShare.jsx → ScreenShareToggle.jsx} +0 -0
  196. /package/src/{assets → Prebuilt/images}/android-perm-1.png +0 -0
  197. /package/src/{assets → Prebuilt/images}/ios-perm-0.png +0 -0
@@ -1,14 +1,10 @@
1
- import React, { useEffect, useMemo, useState } from 'react';
2
- import { matchPath, useLocation } from 'react-router-dom';
3
- import { useSearchParam } from 'react-use';
4
- import { v4 as uuid } from 'uuid';
1
+ import React, { useEffect, useState } from 'react';
5
2
  import { useHMSActions } from '@100mslive/react-sdk';
6
3
  import { styled } from '../../Theme';
7
4
  import { useHMSPrebuiltContext } from '../AppContext';
8
5
  import { ErrorDialog } from '../primitives/DialogContent';
9
6
  import { useSetAppDataByKey, useTokenEndpoint } from './AppData/useUISettings';
10
- import getToken from '../services/tokenService';
11
- import { APP_DATA, QUERY_PARAM_AUTH_TOKEN } from '../common/constants';
7
+ import { APP_DATA } from '../common/constants';
12
8
 
13
9
  /**
14
10
  * query params exposed -
@@ -19,20 +15,12 @@ import { APP_DATA, QUERY_PARAM_AUTH_TOKEN } from '../common/constants';
19
15
  * auth_token=123 => uses the passed in token to join instead of fetching from token endpoint
20
16
  * ui_mode=activespeaker => lands in active speaker mode after joining the room
21
17
  */
22
- const AuthToken = React.memo(({ authTokenByRoomCodeEndpoint }) => {
18
+ const AuthToken = React.memo(({ authTokenByRoomCodeEndpoint, defaultAuthToken }) => {
23
19
  const hmsActions = useHMSActions();
24
20
  const tokenEndpoint = useTokenEndpoint();
25
- const { showPreview, roomCode, userId } = useHMSPrebuiltContext();
26
- const location = useLocation();
27
- const matches = useMemo(
28
- () =>
29
- matchPath(`${showPreview ? 'preview' : 'meeting'}/:roomId/:role`, location.pathname) ||
30
- matchPath(`${showPreview ? 'preview' : 'meeting'}/:roomCode/`, location.pathname),
31
- [location, showPreview],
32
- );
33
- const { roomCode: urlRoomCode, roomId: urlRoomId, role: userRole } = matches?.params || {};
21
+ const { roomCode, userId } = useHMSPrebuiltContext();
34
22
  const [error, setError] = useState({ title: '', body: '' });
35
- let authToken = useSearchParam(QUERY_PARAM_AUTH_TOKEN);
23
+ let authToken = defaultAuthToken;
36
24
  const [, setAuthTokenInAppData] = useSetAppDataByKey(APP_DATA.authToken);
37
25
 
38
26
  useEffect(() => {
@@ -40,34 +28,15 @@ const AuthToken = React.memo(({ authTokenByRoomCodeEndpoint }) => {
40
28
  setAuthTokenInAppData(authToken);
41
29
  return;
42
30
  }
43
- if (!tokenEndpoint && !urlRoomId && !roomCode && !urlRoomCode) {
31
+ if (!tokenEndpoint && !roomCode) {
44
32
  return;
45
33
  }
46
- const code = !userRole && (roomCode || urlRoomCode);
47
34
 
48
- const getTokenFn = code
49
- ? () => hmsActions.getAuthTokenByRoomCode({ roomCode: code, userId }, { endpoint: authTokenByRoomCodeEndpoint })
50
- : () => getToken(tokenEndpoint, uuid(), userRole, urlRoomId);
51
-
52
- getTokenFn()
53
- .then(token => {
54
- setAuthTokenInAppData(token);
55
- })
56
- .catch(error => {
57
- setError(convertError(error));
58
- });
59
- }, [
60
- hmsActions,
61
- tokenEndpoint,
62
- urlRoomId,
63
- urlRoomCode,
64
- userRole,
65
- authToken,
66
- authTokenByRoomCodeEndpoint,
67
- setAuthTokenInAppData,
68
- roomCode,
69
- userId,
70
- ]);
35
+ hmsActions
36
+ .getAuthTokenByRoomCode({ roomCode, userId }, { endpoint: authTokenByRoomCodeEndpoint })
37
+ .then(token => setAuthTokenInAppData(token))
38
+ .catch(error => setError(convertError(error)));
39
+ }, [hmsActions, tokenEndpoint, authToken, authTokenByRoomCodeEndpoint, setAuthTokenInAppData, roomCode, userId]);
71
40
 
72
41
  if (error.title) {
73
42
  return <ErrorDialog title={error.title}>{error.body}</ErrorDialog>;
@@ -1,4 +1,5 @@
1
1
  import React, { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { useMedia } from 'react-use';
2
3
  import {
3
4
  HMSNotificationTypes,
4
5
  selectHMSMessagesCount,
@@ -13,31 +14,36 @@ import { ChevronDownIcon, CrossIcon, PinIcon } from '@100mslive/react-icons';
13
14
  import { Button } from '../../../Button';
14
15
  import { Box, Flex } from '../../../Layout';
15
16
  import { Text } from '../../../Text';
16
- import IconButton from '../../IconButton';
17
+ import { config as cssConfig } from '../../../Theme';
17
18
  import { AnnotisedMessage, ChatBody } from './ChatBody';
18
19
  import { ChatFooter } from './ChatFooter';
19
- import { ChatHeader } from './ChatHeader';
20
+ import { ChatParticipantHeader } from './ChatParticipantHeader';
20
21
  import { useSetSubscribedChatSelector } from '../AppData/useUISettings';
21
22
  import { useSetPinnedMessage } from '../hooks/useSetPinnedMessage';
22
23
  import { useUnreadCount } from './useUnreadCount';
23
24
  import { CHAT_SELECTOR, SESSION_STORE_KEY } from '../../common/constants';
24
25
 
26
+ const PINNED_MESSAGE_LENGTH = 80;
27
+
25
28
  const PinnedMessage = ({ clearPinnedMessage }) => {
26
29
  const permissions = useHMSStore(selectPermissions);
27
30
  const pinnedMessage = useHMSStore(selectSessionStore(SESSION_STORE_KEY.PINNED_MESSAGE));
31
+ const formattedPinnedMessage =
32
+ pinnedMessage?.length && pinnedMessage.length > PINNED_MESSAGE_LENGTH
33
+ ? `${pinnedMessage.slice(0, PINNED_MESSAGE_LENGTH)}...`
34
+ : pinnedMessage;
28
35
 
29
36
  return pinnedMessage ? (
30
37
  <Flex
31
- css={{ p: '$8', color: '$on_surface_medium', bg: '$surface_bright', r: '$1' }}
38
+ title={pinnedMessage}
39
+ css={{ p: '$4', color: '$on_surface_medium', bg: '$surface_default', r: '$1', gap: '$4', mb: '$8', mt: '$8' }}
32
40
  align="center"
33
41
  justify="between"
34
42
  >
35
- <Box>
36
- <PinIcon />
37
- </Box>
43
+ <PinIcon />
44
+
38
45
  <Box
39
46
  css={{
40
- ml: '$8',
41
47
  color: '$on_surface_medium',
42
48
  w: '100%',
43
49
  maxHeight: '$18',
@@ -45,19 +51,22 @@ const PinnedMessage = ({ clearPinnedMessage }) => {
45
51
  }}
46
52
  >
47
53
  <Text variant="sm">
48
- <AnnotisedMessage message={pinnedMessage} />
54
+ <AnnotisedMessage message={formattedPinnedMessage} />
49
55
  </Text>
50
56
  </Box>
51
57
  {permissions.removeOthers && (
52
- <IconButton onClick={() => clearPinnedMessage()}>
58
+ <Flex
59
+ onClick={() => clearPinnedMessage()}
60
+ css={{ cursor: 'pointer', color: '$on_surface_medium', '&:hover': { color: '$on_surface_high' } }}
61
+ >
53
62
  <CrossIcon />
54
- </IconButton>
63
+ </Flex>
55
64
  )}
56
65
  </Flex>
57
66
  ) : null;
58
67
  };
59
68
 
60
- export const Chat = () => {
69
+ export const Chat = ({ screenType }) => {
61
70
  const notification = useHMSNotifications(HMSNotificationTypes.PEER_LEFT);
62
71
  const [peerSelector, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.PEER_ID);
63
72
  const [roleSelector, setRoleSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.ROLE);
@@ -83,6 +92,7 @@ export const Chat = () => {
83
92
  }, [notification, peerSelector, setPeerSelector]);
84
93
 
85
94
  const storeMessageSelector = selectHMSMessagesCount;
95
+ const isMobile = useMedia(cssConfig.media.md);
86
96
 
87
97
  const messagesCount = useHMSStore(storeMessageSelector) || 0;
88
98
  const scrollToBottom = useCallback(
@@ -99,10 +109,26 @@ export const Chat = () => {
99
109
  );
100
110
 
101
111
  return (
102
- <Flex direction="column" css={{ size: '100%' }}>
103
- <ChatHeader
104
- selectorOpen={isSelectorOpen}
112
+ <Flex direction="column" css={{ size: '100%', gap: '$4' }}>
113
+ {!isMobile ? (
114
+ <>
115
+ <ChatParticipantHeader selectorOpen={isSelectorOpen} onToggle={() => setSelectorOpen(value => !value)} />
116
+ <PinnedMessage clearPinnedMessage={setPinnedMessage} />
117
+ </>
118
+ ) : null}
119
+
120
+ <ChatBody
121
+ role={chatOptions.role}
122
+ peerId={chatOptions.peerId}
123
+ ref={listRef}
124
+ scrollToBottom={scrollToBottom}
125
+ screenType={screenType}
126
+ />
127
+ <ChatFooter
128
+ role={chatOptions.role}
129
+ onSend={() => scrollToBottom(1)}
105
130
  selection={chatOptions.selection}
131
+ screenType={screenType}
106
132
  onSelect={({ role, peerId, selection }) => {
107
133
  setChatOptions({
108
134
  role,
@@ -112,16 +138,8 @@ export const Chat = () => {
112
138
  setPeerSelector(peerId);
113
139
  setRoleSelector(role);
114
140
  }}
115
- role={chatOptions.role}
116
141
  peerId={chatOptions.peerId}
117
- onToggle={() => {
118
- setSelectorOpen(value => !value);
119
- }}
120
- />
121
- <PinnedMessage clearPinnedMessage={setPinnedMessage} />
122
-
123
- <ChatBody role={chatOptions.role} peerId={chatOptions.peerId} ref={listRef} scrollToBottom={scrollToBottom} />
124
- <ChatFooter role={chatOptions.role} peerId={chatOptions.peerId} onSend={() => scrollToBottom(1)}>
142
+ >
125
143
  {!isSelectorOpen && (
126
144
  <NewMessageIndicator role={chatOptions.role} peerId={chatOptions.peerId} scrollToBottom={scrollToBottom} />
127
145
  )}
@@ -146,13 +164,26 @@ const NewMessageIndicator = ({ role, peerId, scrollToBottom }) => {
146
164
  }}
147
165
  >
148
166
  <Button
167
+ variant="standard"
149
168
  onClick={() => {
150
169
  scrollToBottom(unreadCount);
151
170
  }}
152
- css={{ p: '$2 $4', '& > svg': { ml: '$4' } }}
171
+ icon
172
+ css={{
173
+ p: '$4',
174
+ pl: '$8',
175
+ pr: '$6',
176
+ '& > svg': { ml: '$4' },
177
+ borderRadius: '$round',
178
+ position: 'relative',
179
+ bottom: '$16',
180
+ fontSize: '$xs',
181
+ fontWeight: '$semiBold',
182
+ c: '$on_secondary_high',
183
+ }}
153
184
  >
154
- New Messages
155
- <ChevronDownIcon width={16} height={16} />
185
+ New {unreadCount === 1 ? 'message' : 'messages'}
186
+ <ChevronDownIcon />
156
187
  </Button>
157
188
  </Flex>
158
189
  );
@@ -1,5 +1,6 @@
1
- import React, { Fragment, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
1
+ import React, { Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
2
2
  import { useInView } from 'react-intersection-observer';
3
+ import { useMedia } from 'react-use';
3
4
  import AutoSizer from 'react-virtualized-auto-sizer';
4
5
  import { VariableSizeList } from 'react-window';
5
6
  import {
@@ -13,13 +14,15 @@ import {
13
14
  useHMSActions,
14
15
  useHMSStore,
15
16
  } from '@100mslive/react-sdk';
16
- import { HorizontalMenuIcon, PinIcon } from '@100mslive/react-icons';
17
+ import { CopyIcon, PinIcon, VerticalMenuIcon } from '@100mslive/react-icons';
17
18
  import { Dropdown } from '../../../Dropdown';
18
19
  import { IconButton } from '../../../IconButton';
19
20
  import { Box, Flex } from '../../../Layout';
20
21
  import { Text } from '../../../Text';
21
- import { styled } from '../../../Theme';
22
+ import { config as cssConfig, styled } from '../../../Theme';
22
23
  import { Tooltip } from '../../../Tooltip';
24
+ import emptyChat from '../../images/empty-chat.svg';
25
+ import { ToastManager } from '../Toast/ToastManager';
23
26
  import { useSetPinnedMessage } from '../hooks/useSetPinnedMessage';
24
27
 
25
28
  const formatTime = date => {
@@ -46,7 +49,7 @@ const MessageTypeContainer = ({ left, right }) => {
46
49
  ml: 'auto',
47
50
  mr: '$4',
48
51
  p: '$2 $4',
49
- border: '1px solid $on_surface_low',
52
+ border: '1px solid $border_bright',
50
53
  r: '$0',
51
54
  }}
52
55
  >
@@ -55,9 +58,9 @@ const MessageTypeContainer = ({ left, right }) => {
55
58
  {left}
56
59
  </SenderName>
57
60
  )}
58
- {left && right && <Box css={{ borderLeft: '1px solid $on_surface_low', mx: '$4', h: '$8' }} />}
61
+ {left && right && <Box css={{ borderLeft: '1px solid $border_bright', mx: '$4', h: '$8' }} />}
59
62
  {right && (
60
- <SenderName as="span" variant="tiny">
63
+ <SenderName as="span" variant="tiny" css={{ textTransform: 'uppercase' }}>
61
64
  {right}
62
65
  </SenderName>
63
66
  )}
@@ -123,16 +126,19 @@ const getMessageType = ({ roles, receiver }) => {
123
126
  }
124
127
  return receiver ? 'private' : '';
125
128
  };
126
-
127
- const ChatActions = ({ onPin }) => {
129
+ const ChatActions = ({ onPin, showPinAction, messageContent }) => {
128
130
  const [open, setOpen] = useState(false);
131
+ const isMobile = useMedia(cssConfig.media.md);
132
+ if (!isMobile && !showPinAction) {
133
+ return null;
134
+ }
129
135
 
130
136
  return (
131
137
  <Dropdown.Root open={open} onOpenChange={setOpen}>
132
- <Dropdown.Trigger asChild>
138
+ <Dropdown.Trigger className="chat_actions" css={{ opacity: open ? 1 : 0, '@md': { opacity: 1 } }} asChild>
133
139
  <IconButton>
134
140
  <Tooltip title="More options">
135
- <HorizontalMenuIcon />
141
+ <VerticalMenuIcon />
136
142
  </Tooltip>
137
143
  </IconButton>
138
144
  </Dropdown.Trigger>
@@ -140,7 +146,7 @@ const ChatActions = ({ onPin }) => {
140
146
  <Dropdown.Content
141
147
  sideOffset={5}
142
148
  align="end"
143
- css={{ width: '$48', backgroundColor: '$surface_bright', py: '$0' }}
149
+ css={{ width: '$48', backgroundColor: '$surface_bright', py: '$0', border: '1px solid $border_bright' }}
144
150
  >
145
151
  <Dropdown.Item data-testid="pin_message_btn" onClick={onPin}>
146
152
  <PinIcon />
@@ -148,6 +154,30 @@ const ChatActions = ({ onPin }) => {
148
154
  Pin Message
149
155
  </Text>
150
156
  </Dropdown.Item>
157
+ {isMobile && showPinAction ? <Dropdown.ItemSeparator css={{ my: 0 }} /> : null}
158
+ {isMobile ? (
159
+ <Dropdown.Item
160
+ data-testid="copy_message_btn"
161
+ onClick={() => {
162
+ try {
163
+ navigator?.clipboard.writeText(messageContent);
164
+ ToastManager.addToast({
165
+ title: 'Message copied successfully',
166
+ });
167
+ } catch (e) {
168
+ console.log(e);
169
+ ToastManager.addToast({
170
+ title: 'Could not copy message',
171
+ });
172
+ }
173
+ }}
174
+ >
175
+ <CopyIcon />
176
+ <Text variant="sm" css={{ ml: '$4' }}>
177
+ Copy Message
178
+ </Text>
179
+ </Dropdown.Item>
180
+ ) : null}
151
181
  </Dropdown.Content>
152
182
  </Dropdown.Portal>
153
183
  </Dropdown.Root>
@@ -160,6 +190,8 @@ const SenderName = styled(Text, {
160
190
  whiteSpace: 'nowrap',
161
191
  maxWidth: '24ch',
162
192
  minWidth: 0,
193
+ color: '$on_surface_high',
194
+ fontWeight: '$semiBold',
163
195
  });
164
196
 
165
197
  const ChatMessage = React.memo(({ index, style = {}, message, setRowHeight, onPin }) => {
@@ -170,6 +202,7 @@ const ChatMessage = React.memo(({ index, style = {}, message, setRowHeight, onPi
170
202
  setRowHeight(index, rowRef.current.clientHeight);
171
203
  }
172
204
  }, [index, setRowHeight]);
205
+ const isMobile = useMedia(cssConfig.media.md);
173
206
 
174
207
  const hmsActions = useHMSActions();
175
208
  const localPeerId = useHMSStore(selectLocalPeerID);
@@ -188,13 +221,19 @@ const ChatMessage = React.memo(({ index, style = {}, message, setRowHeight, onPi
188
221
  }, [message.read, hmsActions, inView, message.id]);
189
222
 
190
223
  return (
191
- <Box ref={ref} as="div" css={{ mb: '$10', pr: '$10' }} style={style}>
224
+ <Box
225
+ ref={ref}
226
+ as="div"
227
+ css={{ mb: '$10', pr: '$10', mt: '$8', '&:hover .chat_actions': { opacity: 1 } }}
228
+ style={style}
229
+ >
192
230
  <Flex
193
231
  ref={rowRef}
194
232
  align="center"
195
233
  css={{
196
234
  flexWrap: 'wrap',
197
- bg: messageType ? '$surface_bright' : undefined,
235
+ // Theme independent color, token should not be used for transparent chat
236
+ bg: messageType ? (isMobile ? 'rgba(0, 0, 0, 0.64)' : '$surface_default') : undefined,
198
237
  r: messageType ? '$1' : undefined,
199
238
  px: messageType ? '$4' : '$2',
200
239
  py: messageType ? '$4' : 0,
@@ -214,32 +253,40 @@ const ChatMessage = React.memo(({ index, style = {}, message, setRowHeight, onPi
214
253
  }}
215
254
  as="div"
216
255
  >
217
- <Flex align="center">
256
+ <Flex align="baseline">
218
257
  {message.senderName === 'You' || !message.senderName ? (
219
- <SenderName as="span">{message.senderName || 'Anonymous'}</SenderName>
258
+ <SenderName as="span" variant="sm">
259
+ {message.senderName || 'Anonymous'}
260
+ </SenderName>
220
261
  ) : (
221
262
  <Tooltip title={message.senderName} side="top" align="start">
222
- <SenderName as="span">{message.senderName}</SenderName>
263
+ <SenderName as="span" variant="sm">
264
+ {message.senderName}
265
+ </SenderName>
223
266
  </Tooltip>
224
267
  )}
225
- <Text
226
- as="span"
227
- variant="sm"
228
- css={{
229
- ml: '$4',
230
- color: '$on_primary_medium',
231
- flexShrink: 0,
232
- }}
233
- >
234
- {formatTime(message.time)}
235
- </Text>
268
+ {!isMobile ? (
269
+ <Text
270
+ as="span"
271
+ variant="xs"
272
+ css={{
273
+ ml: '$4',
274
+ color: '$on_primary_medium',
275
+ flexShrink: 0,
276
+ }}
277
+ >
278
+ {formatTime(message.time)}
279
+ </Text>
280
+ ) : null}
236
281
  </Flex>
237
282
  <MessageType
238
283
  hasCurrentUserSent={message.sender === localPeerId}
239
284
  receiver={message.recipientPeer}
240
285
  roles={message.recipientRoles}
241
286
  />
242
- {showPinAction && <ChatActions onPin={onPin} />}
287
+ {!isMobile ? (
288
+ <ChatActions onPin={onPin} showPinAction={showPinAction} messageContent={message.message} />
289
+ ) : null}
243
290
  </Text>
244
291
  <Text
245
292
  variant="body2"
@@ -345,21 +392,34 @@ export const ChatBody = React.forwardRef(({ role, peerId, scrollToBottom }, list
345
392
  : peerId
346
393
  ? selectMessagesByPeerID(peerId)
347
394
  : selectHMSMessages;
348
- const messages = useHMSStore(storeMessageSelector) || [];
395
+ let messages = useHMSStore(storeMessageSelector);
396
+ messages = useMemo(() => messages?.filter(message => message.type === 'chat') || [], [messages]);
397
+ const isMobile = useMedia(cssConfig.media.md);
349
398
 
350
- if (messages.length === 0) {
399
+ if (messages.length === 0 && !isMobile) {
351
400
  return (
352
401
  <Flex
353
402
  css={{
354
403
  width: '100%',
355
- height: '100%',
404
+ flex: '1 1 0',
356
405
  textAlign: 'center',
357
406
  px: '$4',
358
407
  }}
359
408
  align="center"
360
409
  justify="center"
361
410
  >
362
- <Text>There are no messages here</Text>
411
+ <Box>
412
+ <img src={emptyChat} alt="Empty Chat" height={132} width={185} style={{ margin: '0 auto' }} />
413
+ <Text variant="h5" css={{ mt: '$8', c: '$on_surface_high' }}>
414
+ Start a conversation
415
+ </Text>
416
+ <Text
417
+ variant="sm"
418
+ css={{ mt: '$4', maxWidth: '80%', textAlign: 'center', mx: 'auto', c: '$on_surface_medium' }}
419
+ >
420
+ There are no messages here yet. Start a conversation by sending a message.
421
+ </Text>
422
+ </Box>
363
423
  </Flex>
364
424
  );
365
425
  }
@@ -1,10 +1,12 @@
1
1
  import React, { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { useMedia } from 'react-use';
2
3
  import data from '@emoji-mart/data';
3
4
  import Picker from '@emoji-mart/react';
4
5
  import { useHMSActions } from '@100mslive/react-sdk';
5
6
  import { EmojiIcon, SendIcon } from '@100mslive/react-icons';
6
- import { Box, Flex, IconButton, Popover, styled } from '../../../';
7
+ import { Box, config as cssConfig, Flex, IconButton as BaseIconButton, Popover, styled } from '../../../';
7
8
  import { ToastManager } from '../Toast/ToastManager';
9
+ // import { ChatSelectorContainer } from './ChatSelectorContainer';
8
10
  import { useChatDraftMessage } from '../AppData/useChatState';
9
11
  import { useEmojiPickerStyles } from './useEmojiPickerStyles';
10
12
 
@@ -32,9 +34,9 @@ function EmojiPicker({ onSelect }) {
32
34
  return (
33
35
  <Popover.Root open={showEmoji} onOpenChange={setShowEmoji}>
34
36
  <Popover.Trigger asChild css={{ appearance: 'none' }}>
35
- <IconButton as="div">
37
+ <BaseIconButton as="div">
36
38
  <EmojiIcon />
37
- </IconButton>
39
+ </BaseIconButton>
38
40
  </Popover.Trigger>
39
41
  <Popover.Portal>
40
42
  <Popover.Content
@@ -60,10 +62,11 @@ function EmojiPicker({ onSelect }) {
60
62
  );
61
63
  }
62
64
 
63
- export const ChatFooter = ({ role, peerId, onSend, children }) => {
65
+ export const ChatFooter = ({ role, peerId, onSend, children /* onSelect, selection, screenType */ }) => {
64
66
  const hmsActions = useHMSActions();
65
67
  const inputRef = useRef(null);
66
68
  const [draftMessage, setDraftMessage] = useChatDraftMessage();
69
+ const isMobile = useMedia(cssConfig.media.md);
67
70
 
68
71
  const sendMessage = useCallback(async () => {
69
72
  const message = inputRef.current.value;
@@ -102,49 +105,70 @@ export const ChatFooter = ({ role, peerId, onSend, children }) => {
102
105
  }, [setDraftMessage]);
103
106
 
104
107
  return (
105
- <Flex
106
- align="center"
107
- css={{
108
- bg: '$surface_bright',
109
- minHeight: '$16',
110
- maxHeight: '$24',
111
- position: 'relative',
112
- py: '$6',
113
- pl: '$8',
114
- r: '$1',
115
- }}
116
- >
117
- {children}
118
- <TextArea
119
- placeholder="Write something here"
120
- ref={inputRef}
121
- autoFocus
122
- onKeyPress={async event => {
123
- if (event.key === 'Enter') {
124
- if (!event.shiftKey) {
125
- event.preventDefault();
126
- await sendMessage();
127
- }
128
- }
129
- }}
130
- autoComplete="off"
131
- aria-autocomplete="none"
132
- onPaste={e => e.stopPropagation()}
133
- onCut={e => e.stopPropagation()}
134
- onCopy={e => e.stopPropagation()}
135
- />
136
- <EmojiPicker
137
- onSelect={emoji => {
138
- inputRef.current.value += ` ${emoji.native} `;
139
- }}
140
- />
141
- <IconButton
142
- onClick={sendMessage}
143
- css={{ ml: 'auto', height: 'max-content', mr: '$4' }}
144
- data-testid="send_msg_btn"
145
- >
146
- <SendIcon />
147
- </IconButton>
148
- </Flex>
108
+ <>
109
+ {/* {screenType !== 'hls_live_streaming' ? (
110
+ <ChatSelectorContainer onSelect={onSelect} role={role} peerId={peerId} selection={selection} />
111
+ ) : null} */}
112
+ <Flex align="center" css={{ gap: '$4', w: '100%' }}>
113
+ <Flex
114
+ align="center"
115
+ css={{
116
+ bg: isMobile ? '$surface_dim' : '$surface_default',
117
+ minHeight: '$16',
118
+ maxHeight: '$24',
119
+ position: 'relative',
120
+ py: '$6',
121
+ pl: '$8',
122
+ flexGrow: 1,
123
+ r: '$1',
124
+ '@md': {
125
+ minHeight: 'unset',
126
+ h: '$14',
127
+ boxSizing: 'border-box',
128
+ },
129
+ }}
130
+ >
131
+ {children}
132
+ <TextArea
133
+ placeholder="Send a message...."
134
+ ref={inputRef}
135
+ autoFocus
136
+ onKeyPress={async event => {
137
+ if (event.key === 'Enter') {
138
+ if (!event.shiftKey) {
139
+ event.preventDefault();
140
+ await sendMessage();
141
+ }
142
+ }
143
+ }}
144
+ autoComplete="off"
145
+ aria-autocomplete="none"
146
+ onPaste={e => e.stopPropagation()}
147
+ onCut={e => e.stopPropagation()}
148
+ onCopy={e => e.stopPropagation()}
149
+ />
150
+ {!isMobile ? (
151
+ <EmojiPicker
152
+ onSelect={emoji => {
153
+ inputRef.current.value += ` ${emoji.native} `;
154
+ }}
155
+ />
156
+ ) : null}
157
+ <BaseIconButton
158
+ onClick={sendMessage}
159
+ css={{
160
+ ml: 'auto',
161
+ height: 'max-content',
162
+ mr: '$4',
163
+ color: '$on_surface_low',
164
+ '&:hover': { c: '$on_surface_high' },
165
+ }}
166
+ data-testid="send_msg_btn"
167
+ >
168
+ <SendIcon />
169
+ </BaseIconButton>
170
+ </Flex>
171
+ </Flex>
172
+ </>
149
173
  );
150
174
  };