Explorar el Código

feat(welcome-page): be able to open settings dialog (#3327)

* feat(welcome-page): be able to open settings dialog

- Create a getter for getting a settings tab's props so the device
  selection tab can get updated available devices.
- Be able to call a function from a tab after it has mounted. This is
  used for device selection to essentially call enumerateDevices on
  the welcome page so the device selectors are populated.
- Remove event UIEvents.AUDIO_OUTPUT_DEVICE_CHANGED. Instead directly call
  setAudioOutputDeviceId where possible.
- Fix initialization of the audioOutputDeviceId in settings by defaulting
  the audio output device to the one set in settings.

* squash: updateAvailableDevices -> getAvailableDevices, add comment for propsUpdateFunction
master
virtuacoplenny hace 7 años
padre
commit
cac8888b37

+ 26
- 35
conference.js Ver fichero

@@ -45,6 +45,7 @@ import {
45 45
     setDesktopSharingEnabled
46 46
 } from './react/features/base/conference';
47 47
 import {
48
+    getAvailableDevices,
48 49
     setAudioOutputDeviceId,
49 50
     updateDeviceList
50 51
 } from './react/features/base/devices';
@@ -2129,20 +2130,6 @@ export default {
2129 2130
             }
2130 2131
         );
2131 2132
 
2132
-        APP.UI.addListener(
2133
-            UIEvents.AUDIO_OUTPUT_DEVICE_CHANGED,
2134
-            audioOutputDeviceId => {
2135
-                sendAnalytics(createDeviceChangedEvent('audio', 'output'));
2136
-                setAudioOutputDeviceId(audioOutputDeviceId, APP.store.dispatch)
2137
-                    .then(() => logger.log('changed audio output device'))
2138
-                    .catch(err => {
2139
-                        logger.warn('Failed to change audio output device. '
2140
-                            + 'Default or previously set audio output device '
2141
-                            + 'will be used instead.', err);
2142
-                    });
2143
-            }
2144
-        );
2145
-
2146 2133
         APP.UI.addListener(UIEvents.TOGGLE_AUDIO_ONLY, audioOnly => {
2147 2134
 
2148 2135
             // FIXME On web video track is stored both in redux and in
@@ -2314,39 +2301,43 @@ export default {
2314 2301
     /**
2315 2302
      * Inits list of current devices and event listener for device change.
2316 2303
      * @private
2304
+     * @returns {Promise}
2317 2305
      */
2318 2306
     _initDeviceList() {
2319 2307
         const { mediaDevices } = JitsiMeetJS;
2320 2308
 
2321 2309
         if (mediaDevices.isDeviceListAvailable()
2322 2310
                 && mediaDevices.isDeviceChangeAvailable()) {
2323
-            mediaDevices.enumerateDevices(devices => {
2324
-                // Ugly way to synchronize real device IDs with local storage
2325
-                // and settings menu. This is a workaround until
2326
-                // getConstraints() method will be implemented in browsers.
2327
-                const { dispatch } = APP.store;
2328
-
2329
-                if (this.localAudio) {
2330
-                    dispatch(updateSettings({
2331
-                        micDeviceId: this.localAudio.getDeviceId()
2332
-                    }));
2333
-                }
2334
-                if (this.localVideo) {
2335
-                    dispatch(updateSettings({
2336
-                        cameraDeviceId: this.localVideo.getDeviceId()
2337
-                    }));
2338
-                }
2339
-
2340
-                APP.store.dispatch(updateDeviceList(devices));
2341
-                APP.UI.onAvailableDevicesChanged(devices);
2342
-            });
2343
-
2344 2311
             this.deviceChangeListener = devices =>
2345 2312
                 window.setTimeout(() => this._onDeviceListChanged(devices), 0);
2346 2313
             mediaDevices.addEventListener(
2347 2314
                 JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED,
2348 2315
                 this.deviceChangeListener);
2316
+
2317
+            const { dispatch } = APP.store;
2318
+
2319
+            return dispatch(getAvailableDevices())
2320
+                .then(devices => {
2321
+                    // Ugly way to synchronize real device IDs with local
2322
+                    // storage and settings menu. This is a workaround until
2323
+                    // getConstraints() method will be implemented in browsers.
2324
+                    if (this.localAudio) {
2325
+                        dispatch(updateSettings({
2326
+                            micDeviceId: this.localAudio.getDeviceId()
2327
+                        }));
2328
+                    }
2329
+
2330
+                    if (this.localVideo) {
2331
+                        dispatch(updateSettings({
2332
+                            cameraDeviceId: this.localVideo.getDeviceId()
2333
+                        }));
2334
+                    }
2335
+
2336
+                    APP.UI.onAvailableDevicesChanged(devices);
2337
+                });
2349 2338
         }
2339
+
2340
+        return Promise.resolve();
2350 2341
     },
2351 2342
 
2352 2343
     /**

+ 0
- 11
react/features/base/devices/actionTypes.js Ver fichero

@@ -9,17 +9,6 @@
9 9
  */
10 10
 export const SET_AUDIO_INPUT_DEVICE = Symbol('SET_AUDIO_INPUT_DEVICE');
11 11
 
12
-/**
13
- * The type of Redux action which signals that the currently used audio
14
- * output device should be changed.
15
- *
16
- * {
17
- *     type: SET_AUDIO_OUTPUT_DEVICE,
18
- *     deviceId: string,
19
- * }
20
- */
21
-export const SET_AUDIO_OUTPUT_DEVICE = Symbol('SET_AUDIO_OUTPUT_DEVICE');
22
-
23 12
 /**
24 13
  * The type of Redux action which signals that the currently used video
25 14
  * input device should be changed.

+ 25
- 17
react/features/base/devices/actions.js Ver fichero

@@ -1,38 +1,46 @@
1
+import JitsiMeetJS from '../lib-jitsi-meet';
2
+
1 3
 import {
2 4
     SET_AUDIO_INPUT_DEVICE,
3
-    SET_AUDIO_OUTPUT_DEVICE,
4 5
     SET_VIDEO_INPUT_DEVICE,
5 6
     UPDATE_DEVICE_LIST
6 7
 } from './actionTypes';
7 8
 
8 9
 /**
9
- * Signals to update the currently used audio input device.
10
+ * Queries for connected A/V input and output devices and updates the redux
11
+ * state of known devices.
10 12
  *
11
- * @param {string} deviceId - The id of the new audio input device.
12
- * @returns {{
13
- *      type: SET_AUDIO_INPUT_DEVICE,
14
- *      deviceId: string
15
- * }}
13
+ * @returns {Function}
16 14
  */
17
-export function setAudioInputDevice(deviceId) {
18
-    return {
19
-        type: SET_AUDIO_INPUT_DEVICE,
20
-        deviceId
21
-    };
15
+export function getAvailableDevices() {
16
+    return dispatch => new Promise(resolve => {
17
+        const { mediaDevices } = JitsiMeetJS;
18
+
19
+        if (mediaDevices.isDeviceListAvailable()
20
+                && mediaDevices.isDeviceChangeAvailable()) {
21
+            mediaDevices.enumerateDevices(devices => {
22
+                dispatch(updateDeviceList(devices));
23
+
24
+                resolve(devices);
25
+            });
26
+        } else {
27
+            resolve([]);
28
+        }
29
+    });
22 30
 }
23 31
 
24 32
 /**
25
- * Signals to update the currently used audio output device.
33
+ * Signals to update the currently used audio input device.
26 34
  *
27
- * @param {string} deviceId - The id of the new audio ouput device.
35
+ * @param {string} deviceId - The id of the new audio input device.
28 36
  * @returns {{
29
- *      type: SET_AUDIO_OUTPUT_DEVICE,
37
+ *      type: SET_AUDIO_INPUT_DEVICE,
30 38
  *      deviceId: string
31 39
  * }}
32 40
  */
33
-export function setAudioOutputDevice(deviceId) {
41
+export function setAudioInputDevice(deviceId) {
34 42
     return {
35
-        type: SET_AUDIO_OUTPUT_DEVICE,
43
+        type: SET_AUDIO_INPUT_DEVICE,
36 44
         deviceId
37 45
     };
38 46
 }

+ 0
- 4
react/features/base/devices/middleware.js Ver fichero

@@ -6,7 +6,6 @@ import { MiddlewareRegistry } from '../redux';
6 6
 
7 7
 import {
8 8
     SET_AUDIO_INPUT_DEVICE,
9
-    SET_AUDIO_OUTPUT_DEVICE,
10 9
     SET_VIDEO_INPUT_DEVICE
11 10
 } from './actionTypes';
12 11
 
@@ -22,9 +21,6 @@ MiddlewareRegistry.register(store => next => action => {
22 21
     case SET_AUDIO_INPUT_DEVICE:
23 22
         APP.UI.emitEvent(UIEvents.AUDIO_DEVICE_CHANGED, action.deviceId);
24 23
         break;
25
-    case SET_AUDIO_OUTPUT_DEVICE:
26
-        APP.UI.emitEvent(UIEvents.AUDIO_OUTPUT_DEVICE_CHANGED, action.deviceId);
27
-        break;
28 24
     case SET_VIDEO_INPUT_DEVICE:
29 25
         APP.UI.emitEvent(UIEvents.VIDEO_DEVICE_CHANGED, action.deviceId);
30 26
         break;

+ 0
- 2
react/features/base/devices/reducer.js Ver fichero

@@ -1,6 +1,5 @@
1 1
 import {
2 2
     SET_AUDIO_INPUT_DEVICE,
3
-    SET_AUDIO_OUTPUT_DEVICE,
4 3
     SET_VIDEO_INPUT_DEVICE,
5 4
     UPDATE_DEVICE_LIST
6 5
 } from './actionTypes';
@@ -40,7 +39,6 @@ ReducerRegistry.register(
40 39
         // now.
41 40
         case SET_AUDIO_INPUT_DEVICE:
42 41
         case SET_VIDEO_INPUT_DEVICE:
43
-        case SET_AUDIO_OUTPUT_DEVICE:
44 42
         default:
45 43
             return state;
46 44
         }

+ 24
- 1
react/features/base/dialog/components/DialogWithTabs.web.js Ver fichero

@@ -103,6 +103,28 @@ class DialogWithTabs extends Component<Props, State> {
103 103
         );
104 104
     }
105 105
 
106
+    /**
107
+     * Gets the props to pass into the tab component.
108
+     *
109
+     * @param {number} tabId - The index of the tab configuration within
110
+     * {@link this.state.tabStates}.
111
+     * @returns {Object}
112
+     */
113
+    _getTabProps(tabId) {
114
+        const { tabs } = this.props;
115
+        const { tabStates } = this.state;
116
+        const tabConfiguration = tabs[tabId];
117
+        const currentTabState = tabStates[tabId];
118
+
119
+        if (tabConfiguration.propsUpdateFunction) {
120
+            return tabConfiguration.propsUpdateFunction(
121
+                currentTabState,
122
+                tabConfiguration.props);
123
+        }
124
+
125
+        return { ...currentTabState };
126
+    }
127
+
106 128
     /**
107 129
      * Renders the tabs from the tab information passed on props.
108 130
      *
@@ -155,10 +177,11 @@ class DialogWithTabs extends Component<Props, State> {
155 177
             <div className = { styles }>
156 178
                 <TabComponent
157 179
                     closeDialog = { closeDialog }
180
+                    mountCallback = { this.props.tabs[tabId].onMount }
158 181
                     onTabStateChange
159 182
                         = { this._onTabStateChange }
160 183
                     tabId = { tabId }
161
-                    { ...this.state.tabStates[tabId] } />
184
+                    { ...this._getTabProps(tabId) } />
162 185
             </div>);
163 186
     }
164 187
 

+ 1
- 1
react/features/base/settings/reducer.js Ver fichero

@@ -138,7 +138,7 @@ function _initSettings(featureState) {
138 138
         if (settings.audioOutputDeviceId
139 139
             !== JitsiMeetJS.mediaDevices.getAudioOutputDevice()) {
140 140
             JitsiMeetJS.mediaDevices.setAudioOutputDevice(
141
-                audioOutputDeviceId
141
+                settings.audioOutputDeviceId
142 142
             ).catch(ex => {
143 143
                 logger.warn('Failed to set audio output device from local '
144 144
                     + 'storage. Default audio output device will be used'

+ 30
- 8
react/features/device-selection/actions.js Ver fichero

@@ -4,18 +4,22 @@ import {
4 4
     Transport
5 5
 } from '../../../modules/transport';
6 6
 
7
+import { createDeviceChangedEvent, sendAnalytics } from '../analytics';
7 8
 import {
8 9
     getAudioOutputDeviceId,
9 10
     setAudioInputDevice,
10
-    setAudioOutputDevice,
11
+    setAudioOutputDeviceId,
11 12
     setVideoInputDevice
12 13
 } from '../base/devices';
13 14
 import { i18next } from '../base/i18n';
14 15
 import JitsiMeetJS from '../base/lib-jitsi-meet';
16
+import { updateSettings } from '../base/settings';
15 17
 
16 18
 import { SET_DEVICE_SELECTION_POPUP_DATA } from './actionTypes';
17 19
 import { getDeviceSelectionDialogProps } from './functions';
18 20
 
21
+const logger = require('jitsi-meet-logger').getLogger(__filename);
22
+
19 23
 /**
20 24
  * Opens a popup window with the device selection dialog in it.
21 25
  *
@@ -115,23 +119,22 @@ function _processRequest(dispatch, getState, request, responseCallback) { // esl
115 119
             responseCallback(getState()['features/base/devices']);
116 120
             break;
117 121
         case 'setDevice': {
118
-            let action;
119 122
             const { device } = request;
120 123
 
121 124
             switch (device.kind) {
122 125
             case 'audioinput':
123
-                action = setAudioInputDevice;
126
+                dispatch(setAudioInputDevice(device.id));
124 127
                 break;
125 128
             case 'audiooutput':
126
-                action = setAudioOutputDevice;
129
+                setAudioOutputDeviceId(device.id, dispatch);
127 130
                 break;
128 131
             case 'videoinput':
129
-                action = setVideoInputDevice;
132
+                dispatch(setVideoInputDevice(device.id));
130 133
                 break;
131 134
             default:
132 135
 
133 136
             }
134
-            dispatch(action(device.id));
137
+
135 138
             responseCallback(true);
136 139
             break;
137 140
         }
@@ -179,6 +182,10 @@ export function submitDeviceSelectionTab(newState) {
179 182
         if (newState.selectedVideoInputId
180 183
             && newState.selectedVideoInputId
181 184
                 !== currentState.selectedVideoInputId) {
185
+            dispatch(updateSettings({
186
+                cameraDeviceId: newState.selectedVideoInputId
187
+            }));
188
+
182 189
             dispatch(
183 190
                 setVideoInputDevice(newState.selectedVideoInputId));
184 191
         }
@@ -186,6 +193,10 @@ export function submitDeviceSelectionTab(newState) {
186 193
         if (newState.selectedAudioInputId
187 194
                 && newState.selectedAudioInputId
188 195
                   !== currentState.selectedAudioInputId) {
196
+            dispatch(updateSettings({
197
+                micDeviceId: newState.selectedAudioInputId
198
+            }));
199
+
189 200
             dispatch(
190 201
                 setAudioInputDevice(newState.selectedAudioInputId));
191 202
         }
@@ -193,8 +204,19 @@ export function submitDeviceSelectionTab(newState) {
193 204
         if (newState.selectedAudioOutputId
194 205
                 && newState.selectedAudioOutputId
195 206
                     !== currentState.selectedAudioOutputId) {
196
-            dispatch(
197
-                setAudioOutputDevice(newState.selectedAudioOutputId));
207
+            sendAnalytics(createDeviceChangedEvent('audio', 'output'));
208
+
209
+            setAudioOutputDeviceId(
210
+                newState.selectedAudioOutputId,
211
+                dispatch)
212
+                .then(() => logger.log('changed audio output device'))
213
+                .catch(err => {
214
+                    logger.warn(
215
+                        'Failed to change audio output device.',
216
+                        'Default or previously set audio output device will',
217
+                        ' be used instead.',
218
+                        err);
219
+                });
198 220
         }
199 221
     };
200 222
 }

+ 16
- 4
react/features/device-selection/components/DeviceSelection.js Ver fichero

@@ -12,6 +12,8 @@ import AudioOutputPreview from './AudioOutputPreview';
12 12
 import DeviceSelector from './DeviceSelector';
13 13
 import VideoInputPreview from './VideoInputPreview';
14 14
 
15
+const logger = require('jitsi-meet-logger').getLogger(__filename);
16
+
15 17
 /**
16 18
  * The type of the React {@code Component} props of {@link DeviceSelection}.
17 19
  */
@@ -64,6 +66,12 @@ export type Props = {
64 66
      */
65 67
     hideAudioOutputSelect: boolean,
66 68
 
69
+    /**
70
+     * An optional callback to invoke after the component has completed its
71
+     * mount logic.
72
+     */
73
+    mountCallback?: Function,
74
+
67 75
     /**
68 76
      * The id of the audio input device to preview.
69 77
      */
@@ -134,8 +142,12 @@ class DeviceSelection extends AbstractDialogTab<Props, State> {
134 142
      * @inheritdoc
135 143
      */
136 144
     componentDidMount() {
137
-        this._createAudioInputTrack(this.props.selectedAudioInputId);
138
-        this._createVideoInputTrack(this.props.selectedVideoInputId);
145
+        Promise.all([
146
+            this._createAudioInputTrack(this.props.selectedAudioInputId),
147
+            this._createVideoInputTrack(this.props.selectedVideoInputId)
148
+        ])
149
+        .catch(err => logger.warn('Failed to initialize preview tracks', err))
150
+        .then(() => this.props.mountCallback && this.props.mountCallback());
139 151
     }
140 152
 
141 153
     /**
@@ -212,7 +224,7 @@ class DeviceSelection extends AbstractDialogTab<Props, State> {
212 224
      * @returns {void}
213 225
      */
214 226
     _createAudioInputTrack(deviceId) {
215
-        this._disposeAudioInputPreview()
227
+        return this._disposeAudioInputPreview()
216 228
             .then(() => createLocalTrack('audio', deviceId))
217 229
             .then(jitsiLocalTrack => {
218 230
                 this.setState({
@@ -234,7 +246,7 @@ class DeviceSelection extends AbstractDialogTab<Props, State> {
234 246
      * @returns {void}
235 247
      */
236 248
     _createVideoInputTrack(deviceId) {
237
-        this._disposeVideoInputPreview()
249
+        return this._disposeVideoInputPreview()
238 250
             .then(() => createLocalTrack('video', deviceId))
239 251
             .then(jitsiLocalTrack => {
240 252
                 if (!jitsiLocalTrack) {

+ 19
- 0
react/features/settings/components/web/SettingsDialog.js Ver fichero

@@ -3,6 +3,7 @@
3 3
 import React, { Component } from 'react';
4 4
 import { connect } from 'react-redux';
5 5
 
6
+import { getAvailableDevices } from '../../../base/devices';
6 7
 import { DialogWithTabs, hideDialog } from '../../../base/dialog';
7 8
 import {
8 9
     DeviceSelection,
@@ -77,6 +78,9 @@ class SettingsDialog extends Component<Props> {
77 78
         const tabs = _tabs.map(tab => {
78 79
             return {
79 80
                 ...tab,
81
+                onMount: tab.onMount
82
+                    ? (...args) => dispatch(tab.onMount(...args))
83
+                    : undefined,
80 84
                 submit: (...args) => dispatch(tab.submit(...args))
81 85
             };
82 86
         });
@@ -133,7 +137,22 @@ function _mapStateToProps(state) {
133 137
             name: SETTINGS_TABS.DEVICES,
134 138
             component: DeviceSelection,
135 139
             label: 'settings.devices',
140
+            onMount: getAvailableDevices,
136 141
             props: getDeviceSelectionDialogProps(state),
142
+            propsUpdateFunction: (tabState, newProps) => {
143
+                // Ensure the device selection tab gets updated when new devices
144
+                // are found by taking the new props and only preserving the
145
+                // current user selected devices. If this were not done, the
146
+                // tab would keep using a copy of the initial props it received,
147
+                // leaving the device list to become stale.
148
+
149
+                return {
150
+                    ...newProps,
151
+                    selectedAudioInputId: tabState.selectedAudioInputId,
152
+                    selectedAudioOutputId: tabState.selectedAudioOutputId,
153
+                    selectedVideoInputId: tabState.selectedVideoInputId
154
+                };
155
+            },
137 156
             styles: 'settings-pane devices-pane',
138 157
             submit: submitDeviceSelectionTab
139 158
         });

+ 20
- 10
react/features/settings/functions.js Ver fichero

@@ -74,24 +74,30 @@ export function shouldShowOnlyDeviceSelection() {
74 74
 export function getMoreTabProps(stateful: Object | Function) {
75 75
     const state = toState(stateful);
76 76
     const language = i18next.language || DEFAULT_LANGUAGE;
77
-    const conference = state['features/base/conference'];
77
+    const {
78
+        conference,
79
+        followMeEnabled,
80
+        startAudioMutedPolicy,
81
+        startVideoMutedPolicy
82
+    } = state['features/base/conference'];
78 83
     const configuredTabs = interfaceConfig.SETTINGS_SECTIONS || [];
79 84
     const localParticipant = getLocalParticipant(state);
80 85
 
81 86
 
82 87
     // The settings sections to display.
83
-    const showModeratorSettings
84
-        = configuredTabs.includes('moderator')
85
-            && localParticipant.role === PARTICIPANT_ROLE.MODERATOR;
88
+    const showModeratorSettings = Boolean(
89
+        conference
90
+            && configuredTabs.includes('moderator')
91
+            && localParticipant.role === PARTICIPANT_ROLE.MODERATOR);
86 92
 
87 93
     return {
88 94
         currentLanguage: language,
89
-        followMeEnabled: Boolean(conference.followMeEnabled),
95
+        followMeEnabled: Boolean(conference && followMeEnabled),
90 96
         languages: LANGUAGES,
91 97
         showLanguageSettings: configuredTabs.includes('language'),
92 98
         showModeratorSettings,
93
-        startAudioMuted: Boolean(conference.startAudioMutedPolicy),
94
-        startVideoMuted: Boolean(conference.startVideoMutedPolicy)
99
+        startAudioMuted: Boolean(conference && startAudioMutedPolicy),
100
+        startVideoMuted: Boolean(conference && startVideoMutedPolicy)
95 101
     };
96 102
 }
97 103
 
@@ -106,12 +112,16 @@ export function getMoreTabProps(stateful: Object | Function) {
106 112
  */
107 113
 export function getProfileTabProps(stateful: Object | Function) {
108 114
     const state = toState(stateful);
109
-    const conference = state['features/base/conference'];
115
+    const {
116
+        authEnabled,
117
+        authLogin,
118
+        conference
119
+    } = state['features/base/conference'];
110 120
     const localParticipant = getLocalParticipant(state);
111 121
 
112 122
     return {
113
-        authEnabled: conference.authEnabled,
114
-        authLogin: conference.authLogin,
123
+        authEnabled: Boolean(conference && authEnabled),
124
+        authLogin: Boolean(conference && authLogin),
115 125
         displayName: localParticipant.name,
116 126
         email: localParticipant.email
117 127
     };

+ 25
- 0
react/features/welcome/components/WelcomePage.web.js Ver fichero

@@ -6,9 +6,11 @@ import { AtlasKitThemeProvider } from '@atlaskit/theme';
6 6
 import React from 'react';
7 7
 import { connect } from 'react-redux';
8 8
 
9
+import { DialogContainer } from '../../base/dialog';
9 10
 import { translate } from '../../base/i18n';
10 11
 import { Watermarks } from '../../base/react';
11 12
 import { RecentList } from '../../recent-list';
13
+import { openSettingsDialog } from '../../settings';
12 14
 
13 15
 import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
14 16
 
@@ -18,6 +20,15 @@ import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
18 20
  * @extends AbstractWelcomePage
19 21
  */
20 22
 class WelcomePage extends AbstractWelcomePage {
23
+    /**
24
+     * Default values for {@code WelcomePage} component's properties.
25
+     *
26
+     * @static
27
+     */
28
+    static defaultProps = {
29
+        _room: ''
30
+    };
31
+
21 32
     /**
22 33
      * Initializes a new WelcomePage instance.
23 34
      *
@@ -55,6 +66,7 @@ class WelcomePage extends AbstractWelcomePage {
55 66
 
56 67
         // Bind event handlers so they are only bound once per instance.
57 68
         this._onFormSubmit = this._onFormSubmit.bind(this);
69
+        this._onOpenSettings = this._onOpenSettings.bind(this);
58 70
         this._onRoomChange = this._onRoomChange.bind(this);
59 71
         this._setAdditionalContentRef
60 72
             = this._setAdditionalContentRef.bind(this);
@@ -155,6 +167,9 @@ class WelcomePage extends AbstractWelcomePage {
155 167
                             ref = { this._setAdditionalContentRef } />
156 168
                         : null }
157 169
                 </div>
170
+                <AtlasKitThemeProvider mode = 'dark'>
171
+                    <DialogContainer />
172
+                </AtlasKitThemeProvider>
158 173
             </AtlasKitThemeProvider>
159 174
         );
160 175
     }
@@ -172,6 +187,16 @@ class WelcomePage extends AbstractWelcomePage {
172 187
         this._onJoin();
173 188
     }
174 189
 
190
+    /**
191
+     * Opens {@code SettingsDialog}.
192
+     *
193
+     * @private
194
+     * @returns {void}
195
+     */
196
+    _onOpenSettings() {
197
+        this.props.dispatch(openSettingsDialog());
198
+    }
199
+
175 200
     /**
176 201
      * Overrides the super to account for the differences in the argument types
177 202
      * provided by HTML and React Native text inputs.

+ 0
- 1
service/UI/UIEvents.js Ver fichero

@@ -63,7 +63,6 @@ export default {
63 63
     LOGOUT: 'UI.logout',
64 64
     VIDEO_DEVICE_CHANGED: 'UI.video_device_changed',
65 65
     AUDIO_DEVICE_CHANGED: 'UI.audio_device_changed',
66
-    AUDIO_OUTPUT_DEVICE_CHANGED: 'UI.audio_output_device_changed',
67 66
 
68 67
     /**
69 68
      * Notifies interested listeners that the follow-me feature is enabled or

Loading…
Cancelar
Guardar