feat(api) expose event for mouse movements inside the iframe

This commit is contained in:
Tudor-Ovidiu Avram 2021-06-09 13:09:08 +03:00
parent a564ce581d
commit 7f04767566
5 changed files with 149 additions and 2 deletions

View File

@ -792,6 +792,11 @@ var config = {
websocketKeepAliveUrl
*/
/**
* Default interval (milliseconds) for triggering mouseMoved iframe API event
*/
mouseMoveCallbackInterval: 1000,
/**
Use this array to configure which notifications will be shown to the user
The items correspond to the title or description key of that notification

View File

@ -572,6 +572,44 @@ function toggleScreenSharing(enable) {
}
}
/**
* Removes sensitive data from a mouse event.
*
* @param {MouseEvent} event - The mouse event to sanitize.
* @returns {Object}
*/
function sanitizeMouseEvent(event: MouseEvent) {
const {
clientX,
clientY,
movementX,
movementY,
offsetX,
offsetY,
pageX,
pageY,
x,
y,
screenX,
screenY
} = event;
return {
clientX,
clientY,
movementX,
movementY,
offsetX,
offsetY,
pageX,
pageY,
x,
y,
screenX,
screenY
};
}
/**
* Implements API class that communicates with external API class and provides
* interface to access Jitsi Meet features by external applications that embed
@ -675,6 +713,45 @@ class API {
});
}
/**
* Notify external application (if API is enabled) that the mouse has entered inside the iframe.
*
* @param {MouseEvent} event - The mousemove event.
* @returns {void}
*/
notifyMouseEnter(event: MouseEvent) {
this._sendEvent({
name: 'mouse-enter',
event: sanitizeMouseEvent(event)
});
}
/**
* Notify external application (if API is enabled) that the mouse has entered inside the iframe.
*
* @param {MouseEvent} event - The mousemove event.
* @returns {void}
*/
notifyMouseLeave(event: MouseEvent) {
this._sendEvent({
name: 'mouse-leave',
event: sanitizeMouseEvent(event)
});
}
/**
* Notify external application (if API is enabled) that the mouse has moved inside the iframe.
*
* @param {MouseEvent} event - The mousemove event.
* @returns {void}
*/
notifyMouseMove(event: MouseEvent) {
this._sendEvent({
name: 'mouse-move',
event: sanitizeMouseEvent(event)
});
}
/**
* Notify external application that the video quality setting has changed.
*

View File

@ -84,6 +84,9 @@ const events = {
'incoming-message': 'incomingMessage',
'log': 'log',
'mic-error': 'micError',
'mouse-enter': 'mouseEnter',
'mouse-leave': 'mouseLeave',
'mouse-move': 'mouseMove',
'outgoing-message': 'outgoingMessage',
'participant-joined': 'participantJoined',
'participant-kicked-out': 'participantKickedOut',

View File

@ -140,6 +140,7 @@ export default [
'liveStreamingEnabled',
'localRecording',
'maxFullResolutionParticipants',
'mouseMoveCallbackInterval',
'notifications',
'openSharedDocumentOnJoin',
'opusMaxAverageBitrate',

View File

@ -85,6 +85,11 @@ type Props = AbstractProps & {
*/
_layoutClassName: string,
/**
* The config specified interval for triggering mouseMoved iframe api events
*/
_mouseMoveCallbackInterval: number,
/**
* Name for this conference room.
*/
@ -104,7 +109,11 @@ type Props = AbstractProps & {
*/
class Conference extends AbstractConference<Props, *> {
_onFullScreenChange: Function;
_onMouseEnter: Function;
_onMouseLeave: Function;
_onMouseMove: Function;
_onShowToolbar: Function;
_originalOnMouseMove: Function;
_originalOnShowToolbar: Function;
_setBackground: Function;
@ -117,9 +126,13 @@ class Conference extends AbstractConference<Props, *> {
constructor(props) {
super(props);
const { _mouseMoveCallbackInterval } = props;
// Throttle and bind this component's mousemove handler to prevent it
// from firing too often.
this._originalOnShowToolbar = this._onShowToolbar;
this._originalOnMouseMove = this._onMouseMove;
this._onShowToolbar = _.throttle(
() => this._originalOnShowToolbar(),
100,
@ -128,6 +141,14 @@ class Conference extends AbstractConference<Props, *> {
trailing: false
});
this._onMouseMove = _.throttle(
event => this._originalOnMouseMove(event),
_mouseMoveCallbackInterval,
{
leading: true,
trailing: false
});
// Bind event handler so it is only bound once for every instance.
this._onFullScreenChange = this._onFullScreenChange.bind(this);
this._setBackground = this._setBackground.bind(this);
@ -192,7 +213,11 @@ class Conference extends AbstractConference<Props, *> {
} = this.props;
return (
<div id = 'layout_wrapper'>
<div
id = 'layout_wrapper'
onMouseEnter = { this._onMouseEnter }
onMouseLeave = { this._onMouseLeave }
onMouseMove = { this._onMouseMove } >
<div
className = { _layoutClassName }
id = 'videoconference_page'
@ -262,6 +287,39 @@ class Conference extends AbstractConference<Props, *> {
this.props.dispatch(fullScreenChanged(APP.UI.isFullScreen()));
}
/**
* Triggers iframe API mouseEnter event.
*
* @param {MouseEvent} event - The mouse event.
* @private
* @returns {void}
*/
_onMouseEnter(event) {
APP.API.notifyMouseEnter(event);
}
/**
* Triggers iframe API mouseLeave event.
*
* @param {MouseEvent} event - The mouse event.
* @private
* @returns {void}
*/
_onMouseLeave(event) {
APP.API.notifyMouseLeave(event);
}
/**
* Triggers iframe API mouseMove event.
*
* @param {MouseEvent} event - The mouse event.
* @private
* @returns {void}
*/
_onMouseMove(event) {
APP.API.notifyMouseMove(event);
}
/**
* Displays the toolbar.
*
@ -305,12 +363,15 @@ class Conference extends AbstractConference<Props, *> {
* @returns {Props}
*/
function _mapStateToProps(state) {
const { backgroundAlpha, mouseMoveCallbackInterval } = state['features/base/config'];
return {
...abstractMapStateToProps(state),
_backgroundAlpha: state['features/base/config'].backgroundAlpha,
_backgroundAlpha: backgroundAlpha,
_isLobbyScreenVisible: state['features/base/dialog']?.component === LobbyScreen,
_isParticipantsPaneVisible: getParticipantsPaneOpen(state),
_layoutClassName: LAYOUT_CLASSNAMES[getCurrentLayout(state)],
_mouseMoveCallbackInterval: mouseMoveCallbackInterval,
_roomName: getConferenceNameForTitle(state),
_showPrejoin: isPrejoinPageVisible(state)
};