diff --git a/doc/api.md b/doc/api.md index d3cec00a6..1cd8e9ecd 100644 --- a/doc/api.md +++ b/doc/api.md @@ -387,6 +387,19 @@ changes. The listener will receive an object with the following structure: } ``` +* **participantKickedOut** - event notifications about a participants being removed from the room. The listener will receive an object with the following structure: +```javascript +{ + kicked: { + id: string, // the id of the participant removed from the room + local: boolean // whether or not the participant is the local particiapnt + }, + kicker: { + id: string // the id of the participant who kicked out the other participant + } +} +``` + * **participantLeft** - event notifications about participants that leave the room. The listener will receive an object with the following structure: ```javascript { diff --git a/modules/API/API.js b/modules/API/API.js index 917646d09..2ef9effd4 100644 --- a/modules/API/API.js +++ b/modules/API/API.js @@ -658,6 +658,24 @@ class API { }); } + /** + * Notify external application of a participant, remote or local, being + * removed from the conference by another participant. + * + * @param {string} kicked - The ID of the participant removed from the + * conference. + * @param {string} kicker - The ID of the participant that removed the + * other participant. + * @returns {void} + */ + notifyKickedOut(kicked: Object, kicker: Object) { + this._sendEvent({ + name: 'participant-kicked-out', + kicked, + kicker + }); + } + /** * Notify external application of the current meeting requiring a password * to join. diff --git a/modules/API/external/external_api.js b/modules/API/external/external_api.js index 028baaee5..c226b4436 100644 --- a/modules/API/external/external_api.js +++ b/modules/API/external/external_api.js @@ -63,6 +63,7 @@ const events = { 'mic-error': 'micError', 'outgoing-message': 'outgoingMessage', 'participant-joined': 'participantJoined', + 'participant-kicked-out': 'participantKickedOut', 'participant-left': 'participantLeft', 'password-required': 'passwordRequired', 'proxy-connection-event': 'proxyConnectionEvent', diff --git a/react/features/base/participants/actionTypes.js b/react/features/base/participants/actionTypes.js index 4dd567134..3994ac4fa 100644 --- a/react/features/base/participants/actionTypes.js +++ b/react/features/base/participants/actionTypes.js @@ -65,6 +65,18 @@ export const PARTICIPANT_ID_CHANGED = 'PARTICIPANT_ID_CHANGED'; */ export const PARTICIPANT_JOINED = 'PARTICIPANT_JOINED'; +/** + * Action to signal that a participant has been removed from a conference by + * another participant. + * + * { + * type: PARTICIPANT_KICKED, + * kicked: Object, + * kicker: Object + * } + */ +export const PARTICIPANT_KICKED = 'PARTICIPANT_KICKED'; + /** * Action to handle case when participant lefts. * diff --git a/react/features/base/participants/actions.js b/react/features/base/participants/actions.js index 28618b50f..1ed068e30 100644 --- a/react/features/base/participants/actions.js +++ b/react/features/base/participants/actions.js @@ -9,6 +9,7 @@ import { MUTE_REMOTE_PARTICIPANT, PARTICIPANT_ID_CHANGED, PARTICIPANT_JOINED, + PARTICIPANT_KICKED, PARTICIPANT_LEFT, PARTICIPANT_UPDATED, PIN_PARTICIPANT @@ -415,6 +416,12 @@ export function participantMutedUs(participant) { export function participantKicked(kicker, kicked) { return (dispatch, getState) => { + dispatch({ + type: PARTICIPANT_KICKED, + kicked: kicked.getId(), + kicker: kicker.getId() + }); + dispatch(showNotification({ titleArguments: { kicked: diff --git a/react/features/external-api/middleware.js b/react/features/external-api/middleware.js index 0ca97261a..ffce7b198 100644 --- a/react/features/external-api/middleware.js +++ b/react/features/external-api/middleware.js @@ -1,9 +1,14 @@ // @flow -import { CONFERENCE_FAILED, CONFERENCE_JOINED } from '../base/conference'; +import { + CONFERENCE_FAILED, + CONFERENCE_JOINED, + KICKED_OUT +} from '../base/conference'; import { NOTIFY_CAMERA_ERROR, NOTIFY_MIC_ERROR } from '../base/devices'; import { JitsiConferenceErrors } from '../base/lib-jitsi-meet'; import { + PARTICIPANT_KICKED, getAvatarURLByParticipantId, getLocalParticipant } from '../base/participants'; @@ -53,6 +58,16 @@ MiddlewareRegistry.register(store => next => action => { break; } + case KICKED_OUT: + APP.API.notifyKickedOut( + { + id: getLocalParticipant(store.getState()).id, + local: true + }, + { id: action.participant.getId() } + ); + break; + case NOTIFY_CAMERA_ERROR: if (action.error) { APP.API.notifyOnCameraError( @@ -66,6 +81,15 @@ MiddlewareRegistry.register(store => next => action => { } break; + case PARTICIPANT_KICKED: + APP.API.notifyKickedOut( + { + id: action.kicked, + local: false + }, + { id: action.kicker }); + break; + case SET_FILMSTRIP_VISIBLE: APP.API.notifyFilmstripDisplayChanged(action.visible); break;