diff options
Diffstat (limited to 'src/webview/screenshare.js')
-rw-r--r-- | src/webview/screenshare.js | 91 |
1 files changed, 44 insertions, 47 deletions
diff --git a/src/webview/screenshare.js b/src/webview/screenshare.js index 84d2e1e95..e7e43c04e 100644 --- a/src/webview/screenshare.js +++ b/src/webview/screenshare.js | |||
@@ -2,6 +2,33 @@ import { desktopCapturer } from 'electron'; | |||
2 | 2 | ||
3 | const CANCEL_ID = 'desktop-capturer-selection__cancel'; | 3 | const CANCEL_ID = 'desktop-capturer-selection__cancel'; |
4 | 4 | ||
5 | export async function getDisplayMediaSelector() { | ||
6 | const sources = await desktopCapturer.getSources({ | ||
7 | types: ['screen', 'window'], | ||
8 | }); | ||
9 | return `<div class="desktop-capturer-selection__scroller"> | ||
10 | <ul class="desktop-capturer-selection__list"> | ||
11 | ${sources | ||
12 | .map( | ||
13 | ({ id, name, thumbnail }) => ` | ||
14 | <li class="desktop-capturer-selection__item"> | ||
15 | <button class="desktop-capturer-selection__btn" data-id="${id}" title="${name}"> | ||
16 | <img class="desktop-capturer-selection__thumbnail" src="${thumbnail.toDataURL()}" /> | ||
17 | <span class="desktop-capturer-selection__name">${name}</span> | ||
18 | </button> | ||
19 | </li> | ||
20 | `, | ||
21 | ) | ||
22 | .join('')} | ||
23 | <li class="desktop-capturer-selection__item"> | ||
24 | <button class="desktop-capturer-selection__btn" data-id="${CANCEL_ID}" title="Cancel"> | ||
25 | <span class="desktop-capturer-selection__name desktop-capturer-selection__name--cancel">Cancel</span> | ||
26 | </button> | ||
27 | </li> | ||
28 | </ul> | ||
29 | </div>`; | ||
30 | } | ||
31 | |||
5 | export const screenShareCss = ` | 32 | export const screenShareCss = ` |
6 | .desktop-capturer-selection { | 33 | .desktop-capturer-selection { |
7 | position: fixed; | 34 | position: fixed; |
@@ -46,7 +73,9 @@ export const screenShareCss = ` | |||
46 | padding: 4px; | 73 | padding: 4px; |
47 | background: #252626; | 74 | background: #252626; |
48 | text-align: left; | 75 | text-align: left; |
49 | transition: background-color .15s, box-shadow .15s, color .15s; | 76 | @media (prefers-reduced-motion: no-preference) { |
77 | transition: background-color .15s, box-shadow .15s, color .15s; | ||
78 | } | ||
50 | color: #dedede; | 79 | color: #dedede; |
51 | } | 80 | } |
52 | .desktop-capturer-selection__btn:hover, | 81 | .desktop-capturer-selection__btn:hover, |
@@ -72,38 +101,12 @@ export const screenShareCss = ` | |||
72 | } | 101 | } |
73 | `; | 102 | `; |
74 | 103 | ||
75 | // Patch getDisplayMedia for screen sharing | 104 | export const screenShareJs = ` |
76 | window.navigator.mediaDevices.getDisplayMedia = () => async (resolve, reject) => { | 105 | window.navigator.mediaDevices.getDisplayMedia = () => new Promise(async (resolve, reject) => { |
77 | try { | 106 | try { |
78 | const sources = await desktopCapturer.getSources({ | ||
79 | types: ['screen', 'window'], | ||
80 | }); | ||
81 | |||
82 | const selectionElem = document.createElement('div'); | 107 | const selectionElem = document.createElement('div'); |
83 | selectionElem.classList = 'desktop-capturer-selection'; | 108 | selectionElem.classList = ['desktop-capturer-selection']; |
84 | selectionElem.innerHTML = ` | 109 | selectionElem.innerHTML = await window.ferdi.getDisplayMediaSelector(); |
85 | <div class="desktop-capturer-selection__scroller"> | ||
86 | <ul class="desktop-capturer-selection__list"> | ||
87 | ${sources | ||
88 | .map( | ||
89 | ({ id, name, thumbnail }) => ` | ||
90 | <li class="desktop-capturer-selection__item"> | ||
91 | <button class="desktop-capturer-selection__btn" data-id="${id}" title="${name}"> | ||
92 | <img class="desktop-capturer-selection__thumbnail" src="${thumbnail.toDataURL()}" /> | ||
93 | <span class="desktop-capturer-selection__name">${name}</span> | ||
94 | </button> | ||
95 | </li> | ||
96 | `, | ||
97 | ) | ||
98 | .join('')} | ||
99 | <li class="desktop-capturer-selection__item"> | ||
100 | <button class="desktop-capturer-selection__btn" data-id="${CANCEL_ID}" title="Cancel"> | ||
101 | <span class="desktop-capturer-selection__name desktop-capturer-selection__name--cancel">Cancel</span> | ||
102 | </button> | ||
103 | </li> | ||
104 | </ul> | ||
105 | </div> | ||
106 | `; | ||
107 | document.body.appendChild(selectionElem); | 110 | document.body.appendChild(selectionElem); |
108 | 111 | ||
109 | document | 112 | document |
@@ -112,25 +115,18 @@ window.navigator.mediaDevices.getDisplayMedia = () => async (resolve, reject) => | |||
112 | button.addEventListener('click', async () => { | 115 | button.addEventListener('click', async () => { |
113 | try { | 116 | try { |
114 | const id = button.getAttribute('data-id'); | 117 | const id = button.getAttribute('data-id'); |
115 | if (id === CANCEL_ID) { | 118 | if (id === '${CANCEL_ID}') { |
116 | reject(new Error('Cancelled by user')); | 119 | reject(new Error('Cancelled by user')); |
117 | } else { | 120 | } else { |
118 | const mediaSource = sources.find((source) => source.id === id); | 121 | const stream = await window.navigator.mediaDevices.getUserMedia({ |
119 | if (!mediaSource) { | 122 | audio: false, |
120 | throw new Error(`Source with id ${id} does not exist`); | 123 | video: { |
121 | } | 124 | mandatory: { |
122 | 125 | chromeMediaSource: 'desktop', | |
123 | const stream = await window.navigator.mediaDevices.getUserMedia( | 126 | chromeMediaSourceId: id, |
124 | { | ||
125 | audio: false, | ||
126 | video: { | ||
127 | mandatory: { | ||
128 | chromeMediaSource: 'desktop', | ||
129 | chromeMediaSourceId: mediaSource.id, | ||
130 | }, | ||
131 | }, | 127 | }, |
132 | }, | 128 | }, |
133 | ); | 129 | }); |
134 | resolve(stream); | 130 | resolve(stream); |
135 | } | 131 | } |
136 | } catch (err) { | 132 | } catch (err) { |
@@ -143,4 +139,5 @@ window.navigator.mediaDevices.getDisplayMedia = () => async (resolve, reject) => | |||
143 | } catch (err) { | 139 | } catch (err) { |
144 | reject(err); | 140 | reject(err); |
145 | } | 141 | } |
146 | }; | 142 | }); |
143 | `; | ||