UNPKG

@selfcommunity/react-ui

Version:

React UI Components to integrate a Community created with SelfCommunity Platform.

216 lines (211 loc) • 18 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const jsx_runtime_1 = require("react/jsx-runtime"); const material_1 = require("@mui/material"); const styles_1 = require("@mui/material/styles"); const system_1 = require("@mui/system"); const react_core_1 = require("@selfcommunity/react-core"); const types_1 = require("@selfcommunity/types"); const classnames_1 = tslib_1.__importDefault(require("classnames")); const react_intl_1 = require("react-intl"); const constants_1 = require("./constants"); const react_1 = require("react"); const LiveStreamVideoConference_1 = tslib_1.__importDefault(require("./LiveStreamVideoConference")); require("@livekit/components-styles"); const api_services_1 = require("@selfcommunity/api-services"); const utils_1 = require("@selfcommunity/utils"); const Errors_1 = require("../../constants/Errors"); const PreJoin_1 = require("./LiveStreamVideoConference/PreJoin"); const LiveStreamProvider_1 = require("./LiveStreamVideoConference/LiveStreamProvider"); const notistack_1 = require("notistack"); const DialogContent_1 = tslib_1.__importDefault(require("@mui/material/DialogContent")); const BaseDialog_1 = tslib_1.__importDefault(require("../../shared/BaseDialog")); const CopyTextArea_1 = tslib_1.__importDefault(require("../../shared/CopyTextArea")); const classes = { root: `${constants_1.PREFIX}-root`, content: `${constants_1.PREFIX}-content`, title: `${constants_1.PREFIX}-title`, logo: `${constants_1.PREFIX}-logo`, description: `${constants_1.PREFIX}-description`, endConferenceWrap: `${constants_1.PREFIX}-end-conference-wrap`, btnBackHome: `${constants_1.PREFIX}-btn-back-home`, startPrejoinContent: `${constants_1.PREFIX}-start-prejoin-content`, preJoin: `${constants_1.PREFIX}-prejoin`, preJoinLoading: `${constants_1.PREFIX}-prejoin-loading`, prejoinLoader: `${constants_1.PREFIX}-prejoin-loader`, preJoinAlert: `${constants_1.PREFIX}-prejoin-alert`, shareLink: `${constants_1.PREFIX}-share-link`, endPrejoinContent: `${constants_1.PREFIX}-end-prejoin-content`, endPrejoinContentBox: `${constants_1.PREFIX}-end-prejoin-content-box`, conference: `${constants_1.PREFIX}-conference`, error: `${constants_1.PREFIX}-error` }; const Root = (0, styles_1.styled)(material_1.Box, { name: constants_1.PREFIX, slot: 'Root' })(({ theme }) => ({})); const DialogRoot = (0, styles_1.styled)(BaseDialog_1.default, { name: constants_1.PREFIX, slot: 'Root', overridesResolver: (props, styles) => styles.dialogRoot })(({ theme }) => ({})); /** *> API documentation for the Community-JS LiveStreamRoom component. Learn about the available props and the CSS API. * #### Import ```jsx import {LiveStreamRoom} from '@selfcommunity/react-ui'; ``` #### Component Name The name `LiveStreamRoom` can be used when providing style overrides in the theme. #### CSS |Rule Name|Global class|Description| |---|---|---| |root|.SCLiveStreamRoom-root|Styles applied to the root element.| |title|.SCLiveStreamRoom-title|Styles applied to the title element.| |description|.SCLiveStreamRoom-description|Styles applied to the description element.| |content|.SCLiveStreamRoom-content|Styles applied to the content.| |prejoin|.SCLiveStreamRoom-prejoin|Styles applied to the prejoin.| |conference|.SCLiveStreamRoom-conference|Styles applied to the conference.| |error|.SCLiveStreamRoom-error|Styles applied to the error elements.| * @param inProps */ function LiveStreamRoom(inProps) { var _a, _b, _c, _d; //PROPS const props = (0, system_1.useThemeProps)({ props: inProps, name: constants_1.PREFIX }); const { id = `live_stream_room_object_${props.liveStreamId ? props.liveStreamId : props.liveStream ? props.liveStream.id : ''}`, liveStreamId = null, liveStream = null, className, showPrejoinTitle = true, showPrejoinDescription = false, startPrejoinContent, endPrejoinContent, presetConnectionDetails, presetPreJoinChoices, LiveStreamVideoConferenceComponentProps = { options: { codec: 'vp8', hq: false } } } = props, rest = tslib_1.__rest(props, ["id", "liveStreamId", "liveStream", "className", "showPrejoinTitle", "showPrejoinDescription", "startPrejoinContent", "endPrejoinContent", "presetConnectionDetails", "presetPreJoinChoices", "LiveStreamVideoConferenceComponentProps"]); // CONTEXT const scUserContext = (0, react_core_1.useSCUser)(); const scRoutingContext = (0, react_core_1.useSCRouting)(); const { preferences, features } = (0, react_core_1.useSCPreferences)(); // STATE const { scLiveStream } = (0, react_core_1.useSCFetchLiveStream)({ id: liveStreamId, liveStream }); const [preJoinChoices, setPreJoinChoices] = (0, react_1.useState)(presetPreJoinChoices); const [loading, setLoading] = (0, react_1.useState)(false); const [error, setError] = (0, react_1.useState)(null); const preJoinDefaults = (0, react_1.useMemo)(() => { var _a, _b, _c; return { username: ((_a = scUserContext.user) === null || _a === void 0 ? void 0 : _a.username) || '', videoEnabled: ((_b = scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.settings) === null || _b === void 0 ? void 0 : _b.disableVideo) === false, audioEnabled: ((_c = scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.settings) === null || _c === void 0 ? void 0 : _c.muteParticipants) === false }; }, [scUserContext.user, scLiveStream]); const [connectionDetails, setConnectionDetails] = (0, react_1.useState)(presetConnectionDetails); const liveStreamEnabled = (0, react_1.useMemo)(() => preferences && features && features.includes(types_1.SCFeatureName.LIVE_STREAM) && react_core_1.SCPreferences.CONFIGURATIONS_LIVE_STREAM_ENABLED in preferences && preferences[react_core_1.SCPreferences.CONFIGURATIONS_LIVE_STREAM_ENABLED].value, [preferences, features]); const scPreferencesContext = (0, react_1.useContext)(react_core_1.SCPreferencesContext); const appUrl = (0, react_1.useMemo)(() => scPreferencesContext.preferences && scPreferencesContext.preferences[react_core_1.SCPreferences.CONFIGURATIONS_APP_URL].value, [scPreferencesContext.preferences]); // INTL const intl = (0, react_intl_1.useIntl)(); // MESSAGES const { enqueueSnackbar } = (0, notistack_1.useSnackbar)(); // HANDLERS /** * Handle PreJoin Submit */ const handlePreJoinSubmit = (0, react_1.useCallback)((values) => { if (scLiveStream || !loading) { setLoading(true); setError(null); toggleAttrDisabledPrejoinActions(true); api_services_1.LiveStreamService.join(scLiveStream.id) .then((data) => { setPreJoinChoices(values); setConnectionDetails(Object.assign(Object.assign({}, data), { participantName: scUserContext.user.username })); toggleAttrDisabledPrejoinActions(false); setLoading(false); }) .catch((error) => { utils_1.Logger.error(Errors_1.SCOPE_SC_UI, error); if (error.response && error.response.data && typeof error.response.data === 'object' && error.response.data.errors && error.response.data.errors.length) { let _msg = ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.connect.error.generic", defaultMessage: "'ui.liveStreamRoom.connect.error.generic", values: { link: (...chunks) => (0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({ to: '/' }, { children: chunks })) } })); if (error.response.data.errors[0].code) { const _error = `ui.liveStreamRoom.connect.error.${(0, utils_1.camelCase)(error.response.data.errors[0].code)}`; _msg = ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: _error, defaultMessage: _error, values: { link: (...chunks) => ((0, jsx_runtime_1.jsx)("a", Object.assign({ style: { color: '#FFF' }, href: error.response.data.errors[0].code === types_1.SCLiveStreamConnectionDetailsErrorType.PARTICIPATE_THE_EVENT_TO_JOIN_LIVE_STREAM && scLiveStream.event ? scRoutingContext.url(react_core_1.SCRoutes.EVENT_ROUTE_NAME, scLiveStream.event) : '/' }, { children: chunks }))) } })); if (error.response.data.errors[0].code === types_1.SCLiveStreamConnectionDetailsErrorType.WAITING_HOST_TO_START_LIVE_STREAM || error.response.data.errors[0].code === types_1.SCLiveStreamConnectionDetailsErrorType.PARTICIPANTS_LIMIT_REACHED) { setError(_msg); } else { setTimeout(() => toggleAttrDisabledPrejoinActions(false), 10000); } enqueueSnackbar(_msg, { variant: 'error', autoHideDuration: 5000 }); } else { enqueueSnackbar(_msg, { variant: 'error' }); setError(_msg); } } setLoading(false); }); } }, [scUserContext.user, setPreJoinChoices, setConnectionDetails, scLiveStream, setError, loading]); /** * Handle disable controls button */ const toggleAttrDisabledPrejoinActions = (0, react_1.useCallback)((disabled) => { const container = document.querySelector('.lk-prejoin'); if (container) { const buttons = container.querySelectorAll('button.lk-button'); buttons.forEach((button) => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore button.disabled = disabled; }); } }, []); /** * Handle PreJoin Error */ const handlePreJoinError = (0, react_1.useCallback)((e) => { console.error(e); if (e.message !== 'NotAllowedError: Permission denied') { enqueueSnackbar(intl.formatMessage({ id: 'ui.liveStreamRoom.connect.error.device.permission', defaultMessage: 'ui.liveStreamRoom.connect.error.device.permission' }), { variant: 'error', autoHideDuration: 5000 }); } else if (e.message !== 'NotFoundError: Requested device not found') { enqueueSnackbar(intl.formatMessage({ id: 'ui.liveStreamRoom.connect.error.device.notFound', defaultMessage: 'ui.liveStreamRoom.connect.error.device.notFound' }), { variant: 'error', autoHideDuration: 5000 }); } }, []); /** * User must be authenticated */ if (!scLiveStream || !scUserContext.user || !liveStreamEnabled) { return (0, jsx_runtime_1.jsx)(material_1.CircularProgress, {}); } /** * Renders root object */ 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.jsx)(DialogRoot, Object.assign({ open: true, maxWidth: 'md', fullWidth: true }, { children: (0, jsx_runtime_1.jsxs)(DialogContent_1.default, Object.assign({ className: classes.endConferenceWrap }, { children: [(0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({ to: scRoutingContext.url(react_core_1.SCRoutes.HOME_ROUTE_NAME, {}), className: classes.logo }, { children: (0, jsx_runtime_1.jsx)("img", { src: preferences[react_core_1.SCPreferences.LOGO_NAVBAR_LOGO].value, alt: "logo" }) })), (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: "h4", className: classes.title, alignContent: 'center' }, { children: scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.title }))), (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, joinLabel: intl.formatMessage({ id: 'ui.liveStreamRoom.preJoin.joinRoom', defaultMessage: 'ui.liveStreamRoom.preJoin.joinRoom' }), micLabel: intl.formatMessage({ id: 'ui.liveStreamRoom.preJoin.microphone', defaultMessage: 'ui.liveStreamRoom.preJoin.microphone' }), camLabel: intl.formatMessage({ id: 'ui.liveStreamRoom.preJoin.camera', defaultMessage: 'ui.liveStreamRoom.preJoin.camera' }), userLabel: intl.formatMessage({ id: 'ui.liveStreamRoom.preJoin.username', defaultMessage: 'ui.liveStreamRoom.preJoin.username' }) }) })), 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: [scLiveStream && ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ sx: { width: '47%' }, spacing: 1, className: classes.endPrejoinContentBox }, { children: [scLiveStream && scUserContext.user && scUserContext.user.id !== scLiveStream.host.id && scLiveStream && (((_a = scLiveStream.settings) === null || _a === void 0 ? void 0 : _a.muteParticipants) || ((_b = scLiveStream.settings) === null || _b === void 0 ? void 0 : _b.disableVideo)) && ((0, jsx_runtime_1.jsxs)(material_1.Alert, Object.assign({ variant: "filled", severity: "info", className: classes.preJoinAlert }, { children: [(0, jsx_runtime_1.jsx)(material_1.AlertTitle, { children: (0, jsx_runtime_1.jsx)("b", { children: "Info" }) }), ((_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", {})] })), ((_d = scLiveStream.settings) === null || _d === void 0 ? void 0 : _d.disableVideo) && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["- ", (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.hostDisableVideo", defaultMessage: "ui.liveStreamRoom.hostDisableVideo" })] }))] }))), (0, jsx_runtime_1.jsx)(CopyTextArea_1.default, { className: classes.shareLink, value: `${appUrl}${scRoutingContext.url(react_core_1.SCRoutes.LIVESTREAM_ROUTE_NAME, scLiveStream)}`, label: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.shareLink", defaultMessage: "ui.liveStreamRoom.shareLink" }) }), (scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.description) && ((0, jsx_runtime_1.jsxs)(material_1.Alert, Object.assign({ variant: "filled", severity: "info", className: classes.description }, { children: [(0, jsx_runtime_1.jsx)(material_1.AlertTitle, { children: (0, jsx_runtime_1.jsx)("b", { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.liveStreamRoom.description", defaultMessage: "ui.liveStreamRoom.description" }) }) }), scLiveStream === null || scLiveStream === void 0 ? void 0 : scLiveStream.description] })))] }))), 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)) })) }))) }))) }))); } exports.default = LiveStreamRoom;