@selfcommunity/react-ui 0.10.2-courses.116 → 0.10.2-courses.118

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.
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { BoxProps } from '@mui/material';
3
- import { SCCategoryType } from '@selfcommunity/types/src/index';
3
+ import { SCCategoryType } from '@selfcommunity/types';
4
4
  import { ComposerLayerProps } from '../../../../types/composer';
5
5
  export interface CategoryLayerProps extends Omit<BoxProps, 'defaultValue'>, ComposerLayerProps {
6
6
  defaultValue: SCCategoryType[];
@@ -6,6 +6,7 @@ const react_1 = tslib_1.__importStar(require("react"));
6
6
  const react_intl_1 = require("react-intl");
7
7
  const material_1 = require("@mui/material");
8
8
  const styles_1 = require("@mui/material/styles");
9
+ const react_core_1 = require("@selfcommunity/react-core");
9
10
  const Icon_1 = tslib_1.__importDefault(require("@mui/material/Icon"));
10
11
  const CategoryAutocomplete_1 = tslib_1.__importDefault(require("../../../CategoryAutocomplete"));
11
12
  const DialogContent_1 = tslib_1.__importDefault(require("@mui/material/DialogContent"));
@@ -25,9 +26,11 @@ const CategoryLayer = react_1.default.forwardRef((props, ref) => {
25
26
  const { className, onClose, onSave, defaultValue = [] } = props, rest = tslib_1.__rest(props, ["className", "onClose", "onSave", "defaultValue"]);
26
27
  // STATE
27
28
  const [value, setValue] = (0, react_1.useState)(defaultValue);
29
+ // CONTEXT
30
+ const scUserContext = (0, react_core_1.useSCUser)();
28
31
  // HANDLERS
29
32
  const handleSave = (0, react_1.useCallback)(() => onSave(value), [value, onSave]);
30
33
  const handleChange = (0, react_1.useCallback)((categories) => setValue(categories), []);
31
- return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ ref: ref, className: (0, classnames_1.default)(className, classes.root) }, rest, { children: [(0, jsx_runtime_1.jsxs)(material_1.DialogTitle, Object.assign({ className: classes.title }, { children: [(0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ onClick: onClose }, { children: (0, jsx_runtime_1.jsx)(Icon_1.default, { children: "arrow_back" }) })), (0, jsx_runtime_1.jsx)(material_1.Typography, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.category.title", defaultMessage: "ui.composer.layer.category.title" }) }), (0, jsx_runtime_1.jsx)(material_1.Button, Object.assign({ size: "small", color: "secondary", variant: "contained", onClick: handleSave }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.save", defaultMessage: "ui.composer.layer.save" }) }))] })), (0, jsx_runtime_1.jsx)(DialogContent_1.default, Object.assign({ className: classes.content }, { children: (0, jsx_runtime_1.jsx)(CategoryAutocomplete_1.default, { multiple: true, onChange: handleChange, defaultValue: defaultValue, endpointQueryParams: { can_create_content: true } }) }))] })));
34
+ return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ ref: ref, className: (0, classnames_1.default)(className, classes.root) }, rest, { children: [(0, jsx_runtime_1.jsxs)(material_1.DialogTitle, Object.assign({ className: classes.title }, { children: [(0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ onClick: onClose }, { children: (0, jsx_runtime_1.jsx)(Icon_1.default, { children: "arrow_back" }) })), (0, jsx_runtime_1.jsx)(material_1.Typography, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.category.title", defaultMessage: "ui.composer.layer.category.title" }) }), (0, jsx_runtime_1.jsx)(material_1.Button, Object.assign({ size: "small", color: "secondary", variant: "contained", onClick: handleSave }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.save", defaultMessage: "ui.composer.layer.save" }) }))] })), (0, jsx_runtime_1.jsx)(DialogContent_1.default, Object.assign({ className: classes.content }, { children: (0, jsx_runtime_1.jsx)(CategoryAutocomplete_1.default, Object.assign({ multiple: true, onChange: handleChange, defaultValue: defaultValue }, (!react_core_1.UserUtils.isStaff(scUserContext.user) && { endpointQueryParams: { can_create_content: true } }))) }))] })));
32
35
  });
33
36
  exports.default = CategoryLayer;
@@ -4,5 +4,6 @@ export interface LiveStreamSettingsMenuProps {
4
4
  handleBlur?: (event: any) => void;
5
5
  actionBlurDisabled?: boolean;
6
6
  onlyContentMenu?: boolean;
7
+ hideRecordAction?: boolean;
7
8
  }
8
9
  export default function LiveStreamSettingsMenu(inProps: LiveStreamSettingsMenuProps): JSX.Element;
@@ -9,6 +9,7 @@ const material_1 = require("@mui/material");
9
9
  const styles_1 = require("@mui/material/styles");
10
10
  const system_1 = require("@mui/system");
11
11
  const classnames_1 = tslib_1.__importDefault(require("classnames"));
12
+ // import {useIsRecording, useMaybeLayoutContext, useRoomContext} from '@livekit/components-react';
12
13
  const react_1 = require("react");
13
14
  const react_intl_1 = require("react-intl");
14
15
  const PREFIX = 'SCLiveStreamSettingsMenu';
@@ -49,15 +50,51 @@ function LiveStreamSettingsMenu(inProps) {
49
50
  props: inProps,
50
51
  name: PREFIX
51
52
  });
52
- const { className, actionBlurDisabled = false, blurEnabled = false, handleBlur, onlyContentMenu = false } = props, rest = tslib_1.__rest(props, ["className", "actionBlurDisabled", "blurEnabled", "handleBlur", "onlyContentMenu"]);
53
+ const { className, actionBlurDisabled = false, blurEnabled = false, handleBlur, hideRecordAction = true, onlyContentMenu = false } = props, rest = tslib_1.__rest(props, ["className", "actionBlurDisabled", "blurEnabled", "handleBlur", "hideRecordAction", "onlyContentMenu"]);
53
54
  const [anchorEl, setAnchorEl] = React.useState(null);
54
55
  const open = Boolean(anchorEl);
56
+ /*
57
+ // Recording: https://github.com/livekit-examples/meet/blob/main/lib/SettingsMenu.tsx
58
+ const room = useRoomContext();
59
+ const isRecording = useIsRecording();
60
+ const [initialRecStatus, setInitialRecStatus] = useState(isRecording);
61
+ const [processingRecRequest, setProcessingRecRequest] = useState(false);
62
+ const recordingEndpoint = process.env.NEXT_PUBLIC_LK_RECORD_ENDPOINT;
63
+ */
55
64
  const handleClick = (event) => {
56
65
  setAnchorEl(event.currentTarget);
57
66
  };
58
67
  const handleClose = () => {
59
68
  setAnchorEl(null);
60
69
  };
70
+ /* useEffect(() => {
71
+ if (initialRecStatus !== isRecording) {
72
+ setProcessingRecRequest(false);
73
+ }
74
+ }, [isRecording, initialRecStatus]);
75
+
76
+ const toggleRoomRecording = async () => {
77
+ /* if (!recordingEndpoint) {
78
+ throw TypeError('No recording endpoint specified');
79
+ }
80
+ if (room.isE2EEEnabled) {
81
+ throw Error('Recording of encrypted meetings is currently not supported');
82
+ }
83
+ setProcessingRecRequest(true);
84
+ setInitialRecStatus(isRecording);
85
+ let response: Response;
86
+ if (isRecording) {
87
+ response = await fetch(recordingEndpoint + `/stop?roomName=${room.name}`);
88
+ } else {
89
+ response = await fetch(recordingEndpoint + `/start?roomName=${room.name}`);
90
+ }
91
+ if (response.ok) {
92
+ } else {
93
+ console.error('Error handling recording request, check server logs:', response.status, response.statusText);
94
+ setProcessingRecRequest(false);
95
+ }
96
+ };
97
+ */
61
98
  const MenuContent = (0, react_1.useMemo)(() => ((0, jsx_runtime_1.jsxs)(material_1.Box, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1", component: "div" }, { children: (0, jsx_runtime_1.jsx)("b", { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.settingsMenu.visualEffect", defaultMessage: "ui.liveStreamRoom.settingsMenu.visualEffect" }) }) })), (0, jsx_runtime_1.jsx)(material_1.FormControlLabel, { labelPlacement: "start", control: (0, jsx_runtime_1.jsx)(material_1.Switch, { checked: blurEnabled, disabled: actionBlurDisabled, onChange: handleBlur, inputProps: { 'aria-label': 'controlled' } }), label: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.settingsMenu.visualEffect.blurEffect", defaultMessage: "ui.liveStreamRoom.settingsMenu.visualEffect.blurEffect" }) })] })), [blurEnabled, actionBlurDisabled, handleBlur]);
62
99
  if (onlyContentMenu) {
63
100
  return MenuContent;
@@ -17,6 +17,8 @@ const track_processors_1 = require("@livekit/track-processors");
17
17
  const LiveStreamSettingsMenu_1 = tslib_1.__importDefault(require("./LiveStreamSettingsMenu"));
18
18
  const utils_1 = require("@selfcommunity/utils");
19
19
  const LiveStream_1 = require("../../../constants/LiveStream");
20
+ const react_intl_1 = require("react-intl");
21
+ const notistack_1 = require("notistack");
20
22
  /** @alpha */
21
23
  function usePreviewTracks(options, onError) {
22
24
  const [tracks, setTracks] = React.useState();
@@ -175,6 +177,7 @@ function PreJoin(_a) {
175
177
  preventSave: !persistUserChoices,
176
178
  preventLoad: !persistUserChoices
177
179
  });
180
+ const { enqueueSnackbar } = (0, notistack_1.useSnackbar)();
178
181
  // Initialize device settings
179
182
  const [audioEnabled, setAudioEnabled] = React.useState(initialUserChoices.audioEnabled && canUseAudio);
180
183
  const [videoEnabled, setVideoEnabled] = React.useState(initialUserChoices.videoEnabled && canUseVideo);
@@ -182,7 +185,7 @@ function PreJoin(_a) {
182
185
  const [videoDeviceId, setVideoDeviceId] = React.useState(initialUserChoices.videoDeviceId);
183
186
  const [username, setUsername] = React.useState(initialUserChoices.username);
184
187
  // Processors
185
- const [blurEnabled, setBlurEnabled] = React.useState((0, utils_1.isClientSideRendering)() ? Boolean((_b = window === null || window === void 0 ? void 0 : window.localStorage) === null || _b === void 0 ? void 0 : _b.getItem(LiveStream_1.CHOICE_VIDEO_BLUR_EFFECT)) || false : false);
188
+ const [blurEnabled, setBlurEnabled] = React.useState((0, utils_1.isClientSideRendering)() ? ((_b = window === null || window === void 0 ? void 0 : window.localStorage) === null || _b === void 0 ? void 0 : _b.getItem(LiveStream_1.CHOICE_VIDEO_BLUR_EFFECT)) === 'true' : false);
186
189
  const [processorPending, setProcessorPending] = React.useState(false);
187
190
  // Save user choices to persistent storage.
188
191
  React.useEffect(() => {
@@ -240,8 +243,9 @@ function PreJoin(_a) {
240
243
  }, [onValidate]);
241
244
  const handleBlur = React.useCallback(() => {
242
245
  var _a;
243
- setBlurEnabled((enabled) => !enabled);
244
- (_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(LiveStream_1.CHOICE_VIDEO_BLUR_EFFECT, (!blurEnabled).toString());
246
+ const _blur = !blurEnabled;
247
+ setBlurEnabled(_blur);
248
+ (_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(LiveStream_1.CHOICE_VIDEO_BLUR_EFFECT, _blur.toString());
245
249
  }, [setBlurEnabled, blurEnabled]);
246
250
  (0, react_1.useEffect)(() => {
247
251
  const newUserChoices = {
@@ -255,6 +259,7 @@ function PreJoin(_a) {
255
259
  setIsValid(handleValidation(newUserChoices));
256
260
  }, [username, scUserContext.user, videoEnabled, handleValidation, audioEnabled, audioDeviceId, videoDeviceId]);
257
261
  (0, react_1.useEffect)(() => {
262
+ var _a;
258
263
  if (videoTrack && videoEnabled) {
259
264
  setProcessorPending(true);
260
265
  try {
@@ -265,6 +270,15 @@ function PreJoin(_a) {
265
270
  videoTrack.stopProcessor();
266
271
  }
267
272
  }
273
+ catch (e) {
274
+ console.log(e);
275
+ setBlurEnabled(false);
276
+ (_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(LiveStream_1.CHOICE_VIDEO_BLUR_EFFECT, false.toString());
277
+ enqueueSnackbar((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.errorApplyVideoEffect", defaultMessage: "ui.contributionActionMenu.errorApplyVideoEffect" }), {
278
+ variant: 'warning',
279
+ autoHideDuration: 3000
280
+ });
281
+ }
268
282
  finally {
269
283
  setProcessorPending(false);
270
284
  }
@@ -22,6 +22,9 @@ const LiveStreamSettingsMenu_1 = tslib_1.__importDefault(require("./LiveStreamSe
22
22
  const track_processors_1 = require("@livekit/track-processors");
23
23
  const utils_1 = require("@selfcommunity/utils");
24
24
  const LiveStream_1 = require("../../../constants/LiveStream");
25
+ const Icon_1 = tslib_1.__importDefault(require("@mui/material/Icon"));
26
+ const notistack_1 = require("notistack");
27
+ const react_intl_1 = require("react-intl");
25
28
  const PREFIX = 'SCVideoConference';
26
29
  const classes = {
27
30
  root: `${PREFIX}-root`
@@ -59,7 +62,7 @@ function VideoConference(inProps) {
59
62
  const lastAutoFocusedScreenShareTrack = React.useRef(null);
60
63
  // HOOKS
61
64
  const scUserContext = (0, react_core_1.useSCUser)();
62
- const [blurEnabled, setBlurEnabled] = React.useState((0, utils_1.isClientSideRendering)() ? Boolean((_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.getItem(LiveStream_1.CHOICE_VIDEO_BLUR_EFFECT)) || false : false);
65
+ const [blurEnabled, setBlurEnabled] = React.useState((0, utils_1.isClientSideRendering)() ? ((_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.getItem(LiveStream_1.CHOICE_VIDEO_BLUR_EFFECT)) === 'true' : false);
63
66
  const [processorPending, setProcessorPending] = React.useState(false);
64
67
  const tracks = (0, components_react_1.useTracks)([
65
68
  { source: livekit_client_1.Track.Source.Camera, withPlaceholder: true },
@@ -87,6 +90,7 @@ function VideoConference(inProps) {
87
90
  const focusTrack = (_b = (0, components_react_1.usePinnedTracks)(layoutContext)) === null || _b === void 0 ? void 0 : _b[0];
88
91
  const carouselTracks = tracks.filter((track) => !(0, components_core_1.isEqualTrackRef)(track, focusTrack));
89
92
  const { cameraTrack } = (0, components_react_1.useLocalParticipant)();
93
+ const { enqueueSnackbar } = (0, notistack_1.useSnackbar)();
90
94
  (0, useLiveStreamCheck_1.useLivestreamCheck)();
91
95
  /**
92
96
  * widgetUpdate
@@ -166,6 +170,7 @@ function VideoConference(inProps) {
166
170
  }
167
171
  }, [tracks, participants, speakerFocused]);
168
172
  (0, react_1.useEffect)(() => {
173
+ var _a;
169
174
  const localCamTrack = cameraTrack === null || cameraTrack === void 0 ? void 0 : cameraTrack.track;
170
175
  if (localCamTrack) {
171
176
  setProcessorPending(true);
@@ -177,6 +182,15 @@ function VideoConference(inProps) {
177
182
  localCamTrack.stopProcessor();
178
183
  }
179
184
  }
185
+ catch (e) {
186
+ console.log(e);
187
+ setBlurEnabled(false);
188
+ (_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(LiveStream_1.CHOICE_VIDEO_BLUR_EFFECT, false.toString());
189
+ enqueueSnackbar((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.errorApplyVideoEffect", defaultMessage: "ui.contributionActionMenu.errorApplyVideoEffect" }), {
190
+ variant: 'warning',
191
+ autoHideDuration: 3000
192
+ });
193
+ }
180
194
  finally {
181
195
  setProcessorPending(false);
182
196
  }
@@ -187,6 +201,6 @@ function VideoConference(inProps) {
187
201
  microphone: !disableMicrophone,
188
202
  camera: !disableCamera,
189
203
  screenShare: !disableShareScreen
190
- }, { settings: true }) })] })), !disableChat && ((0, jsx_runtime_1.jsx)(components_react_1.Chat, { style: { display: widgetState.showChat ? 'grid' : 'none' }, messageFormatter: chatMessageFormatter, messageEncoder: chatMessageEncoder, messageDecoder: chatMessageDecoder })), (0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-settings-menu-modal", style: { display: widgetState.showSettings ? 'block' : 'none' } }, { children: SettingsComponent ? ((0, jsx_runtime_1.jsx)(SettingsComponent, {})) : ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(LiveStreamSettingsMenu_1.default, { onlyContentMenu: true, actionBlurDisabled: !cameraTrack && !disableCamera, blurEnabled: blurEnabled, handleBlur: handleBlur }) })) }))] }))), (0, jsx_runtime_1.jsx)(components_react_1.RoomAudioRenderer, {}), (0, jsx_runtime_1.jsx)(components_react_1.ConnectionStateToast, {})] })));
204
+ }, { settings: true }) })] })), !disableChat && ((0, jsx_runtime_1.jsx)(components_react_1.Chat, { style: { display: widgetState.showChat ? 'grid' : 'none' }, messageFormatter: chatMessageFormatter, messageEncoder: chatMessageEncoder, messageDecoder: chatMessageDecoder })), (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-settings-menu-modal", style: { display: widgetState.showSettings ? 'block' : 'none' } }, { children: [(0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ className: "lk-settings-menu-modal-icon-close", onClick: () => { var _a, _b; return (_b = layoutContext === null || layoutContext === void 0 ? void 0 : (_a = layoutContext.widget).dispatch) === null || _b === void 0 ? void 0 : _b.call(_a, { msg: 'toggle_settings' }); } }, { children: (0, jsx_runtime_1.jsx)(Icon_1.default, { children: "close" }) })), SettingsComponent ? ((0, jsx_runtime_1.jsx)(SettingsComponent, {})) : ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(LiveStreamSettingsMenu_1.default, { onlyContentMenu: true, actionBlurDisabled: !cameraTrack && !disableCamera, blurEnabled: blurEnabled, handleBlur: handleBlur }) }))] }))] }))), (0, jsx_runtime_1.jsx)(components_react_1.RoomAudioRenderer, {}), (0, jsx_runtime_1.jsx)(components_react_1.ConnectionStateToast, {})] })));
191
205
  }
192
206
  exports.VideoConference = VideoConference;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { BoxProps } from '@mui/material';
3
- import { SCCategoryType } from '@selfcommunity/types/src/index';
3
+ import { SCCategoryType } from '@selfcommunity/types';
4
4
  import { ComposerLayerProps } from '../../../../types/composer';
5
5
  export interface CategoryLayerProps extends Omit<BoxProps, 'defaultValue'>, ComposerLayerProps {
6
6
  defaultValue: SCCategoryType[];
@@ -4,6 +4,7 @@ import React, { useCallback, useState } from 'react';
4
4
  import { FormattedMessage } from 'react-intl';
5
5
  import { Box, Button, DialogTitle, IconButton, Typography } from '@mui/material';
6
6
  import { styled } from '@mui/material/styles';
7
+ import { UserUtils, useSCUser } from '@selfcommunity/react-core';
7
8
  import Icon from '@mui/material/Icon';
8
9
  import CategoryAutocomplete from '../../../CategoryAutocomplete';
9
10
  import DialogContent from '@mui/material/DialogContent';
@@ -23,9 +24,11 @@ const CategoryLayer = React.forwardRef((props, ref) => {
23
24
  const { className, onClose, onSave, defaultValue = [] } = props, rest = __rest(props, ["className", "onClose", "onSave", "defaultValue"]);
24
25
  // STATE
25
26
  const [value, setValue] = useState(defaultValue);
27
+ // CONTEXT
28
+ const scUserContext = useSCUser();
26
29
  // HANDLERS
27
30
  const handleSave = useCallback(() => onSave(value), [value, onSave]);
28
31
  const handleChange = useCallback((categories) => setValue(categories), []);
29
- return (_jsxs(Root, Object.assign({ ref: ref, className: classNames(className, classes.root) }, rest, { children: [_jsxs(DialogTitle, Object.assign({ className: classes.title }, { children: [_jsx(IconButton, Object.assign({ onClick: onClose }, { children: _jsx(Icon, { children: "arrow_back" }) })), _jsx(Typography, { children: _jsx(FormattedMessage, { id: "ui.composer.layer.category.title", defaultMessage: "ui.composer.layer.category.title" }) }), _jsx(Button, Object.assign({ size: "small", color: "secondary", variant: "contained", onClick: handleSave }, { children: _jsx(FormattedMessage, { id: "ui.composer.layer.save", defaultMessage: "ui.composer.layer.save" }) }))] })), _jsx(DialogContent, Object.assign({ className: classes.content }, { children: _jsx(CategoryAutocomplete, { multiple: true, onChange: handleChange, defaultValue: defaultValue, endpointQueryParams: { can_create_content: true } }) }))] })));
32
+ return (_jsxs(Root, Object.assign({ ref: ref, className: classNames(className, classes.root) }, rest, { children: [_jsxs(DialogTitle, Object.assign({ className: classes.title }, { children: [_jsx(IconButton, Object.assign({ onClick: onClose }, { children: _jsx(Icon, { children: "arrow_back" }) })), _jsx(Typography, { children: _jsx(FormattedMessage, { id: "ui.composer.layer.category.title", defaultMessage: "ui.composer.layer.category.title" }) }), _jsx(Button, Object.assign({ size: "small", color: "secondary", variant: "contained", onClick: handleSave }, { children: _jsx(FormattedMessage, { id: "ui.composer.layer.save", defaultMessage: "ui.composer.layer.save" }) }))] })), _jsx(DialogContent, Object.assign({ className: classes.content }, { children: _jsx(CategoryAutocomplete, Object.assign({ multiple: true, onChange: handleChange, defaultValue: defaultValue }, (!UserUtils.isStaff(scUserContext.user) && { endpointQueryParams: { can_create_content: true } }))) }))] })));
30
33
  });
31
34
  export default CategoryLayer;
@@ -4,5 +4,6 @@ export interface LiveStreamSettingsMenuProps {
4
4
  handleBlur?: (event: any) => void;
5
5
  actionBlurDisabled?: boolean;
6
6
  onlyContentMenu?: boolean;
7
+ hideRecordAction?: boolean;
7
8
  }
8
9
  export default function LiveStreamSettingsMenu(inProps: LiveStreamSettingsMenuProps): JSX.Element;
@@ -7,6 +7,7 @@ import { Box, FormControlLabel, Icon, Switch, Typography } from '@mui/material';
7
7
  import { styled } from '@mui/material/styles';
8
8
  import { useThemeProps } from '@mui/system';
9
9
  import classNames from 'classnames';
10
+ // import {useIsRecording, useMaybeLayoutContext, useRoomContext} from '@livekit/components-react';
10
11
  import { Fragment, useMemo } from 'react';
11
12
  import { FormattedMessage } from 'react-intl';
12
13
  const PREFIX = 'SCLiveStreamSettingsMenu';
@@ -47,15 +48,51 @@ export default function LiveStreamSettingsMenu(inProps) {
47
48
  props: inProps,
48
49
  name: PREFIX
49
50
  });
50
- const { className, actionBlurDisabled = false, blurEnabled = false, handleBlur, onlyContentMenu = false } = props, rest = __rest(props, ["className", "actionBlurDisabled", "blurEnabled", "handleBlur", "onlyContentMenu"]);
51
+ const { className, actionBlurDisabled = false, blurEnabled = false, handleBlur, hideRecordAction = true, onlyContentMenu = false } = props, rest = __rest(props, ["className", "actionBlurDisabled", "blurEnabled", "handleBlur", "hideRecordAction", "onlyContentMenu"]);
51
52
  const [anchorEl, setAnchorEl] = React.useState(null);
52
53
  const open = Boolean(anchorEl);
54
+ /*
55
+ // Recording: https://github.com/livekit-examples/meet/blob/main/lib/SettingsMenu.tsx
56
+ const room = useRoomContext();
57
+ const isRecording = useIsRecording();
58
+ const [initialRecStatus, setInitialRecStatus] = useState(isRecording);
59
+ const [processingRecRequest, setProcessingRecRequest] = useState(false);
60
+ const recordingEndpoint = process.env.NEXT_PUBLIC_LK_RECORD_ENDPOINT;
61
+ */
53
62
  const handleClick = (event) => {
54
63
  setAnchorEl(event.currentTarget);
55
64
  };
56
65
  const handleClose = () => {
57
66
  setAnchorEl(null);
58
67
  };
68
+ /* useEffect(() => {
69
+ if (initialRecStatus !== isRecording) {
70
+ setProcessingRecRequest(false);
71
+ }
72
+ }, [isRecording, initialRecStatus]);
73
+
74
+ const toggleRoomRecording = async () => {
75
+ /* if (!recordingEndpoint) {
76
+ throw TypeError('No recording endpoint specified');
77
+ }
78
+ if (room.isE2EEEnabled) {
79
+ throw Error('Recording of encrypted meetings is currently not supported');
80
+ }
81
+ setProcessingRecRequest(true);
82
+ setInitialRecStatus(isRecording);
83
+ let response: Response;
84
+ if (isRecording) {
85
+ response = await fetch(recordingEndpoint + `/stop?roomName=${room.name}`);
86
+ } else {
87
+ response = await fetch(recordingEndpoint + `/start?roomName=${room.name}`);
88
+ }
89
+ if (response.ok) {
90
+ } else {
91
+ console.error('Error handling recording request, check server logs:', response.status, response.statusText);
92
+ setProcessingRecRequest(false);
93
+ }
94
+ };
95
+ */
59
96
  const MenuContent = useMemo(() => (_jsxs(Box, { children: [_jsx(Typography, Object.assign({ variant: "body1", component: "div" }, { children: _jsx("b", { children: _jsx(FormattedMessage, { id: "ui.liveStreamRoom.settingsMenu.visualEffect", defaultMessage: "ui.liveStreamRoom.settingsMenu.visualEffect" }) }) })), _jsx(FormControlLabel, { labelPlacement: "start", control: _jsx(Switch, { checked: blurEnabled, disabled: actionBlurDisabled, onChange: handleBlur, inputProps: { 'aria-label': 'controlled' } }), label: _jsx(FormattedMessage, { id: "ui.liveStreamRoom.settingsMenu.visualEffect.blurEffect", defaultMessage: "ui.liveStreamRoom.settingsMenu.visualEffect.blurEffect" }) })] })), [blurEnabled, actionBlurDisabled, handleBlur]);
60
97
  if (onlyContentMenu) {
61
98
  return MenuContent;
@@ -14,6 +14,8 @@ import { BackgroundBlur } from '@livekit/track-processors';
14
14
  import LiveStreamSettingsMenu from './LiveStreamSettingsMenu';
15
15
  import { isClientSideRendering } from '@selfcommunity/utils';
16
16
  import { CHOICE_VIDEO_BLUR_EFFECT } from '../../../constants/LiveStream';
17
+ import { FormattedMessage } from 'react-intl';
18
+ import { useSnackbar } from 'notistack';
17
19
  /** @alpha */
18
20
  export function usePreviewTracks(options, onError) {
19
21
  const [tracks, setTracks] = React.useState();
@@ -170,6 +172,7 @@ export function PreJoin(_a) {
170
172
  preventSave: !persistUserChoices,
171
173
  preventLoad: !persistUserChoices
172
174
  });
175
+ const { enqueueSnackbar } = useSnackbar();
173
176
  // Initialize device settings
174
177
  const [audioEnabled, setAudioEnabled] = React.useState(initialUserChoices.audioEnabled && canUseAudio);
175
178
  const [videoEnabled, setVideoEnabled] = React.useState(initialUserChoices.videoEnabled && canUseVideo);
@@ -177,7 +180,7 @@ export function PreJoin(_a) {
177
180
  const [videoDeviceId, setVideoDeviceId] = React.useState(initialUserChoices.videoDeviceId);
178
181
  const [username, setUsername] = React.useState(initialUserChoices.username);
179
182
  // Processors
180
- const [blurEnabled, setBlurEnabled] = React.useState(isClientSideRendering() ? Boolean((_b = window === null || window === void 0 ? void 0 : window.localStorage) === null || _b === void 0 ? void 0 : _b.getItem(CHOICE_VIDEO_BLUR_EFFECT)) || false : false);
183
+ const [blurEnabled, setBlurEnabled] = React.useState(isClientSideRendering() ? ((_b = window === null || window === void 0 ? void 0 : window.localStorage) === null || _b === void 0 ? void 0 : _b.getItem(CHOICE_VIDEO_BLUR_EFFECT)) === 'true' : false);
181
184
  const [processorPending, setProcessorPending] = React.useState(false);
182
185
  // Save user choices to persistent storage.
183
186
  React.useEffect(() => {
@@ -235,8 +238,9 @@ export function PreJoin(_a) {
235
238
  }, [onValidate]);
236
239
  const handleBlur = React.useCallback(() => {
237
240
  var _a;
238
- setBlurEnabled((enabled) => !enabled);
239
- (_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(CHOICE_VIDEO_BLUR_EFFECT, (!blurEnabled).toString());
241
+ const _blur = !blurEnabled;
242
+ setBlurEnabled(_blur);
243
+ (_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(CHOICE_VIDEO_BLUR_EFFECT, _blur.toString());
240
244
  }, [setBlurEnabled, blurEnabled]);
241
245
  useEffect(() => {
242
246
  const newUserChoices = {
@@ -250,6 +254,7 @@ export function PreJoin(_a) {
250
254
  setIsValid(handleValidation(newUserChoices));
251
255
  }, [username, scUserContext.user, videoEnabled, handleValidation, audioEnabled, audioDeviceId, videoDeviceId]);
252
256
  useEffect(() => {
257
+ var _a;
253
258
  if (videoTrack && videoEnabled) {
254
259
  setProcessorPending(true);
255
260
  try {
@@ -260,6 +265,15 @@ export function PreJoin(_a) {
260
265
  videoTrack.stopProcessor();
261
266
  }
262
267
  }
268
+ catch (e) {
269
+ console.log(e);
270
+ setBlurEnabled(false);
271
+ (_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(CHOICE_VIDEO_BLUR_EFFECT, false.toString());
272
+ enqueueSnackbar(_jsx(FormattedMessage, { id: "ui.liveStreamRoom.errorApplyVideoEffect", defaultMessage: "ui.contributionActionMenu.errorApplyVideoEffect" }), {
273
+ variant: 'warning',
274
+ autoHideDuration: 3000
275
+ });
276
+ }
263
277
  finally {
264
278
  setProcessorPending(false);
265
279
  }
@@ -12,13 +12,16 @@ import { FocusLayout, FocusLayoutContainer, FocusLayoutContainerNoParticipants }
12
12
  import { useSCUser } from '@selfcommunity/react-core';
13
13
  import classNames from 'classnames';
14
14
  import { styled } from '@mui/material/styles';
15
- import { Box } from '@mui/material';
15
+ import { Box, IconButton } from '@mui/material';
16
16
  import { useThemeProps } from '@mui/system';
17
17
  import NoParticipants from './NoParticipants';
18
18
  import LiveStreamSettingsMenu from './LiveStreamSettingsMenu';
19
19
  import { BackgroundBlur } from '@livekit/track-processors';
20
20
  import { isClientSideRendering } from '@selfcommunity/utils';
21
21
  import { CHOICE_VIDEO_BLUR_EFFECT } from '../../../constants/LiveStream';
22
+ import Icon from '@mui/material/Icon';
23
+ import { useSnackbar } from 'notistack';
24
+ import { FormattedMessage } from 'react-intl';
22
25
  const PREFIX = 'SCVideoConference';
23
26
  const classes = {
24
27
  root: `${PREFIX}-root`
@@ -56,7 +59,7 @@ export function VideoConference(inProps) {
56
59
  const lastAutoFocusedScreenShareTrack = React.useRef(null);
57
60
  // HOOKS
58
61
  const scUserContext = useSCUser();
59
- const [blurEnabled, setBlurEnabled] = React.useState(isClientSideRendering() ? Boolean((_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.getItem(CHOICE_VIDEO_BLUR_EFFECT)) || false : false);
62
+ const [blurEnabled, setBlurEnabled] = React.useState(isClientSideRendering() ? ((_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.getItem(CHOICE_VIDEO_BLUR_EFFECT)) === 'true' : false);
60
63
  const [processorPending, setProcessorPending] = React.useState(false);
61
64
  const tracks = useTracks([
62
65
  { source: Track.Source.Camera, withPlaceholder: true },
@@ -84,6 +87,7 @@ export function VideoConference(inProps) {
84
87
  const focusTrack = (_b = usePinnedTracks(layoutContext)) === null || _b === void 0 ? void 0 : _b[0];
85
88
  const carouselTracks = tracks.filter((track) => !isEqualTrackRef(track, focusTrack));
86
89
  const { cameraTrack } = useLocalParticipant();
90
+ const { enqueueSnackbar } = useSnackbar();
87
91
  useLivestreamCheck();
88
92
  /**
89
93
  * widgetUpdate
@@ -163,6 +167,7 @@ export function VideoConference(inProps) {
163
167
  }
164
168
  }, [tracks, participants, speakerFocused]);
165
169
  useEffect(() => {
170
+ var _a;
166
171
  const localCamTrack = cameraTrack === null || cameraTrack === void 0 ? void 0 : cameraTrack.track;
167
172
  if (localCamTrack) {
168
173
  setProcessorPending(true);
@@ -174,6 +179,15 @@ export function VideoConference(inProps) {
174
179
  localCamTrack.stopProcessor();
175
180
  }
176
181
  }
182
+ catch (e) {
183
+ console.log(e);
184
+ setBlurEnabled(false);
185
+ (_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.setItem(CHOICE_VIDEO_BLUR_EFFECT, false.toString());
186
+ enqueueSnackbar(_jsx(FormattedMessage, { id: "ui.liveStreamRoom.errorApplyVideoEffect", defaultMessage: "ui.contributionActionMenu.errorApplyVideoEffect" }), {
187
+ variant: 'warning',
188
+ autoHideDuration: 3000
189
+ });
190
+ }
177
191
  finally {
178
192
  setProcessorPending(false);
179
193
  }
@@ -184,5 +198,5 @@ export function VideoConference(inProps) {
184
198
  microphone: !disableMicrophone,
185
199
  camera: !disableCamera,
186
200
  screenShare: !disableShareScreen
187
- }, { settings: true }) })] })), !disableChat && (_jsx(Chat, { style: { display: widgetState.showChat ? 'grid' : 'none' }, messageFormatter: chatMessageFormatter, messageEncoder: chatMessageEncoder, messageDecoder: chatMessageDecoder })), _jsx("div", Object.assign({ className: "lk-settings-menu-modal", style: { display: widgetState.showSettings ? 'block' : 'none' } }, { children: SettingsComponent ? (_jsx(SettingsComponent, {})) : (_jsx(_Fragment, { children: _jsx(LiveStreamSettingsMenu, { onlyContentMenu: true, actionBlurDisabled: !cameraTrack && !disableCamera, blurEnabled: blurEnabled, handleBlur: handleBlur }) })) }))] }))), _jsx(RoomAudioRenderer, {}), _jsx(ConnectionStateToast, {})] })));
201
+ }, { settings: true }) })] })), !disableChat && (_jsx(Chat, { style: { display: widgetState.showChat ? 'grid' : 'none' }, messageFormatter: chatMessageFormatter, messageEncoder: chatMessageEncoder, messageDecoder: chatMessageDecoder })), _jsxs("div", Object.assign({ className: "lk-settings-menu-modal", style: { display: widgetState.showSettings ? 'block' : 'none' } }, { children: [_jsx(IconButton, Object.assign({ className: "lk-settings-menu-modal-icon-close", onClick: () => { var _a, _b; return (_b = layoutContext === null || layoutContext === void 0 ? void 0 : (_a = layoutContext.widget).dispatch) === null || _b === void 0 ? void 0 : _b.call(_a, { msg: 'toggle_settings' }); } }, { children: _jsx(Icon, { children: "close" }) })), SettingsComponent ? (_jsx(SettingsComponent, {})) : (_jsx(_Fragment, { children: _jsx(LiveStreamSettingsMenu, { onlyContentMenu: true, actionBlurDisabled: !cameraTrack && !disableCamera, blurEnabled: blurEnabled, handleBlur: handleBlur }) }))] }))] }))), _jsx(RoomAudioRenderer, {}), _jsx(ConnectionStateToast, {})] })));
188
202
  }