mirror of
https://github.com/finos/SymphonyElectron.git
synced 2025-02-25 18:55:29 -06:00
RTC-5104: screensharing indicator (#536)
* RTC-5104: screensharing indicator * RTC-5104: screensharing indicator, windows fixes
This commit is contained in:
parent
4832c28dd2
commit
9609bc7976
@ -83,9 +83,9 @@
|
||||
|
||||
<hr>
|
||||
<p>Get Media Sources:</p>
|
||||
<button id='get-sources'>Open screen picker</button>
|
||||
<button id='get-sources'>Open screen picker & screensharing indicator</button>
|
||||
<br>
|
||||
<video id='video'></video>
|
||||
<video id='video' autoPlay loop muted style='max-width: 640px'></video>
|
||||
|
||||
<hr>
|
||||
<p>Get Version Info:</p>
|
||||
@ -226,8 +226,8 @@
|
||||
var getSources = document.getElementById('get-sources');
|
||||
getSources.addEventListener('click', function() {
|
||||
ssf.getMediaSource({types: ['window', 'screen']}, function(error, source) {
|
||||
if (error) throw error
|
||||
navigator.webkitGetUserMedia({
|
||||
if (error) throw error;
|
||||
navigator.webkitGetUserMedia({
|
||||
audio: false,
|
||||
video: {
|
||||
mandatory: {
|
||||
@ -239,12 +239,24 @@
|
||||
maxHeight: 720
|
||||
}
|
||||
}
|
||||
}, handleStream, handleError)
|
||||
}, stream => {
|
||||
handleStream(stream, source.display_id);
|
||||
}, handleError)
|
||||
});
|
||||
});
|
||||
|
||||
function handleStream (stream) {
|
||||
document.querySelector('video').src = URL.createObjectURL(stream)
|
||||
function handleStream(stream, displayId) {
|
||||
document.getElementById('video').srcObject = stream;
|
||||
ssf.showScreenSharingIndicator({
|
||||
stream,
|
||||
displayId
|
||||
}, function(event) {
|
||||
console.log('screen-sharing-indicator callback', event);
|
||||
if (event.type === 'stopRequested') {
|
||||
stream.getVideoTracks().forEach(t => t.stop());
|
||||
document.getElementById('video').srcObject = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleError (e) {
|
||||
|
@ -25,6 +25,7 @@ const cmds = keyMirror({
|
||||
setIsInMeeting: null,
|
||||
setLocale: null,
|
||||
keyPress: null,
|
||||
openScreenSharingIndicator: null
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
|
@ -17,6 +17,7 @@ const { bringToFront } = require('./bringToFront.js');
|
||||
const eventEmitter = require('./eventEmitter');
|
||||
const { isMac } = require('./utils/misc');
|
||||
const { openScreenPickerWindow } = require('./desktopCapturer');
|
||||
const { openScreenSharingIndicator } = require('./screenSharingIndicator');
|
||||
const { setPreloadMemoryInfo, setIsInMeeting, setPreloadWindow } = require('./memoryMonitor');
|
||||
|
||||
const apiEnums = require('./enums/api.js');
|
||||
@ -179,6 +180,11 @@ electron.ipcMain.on(apiName, (event, arg) => {
|
||||
windowMgr.handleKeyPress(arg.keyCode);
|
||||
}
|
||||
break;
|
||||
case apiCmds.openScreenSharingIndicator:
|
||||
if (typeof arg.displayId === 'string' && typeof arg.id === 'number') {
|
||||
openScreenSharingIndicator(event.sender, arg.displayId, arg.id);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ const apiCmds = apiEnums.cmds;
|
||||
const apiName = apiEnums.apiName;
|
||||
const getMediaSources = require('../desktopCapturer/getSources');
|
||||
const getMediaSource = require('../desktopCapturer/getSource');
|
||||
const showScreenSharingIndicator = require('../screenSharingIndicator/showScreenSharingIndicator');
|
||||
const { TitleBar } = require('../windowsTitlebar');
|
||||
const titleBar = new TitleBar();
|
||||
const { buildNumber } = require('../../package.json');
|
||||
@ -317,6 +318,20 @@ function createAPI() {
|
||||
*/
|
||||
getMediaSource: getMediaSource,
|
||||
|
||||
/**
|
||||
* Shows a banner that informs user that the screen is being shared.
|
||||
*
|
||||
* @param params object with following fields:
|
||||
* - stream https://developer.mozilla.org/en-US/docs/Web/API/MediaStream/MediaStream object.
|
||||
* The indicator automatically destroys itself when stream becomes inactive (see MediaStream.active).
|
||||
* - displayId id of the display that is being shared or that contains the shared app
|
||||
* @param callback callback function that will be called to handle events.
|
||||
* Callback receives event object { type: string }. Types:
|
||||
* - 'error' - error occured. Event object contains 'reason' field.
|
||||
* - 'stopRequested' - user clicked "Stop Sharing" button.
|
||||
*/
|
||||
showScreenSharingIndicator: showScreenSharingIndicator,
|
||||
|
||||
/**
|
||||
* Opens a modal window to configure notification preference.
|
||||
*/
|
||||
|
104
js/screenSharingIndicator/index.js
Executable file
104
js/screenSharingIndicator/index.js
Executable file
@ -0,0 +1,104 @@
|
||||
'use strict';
|
||||
|
||||
const electron = require('electron');
|
||||
const ipcMain = electron.ipcMain;
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const log = require('../log.js');
|
||||
const logLevels = require('../enums/logLevels.js');
|
||||
const { initCrashReporterMain, initCrashReporterRenderer } = require('../crashReporter.js');
|
||||
const i18n = require('../translation/i18n');
|
||||
const { isMac } = require('./../utils/misc.js');
|
||||
|
||||
const baseWindowConfig = {
|
||||
width: 592,
|
||||
height: 48,
|
||||
show: false,
|
||||
modal: true,
|
||||
frame: false,
|
||||
focusable: false,
|
||||
transparent: true,
|
||||
autoHideMenuBar: true,
|
||||
resizable: false,
|
||||
minimizable: false,
|
||||
maximizable: false,
|
||||
closable: true,
|
||||
alwaysOnTop: true,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'renderer.js'),
|
||||
sandbox: true,
|
||||
nodeIntegration: false,
|
||||
devTools: false
|
||||
}
|
||||
};
|
||||
|
||||
function getTemplatePath() {
|
||||
let templatePath = path.join(__dirname, 'screen-sharing-indicator.html');
|
||||
try {
|
||||
fs.statSync(templatePath).isFile();
|
||||
} catch (err) {
|
||||
log.send(logLevels.ERROR, `screen-sharing-indicator: Could not find template ("${templatePath}").`);
|
||||
}
|
||||
return `file://${templatePath}`;
|
||||
}
|
||||
|
||||
function openScreenSharingIndicator(eventSender, displayId, id) {
|
||||
const indicatorScreen = (displayId && electron.screen.getAllDisplays().filter(d => displayId.includes(d.id))[0]) || electron.screen.getPrimaryDisplay();
|
||||
const screenRect = indicatorScreen.workArea;
|
||||
const windowConfig = Object.assign({}, baseWindowConfig, {
|
||||
x: screenRect.x + Math.round((screenRect.width - baseWindowConfig.width) / 2),
|
||||
y: screenRect.y + screenRect.height - baseWindowConfig.height
|
||||
});
|
||||
|
||||
const indicatorWindow = new electron.BrowserWindow(windowConfig);
|
||||
indicatorWindow.setVisibleOnAllWorkspaces(true);
|
||||
indicatorWindow.setMenu(null);
|
||||
indicatorWindow.loadURL(getTemplatePath());
|
||||
|
||||
indicatorWindow.once('ready-to-show', () => {
|
||||
indicatorWindow.show();
|
||||
});
|
||||
|
||||
indicatorWindow.webContents.on('did-finish-load', () => {
|
||||
initCrashReporterMain({ process: 'screen sharing indicator window' });
|
||||
initCrashReporterRenderer(indicatorWindow, { process: 'render | screen sharing indicator window' });
|
||||
indicatorWindow.webContents.send('window-data', {
|
||||
id,
|
||||
i18n: i18n.getMessageFor('ScreenSharingIndicator'),
|
||||
isMac
|
||||
});
|
||||
});
|
||||
|
||||
indicatorWindow.webContents.on('crashed', () => {
|
||||
const errorDialogOptions = {
|
||||
type: 'error',
|
||||
title: i18n.getMessageFor('Renderer Process Crashed'),
|
||||
message: i18n.getMessageFor('Oops! Looks like we have had a crash.'),
|
||||
buttons: ['Close']
|
||||
};
|
||||
electron.dialog.showMessageBox(errorDialogOptions, () => indicatorWindow.close());
|
||||
});
|
||||
|
||||
const handleStopSharingClicked = (event, indicatorId) => {
|
||||
if (indicatorId === id) {
|
||||
eventSender.send('stop-sharing-requested', id);
|
||||
}
|
||||
}
|
||||
|
||||
const handleDestroyScreensharingIndicator = (event, indicatorId) => {
|
||||
if (indicatorId === id) {
|
||||
if (!indicatorWindow.isDestroyed()) {
|
||||
indicatorWindow.close();
|
||||
}
|
||||
ipcMain.removeListener('stop-sharing-clicked', handleStopSharingClicked);
|
||||
ipcMain.removeListener('destroy-screensharing-indicator', handleDestroyScreensharingIndicator);
|
||||
}
|
||||
};
|
||||
|
||||
ipcMain.on('stop-sharing-clicked', handleStopSharingClicked);
|
||||
ipcMain.on('destroy-screensharing-indicator', handleDestroyScreensharingIndicator);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
openScreenSharingIndicator
|
||||
};
|
38
js/screenSharingIndicator/renderer.js
Normal file
38
js/screenSharingIndicator/renderer.js
Normal file
@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
const { ipcRenderer, crashReporter } = require('electron');
|
||||
|
||||
let indicatorId;
|
||||
|
||||
function renderDom() {
|
||||
const stopSharingButton = document.getElementById('stop-sharing-button');
|
||||
stopSharingButton.addEventListener('click', () => {
|
||||
ipcRenderer.send('stop-sharing-clicked', indicatorId);
|
||||
}, false);
|
||||
|
||||
const hideButton = document.getElementById('hide-button');
|
||||
hideButton.addEventListener('click', () => {
|
||||
window.close();
|
||||
}, false);
|
||||
}
|
||||
|
||||
ipcRenderer.on('window-data', (event, content) => {
|
||||
indicatorId = content.id;
|
||||
const setText = (el, text) => {
|
||||
document.getElementById(el).innerHTML = (content.i18n[text] || text).replace('Symphony', '<b>Symphony</b>');
|
||||
};
|
||||
setText('stop-sharing-button', 'Stop sharing');
|
||||
setText('hide-button', 'Hide');
|
||||
setText('text-label', 'You are sharing your screen on Symphony');
|
||||
document.body.className = content.isMac ? 'mac' : '';
|
||||
});
|
||||
|
||||
ipcRenderer.on('register-crash-reporter', (event, arg) => {
|
||||
if (arg && typeof arg === 'object') {
|
||||
crashReporter.start(arg);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
renderDom();
|
||||
});
|
104
js/screenSharingIndicator/screen-sharing-indicator.html
Executable file
104
js/screenSharingIndicator/screen-sharing-indicator.html
Executable file
@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title data-i18n-text="Screen Sharing"></title>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: system;
|
||||
font-style: normal;
|
||||
src: local(".SFNSText"), local(".HelveticaNeueDeskInterface"), local("Ubuntu Light"), local("Segoe UI"), local("Roboto"), local("Tahoma");
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "system";
|
||||
font-size: 13px;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
user-select: none;
|
||||
-webkit-app-region: drag;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
background: rgba(255, 255, 255, 0.94);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
body:not(.mac) .container {
|
||||
border: 1px solid rgb(212, 212, 212);
|
||||
}
|
||||
|
||||
.buttons {
|
||||
float: right;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#stop-sharing-button {
|
||||
text-transform: uppercase;
|
||||
background: #107ccc;
|
||||
color: white;
|
||||
border: none;
|
||||
font-size: inherit;
|
||||
border-radius: 14px;
|
||||
height: 28px;
|
||||
padding: 6px 14px;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
#hide-button {
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
color: #6b717c;
|
||||
margin-right: 29px;
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
#text-label {
|
||||
position: relative;
|
||||
top: -2px;
|
||||
left: 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#drag-area {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 22px;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
text-transform: uppercase;
|
||||
background: repeating-linear-gradient(
|
||||
0deg,
|
||||
rgba(0, 0, 0, 0),
|
||||
rgba(0, 0, 0, 0) 1px,
|
||||
rgba(0, 0, 0, 0.22) 1px,
|
||||
rgba(0, 0, 0, 0.22) 2px
|
||||
);
|
||||
}
|
||||
|
||||
.mac #hide-button {
|
||||
color: #303237;
|
||||
}
|
||||
|
||||
.mac #stop-sharing-button {
|
||||
padding: 6px 18px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<span id='drag-area'></span>
|
||||
<span id='text-label'>You are sharing your screen on <b>Symphony</b></span>
|
||||
<span class='buttons'>
|
||||
<a id='hide-button' href='#'>Hide</a>
|
||||
<button id='stop-sharing-button'>Stop sharing</button>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
46
js/screenSharingIndicator/showScreenSharingIndicator.js
Normal file
46
js/screenSharingIndicator/showScreenSharingIndicator.js
Normal file
@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
const { ipcRenderer } = require('electron');
|
||||
const apiEnums = require('../enums/api.js');
|
||||
const apiCmds = apiEnums.cmds;
|
||||
const apiName = apiEnums.apiName;
|
||||
|
||||
let nextIndicatorId = 0;
|
||||
|
||||
function showScreenSharingIndicator(options, callback) {
|
||||
const { stream, displayId } = options;
|
||||
|
||||
if (!stream || !stream.active || stream.getVideoTracks().length !== 1) {
|
||||
callback({type: 'error', reason: 'bad stream'});
|
||||
return;
|
||||
}
|
||||
if (displayId && typeof(displayId) !== 'string') {
|
||||
callback({type: 'error', reason: 'bad displayId'});
|
||||
return;
|
||||
}
|
||||
|
||||
const id = ++nextIndicatorId;
|
||||
ipcRenderer.send(apiName, {
|
||||
cmd: apiCmds.openScreenSharingIndicator,
|
||||
displayId: options.displayId,
|
||||
id
|
||||
});
|
||||
|
||||
const handleStopRequest = (e, indicatorId) => {
|
||||
if (indicatorId === id) {
|
||||
callback({type: 'stopRequested'});
|
||||
}
|
||||
}
|
||||
|
||||
const destroy = () => {
|
||||
ipcRenderer.send('destroy-screensharing-indicator', id);
|
||||
options.stream.removeEventListener('inactive', destroy);
|
||||
ipcRenderer.removeListener('stop-sharing-requested', handleStopRequest);
|
||||
};
|
||||
|
||||
ipcRenderer.on('stop-sharing-requested', handleStopRequest);
|
||||
options.stream.addEventListener('inactive', destroy);
|
||||
}
|
||||
|
||||
|
||||
module.exports = showScreenSharingIndicator;
|
@ -111,6 +111,11 @@
|
||||
"Select Screen": "Select Screen",
|
||||
"Share": "Share"
|
||||
},
|
||||
"ScreenSharingIndicator": {
|
||||
"You are sharing your screen on Symphony": "You are sharing your screen on Symphony",
|
||||
"Stop sharing": "Stop sharing",
|
||||
"Hide": "Hide"
|
||||
},
|
||||
"ScreenSnippet": {
|
||||
"Done": "Done",
|
||||
"Erase": "Erase",
|
||||
|
@ -109,6 +109,11 @@
|
||||
"Select Screen": "Select Screen",
|
||||
"Share": "Share"
|
||||
},
|
||||
"ScreenSharingIndicator": {
|
||||
"You are sharing your screen on Symphony": "You are sharing your screen on Symphony",
|
||||
"Stop sharing": "Stop sharing",
|
||||
"Hide": "Hide"
|
||||
},
|
||||
"ScreenSnippet": {
|
||||
"Done": "Done",
|
||||
"Erase": "Erase",
|
||||
|
@ -109,6 +109,11 @@
|
||||
"Select Screen":"Sélectionnez l'écran",
|
||||
"Share":"Partager"
|
||||
},
|
||||
"ScreenSharingIndicator": {
|
||||
"You are sharing your screen on Symphony": "Vous partagez votre écran sur Symphony",
|
||||
"Stop sharing": "Arrêter le partage",
|
||||
"Hide": "Masquer"
|
||||
},
|
||||
"ScreenSnippet":{
|
||||
"Done":"Terminé",
|
||||
"Erase":"Effacer",
|
||||
|
@ -109,6 +109,11 @@
|
||||
"Select Screen":"Sélectionnez l'écran",
|
||||
"Share":"Partager"
|
||||
},
|
||||
"ScreenSharingIndicator": {
|
||||
"You are sharing your screen on Symphony": "Vous partagez votre écran sur Symphony",
|
||||
"Stop sharing": "Arrêter le partage",
|
||||
"Hide": "Masquer"
|
||||
},
|
||||
"ScreenSnippet":{
|
||||
"Done":"Terminé",
|
||||
"Erase":"Effacer",
|
||||
|
@ -111,6 +111,11 @@
|
||||
"Select Screen": "画面を選択",
|
||||
"Share": "共有"
|
||||
},
|
||||
"ScreenSharingIndicator": {
|
||||
"You are sharing your screen on Symphony": "あなたはSymphony上であなたの画面を共有しています",
|
||||
"Stop Sharing": "共有を停止",
|
||||
"Hide": "非表示にする"
|
||||
},
|
||||
"ScreenSnippet": {
|
||||
"Done": "完了",
|
||||
"Erase": "消去",
|
||||
|
@ -109,6 +109,11 @@
|
||||
"Select Screen": "画面を選択",
|
||||
"Share": "共有"
|
||||
},
|
||||
"ScreenSharingIndicator": {
|
||||
"You are sharing your screen on Symphony": "あなたはSymphony上であなたの画面を共有しています",
|
||||
"Stop Sharing": "共有を停止",
|
||||
"Hide": "非表示にする"
|
||||
},
|
||||
"ScreenSnippet": {
|
||||
"Done": "完了",
|
||||
"Erase": "消去",
|
||||
|
Loading…
Reference in New Issue
Block a user