@selfcommunity/react-ui 0.8.0-live.63 → 0.8.0-live.65

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.
@@ -18,11 +18,14 @@ const utils_1 = require("@selfcommunity/utils");
18
18
  const Errors_1 = require("../../constants/Errors");
19
19
  const PreJoin_1 = require("./LiveStreamVideoConference/PreJoin");
20
20
  const LiveStreamProvider_1 = require("./LiveStreamVideoConference/LiveStreamProvider");
21
+ const notistack_1 = require("notistack");
21
22
  const classes = {
22
23
  root: `${constants_1.PREFIX}-root`,
23
24
  content: `${constants_1.PREFIX}-content`,
24
25
  title: `${constants_1.PREFIX}-title`,
25
26
  description: `${constants_1.PREFIX}-description`,
27
+ endConferenceWrap: `${constants_1.PREFIX}-end-conference-wrap`,
28
+ btnBackHome: `${constants_1.PREFIX}-btn-back-home`,
26
29
  startPrejoinContent: `${constants_1.PREFIX}-start-prejoin-content`,
27
30
  preJoin: `${constants_1.PREFIX}-prejoin`,
28
31
  preJoinLoading: `${constants_1.PREFIX}-prejoin-loading`,
@@ -75,6 +78,7 @@ function LiveStreamRoom(inProps) {
75
78
  const { scLiveStream } = (0, react_core_1.useSCFetchLiveStream)({ id: liveStreamId, liveStream });
76
79
  const [preJoinChoices, setPreJoinChoices] = (0, react_1.useState)(presetPreJoinChoices);
77
80
  const [loading, setLoading] = (0, react_1.useState)(false);
81
+ const [error, setError] = (0, react_1.useState)(null);
78
82
  const preJoinDefaults = (0, react_1.useMemo)(() => {
79
83
  var _a, _b, _c;
80
84
  return {
@@ -89,24 +93,19 @@ function LiveStreamRoom(inProps) {
89
93
  features.includes(types_1.SCFeatureName.LIVE_STREAM) &&
90
94
  react_core_1.SCPreferences.CONFIGURATIONS_LIVE_STREAM_ENABLED in preferences &&
91
95
  preferences[react_core_1.SCPreferences.CONFIGURATIONS_LIVE_STREAM_ENABLED].value, [preferences, features]);
92
- const toggleAttrDisabledPrejoinActions = (0, react_1.useCallback)((disabled) => {
93
- const container = document.querySelector('.lk-prejoin');
94
- if (container) {
95
- const buttons = container.querySelectorAll('button.lk-button');
96
- buttons.forEach((button) => {
97
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
98
- // @ts-ignore
99
- button.disabled = disabled;
100
- });
101
- }
102
- }, []);
96
+ // INTL
97
+ const intl = (0, react_intl_1.useIntl)();
98
+ // MESSAGES
99
+ const { enqueueSnackbar } = (0, notistack_1.useSnackbar)();
103
100
  // HANDLERS
104
101
  /**
105
102
  * Handle PreJoin Submit
106
103
  */
107
104
  const handlePreJoinSubmit = (0, react_1.useCallback)((values) => {
108
- if (scLiveStream) {
105
+ if (scLiveStream || !loading) {
109
106
  setLoading(true);
107
+ setError(null);
108
+ toggleAttrDisabledPrejoinActions(true);
110
109
  api_services_1.LiveStreamService.join(scLiveStream.id)
111
110
  .then((data) => {
112
111
  setPreJoinChoices(values);
@@ -114,12 +113,42 @@ function LiveStreamRoom(inProps) {
114
113
  toggleAttrDisabledPrejoinActions(false);
115
114
  setLoading(false);
116
115
  })
117
- .catch((e) => {
118
- utils_1.Logger.error(Errors_1.SCOPE_SC_UI, e);
116
+ .catch((error) => {
117
+ utils_1.Logger.error(Errors_1.SCOPE_SC_UI, error);
118
+ if (error.response &&
119
+ error.response.data &&
120
+ typeof error.response.data === 'object' &&
121
+ error.response.data.errors &&
122
+ error.response.data.errors.length) {
123
+ let _msg = intl.formatMessage({
124
+ id: 'ui.liveStreamRoom.connect.error.generic',
125
+ defaultMessage: 'ui.liveStreamRoom.connect.error.generic'
126
+ });
127
+ if (error.response.data.errors[0].code) {
128
+ const _error = `ui.liveStreamRoom.connect.error.${(0, utils_1.camelCase)(error.response.data.errors[0].code)}`;
129
+ _msg = intl.formatMessage({ id: _error, defaultMessage: _error });
130
+ }
131
+ setError(_msg);
132
+ enqueueSnackbar(_msg, { variant: 'error', autoHideDuration: 5000 });
133
+ }
134
+ setLoading(false);
119
135
  });
120
- toggleAttrDisabledPrejoinActions(true);
121
136
  }
122
- }, [scUserContext.user, setPreJoinChoices, setConnectionDetails, scLiveStream]);
137
+ }, [scUserContext.user, setPreJoinChoices, setConnectionDetails, scLiveStream, setError, loading]);
138
+ /**
139
+ * Handle disable controls button
140
+ */
141
+ const toggleAttrDisabledPrejoinActions = (0, react_1.useCallback)((disabled) => {
142
+ const container = document.querySelector('.lk-prejoin');
143
+ if (container) {
144
+ const buttons = container.querySelectorAll('button.lk-button');
145
+ buttons.forEach((button) => {
146
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
147
+ // @ts-ignore
148
+ button.disabled = disabled;
149
+ });
150
+ }
151
+ }, []);
123
152
  /**
124
153
  * Handle PreJoin Error
125
154
  */
@@ -133,9 +162,9 @@ function LiveStreamRoom(inProps) {
133
162
  /**
134
163
  * Renders root object
135
164
  */
136
- return ((0, jsx_runtime_1.jsx)(Root, Object.assign({ id: id, className: (0, classnames_1.default)(classes.root, className) }, rest, { children: (0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.content, "data-lk-theme": "default" }, { children: connectionDetails === undefined || preJoinChoices === undefined ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [startPrejoinContent && (0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.startPrejoinContent }, { children: startPrejoinContent })), (scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.title) && ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ component: 'div', variant: "h5", className: classes.title }, { children: scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.title }))), (scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.description) && ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ component: 'div', variant: "body1", className: classes.description }, { children: scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.description }))), (0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: (0, classnames_1.default)(classes.preJoin, { [classes.preJoinLoading]: loading }) }, { children: [(0, jsx_runtime_1.jsx)(LiveStreamProvider_1.LiveStreamContext.Provider, Object.assign({ value: { liveStream: scLiveStream } }, { children: (0, jsx_runtime_1.jsx)(PreJoin_1.PreJoin, { defaults: preJoinDefaults, onSubmit: handlePreJoinSubmit, onError: handlePreJoinError }) })), loading && ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: classes.prejoinLoader }, { children: [(0, jsx_runtime_1.jsx)(material_1.CircularProgress, {}), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ component: 'div', variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.connecting", defaultMessage: "ui.liveStreamRoom.connecting" }) }))] })))] })), (0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: classes.endPrejoinContent }, { children: [Boolean(scUserContext.user &&
165
+ return ((0, jsx_runtime_1.jsx)(Root, Object.assign({ id: id, className: (0, classnames_1.default)(classes.root, className) }, rest, { children: scLiveStream.closed_at_by_host ? ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: classes.endConferenceWrap }, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "h5" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.conference.closed", defaultMessage: "ui.liveStreamRoom.conference.closed" }) })), (0, jsx_runtime_1.jsx)(material_1.Button, Object.assign({ variant: "contained", color: "secondary", component: react_core_1.Link, to: '/', className: classes.btnBackHome }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.button.backHome", defaultMessage: "ui.liveStreamRoom.button.backHome" }) }))] }))) : ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.content, "data-lk-theme": "default" }, { children: connectionDetails === undefined || preJoinChoices === undefined ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [startPrejoinContent && (0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.startPrejoinContent }, { children: startPrejoinContent })), (scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.title) && ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ component: 'div', variant: "h5", className: classes.title }, { children: scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.title }))), (scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.description) && ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ component: 'div', variant: "body1", className: classes.description }, { children: scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.description }))), (0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: (0, classnames_1.default)(classes.preJoin, { [classes.preJoinLoading]: loading || error }) }, { children: [(0, jsx_runtime_1.jsx)(LiveStreamProvider_1.LiveStreamContext.Provider, Object.assign({ value: { liveStream: scLiveStream } }, { children: (0, jsx_runtime_1.jsx)(PreJoin_1.PreJoin, { defaults: preJoinDefaults, onSubmit: handlePreJoinSubmit, onError: handlePreJoinError }) })), loading && ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: classes.prejoinLoader }, { children: [(0, jsx_runtime_1.jsx)(material_1.CircularProgress, {}), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ component: 'div', variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.connecting", defaultMessage: "ui.liveStreamRoom.connecting" }) }))] }))), error && ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.prejoinLoader }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ component: 'div', variant: "body2" }, { children: error })) })))] })), (0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: classes.endPrejoinContent }, { children: [Boolean(scUserContext.user &&
137
166
  scUserContext.user.id !== scLiveStream.host.id &&
138
167
  scLiveStream &&
139
- (((_a = scLiveStream.settings) === null || _a === void 0 ? void 0 : _a.muteParticipants) || (scLiveStream && ((_b = scLiveStream.settings) === null || _b === void 0 ? void 0 : _b.disableVideo)))) && ((0, jsx_runtime_1.jsxs)(material_1.Alert, Object.assign({ variant: "filled", severity: "error" }, { children: [scLiveStream && ((_c = scLiveStream.settings) === null || _c === void 0 ? void 0 : _c.muteParticipants) && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.hostDisableMicrophone", defaultMessage: "ui.liveStreamRoom.hostDisableMicrophone" }), (0, jsx_runtime_1.jsx)("br", {})] })), scLiveStream && ((_d = scLiveStream.settings) === null || _d === void 0 ? void 0 : _d.disableVideo) && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.hostDisableVideo", defaultMessage: "ui.liveStreamRoom.hostDisableVideo" }) }))] }))), endPrejoinContent] }))] })) : ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.conference }, { children: (0, jsx_runtime_1.jsx)(LiveStreamProvider_1.LiveStreamContext.Provider, Object.assign({ value: { liveStream: scLiveStream } }, { children: (0, jsx_runtime_1.jsx)(LiveStreamVideoConference_1.default, Object.assign({ connectionDetails: connectionDetails, userChoices: preJoinChoices }, LiveStreamVideoConferenceComponentProps)) })) }))) })) })));
168
+ (((_a = scLiveStream.settings) === null || _a === void 0 ? void 0 : _a.muteParticipants) || (scLiveStream && ((_b = scLiveStream.settings) === null || _b === void 0 ? void 0 : _b.disableVideo)))) && ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ sx: { width: '60%' }, spacing: 1 }, { children: [scLiveStream && ((_c = scLiveStream.settings) === null || _c === void 0 ? void 0 : _c.muteParticipants) && ((0, jsx_runtime_1.jsx)(material_1.Alert, Object.assign({ variant: "outlined", severity: "info", component: 'div' }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.hostDisableMicrophone", defaultMessage: "ui.liveStreamRoom.hostDisableMicrophone" }) }))), scLiveStream && ((_d = scLiveStream.settings) === null || _d === void 0 ? void 0 : _d.disableVideo) && ((0, jsx_runtime_1.jsx)(material_1.Alert, Object.assign({ variant: "outlined", severity: "info" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.hostDisableVideo", defaultMessage: "ui.liveStreamRoom.hostDisableVideo" }) })))] }))), endPrejoinContent] }))] })) : ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.conference }, { children: (0, jsx_runtime_1.jsx)(LiveStreamProvider_1.LiveStreamContext.Provider, Object.assign({ value: { liveStream: scLiveStream } }, { children: (0, jsx_runtime_1.jsx)(LiveStreamVideoConference_1.default, Object.assign({ connectionDetails: connectionDetails, userChoices: preJoinChoices }, LiveStreamVideoConferenceComponentProps)) })) }))) }))) })));
140
169
  }
141
170
  exports.default = LiveStreamRoom;
@@ -5,12 +5,67 @@ const tslib_1 = require("tslib");
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const React = tslib_1.__importStar(require("react"));
7
7
  const components_react_1 = require("@livekit/components-react");
8
+ const react_1 = require("react");
9
+ const api_services_1 = require("@selfcommunity/api-services");
10
+ const LiveStreamProvider_1 = require("./LiveStreamProvider");
11
+ const react_intl_1 = require("react-intl");
12
+ const material_1 = require("@mui/material");
13
+ const react_core_1 = require("@selfcommunity/react-core");
14
+ const ConfirmDialog_1 = tslib_1.__importDefault(require("../../../shared/ConfirmDialog/ConfirmDialog"));
8
15
  /**
9
16
  * The `DisconnectButton` is a basic html button with the added ability to disconnect from a LiveKit room.
10
17
  * Normally this is the big red button that allows end users to leave the video or audio call.
11
18
  */
12
19
  exports.DisconnectButton =
13
20
  /* @__PURE__ */ React.forwardRef(function DisconnectButton(props, ref) {
21
+ // CONTEXT
22
+ const { liveStream } = (0, LiveStreamProvider_1.useLiveStream)();
23
+ const scUserContext = (0, react_core_1.useSCUser)();
24
+ // STATE
25
+ const [closeLive, setCloseLive] = (0, react_1.useState)(false);
26
+ const [openConfirmDialog, setOpenConfirmDialog] = (0, react_1.useState)(false);
27
+ const [isUpdating, setIsUpdating] = (0, react_1.useState)(false);
14
28
  const { buttonProps } = (0, components_react_1.useDisconnectButton)(props);
15
- return ((0, jsx_runtime_1.jsx)("button", Object.assign({ ref: ref }, buttonProps, { children: props.children })));
29
+ const { onClick } = buttonProps, rest = tslib_1.__rest(buttonProps, ["onClick"]);
30
+ /**
31
+ * Intercept fist leave action
32
+ */
33
+ const handleOnLeave = (0, react_1.useCallback)(() => {
34
+ setOpenConfirmDialog(true);
35
+ }, [setOpenConfirmDialog]);
36
+ /**
37
+ * Control close live
38
+ */
39
+ const handleChangeCloseLive = (0, react_1.useCallback)((event) => {
40
+ setCloseLive(event.target.checked);
41
+ }, [closeLive]);
42
+ /**
43
+ * Perform set liveStream as closed
44
+ */
45
+ const performCloseLiveStream = (0, react_1.useMemo)(() => () => tslib_1.__awaiter(this, void 0, void 0, function* () {
46
+ const res = yield api_services_1.LiveStreamApiClient.close(liveStream.id);
47
+ if (res.status >= 300) {
48
+ return Promise.reject(res);
49
+ }
50
+ return yield Promise.resolve(res.data);
51
+ }), [liveStream]);
52
+ /**
53
+ * Perform patch liveStream before leave the live
54
+ */
55
+ const handleLeaveAction = () => {
56
+ if (!isUpdating && liveStream && scUserContext.user.id === liveStream.host.id && closeLive) {
57
+ setIsUpdating(true);
58
+ performCloseLiveStream()
59
+ .then(() => {
60
+ onClick === null || onClick === void 0 ? void 0 : onClick();
61
+ })
62
+ .catch((error) => {
63
+ console.error(error);
64
+ });
65
+ }
66
+ else {
67
+ onClick === null || onClick === void 0 ? void 0 : onClick();
68
+ }
69
+ };
70
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("button", Object.assign({ ref: ref }, rest, { onClick: handleOnLeave }, { children: props.children })), openConfirmDialog && ((0, jsx_runtime_1.jsx)(ConfirmDialog_1.default, { open: openConfirmDialog, title: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {}), content: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.live.terminate", defaultMessage: "ui.liveStreamRoom.live.terminate" }), (0, jsx_runtime_1.jsx)(material_1.FormGroup, { children: (0, jsx_runtime_1.jsx)(material_1.FormControlLabel, { control: (0, jsx_runtime_1.jsx)(material_1.Checkbox, { checked: closeLive, onChange: handleChangeCloseLive, inputProps: { 'aria-label': 'controlled' } }), label: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.live.terminatePermanently", defaultMessage: "ui.liveStreamRoom.live.terminatePermanently" }) }) })] }), onConfirm: handleLeaveAction, isUpdating: isUpdating, onClose: () => setOpenConfirmDialog(false) }))] }));
16
71
  });
@@ -69,8 +69,6 @@ function LiveStreamVideoConference(inProps) {
69
69
  const canUseChat = (0, react_1.useMemo)(() => { var _a; return scUserContext.user && liveStream && liveStream && !((_a = liveStream === null || liveStream === void 0 ? void 0 : liveStream.settings) === null || _a === void 0 ? void 0 : _a.disableChat); }, [scUserContext, liveStream]);
70
70
  const canUseShareScreen = (0, react_1.useMemo)(() => { var _a; return scUserContext.user && liveStream && (liveStream.host.id === scUserContext.user.id || (liveStream && !((_a = liveStream === null || liveStream === void 0 ? void 0 : liveStream.settings) === null || _a === void 0 ? void 0 : _a.disableShareScreen))); }, [scUserContext, liveStream]);
71
71
  const speakerFocused = (0, react_1.useMemo)(() => (scUserContext.user && liveStream && liveStream.settings.view === types_1.SCLiveStreamViewType.SPEAKER ? liveStream.host : null), [scUserContext, liveStream]);
72
- console.log(canUseChat);
73
- console.log(speakerFocused);
74
72
  // CONNECT OPTIONS
75
73
  const connectOptions = (0, react_1.useMemo)(() => {
76
74
  return {
@@ -10,6 +10,7 @@ const components_react_1 = require("@livekit/components-react");
10
10
  const ParticipantTileAvatar_1 = tslib_1.__importDefault(require("./ParticipantTileAvatar"));
11
11
  const ParticipantTileActions_1 = tslib_1.__importDefault(require("./ParticipantTileActions"));
12
12
  const react_core_1 = require("@selfcommunity/react-core");
13
+ const LiveStreamProvider_1 = require("./LiveStreamProvider");
13
14
  /**
14
15
  * The `ParticipantContextIfNeeded` component only creates a `ParticipantContext`
15
16
  * if there is no `ParticipantContext` already.
@@ -45,6 +46,7 @@ exports.ParticipantTile =
45
46
  });
46
47
  const isEncrypted = (0, components_react_1.useIsEncrypted)(trackReference.participant);
47
48
  const layoutContext = (0, components_react_1.useMaybeLayoutContext)();
49
+ const { liveStream } = (0, LiveStreamProvider_1.useLiveStream)();
48
50
  const autoManageSubscription = (_b = (0, components_react_1.useFeatureContext)()) === null || _b === void 0 ? void 0 : _b.autoSubscription;
49
51
  const handleSubscribe = React.useCallback((subscribed) => {
50
52
  if (trackReference.source &&
@@ -58,7 +60,7 @@ exports.ParticipantTile =
58
60
  return ((0, jsx_runtime_1.jsx)("div", Object.assign({ ref: ref, style: { position: 'relative' } }, elementProps, { children: (0, jsx_runtime_1.jsx)(TrackRefContextIfNeeded, Object.assign({ trackRef: trackReference }, { children: (0, jsx_runtime_1.jsxs)(ParticipantContextIfNeeded, Object.assign({ participant: trackReference.participant }, { children: [children !== null && children !== void 0 ? children : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, components_core_1.isTrackReference)(trackReference) &&
59
61
  (((_c = trackReference.publication) === null || _c === void 0 ? void 0 : _c.kind) === 'video' ||
60
62
  trackReference.source === livekit_client_1.Track.Source.Camera ||
61
- trackReference.source === livekit_client_1.Track.Source.ScreenShare) ? ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(components_react_1.VideoTrack, { trackRef: trackReference, onSubscriptionStatusChanged: handleSubscribe, manageSubscription: autoManageSubscription }) })) : ((0, components_core_1.isTrackReference)(trackReference) && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(components_react_1.AudioTrack, { trackRef: trackReference, onSubscriptionStatusChanged: handleSubscribe }) }))), (0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-participant-placeholder" }, { children: (0, jsx_runtime_1.jsx)(ParticipantTileAvatar_1.default, { participant: trackReference.participant }) })), (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-participant-metadata" }, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-participant-metadata-item" }, { children: trackReference.source === livekit_client_1.Track.Source.Camera ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isEncrypted && (0, jsx_runtime_1.jsx)(components_react_1.LockLockedIcon, { style: { marginRight: '0.25rem' } }), (0, jsx_runtime_1.jsx)(components_react_1.TrackMutedIndicator, { trackRef: {
63
+ trackReference.source === livekit_client_1.Track.Source.ScreenShare) ? ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(components_react_1.VideoTrack, { trackRef: trackReference, onSubscriptionStatusChanged: handleSubscribe, manageSubscription: autoManageSubscription }) })) : ((0, components_core_1.isTrackReference)(trackReference) && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(components_react_1.AudioTrack, { trackRef: trackReference, onSubscriptionStatusChanged: handleSubscribe }) }))), (0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-participant-placeholder" }, { children: (0, jsx_runtime_1.jsx)(ParticipantTileAvatar_1.default, Object.assign({}, ((liveStream === null || liveStream === void 0 ? void 0 : liveStream.host.id) !== scUserContext.user.id ? { participant: trackReference.participant } : {}))) })), (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-participant-metadata" }, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-participant-metadata-item" }, { children: trackReference.source === livekit_client_1.Track.Source.Camera ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isEncrypted && (0, jsx_runtime_1.jsx)(components_react_1.LockLockedIcon, { style: { marginRight: '0.25rem' } }), (0, jsx_runtime_1.jsx)(components_react_1.TrackMutedIndicator, { trackRef: {
62
64
  participant: trackReference.participant,
63
65
  source: livekit_client_1.Track.Source.Microphone
64
66
  }, show: 'muted' }), (0, jsx_runtime_1.jsx)(components_react_1.ParticipantName, { children: !disableTileActions && (0, jsx_runtime_1.jsx)(ParticipantTileActions_1.default, {}) })] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(components_react_1.ScreenShareIcon, { style: { marginRight: '0.25rem' } }), (0, jsx_runtime_1.jsx)(components_react_1.ParticipantName, { children: "'s screen" })] })) })), (0, jsx_runtime_1.jsx)(components_react_1.ConnectionQualityIndicator, { className: "lk-participant-metadata-item" })] }))] })), (0, jsx_runtime_1.jsx)(components_react_1.FocusToggle, { trackRef: trackReference })] })) })) })));
@@ -102,7 +102,7 @@ function ContributionActionsMenu(props) {
102
102
  * Perform ban participant
103
103
  */
104
104
  const performBanParticipant = (0, react_1.useMemo)(() => () => tslib_1.__awaiter(this, void 0, void 0, function* () {
105
- const res = yield api_services_1.LiveStreamApiClient.removeUserFromRoom(liveStream.id, p.identity);
105
+ const res = yield api_services_1.LiveStreamApiClient.removeParticipant(liveStream.id, { participant_id: p.identity });
106
106
  if (res.status >= 300) {
107
107
  return Promise.reject(res);
108
108
  }
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const react_1 = require("react");
6
5
  const styles_1 = require("@mui/material/styles");
7
6
  const system_1 = require("@mui/system");
8
7
  const material_1 = require("@mui/material");
@@ -34,16 +33,7 @@ function ParticipantTileAvatar(inProps) {
34
33
  const { className, user, participant } = props, rest = tslib_1.__rest(props, ["className", "user", "participant"]);
35
34
  // CONTEXT
36
35
  const scContext = (0, react_core_1.useSCContext)();
37
- // AVATAR
38
- const avatar = (0, react_1.useMemo)(() => {
39
- if (user) {
40
- return (0, jsx_runtime_1.jsx)("img", { src: `${user.avatar}` });
41
- }
42
- if (participant) {
43
- return (0, jsx_runtime_1.jsx)("img", { src: `${scContext.settings.portal}/api/v2/avatar/${participant.identity}` });
44
- }
45
- return (0, jsx_runtime_1.jsx)(ParticipantPlaceholder_1.default, {});
46
- }, [user, participant]);
47
- return ((0, jsx_runtime_1.jsx)(Root, Object.assign({ className: (0, classnames_1.default)(className, classes.root) }, rest, { children: avatar })));
36
+ console.log(participant);
37
+ return ((0, jsx_runtime_1.jsx)(Root, Object.assign({ className: (0, classnames_1.default)(className, classes.root) }, rest, { children: participant ? ((0, jsx_runtime_1.jsx)("img", { src: `${scContext.settings.portal}/api/v2/avatar/${participant.identity}` })) : user ? ((0, jsx_runtime_1.jsx)("img", { src: `${user.avatar}` })) : ((0, jsx_runtime_1.jsx)(ParticipantPlaceholder_1.default, {})) })));
48
38
  }
49
39
  exports.default = ParticipantTileAvatar;
@@ -33,7 +33,7 @@ function LiveStreamInfoDetails(inProps) {
33
33
  if (!scLiveStream) {
34
34
  return null;
35
35
  }
36
- return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: classes.root }, { children: [beforeDateInfo, hasDateInfo && ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.iconTextWrapper }, { children: [!hideDateIcon && (0, jsx_runtime_1.jsx)(material_1.Icon, Object.assign({ fontSize: "small" }, { children: scLiveStream.closed_at ? 'calendar_off' : 'CalendarIcon' })), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.eventInfoDetails.date.startEndTime", defaultMessage: "ui.eventInfoDetails.date.startEndTime", values: {
36
+ return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: classes.root }, { children: [beforeDateInfo, hasDateInfo && ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.iconTextWrapper }, { children: [!hideDateIcon && (0, jsx_runtime_1.jsx)(material_1.Icon, Object.assign({ fontSize: "small" }, { children: scLiveStream.closed_at_by_host ? 'calendar_off' : 'CalendarIcon' })), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.eventInfoDetails.date.startEndTime", defaultMessage: "ui.eventInfoDetails.date.startEndTime", values: {
37
37
  date: intl.formatDate(scLiveStream.created_at, {
38
38
  weekday: 'long',
39
39
  day: 'numeric',
@@ -41,7 +41,7 @@ function LiveStreamInfoDetails(inProps) {
41
41
  month: 'long'
42
42
  }),
43
43
  start: intl.formatDate(scLiveStream.created_at, { hour: 'numeric', minute: 'numeric' })
44
- } }) })), hasInProgress && scLiveStream.running && ((0, jsx_runtime_1.jsx)(material_1.Tooltip, Object.assign({ title: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.eventInfoDetails.inProgress", defaultMessage: "ui.eventInfoDetails.inProgress" }) }, { children: (0, jsx_runtime_1.jsx)(material_1.Box, { className: classes.inProgress }) })))] }))), beforeLocationInfo, hasLocationInfo && ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.iconTextWrapper }, { children: [!hideLocationIcon && (0, jsx_runtime_1.jsx)(material_1.Icon, Object.assign({ fontSize: "small" }, { children: "play_circle_outline" })), (0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({ to: scRoutingContext.url(react_core_1.SCRoutes.LIVESTREAM_ROUTE_NAME, scLiveStream), target: "_blank", className: classes.link }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1", className: classes.url }, { children: scRoutingContext.url(react_core_1.SCRoutes.LIVESTREAM_ROUTE_NAME, scLiveStream) })) }))] }))), beforeCreatedInfo, hasCreatedInfo && ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.creationWrapper }, { children: [!hideCreatedIcon && (0, jsx_runtime_1.jsx)(material_1.Icon, Object.assign({ fontSize: "small" }, { children: "create" })), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.eventInfoDetails.date.create", defaultMessage: "ui.eventInfoDetails.date.create", values: {
44
+ } }) })), hasInProgress && scLiveStream.last_started_at && ((0, jsx_runtime_1.jsx)(material_1.Tooltip, Object.assign({ title: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.eventInfoDetails.inProgress", defaultMessage: "ui.eventInfoDetails.inProgress" }) }, { children: (0, jsx_runtime_1.jsx)(material_1.Box, { className: classes.inProgress }) })))] }))), beforeLocationInfo, hasLocationInfo && ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.iconTextWrapper }, { children: [!hideLocationIcon && (0, jsx_runtime_1.jsx)(material_1.Icon, Object.assign({ fontSize: "small" }, { children: "play_circle_outline" })), (0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({ to: scRoutingContext.url(react_core_1.SCRoutes.LIVESTREAM_ROUTE_NAME, scLiveStream), target: "_blank", className: classes.link }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1", className: classes.url }, { children: scRoutingContext.url(react_core_1.SCRoutes.LIVESTREAM_ROUTE_NAME, scLiveStream) })) }))] }))), beforeCreatedInfo, hasCreatedInfo && ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.creationWrapper }, { children: [!hideCreatedIcon && (0, jsx_runtime_1.jsx)(material_1.Icon, Object.assign({ fontSize: "small" }, { children: "create" })), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.eventInfoDetails.date.create", defaultMessage: "ui.eventInfoDetails.date.create", values: {
45
45
  date: intl.formatDate(scLiveStream.created_at, {
46
46
  weekday: 'long',
47
47
  day: 'numeric',
@@ -1,26 +1,29 @@
1
1
  import { __rest } from "tslib";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { Alert, Box, CircularProgress, Typography } from '@mui/material';
3
+ import { Alert, Box, Button, CircularProgress, Stack, Typography } from '@mui/material';
4
4
  import { styled } from '@mui/material/styles';
5
5
  import { useThemeProps } from '@mui/system';
6
- import { SCPreferences, useSCFetchLiveStream, useSCPreferences, useSCUser } from '@selfcommunity/react-core';
6
+ import { Link, SCPreferences, useSCFetchLiveStream, useSCPreferences, useSCUser } from '@selfcommunity/react-core';
7
7
  import { SCFeatureName } from '@selfcommunity/types';
8
8
  import classNames from 'classnames';
9
- import { FormattedMessage } from 'react-intl';
9
+ import { FormattedMessage, useIntl } from 'react-intl';
10
10
  import { PREFIX } from './constants';
11
11
  import { useCallback, useMemo, useState } from 'react';
12
12
  import LiveStreamVideoConference from './LiveStreamVideoConference';
13
13
  import '@livekit/components-styles';
14
14
  import { LiveStreamService } from '@selfcommunity/api-services';
15
- import { Logger } from '@selfcommunity/utils';
15
+ import { camelCase, Logger } from '@selfcommunity/utils';
16
16
  import { SCOPE_SC_UI } from '../../constants/Errors';
17
17
  import { PreJoin } from './LiveStreamVideoConference/PreJoin';
18
18
  import { LiveStreamContext } from './LiveStreamVideoConference/LiveStreamProvider';
19
+ import { useSnackbar } from 'notistack';
19
20
  const classes = {
20
21
  root: `${PREFIX}-root`,
21
22
  content: `${PREFIX}-content`,
22
23
  title: `${PREFIX}-title`,
23
24
  description: `${PREFIX}-description`,
25
+ endConferenceWrap: `${PREFIX}-end-conference-wrap`,
26
+ btnBackHome: `${PREFIX}-btn-back-home`,
24
27
  startPrejoinContent: `${PREFIX}-start-prejoin-content`,
25
28
  preJoin: `${PREFIX}-prejoin`,
26
29
  preJoinLoading: `${PREFIX}-prejoin-loading`,
@@ -73,6 +76,7 @@ export default function LiveStreamRoom(inProps) {
73
76
  const { scLiveStream } = useSCFetchLiveStream({ id: liveStreamId, liveStream });
74
77
  const [preJoinChoices, setPreJoinChoices] = useState(presetPreJoinChoices);
75
78
  const [loading, setLoading] = useState(false);
79
+ const [error, setError] = useState(null);
76
80
  const preJoinDefaults = useMemo(() => {
77
81
  var _a, _b, _c;
78
82
  return {
@@ -87,24 +91,19 @@ export default function LiveStreamRoom(inProps) {
87
91
  features.includes(SCFeatureName.LIVE_STREAM) &&
88
92
  SCPreferences.CONFIGURATIONS_LIVE_STREAM_ENABLED in preferences &&
89
93
  preferences[SCPreferences.CONFIGURATIONS_LIVE_STREAM_ENABLED].value, [preferences, features]);
90
- const toggleAttrDisabledPrejoinActions = useCallback((disabled) => {
91
- const container = document.querySelector('.lk-prejoin');
92
- if (container) {
93
- const buttons = container.querySelectorAll('button.lk-button');
94
- buttons.forEach((button) => {
95
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
96
- // @ts-ignore
97
- button.disabled = disabled;
98
- });
99
- }
100
- }, []);
94
+ // INTL
95
+ const intl = useIntl();
96
+ // MESSAGES
97
+ const { enqueueSnackbar } = useSnackbar();
101
98
  // HANDLERS
102
99
  /**
103
100
  * Handle PreJoin Submit
104
101
  */
105
102
  const handlePreJoinSubmit = useCallback((values) => {
106
- if (scLiveStream) {
103
+ if (scLiveStream || !loading) {
107
104
  setLoading(true);
105
+ setError(null);
106
+ toggleAttrDisabledPrejoinActions(true);
108
107
  LiveStreamService.join(scLiveStream.id)
109
108
  .then((data) => {
110
109
  setPreJoinChoices(values);
@@ -112,12 +111,42 @@ export default function LiveStreamRoom(inProps) {
112
111
  toggleAttrDisabledPrejoinActions(false);
113
112
  setLoading(false);
114
113
  })
115
- .catch((e) => {
116
- Logger.error(SCOPE_SC_UI, e);
114
+ .catch((error) => {
115
+ Logger.error(SCOPE_SC_UI, error);
116
+ if (error.response &&
117
+ error.response.data &&
118
+ typeof error.response.data === 'object' &&
119
+ error.response.data.errors &&
120
+ error.response.data.errors.length) {
121
+ let _msg = intl.formatMessage({
122
+ id: 'ui.liveStreamRoom.connect.error.generic',
123
+ defaultMessage: 'ui.liveStreamRoom.connect.error.generic'
124
+ });
125
+ if (error.response.data.errors[0].code) {
126
+ const _error = `ui.liveStreamRoom.connect.error.${camelCase(error.response.data.errors[0].code)}`;
127
+ _msg = intl.formatMessage({ id: _error, defaultMessage: _error });
128
+ }
129
+ setError(_msg);
130
+ enqueueSnackbar(_msg, { variant: 'error', autoHideDuration: 5000 });
131
+ }
132
+ setLoading(false);
117
133
  });
118
- toggleAttrDisabledPrejoinActions(true);
119
134
  }
120
- }, [scUserContext.user, setPreJoinChoices, setConnectionDetails, scLiveStream]);
135
+ }, [scUserContext.user, setPreJoinChoices, setConnectionDetails, scLiveStream, setError, loading]);
136
+ /**
137
+ * Handle disable controls button
138
+ */
139
+ const toggleAttrDisabledPrejoinActions = useCallback((disabled) => {
140
+ const container = document.querySelector('.lk-prejoin');
141
+ if (container) {
142
+ const buttons = container.querySelectorAll('button.lk-button');
143
+ buttons.forEach((button) => {
144
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
145
+ // @ts-ignore
146
+ button.disabled = disabled;
147
+ });
148
+ }
149
+ }, []);
121
150
  /**
122
151
  * Handle PreJoin Error
123
152
  */
@@ -131,8 +160,8 @@ export default function LiveStreamRoom(inProps) {
131
160
  /**
132
161
  * Renders root object
133
162
  */
134
- return (_jsx(Root, Object.assign({ id: id, className: classNames(classes.root, className) }, rest, { children: _jsx(Box, Object.assign({ className: classes.content, "data-lk-theme": "default" }, { children: connectionDetails === undefined || preJoinChoices === undefined ? (_jsxs(_Fragment, { children: [startPrejoinContent && _jsx(Box, Object.assign({ className: classes.startPrejoinContent }, { children: startPrejoinContent })), (scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.title) && (_jsx(Typography, Object.assign({ component: 'div', variant: "h5", className: classes.title }, { children: scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.title }))), (scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.description) && (_jsx(Typography, Object.assign({ component: 'div', variant: "body1", className: classes.description }, { children: scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.description }))), _jsxs(Box, Object.assign({ className: classNames(classes.preJoin, { [classes.preJoinLoading]: loading }) }, { children: [_jsx(LiveStreamContext.Provider, Object.assign({ value: { liveStream: scLiveStream } }, { children: _jsx(PreJoin, { defaults: preJoinDefaults, onSubmit: handlePreJoinSubmit, onError: handlePreJoinError }) })), loading && (_jsxs(Box, Object.assign({ className: classes.prejoinLoader }, { children: [_jsx(CircularProgress, {}), _jsx(Typography, Object.assign({ component: 'div', variant: "body2" }, { children: _jsx(FormattedMessage, { id: "ui.liveStreamRoom.connecting", defaultMessage: "ui.liveStreamRoom.connecting" }) }))] })))] })), _jsxs(Box, Object.assign({ className: classes.endPrejoinContent }, { children: [Boolean(scUserContext.user &&
163
+ return (_jsx(Root, Object.assign({ id: id, className: classNames(classes.root, className) }, rest, { children: scLiveStream.closed_at_by_host ? (_jsxs(Box, Object.assign({ className: classes.endConferenceWrap }, { children: [_jsx(Typography, Object.assign({ variant: "h5" }, { children: _jsx(FormattedMessage, { id: "ui.liveStreamRoom.conference.closed", defaultMessage: "ui.liveStreamRoom.conference.closed" }) })), _jsx(Button, Object.assign({ variant: "contained", color: "secondary", component: Link, to: '/', className: classes.btnBackHome }, { children: _jsx(FormattedMessage, { id: "ui.liveStreamRoom.button.backHome", defaultMessage: "ui.liveStreamRoom.button.backHome" }) }))] }))) : (_jsx(Box, Object.assign({ className: classes.content, "data-lk-theme": "default" }, { children: connectionDetails === undefined || preJoinChoices === undefined ? (_jsxs(_Fragment, { children: [startPrejoinContent && _jsx(Box, Object.assign({ className: classes.startPrejoinContent }, { children: startPrejoinContent })), (scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.title) && (_jsx(Typography, Object.assign({ component: 'div', variant: "h5", className: classes.title }, { children: scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.title }))), (scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.description) && (_jsx(Typography, Object.assign({ component: 'div', variant: "body1", className: classes.description }, { children: scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.description }))), _jsxs(Box, Object.assign({ className: classNames(classes.preJoin, { [classes.preJoinLoading]: loading || error }) }, { children: [_jsx(LiveStreamContext.Provider, Object.assign({ value: { liveStream: scLiveStream } }, { children: _jsx(PreJoin, { defaults: preJoinDefaults, onSubmit: handlePreJoinSubmit, onError: handlePreJoinError }) })), loading && (_jsxs(Box, Object.assign({ className: classes.prejoinLoader }, { children: [_jsx(CircularProgress, {}), _jsx(Typography, Object.assign({ component: 'div', variant: "body2" }, { children: _jsx(FormattedMessage, { id: "ui.liveStreamRoom.connecting", defaultMessage: "ui.liveStreamRoom.connecting" }) }))] }))), error && (_jsx(Box, Object.assign({ className: classes.prejoinLoader }, { children: _jsx(Typography, Object.assign({ component: 'div', variant: "body2" }, { children: error })) })))] })), _jsxs(Box, Object.assign({ className: classes.endPrejoinContent }, { children: [Boolean(scUserContext.user &&
135
164
  scUserContext.user.id !== scLiveStream.host.id &&
136
165
  scLiveStream &&
137
- (((_a = scLiveStream.settings) === null || _a === void 0 ? void 0 : _a.muteParticipants) || (scLiveStream && ((_b = scLiveStream.settings) === null || _b === void 0 ? void 0 : _b.disableVideo)))) && (_jsxs(Alert, Object.assign({ variant: "filled", severity: "error" }, { children: [scLiveStream && ((_c = scLiveStream.settings) === null || _c === void 0 ? void 0 : _c.muteParticipants) && (_jsxs(_Fragment, { children: [_jsx(FormattedMessage, { id: "ui.liveStreamRoom.hostDisableMicrophone", defaultMessage: "ui.liveStreamRoom.hostDisableMicrophone" }), _jsx("br", {})] })), scLiveStream && ((_d = scLiveStream.settings) === null || _d === void 0 ? void 0 : _d.disableVideo) && (_jsx(_Fragment, { children: _jsx(FormattedMessage, { id: "ui.liveStreamRoom.hostDisableVideo", defaultMessage: "ui.liveStreamRoom.hostDisableVideo" }) }))] }))), endPrejoinContent] }))] })) : (_jsx(Box, Object.assign({ className: classes.conference }, { children: _jsx(LiveStreamContext.Provider, Object.assign({ value: { liveStream: scLiveStream } }, { children: _jsx(LiveStreamVideoConference, Object.assign({ connectionDetails: connectionDetails, userChoices: preJoinChoices }, LiveStreamVideoConferenceComponentProps)) })) }))) })) })));
166
+ (((_a = scLiveStream.settings) === null || _a === void 0 ? void 0 : _a.muteParticipants) || (scLiveStream && ((_b = scLiveStream.settings) === null || _b === void 0 ? void 0 : _b.disableVideo)))) && (_jsxs(Stack, Object.assign({ sx: { width: '60%' }, spacing: 1 }, { children: [scLiveStream && ((_c = scLiveStream.settings) === null || _c === void 0 ? void 0 : _c.muteParticipants) && (_jsx(Alert, Object.assign({ variant: "outlined", severity: "info", component: 'div' }, { children: _jsx(FormattedMessage, { id: "ui.liveStreamRoom.hostDisableMicrophone", defaultMessage: "ui.liveStreamRoom.hostDisableMicrophone" }) }))), scLiveStream && ((_d = scLiveStream.settings) === null || _d === void 0 ? void 0 : _d.disableVideo) && (_jsx(Alert, Object.assign({ variant: "outlined", severity: "info" }, { children: _jsx(FormattedMessage, { id: "ui.liveStreamRoom.hostDisableVideo", defaultMessage: "ui.liveStreamRoom.hostDisableVideo" }) })))] }))), endPrejoinContent] }))] })) : (_jsx(Box, Object.assign({ className: classes.conference }, { children: _jsx(LiveStreamContext.Provider, Object.assign({ value: { liveStream: scLiveStream } }, { children: _jsx(LiveStreamVideoConference, Object.assign({ connectionDetails: connectionDetails, userChoices: preJoinChoices }, LiveStreamVideoConferenceComponentProps)) })) }))) }))) })));
138
167
  }
@@ -1,12 +1,68 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { __awaiter, __rest } from "tslib";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import * as React from 'react';
3
4
  import { useDisconnectButton } from '@livekit/components-react';
5
+ import { useCallback, useMemo, useState } from 'react';
6
+ import { LiveStreamApiClient } from '@selfcommunity/api-services';
7
+ import { useLiveStream } from './LiveStreamProvider';
8
+ import { FormattedMessage } from 'react-intl';
9
+ import { Checkbox, FormControlLabel, FormGroup } from '@mui/material';
10
+ import { useSCUser } from '@selfcommunity/react-core';
11
+ import ConfirmDialog from '../../../shared/ConfirmDialog/ConfirmDialog';
4
12
  /**
5
13
  * The `DisconnectButton` is a basic html button with the added ability to disconnect from a LiveKit room.
6
14
  * Normally this is the big red button that allows end users to leave the video or audio call.
7
15
  */
8
16
  export const DisconnectButton =
9
17
  /* @__PURE__ */ React.forwardRef(function DisconnectButton(props, ref) {
18
+ // CONTEXT
19
+ const { liveStream } = useLiveStream();
20
+ const scUserContext = useSCUser();
21
+ // STATE
22
+ const [closeLive, setCloseLive] = useState(false);
23
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
24
+ const [isUpdating, setIsUpdating] = useState(false);
10
25
  const { buttonProps } = useDisconnectButton(props);
11
- return (_jsx("button", Object.assign({ ref: ref }, buttonProps, { children: props.children })));
26
+ const { onClick } = buttonProps, rest = __rest(buttonProps, ["onClick"]);
27
+ /**
28
+ * Intercept fist leave action
29
+ */
30
+ const handleOnLeave = useCallback(() => {
31
+ setOpenConfirmDialog(true);
32
+ }, [setOpenConfirmDialog]);
33
+ /**
34
+ * Control close live
35
+ */
36
+ const handleChangeCloseLive = useCallback((event) => {
37
+ setCloseLive(event.target.checked);
38
+ }, [closeLive]);
39
+ /**
40
+ * Perform set liveStream as closed
41
+ */
42
+ const performCloseLiveStream = useMemo(() => () => __awaiter(this, void 0, void 0, function* () {
43
+ const res = yield LiveStreamApiClient.close(liveStream.id);
44
+ if (res.status >= 300) {
45
+ return Promise.reject(res);
46
+ }
47
+ return yield Promise.resolve(res.data);
48
+ }), [liveStream]);
49
+ /**
50
+ * Perform patch liveStream before leave the live
51
+ */
52
+ const handleLeaveAction = () => {
53
+ if (!isUpdating && liveStream && scUserContext.user.id === liveStream.host.id && closeLive) {
54
+ setIsUpdating(true);
55
+ performCloseLiveStream()
56
+ .then(() => {
57
+ onClick === null || onClick === void 0 ? void 0 : onClick();
58
+ })
59
+ .catch((error) => {
60
+ console.error(error);
61
+ });
62
+ }
63
+ else {
64
+ onClick === null || onClick === void 0 ? void 0 : onClick();
65
+ }
66
+ };
67
+ return (_jsxs(_Fragment, { children: [_jsx("button", Object.assign({ ref: ref }, rest, { onClick: handleOnLeave }, { children: props.children })), openConfirmDialog && (_jsx(ConfirmDialog, { open: openConfirmDialog, title: _jsx(_Fragment, {}), content: _jsxs(_Fragment, { children: [_jsx(FormattedMessage, { id: "ui.liveStreamRoom.live.terminate", defaultMessage: "ui.liveStreamRoom.live.terminate" }), _jsx(FormGroup, { children: _jsx(FormControlLabel, { control: _jsx(Checkbox, { checked: closeLive, onChange: handleChangeCloseLive, inputProps: { 'aria-label': 'controlled' } }), label: _jsx(FormattedMessage, { id: "ui.liveStreamRoom.live.terminatePermanently", defaultMessage: "ui.liveStreamRoom.live.terminatePermanently" }) }) })] }), onConfirm: handleLeaveAction, isUpdating: isUpdating, onClose: () => setOpenConfirmDialog(false) }))] }));
12
68
  });
@@ -67,8 +67,6 @@ export default function LiveStreamVideoConference(inProps) {
67
67
  const canUseChat = useMemo(() => { var _a; return scUserContext.user && liveStream && liveStream && !((_a = liveStream === null || liveStream === void 0 ? void 0 : liveStream.settings) === null || _a === void 0 ? void 0 : _a.disableChat); }, [scUserContext, liveStream]);
68
68
  const canUseShareScreen = useMemo(() => { var _a; return scUserContext.user && liveStream && (liveStream.host.id === scUserContext.user.id || (liveStream && !((_a = liveStream === null || liveStream === void 0 ? void 0 : liveStream.settings) === null || _a === void 0 ? void 0 : _a.disableShareScreen))); }, [scUserContext, liveStream]);
69
69
  const speakerFocused = useMemo(() => (scUserContext.user && liveStream && liveStream.settings.view === SCLiveStreamViewType.SPEAKER ? liveStream.host : null), [scUserContext, liveStream]);
70
- console.log(canUseChat);
71
- console.log(speakerFocused);
72
70
  // CONNECT OPTIONS
73
71
  const connectOptions = useMemo(() => {
74
72
  return {
@@ -7,6 +7,7 @@ import { AudioTrack, ConnectionQualityIndicator, FocusToggle, LockLockedIcon, Pa
7
7
  import ParticipantTileAvatar from './ParticipantTileAvatar';
8
8
  import ParticipantTileActions from './ParticipantTileActions';
9
9
  import { useSCUser } from '@selfcommunity/react-core';
10
+ import { useLiveStream } from './LiveStreamProvider';
10
11
  /**
11
12
  * The `ParticipantContextIfNeeded` component only creates a `ParticipantContext`
12
13
  * if there is no `ParticipantContext` already.
@@ -40,6 +41,7 @@ export const ParticipantTile =
40
41
  });
41
42
  const isEncrypted = useIsEncrypted(trackReference.participant);
42
43
  const layoutContext = useMaybeLayoutContext();
44
+ const { liveStream } = useLiveStream();
43
45
  const autoManageSubscription = (_b = useFeatureContext()) === null || _b === void 0 ? void 0 : _b.autoSubscription;
44
46
  const handleSubscribe = React.useCallback((subscribed) => {
45
47
  if (trackReference.source &&
@@ -53,7 +55,7 @@ export const ParticipantTile =
53
55
  return (_jsx("div", Object.assign({ ref: ref, style: { position: 'relative' } }, elementProps, { children: _jsx(TrackRefContextIfNeeded, Object.assign({ trackRef: trackReference }, { children: _jsxs(ParticipantContextIfNeeded, Object.assign({ participant: trackReference.participant }, { children: [children !== null && children !== void 0 ? children : (_jsxs(_Fragment, { children: [isTrackReference(trackReference) &&
54
56
  (((_c = trackReference.publication) === null || _c === void 0 ? void 0 : _c.kind) === 'video' ||
55
57
  trackReference.source === Track.Source.Camera ||
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: {
58
+ 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, Object.assign({}, ((liveStream === null || liveStream === void 0 ? void 0 : liveStream.host.id) !== scUserContext.user.id ? { 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
59
  participant: trackReference.participant,
58
60
  source: Track.Source.Microphone
59
61
  }, 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 })] })) })) })));
@@ -100,7 +100,7 @@ export default function ContributionActionsMenu(props) {
100
100
  * Perform ban participant
101
101
  */
102
102
  const performBanParticipant = useMemo(() => () => __awaiter(this, void 0, void 0, function* () {
103
- const res = yield LiveStreamApiClient.removeUserFromRoom(liveStream.id, p.identity);
103
+ const res = yield LiveStreamApiClient.removeParticipant(liveStream.id, { participant_id: p.identity });
104
104
  if (res.status >= 300) {
105
105
  return Promise.reject(res);
106
106
  }
@@ -1,6 +1,5 @@
1
1
  import { __rest } from "tslib";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { useMemo } from 'react';
4
3
  import { styled } from '@mui/material/styles';
5
4
  import { useThemeProps } from '@mui/system';
6
5
  import { Box } from '@mui/material';
@@ -32,15 +31,6 @@ export default function ParticipantTileAvatar(inProps) {
32
31
  const { className, user, participant } = props, rest = __rest(props, ["className", "user", "participant"]);
33
32
  // CONTEXT
34
33
  const scContext = useSCContext();
35
- // AVATAR
36
- const avatar = useMemo(() => {
37
- if (user) {
38
- return _jsx("img", { src: `${user.avatar}` });
39
- }
40
- if (participant) {
41
- return _jsx("img", { src: `${scContext.settings.portal}/api/v2/avatar/${participant.identity}` });
42
- }
43
- return _jsx(ParticipantPlaceholder, {});
44
- }, [user, participant]);
45
- return (_jsx(Root, Object.assign({ className: classNames(className, classes.root) }, rest, { children: avatar })));
34
+ console.log(participant);
35
+ return (_jsx(Root, Object.assign({ className: classNames(className, classes.root) }, rest, { children: participant ? (_jsx("img", { src: `${scContext.settings.portal}/api/v2/avatar/${participant.identity}` })) : user ? (_jsx("img", { src: `${user.avatar}` })) : (_jsx(ParticipantPlaceholder, {})) })));
46
36
  }