@selfcommunity/react-ui
Version:
React UI Components to integrate a Community created with SelfCommunity Platform.
153 lines (148 loc) • 10.3 kB
JavaScript
import { __rest } from "tslib";
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { Box, Button, CircularProgress, Typography } from '@mui/material';
import { styled } from '@mui/material/styles';
import { useThemeProps } from '@mui/system';
import { Link, SCPreferences, SCRoutes, useSCPreferences, useSCRouting, useSCUser } from '@selfcommunity/react-core';
import { SCLiveStreamViewType } from '@selfcommunity/types';
import classNames from 'classnames';
import { PREFIX } from './constants';
import { ConnectionState, formatChatMessageLinks, LayoutContextProvider, LiveKitRoom } from '@livekit/components-react';
import { useCallback, useMemo, useState } from 'react';
import { defaultUserChoices } from '@livekit/components-core';
import { defaultVideoOptions } from '../constants';
import { FormattedMessage, useIntl } from 'react-intl';
import { VideoConference } from './VideoConference';
import { useLiveStream } from './LiveStreamProvider';
import DialogContent from '@mui/material/DialogContent';
import BaseDialog from '../../../shared/BaseDialog';
import { closeSnackbar } from 'notistack';
const classes = {
root: `${PREFIX}-root`,
logo: `${PREFIX}-logo`,
title: `${PREFIX}-title`,
content: `${PREFIX}-content`,
endConferenceWrap: `${PREFIX}-end-conference-wrap`,
btnBackHome: `${PREFIX}-btn-back-home`,
actions: `${PREFIX}-actions`,
error: `${PREFIX}-error`
};
const Root = styled(Box, {
name: PREFIX,
slot: 'Root'
})(({ theme }) => ({}));
const DialogRoot = styled(BaseDialog, {
name: PREFIX,
slot: 'Root',
overridesResolver: (props, styles) => styles.dialogRoot
})(({ theme }) => ({}));
const PREFERENCES = [SCPreferences.LOGO_NAVBAR_LOGO];
/**
*> API documentation for the Community-JS LiveStreamVideoConference component. Learn about the available props and the CSS API.
*
#### Import
```jsx
import {LiveStreamVideoConference} from '@selfcommunity/react-ui';
```
#### Component Name
The name `LiveStreamVideoConference` can be used when providing style overrides in the theme.
#### CSS
|Rule Name|Global class|Description|
|---|---|---|
|root|.SCLiveStreamForm-root|Styles applied to the root element.|
* @param inProps
*/
export default function LiveStreamVideoConference(inProps) {
//PROPS
const props = useThemeProps({
props: inProps,
name: PREFIX
});
const { className, handleOnLeaveRoom, userChoices = defaultUserChoices, connectionDetails = {}, LiveKitRoomComponentProps = {
/* simulateParticipants: true */
}, VideoConferenceComponentProps = {}, startConferenceEndContent, endConferenceEndContent, options = defaultVideoOptions } = props, rest = __rest(props, ["className", "handleOnLeaveRoom", "userChoices", "connectionDetails", "LiveKitRoomComponentProps", "VideoConferenceComponentProps", "startConferenceEndContent", "endConferenceEndContent", "options"]);
// CONTEXT
const scUserContext = useSCUser();
const scRoutingContext = useSCRouting();
const scPreferences = useSCPreferences();
const { liveStream } = useLiveStream();
// STATE
const [liveActive, setLiveActive] = useState(true);
const [error, setError] = useState(null);
// INTL
const intl = useIntl();
// PREFERENCES
const preferences = useMemo(() => {
const _preferences = {};
PREFERENCES.map((p) => (_preferences[p] = p in scPreferences.preferences ? scPreferences.preferences[p].value : null));
return _preferences;
}, [scPreferences.preferences]);
// PERMISSIONS
const canUseAudio = 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.muteParticipants))); }, [scUserContext, liveStream]);
const canUseVideo = 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.disableVideo))); }, [scUserContext, liveStream]);
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]);
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]);
const speakerFocused = useMemo(() => (scUserContext.user && liveStream && liveStream.settings.view === SCLiveStreamViewType.SPEAKER ? liveStream.host : null), [scUserContext, liveStream]);
const hideParticipantsList = useMemo(() => { var _a; return scUserContext.user && liveStream && ((_a = liveStream === null || liveStream === void 0 ? void 0 : liveStream.settings) === null || _a === void 0 ? void 0 : _a.hideParticipantsList) && liveStream.host.id !== scUserContext.user.id; }, [scUserContext, liveStream]);
// CONNECT OPTIONS
const connectOptions = useMemo(() => {
return {
autoSubscribe: true
};
}, []);
// HANDLERS
/**
* Handle on leave
*/
const handleOnLeave = useCallback(() => {
setLiveActive(false);
handleOnLeaveRoom === null || handleOnLeaveRoom === void 0 ? void 0 : handleOnLeaveRoom();
}, [handleOnLeaveRoom]);
/**
* Handle on error
*/
const handleError = useCallback((error) => {
console.error(error);
if (error.message === 'Permission denied') {
setError(intl.formatMessage({
id: 'ui.liveStreamRoom.connect.error.device.permission',
defaultMessage: 'ui.liveStreamRoom.connect.error.device.permission'
}));
}
else if (error.message === 'Requested device not found') {
setError(intl.formatMessage({
id: 'ui.liveStreamRoom.connect.error.device.notFound',
defaultMessage: 'ui.liveStreamRoom.connect.error.device.notFound'
}));
}
else {
console.log(`Encountered an unexpected error, check the console logs for details: ${error.message}`);
setError(intl.formatMessage({
id: 'ui.liveStreamRoom.connect.error.clientInitiatedDisconnect',
defaultMessage: 'ui.liveStreamRoom.connect.error.clientInitiatedDisconnect'
}));
}
setLiveActive(false);
}, []);
/**
* Handle encryption error
*/
const handleEncryptionError = useCallback((error) => {
console.error(error);
setError(`Encountered an unexpected encryption error, check the console logs for details: ${error.message}`);
setLiveActive(false);
}, []);
const handleBackHome = useCallback(() => {
closeSnackbar();
}, [closeSnackbar]);
/**
* User must be authenticated
*/
if (!scUserContext.user || !connectionDetails) {
return _jsx(CircularProgress, {});
}
/**
* Renders root object
*/
return (_jsx(Root, Object.assign({ className: classNames(classes.root, className) }, rest, { children: liveActive && !error ? (_jsx(_Fragment, { children: _jsx(LiveKitRoom, Object.assign({ connect: Boolean(liveActive), token: connectionDetails['participantToken'], serverUrl: connectionDetails['serverUrl'], connectOptions: connectOptions, video: userChoices.videoEnabled, audio: userChoices.audioEnabled, onDisconnected: handleOnLeave, onEncryptionError: handleEncryptionError, onError: handleError }, LiveKitRoomComponentProps, { children: _jsxs(LayoutContextProvider, { children: [_jsx(VideoConference, Object.assign({ chatMessageFormatter: formatChatMessageLinks }, (speakerFocused && { speakerFocused: liveStream.host }), VideoConferenceComponentProps, { disableMicrophone: !canUseAudio, disableCamera: !canUseVideo, disableChat: !canUseChat, disableShareScreen: !canUseShareScreen, hideParticipantsList: hideParticipantsList })), _jsx(ConnectionState, {})] }) })) })) : (_jsx(_Fragment, { children: error ? (_jsx(DialogRoot, Object.assign({ open: true, maxWidth: 'md', fullWidth: true }, { children: _jsx(DialogContent, { children: _jsxs(Box, Object.assign({ className: classes.endConferenceWrap }, { children: [_jsx(Link, Object.assign({ to: scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}), className: classes.logo }, { children: _jsx("img", { src: preferences[SCPreferences.LOGO_NAVBAR_LOGO], alt: "logo" }) })), startConferenceEndContent, error, _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" }) })), endConferenceEndContent] })) }) }))) : liveActive === false ? (_jsx(DialogRoot, Object.assign({ open: true, maxWidth: 'md', fullWidth: true }, { children: _jsx(DialogContent, { children: _jsxs(Box, Object.assign({ className: classes.endConferenceWrap }, { children: [_jsx(Link, Object.assign({ to: scRoutingContext.url(SCRoutes.HOME_ROUTE_NAME, {}), className: classes.logo }, { children: _jsx("img", { src: preferences[SCPreferences.LOGO_NAVBAR_LOGO], alt: "logo" }) })), startConferenceEndContent, _jsx(Typography, Object.assign({ variant: "h5" }, { children: _jsx(FormattedMessage, { id: "ui.liveStreamRoom.conference.end", defaultMessage: "ui.liveStreamRoom.conference.end" }) })), _jsx(Button, Object.assign({ variant: "contained", color: "secondary", component: Link, to: '/', onClick: handleBackHome, className: classes.btnBackHome }, { children: _jsx(FormattedMessage, { id: "ui.liveStreamRoom.button.backHome", defaultMessage: "ui.liveStreamRoom.button.backHome" }) })), endConferenceEndContent] })) }) }))) : (_jsx(CircularProgress, {})) })) })));
}