diff options
author | 2021-05-28 19:51:37 +0200 | |
---|---|---|
committer | 2021-05-28 19:51:37 +0200 | |
commit | 97408875613c39ea0acc33af41c5caf6a82e7ba1 (patch) | |
tree | 48e9411543fbde7fad0af62b402fadc32bbd4e92 /src/webview/recipe.js | |
parent | Read CSS assets in recipes as utf8 (#1459) (diff) | |
download | ferdium-app-97408875613c39ea0acc33af41c5caf6a82e7ba1.tar.gz ferdium-app-97408875613c39ea0acc33af41c5caf6a82e7ba1.tar.zst ferdium-app-97408875613c39ea0acc33af41c5caf6a82e7ba1.zip |
Screen share refactoring (#1460)
* Extract screenshare into a separate file
Extracted from 240c3a72363e7388779c9ed3c6467ec63bb64d94 according to
https://github.com/getferdi/ferdi/pull/1456#discussion_r641194876
* Cosmetic screenshare changes and cancellation
* Makes the screen/window selector more readable
* Adds a Cancel button to close the selector
Diffstat (limited to 'src/webview/recipe.js')
-rw-r--r-- | src/webview/recipe.js | 123 |
1 files changed, 2 insertions, 121 deletions
diff --git a/src/webview/recipe.js b/src/webview/recipe.js index 6180270b2..5a24effa2 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 */ |
2 | import { ipcRenderer, desktopCapturer } from 'electron'; | 2 | import { ipcRenderer } from 'electron'; |
3 | import { getCurrentWebContents } from '@electron/remote'; | 3 | import { getCurrentWebContents } from '@electron/remote'; |
4 | import path from 'path'; | 4 | import path from 'path'; |
5 | import { autorun, computed, observable } from 'mobx'; | 5 | import { autorun, computed, observable } from 'mobx'; |
@@ -27,75 +27,13 @@ import { switchDict, getSpellcheckerLocaleByFuzzyIdentifier } from './spellcheck | |||
27 | import { injectDarkModeStyle, isDarkModeStyleInjected, removeDarkModeStyle } from './darkmode'; | 27 | import { injectDarkModeStyle, isDarkModeStyleInjected, removeDarkModeStyle } from './darkmode'; |
28 | import contextMenu from './contextMenu'; | 28 | import contextMenu from './contextMenu'; |
29 | import './notifications'; | 29 | import './notifications'; |
30 | import { screenShareCss } from './screenshare'; | ||
30 | 31 | ||
31 | import { DEFAULT_APP_SETTINGS } from '../config'; | 32 | import { DEFAULT_APP_SETTINGS } from '../config'; |
32 | import { isDevMode } from '../environment'; | 33 | import { isDevMode } from '../environment'; |
33 | 34 | ||
34 | const debug = require('debug')('Ferdi:Plugin'); | 35 | const debug = require('debug')('Ferdi:Plugin'); |
35 | 36 | ||
36 | const screenShareCss = ` | ||
37 | .desktop-capturer-selection { | ||
38 | position: fixed; | ||
39 | top: 0; | ||
40 | left: 0; | ||
41 | width: 100%; | ||
42 | height: 100vh; | ||
43 | background: rgba(30,30,30,.75); | ||
44 | color: #fff; | ||
45 | z-index: 10000000; | ||
46 | display: flex; | ||
47 | align-items: center; | ||
48 | justify-content: center; | ||
49 | } | ||
50 | .desktop-capturer-selection__scroller { | ||
51 | width: 100%; | ||
52 | max-height: 100vh; | ||
53 | overflow-y: auto; | ||
54 | } | ||
55 | .desktop-capturer-selection__list { | ||
56 | max-width: calc(100% - 100px); | ||
57 | margin: 50px; | ||
58 | padding: 0; | ||
59 | display: flex; | ||
60 | flex-wrap: wrap; | ||
61 | list-style: none; | ||
62 | overflow: hidden; | ||
63 | justify-content: center; | ||
64 | } | ||
65 | .desktop-capturer-selection__item { | ||
66 | display: flex; | ||
67 | margin: 4px; | ||
68 | } | ||
69 | .desktop-capturer-selection__btn { | ||
70 | display: flex; | ||
71 | flex-direction: column; | ||
72 | align-items: stretch; | ||
73 | width: 145px; | ||
74 | margin: 0; | ||
75 | border: 0; | ||
76 | border-radius: 3px; | ||
77 | padding: 4px; | ||
78 | background: #252626; | ||
79 | text-align: left; | ||
80 | transition: background-color .15s, box-shadow .15s; | ||
81 | } | ||
82 | .desktop-capturer-selection__btn:hover, | ||
83 | .desktop-capturer-selection__btn:focus { | ||
84 | background: rgba(98,100,167,.8); | ||
85 | } | ||
86 | .desktop-capturer-selection__thumbnail { | ||
87 | width: 100%; | ||
88 | height: 81px; | ||
89 | object-fit: cover; | ||
90 | } | ||
91 | .desktop-capturer-selection__name { | ||
92 | margin: 6px 0 6px; | ||
93 | white-space: nowrap; | ||
94 | text-overflow: ellipsis; | ||
95 | overflow: hidden; | ||
96 | } | ||
97 | `; | ||
98 | |||
99 | class RecipeController { | 37 | class RecipeController { |
100 | @observable settings = { | 38 | @observable settings = { |
101 | overrideSpellcheckerLanguage: false, | 39 | overrideSpellcheckerLanguage: false, |
@@ -438,60 +376,3 @@ window.open = (url, frameName, features) => { | |||
438 | if (isDevMode) { | 376 | if (isDevMode) { |
439 | window.log = console.log; | 377 | window.log = console.log; |
440 | } | 378 | } |
441 | |||
442 | // Patch getDisplayMedia for screen sharing | ||
443 | window.navigator.mediaDevices.getDisplayMedia = () => new Promise(async (resolve, reject) => { | ||
444 | try { | ||
445 | const sources = await desktopCapturer.getSources({ types: ['screen', 'window'] }); | ||
446 | |||
447 | const selectionElem = document.createElement('div'); | ||
448 | selectionElem.classList = 'desktop-capturer-selection'; | ||
449 | selectionElem.innerHTML = ` | ||
450 | <div class="desktop-capturer-selection__scroller"> | ||
451 | <ul class="desktop-capturer-selection__list"> | ||
452 | ${sources.map(({ | ||
453 | id, name, thumbnail, | ||
454 | }) => ` | ||
455 | <li class="desktop-capturer-selection__item"> | ||
456 | <button class="desktop-capturer-selection__btn" data-id="${id}" title="${name}"> | ||
457 | <img class="desktop-capturer-selection__thumbnail" src="${thumbnail.toDataURL()}" /> | ||
458 | <span class="desktop-capturer-selection__name">${name}</span> | ||
459 | </button> | ||
460 | </li> | ||
461 | `).join('')} | ||
462 | </ul> | ||
463 | </div> | ||
464 | `; | ||
465 | document.body.appendChild(selectionElem); | ||
466 | |||
467 | document.querySelectorAll('.desktop-capturer-selection__btn') | ||
468 | .forEach((button) => { | ||
469 | button.addEventListener('click', async () => { | ||
470 | try { | ||
471 | const id = button.getAttribute('data-id'); | ||
472 | const mediaSource = sources.find(source => source.id === id); | ||
473 | if (!mediaSource) { | ||
474 | throw new Error(`Source with id ${id} does not exist`); | ||
475 | } | ||
476 | |||
477 | const stream = await window.navigator.mediaDevices.getUserMedia({ | ||
478 | audio: false, | ||
479 | video: { | ||
480 | mandatory: { | ||
481 | chromeMediaSource: 'desktop', | ||
482 | chromeMediaSourceId: mediaSource.id, | ||
483 | }, | ||
484 | }, | ||
485 | }); | ||
486 | resolve(stream); | ||
487 | |||
488 | selectionElem.remove(); | ||
489 | } catch (err) { | ||
490 | reject(err); | ||
491 | } | ||
492 | }); | ||
493 | }); | ||
494 | } catch (err) { | ||
495 | reject(err); | ||
496 | } | ||
497 | }); | ||