Browse Source

Merge pull request #1 from rodriguescelio/fix/screen-share

Fixed the screenshare capability
pull/3163/head
Bluscream 4 years ago committed by GitHub
parent
commit
87d48a6a00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 45
      electron/main.js
  2. 146
      resources/css/screenselector.css
  3. 48
      resources/js/rambox-service-api.js
  4. 77
      resources/js/screenselector.js
  5. 22
      screenselector.html

45
electron/main.js

@ -576,6 +576,51 @@ ipcMain.on('toggleWin', function(event, allwaysShow) {
}
});
// ScreenShare
ipcMain.on('screenShare:show', (event, screenList) => {
let tmpWindow = new BrowserWindow({
width: 600,
height: 500,
icon: __dirname + '/../resources/Icon.ico',
autoHideMenuBar: true,
transparent: true,
show: true,
frame: false,
hasShadow: true,
webPreferences: {
nodeIntegration: true,
},
});
const close = () => {
tmpWindow.close();
tmpWindow = null;
};
const onCancel = () => {
event.sender.send('screenShare:cancel');
close();
};
const onShare = (_, shareId) => {
event.sender.send('screenShare:share', shareId);
close();
};
ipcMain.handle('screenShare:getSources', () => screenList);
ipcMain.on('screenShare:cancelSelection', onCancel);
ipcMain.on('screenShare:selectScreen', onShare);
tmpWindow.on('closed', () => {
ipcMain.removeHandler('screenShare:getSources');
ipcMain.removeAllListeners('screenShare:cancelSelection');
ipcMain.removeAllListeners('screenShare:selectScreen');
});
tmpWindow.loadFile(__dirname + '/../screenselector.html');
});
// Proxy
if ( config.get('proxy') ) {
app.commandLine.appendSwitch('proxy-server', config.get('proxyHost')+':'+config.get('proxyPort'));

146
resources/css/screenselector.css

@ -0,0 +1,146 @@
html, body {
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
.screen-selector {
background-color: #fff;
width: 100%;
height: 100%;
border-radius: 5px;
border: solid 1px #cdcdcd;
box-sizing: border-box;
}
.screen-selector ul.type {
display: inline-block;
padding: 0;
margin: 0;
border-bottom: solid 1px #cdcdcd;
width: 100%;
-webkit-app-region: drag;
}
.screen-selector ul.type li {
display: inline-block;
height: 40px;
line-height: 40px;
color: #65696c;
border-bottom: 2px solid transparent;
font-family: sans-serif;
font-weight: bold;
padding: 0 15px;
cursor: pointer;
-webkit-app-region: no-drag;
}
.screen-selector ul.type li.active, .screen-selector ul.type li:hover {
color: #426ba3;
border-color: #426ba3;
}
.screen-selector > .content {
height: calc(100% - 92px);
}
.screen-selector ul.preview {
display: flex;
margin: 0;
padding: 0;
width: 100%;
max-height: calc(100% - 45px);
box-sizing: border-box;
padding: 10px;
overflow-y: auto;
flex-wrap: wrap;
list-style-type: none;
}
.screen-selector ul.preview li {
display: inline-block;
box-sizing: border-box;
width: calc(33% - 1px);
cursor: pointer;
padding: 5px;
}
.screen-selector ul.preview li .content {
display: flex;
box-sizing: border-box;
padding: 10px;
border: solid 2px transparent;
border-radius: 5px;
height: 100%;
flex-direction: column;
}
.screen-selector ul.preview li.active .content,
.screen-selector ul.preview li:hover .content {
border-color: #88abdb;
}
.screen-selector ul.preview li.active .content {
color: #000;
height: 100%;
}
.screen-selector ul.preview li .content .img-wrapper {
display: flex;
height: 100%;
align-items: center;
background: #f0f0f0;
}
.screen-selector ul.preview li .content img {
display: inline-block;
width: 100%;
}
.screen-selector ul.preview li .content span {
display: inline-block;
width: 100%;
font-family: sans-serif;
text-align: center;
font-size: 14px;
margin-top: 10px;
color: #333;
box-sizing: border-box;
}
.screen-selector .footer {
display: inline-block;
width: 100%;
border-top: solid 1px #cdcdcd;
}
.screen-selector .footer button {
float: right;
margin-top: 10px;
margin-right: 10px;
border: none;
border-radius: 5px;
padding: 5px 10px;
font-size: 14px;
cursor: pointer;
font-weight: bold;
}
.screen-selector .footer button#cancel {
border: solid 1px #cdcdcd;
background: #fff;
color: #1c73e4;
}
.screen-selector .footer button#share {
border: solid 1px #186ddd;
background: #1c73e4;
color: #fff;
}
.screen-selector .footer button#share[disabled] {
background: #666;
cursor: default;
}

48
resources/js/rambox-service-api.js

@ -2,7 +2,7 @@
* This file is loaded in the service web views to provide a Rambox API.
*/
const { ipcRenderer } = require('electron');
const { desktopCapturer, ipcRenderer } = require('electron');
const { ContextMenuBuilder, ContextMenuListener } = require('electron-contextmenu-wrapper');
/**
@ -61,3 +61,49 @@ mousetrap.bind(process.platform === 'darwin' ? ['command+left', 'command+right']
if (location.href.indexOf('slack.com') !== -1) return;
e.key === 'ArrowLeft' ? history.back() : history.forward();
});
// ScreenShare
window.navigator.mediaDevices.getDisplayMedia = () =>
new Promise(async (resolve, reject) => {
try {
const sources = await desktopCapturer.getSources({
types: ['screen', 'window'],
});
const unlisten = () => {
ipcRenderer.removeAllListeners('screenShare:cancel');
ipcRenderer.removeAllListeners('screenShare:share');
};
ipcRenderer.on('screenShare:cancel', () => {
unlisten();
reject(new Error('Cancelled by user'));
});
ipcRenderer.on('screenShare:share', (_, shareId) => {
unlisten();
window.navigator.mediaDevices
.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: shareId,
},
},
})
.then(stream => resolve(stream));
});
const mappedSources = sources.map(it => ({
id: it.id,
name: it.name,
thumbnail: it.thumbnail.toDataURL(),
}));
ipcRenderer.send('screenShare:show', mappedSources);
} catch (err) {
reject(err);
}
});

77
resources/js/screenselector.js

@ -0,0 +1,77 @@
const { ipcRenderer } = require('electron');
let sourceList, contentList, typeButtons, shareButton, cancelButton, activeItem, activeTab = 'screen';
const getItemDOM = item => {
const li = document.createElement('li');
li.setAttribute('data-id', item.id);
li.innerHTML = `<div class="content"><div class="img-wrapper"><img src="${item.thumbnail}" /></div><span>${item.name}</span></div>`;
li.addEventListener('click', onItemClick, false);
return li;
};
const updateTab = () => {
const sources = sourceList.filter(it => it.id.indexOf(activeTab) === 0);
contentList.innerHTML = '';
sources.forEach(source => contentList.appendChild(getItemDOM(source)));
};
const bindTypeClick = () => {
typeButtons.forEach(it => it.addEventListener('click', onChangeType, false));
};
const bindActionsClick = () => {
shareButton.addEventListener('click', onShareClick, false);
cancelButton.addEventListener('click', onCancelClick, false);
};
const onChangeType = event => {
event.preventDefault();
if (!event.target.classList.contains('active')) {
activeTab = event.target.dataset.type;
typeButtons.forEach(it => it.classList.remove('active'));
event.target.classList.add('active');
updateTab();
}
};
const onItemClick = event => {
event.preventDefault();
if (!event.currentTarget.classList.contains('active')) {
activeItem = event.currentTarget.dataset.id;
document.querySelectorAll('.preview li').forEach(it => it.classList.remove('active'));
event.currentTarget.classList.add('active');
changeShareState();
}
};
const onCancelClick = event => {
event.preventDefault();
ipcRenderer.send('screenShare:cancelSelection');
};
const onShareClick = event => {
event.preventDefault();
if (activeItem) {
ipcRenderer.send('screenShare:selectScreen', activeItem);
}
};
const changeShareState = () => {
if (shareButton.getAttribute('disabled') !== null) {
shareButton.removeAttribute('disabled');
}
};
window.addEventListener('load', async () => {
sourceList = await ipcRenderer.invoke('screenShare:getSources');
contentList = document.querySelector('.preview');
typeButtons = document.querySelectorAll('.type li');
shareButton = document.querySelector('#share');
cancelButton = document.querySelector('#cancel');
bindTypeClick();
bindActionsClick();
updateTab();
}, false);

22
screenselector.html

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="resources/css/screenselector.css" />
</head>
<body>
<div class="screen-selector">
<ul class="type">
<li class="active" data-type="screen">Entire Screen</li>
<li data-type="window">Window</li>
</ul>
<div class="content">
<ul class="preview"></ul>
</div>
<div class="footer">
<button id="share" disabled>Share</button>
<button id="cancel">Cancel</button>
</div>
</div>
<script src="resources/js/screenselector.js"></script>
</body>
</html>
Loading…
Cancel
Save