@100mslive/roomkit-react 0.3.10-alpha.0 → 0.3.10-alpha.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. package/dist/{HLSView-5GXP76IN.js → HLSView-73GDHCD4.js} +2 -2
  2. package/dist/{HLSView-FBGVUTA5.css → HLSView-NUX3NEDM.css} +16 -3
  3. package/dist/{HLSView-FBGVUTA5.css.map → HLSView-NUX3NEDM.css.map} +3 -3
  4. package/dist/Prebuilt/common/constants.d.ts +1 -0
  5. package/dist/Prebuilt/components/AppData/useSidepaneResetOnLayoutUpdate.d.ts +3 -0
  6. package/dist/Prebuilt/components/Chat/Chat.d.ts +1 -1
  7. package/dist/Prebuilt/components/RoleChangeModal.d.ts +5 -0
  8. package/dist/Prebuilt/components/TileMenu/TileMenuContent.d.ts +2 -1
  9. package/dist/{chunk-WSDBUVSZ.js → chunk-K7LIJG5P.js} +610 -563
  10. package/dist/chunk-K7LIJG5P.js.map +7 -0
  11. package/dist/index.cjs.css +15 -2
  12. package/dist/index.cjs.css.map +3 -3
  13. package/dist/index.cjs.js +1949 -1894
  14. package/dist/index.cjs.js.map +4 -4
  15. package/dist/index.css +15 -2
  16. package/dist/index.css.map +3 -3
  17. package/dist/index.js +1 -1
  18. package/dist/meta.cjs.json +136 -62
  19. package/dist/meta.esbuild.json +150 -76
  20. package/package.json +7 -7
  21. package/src/Modal/DialogContent.tsx +1 -1
  22. package/src/Prebuilt/common/constants.ts +2 -0
  23. package/src/Prebuilt/components/AppData/useSidepaneResetOnLayoutUpdate.tsx +22 -0
  24. package/src/Prebuilt/components/AudioVideoToggle.tsx +1 -1
  25. package/src/Prebuilt/components/Chat/Chat.tsx +3 -4
  26. package/src/Prebuilt/components/Footer/ParticipantList.tsx +58 -37
  27. package/src/Prebuilt/components/RoleChangeModal.tsx +188 -0
  28. package/src/Prebuilt/components/TileMenu/TileMenu.tsx +5 -0
  29. package/src/Prebuilt/components/TileMenu/TileMenuContent.tsx +25 -1
  30. package/src/Prebuilt/components/VirtualBackground/VBPicker.tsx +3 -0
  31. package/src/Prebuilt/layouts/SidePane.tsx +9 -9
  32. package/dist/chunk-WSDBUVSZ.js.map +0 -7
  33. package/src/Prebuilt/components/RoleChangeModal.jsx +0 -185
  34. /package/dist/{HLSView-5GXP76IN.js.map → HLSView-73GDHCD4.js.map} +0 -0
@@ -15,8 +15,9 @@ import { ChatFooter } from './ChatFooter';
15
15
  import { ChatBlocked, ChatPaused } from './ChatStates';
16
16
  import { PinnedMessage } from './PinnedMessage';
17
17
  import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
18
+ import { useSidepaneResetOnLayoutUpdate } from '../AppData/useSidepaneResetOnLayoutUpdate';
18
19
  import { useLandscapeHLSStream, useMobileHLSStream } from '../../common/hooks';
19
- import { SESSION_STORE_KEY } from '../../common/constants';
20
+ import { SESSION_STORE_KEY, SIDE_PANE_OPTIONS } from '../../common/constants';
20
21
 
21
22
  export const Chat = () => {
22
23
  const { elements } = useRoomLayoutConferencingScreen();
@@ -27,6 +28,7 @@ export const Chat = () => {
27
28
  const isMobile = useMedia(cssConfig.media.md);
28
29
  const isMobileHLSStream = useMobileHLSStream();
29
30
  const isLandscapeStream = useLandscapeHLSStream();
31
+ useSidepaneResetOnLayoutUpdate('chat', SIDE_PANE_OPTIONS.CHAT);
30
32
 
31
33
  const scrollToBottom = useCallback(
32
34
  (unreadCount = 0) => {
@@ -42,9 +44,6 @@ export const Chat = () => {
42
44
  [hmsActions, vanillaStore],
43
45
  );
44
46
 
45
- if (!elements?.chat) {
46
- return null;
47
- }
48
47
  const streaming = isMobileHLSStream || isLandscapeStream;
49
48
 
50
49
  return (
@@ -4,6 +4,7 @@ import {
4
4
  HMSPeer,
5
5
  HMSPeerType,
6
6
  HMSRoleName,
7
+ selectAvailableRoleNames,
7
8
  selectHandRaisedPeers,
8
9
  selectHasPeerHandRaised,
9
10
  selectIsLargeRoom,
@@ -21,6 +22,7 @@ import {
21
22
  HandIcon,
22
23
  MicOffIcon,
23
24
  PeopleIcon,
25
+ PersonSettingsIcon,
24
26
  SearchIcon,
25
27
  VerticalMenuIcon,
26
28
  } from '@100mslive/react-icons';
@@ -29,10 +31,12 @@ import { Accordion, Box, Button, config as cssConfig, Dropdown, Flex, Input, Tex
29
31
  import IconButton from '../../IconButton';
30
32
  import { ConnectionIndicator } from '../Connection/ConnectionIndicator';
31
33
  import { RemoveParticipant } from '../RemoveParticipant';
34
+ import { RoleChangeModal } from '../RoleChangeModal';
32
35
  import { RoleAccordion } from './RoleAccordion';
33
36
  import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
34
37
  // @ts-ignore: No implicit Any
35
38
  import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane';
39
+ import { useSidepaneResetOnLayoutUpdate } from '../AppData/useSidepaneResetOnLayoutUpdate';
36
40
  import { usePeerOnStageActions } from '../hooks/usePeerOnStageActions';
37
41
  import { useParticipants } from '../../common/hooks';
38
42
  // @ts-ignore: No implicit Any
@@ -71,6 +75,8 @@ export const ParticipantList = ({
71
75
  });
72
76
  }
73
77
 
78
+ useSidepaneResetOnLayoutUpdate('participant_list', SIDE_PANE_OPTIONS.PARTICIPANTS);
79
+
74
80
  const onSearch = useCallback((value: string) => {
75
81
  setFilter(filterValue => {
76
82
  if (!filterValue) {
@@ -365,45 +371,60 @@ const ParticipantMoreActions = ({ peerId, role }: { peerId: string; role: string
365
371
  isInStage,
366
372
  shouldShowStageRoleChange,
367
373
  } = usePeerOnStageActions({ peerId, role });
374
+ const canChangeRole = !!useHMSStore(selectPermissions)?.changeRole;
375
+ const [openRoleChangeModal, setOpenRoleChangeModal] = useState(false);
376
+ const roles = useHMSStore(selectAvailableRoleNames);
377
+
368
378
  return (
369
- <Dropdown.Root open={open} onOpenChange={value => setOpen(value)} modal={false}>
370
- <Dropdown.Trigger
371
- asChild
372
- data-testid="participant_more_actions"
373
- className="participant_item"
374
- css={{
375
- p: '$1',
376
- r: '$0',
377
- c: '$on_surface_high',
378
- display: open ? 'flex' : 'none',
379
- '&:hover': {
380
- bg: '$surface_bright',
381
- },
382
- '@md': {
383
- display: 'flex',
384
- },
385
- }}
386
- tabIndex={0}
387
- >
388
- <Box css={{ my: 'auto' }}>
389
- <VerticalMenuIcon />
390
- </Box>
391
- </Dropdown.Trigger>
392
- <Dropdown.Portal>
393
- <Dropdown.Content align="end" sideOffset={8} css={{ w: '$64', bg: '$surface_default' }}>
394
- {shouldShowStageRoleChange ? (
395
- <Dropdown.Item css={{ bg: '$surface_default' }} onClick={() => handleStageAction()}>
396
- <ChangeRoleIcon />
397
- <Text variant="sm" css={{ ml: '$4', fontWeight: '$semiBold', c: '$on_surface_high' }}>
398
- {isInStage ? remove_from_stage_label : bring_to_stage_label}
399
- </Text>
400
- </Dropdown.Item>
401
- ) : null}
379
+ <>
380
+ <Dropdown.Root open={open} onOpenChange={value => setOpen(value)} modal={false}>
381
+ <Dropdown.Trigger
382
+ asChild
383
+ data-testid="participant_more_actions"
384
+ className="participant_item"
385
+ css={{
386
+ p: '$1',
387
+ r: '$0',
388
+ c: '$on_surface_high',
389
+ display: open ? 'flex' : 'none',
390
+ '&:hover': {
391
+ bg: '$surface_bright',
392
+ },
393
+ '@md': {
394
+ display: 'flex',
395
+ },
396
+ }}
397
+ tabIndex={0}
398
+ >
399
+ <Box css={{ my: 'auto' }}>
400
+ <VerticalMenuIcon />
401
+ </Box>
402
+ </Dropdown.Trigger>
403
+ <Dropdown.Portal>
404
+ <Dropdown.Content align="end" sideOffset={8} css={{ w: '$64', bg: '$surface_default' }}>
405
+ {shouldShowStageRoleChange ? (
406
+ <Dropdown.Item css={{ bg: '$surface_default' }} onClick={() => handleStageAction()}>
407
+ <ChangeRoleIcon />
408
+ <Text variant="sm" css={{ ml: '$4', fontWeight: '$semiBold', c: '$on_surface_high' }}>
409
+ {isInStage ? remove_from_stage_label : bring_to_stage_label}
410
+ </Text>
411
+ </Dropdown.Item>
412
+ ) : null}
402
413
 
403
- <RemoveParticipant peerId={peerId} />
404
- </Dropdown.Content>
405
- </Dropdown.Portal>
406
- </Dropdown.Root>
414
+ {canChangeRole && roles.length > 1 ? (
415
+ <Dropdown.Item css={{ bg: '$surface_default' }} onClick={() => setOpenRoleChangeModal(true)}>
416
+ <PersonSettingsIcon />
417
+ <Text variant="sm" css={{ ml: '$4', fontWeight: '$semiBold', c: '$on_surface_high' }}>
418
+ Switch Role
419
+ </Text>
420
+ </Dropdown.Item>
421
+ ) : null}
422
+ <RemoveParticipant peerId={peerId} />
423
+ </Dropdown.Content>
424
+ </Dropdown.Portal>
425
+ </Dropdown.Root>
426
+ {openRoleChangeModal && <RoleChangeModal peerId={peerId} onOpenChange={setOpenRoleChangeModal} />}
427
+ </>
407
428
  );
408
429
  };
409
430
 
@@ -0,0 +1,188 @@
1
+ import React, { useRef, useState } from 'react';
2
+ import { useMedia } from 'react-use';
3
+ import { HMSPeer, selectAvailableRoleNames, selectPeerByID, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
4
+ import { ChevronDownIcon, ChevronUpIcon, CrossIcon } from '@100mslive/react-icons';
5
+ import { Button } from '../../Button';
6
+ import { Dropdown } from '../../Dropdown';
7
+ import { Box, Flex } from '../../Layout';
8
+ import { Dialog } from '../../Modal';
9
+ import { Sheet } from '../../Sheet';
10
+ import { Text } from '../../Text';
11
+ import { config as cssConfig } from '../../Theme';
12
+ import { Tooltip } from '../../Tooltip';
13
+
14
+ const HighlightTerm = ({ value }: { value: string | undefined }) => {
15
+ return value ? (
16
+ <Tooltip side="top" title={value}>
17
+ <Text
18
+ variant="body2"
19
+ css={{
20
+ color: '$on_surface_medium',
21
+ fontWeight: '$semiBold',
22
+ }}
23
+ >
24
+ '{value.slice(0, 100)}
25
+ {value.length > 100 ? '...' : ''}'
26
+ </Text>
27
+ </Tooltip>
28
+ ) : (
29
+ <></>
30
+ );
31
+ };
32
+
33
+ const RoleChangeContent = ({
34
+ peer,
35
+ onOpenChange,
36
+ isMobile = false,
37
+ }: {
38
+ peer: HMSPeer;
39
+ onOpenChange: (open: boolean) => void;
40
+ isMobile?: boolean;
41
+ }) => {
42
+ const roles = useHMSStore(selectAvailableRoleNames).filter(
43
+ role => role !== peer?.roleName && role !== '__internal_recorder',
44
+ );
45
+ const [selectedRole, setRole] = useState(roles.filter(role => role !== peer?.roleName)?.[0] || peer?.roleName);
46
+ const hmsActions = useHMSActions();
47
+ const [open, setOpen] = useState(false);
48
+ const triggerRef = useRef<HTMLButtonElement | undefined>();
49
+
50
+ return (
51
+ <>
52
+ <Flex align="center" justify="between" css={{ w: '100%' }}>
53
+ <Text as="h6" variant="h6">
54
+ Switch Role
55
+ </Text>
56
+ {isMobile && <CrossIcon onClick={() => onOpenChange(false)} />}
57
+ </Flex>
58
+
59
+ <Box>
60
+ <Text
61
+ variant="sm"
62
+ css={{
63
+ mt: '$4',
64
+ mb: '$8',
65
+ c: '$on_surface_medium',
66
+ display: 'flex',
67
+ flexWrap: 'wrap',
68
+ columnGap: '4px',
69
+ }}
70
+ >
71
+ Switch the role of
72
+ <HighlightTerm value={peer.name} />
73
+ from <HighlightTerm value={peer.roleName} /> to
74
+ </Text>
75
+ </Box>
76
+ <Flex
77
+ align="center"
78
+ css={{
79
+ w: '100%',
80
+ mb: '$10',
81
+ }}
82
+ >
83
+ <Box
84
+ css={{
85
+ position: 'relative',
86
+ flex: '1 1 0',
87
+ minWidth: 0,
88
+ }}
89
+ >
90
+ <Dropdown.Root open={open} onOpenChange={setOpen} css={{ width: '100%' }}>
91
+ <Dropdown.Trigger
92
+ // @ts-ignore
93
+ ref={triggerRef}
94
+ data-testid="open_role_selection_dropdown"
95
+ asChild
96
+ css={{
97
+ bg: '$surface_default',
98
+ r: '$1',
99
+ p: '$6 $9',
100
+ }}
101
+ >
102
+ <Flex align="center" justify="between" css={{ width: '100%' }}>
103
+ <Text>{selectedRole}</Text>
104
+ {open ? <ChevronUpIcon /> : <ChevronDownIcon />}
105
+ </Flex>
106
+ </Dropdown.Trigger>
107
+
108
+ <Dropdown.Content align="start" sideOffset={8} css={{ zIndex: 1000, w: '100%' }}>
109
+ {roles.map(role => (
110
+ <Dropdown.Item
111
+ data-testid={role}
112
+ key={role}
113
+ onSelect={() => setRole(role)}
114
+ css={{ w: `${triggerRef.current?.clientWidth}px` }}
115
+ >
116
+ {role}
117
+ </Dropdown.Item>
118
+ ))}
119
+ </Dropdown.Content>
120
+ </Dropdown.Root>
121
+ </Box>
122
+ </Flex>
123
+ <Flex justify="center" align="center" css={{ width: '100%', gap: '$md' }}>
124
+ {!isMobile && (
125
+ <Button
126
+ variant="standard"
127
+ outlined
128
+ css={{ width: '100%' }}
129
+ onClick={() => onOpenChange(false)}
130
+ data-testid="cancel_button"
131
+ >
132
+ Cancel
133
+ </Button>
134
+ )}
135
+
136
+ <Button
137
+ data-testid="change_button"
138
+ variant="primary"
139
+ css={{ width: '100%' }}
140
+ onClick={async () => {
141
+ if (selectedRole) {
142
+ await hmsActions.changeRoleOfPeer(peer.id, selectedRole, true);
143
+ onOpenChange(false);
144
+ }
145
+ }}
146
+ >
147
+ Switch Role
148
+ </Button>
149
+ </Flex>
150
+ </>
151
+ );
152
+ };
153
+
154
+ export const RoleChangeModal = ({
155
+ peerId,
156
+ onOpenChange,
157
+ }: {
158
+ peerId: string;
159
+ onOpenChange: (open: boolean) => void;
160
+ }) => {
161
+ const peer = useHMSStore(selectPeerByID(peerId));
162
+ const isMobile = useMedia(cssConfig.media.md);
163
+
164
+ if (!peer) {
165
+ return null;
166
+ }
167
+
168
+ if (isMobile) {
169
+ return (
170
+ <Sheet.Root open={true} onOpenChange={onOpenChange} css={{ borderRadius: '$0 $0 0 0' }}>
171
+ <Sheet.Content css={{ p: '$10 $8', background: '$surface_dim', border: '1px solid $border_default' }}>
172
+ <RoleChangeContent peer={peer} onOpenChange={onOpenChange} isMobile />
173
+ </Sheet.Content>
174
+ </Sheet.Root>
175
+ );
176
+ }
177
+
178
+ return (
179
+ <Dialog.Root defaultOpen onOpenChange={onOpenChange}>
180
+ <Dialog.Portal>
181
+ <Dialog.Overlay />
182
+ <Dialog.Content css={{ width: 'min(400px,80%)', p: '$10', overflow: 'visible' }}>
183
+ <RoleChangeContent peer={peer} onOpenChange={onOpenChange} />
184
+ </Dialog.Content>
185
+ </Dialog.Portal>
186
+ </Dialog.Root>
187
+ );
188
+ };
@@ -17,6 +17,7 @@ import { Text } from '../../../Text';
17
17
  import { config as cssConfig, useTheme } from '../../../Theme';
18
18
  import { StyledMenuTile } from '../../../TileMenu';
19
19
  import { ChangeNameModal } from '../MoreSettings/ChangeNameModal';
20
+ import { RoleChangeModal } from '../RoleChangeModal';
20
21
  import { TileMenuContent } from './TileMenuContent';
21
22
  import { useDropdownList } from '../hooks/useDropdownList';
22
23
  import { getDragClassName } from './utils';
@@ -56,6 +57,7 @@ const TileMenu = ({
56
57
  const isMobile = useMedia(cssConfig.media.md);
57
58
  const peer = useHMSStore(selectPeerByID(peerID));
58
59
  const [showNameChangeModal, setShowNameChangeModal] = useState(false);
60
+ const [showRoleChangeModal, setShowRoleChangeModal] = useState(false);
59
61
  useDropdownList({ open, name: 'TileMenu' });
60
62
  const dragClassName = getDragClassName();
61
63
 
@@ -64,6 +66,7 @@ const TileMenu = ({
64
66
  }
65
67
 
66
68
  const openNameChangeModal = () => setShowNameChangeModal(true);
69
+ const openRoleChangeModal = () => setShowRoleChangeModal(true);
67
70
 
68
71
  const props = {
69
72
  isLocal,
@@ -76,6 +79,7 @@ const TileMenu = ({
76
79
  showPinAction,
77
80
  canMinimise,
78
81
  openNameChangeModal,
82
+ openRoleChangeModal,
79
83
  };
80
84
 
81
85
  return (
@@ -133,6 +137,7 @@ const TileMenu = ({
133
137
  )}
134
138
  </StyledMenuTile.Root>
135
139
  {showNameChangeModal && <ChangeNameModal onOpenChange={setShowNameChangeModal} />}
140
+ {showRoleChangeModal && <RoleChangeModal peerId={peerID} onOpenChange={setShowRoleChangeModal} />}
136
141
  </>
137
142
  );
138
143
  };
@@ -5,6 +5,7 @@ import {
5
5
  HMSSimulcastLayerDefinition,
6
6
  HMSTrackID,
7
7
  HMSVideoTrack,
8
+ selectAvailableRoleNames,
8
9
  selectPermissions,
9
10
  selectSessionStore,
10
11
  selectTrackByID,
@@ -17,6 +18,7 @@ import {
17
18
  MicOffIcon,
18
19
  MicOnIcon,
19
20
  PencilIcon,
21
+ PersonSettingsIcon,
20
22
  PinIcon,
21
23
  RemoveUserIcon,
22
24
  ShareScreenIcon,
@@ -224,6 +226,9 @@ export const TileMenuContent = ({
224
226
  openNameChangeModal = () => {
225
227
  return;
226
228
  },
229
+ openRoleChangeModal = () => {
230
+ return;
231
+ },
227
232
  }: {
228
233
  videoTrackID: string;
229
234
  audioTrackID: string;
@@ -235,11 +240,15 @@ export const TileMenuContent = ({
235
240
  canMinimise?: boolean;
236
241
  closeSheetOnClick?: () => void;
237
242
  openNameChangeModal?: () => void;
243
+ openRoleChangeModal?: () => void;
238
244
  }) => {
239
245
  const actions = useHMSActions();
240
246
  const dragClassName = getDragClassName();
241
- const removeOthers: boolean | undefined = useHMSStore(selectPermissions)?.removeOthers;
247
+ const permissions = useHMSStore(selectPermissions);
248
+ const canChangeRole = !!permissions?.changeRole;
249
+ const removeOthers = !!permissions?.removeOthers;
242
250
  const { userName } = useHMSPrebuiltContext();
251
+ const roles = useHMSStore(selectAvailableRoleNames);
243
252
 
244
253
  const { isAudioEnabled, isVideoEnabled, setVolume, toggleAudio, toggleVideo, volume } = useRemoteAVToggle(
245
254
  audioTrackID,
@@ -308,6 +317,21 @@ export const TileMenuContent = ({
308
317
  </StyledMenuTile.ItemButton>
309
318
  ) : null}
310
319
 
320
+ {canChangeRole && roles.length > 1 ? (
321
+ <StyledMenuTile.ItemButton
322
+ className={dragClassName}
323
+ css={spacingCSS}
324
+ onClick={() => {
325
+ openRoleChangeModal();
326
+ closeSheetOnClick();
327
+ }}
328
+ data-testid="change_role_btn"
329
+ >
330
+ <PersonSettingsIcon height={20} width={20} />
331
+ <span>Switch Role</span>
332
+ </StyledMenuTile.ItemButton>
333
+ ) : null}
334
+
311
335
  {audioTrackID ? (
312
336
  <StyledMenuTile.VolumeItem data-testid="participant_volume_slider" css={{ ...spacingCSS, mb: '$0' }}>
313
337
  <Flex align="center" gap={1}>
@@ -26,6 +26,7 @@ import { VBCollection } from './VBCollection';
26
26
  import { VBHandler } from './VBHandler';
27
27
  // @ts-ignore
28
28
  import { useSidepaneToggle } from '../AppData/useSidepane';
29
+ import { useSidepaneResetOnLayoutUpdate } from '../AppData/useSidepaneResetOnLayoutUpdate';
29
30
  // @ts-ignore
30
31
  import { useSetAppDataByKey, useUISettings } from '../AppData/useUISettings';
31
32
  import { APP_DATA, SIDE_PANE_OPTIONS, UI_SETTINGS } from '../../common/constants';
@@ -113,6 +114,8 @@ export const VBPicker = ({ backgroundMedia = [] }: { backgroundMedia: VirtualBac
113
114
  return () => setLoadingEffects(false);
114
115
  }, [isVideoOn, setLoadingEffects, toggleVB]);
115
116
 
117
+ useSidepaneResetOnLayoutUpdate('virtual_background', SIDE_PANE_OPTIONS.VB);
118
+
116
119
  return (
117
120
  <Flex css={{ pr: '$6', size: '100%' }} direction="column">
118
121
  <Flex align="center" justify="between" css={{ w: '100%', background: '$surface_dim', pb: '$4' }}>
@@ -141,14 +141,6 @@ const SidePane = ({
141
141
  ? preview_elements?.virtual_background?.background_media
142
142
  : elements?.virtual_background?.background_media || [];
143
143
 
144
- const resetSidePane = useSidepaneReset();
145
-
146
- useEffect(() => {
147
- return () => {
148
- resetSidePane();
149
- };
150
- }, [resetSidePane]);
151
-
152
144
  const tileLayout = {
153
145
  hideParticipantNameOnTile: tileProps?.hide_participant_name_on_tile,
154
146
  roundedVideoTile: tileProps?.rounded_video_tile,
@@ -199,7 +191,15 @@ const SidePane = ({
199
191
  return null;
200
192
  });
201
193
 
202
- if (!trackId && !SidepaneComponent) {
194
+ const resetSidePane = useSidepaneReset();
195
+
196
+ useEffect(() => {
197
+ return () => {
198
+ resetSidePane();
199
+ };
200
+ }, [resetSidePane]);
201
+
202
+ if (!SidepaneComponent && !trackId) {
203
203
  return null;
204
204
  }
205
205