Pārlūkot izejas kodu

electron: add desktop picker

#1411
j8
virtuacoplenny 8 gadus atpakaļ
vecāks
revīzija
24ee8eb16a

+ 13
- 0
conference.js Parādīt failu

@@ -39,6 +39,9 @@ import {
39 39
     participantLeft,
40 40
     participantRoleChanged
41 41
 } from './react/features/base/participants';
42
+import {
43
+    showDesktopPicker
44
+} from  './react/features/desktop-picker';
42 45
 import {
43 46
     mediaPermissionPromptVisibilityChanged,
44 47
     suspendDetected
@@ -66,6 +69,16 @@ let DSExternalInstallationInProgress = false;
66 69
 
67 70
 import {VIDEO_CONTAINER_TYPE} from "./modules/UI/videolayout/VideoContainer";
68 71
 
72
+/*
73
+ * Logic to open a desktop picker put on the window global for
74
+ * lib-jitsi-meet to detect and invoke
75
+ */
76
+window.JitsiMeetScreenObtainer = {
77
+    openDesktopPicker(onSourceChoose) {
78
+        APP.store.dispatch(showDesktopPicker(onSourceChoose));
79
+    }
80
+};
81
+
69 82
 /**
70 83
  * Known custom conference commands.
71 84
  */

+ 5
- 5
css/_chat.scss Parādīt failu

@@ -212,24 +212,24 @@
212 212
     line-height: 30px;
213 213
 }
214 214
 
215
-::-webkit-scrollbar {
215
+:not(.default-scrollbar)::-webkit-scrollbar {
216 216
     background: #06a5df;
217 217
     width: 7px;
218 218
 }
219 219
 
220
-::-webkit-scrollbar-button {
220
+:not(.default-scrollbar)::-webkit-scrollbar-button {
221 221
     display: none;
222 222
 }
223 223
 
224
-::-webkit-scrollbar-track {
224
+:not(.default-scrollbar)::-webkit-scrollbar-track {
225 225
     background: black;
226 226
 }
227 227
 
228
-::-webkit-scrollbar-track-piece {
228
+:not(.default-scrollbar)::-webkit-scrollbar-track-piece {
229 229
     background: black;
230 230
 }
231 231
 
232
-::-webkit-scrollbar-thumb {
232
+:not(.default-scrollbar)::-webkit-scrollbar-thumb {
233 233
     background: #06a5df;
234 234
     border-radius: 4px;
235 235
 }

+ 1
- 0
css/main.scss Parādīt failu

@@ -37,6 +37,7 @@
37 37
 @import 'overlay/overlay';
38 38
 @import 'inlay';
39 39
 @import 'reload_overlay/reload_overlay';
40
+@import 'modals/desktop-picker/desktop-picker';
40 41
 @import 'modals/dialog';
41 42
 @import 'modals/feedback/feedback';
42 43
 @import 'modals/speaker_stats/speaker_stats';

+ 59
- 0
css/modals/desktop-picker/_desktop-picker.scss Parādīt failu

@@ -0,0 +1,59 @@
1
+.desktop-picker-pane {
2
+    height: 320px;
3
+    overflow-x: hidden;
4
+    overflow-y: auto;
5
+    width: 100%;
6
+
7
+    &.source-type-screen {
8
+        .desktop-picker-source {
9
+            margin-left: auto;
10
+            margin-right: auto;
11
+            width: 50%;
12
+        }
13
+
14
+        .desktop-source-preview-thumbnail {
15
+            width: 100%;
16
+        }
17
+
18
+        .desktop-source-preview-label {
19
+            display: none;
20
+        }
21
+    }
22
+
23
+    &.source-type-window {
24
+        .desktop-picker-source {
25
+            display: inline-block;
26
+            width: 30%;
27
+        }
28
+    }
29
+}
30
+
31
+.desktop-picker-source {
32
+    color: $defaultDarkFontColor;
33
+    margin-top: 10px;
34
+    text-align: center;
35
+
36
+    &.is-selected {
37
+        .desktop-source-preview-image-container {
38
+            background: rgba(0, 0, 0, 0.1);
39
+            border-radius: $borderRadius;
40
+        }
41
+    }
42
+}
43
+
44
+.desktop-source-preview-label {
45
+    margin-top: 3px;
46
+    overflow: hidden;
47
+    text-overflow: ellipsis;
48
+    white-space: nowrap;
49
+}
50
+
51
+.desktop-source-preview-thumbnail {
52
+    box-shadow: 5px 5px 5px grey;
53
+    height: auto;
54
+    max-width: 100%;
55
+}
56
+
57
+.desktop-source-preview-image-container {
58
+    padding: 10px;
59
+}

+ 4
- 1
lang/main.json Parādīt failu

@@ -339,7 +339,10 @@
339 339
         "remoteControlAllowedMessage": "__user__ accepted your remote control request!",
340 340
         "remoteControlErrorMessage": "An error occurred while trying to request remote control permissions from __user__!",
341 341
         "remoteControlStopMessage": "The remote control session ended!",
342
-        "close": "Close"
342
+        "close": "Close",
343
+        "shareYourScreen": "Share your screen",
344
+        "yourEntireScreen": "Your entire screen",
345
+        "applicationWindow": "Application window"
343 346
     },
344 347
     "email":
345 348
     {

+ 1
- 0
package.json Parādīt failu

@@ -20,6 +20,7 @@
20 20
     "@atlaskit/button": "1.0.3",
21 21
     "@atlaskit/button-group": "1.0.0",
22 22
     "@atlaskit/modal-dialog": "1.2.4",
23
+    "@atlaskit/tabs": "1.2.5",
23 24
     "async": "0.9.0",
24 25
     "autosize": "1.18.13",
25 26
     "bootstrap": "3.1.1",

+ 20
- 0
react/features/desktop-picker/actionTypes.js Parādīt failu

@@ -0,0 +1,20 @@
1
+import { Symbol } from '../base/react';
2
+
3
+/**
4
+ * Action to remove known DesktopCapturerSources.
5
+ *
6
+ * {
7
+ *     type: RESET_DESKTOP_SOURCES,
8
+ * }
9
+ */
10
+export const RESET_DESKTOP_SOURCES = Symbol('RESET_DESKTOP_SOURCES');
11
+
12
+/**
13
+ * Action to replace stored DesktopCapturerSources with new sources.
14
+ *
15
+ * {
16
+ *     type: UPDATE_DESKTOP_SOURCES,
17
+ *     sources: {Array}
18
+ * }
19
+ */
20
+export const UPDATE_DESKTOP_SOURCES = Symbol('UPDATE_DESKTOP_SOURCES');

+ 87
- 0
react/features/desktop-picker/actions.js Parādīt failu

@@ -0,0 +1,87 @@
1
+import { getLogger } from 'jitsi-meet-logger';
2
+
3
+import { openDialog } from '../base/dialog';
4
+import {
5
+    RESET_DESKTOP_SOURCES,
6
+    UPDATE_DESKTOP_SOURCES
7
+} from './actionTypes';
8
+import { DesktopPicker } from './components';
9
+
10
+const logger = getLogger(__filename);
11
+
12
+/**
13
+ * Signals to remove all stored DesktopCapturerSources.
14
+ *
15
+ * @returns {{
16
+ *     type: RESET_DESKTOP_SOURCES
17
+ * }}
18
+ */
19
+export function resetDesktopSources() {
20
+    return {
21
+        type: RESET_DESKTOP_SOURCES
22
+    };
23
+}
24
+
25
+/**
26
+ * Begins a request to get available DesktopCapturerSources.
27
+ *
28
+ * @param {Array} types - An array with DesktopCapturerSource type strings.
29
+ * @param {Object} options - Additional configuration for getting a list
30
+ * of sources.
31
+ * @param {Object} options.thumbnailSize - The desired height and width
32
+ * of the return native image object used for the preview image of the source.
33
+ * @returns {Function}
34
+ */
35
+export function obtainDesktopSources(types, options = {}) {
36
+    const capturerOptions = {
37
+        types
38
+    };
39
+
40
+    if (options.thumbnailSize) {
41
+        capturerOptions.thumbnailSize = options.thumbnailSize;
42
+    }
43
+
44
+    return dispatch => {
45
+        if (window.JitsiMeetElectron
46
+            && window.JitsiMeetElectron.obtainDesktopStreams) {
47
+            window.JitsiMeetElectron.obtainDesktopStreams(
48
+                sources => dispatch(updateDesktopSources(sources)),
49
+                error => logger.error(
50
+                    `Error while obtaining desktop sources: ${error}`),
51
+                capturerOptions
52
+            );
53
+        } else {
54
+            logger.error('Called JitsiMeetElectron.obtainDesktopStreams '
55
+                + 'but it is not defined');
56
+        }
57
+    };
58
+}
59
+
60
+/**
61
+ * Signals to open a dialog with the DesktopPicker component.
62
+ *
63
+ * @param {Function} onSourceChoose - The callback to invoke when
64
+ * a DesktopCapturerSource has been chosen.
65
+ * @returns {Object}
66
+ */
67
+export function showDesktopPicker(onSourceChoose) {
68
+    return openDialog(DesktopPicker, {
69
+        onSourceChoose
70
+    });
71
+}
72
+
73
+/**
74
+ * Signals new DesktopCapturerSources have been received.
75
+ *
76
+ * @param {Object} sources - Arrays with DesktopCapturerSources.
77
+ * @returns {{
78
+ *     type: UPDATE_DESKTOP_SOURCES,
79
+ *     sources: Array
80
+ * }}
81
+ */
82
+export function updateDesktopSources(sources) {
83
+    return {
84
+        type: UPDATE_DESKTOP_SOURCES,
85
+        sources
86
+    };
87
+}

+ 264
- 0
react/features/desktop-picker/components/DesktopPicker.js Parādīt failu

@@ -0,0 +1,264 @@
1
+/* global config */
2
+
3
+import Tabs from '@atlaskit/tabs';
4
+import React, { Component } from 'react';
5
+import { connect } from 'react-redux';
6
+
7
+import { Dialog, hideDialog } from '../../base/dialog';
8
+import { translate } from '../../base/i18n';
9
+import {
10
+    resetDesktopSources,
11
+    obtainDesktopSources
12
+} from '../actions';
13
+import DesktopPickerPane from './DesktopPickerPane';
14
+
15
+const updateInterval = 1000;
16
+const thumbnailSize = {
17
+    height: 300,
18
+    width: 300
19
+};
20
+const tabConfigurations = [
21
+    {
22
+        label: 'dialog.yourEntireScreen',
23
+        type: 'screen',
24
+        isDefault: true
25
+    },
26
+    {
27
+        label: 'dialog.applicationWindow',
28
+        type: 'window'
29
+    }
30
+];
31
+
32
+const validTypes = tabConfigurations.map(configuration => configuration.type);
33
+const configuredTypes = config.desktopSharingChromeSources || [];
34
+
35
+const tabsToPopulate = tabConfigurations.filter(configuration =>
36
+    configuredTypes.includes(configuration.type)
37
+    && validTypes.includes(configuration.type)
38
+);
39
+const typesToFetch = tabsToPopulate.map(configuration => configuration.type);
40
+
41
+/**
42
+ * React component for DesktopPicker.
43
+ *
44
+ * @extends Component
45
+ */
46
+class DesktopPicker extends Component {
47
+    /**
48
+     * DesktopPicker component's property types.
49
+     *
50
+     * @static
51
+     */
52
+    static propTypes = {
53
+        /**
54
+         * Used to request DesktopCapturerSources.
55
+         */
56
+        dispatch: React.PropTypes.func,
57
+
58
+        /**
59
+         * The callback to be invoked when the component is closed or
60
+         * when a DesktopCapturerSource has been chosen.
61
+         */
62
+        onSourceChoose: React.PropTypes.func,
63
+
64
+        /**
65
+         * An object with arrays of DesktopCapturerSources. The key
66
+         * should be the source type.
67
+         */
68
+        sources: React.PropTypes.object,
69
+
70
+        /**
71
+         * Used to obtain translations.
72
+         */
73
+        t: React.PropTypes.func
74
+    }
75
+
76
+    /**
77
+     * Initializes a new DesktopPicker instance.
78
+     *
79
+     * @param {Object} props - The read-only properties with which the new
80
+     * instance is to be initialized.
81
+     */
82
+    constructor(props) {
83
+        super(props);
84
+
85
+        this.state = {
86
+            selectedSourceId: ''
87
+        };
88
+
89
+        this._poller = null;
90
+        this._onCloseModal = this._onCloseModal.bind(this);
91
+        this._onPreviewClick = this._onPreviewClick.bind(this);
92
+        this._onSubmit = this._onSubmit.bind(this);
93
+        this._updateSources = this._updateSources.bind(this);
94
+    }
95
+
96
+    /**
97
+     * Perform an immediate update request for DesktopCapturerSources and
98
+     * begin requesting updates at an interval.
99
+     *
100
+     * @inheritdoc
101
+     */
102
+    componentWillMount() {
103
+        this._updateSources();
104
+        this._startPolling();
105
+    }
106
+
107
+    /**
108
+     * Clean up component and DesktopCapturerSource store state.
109
+     *
110
+     * @inheritdoc
111
+     */
112
+    componentWillUnmount() {
113
+        this._stopPolling();
114
+        this.props.dispatch(resetDesktopSources());
115
+    }
116
+
117
+    /**
118
+     * Notifies this mounted React Component that it will receive new props.
119
+     * Sets a default selected source if one is not already set.
120
+     *
121
+     * @inheritdoc
122
+     * @param {Object} nextProps - The read-only React Component props that this
123
+     * instance will receive.
124
+     * @returns {void}
125
+     */
126
+    componentWillReceiveProps(nextProps) {
127
+        if (!this.state.selectedSourceId
128
+            && nextProps.sources.screen.length) {
129
+            this.setState({ selectedSourceId: nextProps.sources.screen[0].id });
130
+        }
131
+    }
132
+
133
+    /**
134
+     * Implements React's {@link Component#render()}.
135
+     *
136
+     * @inheritdoc
137
+     */
138
+    render() {
139
+        return (
140
+            <Dialog
141
+                isModal = { false }
142
+                okTitleKey = 'dialog.Share'
143
+                onCancel = { this._onCloseModal }
144
+                onSubmit = { this._onSubmit }
145
+                titleKey = 'dialog.shareYourScreen'
146
+                width = 'medium' >
147
+                { this._renderTabs() }
148
+            </Dialog>);
149
+    }
150
+
151
+    /**
152
+     * Dispatches an action to get currently available DesktopCapturerSources.
153
+     *
154
+     * @private
155
+     * @returns {void}
156
+     */
157
+    _updateSources() {
158
+        this.props.dispatch(obtainDesktopSources(
159
+            typesToFetch,
160
+            {
161
+                thumbnailSize
162
+            }
163
+        ));
164
+    }
165
+
166
+    /**
167
+     * Create an interval to update knwon available DesktopCapturerSources.
168
+     *
169
+     * @private
170
+     * @returns {void}
171
+     */
172
+    _startPolling() {
173
+        this._stopPolling();
174
+        this._poller = window.setInterval(this._updateSources,
175
+            updateInterval);
176
+    }
177
+
178
+    /**
179
+     * Cancels the interval to update DesktopCapturerSources.
180
+     *
181
+     * @private
182
+     * @returns {void}
183
+     */
184
+    _stopPolling() {
185
+        window.clearInterval(this._poller);
186
+        this._poller = null;
187
+    }
188
+
189
+    /**
190
+     * Sets the currently selected DesktopCapturerSource.
191
+     *
192
+     * @param {string} id - The id of DesktopCapturerSource.
193
+     * @returns {void}
194
+     */
195
+    _onPreviewClick(id) {
196
+        this.setState({ selectedSourceId: id });
197
+    }
198
+
199
+    /**
200
+     * Request to close the modal and execute callbacks
201
+     * with the selected source id.
202
+     *
203
+     * @returns {void}
204
+     */
205
+    _onSubmit() {
206
+        this._onCloseModal(this.state.selectedSourceId);
207
+    }
208
+
209
+    /**
210
+     * Dispatches an action to hide the DesktopPicker and invokes
211
+     * the passed in callback with a selectedSourceId, if any.
212
+     *
213
+     * @param {string} id - The id of the DesktopCapturerSource to pass into
214
+     * the onSourceChoose callback.
215
+     * @returns {void}
216
+     */
217
+    _onCloseModal(id = '') {
218
+        this.props.onSourceChoose(id);
219
+        this.props.dispatch(hideDialog());
220
+    }
221
+
222
+    /**
223
+     * Configures and renders the tabs for display.
224
+     *
225
+     * @returns {ReactElement}
226
+     * @private
227
+     */
228
+    _renderTabs() {
229
+        const tabs = tabsToPopulate.map(tabConfig => {
230
+            const type = tabConfig.type;
231
+
232
+            return {
233
+                label: this.props.t(tabConfig.label),
234
+                defaultSelected: tabConfig.isDefault,
235
+                content: <DesktopPickerPane
236
+                    key = { type }
237
+                    onClick = { this._onPreviewClick }
238
+                    onDoubleClick = { this._onCloseModal }
239
+                    selectedSourceId = { this.state.selectedSourceId }
240
+                    sources = { this.props.sources[type] || [] }
241
+                    type = { type } />
242
+            };
243
+        });
244
+
245
+        return <Tabs tabs = { tabs } />;
246
+    }
247
+}
248
+
249
+/**
250
+ * Maps (parts of) the Redux state to the associated DesktopPicker's props.
251
+ *
252
+ * @param {Object} state - Redux state.
253
+ * @protected
254
+ * @returns {{
255
+ *     sources: Object
256
+ * }}
257
+ */
258
+function mapStateToProps(state) {
259
+    return {
260
+        sources: state['features/desktop-picker/sources']
261
+    };
262
+}
263
+
264
+export default translate(connect(mapStateToProps)(DesktopPicker));

+ 69
- 0
react/features/desktop-picker/components/DesktopPickerPane.js Parādīt failu

@@ -0,0 +1,69 @@
1
+import React, { Component } from 'react';
2
+import DesktopSourcePreview from './DesktopSourcePreview';
3
+
4
+/**
5
+ * React component for showing a grid of DesktopSourcePreviews.
6
+ *
7
+ * @extends Component
8
+ */
9
+class DesktopPickerPane extends Component {
10
+    /**
11
+     * DesktopPickerPane component's property types.
12
+     *
13
+     * @static
14
+     */
15
+    static propTypes = {
16
+        /**
17
+         * The handler to be invoked when a DesktopSourcePreview is clicked.
18
+         */
19
+        onClick: React.PropTypes.func,
20
+
21
+        /**
22
+         * The handler to be invoked when a DesktopSourcePreview is
23
+         * double clicked.
24
+         */
25
+        onDoubleClick: React.PropTypes.func,
26
+
27
+        /**
28
+         * The id of the DesktopCapturerSource that is currently selected.
29
+         */
30
+        selectedSourceId: React.PropTypes.string,
31
+
32
+        /**
33
+         * An array of DesktopCapturerSources.
34
+         */
35
+        sources: React.PropTypes.array,
36
+
37
+        /**
38
+         * The source type of the DesktopCapturerSources to display.
39
+         */
40
+        type: React.PropTypes.string
41
+    }
42
+
43
+    /**
44
+     * Implements React's {@link Component#render()}.
45
+     *
46
+     * @inheritdoc
47
+     * @returns {ReactElement}
48
+     */
49
+    render() {
50
+        const previews = this.props.sources.map(source =>
51
+            <DesktopSourcePreview
52
+                isSelected = { source.id === this.props.selectedSourceId }
53
+                key = { source.id }
54
+                onClick = { this.props.onClick }
55
+                onDoubleClick = { this.props.onDoubleClick }
56
+                source = { source } />
57
+        );
58
+        const classnames = 'desktop-picker-pane default-scrollbar '
59
+            + `source-type-${this.props.type}`;
60
+
61
+        return (
62
+            <div className = { classnames }>
63
+                { previews }
64
+            </div>
65
+        );
66
+    }
67
+}
68
+
69
+export default DesktopPickerPane;

+ 97
- 0
react/features/desktop-picker/components/DesktopSourcePreview.js Parādīt failu

@@ -0,0 +1,97 @@
1
+import React, { Component } from 'react';
2
+
3
+/**
4
+ * React component for displaying a preview of a DesktopCapturerSource.
5
+ *
6
+ * @extends Component
7
+ */
8
+class DesktopSourcePreview extends Component {
9
+    /**
10
+     * DesktopSourcePreview component's property types.
11
+     *
12
+     * @static
13
+     */
14
+    static propTypes = {
15
+        /**
16
+         * If true the 'is-selected' class will be added to the component.
17
+         */
18
+        isSelected: React.PropTypes.bool,
19
+
20
+        /**
21
+         * The callback to invoke when the component is clicked.
22
+         * The id of the DesktopCapturerSource will be passed in.
23
+         */
24
+        onClick: React.PropTypes.func,
25
+
26
+        /**
27
+         * The callback to invoke when the component is double clicked.
28
+         * The id of the DesktopCapturerSource will be passed in.
29
+         */
30
+        onDoubleClick: React.PropTypes.func,
31
+
32
+        /**
33
+         * The DesktopCapturerSource to display.
34
+         */
35
+        source: React.PropTypes.object
36
+    }
37
+
38
+    /**
39
+     * Initializes a new DesktopSourcePreview instance.
40
+     *
41
+     * @param {Object} props - The read-only properties with which the new
42
+     * instance is to be initialized.
43
+     */
44
+    constructor(props) {
45
+        super(props);
46
+
47
+        this._onClick = this._onClick.bind(this);
48
+        this._onDoubleClick = this._onDoubleClick.bind(this);
49
+    }
50
+
51
+    /**
52
+     * Implements React's {@link Component#render()}.
53
+     *
54
+     * @inheritdoc
55
+     * @returns {ReactElement}
56
+     */
57
+    render() {
58
+        const isSelectedClass = this.props.isSelected ? 'is-selected' : '';
59
+        const displayClasses = `desktop-picker-source ${isSelectedClass}`;
60
+
61
+        return (
62
+            <div
63
+                className = { displayClasses }
64
+                onClick = { this._onClick }
65
+                onDoubleClick = { this._onDoubleClick }>
66
+                <div className = 'desktop-source-preview-image-container'>
67
+                    <img
68
+                        className = 'desktop-source-preview-thumbnail'
69
+                        src = { this.props.source.thumbnail.toDataURL() } />
70
+                </div>
71
+                <div className = 'desktop-source-preview-label'>
72
+                    { this.props.source.name }
73
+                </div>
74
+            </div>
75
+        );
76
+    }
77
+
78
+    /**
79
+     * Invokes the passed in onClick callback.
80
+     *
81
+     * @returns {void}
82
+     */
83
+    _onClick() {
84
+        this.props.onClick(this.props.source.id);
85
+    }
86
+
87
+    /**
88
+     * Invokes the passed in onDoubleClick callback.
89
+     *
90
+     * @returns {void}
91
+     */
92
+    _onDoubleClick() {
93
+        this.props.onDoubleClick(this.props.source.id);
94
+    }
95
+}
96
+
97
+export default DesktopSourcePreview;

+ 1
- 0
react/features/desktop-picker/components/index.js Parādīt failu

@@ -0,0 +1 @@
1
+export { default as DesktopPicker } from './DesktopPicker';

+ 5
- 0
react/features/desktop-picker/index.js Parādīt failu

@@ -0,0 +1,5 @@
1
+export * from './actionTypes';
2
+export * from './actions';
3
+export * from './components';
4
+
5
+import './reducer';

+ 59
- 0
react/features/desktop-picker/reducer.js Parādīt failu

@@ -0,0 +1,59 @@
1
+import { ReducerRegistry } from '../base/redux';
2
+import {
3
+    RESET_DESKTOP_SOURCES,
4
+    UPDATE_DESKTOP_SOURCES
5
+} from './actionTypes';
6
+
7
+const defaultState = {
8
+    screen: [],
9
+    window: []
10
+};
11
+
12
+/**
13
+ * Listen for actions that mutate the known available DesktopCapturerSources.
14
+ *
15
+ * @param {Object[]} state - Current state.
16
+ * @param {Object} action - Action object.
17
+ * @param {string} action.type - Type of action.
18
+ * @param {Array} action.sources - DesktopCapturerSources.
19
+ * @returns {Object}
20
+ */
21
+ReducerRegistry.register(
22
+    'features/desktop-picker/sources',
23
+    (state = defaultState, action) => {
24
+        switch (action.type) {
25
+        case RESET_DESKTOP_SOURCES:
26
+            return { ...defaultState };
27
+        case UPDATE_DESKTOP_SOURCES:
28
+            return seperateSourcesByType(action.sources);
29
+        default:
30
+            return state;
31
+        }
32
+    });
33
+
34
+/**
35
+ * Converts an array of DesktopCapturerSources to an object with types
36
+ * for keys and values being an array with sources of the key's type.
37
+ *
38
+ * @param {Array} sources - DesktopCapturerSources.
39
+ * @returns {Object} An object with the sources split into seperate arrays
40
+ * based on source type.
41
+ * @private
42
+ */
43
+function seperateSourcesByType(sources = []) {
44
+    const sourcesByType = {
45
+        screen: [],
46
+        window: []
47
+    };
48
+
49
+    sources.forEach(source => {
50
+        const sourceIdParts = source.id.split(':');
51
+        const sourceType = sourceIdParts[0];
52
+
53
+        if (sourcesByType[sourceType]) {
54
+            sourcesByType[sourceType].push(source);
55
+        }
56
+    });
57
+
58
+    return sourcesByType;
59
+}

Notiek ielāde…
Atcelt
Saglabāt