@selfcommunity/react-ui
Version:
React UI Components to integrate a Community created with SelfCommunity Platform.
196 lines (195 loc) • 9.27 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useLivestreamCheck = void 0;
const react_1 = require("react");
const api_services_1 = require("@selfcommunity/api-services");
const components_react_1 = require("@livekit/components-react");
const LiveStreamProvider_1 = require("./LiveStreamProvider");
const notistack_1 = require("notistack");
const react_intl_1 = require("react-intl");
const react_core_1 = require("@selfcommunity/react-core");
const constants_1 = require("../constants");
const livekit_client_1 = require("livekit-client");
const _INITIAL_STATE = {
checkStarted: false,
timeRemaining: 60,
isExpiringSoonAloneInRoom: false,
isExpiringSoonMissingHost: false,
isExpiringSoonFewMinutesRemaining: false,
isExpiredSoonAloneInRoom: false,
isExpiredSoonMissingHost: false,
isExpiredSoonFewMinutesRemaining: false
};
const reducer = (state, action) => {
switch (action.type) {
case 'startChecking':
return Object.assign(Object.assign({}, _INITIAL_STATE), { checkStarted: true });
case 'stopChecking':
return Object.assign(Object.assign({}, _INITIAL_STATE), { checkStarted: false });
case 'reset':
return Object.assign({}, _INITIAL_STATE);
case 'isExpiringSoonAloneInRoom':
return Object.assign(Object.assign({}, state), { isExpiringSoonAloneInRoom: action.value });
case 'isExpiringSoonMissingHost':
return Object.assign(Object.assign({}, state), { isExpiringSoonMissingHost: action.value });
case 'isExpiringSoonFewMinutesRemaining':
return Object.assign(Object.assign({}, state), { isExpiringSoonFewMinutesRemaining: action.value });
case 'isExpiredAloneInRoom':
return Object.assign(Object.assign({}, state), { isExpiredAloneInRoom: action.value });
case 'isExpiredSoonMissingHost':
return Object.assign(Object.assign({}, state), { isExpiredSoonMissingHost: action.value });
case 'isExpiredSoonFewMinutesRemaining':
return Object.assign(Object.assign({}, state), { isExpiredSoonFewMinutesRemaining: action.value });
case 'timeRemaining':
return Object.assign(Object.assign({}, state), { timeRemaining: action.value });
default:
return Object.assign(Object.assign({}, state), { [action.type]: action.value });
}
};
/**
* Custom hook for monitoring livestream.
* @param {number} warningThreshold
* @param showWarnings
* @param performDisconnect
*/
function useLivestreamCheck(warningThreshold = constants_1.WARNING_THRESHOLD_EXPIRING_SOON, showWarnings = true, performDisconnect = true) {
// STATE
const [state, dispatch] = (0, react_1.useReducer)(reducer, _INITIAL_STATE);
const intervalRef = (0, react_1.useRef)(null);
// HOOKS
const scUserContext = (0, react_core_1.useSCUser)();
const participants = (0, components_react_1.useParticipants)({
updateOnlyOn: [
livekit_client_1.RoomEvent.ParticipantConnected,
livekit_client_1.RoomEvent.ParticipantDisconnected,
livekit_client_1.RoomEvent.ConnectionStateChanged,
livekit_client_1.RoomEvent.Connected,
livekit_client_1.RoomEvent.Disconnected,
livekit_client_1.RoomEvent.TrackSubscribed,
livekit_client_1.RoomEvent.TrackUnsubscribed
]
});
const { liveStream } = (0, LiveStreamProvider_1.useLiveStream)();
const { buttonProps } = (0, components_react_1.useDisconnectButton)({});
const { enqueueSnackbar } = (0, notistack_1.useSnackbar)();
const __DEBUG = (0, react_1.useRef)(true);
// INTL
const intl = (0, react_intl_1.useIntl)();
/**
* fetchLivestreamStatus
*/
const fetchLivestreamStatus = () => {
api_services_1.LiveStreamApiClient.getMonthlyDuration()
.then((r) => {
dispatch({ type: 'timeRemaining', value: r.remaining_minutes });
if (r.remaining_minutes > 0 && r.remaining_minutes <= warningThreshold) {
if (!state.isExpiringSoonFewMinutesRemaining &&
!state.isExpiredSoonFewMinutesRemaining &&
liveStream.host.id === scUserContext.user.id &&
showWarnings) {
__DEBUG && console.log('Warning: ');
enqueueSnackbar(intl.formatMessage({ id: 'ui.liveStreamRoom.check.fewMinutesRemaining', defaultMessage: 'ui.liveStreamRoom.check.fewMinutesRemaining' }), {
variant: 'warning',
autoHideDuration: 30000
});
dispatch({ type: 'isExpiringSoonFewMinutesRemaining', value: true });
}
}
else if (r.remaining_minutes <= 0) {
__DEBUG && console.log('Livestream expired');
dispatch({ type: 'isExpiredFewMinutesRemaining', value: true });
}
else if (state.isExpiredFewMinutesRemaining) {
dispatch({ type: 'isExpiringSoonFewMinutesRemaining', value: false });
}
})
.catch((error) => {
console.error('Error fetching live status:', error);
});
};
/**
* Check live
*/
const check = (0, react_1.useCallback)(() => {
if (__DEBUG) {
console.log('Checking live status');
console.log('Status: ', state);
console.log('Checking participants...', participants.length);
console.log(participants);
}
if (participants.length <= 1) {
if (!state.isExpiringSoonAloneInRoom && !state.isExpiredAloneInRoom && showWarnings) {
__DEBUG && console.log('Set expire soon: you are alone in the room');
enqueueSnackbar(intl.formatMessage({ id: 'ui.liveStreamRoom.check.youAreAloneInTheRoom', defaultMessage: 'ui.liveStreamRoom.check.youAreAloneInTheRoom' }), { variant: 'warning', autoHideDuration: 10000 });
state.isExpiringSoonAloneInRoom
? dispatch({ type: 'isExpiredAloneInRoom', value: true })
: dispatch({ type: 'isExpiringSoonAloneInRoom', value: true });
}
else if (performDisconnect && (state.isExpiringSoonAloneInRoom || state.isExpiredAloneInRoom)) {
// Leave the room
__DEBUG && console.log('Leave the room: no participants');
buttonProps.onClick();
}
return;
}
else if (state.isExpiringSoonAloneInRoom) {
__DEBUG && console.log('Reset expire soon');
dispatch({ type: 'isExpiringSoonAloneInRoom', value: false });
}
__DEBUG && console.log('Checking live speaker...');
const speaker = participants.find((pt) => {
return pt.name === liveStream.host.username;
});
if (!speaker) {
if (!state.isExpiredSoonMissingHost && !state.isExpiringSoonMissingHost && liveStream.host.id !== scUserContext.user.id && showWarnings) {
enqueueSnackbar(intl.formatMessage({ id: 'ui.liveStreamRoom.check.hostMissing', defaultMessage: 'ui.liveStreamRoom.check.hostMissing' }), {
variant: 'warning',
autoHideDuration: 10000
});
state.isExpiringSoonMissingHost
? dispatch({ type: 'isExpiredSoonMissingHost', value: true })
: dispatch({ type: 'isExpiringSoonMissingHost', value: true });
}
else if (performDisconnect && (state.isExpiredSoonMissingHost || state.isExpiringSoonMissingHost)) {
// Leave the room
__DEBUG && console.log('Leave the room: no host');
buttonProps.onClick();
}
}
else if (state.isExpiringSoonMissingHost) {
dispatch({ type: 'isExpiringSoonMissingHost', value: false });
}
__DEBUG && console.log('Checking live status resources...');
fetchLivestreamStatus();
}, [state, buttonProps, participants]);
/**
* Check live status
*/
(0, react_1.useEffect)(() => {
if (state.checkStarted) {
intervalRef.current = setInterval(check, constants_1.LIVE_CHECKING_INTERVAL * 60000);
}
return () => {
intervalRef.current && clearInterval(intervalRef.current);
};
}, [state, participants]);
/**
* Start the checking after a delay
*/
(0, react_1.useEffect)(() => {
let _timeout;
if (liveStream) {
_timeout = setTimeout(() => {
// Start the checking after 5 minutes
dispatch({ type: 'startChecking' });
__DEBUG && console.log('Start checking');
}, (liveStream.host.id === scUserContext.user.id ? constants_1.LIVE_CHECKING_INITIAL_DELAY_HOST : constants_1.LIVE_CHECKING_INITIAL_DELAY_GUEST) * 60000);
}
return () => {
_timeout && clearTimeout(_timeout);
dispatch({ type: 'stopChecking' });
};
}, [liveStream]);
return state;
}
exports.useLivestreamCheck = useLivestreamCheck;