aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Gautam Singh <5769869+gautamsi@users.noreply.github.com>2020-09-23 04:14:20 +0530
committerLibravatar GitHub <noreply@github.com>2020-09-22 23:44:20 +0100
commit62df97a366923de638c0f45def3f76caa302a0c9 (patch)
treed38b73d7143df11be897069533605cba0cb0687a /src
parentUpdate adaptable dark mode to work on all platforms (#834) (diff)
downloadferdium-app-62df97a366923de638c0f45def3f76caa302a0c9.tar.gz
ferdium-app-62df97a366923de638c0f45def3f76caa302a0c9.tar.zst
ferdium-app-62df97a366923de638c0f45def3f76caa302a0c9.zip
Patch getDisplayMedia for screen sharing in all services (#802)
Co-authored-by: Gautam Singh <gautamsi@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r--src/webview/recipe.js131
1 files changed, 126 insertions, 5 deletions
diff --git a/src/webview/recipe.js b/src/webview/recipe.js
index c6724e35a..675f8e311 100644
--- a/src/webview/recipe.js
+++ b/src/webview/recipe.js
@@ -1,5 +1,5 @@
1/* eslint-disable import/first */ 1/* eslint-disable import/first */
2import { ipcRenderer, remote } from 'electron'; 2import { ipcRenderer, remote, desktopCapturer } from 'electron';
3import path from 'path'; 3import path from 'path';
4import { autorun, computed, observable } from 'mobx'; 4import { autorun, computed, observable } from 'mobx';
5import fs from 'fs-extra'; 5import fs from 'fs-extra';
@@ -32,6 +32,69 @@ import { isDevMode } from '../environment';
32 32
33const debug = require('debug')('Ferdi:Plugin'); 33const debug = require('debug')('Ferdi:Plugin');
34 34
35const screenShareCss = `
36.desktop-capturer-selection {
37 position: fixed;
38 top: 0;
39 left: 0;
40 width: 100%;
41 height: 100vh;
42 background: rgba(30,30,30,.75);
43 color: #fff;
44 z-index: 10000000;
45 display: flex;
46 align-items: center;
47 justify-content: center;
48}
49.desktop-capturer-selection__scroller {
50 width: 100%;
51 max-height: 100vh;
52 overflow-y: auto;
53}
54.desktop-capturer-selection__list {
55 max-width: calc(100% - 100px);
56 margin: 50px;
57 padding: 0;
58 display: flex;
59 flex-wrap: wrap;
60 list-style: none;
61 overflow: hidden;
62 justify-content: center;
63}
64.desktop-capturer-selection__item {
65 display: flex;
66 margin: 4px;
67}
68.desktop-capturer-selection__btn {
69 display: flex;
70 flex-direction: column;
71 align-items: stretch;
72 width: 145px;
73 margin: 0;
74 border: 0;
75 border-radius: 3px;
76 padding: 4px;
77 background: #252626;
78 text-align: left;
79 transition: background-color .15s, box-shadow .15s;
80}
81.desktop-capturer-selection__btn:hover,
82.desktop-capturer-selection__btn:focus {
83 background: rgba(98,100,167,.8);
84}
85.desktop-capturer-selection__thumbnail {
86 width: 100%;
87 height: 81px;
88 object-fit: cover;
89}
90.desktop-capturer-selection__name {
91 margin: 6px 0 6px;
92 white-space: nowrap;
93 text-overflow: ellipsis;
94 overflow: hidden;
95}
96`;
97
35class RecipeController { 98class RecipeController {
36 @observable settings = { 99 @observable settings = {
37 overrideSpellcheckerLanguage: false, 100 overrideSpellcheckerLanguage: false,
@@ -128,14 +191,15 @@ class RecipeController {
128 } 191 }
129 192
130 async loadUserFiles(recipe, config) { 193 async loadUserFiles(recipe, config) {
194 const styles = document.createElement('style');
195 styles.innerHTML = screenShareCss;
196
131 const userCss = path.join(recipe.path, 'user.css'); 197 const userCss = path.join(recipe.path, 'user.css');
132 if (await fs.exists(userCss)) { 198 if (await fs.exists(userCss)) {
133 const data = await fs.readFile(userCss); 199 const data = await fs.readFile(userCss);
134 const styles = document.createElement('style'); 200 styles.innerHTML += data.toString();
135 styles.innerHTML = data.toString();
136
137 document.querySelector('head').appendChild(styles);
138 } 201 }
202 document.querySelector('head').appendChild(styles);
139 203
140 const userJs = path.join(recipe.path, 'user.js'); 204 const userJs = path.join(recipe.path, 'user.js');
141 if (await fs.exists(userJs)) { 205 if (await fs.exists(userJs)) {
@@ -386,3 +450,60 @@ window.open = (url, frameName, features) => {
386if (isDevMode) { 450if (isDevMode) {
387 window.log = console.log; 451 window.log = console.log;
388} 452}
453
454// Patch getDisplayMedia for screen sharing
455window.navigator.mediaDevices.getDisplayMedia = () => new Promise(async (resolve, reject) => {
456 try {
457 const sources = await desktopCapturer.getSources({ types: ['screen', 'window'] });
458
459 const selectionElem = document.createElement('div');
460 selectionElem.classList = 'desktop-capturer-selection';
461 selectionElem.innerHTML = `
462 <div class="desktop-capturer-selection__scroller">
463 <ul class="desktop-capturer-selection__list">
464 ${sources.map(({
465 id, name, thumbnail,
466 }) => `
467 <li class="desktop-capturer-selection__item">
468 <button class="desktop-capturer-selection__btn" data-id="${id}" title="${name}">
469 <img class="desktop-capturer-selection__thumbnail" src="${thumbnail.toDataURL()}" />
470 <span class="desktop-capturer-selection__name">${name}</span>
471 </button>
472 </li>
473 `).join('')}
474 </ul>
475 </div>
476 `;
477 document.body.appendChild(selectionElem);
478
479 document.querySelectorAll('.desktop-capturer-selection__btn')
480 .forEach((button) => {
481 button.addEventListener('click', async () => {
482 try {
483 const id = button.getAttribute('data-id');
484 const mediaSource = sources.find(source => source.id === id);
485 if (!mediaSource) {
486 throw new Error(`Source with id ${id} does not exist`);
487 }
488
489 const stream = await window.navigator.mediaDevices.getUserMedia({
490 audio: false,
491 video: {
492 mandatory: {
493 chromeMediaSource: 'desktop',
494 chromeMediaSourceId: mediaSource.id,
495 },
496 },
497 });
498 resolve(stream);
499
500 selectionElem.remove();
501 } catch (err) {
502 reject(err);
503 }
504 });
505 });
506 } catch (err) {
507 reject(err);
508 }
509});