@selfcommunity/react-ui 0.10.5-alpha.12 → 0.10.5-alpha.14

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.
@@ -46,10 +46,10 @@ function CreateEventWidget(inProps) {
46
46
  react_core_1.SCPreferences.CONFIGURATIONS_EVENTS_ENABLED in preferences &&
47
47
  preferences[react_core_1.SCPreferences.CONFIGURATIONS_EVENTS_ENABLED].value, [preferences, features]);
48
48
  const authUserId = scUserContext.user ? scUserContext.user.id : null;
49
- const onlyStaffEnabled = (0, react_1.useMemo)(() => preferences[react_core_1.SCPreferences.CONFIGURATIONS_GROUPS_ONLY_STAFF_ENABLED].value, [preferences]);
49
+ const onlyStaffEnabled = (0, react_1.useMemo)(() => preferences[react_core_1.SCPreferences.CONFIGURATIONS_EVENTS_ONLY_STAFF_ENABLED].value, [preferences]);
50
50
  // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
51
51
  // @ts-ignore
52
- const canCreateEvent = (0, react_1.useMemo)(() => { var _a, _b; return (_b = (_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.create_group; }, [(_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission]);
52
+ const canCreateEvent = (0, react_1.useMemo)(() => { var _a, _b; return (_b = (_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.create_event; }, [(_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission]);
53
53
  (0, react_1.useEffect)(() => {
54
54
  setLoading(false);
55
55
  }, []);
@@ -87,6 +87,6 @@ function CreateLiveStreamButton(inProps) {
87
87
  /**
88
88
  * Renders root object
89
89
  */
90
- return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [(0, jsx_runtime_1.jsx)(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className), onClick: handleClose, variant: "contained", color: "secondary", startIcon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "photo_camera" }) }, rest, { children: children !== null && children !== void 0 ? children : (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.createEventButton.goLive", defaultMessage: "ui.createEventButton.goLive" }) })), open && (0, jsx_runtime_1.jsx)(CreateLiveStreamDialog_1.default, Object.assign({ open: true, onClose: handleClose, onSuccess: handleSuccess }, CreateLiveStreamDialogComponentProps))] }));
90
+ return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [(0, jsx_runtime_1.jsx)(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className), onClick: handleClose, variant: "contained", color: "secondary", startIcon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "movie" }) }, rest, { children: children !== null && children !== void 0 ? children : (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.createEventButton.goLive", defaultMessage: "ui.createEventButton.goLive" }) })), open && (0, jsx_runtime_1.jsx)(CreateLiveStreamDialog_1.default, Object.assign({ open: true, onClose: handleClose, onSuccess: handleSuccess }, CreateLiveStreamDialogComponentProps))] }));
91
91
  }
92
92
  exports.default = CreateLiveStreamButton;
@@ -143,8 +143,8 @@ function LiveStreamRoom(inProps) {
143
143
  ? scRoutingContext.url(react_core_1.SCRoutes.EVENT_ROUTE_NAME, scLiveStream.event)
144
144
  : '/' }, { children: chunks })))
145
145
  } }));
146
- if (error.response.data.errors[0].code !== types_1.SCLiveStreamConnectionDetailsErrorType.WAITING_HOST_TO_START_LIVE_STREAM &&
147
- error.response.data.errors[0].code !== types_1.SCLiveStreamConnectionDetailsErrorType.PARTICIPANTS_LIMIT_REACHED) {
146
+ if (error.response.data.errors[0].code === types_1.SCLiveStreamConnectionDetailsErrorType.WAITING_HOST_TO_START_LIVE_STREAM ||
147
+ error.response.data.errors[0].code === types_1.SCLiveStreamConnectionDetailsErrorType.PARTICIPANTS_LIMIT_REACHED) {
148
148
  setError(_msg);
149
149
  }
150
150
  else {
@@ -178,7 +178,21 @@ function LiveStreamRoom(inProps) {
178
178
  /**
179
179
  * Handle PreJoin Error
180
180
  */
181
- const handlePreJoinError = (0, react_1.useCallback)((e) => console.error(e), []);
181
+ const handlePreJoinError = (0, react_1.useCallback)((e) => {
182
+ console.error(e);
183
+ if (e.message !== 'NotAllowedError: Permission denied') {
184
+ enqueueSnackbar(intl.formatMessage({
185
+ id: 'ui.liveStreamRoom.connect.error.device.permission',
186
+ defaultMessage: 'ui.liveStreamRoom.connect.error.device.permission'
187
+ }), { variant: 'error', autoHideDuration: 5000 });
188
+ }
189
+ else if (e.message !== 'NotFoundError: Requested device not found') {
190
+ enqueueSnackbar(intl.formatMessage({
191
+ id: 'ui.liveStreamRoom.connect.error.device.notFound',
192
+ defaultMessage: 'ui.liveStreamRoom.connect.error.device.notFound'
193
+ }), { variant: 'error', autoHideDuration: 5000 });
194
+ }
195
+ }, []);
182
196
  /**
183
197
  * User must be authenticated
184
198
  */
@@ -75,6 +75,8 @@ function LiveStreamVideoConference(inProps) {
75
75
  // STATE
76
76
  const [liveActive, setLiveActive] = (0, react_1.useState)(true);
77
77
  const [error, setError] = (0, react_1.useState)(null);
78
+ // INTL
79
+ const intl = (0, react_intl_1.useIntl)();
78
80
  // PREFERENCES
79
81
  const preferences = (0, react_1.useMemo)(() => {
80
82
  const _preferences = {};
@@ -107,8 +109,24 @@ function LiveStreamVideoConference(inProps) {
107
109
  */
108
110
  const handleError = (0, react_1.useCallback)((error) => {
109
111
  console.error(error);
110
- if (error.message !== 'Client initiated disconnect') {
111
- setError(`Encountered an unexpected error, check the console logs for details: ${error.message}`);
112
+ if (error.message === 'Permission denied') {
113
+ setError(intl.formatMessage({
114
+ id: 'ui.liveStreamRoom.connect.error.device.permission',
115
+ defaultMessage: 'ui.liveStreamRoom.connect.error.device.permission'
116
+ }));
117
+ }
118
+ else if (error.message === 'Requested device not found') {
119
+ setError(intl.formatMessage({
120
+ id: 'ui.liveStreamRoom.connect.error.device.notFound',
121
+ defaultMessage: 'ui.liveStreamRoom.connect.error.device.notFound'
122
+ }));
123
+ }
124
+ else {
125
+ console.log(`Encountered an unexpected error, check the console logs for details: ${error.message}`);
126
+ setError(intl.formatMessage({
127
+ id: 'ui.liveStreamRoom.connect.error.clientInitiatedDisconnect',
128
+ defaultMessage: 'ui.liveStreamRoom.connect.error.clientInitiatedDisconnect'
129
+ }));
112
130
  }
113
131
  setLiveActive(false);
114
132
  }, []);
@@ -30,7 +30,10 @@ export interface PreJoinProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
30
30
  persistUserChoices?: boolean;
31
31
  }
32
32
  /** @alpha */
33
- export declare function usePreviewTracks(options: CreateLocalTracksOptions, onError?: (err: Error) => void): LocalTrack<Track.Kind>[];
33
+ export declare function usePreviewTracks(options: CreateLocalTracksOptions, onError?: (err: Error) => void): {
34
+ tracks: LocalTrack<Track.Kind>[];
35
+ error: boolean;
36
+ };
34
37
  /** @public */
35
38
  export declare function usePreviewDevice<T extends LocalVideoTrack | LocalAudioTrack>(enabled: boolean, deviceId: string, kind: 'videoinput' | 'audioinput'): {
36
39
  selectedDevice: MediaDeviceInfo;
@@ -16,6 +16,7 @@ const LiveStreamProvider_1 = require("./LiveStreamProvider");
16
16
  /** @alpha */
17
17
  function usePreviewTracks(options, onError) {
18
18
  const [tracks, setTracks] = React.useState();
19
+ const [error, setError] = React.useState(false);
19
20
  const trackLock = React.useMemo(() => new livekit_client_1.Mutex(), []);
20
21
  React.useEffect(() => {
21
22
  let needsCleanup = false;
@@ -30,6 +31,7 @@ function usePreviewTracks(options, onError) {
30
31
  else {
31
32
  setTracks(localTracks);
32
33
  }
34
+ setError(false);
33
35
  }
34
36
  }
35
37
  catch (e) {
@@ -39,6 +41,7 @@ function usePreviewTracks(options, onError) {
39
41
  else {
40
42
  components_core_1.log.error(e);
41
43
  }
44
+ setError(true);
42
45
  }
43
46
  finally {
44
47
  unlock();
@@ -49,9 +52,10 @@ function usePreviewTracks(options, onError) {
49
52
  localTracks.forEach((track) => {
50
53
  track.stop();
51
54
  });
55
+ setError(false);
52
56
  };
53
57
  }, [JSON.stringify(options), onError, trackLock]);
54
- return tracks;
58
+ return { tracks, error };
55
59
  }
56
60
  exports.usePreviewTracks = usePreviewTracks;
57
61
  /** @public */
@@ -190,7 +194,7 @@ function PreJoin(_a) {
190
194
  saveUsername(scUserContext.user.username);
191
195
  }
192
196
  }, [username, saveUsername, scUserContext.user]);
193
- const tracks = usePreviewTracks({
197
+ const { tracks, error } = usePreviewTracks({
194
198
  audio: audioEnabled ? { deviceId: initialUserChoices.audioDeviceId } : false,
195
199
  video: videoEnabled ? { deviceId: initialUserChoices.videoDeviceId } : false
196
200
  }, onError);
@@ -221,7 +225,9 @@ function PreJoin(_a) {
221
225
  return onValidate(values);
222
226
  }
223
227
  else {
224
- return values.username !== '';
228
+ return Boolean(values.username !== '' &&
229
+ ((values.audioEnabled && values.audioDeviceId) || !values.audioEnabled) &&
230
+ ((values.videoEnabled && values.videoDeviceId) || !values.videoEnabled));
225
231
  }
226
232
  }, [onValidate]);
227
233
  (0, react_1.useEffect)(() => {
@@ -246,6 +252,6 @@ function PreJoin(_a) {
246
252
  components_core_1.log.warn('Validation failed with: ', userChoices);
247
253
  }
248
254
  }
249
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-prejoin" }, htmlProps, { children: [(0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-video-container" }, { children: [videoTrack && (0, jsx_runtime_1.jsx)("video", { ref: videoEl, width: "1280", height: "720", "data-lk-facing-mode": facingMode }), (!videoTrack || !videoEnabled) && ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-camera-off-note" }, { children: (0, jsx_runtime_1.jsx)(ParticipantTileAvatar_1.default, { user: scUserContext.user }) })))] })), (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-button-group-container" }, { children: [(0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-button-group audio" }, { children: [(0, jsx_runtime_1.jsx)(TrackToggle_1.TrackToggle, Object.assign({ disabled: !canUseAudio, initialState: audioEnabled, source: livekit_client_1.Track.Source.Microphone, onChange: (enabled) => setAudioEnabled(enabled) }, { children: micLabel })), (0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-button-group-menu" }, { children: (0, jsx_runtime_1.jsx)(components_react_1.MediaDeviceMenu, { initialSelection: audioDeviceId, kind: "audioinput", disabled: !audioTrack || !canUseAudio, tracks: { audioinput: audioTrack }, onActiveDeviceChange: (_, id) => setAudioDeviceId(id) }) }))] })), (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-button-group video" }, { children: [(0, jsx_runtime_1.jsx)(TrackToggle_1.TrackToggle, Object.assign({ disabled: !canUseVideo, initialState: videoEnabled, source: livekit_client_1.Track.Source.Camera, onChange: (enabled) => setVideoEnabled(enabled) }, { children: camLabel })), (0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-button-group-menu" }, { children: (0, jsx_runtime_1.jsx)(components_react_1.MediaDeviceMenu, { initialSelection: videoDeviceId, kind: "videoinput", disabled: !videoTrack || !canUseVideo, tracks: { videoinput: videoTrack }, onActiveDeviceChange: (_, id) => setVideoDeviceId(id) }) }))] }))] })), (0, jsx_runtime_1.jsx)("form", Object.assign({ className: "lk-username-container" }, { children: (0, jsx_runtime_1.jsx)("button", Object.assign({ className: "lk-button lk-join-button", type: "submit", onClick: handleSubmit, disabled: !isValid }, { children: joinLabel })) })), debug && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("strong", { children: "User Choices:" }), (0, jsx_runtime_1.jsxs)("ul", Object.assign({ className: "lk-list", style: { overflow: 'hidden', maxWidth: '15rem' } }, { children: [(0, jsx_runtime_1.jsxs)("li", { children: ["Username: ", `${userChoices.username}`] }), (0, jsx_runtime_1.jsxs)("li", { children: ["Video Enabled: ", `${userChoices.videoEnabled}`] }), (0, jsx_runtime_1.jsxs)("li", { children: ["Audio Enabled: ", `${userChoices.audioEnabled}`] }), (0, jsx_runtime_1.jsxs)("li", { children: ["Video Device: ", `${userChoices.videoDeviceId}`] }), (0, jsx_runtime_1.jsxs)("li", { children: ["Audio Device: ", `${userChoices.audioDeviceId}`] })] }))] }))] })));
255
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-prejoin" }, htmlProps, { children: [(0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-video-container" }, { children: [videoTrack && (0, jsx_runtime_1.jsx)("video", { ref: videoEl, width: "1280", height: "720", "data-lk-facing-mode": facingMode }), (!videoTrack || !videoEnabled) && ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-camera-off-note" }, { children: (0, jsx_runtime_1.jsx)(ParticipantTileAvatar_1.default, { user: scUserContext.user }) })))] })), (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-button-group-container" }, { children: [(0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-button-group audio" }, { children: [(0, jsx_runtime_1.jsx)(TrackToggle_1.TrackToggle, Object.assign({ disabled: !canUseAudio, initialState: audioEnabled, source: livekit_client_1.Track.Source.Microphone, onChange: (enabled) => setAudioEnabled(enabled) }, { children: micLabel })), (0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-button-group-menu" }, { children: (0, jsx_runtime_1.jsx)(components_react_1.MediaDeviceMenu, { initialSelection: audioDeviceId, kind: "audioinput", disabled: !audioTrack || !canUseAudio || !audioEnabled, tracks: { audioinput: audioTrack }, onActiveDeviceChange: (_, id) => setAudioDeviceId(id) }) }))] })), (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-button-group video" }, { children: [(0, jsx_runtime_1.jsx)(TrackToggle_1.TrackToggle, Object.assign({ disabled: !canUseVideo, initialState: videoEnabled, source: livekit_client_1.Track.Source.Camera, onChange: (enabled) => setVideoEnabled(enabled) }, { children: camLabel })), (0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-button-group-menu" }, { children: (0, jsx_runtime_1.jsx)(components_react_1.MediaDeviceMenu, { initialSelection: videoDeviceId, kind: "videoinput", disabled: !videoTrack || !canUseVideo || !videoEnabled, tracks: { videoinput: videoTrack }, onActiveDeviceChange: (_, id) => setVideoDeviceId(id) }) }))] }))] })), (0, jsx_runtime_1.jsx)("form", Object.assign({ className: "lk-username-container" }, { children: (0, jsx_runtime_1.jsx)("button", Object.assign({ className: "lk-button lk-join-button", type: "submit", onClick: handleSubmit, disabled: !isValid || error }, { children: joinLabel })) })), debug && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("strong", { children: "User Choices:" }), (0, jsx_runtime_1.jsxs)("ul", Object.assign({ className: "lk-list", style: { overflow: 'hidden', maxWidth: '15rem' } }, { children: [(0, jsx_runtime_1.jsxs)("li", { children: ["Username: ", `${userChoices.username}`] }), (0, jsx_runtime_1.jsxs)("li", { children: ["Video Enabled: ", `${userChoices.videoEnabled}`] }), (0, jsx_runtime_1.jsxs)("li", { children: ["Audio Enabled: ", `${userChoices.audioEnabled}`] }), (0, jsx_runtime_1.jsxs)("li", { children: ["Video Device: ", `${userChoices.videoDeviceId}`] }), (0, jsx_runtime_1.jsxs)("li", { children: ["Audio Device: ", `${userChoices.audioDeviceId}`] })] }))] }))] })));
250
256
  }
251
257
  exports.PreJoin = PreJoin;
@@ -38,7 +38,7 @@ function NavigationMenuDrawer(inProps) {
38
38
  });
39
39
  const { className = null, showDrawerHeader = true, drawerHeaderContent = (0, jsx_runtime_1.jsx)(DefaultHeaderContent_1.default, {}), drawerContent = (0, jsx_runtime_1.jsx)(DefaultDrawerContent_1.default, {}), showDrawerFooterContent = true, drawerFooterContent = null, ScrollContainerProps = {}, CreateLiveStreamButtonComponentProps = {}, open, onClose } = props, rest = tslib_1.__rest(props, ["className", "showDrawerHeader", "drawerHeaderContent", "drawerContent", "showDrawerFooterContent", "drawerFooterContent", "ScrollContainerProps", "CreateLiveStreamButtonComponentProps", "open", "onClose"]);
40
40
  const scUserContext = (0, react_core_1.useSCUser)();
41
- const canCreateLiveStream = (0, react_1.useMemo)(() => { var _a, _b; return (_b = (_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.create_livestream; }, [(_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission]);
41
+ const canCreateLiveStream = (0, react_1.useMemo)(() => { var _a, _b; return (_b = (_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.create_live_stream; }, [(_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission]);
42
42
  return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ anchor: "left", className: (0, classnames_1.default)(classes.root, className), open: open, onClose: onClose }, rest, { children: [showDrawerHeader && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: classes.drawerHeader }, { children: [drawerHeaderContent, (0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ className: classes.drawerHeaderAction, onClick: onClose }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "close" }) }))] })), (0, jsx_runtime_1.jsx)(material_1.Divider, {})] })), (0, jsx_runtime_1.jsx)(ScrollContainer_1.default, Object.assign({}, ScrollContainerProps, { children: (0, jsx_runtime_1.jsx)(material_1.List, Object.assign({ className: classes.drawerContent, onClick: onClose }, { children: drawerContent })) })), showDrawerFooterContent && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.drawerFooter }, { children: drawerFooterContent ? (drawerFooterContent) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [canCreateLiveStream && (0, jsx_runtime_1.jsx)(material_1.Divider, {}), (0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.drawerFooterLiveStream }, { children: (0, jsx_runtime_1.jsx)(CreateLiveStreamButton_1.default, Object.assign({ color: "primary", className: classes.drawerFooterLiveStreamButton, fullWidth: true }, CreateLiveStreamButtonComponentProps)) }))] })) })) }))] })));
43
43
  }
44
44
  exports.default = NavigationMenuDrawer;
@@ -44,10 +44,10 @@ export default function CreateEventWidget(inProps) {
44
44
  SCPreferences.CONFIGURATIONS_EVENTS_ENABLED in preferences &&
45
45
  preferences[SCPreferences.CONFIGURATIONS_EVENTS_ENABLED].value, [preferences, features]);
46
46
  const authUserId = scUserContext.user ? scUserContext.user.id : null;
47
- const onlyStaffEnabled = useMemo(() => preferences[SCPreferences.CONFIGURATIONS_GROUPS_ONLY_STAFF_ENABLED].value, [preferences]);
47
+ const onlyStaffEnabled = useMemo(() => preferences[SCPreferences.CONFIGURATIONS_EVENTS_ONLY_STAFF_ENABLED].value, [preferences]);
48
48
  // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
49
49
  // @ts-ignore
50
- const canCreateEvent = useMemo(() => { var _a, _b; return (_b = (_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.create_group; }, [(_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission]);
50
+ const canCreateEvent = useMemo(() => { var _a, _b; return (_b = (_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.create_event; }, [(_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission]);
51
51
  useEffect(() => {
52
52
  setLoading(false);
53
53
  }, []);
@@ -85,5 +85,5 @@ export default function CreateLiveStreamButton(inProps) {
85
85
  /**
86
86
  * Renders root object
87
87
  */
88
- return (_jsxs(React.Fragment, { children: [_jsx(Root, Object.assign({ className: classNames(classes.root, className), onClick: handleClose, variant: "contained", color: "secondary", startIcon: _jsx(Icon, { children: "photo_camera" }) }, rest, { children: children !== null && children !== void 0 ? children : _jsx(FormattedMessage, { id: "ui.createEventButton.goLive", defaultMessage: "ui.createEventButton.goLive" }) })), open && _jsx(CreateLivestreamDialog, Object.assign({ open: true, onClose: handleClose, onSuccess: handleSuccess }, CreateLiveStreamDialogComponentProps))] }));
88
+ return (_jsxs(React.Fragment, { children: [_jsx(Root, Object.assign({ className: classNames(classes.root, className), onClick: handleClose, variant: "contained", color: "secondary", startIcon: _jsx(Icon, { children: "movie" }) }, rest, { children: children !== null && children !== void 0 ? children : _jsx(FormattedMessage, { id: "ui.createEventButton.goLive", defaultMessage: "ui.createEventButton.goLive" }) })), open && _jsx(CreateLivestreamDialog, Object.assign({ open: true, onClose: handleClose, onSuccess: handleSuccess }, CreateLiveStreamDialogComponentProps))] }));
89
89
  }
@@ -141,8 +141,8 @@ export default function LiveStreamRoom(inProps) {
141
141
  ? scRoutingContext.url(SCRoutes.EVENT_ROUTE_NAME, scLiveStream.event)
142
142
  : '/' }, { children: chunks })))
143
143
  } }));
144
- if (error.response.data.errors[0].code !== SCLiveStreamConnectionDetailsErrorType.WAITING_HOST_TO_START_LIVE_STREAM &&
145
- error.response.data.errors[0].code !== SCLiveStreamConnectionDetailsErrorType.PARTICIPANTS_LIMIT_REACHED) {
144
+ if (error.response.data.errors[0].code === SCLiveStreamConnectionDetailsErrorType.WAITING_HOST_TO_START_LIVE_STREAM ||
145
+ error.response.data.errors[0].code === SCLiveStreamConnectionDetailsErrorType.PARTICIPANTS_LIMIT_REACHED) {
146
146
  setError(_msg);
147
147
  }
148
148
  else {
@@ -176,7 +176,21 @@ export default function LiveStreamRoom(inProps) {
176
176
  /**
177
177
  * Handle PreJoin Error
178
178
  */
179
- const handlePreJoinError = useCallback((e) => console.error(e), []);
179
+ const handlePreJoinError = useCallback((e) => {
180
+ console.error(e);
181
+ if (e.message !== 'NotAllowedError: Permission denied') {
182
+ enqueueSnackbar(intl.formatMessage({
183
+ id: 'ui.liveStreamRoom.connect.error.device.permission',
184
+ defaultMessage: 'ui.liveStreamRoom.connect.error.device.permission'
185
+ }), { variant: 'error', autoHideDuration: 5000 });
186
+ }
187
+ else if (e.message !== 'NotFoundError: Requested device not found') {
188
+ enqueueSnackbar(intl.formatMessage({
189
+ id: 'ui.liveStreamRoom.connect.error.device.notFound',
190
+ defaultMessage: 'ui.liveStreamRoom.connect.error.device.notFound'
191
+ }), { variant: 'error', autoHideDuration: 5000 });
192
+ }
193
+ }, []);
180
194
  /**
181
195
  * User must be authenticated
182
196
  */
@@ -11,7 +11,7 @@ import { ConnectionState, formatChatMessageLinks, LayoutContextProvider, LiveKit
11
11
  import { useCallback, useMemo, useState } from 'react';
12
12
  import { defaultUserChoices } from '@livekit/components-core';
13
13
  import { defaultVideoOptions } from '../constants';
14
- import { FormattedMessage } from 'react-intl';
14
+ import { FormattedMessage, useIntl } from 'react-intl';
15
15
  import { VideoConference } from './VideoConference';
16
16
  import { useLiveStream } from './LiveStreamProvider';
17
17
  import DialogContent from '@mui/material/DialogContent';
@@ -73,6 +73,8 @@ export default function LiveStreamVideoConference(inProps) {
73
73
  // STATE
74
74
  const [liveActive, setLiveActive] = useState(true);
75
75
  const [error, setError] = useState(null);
76
+ // INTL
77
+ const intl = useIntl();
76
78
  // PREFERENCES
77
79
  const preferences = useMemo(() => {
78
80
  const _preferences = {};
@@ -105,8 +107,24 @@ export default function LiveStreamVideoConference(inProps) {
105
107
  */
106
108
  const handleError = useCallback((error) => {
107
109
  console.error(error);
108
- if (error.message !== 'Client initiated disconnect') {
109
- setError(`Encountered an unexpected error, check the console logs for details: ${error.message}`);
110
+ if (error.message === 'Permission denied') {
111
+ setError(intl.formatMessage({
112
+ id: 'ui.liveStreamRoom.connect.error.device.permission',
113
+ defaultMessage: 'ui.liveStreamRoom.connect.error.device.permission'
114
+ }));
115
+ }
116
+ else if (error.message === 'Requested device not found') {
117
+ setError(intl.formatMessage({
118
+ id: 'ui.liveStreamRoom.connect.error.device.notFound',
119
+ defaultMessage: 'ui.liveStreamRoom.connect.error.device.notFound'
120
+ }));
121
+ }
122
+ else {
123
+ console.log(`Encountered an unexpected error, check the console logs for details: ${error.message}`);
124
+ setError(intl.formatMessage({
125
+ id: 'ui.liveStreamRoom.connect.error.clientInitiatedDisconnect',
126
+ defaultMessage: 'ui.liveStreamRoom.connect.error.clientInitiatedDisconnect'
127
+ }));
110
128
  }
111
129
  setLiveActive(false);
112
130
  }, []);
@@ -30,7 +30,10 @@ export interface PreJoinProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
30
30
  persistUserChoices?: boolean;
31
31
  }
32
32
  /** @alpha */
33
- export declare function usePreviewTracks(options: CreateLocalTracksOptions, onError?: (err: Error) => void): LocalTrack<Track.Kind>[];
33
+ export declare function usePreviewTracks(options: CreateLocalTracksOptions, onError?: (err: Error) => void): {
34
+ tracks: LocalTrack<Track.Kind>[];
35
+ error: boolean;
36
+ };
34
37
  /** @public */
35
38
  export declare function usePreviewDevice<T extends LocalVideoTrack | LocalAudioTrack>(enabled: boolean, deviceId: string, kind: 'videoinput' | 'audioinput'): {
36
39
  selectedDevice: MediaDeviceInfo;
@@ -13,6 +13,7 @@ import { useLiveStream } from './LiveStreamProvider';
13
13
  /** @alpha */
14
14
  export function usePreviewTracks(options, onError) {
15
15
  const [tracks, setTracks] = React.useState();
16
+ const [error, setError] = React.useState(false);
16
17
  const trackLock = React.useMemo(() => new Mutex(), []);
17
18
  React.useEffect(() => {
18
19
  let needsCleanup = false;
@@ -27,6 +28,7 @@ export function usePreviewTracks(options, onError) {
27
28
  else {
28
29
  setTracks(localTracks);
29
30
  }
31
+ setError(false);
30
32
  }
31
33
  }
32
34
  catch (e) {
@@ -36,6 +38,7 @@ export function usePreviewTracks(options, onError) {
36
38
  else {
37
39
  log.error(e);
38
40
  }
41
+ setError(true);
39
42
  }
40
43
  finally {
41
44
  unlock();
@@ -46,9 +49,10 @@ export function usePreviewTracks(options, onError) {
46
49
  localTracks.forEach((track) => {
47
50
  track.stop();
48
51
  });
52
+ setError(false);
49
53
  };
50
54
  }, [JSON.stringify(options), onError, trackLock]);
51
- return tracks;
55
+ return { tracks, error };
52
56
  }
53
57
  /** @public */
54
58
  export function usePreviewDevice(enabled, deviceId, kind) {
@@ -185,7 +189,7 @@ export function PreJoin(_a) {
185
189
  saveUsername(scUserContext.user.username);
186
190
  }
187
191
  }, [username, saveUsername, scUserContext.user]);
188
- const tracks = usePreviewTracks({
192
+ const { tracks, error } = usePreviewTracks({
189
193
  audio: audioEnabled ? { deviceId: initialUserChoices.audioDeviceId } : false,
190
194
  video: videoEnabled ? { deviceId: initialUserChoices.videoDeviceId } : false
191
195
  }, onError);
@@ -216,7 +220,9 @@ export function PreJoin(_a) {
216
220
  return onValidate(values);
217
221
  }
218
222
  else {
219
- return values.username !== '';
223
+ return Boolean(values.username !== '' &&
224
+ ((values.audioEnabled && values.audioDeviceId) || !values.audioEnabled) &&
225
+ ((values.videoEnabled && values.videoDeviceId) || !values.videoEnabled));
220
226
  }
221
227
  }, [onValidate]);
222
228
  useEffect(() => {
@@ -241,5 +247,5 @@ export function PreJoin(_a) {
241
247
  log.warn('Validation failed with: ', userChoices);
242
248
  }
243
249
  }
244
- 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, 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, 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 }, { 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}`] })] }))] }))] })));
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}`] })] }))] }))] })));
245
251
  }
@@ -36,6 +36,6 @@ export default function NavigationMenuDrawer(inProps) {
36
36
  });
37
37
  const { className = null, showDrawerHeader = true, drawerHeaderContent = _jsx(DefaultHeaderContent, {}), drawerContent = _jsx(DefaultDrawerContent, {}), showDrawerFooterContent = true, drawerFooterContent = null, ScrollContainerProps = {}, CreateLiveStreamButtonComponentProps = {}, open, onClose } = props, rest = __rest(props, ["className", "showDrawerHeader", "drawerHeaderContent", "drawerContent", "showDrawerFooterContent", "drawerFooterContent", "ScrollContainerProps", "CreateLiveStreamButtonComponentProps", "open", "onClose"]);
38
38
  const scUserContext = useSCUser();
39
- const canCreateLiveStream = useMemo(() => { var _a, _b; return (_b = (_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.create_livestream; }, [(_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission]);
39
+ const canCreateLiveStream = useMemo(() => { var _a, _b; return (_b = (_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.create_live_stream; }, [(_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission]);
40
40
  return (_jsxs(Root, Object.assign({ anchor: "left", className: classNames(classes.root, className), open: open, onClose: onClose }, rest, { children: [showDrawerHeader && (_jsxs(_Fragment, { children: [_jsxs(Box, Object.assign({ className: classes.drawerHeader }, { children: [drawerHeaderContent, _jsx(IconButton, Object.assign({ className: classes.drawerHeaderAction, onClick: onClose }, { children: _jsx(Icon, { children: "close" }) }))] })), _jsx(Divider, {})] })), _jsx(ScrollContainer, Object.assign({}, ScrollContainerProps, { children: _jsx(List, Object.assign({ className: classes.drawerContent, onClick: onClose }, { children: drawerContent })) })), showDrawerFooterContent && (_jsx(_Fragment, { children: _jsx(Box, Object.assign({ className: classes.drawerFooter }, { children: drawerFooterContent ? (drawerFooterContent) : (_jsxs(_Fragment, { children: [canCreateLiveStream && _jsx(Divider, {}), _jsx(Box, Object.assign({ className: classes.drawerFooterLiveStream }, { children: _jsx(CreateLiveStreamButton, Object.assign({ color: "primary", className: classes.drawerFooterLiveStreamButton, fullWidth: true }, CreateLiveStreamButtonComponentProps)) }))] })) })) }))] })));
41
41
  }