mirror of
https://github.com/netzbegruenung/jitsi-meet-electron.git
synced 2024-05-03 17:23:41 +02:00
feat(remotecontrol): Implement requesting remote control permissions
This commit is contained in:
parent
c07fe8fa1e
commit
59b79cffe5
|
@ -1,5 +1,5 @@
|
||||||
# Electron's version.
|
# Electron's version.
|
||||||
export npm_config_target=1.4.7
|
export npm_config_target=1.4.13
|
||||||
# The architecture of Electron, can be ia32 or x64.
|
# The architecture of Electron, can be ia32 or x64.
|
||||||
export npm_config_arch=x64
|
export npm_config_arch=x64
|
||||||
export npm_config_target_arch=x64
|
export npm_config_target_arch=x64
|
||||||
|
|
1
main.js
1
main.js
|
@ -1,3 +1,4 @@
|
||||||
|
/* global __dirname, process */
|
||||||
//Electron includes
|
//Electron includes
|
||||||
const electron = require("electron");
|
const electron = require("electron");
|
||||||
const APP = electron.app;
|
const APP = electron.app;
|
||||||
|
|
31
modules/remotecontrol/constants.js
Normal file
31
modules/remotecontrol/constants.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
module.exports = {
|
||||||
|
/**
|
||||||
|
* Types of remote-control-event events.
|
||||||
|
*/
|
||||||
|
EVENT_TYPES: {
|
||||||
|
mousemove: "mousemove",
|
||||||
|
mousedown: "mousedown",
|
||||||
|
mouseup: "mouseup",
|
||||||
|
mousedblclick: "mousedblclick",
|
||||||
|
mousescroll: "mousescroll",
|
||||||
|
keydown: "keydown",
|
||||||
|
keyup: "keyup",
|
||||||
|
permissions: "permissions",
|
||||||
|
stop: "stop",
|
||||||
|
supported: "supported"
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actions for the remote control permission events.
|
||||||
|
*/
|
||||||
|
PERMISSIONS_ACTIONS: {
|
||||||
|
request: "request",
|
||||||
|
grant: "grant",
|
||||||
|
deny: "deny"
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of remote control events sent trough the API module.
|
||||||
|
*/
|
||||||
|
REMOTE_CONTROL_EVENT_TYPE: "remote-control-event"
|
||||||
|
};
|
|
@ -1,4 +1,6 @@
|
||||||
let robot = require("robotjs");
|
let robot = require("robotjs");
|
||||||
|
const constants = require("../../modules/remotecontrol/constants");
|
||||||
|
const {EVENT_TYPES, PERMISSIONS_ACTIONS, REMOTE_CONTROL_EVENT_TYPE} = constants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaching to the window for debug purposes.
|
* Attaching to the window for debug purposes.
|
||||||
|
@ -59,6 +61,45 @@ class RemoteControl {
|
||||||
this.started = false;
|
this.started = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the remote control functionality.
|
||||||
|
*/
|
||||||
|
init(channel, windowManager) {
|
||||||
|
this.windowManager = windowManager;
|
||||||
|
this.channel = channel;
|
||||||
|
this.start();
|
||||||
|
this.channel.ready(() => {
|
||||||
|
this.channel.listen(REMOTE_CONTROL_EVENT_TYPE,
|
||||||
|
event => this.onRemoteControlEvent(event));
|
||||||
|
this.sendEvent({type: EVENT_TYPES.supported});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles permission requests from Jitsi Meet.
|
||||||
|
* @param {object} userInfo - information about the user that has requested
|
||||||
|
* permissions:
|
||||||
|
* @param {string} userInfo.displayName - display name
|
||||||
|
* @param {string} userInfo.userJID - the JID of the user.
|
||||||
|
* @param {string} userInfo.userId - the user id (the resource of the JID)
|
||||||
|
*/
|
||||||
|
handlePermissionRequest(userInfo) {
|
||||||
|
this.windowManager.requestRemoteControlPermissions(userInfo)
|
||||||
|
.then(result => {
|
||||||
|
this.sendEvent({
|
||||||
|
type: EVENT_TYPES.permissions,
|
||||||
|
action: result ? PERMISSIONS_ACTIONS.grant
|
||||||
|
: PERMISSIONS_ACTIONS.deny,
|
||||||
|
userId: userInfo.userId
|
||||||
|
});
|
||||||
|
if(result) {
|
||||||
|
this.start();
|
||||||
|
}
|
||||||
|
}).catch(e => {
|
||||||
|
console.error(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts processing the events.
|
* Starts processing the events.
|
||||||
*/
|
*/
|
||||||
|
@ -77,12 +118,13 @@ class RemoteControl {
|
||||||
* Executes the passed event.
|
* Executes the passed event.
|
||||||
* @param {Object} event the remote-control-event.
|
* @param {Object} event the remote-control-event.
|
||||||
*/
|
*/
|
||||||
executeRemoteControlEvent(event) {
|
onRemoteControlEvent(event) {
|
||||||
if(!this.started) {
|
|
||||||
|
if(!this.started && event.type !== EVENT_TYPES.permissions) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch(event.type) {
|
switch(event.type) {
|
||||||
case "mousemove":
|
case EVENT_TYPES.mousemove: {
|
||||||
const x = event.x * width, y = event.y * height;
|
const x = event.x * width, y = event.y * height;
|
||||||
if(mouseButtonStatus === "down") {
|
if(mouseButtonStatus === "down") {
|
||||||
robot.dragMouse(x, y);
|
robot.dragMouse(x, y);
|
||||||
|
@ -90,20 +132,23 @@ class RemoteControl {
|
||||||
robot.moveMouse(x, y);
|
robot.moveMouse(x, y);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "mousedown":
|
}
|
||||||
case "mouseup":
|
case EVENT_TYPES.mousedown:
|
||||||
|
case EVENT_TYPES.mouseup: {
|
||||||
mouseButtonStatus = MOUSE_ACTIONS_FROM_EVENT_TYPE[event.type];
|
mouseButtonStatus = MOUSE_ACTIONS_FROM_EVENT_TYPE[event.type];
|
||||||
robot.mouseToggle(
|
robot.mouseToggle(
|
||||||
mouseButtonStatus,
|
mouseButtonStatus,
|
||||||
(event.button ? MOUSE_BUTTONS[event.button] : undefined));
|
(event.button ? MOUSE_BUTTONS[event.button] : undefined));
|
||||||
break;
|
break;
|
||||||
case "mousedblclick":
|
}
|
||||||
|
case EVENT_TYPES.mousedblclick: {
|
||||||
robot.mouseClick(
|
robot.mouseClick(
|
||||||
(event.button ? MOUSE_BUTTONS[event.button] : undefined),
|
(event.button ? MOUSE_BUTTONS[event.button] : undefined),
|
||||||
true);
|
true);
|
||||||
break;
|
break;
|
||||||
case "mousescroll":
|
}
|
||||||
//FIXME: implement horizontal scrolling
|
case EVENT_TYPES.mousescroll:{
|
||||||
|
//FIXME: implement horizontal scrolling
|
||||||
if(event.y !== 0) {
|
if(event.y !== 0) {
|
||||||
robot.scrollMouse(
|
robot.scrollMouse(
|
||||||
Math.abs(event.y),
|
Math.abs(event.y),
|
||||||
|
@ -111,15 +156,40 @@ class RemoteControl {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "keydown":
|
}
|
||||||
case "keyup":
|
case EVENT_TYPES.keydown:
|
||||||
|
case EVENT_TYPES.keyup: {
|
||||||
robot.keyToggle(event.key,
|
robot.keyToggle(event.key,
|
||||||
KEY_ACTIONS_FROM_EVENT_TYPE[event.type], event.modifiers);
|
KEY_ACTIONS_FROM_EVENT_TYPE[event.type], event.modifiers);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
case EVENT_TYPES.permissions: {
|
||||||
|
if(event.action !== PERMISSIONS_ACTIONS.request)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//Open Dialog and answer
|
||||||
|
this.handlePermissionRequest({
|
||||||
|
userId: event.userId,
|
||||||
|
userJID: event.userJID,
|
||||||
|
displayName: event.displayName});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case EVENT_TYPES.stop: {
|
||||||
|
this.stop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
console.error("Unknown event type!");
|
console.error("Unknown event type!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends remote control event to the controlled participant.
|
||||||
|
* @param {Object} event the remote control event.
|
||||||
|
*/
|
||||||
|
sendEvent(event) {
|
||||||
|
this.channel.send({method: REMOTE_CONTROL_EVENT_TYPE, params: event});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = new RemoteControl();
|
module.exports = new RemoteControl();
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
"postis": "^2.2.0"
|
"postis": "^2.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"electron": "1.4.7",
|
"electron": "1.4.13",
|
||||||
"eslint": ">=3",
|
"eslint": ">=3",
|
||||||
"eslint-plugin-jsdoc": "*",
|
"eslint-plugin-jsdoc": "*",
|
||||||
"precommit-hook": "3.0.0"
|
"precommit-hook": "3.0.0"
|
||||||
|
|
|
@ -2,6 +2,7 @@ const remoteControl = require("../../modules/remotecontrol");
|
||||||
let postis = require("postis");
|
let postis = require("postis");
|
||||||
const setupScreenSharingForWindow = require("../../modules/screensharing");
|
const setupScreenSharingForWindow = require("../../modules/screensharing");
|
||||||
const config = require("../../config.js");
|
const config = require("../../config.js");
|
||||||
|
const {dialog} = require('electron').remote;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The postis channel.
|
* The postis channel.
|
||||||
|
@ -18,16 +19,51 @@ iframe.onload = onload;
|
||||||
document.body.appendChild(iframe);
|
document.body.appendChild(iframe);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the remote control functionality.
|
* Factory for dialogs.
|
||||||
*/
|
*/
|
||||||
function initRemoteControl() {
|
class DialogFactory {
|
||||||
remoteControl.start();
|
/**
|
||||||
channel.ready(() =>
|
* Creates new instance
|
||||||
channel.listen('remote-control-event',
|
* @constructor
|
||||||
event => remoteControl.executeRemoteControlEvent(event))
|
*/
|
||||||
);
|
constructor() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows message box dialog for request for remote control permissions
|
||||||
|
* @param {object} userInfo - information about the user that has sent the
|
||||||
|
* request:
|
||||||
|
* @param {string} userInfo.displayName - display name
|
||||||
|
* @param {string} userInfo.userJID - the JID of the user.
|
||||||
|
*/
|
||||||
|
requestRemoteControlPermissions(userInfo) {
|
||||||
|
return new Promise( resolve =>
|
||||||
|
dialog.showMessageBox({
|
||||||
|
type: "question",
|
||||||
|
buttons: ["Yes", "No"],
|
||||||
|
defaultId: 0,
|
||||||
|
title: "Request for permission for remote control",
|
||||||
|
message: "Would you like to allow " + userInfo.displayName
|
||||||
|
+ " to remotely control your desktop.",
|
||||||
|
detail: "userId: " + userInfo.userJID,
|
||||||
|
cancelId: 1
|
||||||
|
}, response => resolve(response === 0? true : false))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog factory instance.
|
||||||
|
*/
|
||||||
|
const dialogFactory = new DialogFactory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boolean variable that indicates whether the onloaded function was already
|
||||||
|
* called.
|
||||||
|
* NOTE: Used to not call the onload method more than once during reloads of
|
||||||
|
* the iframe or location changes.
|
||||||
|
*/
|
||||||
|
let loaded = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles loaded event for iframe:
|
* Handles loaded event for iframe:
|
||||||
* Enables screen sharing functionality to the iframe webpage.
|
* Enables screen sharing functionality to the iframe webpage.
|
||||||
|
@ -35,10 +71,14 @@ function initRemoteControl() {
|
||||||
* Initializes remote control.
|
* Initializes remote control.
|
||||||
*/
|
*/
|
||||||
function onload() {
|
function onload() {
|
||||||
|
if(loaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loaded = true;
|
||||||
setupScreenSharingForWindow(iframe.contentWindow);
|
setupScreenSharingForWindow(iframe.contentWindow);
|
||||||
channel = postis({
|
channel = postis({
|
||||||
window: iframe.contentWindow,
|
window: iframe.contentWindow,
|
||||||
windowForEventListening: window
|
windowForEventListening: window
|
||||||
});
|
});
|
||||||
initRemoteControl();
|
remoteControl.init(channel, dialogFactory);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue