Parcourir la source

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.
j8
Ilya Daynatovich il y a 8 ans
Parent
révision
bcbdaaa6ea

+ 12
- 0
react/features/toolbox/actionTypes.js Voir le fichier

@@ -9,6 +9,18 @@ import { Symbol } from '../base/react';
9 9
  */
10 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 25
  * The type of the action which sets the permanent visibility of the Toolbox.
14 26
  *

+ 34
- 16
react/features/toolbox/actions.native.js Voir le fichier

@@ -4,6 +4,7 @@ import type { Dispatch } from 'redux-thunk';
4 4
 
5 5
 import {
6 6
     CLEAR_TOOLBOX_TIMEOUT,
7
+    SET_DEFAULT_TOOLBOX_BUTTONS,
7 8
     SET_TOOLBOX_ALWAYS_VISIBLE,
8 9
     SET_SUBJECT,
9 10
     SET_SUBJECT_SLIDE_IN,
@@ -13,6 +14,7 @@ import {
13 14
     SET_TOOLBOX_TIMEOUT_MS,
14 15
     SET_TOOLBOX_VISIBLE
15 16
 } from './actionTypes';
17
+import { getDefaultToolboxButtons } from './functions';
16 18
 
17 19
 /**
18 20
  * Event handler for local raise hand changed event.
@@ -46,22 +48,6 @@ export function clearToolboxTimeout(): Object {
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 52
  * Enables/disables audio toolbar button.
67 53
  *
@@ -83,6 +69,22 @@ export function setAudioIconEnabled(enabled: boolean = false): Function {
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 89
  * Signals that value of conference subject should be changed.
88 90
  *
@@ -148,6 +150,22 @@ export function setToolbarHovered(hovered: boolean): Object {
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 169
 /* eslint-disable flowtype/space-before-type-colon */
152 170
 
153 171
 /**

+ 33
- 2
react/features/toolbox/components/Toolbox.web.js Voir le fichier

@@ -5,7 +5,10 @@ import { connect } from 'react-redux';
5 5
 
6 6
 import UIEvents from '../../../../service/UI/UIEvents';
7 7
 
8
-import { setToolboxAlwaysVisible } from '../actions';
8
+import {
9
+    setDefaultToolboxButtons,
10
+    setToolboxAlwaysVisible
11
+} from '../actions';
9 12
 import {
10 13
     abstractMapStateToProps,
11 14
     showCustomToolbarPopup
@@ -28,6 +31,11 @@ class Toolbox extends Component {
28 31
      * @static
29 32
      */
30 33
     static propTypes = {
34
+        /**
35
+         * Handler dispatching setting default buttons action.
36
+         */
37
+        _setDefaultToolboxButtons: React.PropTypes.func,
38
+
31 39
         /**
32 40
          * Handler dispatching reset always visible toolbox action.
33 41
          */
@@ -61,6 +69,19 @@ class Toolbox extends Component {
61 69
         APP.UI.addListener(
62 70
             UIEvents.SHOW_CUSTOM_TOOLBAR_BUTTON_POPUP,
63 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,15 +179,25 @@ class Toolbox extends Component {
158 179
  *
159 180
  * @param {Function} dispatch - Redux action dispatcher.
160 181
  * @returns {{
182
+ *     _setDefaultToolboxButtons: Function,
161 183
  *     _setToolboxAlwaysVisible: Function
162 184
  * }}
163 185
  * @private
164 186
  */
165 187
 function _mapDispatchToProps(dispatch: Function): Object {
166 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 202
          * @returns {Object} Dispatched action.
172 203
          */

+ 16
- 5
react/features/toolbox/functions.js Voir le fichier

@@ -112,14 +112,23 @@ export function abstractMapStateToProps(state: Object): Object {
112 112
     };
113 113
 }
114 114
 
115
+/* eslint-disable flowtype/space-before-type-colon */
116
+
115 117
 /**
116 118
  * Takes toolbar button props and maps them to HTML attributes to set.
117 119
  *
118 120
  * @param {Object} props - Props set to the React component.
119 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 133
     props.toggled && classNames.push('toggled');
125 134
     props.unclickable && classNames.push('unclickable');
@@ -142,13 +151,15 @@ export function getButtonAttributesByProps(props: Object): MapOfAttributes {
142 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 160
  * @returns {Object}
150 161
  */
151
-export function getDefaultToolbarButtons(): Object {
162
+export function getDefaultToolboxButtons(): Object {
152 163
     let toolbarButtons = {
153 164
         primaryToolbarButtons: new Map(),
154 165
         secondaryToolbarButtons: new Map()

+ 27
- 8
react/features/toolbox/reducer.js Voir le fichier

@@ -4,6 +4,7 @@ import { ReducerRegistry } from '../base/redux';
4 4
 
5 5
 import {
6 6
     CLEAR_TOOLBOX_TIMEOUT,
7
+    SET_DEFAULT_TOOLBOX_BUTTONS,
7 8
     SET_TOOLBOX_ALWAYS_VISIBLE,
8 9
     SET_SUBJECT,
9 10
     SET_SUBJECT_SLIDE_IN,
@@ -13,7 +14,6 @@ import {
13 14
     SET_TOOLBOX_TIMEOUT_MS,
14 15
     SET_TOOLBOX_VISIBLE
15 16
 } from './actionTypes';
16
-import { getDefaultToolbarButtons } from './functions';
17 17
 
18 18
 declare var interfaceConfig: Object;
19 19
 
@@ -43,8 +43,6 @@ function _getInitialState() {
43 43
     }
44 44
 
45 45
     return {
46
-        ...getDefaultToolbarButtons(),
47
-
48 46
         /**
49 47
          * The indicator which determines whether the Toolbox should always be
50 48
          * visible.
@@ -61,6 +59,20 @@ function _getInitialState() {
61 59
          */
62 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 77
          * The text of the conference subject.
66 78
          *
@@ -110,6 +122,16 @@ ReducerRegistry.register(
110 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 135
         case SET_TOOLBOX_ALWAYS_VISIBLE:
114 136
             return {
115 137
                 ...state,
@@ -170,11 +192,8 @@ ReducerRegistry.register(
170 192
  * @private
171 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 197
     let selectedButton = primaryToolbarButtons.get(buttonName);
179 198
     let place = 'primaryToolbarButtons';
180 199
 

Chargement…
Annuler
Enregistrer