@selfcommunity/react-ui 0.11.0-alpha.3 → 0.11.0-alpha.30

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 (78) hide show
  1. package/lib/cjs/components/CategoryAutocomplete/CategoryAutocomplete.d.ts +5 -0
  2. package/lib/cjs/components/CategoryAutocomplete/CategoryAutocomplete.js +3 -3
  3. package/lib/cjs/components/Composer/Layer/CategoryLayer/CategoryLayer.d.ts +1 -1
  4. package/lib/cjs/components/Composer/Layer/CategoryLayer/CategoryLayer.js +4 -1
  5. package/lib/cjs/components/ComposerIconButton/ComposerIconButton.js +10 -2
  6. package/lib/cjs/components/CreateEventButton/CreateEventButton.d.ts +1 -1
  7. package/lib/cjs/components/CreateEventButton/CreateEventButton.js +1 -1
  8. package/lib/cjs/components/CreateLiveStreamDialog/CreateLiveStreamDialog.js +11 -9
  9. package/lib/cjs/components/CreateLiveStreamDialog/LiveStreamSelector/LiveStreamSelector.js +21 -12
  10. package/lib/cjs/components/Editor/plugins/ToolbarPlugin.js +1 -1
  11. package/lib/cjs/components/EventForm/EventForm.js +7 -5
  12. package/lib/cjs/components/EventMediaWidget/EventMediaWidget.js +2 -2
  13. package/lib/cjs/components/EventMembersWidget/TabContentComponent.js +1 -1
  14. package/lib/cjs/components/EventParticipantsButton/EventParticipantsButton.js +4 -4
  15. package/lib/cjs/components/Events/Events.d.ts +6 -0
  16. package/lib/cjs/components/Events/Events.js +2 -2
  17. package/lib/cjs/components/FeedObject/Activities/Activities.js +1 -1
  18. package/lib/cjs/components/LiveStreamForm/LiveStreamForm.js +65 -6
  19. package/lib/cjs/components/LiveStreamForm/LiveStreamFormSettings.js +8 -3
  20. package/lib/cjs/components/LiveStreamRoom/LiveStreamRoom.js +8 -6
  21. package/lib/cjs/components/LiveStreamRoom/LiveStreamVideoConference/ControlBar.js +3 -1
  22. package/lib/cjs/components/LiveStreamRoom/LiveStreamVideoConference/FocusLayout.d.ts +2 -1
  23. package/lib/cjs/components/LiveStreamRoom/LiveStreamVideoConference/FocusLayout.js +2 -2
  24. package/lib/cjs/components/LiveStreamRoom/LiveStreamVideoConference/LiveStreamSettingsMenu.d.ts +9 -0
  25. package/lib/cjs/components/LiveStreamRoom/LiveStreamVideoConference/LiveStreamSettingsMenu.js +106 -0
  26. package/lib/cjs/components/LiveStreamRoom/LiveStreamVideoConference/NoParticipants.d.ts +4 -0
  27. package/lib/cjs/components/LiveStreamRoom/LiveStreamVideoConference/NoParticipants.js +37 -0
  28. package/lib/cjs/components/LiveStreamRoom/LiveStreamVideoConference/ParticipantTile.d.ts +1 -0
  29. package/lib/cjs/components/LiveStreamRoom/LiveStreamVideoConference/ParticipantTile.js +2 -2
  30. package/lib/cjs/components/LiveStreamRoom/LiveStreamVideoConference/PreJoin.d.ts +3 -2
  31. package/lib/cjs/components/LiveStreamRoom/LiveStreamVideoConference/PreJoin.js +45 -2
  32. package/lib/cjs/components/LiveStreamRoom/LiveStreamVideoConference/VideoConference.js +60 -5
  33. package/lib/cjs/constants/LiveStream.d.ts +1 -0
  34. package/lib/cjs/constants/LiveStream.js +2 -1
  35. package/lib/cjs/shared/AutoPlayer/index.js +1 -1
  36. package/lib/cjs/shared/UpScalingTierBadge/index.js +9 -0
  37. package/lib/cjs/utils/contribution.js +1 -2
  38. package/lib/esm/components/CategoryAutocomplete/CategoryAutocomplete.d.ts +5 -0
  39. package/lib/esm/components/CategoryAutocomplete/CategoryAutocomplete.js +3 -3
  40. package/lib/esm/components/Composer/Layer/CategoryLayer/CategoryLayer.d.ts +1 -1
  41. package/lib/esm/components/Composer/Layer/CategoryLayer/CategoryLayer.js +4 -1
  42. package/lib/esm/components/ComposerIconButton/ComposerIconButton.js +11 -3
  43. package/lib/esm/components/CreateEventButton/CreateEventButton.d.ts +1 -1
  44. package/lib/esm/components/CreateEventButton/CreateEventButton.js +1 -1
  45. package/lib/esm/components/CreateLiveStreamDialog/CreateLiveStreamDialog.js +11 -9
  46. package/lib/esm/components/CreateLiveStreamDialog/LiveStreamSelector/LiveStreamSelector.js +23 -14
  47. package/lib/esm/components/Editor/plugins/ToolbarPlugin.js +1 -1
  48. package/lib/esm/components/EventForm/EventForm.js +8 -6
  49. package/lib/esm/components/EventMediaWidget/EventMediaWidget.js +2 -2
  50. package/lib/esm/components/EventMembersWidget/TabContentComponent.js +1 -1
  51. package/lib/esm/components/EventParticipantsButton/EventParticipantsButton.js +4 -4
  52. package/lib/esm/components/Events/Events.d.ts +6 -0
  53. package/lib/esm/components/Events/Events.js +2 -2
  54. package/lib/esm/components/FeedObject/Activities/Activities.js +1 -1
  55. package/lib/esm/components/LiveStreamForm/LiveStreamForm.js +67 -8
  56. package/lib/esm/components/LiveStreamForm/LiveStreamFormSettings.js +8 -3
  57. package/lib/esm/components/LiveStreamRoom/LiveStreamRoom.js +8 -6
  58. package/lib/esm/components/LiveStreamRoom/LiveStreamVideoConference/ControlBar.js +3 -1
  59. package/lib/esm/components/LiveStreamRoom/LiveStreamVideoConference/FocusLayout.d.ts +2 -1
  60. package/lib/esm/components/LiveStreamRoom/LiveStreamVideoConference/FocusLayout.js +2 -2
  61. package/lib/esm/components/LiveStreamRoom/LiveStreamVideoConference/LiveStreamSettingsMenu.d.ts +9 -0
  62. package/lib/esm/components/LiveStreamRoom/LiveStreamVideoConference/LiveStreamSettingsMenu.js +103 -0
  63. package/lib/esm/components/LiveStreamRoom/LiveStreamVideoConference/NoParticipants.d.ts +4 -0
  64. package/lib/esm/components/LiveStreamRoom/LiveStreamVideoConference/NoParticipants.js +34 -0
  65. package/lib/esm/components/LiveStreamRoom/LiveStreamVideoConference/ParticipantTile.d.ts +1 -0
  66. package/lib/esm/components/LiveStreamRoom/LiveStreamVideoConference/ParticipantTile.js +2 -2
  67. package/lib/esm/components/LiveStreamRoom/LiveStreamVideoConference/PreJoin.d.ts +3 -2
  68. package/lib/esm/components/LiveStreamRoom/LiveStreamVideoConference/PreJoin.js +45 -2
  69. package/lib/esm/components/LiveStreamRoom/LiveStreamVideoConference/VideoConference.js +64 -9
  70. package/lib/esm/constants/LiveStream.d.ts +1 -0
  71. package/lib/esm/constants/LiveStream.js +1 -0
  72. package/lib/esm/shared/AutoPlayer/index.js +1 -1
  73. package/lib/esm/shared/UpScalingTierBadge/index.js +9 -0
  74. package/lib/esm/utils/contribution.js +1 -2
  75. package/lib/umd/{653.js → 212.js} +2 -2
  76. package/lib/umd/react-ui.js +1 -1
  77. package/package.json +8 -7
  78. /package/lib/umd/{653.js.LICENSE.txt → 212.js.LICENSE.txt} +0 -0
@@ -0,0 +1,103 @@
1
+ import { __rest } from "tslib";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import Button from '@mui/material/Button';
5
+ import Menu from '@mui/material/Menu';
6
+ import { Box, FormControlLabel, Icon, Switch, Typography } from '@mui/material';
7
+ import { styled } from '@mui/material/styles';
8
+ import { useThemeProps } from '@mui/system';
9
+ import classNames from 'classnames';
10
+ // import {useIsRecording, useMaybeLayoutContext, useRoomContext} from '@livekit/components-react';
11
+ import { Fragment, useMemo } from 'react';
12
+ import { FormattedMessage } from 'react-intl';
13
+ const PREFIX = 'SCLiveStreamSettingsMenu';
14
+ const classes = {
15
+ root: `${PREFIX}-root`,
16
+ menuRoot: `${PREFIX}-menu-root`
17
+ };
18
+ const Root = styled(Button, {
19
+ name: PREFIX,
20
+ slot: 'Root',
21
+ overridesResolver: (props, styles) => styles.root
22
+ })(({ theme }) => ({
23
+ borderRadius: 7,
24
+ color: theme.palette.common.white,
25
+ paddingLeft: theme.spacing(),
26
+ paddingRight: theme.spacing(),
27
+ minWidth: 45
28
+ }));
29
+ const MenuRoot = styled(Menu, {
30
+ name: PREFIX,
31
+ slot: 'Root',
32
+ overridesResolver: (props, styles) => styles.menuRoot
33
+ })(({ theme }) => ({
34
+ '& .MuiPaper-root': {
35
+ minWidth: 120,
36
+ paddingRight: theme.spacing(2),
37
+ '& div.MuiTypography-body1': {
38
+ paddingLeft: theme.spacing(2)
39
+ },
40
+ '& .MuiFormControlLabel-label.Mui-disabled': {
41
+ color: theme.palette.text.primary
42
+ }
43
+ }
44
+ }));
45
+ export default function LiveStreamSettingsMenu(inProps) {
46
+ // PROPS
47
+ const props = useThemeProps({
48
+ props: inProps,
49
+ name: PREFIX
50
+ });
51
+ const { className, actionBlurDisabled = false, blurEnabled = false, handleBlur, hideRecordAction = true, onlyContentMenu = false } = props, rest = __rest(props, ["className", "actionBlurDisabled", "blurEnabled", "handleBlur", "hideRecordAction", "onlyContentMenu"]);
52
+ const [anchorEl, setAnchorEl] = React.useState(null);
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
+ */
62
+ const handleClick = (event) => {
63
+ setAnchorEl(event.currentTarget);
64
+ };
65
+ const handleClose = () => {
66
+ setAnchorEl(null);
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
+ */
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]);
97
+ if (onlyContentMenu) {
98
+ return MenuContent;
99
+ }
100
+ return (_jsxs(Fragment, { children: [_jsx(Root, Object.assign({ className: classNames(className, classes.root, 'lk-button'), "aria-controls": open ? 'live-stream-settings-menu' : undefined, "aria-haspopup": "true", "aria-expanded": open ? 'true' : undefined, onClick: handleClick }, rest, { children: _jsx(Icon, { children: "more_vert" }) })), _jsx(MenuRoot, Object.assign({ id: "live-stream-settings-menu", anchorEl: anchorEl, open: open, onClose: handleClose, MenuListProps: {
101
+ 'aria-labelledby': 'basic-button'
102
+ } }, { children: MenuContent }))] }));
103
+ }
@@ -0,0 +1,4 @@
1
+ export interface NoParticipantsProps {
2
+ className?: string;
3
+ }
4
+ export default function NoParticipants(inProps: NoParticipantsProps): JSX.Element;
@@ -0,0 +1,34 @@
1
+ import { __rest } from "tslib";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { styled } from '@mui/material/styles';
4
+ import { useThemeProps } from '@mui/system';
5
+ import { Box } from '@mui/material';
6
+ import classNames from 'classnames';
7
+ import { FormattedMessage } from 'react-intl';
8
+ const PREFIX = 'SCNoParticipants';
9
+ const classes = {
10
+ root: `${PREFIX}-root`
11
+ };
12
+ const Root = styled(Box, {
13
+ name: PREFIX,
14
+ slot: 'Root',
15
+ overridesResolver: (props, styles) => styles.root
16
+ })(({ theme }) => ({
17
+ display: 'flex',
18
+ alignItems: 'center',
19
+ justifyContent: 'center',
20
+ backgroundColor: '#1e1e1e',
21
+ transition: 'opacity .2sease-in-out',
22
+ pointerEvents: 'none',
23
+ borderRadius: 7
24
+ }));
25
+ export default function NoParticipants(inProps) {
26
+ // PROPS
27
+ const props = useThemeProps({
28
+ props: inProps,
29
+ name: PREFIX
30
+ });
31
+ const { className } = props, rest = __rest(props, ["className"]);
32
+ // RENDER
33
+ return (_jsx(Root, Object.assign({ className: classNames(className, classes.root) }, rest, { children: _jsx(FormattedMessage, { id: "ui.liveStreamRoom.noParticipants", defaultMessage: "ui.liveStreamRoom.noParticipants" }) })));
34
+ }
@@ -19,6 +19,7 @@ export interface ParticipantTileProps extends React.HTMLAttributes<HTMLDivElemen
19
19
  trackRef?: TrackReferenceOrPlaceholder;
20
20
  disableSpeakingIndicator?: boolean;
21
21
  disableTileActions?: boolean;
22
+ disableTileFocusToggle?: boolean;
22
23
  onParticipantClick?: (event: ParticipantClickEvent) => void;
23
24
  }
24
25
  /**
@@ -29,7 +29,7 @@ export function TrackRefContextIfNeeded(props) {
29
29
  export const ParticipantTile =
30
30
  /* @__PURE__ */ React.forwardRef(function ParticipantTile(_a, ref) {
31
31
  var _b, _c;
32
- var { trackRef, children, onParticipantClick, disableSpeakingIndicator, disableTileActions = false } = _a, htmlProps = __rest(_a, ["trackRef", "children", "onParticipantClick", "disableSpeakingIndicator", "disableTileActions"]);
32
+ var { trackRef, children, onParticipantClick, disableSpeakingIndicator, disableTileFocusToggle = false, disableTileActions = false } = _a, htmlProps = __rest(_a, ["trackRef", "children", "onParticipantClick", "disableSpeakingIndicator", "disableTileFocusToggle", "disableTileActions"]);
33
33
  const scUserContext = useSCUser();
34
34
  const trackReference = useEnsureTrackRef(trackRef);
35
35
  const { elementProps } = useParticipantTile({
@@ -56,5 +56,5 @@ export const ParticipantTile =
56
56
  trackReference.source === Track.Source.ScreenShare) ? (_jsx(_Fragment, { children: _jsx(VideoTrack, { trackRef: trackReference, onSubscriptionStatusChanged: handleSubscribe, manageSubscription: autoManageSubscription }) })) : (isTrackReference(trackReference) && (_jsx(_Fragment, { children: _jsx(AudioTrack, { trackRef: trackReference, onSubscriptionStatusChanged: handleSubscribe }) }))), _jsx("div", Object.assign({ className: "lk-participant-placeholder" }, { children: _jsx(ParticipantTileAvatar, { participant: trackReference.participant }) })), _jsxs("div", Object.assign({ className: "lk-participant-metadata" }, { children: [_jsx("div", Object.assign({ className: "lk-participant-metadata-item" }, { children: trackReference.source === Track.Source.Camera ? (_jsxs(_Fragment, { children: [isEncrypted && _jsx(LockLockedIcon, { style: { marginRight: '0.25rem' } }), _jsx(TrackMutedIndicator, { trackRef: {
57
57
  participant: trackReference.participant,
58
58
  source: Track.Source.Microphone
59
- }, show: 'muted' }), _jsx(ParticipantName, { children: !disableTileActions && _jsx(ParticipantTileActions, {}) })] })) : (_jsxs(_Fragment, { children: [_jsx(ScreenShareIcon, { style: { marginRight: '0.25rem' } }), _jsx(ParticipantName, { children: "'s screen" })] })) })), _jsx(ConnectionQualityIndicator, { className: "lk-participant-metadata-item" })] }))] })), _jsx(FocusToggle, { trackRef: trackReference })] })) })) })));
59
+ }, show: 'muted' }), _jsx(ParticipantName, { children: !disableTileActions && _jsx(ParticipantTileActions, {}) })] })) : (_jsxs(_Fragment, { children: [_jsx(ScreenShareIcon, { style: { marginRight: '0.25rem' } }), _jsx(ParticipantName, { children: "'s screen" })] })) })), _jsx(ConnectionQualityIndicator, { className: "lk-participant-metadata-item" })] }))] })), !disableTileFocusToggle && _jsx(FocusToggle, { trackRef: trackReference })] })) })) })));
60
60
  });
@@ -1,5 +1,5 @@
1
1
  import type { CreateLocalTracksOptions, LocalAudioTrack, LocalTrack, LocalVideoTrack } from 'livekit-client';
2
- import { Track } from 'livekit-client';
2
+ import { Track, TrackProcessor } from 'livekit-client';
3
3
  import * as React from 'react';
4
4
  import type { LocalUserChoices } from '@livekit/components-core';
5
5
  /**
@@ -28,6 +28,7 @@ export interface PreJoinProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
28
28
  * @alpha
29
29
  */
30
30
  persistUserChoices?: boolean;
31
+ videoProcessor?: TrackProcessor<Track.Kind.Video>;
31
32
  }
32
33
  /** @alpha */
33
34
  export declare function usePreviewTracks(options: CreateLocalTracksOptions, onError?: (err: Error) => void): {
@@ -55,4 +56,4 @@ export declare function usePreviewDevice<T extends LocalVideoTrack | LocalAudioT
55
56
  * ```
56
57
  * @public
57
58
  */
58
- export declare function PreJoin({ defaults, onValidate, onSubmit, onError, debug, joinLabel, micLabel, camLabel, userLabel, persistUserChoices, ...htmlProps }: PreJoinProps): JSX.Element;
59
+ export declare function PreJoin({ defaults, onValidate, onSubmit, onError, debug, joinLabel, micLabel, camLabel, userLabel, persistUserChoices, videoProcessor, ...htmlProps }: PreJoinProps): JSX.Element;
@@ -10,6 +10,12 @@ import ParticipantTileAvatar from './ParticipantTileAvatar';
10
10
  import { useEffect, useMemo } from 'react';
11
11
  import { TrackToggle } from './TrackToggle';
12
12
  import { useLiveStream } from './LiveStreamProvider';
13
+ import { BackgroundBlur } from '@livekit/track-processors';
14
+ import LiveStreamSettingsMenu from './LiveStreamSettingsMenu';
15
+ import { isClientSideRendering } from '@selfcommunity/utils';
16
+ import { CHOICE_VIDEO_BLUR_EFFECT } from '../../../constants/LiveStream';
17
+ import { FormattedMessage } from 'react-intl';
18
+ import { useSnackbar } from 'notistack';
13
19
  /** @alpha */
14
20
  export function usePreviewTracks(options, onError) {
15
21
  const [tracks, setTracks] = React.useState();
@@ -152,7 +158,8 @@ export function usePreviewDevice(enabled, deviceId, kind) {
152
158
  * @public
153
159
  */
154
160
  export function PreJoin(_a) {
155
- var { defaults = {}, onValidate, onSubmit, onError, debug, joinLabel = 'Join Room', micLabel = 'Microphone', camLabel = 'Camera', userLabel = 'Username', persistUserChoices = true } = _a, htmlProps = __rest(_a, ["defaults", "onValidate", "onSubmit", "onError", "debug", "joinLabel", "micLabel", "camLabel", "userLabel", "persistUserChoices"]);
161
+ var _b;
162
+ var { defaults = {}, onValidate, onSubmit, onError, debug, joinLabel = 'Join Room', micLabel = 'Microphone', camLabel = 'Camera', userLabel = 'Username', persistUserChoices = true, videoProcessor } = _a, htmlProps = __rest(_a, ["defaults", "onValidate", "onSubmit", "onError", "debug", "joinLabel", "micLabel", "camLabel", "userLabel", "persistUserChoices", "videoProcessor"]);
156
163
  const { liveStream } = useLiveStream();
157
164
  const scUserContext = useSCUser();
158
165
  const [userChoices, setUserChoices] = React.useState(defaultUserChoices);
@@ -165,12 +172,16 @@ export function PreJoin(_a) {
165
172
  preventSave: !persistUserChoices,
166
173
  preventLoad: !persistUserChoices
167
174
  });
175
+ const { enqueueSnackbar } = useSnackbar();
168
176
  // Initialize device settings
169
177
  const [audioEnabled, setAudioEnabled] = React.useState(initialUserChoices.audioEnabled && canUseAudio);
170
178
  const [videoEnabled, setVideoEnabled] = React.useState(initialUserChoices.videoEnabled && canUseVideo);
171
179
  const [audioDeviceId, setAudioDeviceId] = React.useState(initialUserChoices.audioDeviceId);
172
180
  const [videoDeviceId, setVideoDeviceId] = React.useState(initialUserChoices.videoDeviceId);
173
181
  const [username, setUsername] = React.useState(initialUserChoices.username);
182
+ // Processors
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);
184
+ const [processorPending, setProcessorPending] = React.useState(false);
174
185
  // Save user choices to persistent storage.
175
186
  React.useEffect(() => {
176
187
  saveAudioInputEnabled(audioEnabled && canUseAudio);
@@ -225,6 +236,12 @@ export function PreJoin(_a) {
225
236
  ((values.videoEnabled && values.videoDeviceId) || !values.videoEnabled));
226
237
  }
227
238
  }, [onValidate]);
239
+ const handleBlur = React.useCallback(() => {
240
+ var _a;
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());
244
+ }, [setBlurEnabled, blurEnabled]);
228
245
  useEffect(() => {
229
246
  const newUserChoices = {
230
247
  username,
@@ -236,6 +253,32 @@ export function PreJoin(_a) {
236
253
  setUserChoices(newUserChoices);
237
254
  setIsValid(handleValidation(newUserChoices));
238
255
  }, [username, scUserContext.user, videoEnabled, handleValidation, audioEnabled, audioDeviceId, videoDeviceId]);
256
+ useEffect(() => {
257
+ var _a;
258
+ if (videoTrack && videoEnabled) {
259
+ setProcessorPending(true);
260
+ try {
261
+ if (blurEnabled && !videoTrack.getProcessor()) {
262
+ videoTrack.setProcessor(BackgroundBlur(20));
263
+ }
264
+ else if (!blurEnabled) {
265
+ videoTrack.stopProcessor();
266
+ }
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
+ }
277
+ finally {
278
+ setProcessorPending(false);
279
+ }
280
+ }
281
+ }, [blurEnabled, videoTrack, videoEnabled]);
239
282
  function handleSubmit(event) {
240
283
  event.preventDefault();
241
284
  if (handleValidation(userChoices)) {
@@ -247,5 +290,5 @@ export function PreJoin(_a) {
247
290
  log.warn('Validation failed with: ', userChoices);
248
291
  }
249
292
  }
250
- return (_jsxs("div", Object.assign({ className: "lk-prejoin" }, htmlProps, { children: [_jsxs("div", Object.assign({ className: "lk-video-container" }, { children: [videoTrack && _jsx("video", { ref: videoEl, width: "1280", height: "720", "data-lk-facing-mode": facingMode }), (!videoTrack || !videoEnabled) && (_jsx("div", Object.assign({ className: "lk-camera-off-note" }, { children: _jsx(ParticipantTileAvatar, { user: scUserContext.user }) })))] })), _jsxs("div", Object.assign({ className: "lk-button-group-container" }, { children: [_jsxs("div", Object.assign({ className: "lk-button-group audio" }, { children: [_jsx(TrackToggle, Object.assign({ disabled: !canUseAudio, initialState: audioEnabled, source: Track.Source.Microphone, onChange: (enabled) => setAudioEnabled(enabled) }, { children: micLabel })), _jsx("div", Object.assign({ className: "lk-button-group-menu" }, { children: _jsx(MediaDeviceMenu, { initialSelection: audioDeviceId, kind: "audioinput", disabled: !audioTrack || !canUseAudio || !audioEnabled, tracks: { audioinput: audioTrack }, onActiveDeviceChange: (_, id) => setAudioDeviceId(id) }) }))] })), _jsxs("div", Object.assign({ className: "lk-button-group video" }, { children: [_jsx(TrackToggle, Object.assign({ disabled: !canUseVideo, initialState: videoEnabled, source: Track.Source.Camera, onChange: (enabled) => setVideoEnabled(enabled) }, { children: camLabel })), _jsx("div", Object.assign({ className: "lk-button-group-menu" }, { children: _jsx(MediaDeviceMenu, { initialSelection: videoDeviceId, kind: "videoinput", disabled: !videoTrack || !canUseVideo || !videoEnabled, tracks: { videoinput: videoTrack }, onActiveDeviceChange: (_, id) => setVideoDeviceId(id) }) }))] }))] })), _jsx("form", Object.assign({ className: "lk-username-container" }, { children: _jsx("button", Object.assign({ className: "lk-button lk-join-button", type: "submit", onClick: handleSubmit, disabled: !isValid || error }, { children: joinLabel })) })), debug && (_jsxs(_Fragment, { children: [_jsx("strong", { children: "User Choices:" }), _jsxs("ul", Object.assign({ className: "lk-list", style: { overflow: 'hidden', maxWidth: '15rem' } }, { children: [_jsxs("li", { children: ["Username: ", `${userChoices.username}`] }), _jsxs("li", { children: ["Video Enabled: ", `${userChoices.videoEnabled}`] }), _jsxs("li", { children: ["Audio Enabled: ", `${userChoices.audioEnabled}`] }), _jsxs("li", { children: ["Video Device: ", `${userChoices.videoDeviceId}`] }), _jsxs("li", { children: ["Audio Device: ", `${userChoices.audioDeviceId}`] })] }))] }))] })));
293
+ return (_jsxs("div", Object.assign({ className: "lk-prejoin" }, htmlProps, { children: [_jsxs("div", Object.assign({ className: "lk-video-container" }, { children: [videoTrack && _jsx("video", { ref: videoEl, width: "1280", height: "720", "data-lk-facing-mode": facingMode }), (!videoTrack || !videoEnabled) && (_jsx("div", Object.assign({ className: "lk-camera-off-note" }, { children: _jsx(ParticipantTileAvatar, { user: scUserContext.user }) })))] })), _jsxs("div", Object.assign({ className: "lk-button-group-container" }, { children: [_jsxs("div", Object.assign({ className: "lk-button-group audio" }, { children: [_jsx(TrackToggle, Object.assign({ disabled: !canUseAudio, initialState: audioEnabled, source: Track.Source.Microphone, onChange: (enabled) => setAudioEnabled(enabled) }, { children: micLabel })), _jsx("div", Object.assign({ className: "lk-button-group-menu" }, { children: _jsx(MediaDeviceMenu, { initialSelection: audioDeviceId, kind: "audioinput", disabled: !audioTrack || !canUseAudio || !audioEnabled, tracks: { audioinput: audioTrack }, onActiveDeviceChange: (_, id) => setAudioDeviceId(id) }) }))] })), _jsxs("div", Object.assign({ className: "lk-button-group video" }, { children: [_jsx(TrackToggle, Object.assign({ disabled: !canUseVideo, initialState: videoEnabled, source: Track.Source.Camera, onChange: (enabled) => setVideoEnabled(enabled) }, { children: camLabel })), _jsx("div", Object.assign({ className: "lk-button-group-menu" }, { children: _jsx(MediaDeviceMenu, { initialSelection: videoDeviceId, kind: "videoinput", disabled: !videoTrack || !canUseVideo || !videoEnabled, tracks: { videoinput: videoTrack }, onActiveDeviceChange: (_, id) => setVideoDeviceId(id) }) }))] })), _jsx(LiveStreamSettingsMenu, { actionBlurDisabled: !canUseVideo || !videoEnabled, blurEnabled: blurEnabled, handleBlur: handleBlur })] })), _jsx("form", Object.assign({ className: "lk-username-container" }, { children: _jsx("button", Object.assign({ className: "lk-button lk-join-button", type: "submit", onClick: handleSubmit, disabled: !isValid || error }, { children: joinLabel })) })), debug && (_jsxs(_Fragment, { children: [_jsx("strong", { children: "User Choices:" }), _jsxs("ul", Object.assign({ className: "lk-list", style: { overflow: 'hidden', maxWidth: '15rem' } }, { children: [_jsxs("li", { children: ["Username: ", `${userChoices.username}`] }), _jsxs("li", { children: ["Video Enabled: ", `${userChoices.videoEnabled}`] }), _jsxs("li", { children: ["Audio Enabled: ", `${userChoices.audioEnabled}`] }), _jsxs("li", { children: ["Video Device: ", `${userChoices.videoDeviceId}`] }), _jsxs("li", { children: ["Audio Device: ", `${userChoices.audioDeviceId}`] })] }))] }))] })));
251
294
  }
@@ -1,19 +1,27 @@
1
1
  import { __rest } from "tslib";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import * as React from 'react';
4
4
  import { isEqualTrackRef, isTrackReference, isWeb, log } from '@livekit/components-core';
5
5
  import { RoomEvent, Track } from 'livekit-client';
6
- import { CarouselLayout, Chat, ConnectionStateToast, GridLayout, LayoutContextProvider, RoomAudioRenderer, useCreateLayoutContext, useParticipants, usePinnedTracks, useTracks } from '@livekit/components-react';
6
+ import { CarouselLayout, Chat, ConnectionStateToast, GridLayout, LayoutContextProvider, RoomAudioRenderer, useCreateLayoutContext, useLocalParticipant, useParticipants, usePinnedTracks, useTracks } from '@livekit/components-react';
7
7
  import { ParticipantTile } from './ParticipantTile';
8
8
  import { ControlBar } from './ControlBar';
9
- import { useEffect } from 'react';
9
+ import { useEffect, useMemo } from 'react';
10
10
  import { useLivestreamCheck } from './useLiveStreamCheck';
11
11
  import { FocusLayout, FocusLayoutContainer, FocusLayoutContainerNoParticipants } from './FocusLayout';
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
+ import NoParticipants from './NoParticipants';
18
+ import LiveStreamSettingsMenu from './LiveStreamSettingsMenu';
19
+ import { BackgroundBlur } from '@livekit/track-processors';
20
+ import { isClientSideRendering } from '@selfcommunity/utils';
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';
17
25
  const PREFIX = 'SCVideoConference';
18
26
  const classes = {
19
27
  root: `${PREFIX}-root`
@@ -34,7 +42,7 @@ const Root = styled(Box, {
34
42
  *
35
43
  */
36
44
  export function VideoConference(inProps) {
37
- var _a, _b;
45
+ var _a, _b, _c;
38
46
  // PROPS
39
47
  const props = useThemeProps({
40
48
  props: inProps,
@@ -51,15 +59,35 @@ export function VideoConference(inProps) {
51
59
  const lastAutoFocusedScreenShareTrack = React.useRef(null);
52
60
  // HOOKS
53
61
  const scUserContext = useSCUser();
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);
63
+ const [processorPending, setProcessorPending] = React.useState(false);
54
64
  const tracks = useTracks([
55
65
  { source: Track.Source.Camera, withPlaceholder: true },
56
66
  { source: Track.Source.ScreenShare, withPlaceholder: false }
57
67
  ], { updateOnlyOn: [RoomEvent.ActiveSpeakersChanged], onlySubscribed: false });
68
+ const tracksNoParticipants = useMemo(() => tracks.filter((t) => t.participant.name === scUserContext.user.username || t.participant.name === speakerFocused.username || t.source === 'screen_share'), [tracks, scUserContext.user]);
69
+ const handleBlur = React.useCallback((event) => {
70
+ var _a, _b;
71
+ if (event.target) {
72
+ if ('checked' in event.target) {
73
+ setBlurEnabled((_a = event.target) === null || _a === void 0 ? void 0 : _a.checked);
74
+ }
75
+ else {
76
+ setBlurEnabled((enabled) => !enabled);
77
+ }
78
+ }
79
+ else {
80
+ setBlurEnabled((enabled) => !enabled);
81
+ }
82
+ (_b = window === null || window === void 0 ? void 0 : window.localStorage) === null || _b === void 0 ? void 0 : _b.setItem(CHOICE_VIDEO_BLUR_EFFECT, (!blurEnabled).toString());
83
+ }, [setBlurEnabled, blurEnabled]);
58
84
  const participants = useParticipants();
59
85
  const layoutContext = useCreateLayoutContext();
60
86
  const screenShareTracks = tracks.filter(isTrackReference).filter((track) => track.publication.source === Track.Source.ScreenShare);
61
- const focusTrack = (_a = usePinnedTracks(layoutContext)) === null || _a === void 0 ? void 0 : _a[0];
87
+ const focusTrack = (_b = usePinnedTracks(layoutContext)) === null || _b === void 0 ? void 0 : _b[0];
62
88
  const carouselTracks = tracks.filter((track) => !isEqualTrackRef(track, focusTrack));
89
+ const { cameraTrack } = useLocalParticipant();
90
+ const { enqueueSnackbar } = useSnackbar();
63
91
  useLivestreamCheck();
64
92
  /**
65
93
  * widgetUpdate
@@ -115,7 +143,7 @@ export function VideoConference(inProps) {
115
143
  }
116
144
  }, [
117
145
  screenShareTracks.map((ref) => `${ref.publication.trackSid}_${ref.publication.isSubscribed}`).join(),
118
- (_b = focusTrack === null || focusTrack === void 0 ? void 0 : focusTrack.publication) === null || _b === void 0 ? void 0 : _b.trackSid,
146
+ (_c = focusTrack === null || focusTrack === void 0 ? void 0 : focusTrack.publication) === null || _c === void 0 ? void 0 : _c.trackSid,
119
147
  tracks,
120
148
  participants,
121
149
  speakerFocused
@@ -138,10 +166,37 @@ export function VideoConference(inProps) {
138
166
  }
139
167
  }
140
168
  }, [tracks, participants, speakerFocused]);
141
- return (_jsxs(Root, Object.assign({ className: classNames(className, classes.root, 'lk-video-conference') }, rest, { children: [isWeb() && (_jsxs(LayoutContextProvider, Object.assign({ value: layoutContext, onPinChange: handleFocusStateChange, onWidgetChange: widgetUpdate }, { children: [_jsxs("div", Object.assign({ className: "lk-video-conference-inner" }, { children: [!focusTrack ? (_jsx("div", Object.assign({ className: "lk-grid-layout-wrapper" }, { children: _jsx(GridLayout, Object.assign({ tracks: tracks }, { children: _jsx(ParticipantTile, {}) })) }))) : (_jsx("div", Object.assign({ className: "lk-focus-layout-wrapper" }, { children: hideParticipantsList ? (_jsx(FocusLayoutContainerNoParticipants, { children: focusTrack && _jsx(FocusLayout, { trackRef: focusTrack }) })) : (_jsxs(FocusLayoutContainer, { children: [_jsx(CarouselLayout, Object.assign({ tracks: carouselTracks }, { children: _jsx(ParticipantTile, {}) })), focusTrack && _jsx(FocusLayout, { trackRef: focusTrack })] })) }))), _jsx(ControlBar, { controls: Object.assign({
169
+ useEffect(() => {
170
+ var _a;
171
+ const localCamTrack = cameraTrack === null || cameraTrack === void 0 ? void 0 : cameraTrack.track;
172
+ if (localCamTrack) {
173
+ setProcessorPending(true);
174
+ try {
175
+ if (blurEnabled && !localCamTrack.getProcessor()) {
176
+ localCamTrack.setProcessor(BackgroundBlur(20));
177
+ }
178
+ else if (!blurEnabled) {
179
+ localCamTrack.stopProcessor();
180
+ }
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
+ }
191
+ finally {
192
+ setProcessorPending(false);
193
+ }
194
+ }
195
+ }, [blurEnabled, cameraTrack]);
196
+ return (_jsxs(Root, Object.assign({ className: classNames(className, classes.root, 'lk-video-conference') }, rest, { children: [isWeb() && (_jsxs(LayoutContextProvider, Object.assign({ value: layoutContext, onPinChange: handleFocusStateChange, onWidgetChange: widgetUpdate }, { children: [_jsxs("div", Object.assign({ className: "lk-video-conference-inner" }, { children: [!focusTrack ? (_jsx("div", Object.assign({ className: "lk-grid-layout-wrapper" }, { children: _jsx(GridLayout, Object.assign({ tracks: hideParticipantsList ? tracksNoParticipants : tracks }, { children: _jsx(ParticipantTile, {}) })) }))) : (_jsx("div", Object.assign({ className: "lk-focus-layout-wrapper" }, { children: hideParticipantsList ? (_jsx(FocusLayoutContainerNoParticipants, { children: focusTrack && _jsx(FocusLayout, { trackRef: focusTrack }) })) : (_jsxs(FocusLayoutContainer, { children: [carouselTracks.length ? (_jsx(CarouselLayout, Object.assign({ tracks: carouselTracks }, { children: _jsx(ParticipantTile, {}) }))) : (_jsx(NoParticipants, {})), focusTrack && _jsx(FocusLayout, { trackRef: focusTrack })] })) }))), _jsx(ControlBar, { controls: Object.assign({
142
197
  chat: !disableChat,
143
198
  microphone: !disableMicrophone,
144
199
  camera: !disableCamera,
145
200
  screenShare: !disableShareScreen
146
- }, { settings: !!SettingsComponent }) })] })), !disableChat && (_jsx(Chat, { style: { display: widgetState.showChat ? 'grid' : 'none' }, messageFormatter: chatMessageFormatter, messageEncoder: chatMessageEncoder, messageDecoder: chatMessageDecoder })), SettingsComponent && (_jsx("div", Object.assign({ className: "lk-settings-menu-modal", style: { display: widgetState.showSettings ? 'block' : 'none' } }, { children: _jsx(SettingsComponent, {}) })))] }))), _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, {})] })));
147
202
  }
@@ -1,3 +1,4 @@
1
1
  export declare const LIVE_STREAM_TITLE_MAX_LENGTH = 100;
2
2
  export declare const LIVE_STREAM_SLUG_MAX_LENGTH = 50;
3
3
  export declare const LIVE_STREAM_DESCRIPTION_MAX_LENGTH = 500;
4
+ export declare const CHOICE_VIDEO_BLUR_EFFECT = "lk-video-blur";
@@ -1,3 +1,4 @@
1
1
  export const LIVE_STREAM_TITLE_MAX_LENGTH = 100;
2
2
  export const LIVE_STREAM_SLUG_MAX_LENGTH = 50;
3
3
  export const LIVE_STREAM_DESCRIPTION_MAX_LENGTH = 500;
4
+ export const CHOICE_VIDEO_BLUR_EFFECT = 'lk-video-blur';
@@ -20,7 +20,7 @@ export default function AutoPlayer(props) {
20
20
  const [played, setPlayed] = useState(0);
21
21
  useEffect(() => {
22
22
  if (played >= 10 && played <= 11) {
23
- onVideoWatch();
23
+ onVideoWatch === null || onVideoWatch === void 0 ? void 0 : onVideoWatch();
24
24
  }
25
25
  }, [played]);
26
26
  /**
@@ -3,6 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { styled } from '@mui/material/styles';
4
4
  import { useThemeProps } from '@mui/system';
5
5
  import { FormattedMessage } from 'react-intl';
6
+ import { SCPreferences, useSCPreferences } from '@selfcommunity/react-core';
6
7
  import { Chip, Tooltip } from '@mui/material';
7
8
  import { useMemo } from 'react';
8
9
  import { SCCommunitySubscriptionTier } from '@selfcommunity/types';
@@ -28,6 +29,11 @@ export default function UpScalingTierBadge(inProps) {
28
29
  name: PREFIX
29
30
  });
30
31
  const { className, desiredTier = SCCommunitySubscriptionTier.GO } = props, rest = __rest(props, ["className", "desiredTier"]);
32
+ const { preferences } = useSCPreferences();
33
+ const isEnterpriseTier = useMemo(() => preferences &&
34
+ SCPreferences.CONFIGURATIONS_SUBSCRIPTION_TIER in preferences &&
35
+ preferences[SCPreferences.CONFIGURATIONS_SUBSCRIPTION_TIER].value &&
36
+ preferences[SCPreferences.CONFIGURATIONS_SUBSCRIPTION_TIER].value === SCCommunitySubscriptionTier.ENTERPRISE, [preferences]);
31
37
  const tooltipMsg = useMemo(() => {
32
38
  let _msg = _jsx(FormattedMessage, { id: "ui.upScalingTierBadge.goFeature", defaultMessage: "ui.upScalingTierBadge.goFeature" });
33
39
  switch (desiredTier) {
@@ -56,5 +62,8 @@ export default function UpScalingTierBadge(inProps) {
56
62
  }
57
63
  return _label;
58
64
  }, [desiredTier]);
65
+ if (desiredTier === SCCommunitySubscriptionTier.ENTERPRISE && isEnterpriseTier) {
66
+ return null;
67
+ }
59
68
  return (_jsx(Root, Object.assign({ classes: { root: classNames(className, classes.root) }, title: tooltipMsg, placement: "top" }, rest, { children: _jsx(Badge, { color: "secondary", size: "small", label: badgeLabel, className: classes.badge }) })));
60
69
  }
@@ -51,8 +51,7 @@ export function getContributionSnippet(obj) {
51
51
  * @param handleUrl Func that handle urls
52
52
  */
53
53
  export function getContributionHtml(html, handleUrl) {
54
- const _html = html.replace(/<p\b[^>]*>(.*?)<\/p>/g, (match, content) => content);
55
- return _html.replace(/<mention.*? id="([0-9]+)"{1}.*?>@([a-z\d_-]+)<\/mention>/gi, (match, id, username) => {
54
+ return html.replace(/<mention.*? id="([0-9]+)"{1}.*?>@([a-z\d_-]+)<\/mention>/gi, (match, id, username) => {
56
55
  return `<a href='${handleUrl(SCRoutes.USER_PROFILE_ROUTE_NAME, { id, username })}'>@${username}</a>`;
57
56
  });
58
57
  }