Browse Source

fix(DesktopPicker): Issues with selection (#2113)

j8
hristoterezov 8 years ago
parent
commit
178235513b
1 changed files with 110 additions and 50 deletions
  1. 110
    50
      react/features/desktop-picker/components/DesktopPicker.js

+ 110
- 50
react/features/desktop-picker/components/DesktopPicker.js View File

11
 import DesktopPickerPane from './DesktopPickerPane';
11
 import DesktopPickerPane from './DesktopPickerPane';
12
 import { obtainDesktopSources } from '../functions';
12
 import { obtainDesktopSources } from '../functions';
13
 
13
 
14
+/**
15
+ * The size of the requested thumbnails.
16
+ *
17
+ * @type {Object}
18
+ */
14
 const THUMBNAIL_SIZE = {
19
 const THUMBNAIL_SIZE = {
15
     height: 300,
20
     height: 300,
16
     width: 300
21
     width: 300
17
 };
22
 };
18
 
23
 
24
+/**
25
+ * The sources polling interval in ms.
26
+ *
27
+ * @type {int}
28
+ */
19
 const UPDATE_INTERVAL = 2000;
29
 const UPDATE_INTERVAL = 2000;
20
 
30
 
21
-type TabConfiguration = {
22
-    defaultSelected?: boolean,
23
-    label: string
24
-};
31
+/**
32
+ * The default selected tab.
33
+ *
34
+ * @type {string}
35
+ */
36
+const DEFAULT_TAB_TYPE = 'screen';
25
 
37
 
26
-const TAB_CONFIGURATIONS: { [type: string]: TabConfiguration} = {
27
-    screen: {
28
-        /**
29
-         * The indicator which determines whether this tab configuration is
30
-         * selected by default.
31
-         *
32
-         * @type {boolean}
33
-         */
34
-        defaultSelected: true,
35
-        label: 'dialog.yourEntireScreen'
36
-    },
37
-    window: {
38
-        label: 'dialog.applicationWindow'
39
-    }
38
+const TAB_LABELS = {
39
+    screen: 'dialog.yourEntireScreen',
40
+    window: 'dialog.applicationWindow'
40
 };
41
 };
41
 
42
 
42
-const VALID_TYPES = Object.keys(TAB_CONFIGURATIONS);
43
+const VALID_TYPES = Object.keys(TAB_LABELS);
43
 
44
 
44
 /**
45
 /**
45
  * React component for DesktopPicker.
46
  * React component for DesktopPicker.
84
         types: []
85
         types: []
85
     };
86
     };
86
 
87
 
88
+    /**
89
+     * Stores the type of the selected tab.
90
+     *
91
+     * @type {string}
92
+     */
93
+    _selectedTabType = DEFAULT_TAB_TYPE;
94
+
87
     /**
95
     /**
88
      * Initializes a new DesktopPicker instance.
96
      * Initializes a new DesktopPicker instance.
89
      *
97
      *
97
         this._onCloseModal = this._onCloseModal.bind(this);
105
         this._onCloseModal = this._onCloseModal.bind(this);
98
         this._onPreviewClick = this._onPreviewClick.bind(this);
106
         this._onPreviewClick = this._onPreviewClick.bind(this);
99
         this._onSubmit = this._onSubmit.bind(this);
107
         this._onSubmit = this._onSubmit.bind(this);
108
+        this._onTabSelected = this._onTabSelected.bind(this);
100
         this._updateSources = this._updateSources.bind(this);
109
         this._updateSources = this._updateSources.bind(this);
101
 
110
 
102
         this.state.types
111
         this.state.types
167
         );
176
         );
168
     }
177
     }
169
 
178
 
179
+    /**
180
+     * Computates the selected source.
181
+     *
182
+     * @param {Object} sources - The available sources.
183
+     * @returns {Object} The selectedSource value.
184
+     */
185
+    _getSelectedSource(sources = {}) {
186
+        const { selectedSource } = this.state;
187
+
188
+        /**
189
+         * If there are no sources for this type (or no sources for any type)
190
+         * we can't select anything.
191
+         */
192
+        if (!Array.isArray(sources[this._selectedTabType])
193
+                || sources[this._selectedTabType].length <= 0) {
194
+            return {};
195
+        }
196
+
197
+        /**
198
+         * Select the first available source for this type in the following
199
+         * scenarios:
200
+         * 1) Nothing is yet selected.
201
+         * 2) Tab change.
202
+         * 3) The selected source is no longer available.
203
+         */
204
+        if (!selectedSource // scenario 1)
205
+                || selectedSource.type !== this._selectedTabType // scenario 2)
206
+                || !sources[this._selectedTabType].some( // scenario 3)
207
+                        source => source.id === selectedSource.id)) {
208
+            return {
209
+                id: sources[this._selectedTabType][0].id,
210
+                type: this._selectedTabType
211
+            };
212
+        }
213
+
214
+        /**
215
+         * For all other scenarios don't change the selection.
216
+         */
217
+        return selectedSource;
218
+    }
219
+
220
+    /**
221
+     * Extracts only the valid types from the passed {@code types}.
222
+     *
223
+     * @param {Array<string>} types - The types to filter.
224
+     * @returns {Array<string>} The filtered types.
225
+     */
226
+    _getValidTypes(types = []) {
227
+        return types.filter(
228
+            type => VALID_TYPES.includes(type));
229
+    }
230
+
170
     _onCloseModal: (?string, string) => void;
231
     _onCloseModal: (?string, string) => void;
171
 
232
 
172
     /**
233
     /**
202
         });
263
         });
203
     }
264
     }
204
 
265
 
205
-    /**
206
-     * Extracts only the valid types from the passed {@code types}.
207
-     *
208
-     * @param {Array<string>} types - The types to filter.
209
-     * @returns {Array<string>} The filtered types.
210
-     */
211
-    _getValidTypes(types = []) {
212
-        return types.filter(
213
-            type => VALID_TYPES.includes(type));
214
-    }
215
-
216
     _onSubmit: () => void;
266
     _onSubmit: () => void;
217
 
267
 
218
     /**
268
     /**
227
         this._onCloseModal(id, type);
277
         this._onCloseModal(id, type);
228
     }
278
     }
229
 
279
 
280
+    _onTabSelected: () => void;
281
+
282
+    /**
283
+     * Stores the selected tab and updates the selected source via
284
+     * {@code _getSelectedSource}.
285
+     *
286
+     * @param {int} idx - The index of the selected tab.
287
+     * @returns {void}
288
+     */
289
+    _onTabSelected(idx) {
290
+        const { types, sources } = this.state;
291
+
292
+        this._selectedTabType = types[idx];
293
+        this.setState({
294
+            selectedSource: this._getSelectedSource(sources)
295
+        });
296
+    }
297
+
230
     /**
298
     /**
231
      * Configures and renders the tabs for display.
299
      * Configures and renders the tabs for display.
232
      *
300
      *
239
         const tabs
307
         const tabs
240
             = types.map(
308
             = types.map(
241
                 type => {
309
                 type => {
242
-                    const { defaultSelected, label } = TAB_CONFIGURATIONS[type];
243
-
244
                     return {
310
                     return {
245
                         content: <DesktopPickerPane
311
                         content: <DesktopPickerPane
246
                             key = { type }
312
                             key = { type }
249
                             selectedSourceId = { selectedSource.id }
315
                             selectedSourceId = { selectedSource.id }
250
                             sources = { sources[type] }
316
                             sources = { sources[type] }
251
                             type = { type } />,
317
                             type = { type } />,
252
-                        defaultSelected,
253
-                        label: t(label)
318
+                        defaultSelected: type === DEFAULT_TAB_TYPE,
319
+                        label: t(TAB_LABELS[type])
254
                     };
320
                     };
255
                 });
321
                 });
256
 
322
 
257
-        return <Tabs tabs = { tabs } />;
323
+        return (
324
+            <Tabs
325
+                onSelect = { this._onTabSelected }
326
+                tabs = { tabs } />);
258
     }
327
     }
259
 
328
 
260
     /**
329
     /**
283
     _updateSources: () => void;
352
     _updateSources: () => void;
284
 
353
 
285
     /**
354
     /**
286
-     * Dispatches an action to get currently available DesktopCapturerSources.
355
+     * Obtains the desktop sources and updates state with them.
287
      *
356
      *
288
      * @private
357
      * @private
289
      * @returns {void}
358
      * @returns {void}
297
                 { thumbnailSize: THUMBNAIL_SIZE }
366
                 { thumbnailSize: THUMBNAIL_SIZE }
298
             )
367
             )
299
             .then(sources => {
368
             .then(sources => {
300
-                const nextState: Object = {
301
-                    sources
302
-                };
303
-
304
-                // FIXME: selectedSource when screen is disabled, when the
305
-                // source has been removed or when the selectedTab is changed!!!
306
-                if (!this.state.selectedSource.id
307
-                        && sources.screen.length > 0) {
308
-                    nextState.selectedSource = {
309
-                        id: sources.screen[0].id,
310
-                        type: 'screen'
311
-                    };
312
-                }
369
+                const selectedSource = this._getSelectedSource(sources);
313
 
370
 
314
                 // TODO: Maybe check if we have stopped the timer and unmounted
371
                 // TODO: Maybe check if we have stopped the timer and unmounted
315
                 // the component.
372
                 // the component.
316
-                this.setState(nextState);
373
+                this.setState({
374
+                    sources,
375
+                    selectedSource
376
+                });
317
             })
377
             })
318
             .catch(() => { /* ignore */ });
378
             .catch(() => { /* ignore */ });
319
         }
379
         }

Loading…
Cancel
Save