jitsi-meet/react/features/whiteboard/middleware.web.ts
theluyuan 38ba663466
Some checks failed
Close stale issues and PRs / stale (push) Has been cancelled
init
2025-09-02 14:49:16 +08:00

163 lines
5.2 KiB
TypeScript

import { generateCollaborationLinkData } from '@jitsi/excalidraw';
import { AnyAction } from 'redux';
import { IStore } from '../app/types';
import { getCurrentConference } from '../base/conference/functions';
import { hideDialog, openDialog } from '../base/dialog/actions';
import { isDialogOpen } from '../base/dialog/functions';
import { participantJoined, participantLeft, pinParticipant } from '../base/participants/actions';
import { FakeParticipant } from '../base/participants/types';
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import { getCurrentRoomId } from '../breakout-rooms/functions';
import { addStageParticipant } from '../filmstrip/actions.web';
import { isStageFilmstripAvailable } from '../filmstrip/functions.web';
import { RESET_WHITEBOARD, SET_WHITEBOARD_OPEN } from './actionTypes';
import {
notifyWhiteboardLimit,
restrictWhiteboard,
setupWhiteboard
} from './actions';
import WhiteboardLimitDialog from './components/web/WhiteboardLimitDialog';
import { WHITEBOARD_ID, WHITEBOARD_PARTICIPANT_NAME } from './constants';
import {
generateCollabServerUrl,
getCollabDetails,
isWhiteboardPresent,
shouldEnforceUserLimit,
shouldNotifyUserLimit
} from './functions';
import { WhiteboardStatus } from './types';
import './middleware.any';
const focusWhiteboard = (store: IStore) => {
const { dispatch, getState } = store;
const state = getState();
const conference = getCurrentConference(state);
const stageFilmstrip = isStageFilmstripAvailable(state);
const isPresent = isWhiteboardPresent(state);
if (!isPresent) {
dispatch(participantJoined({
conference,
fakeParticipant: FakeParticipant.Whiteboard,
id: WHITEBOARD_ID,
name: WHITEBOARD_PARTICIPANT_NAME
}));
}
if (stageFilmstrip) {
dispatch(addStageParticipant(WHITEBOARD_ID, true));
} else {
dispatch(pinParticipant(WHITEBOARD_ID));
}
};
/**
* Middleware which intercepts whiteboard actions to handle changes to the related state.
*
* @param {Store} store - The redux store.
* @returns {Function}
*/
MiddlewareRegistry.register((store: IStore) => (next: Function) => (action: AnyAction) => {
const { dispatch, getState } = store;
const state = getState();
const conference = getCurrentConference(state);
switch (action.type) {
case SET_WHITEBOARD_OPEN: {
const existingCollabDetails = getCollabDetails(state);
const enforceUserLimit = shouldEnforceUserLimit(state);
const notifyUserLimit = shouldNotifyUserLimit(state);
const iAmRecorder = Boolean(state['features/base/config'].iAmRecorder);
if (enforceUserLimit) {
dispatch(restrictWhiteboard(false));
dispatch(openDialog(WhiteboardLimitDialog));
iAmRecorder && setTimeout(() => dispatch(hideDialog(WhiteboardLimitDialog)), 3000);
return next(action);
}
if (!existingCollabDetails) {
setNewWhiteboardOpen(store);
return next(action);
}
if (action.isOpen) {
if (enforceUserLimit) {
dispatch(restrictWhiteboard());
return next(action);
}
if (notifyUserLimit) {
dispatch(notifyWhiteboardLimit());
}
if (isDialogOpen(state, WhiteboardLimitDialog)) {
dispatch(hideDialog(WhiteboardLimitDialog));
}
focusWhiteboard(store);
raiseWhiteboardNotification(WhiteboardStatus.SHOWN);
return next(action);
}
dispatch(participantLeft(WHITEBOARD_ID, conference, { fakeParticipant: FakeParticipant.Whiteboard }));
raiseWhiteboardNotification(WhiteboardStatus.HIDDEN);
break;
}
case RESET_WHITEBOARD: {
dispatch(participantLeft(WHITEBOARD_ID, conference, { fakeParticipant: FakeParticipant.Whiteboard }));
raiseWhiteboardNotification(WhiteboardStatus.RESET);
break;
}
}
return next(action);
});
/**
* Raises the whiteboard status notifications changes (if API is enabled).
*
* @param {WhiteboardStatus} status - The whiteboard changed status.
* @returns {Function}
*/
function raiseWhiteboardNotification(status: WhiteboardStatus) {
if (typeof APP !== 'undefined') {
APP.API.notifyWhiteboardStatusChanged(status);
}
}
/**
* Sets a new whiteboard open.
*
* @param {IStore} store - The redux store.
* @returns {Promise}
*/
async function setNewWhiteboardOpen(store: IStore) {
const { dispatch, getState } = store;
const collabLinkData = await generateCollaborationLinkData();
const state = getState();
const conference = getCurrentConference(state);
const collabServerUrl = generateCollabServerUrl(state);
const roomId = getCurrentRoomId(state);
const collabData = {
collabDetails: {
roomId,
roomKey: collabLinkData.roomKey
},
collabServerUrl
};
focusWhiteboard(store);
dispatch(setupWhiteboard(collabData));
conference?.getMetadataHandler().setMetadata(WHITEBOARD_ID, collabData);
raiseWhiteboardNotification(WhiteboardStatus.INSTANTIATED);
}