snapshot of https://github.com/jitsi/jitsi-meet.git @ fd1749dd28f4138aa80234fc7f311b19aaffa0e7 (2026-09-15)
This commit is contained in:
206
react/features/whiteboard/middleware.web.ts
Normal file
206
react/features/whiteboard/middleware.web.ts
Normal file
@@ -0,0 +1,206 @@
|
||||
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 { showErrorNotification } from '../notifications/actions';
|
||||
import { NOTIFICATION_TIMEOUT_TYPE } from '../notifications/constants';
|
||||
|
||||
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,
|
||||
getCollabServerUrl,
|
||||
isWhiteboardPresent,
|
||||
shouldEnforceUserLimit,
|
||||
shouldNotifyUserLimit
|
||||
} from './functions';
|
||||
import logger from './logger';
|
||||
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 collabServerUrl = getCollabServerUrl(state);
|
||||
const enforceUserLimit = shouldEnforceUserLimit(state);
|
||||
const notifyUserLimit = shouldNotifyUserLimit(state);
|
||||
const iAmRecorder = Boolean(state['features/base/config'].iAmRecorder);
|
||||
|
||||
const iAmSipGateway = Boolean(state['features/base/config'].iAmSipGateway);
|
||||
|
||||
if ((iAmRecorder || iAmSipGateway) && action.isOpen) {
|
||||
logger.info('Whiteboard open skipped, not supported in recorder mode');
|
||||
|
||||
return next(action);
|
||||
}
|
||||
|
||||
if (enforceUserLimit) {
|
||||
dispatch(restrictWhiteboard(false));
|
||||
dispatch(openDialog('WhiteboardLimitDialog', WhiteboardLimitDialog));
|
||||
|
||||
return next(action);
|
||||
}
|
||||
|
||||
if (!existingCollabDetails) {
|
||||
if (action.isOpen) {
|
||||
if (!generateCollabServerUrl(state)) {
|
||||
logger.error('Whiteboard open failed, collabServerBaseUrl not configured');
|
||||
|
||||
if (action.userInitiated) {
|
||||
dispatch(showErrorNotification({
|
||||
titleKey: 'info.noWhiteboard'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
setNewWhiteboardOpen(store);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return next(action);
|
||||
}
|
||||
|
||||
if (action.isOpen) {
|
||||
if (!existingCollabDetails.roomId || !existingCollabDetails.roomKey || !collabServerUrl) {
|
||||
const missing = [
|
||||
!existingCollabDetails.roomId && 'roomId',
|
||||
!existingCollabDetails.roomKey && 'roomKey',
|
||||
!collabServerUrl && 'collabServerUrl'
|
||||
].filter(Boolean).join(', ');
|
||||
|
||||
logger.error(`Whiteboard open failed, missing collaboration data: ${missing}`);
|
||||
|
||||
if (action.userInitiated) {
|
||||
dispatch(showErrorNotification({
|
||||
titleKey: 'info.noWhiteboard'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (enforceUserLimit) {
|
||||
dispatch(restrictWhiteboard());
|
||||
|
||||
return next(action);
|
||||
}
|
||||
|
||||
if (notifyUserLimit) {
|
||||
dispatch(notifyWhiteboardLimit());
|
||||
}
|
||||
|
||||
if (isDialogOpen(state, WhiteboardLimitDialog)) {
|
||||
dispatch(hideDialog('WhiteboardLimitDialog', 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 { generateCollaborationLinkData } = await import(/* webpackChunkName: "excalidraw" */ '@jitsi/excalidraw');
|
||||
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
|
||||
};
|
||||
|
||||
dispatch(setupWhiteboard(collabData));
|
||||
conference?.getMetadataHandler().setMetadata(WHITEBOARD_ID, collabData);
|
||||
raiseWhiteboardNotification(WhiteboardStatus.INSTANTIATED);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user