浏览代码

Fix interface_config.js/interfaceConfig overriding

It got broken while rewriting the Web toolbar in React Toolbox. There is
a problem with the toolbars and how we construct the intialState of the
buttons. The _getInitialState() in the toolbox reducer gets the list of
buttons from interfaceConfig, but in fact interfaceConfig is meant to be
overriden in several very important cases. One of the cases being the
external API, which we use in several projects in production.
master
Ilya Daynatovich 8 年前
父节点
当前提交
bcbdaaa6ea

+ 12
- 0
react/features/toolbox/actionTypes.js 查看文件

9
  */
9
  */
10
 export const CLEAR_TOOLBOX_TIMEOUT = Symbol('CLEAR_TOOLBOX_TIMEOUT');
10
 export const CLEAR_TOOLBOX_TIMEOUT = Symbol('CLEAR_TOOLBOX_TIMEOUT');
11
 
11
 
12
+/**
13
+ * The type of the action which sets the default toolbar buttons of the Toolbox.
14
+ *
15
+ * {
16
+ *     type: SET_DEFAULT_TOOLBOX_BUTTONS,
17
+ *     primaryToolbarButtons: Map,
18
+ *     secondaryToolbarButtons: Map
19
+ * }
20
+ */
21
+export const SET_DEFAULT_TOOLBOX_BUTTONS
22
+    = Symbol('SET_DEFAULT_TOOLBOX_BUTTONS');
23
+
12
 /**
24
 /**
13
  * The type of the action which sets the permanent visibility of the Toolbox.
25
  * The type of the action which sets the permanent visibility of the Toolbox.
14
  *
26
  *

+ 34
- 16
react/features/toolbox/actions.native.js 查看文件

4
 
4
 
5
 import {
5
 import {
6
     CLEAR_TOOLBOX_TIMEOUT,
6
     CLEAR_TOOLBOX_TIMEOUT,
7
+    SET_DEFAULT_TOOLBOX_BUTTONS,
7
     SET_TOOLBOX_ALWAYS_VISIBLE,
8
     SET_TOOLBOX_ALWAYS_VISIBLE,
8
     SET_SUBJECT,
9
     SET_SUBJECT,
9
     SET_SUBJECT_SLIDE_IN,
10
     SET_SUBJECT_SLIDE_IN,
13
     SET_TOOLBOX_TIMEOUT_MS,
14
     SET_TOOLBOX_TIMEOUT_MS,
14
     SET_TOOLBOX_VISIBLE
15
     SET_TOOLBOX_VISIBLE
15
 } from './actionTypes';
16
 } from './actionTypes';
17
+import { getDefaultToolboxButtons } from './functions';
16
 
18
 
17
 /**
19
 /**
18
  * Event handler for local raise hand changed event.
20
  * Event handler for local raise hand changed event.
46
     };
48
     };
47
 }
49
 }
48
 
50
 
49
-/**
50
- * Signals that always visible toolbars value should be changed.
51
- *
52
- * @param {boolean} alwaysVisible - Value to be set in redux store.
53
- * @returns {{
54
- *     type: SET_TOOLBOX_ALWAYS_VISIBLE,
55
- *     alwaysVisible: boolean
56
- * }}
57
- */
58
-export function setToolboxAlwaysVisible(alwaysVisible: boolean): Object {
59
-    return {
60
-        type: SET_TOOLBOX_ALWAYS_VISIBLE,
61
-        alwaysVisible
62
-    };
63
-}
64
-
65
 /**
51
 /**
66
  * Enables/disables audio toolbar button.
52
  * Enables/disables audio toolbar button.
67
  *
53
  *
83
     };
69
     };
84
 }
70
 }
85
 
71
 
72
+/**
73
+ * Sets the default toolbar buttons of the Toolbox.
74
+ *
75
+ * @returns {{
76
+ *     type: SET_DEFAULT_TOOLBOX_BUTTONS,
77
+ *     primaryToolbarButtons: Map,
78
+ *     secondaryToolbarButtons: Map
79
+ * }}
80
+ */
81
+export function setDefaultToolboxButtons(): Object {
82
+    return {
83
+        type: SET_DEFAULT_TOOLBOX_BUTTONS,
84
+        ...getDefaultToolboxButtons()
85
+    };
86
+}
87
+
86
 /**
88
 /**
87
  * Signals that value of conference subject should be changed.
89
  * Signals that value of conference subject should be changed.
88
  *
90
  *
148
     };
150
     };
149
 }
151
 }
150
 
152
 
153
+/**
154
+ * Signals that always visible toolbars value should be changed.
155
+ *
156
+ * @param {boolean} alwaysVisible - Value to be set in redux store.
157
+ * @returns {{
158
+ *     type: SET_TOOLBOX_ALWAYS_VISIBLE,
159
+ *     alwaysVisible: boolean
160
+ * }}
161
+ */
162
+export function setToolboxAlwaysVisible(alwaysVisible: boolean): Object {
163
+    return {
164
+        type: SET_TOOLBOX_ALWAYS_VISIBLE,
165
+        alwaysVisible
166
+    };
167
+}
168
+
151
 /* eslint-disable flowtype/space-before-type-colon */
169
 /* eslint-disable flowtype/space-before-type-colon */
152
 
170
 
153
 /**
171
 /**

+ 33
- 2
react/features/toolbox/components/Toolbox.web.js 查看文件

5
 
5
 
6
 import UIEvents from '../../../../service/UI/UIEvents';
6
 import UIEvents from '../../../../service/UI/UIEvents';
7
 
7
 
8
-import { setToolboxAlwaysVisible } from '../actions';
8
+import {
9
+    setDefaultToolboxButtons,
10
+    setToolboxAlwaysVisible
11
+} from '../actions';
9
 import {
12
 import {
10
     abstractMapStateToProps,
13
     abstractMapStateToProps,
11
     showCustomToolbarPopup
14
     showCustomToolbarPopup
28
      * @static
31
      * @static
29
      */
32
      */
30
     static propTypes = {
33
     static propTypes = {
34
+        /**
35
+         * Handler dispatching setting default buttons action.
36
+         */
37
+        _setDefaultToolboxButtons: React.PropTypes.func,
38
+
31
         /**
39
         /**
32
          * Handler dispatching reset always visible toolbox action.
40
          * Handler dispatching reset always visible toolbox action.
33
          */
41
          */
61
         APP.UI.addListener(
69
         APP.UI.addListener(
62
             UIEvents.SHOW_CUSTOM_TOOLBAR_BUTTON_POPUP,
70
             UIEvents.SHOW_CUSTOM_TOOLBAR_BUTTON_POPUP,
63
             showCustomToolbarPopup);
71
             showCustomToolbarPopup);
72
+
73
+        // FIXME The redux action SET_DEFAULT_TOOLBOX_BUTTONS and related source
74
+        // code such as the redux action creator setDefaultToolboxButtons and
75
+        // _setDefaultToolboxButtons were introduced to solve the following bug
76
+        // in the implementation of features/toolbar at the time of this
77
+        // writing: getDefaultToolboxButtons uses interfaceConfig which is not
78
+        // in the redux store at the time of this writing yet interfaceConfig is
79
+        // modified after getDefaultToolboxButtons is called.
80
+        // SET_DEFAULT_TOOLBOX_BUTTONS represents/implements an explicit delay
81
+        // of the invocation of getDefaultToolboxButtons until, heuristically,
82
+        // all existing changes to interfaceConfig have been applied already in
83
+        // our known execution paths.
84
+        this.props._setDefaultToolboxButtons();
64
     }
85
     }
65
 
86
 
66
     /**
87
     /**
158
  *
179
  *
159
  * @param {Function} dispatch - Redux action dispatcher.
180
  * @param {Function} dispatch - Redux action dispatcher.
160
  * @returns {{
181
  * @returns {{
182
+ *     _setDefaultToolboxButtons: Function,
161
  *     _setToolboxAlwaysVisible: Function
183
  *     _setToolboxAlwaysVisible: Function
162
  * }}
184
  * }}
163
  * @private
185
  * @private
164
  */
186
  */
165
 function _mapDispatchToProps(dispatch: Function): Object {
187
 function _mapDispatchToProps(dispatch: Function): Object {
166
     return {
188
     return {
189
+        /**
190
+         * Dispatches a (redux) action to set the default toolbar buttons.
191
+         *
192
+         * @returns {Object} Dispatched action.
193
+         */
194
+        _setDefaultToolboxButtons() {
195
+            dispatch(setDefaultToolboxButtons());
196
+        },
167
 
197
 
168
         /**
198
         /**
169
-         * Dispatches an action resetting always visible toolbox.
199
+         * Dispatches a (redux) action to reset the permanent visibility of
200
+         * the Toolbox.
170
          *
201
          *
171
          * @returns {Object} Dispatched action.
202
          * @returns {Object} Dispatched action.
172
          */
203
          */

+ 16
- 5
react/features/toolbox/functions.js 查看文件

112
     };
112
     };
113
 }
113
 }
114
 
114
 
115
+/* eslint-disable flowtype/space-before-type-colon */
116
+
115
 /**
117
 /**
116
  * Takes toolbar button props and maps them to HTML attributes to set.
118
  * Takes toolbar button props and maps them to HTML attributes to set.
117
  *
119
  *
118
  * @param {Object} props - Props set to the React component.
120
  * @param {Object} props - Props set to the React component.
119
  * @returns {MapOfAttributes}
121
  * @returns {MapOfAttributes}
120
  */
122
  */
121
-export function getButtonAttributesByProps(props: Object): MapOfAttributes {
122
-    const classNames = [ ...props.classNames ];
123
+export function getButtonAttributesByProps(props: Object = {})
124
+        : MapOfAttributes {
125
+    let classNames = props.classNames;
126
+
127
+    if (classNames) {
128
+        // XXX Make sure to not modify props.classNames because that'd be bad
129
+        // practice.
130
+        classNames = [ ...classNames ];
131
+    }
123
 
132
 
124
     props.toggled && classNames.push('toggled');
133
     props.toggled && classNames.push('toggled');
125
     props.unclickable && classNames.push('unclickable');
134
     props.unclickable && classNames.push('unclickable');
142
     return result;
151
     return result;
143
 }
152
 }
144
 
153
 
154
+/* eslint-enable flowtype/space-before-type-colon */
155
+
145
 /**
156
 /**
146
- * Returns object containing default buttons for the primary and secondary
147
- * toolbars.
157
+ * Returns an object which contains the default buttons for the primary and
158
+ * secondary toolbars.
148
  *
159
  *
149
  * @returns {Object}
160
  * @returns {Object}
150
  */
161
  */
151
-export function getDefaultToolbarButtons(): Object {
162
+export function getDefaultToolboxButtons(): Object {
152
     let toolbarButtons = {
163
     let toolbarButtons = {
153
         primaryToolbarButtons: new Map(),
164
         primaryToolbarButtons: new Map(),
154
         secondaryToolbarButtons: new Map()
165
         secondaryToolbarButtons: new Map()

+ 27
- 8
react/features/toolbox/reducer.js 查看文件

4
 
4
 
5
 import {
5
 import {
6
     CLEAR_TOOLBOX_TIMEOUT,
6
     CLEAR_TOOLBOX_TIMEOUT,
7
+    SET_DEFAULT_TOOLBOX_BUTTONS,
7
     SET_TOOLBOX_ALWAYS_VISIBLE,
8
     SET_TOOLBOX_ALWAYS_VISIBLE,
8
     SET_SUBJECT,
9
     SET_SUBJECT,
9
     SET_SUBJECT_SLIDE_IN,
10
     SET_SUBJECT_SLIDE_IN,
13
     SET_TOOLBOX_TIMEOUT_MS,
14
     SET_TOOLBOX_TIMEOUT_MS,
14
     SET_TOOLBOX_VISIBLE
15
     SET_TOOLBOX_VISIBLE
15
 } from './actionTypes';
16
 } from './actionTypes';
16
-import { getDefaultToolbarButtons } from './functions';
17
 
17
 
18
 declare var interfaceConfig: Object;
18
 declare var interfaceConfig: Object;
19
 
19
 
43
     }
43
     }
44
 
44
 
45
     return {
45
     return {
46
-        ...getDefaultToolbarButtons(),
47
-
48
         /**
46
         /**
49
          * The indicator which determines whether the Toolbox should always be
47
          * The indicator which determines whether the Toolbox should always be
50
          * visible.
48
          * visible.
61
          */
59
          */
62
         hovered: false,
60
         hovered: false,
63
 
61
 
62
+        /**
63
+         * A Map of the default buttons of the PrimaryToolbar.
64
+         *
65
+         * @type {Map}
66
+         */
67
+        primaryToolbarButtons: new Map(),
68
+
69
+        /**
70
+         * A Map of the default buttons of the SecondaryToolbar.
71
+         *
72
+         * @type {Map}
73
+         */
74
+        secondaryToolbarButtons: new Map(),
75
+
64
         /**
76
         /**
65
          * The text of the conference subject.
77
          * The text of the conference subject.
66
          *
78
          *
110
                 timeoutID: undefined
122
                 timeoutID: undefined
111
             };
123
             };
112
 
124
 
125
+        case SET_DEFAULT_TOOLBOX_BUTTONS: {
126
+            const { primaryToolbarButtons, secondaryToolbarButtons } = action;
127
+
128
+            return {
129
+                ...state,
130
+                primaryToolbarButtons,
131
+                secondaryToolbarButtons
132
+            };
133
+        }
134
+
113
         case SET_TOOLBOX_ALWAYS_VISIBLE:
135
         case SET_TOOLBOX_ALWAYS_VISIBLE:
114
             return {
136
             return {
115
                 ...state,
137
                 ...state,
170
  * @private
192
  * @private
171
  * @returns {Object}
193
  * @returns {Object}
172
  */
194
  */
173
-function _setButton(state, { buttonName, button }): Object {
174
-    const {
175
-        primaryToolbarButtons,
176
-        secondaryToolbarButtons
177
-    } = state;
195
+function _setButton(state, { button, buttonName }): Object {
196
+    const { primaryToolbarButtons, secondaryToolbarButtons } = state;
178
     let selectedButton = primaryToolbarButtons.get(buttonName);
197
     let selectedButton = primaryToolbarButtons.get(buttonName);
179
     let place = 'primaryToolbarButtons';
198
     let place = 'primaryToolbarButtons';
180
 
199
 

正在加载...
取消
保存