Переглянути джерело

Implements a filmstrip-only mode for the toolbox

j8
yanas 8 роки тому
джерело
коміт
77b789e26a

+ 31
- 9
css/_toolbars.scss Переглянути файл

@@ -19,9 +19,9 @@
19 19
     vertical-align: middle;
20 20
 }
21 21
 
22
-/**
23
-* Toolbar button styles.
24
-*/
22
+ /**
23
+  * Toolbar button styles.
24
+  */
25 25
 .button {
26 26
     color: #FFFFFF;
27 27
     cursor: pointer;
@@ -97,8 +97,8 @@
97 97
 }
98 98
 
99 99
 /**
100
-* Common toolbar styles.
101
-*/
100
+ * Common toolbar styles.
101
+ */
102 102
 .toolbar {
103 103
     background-color: $toolbarBackground;
104 104
     height: 100%;
@@ -119,8 +119,8 @@
119 119
     }
120 120
 
121 121
     /**
122
-    * Primary toolbar styles.
123
-    */
122
+     * Primary toolbar styles.
123
+     */
124 124
     &_primary {
125 125
         position: absolute;
126 126
         left: 50%;
@@ -148,8 +148,8 @@
148 148
     }
149 149
 
150 150
     /**
151
-    * Secondary toolbar styles.
152
-    */
151
+     * Secondary toolbar styles.
152
+     */
153 153
     &_secondary {
154 154
         position: absolute;
155 155
         align-items: center;
@@ -186,6 +186,28 @@
186 186
         }
187 187
     }
188 188
 
189
+    /**
190
+     * Styles the toolbar in filmstrip-only mode.
191
+     */
192
+    &_filmstrip-only {
193
+        border-radius: 3px;
194
+        bottom: 0;
195
+        display: inline-block;
196
+        height: auto;
197
+        position: absolute;
198
+        right: 0;
199
+        width: $defaultToolbarSize;
200
+
201
+        .button:first-child {
202
+            border-top-left-radius: 3px;
203
+            border-top-right-radius: 3px;
204
+        }
205
+        .button:last-child {
206
+            border-bottom-right-radius: 3px;
207
+            border-bottom-left-radius: 3px;
208
+        }
209
+    }
210
+
189 211
     /**
190 212
      * Toolbar specific round badge.
191 213
      */

+ 11
- 10
react/features/toolbox/actions.web.js Переглянути файл

@@ -233,21 +233,22 @@ export function showSIPCallButton(show: boolean): Function {
233 233
  */
234 234
 export function showToolbox(timeout: number = 0): Object {
235 235
     return (dispatch: Dispatch<*>, getState: Function) => {
236
-        if (interfaceConfig.filmStripOnly) {
237
-            return;
238
-        }
239
-
240 236
         const state = getState();
241
-        const { timeoutMS, visible } = state['features/toolbox'];
237
+        const { alwaysVisible, timeoutMS, visible } = state['features/toolbox'];
242 238
 
243 239
         if (!visible) {
244 240
             dispatch(setToolboxVisible(true));
245 241
             dispatch(setSubjectSlideIn(true));
246
-            dispatch(
247
-                setToolboxTimeout(
248
-                    () => dispatch(hideToolbox()),
249
-                    timeout || timeoutMS));
250
-            dispatch(setToolboxTimeoutMS(interfaceConfig.TOOLBAR_TIMEOUT));
242
+
243
+            // If the Toolbox is always visible, there's no need for a timeout
244
+            // to toggle its visibility.
245
+            if (!alwaysVisible) {
246
+                dispatch(
247
+                    setToolboxTimeout(
248
+                        () => dispatch(hideToolbox()),
249
+                        timeout || timeoutMS));
250
+                dispatch(setToolboxTimeoutMS(interfaceConfig.TOOLBAR_TIMEOUT));
251
+            }
251 252
         }
252 253
     };
253 254
 }

+ 10
- 2
react/features/toolbox/components/PrimaryToolbar.web.js Переглянути файл

@@ -101,9 +101,17 @@ class PrimaryToolbar extends Component {
101 101
      *
102 102
      * @returns {ReactElement}
103 103
      */
104
-    render() {
105
-        const { buttonHandlers, splitterIndex } = this.state;
104
+    render(): ReactElement<*> | null {
106 105
         const { _primaryToolbarButtons } = this.props;
106
+
107
+        // The number of buttons to show in the toolbar isn't fixed, it depends
108
+        // on availability of features and configuration parameters, so if we
109
+        // don't have anything to render we exit here.
110
+        if (_primaryToolbarButtons.size === 0) {
111
+            return null;
112
+        }
113
+
114
+        const { buttonHandlers, splitterIndex } = this.state;
107 115
         const { primaryToolbarClassName } = getToolbarClassNames(this.props);
108 116
 
109 117
         return (

+ 10
- 2
react/features/toolbox/components/SecondaryToolbar.web.js Переглянути файл

@@ -150,9 +150,17 @@ class SecondaryToolbar extends Component {
150 150
      *
151 151
      * @returns {ReactElement}
152 152
      */
153
-    render(): ReactElement<*> {
154
-        const { buttonHandlers } = this.state;
153
+    render(): ReactElement<*> | null {
155 154
         const { _secondaryToolbarButtons } = this.props;
155
+
156
+        // The number of buttons to show in the toolbar isn't fixed, it depends
157
+        // on availability of features and configuration parameters, so if we
158
+        // don't have anything to render we exit here.
159
+        if (_secondaryToolbarButtons.size === 0) {
160
+            return null;
161
+        }
162
+
163
+        const { buttonHandlers } = this.state;
156 164
         const { secondaryToolbarClassName } = getToolbarClassNames(this.props);
157 165
 
158 166
         return (

+ 9
- 4
react/features/toolbox/components/Toolbar.web.js Переглянути файл

@@ -8,10 +8,6 @@ import {
8 8
 } from '../actions';
9 9
 import ToolbarButton from './ToolbarButton';
10 10
 
11
-declare var APP: Object;
12
-declare var config: Object;
13
-declare var interfaceConfig: Object;
14
-
15 11
 /**
16 12
  * Implements a toolbar in React/Web. It is a strip that contains a set of
17 13
  * toolbar items such as buttons. Toolbar is commonly placed inside of a
@@ -153,6 +149,15 @@ class Toolbar extends Component {
153 149
             toolbarButtons
154 150
         } = this.props;
155 151
 
152
+        // Only a few buttons have custom button handlers defined, so this
153
+        // list may be undefined or empty depending on the buttons we're
154
+        // rendering.
155
+        // TODO: merge the buttonHandlers and onClick properties and come up
156
+        // with a consistent event handling property.
157
+        if (!buttonHandlers) {
158
+            return;
159
+        }
160
+
156 161
         Object.keys(buttonHandlers).forEach(key => {
157 162
             let button = toolbarButtons.get(key);
158 163
 

+ 24
- 7
react/features/toolbox/components/Toolbox.web.js Переглянути файл

@@ -31,6 +31,11 @@ class Toolbox extends Component {
31 31
      * @static
32 32
      */
33 33
     static propTypes = {
34
+        /**
35
+         * Indicates if the toolbox should always be visible.
36
+         */
37
+        _alwaysVisible: React.PropTypes.bool,
38
+
34 39
         /**
35 40
          * Handler dispatching setting default buttons action.
36 41
          */
@@ -159,8 +164,9 @@ class Toolbox extends Component {
159 164
      * @private
160 165
      */
161 166
     _renderToolbars(): ReactElement<*> | null {
162
-        // The toolbars should not be shown until timeoutID is initialized.
163
-        if (this.props._timeoutID === null) {
167
+        // In case we're not in alwaysVisible mode the toolbox should not be
168
+        // shown until timeoutID is initialized.
169
+        if (!this.props._alwaysVisible && this.props._timeoutID === null) {
164 170
             return null;
165 171
         }
166 172
 
@@ -202,8 +208,9 @@ function _mapDispatchToProps(dispatch: Function): Object {
202 208
          * @returns {Object} Dispatched action.
203 209
          */
204 210
         _setToolboxAlwaysVisible() {
205
-            dispatch(
206
-                setToolboxAlwaysVisible(config.alwaysVisibleToolbar === true));
211
+            dispatch(setToolboxAlwaysVisible(
212
+                config.alwaysVisibleToolbar === true
213
+                    || interfaceConfig.filmStripOnly));
207 214
         }
208 215
     };
209 216
 }
@@ -214,6 +221,7 @@ function _mapDispatchToProps(dispatch: Function): Object {
214 221
  * @param {Object} state - Redux state.
215 222
  * @private
216 223
  * @returns {{
224
+ *     _alwaysVisible: boolean,
217 225
  *     _audioMuted: boolean,
218 226
  *     _locked: boolean,
219 227
  *     _subjectSlideIn: boolean,
@@ -222,6 +230,7 @@ function _mapDispatchToProps(dispatch: Function): Object {
222 230
  */
223 231
 function _mapStateToProps(state: Object): Object {
224 232
     const {
233
+        alwaysVisible,
225 234
         subject,
226 235
         subjectSlideIn,
227 236
         timeoutID
@@ -230,10 +239,18 @@ function _mapStateToProps(state: Object): Object {
230 239
     return {
231 240
         ...abstractMapStateToProps(state),
232 241
 
242
+        /**
243
+         * Indicates if the toolbox should always be visible.
244
+         *
245
+         * @private
246
+         * @type {boolean}
247
+         */
248
+        _alwaysVisible: alwaysVisible,
249
+
233 250
         /**
234 251
          * Property containing conference subject.
235 252
          *
236
-         * @protected
253
+         * @private
237 254
          * @type {string}
238 255
          */
239 256
         _subject: subject,
@@ -241,7 +258,7 @@ function _mapStateToProps(state: Object): Object {
241 258
         /**
242 259
          * Flag showing whether to set subject slide in animation.
243 260
          *
244
-         * @protected
261
+         * @private
245 262
          * @type {boolean}
246 263
          */
247 264
         _subjectSlideIn: subjectSlideIn,
@@ -249,7 +266,7 @@ function _mapStateToProps(state: Object): Object {
249 266
         /**
250 267
          * Property containing toolbox timeout id.
251 268
          *
252
-         * @protected
269
+         * @private
253 270
          * @type {number}
254 271
          */
255 272
         _timeoutID: timeoutID

+ 3
- 0
react/features/toolbox/defaultToolbarButtons.js Переглянути файл

@@ -46,6 +46,7 @@ export default {
46 46
     camera: {
47 47
         classNames: [ 'button', 'icon-camera' ],
48 48
         enabled: true,
49
+        filmstripOnlyEnabled: true,
49 50
         id: 'toolbar_button_camera',
50 51
         onClick() {
51 52
             if (APP.conference.videoMuted) {
@@ -203,6 +204,7 @@ export default {
203 204
     hangup: {
204 205
         classNames: [ 'button', 'icon-hangup', 'button_hangup' ],
205 206
         enabled: true,
207
+        filmstripOnlyEnabled: true,
206 208
         id: 'toolbar_button_hangup',
207 209
         onClick() {
208 210
             JitsiMeetJS.analytics.sendEvent('toolbar.hangup');
@@ -231,6 +233,7 @@ export default {
231 233
     microphone: {
232 234
         classNames: [ 'button', 'icon-microphone' ],
233 235
         enabled: true,
236
+        filmstripOnlyEnabled: true,
234 237
         id: 'toolbar_button_mute',
235 238
         onClick() {
236 239
             const sharedVideoManager = APP.UI.getSharedVideoManager();

+ 13
- 2
react/features/toolbox/functions.js Переглянути файл

@@ -167,6 +167,8 @@ export function getDefaultToolboxButtons(): Object {
167 167
 
168 168
     if (typeof interfaceConfig !== 'undefined'
169 169
             && interfaceConfig.TOOLBAR_BUTTONS) {
170
+        const { filmStripOnly } = interfaceConfig;
171
+
170 172
         toolbarButtons
171 173
             = interfaceConfig.TOOLBAR_BUTTONS.reduce(
172 174
                 (acc, buttonName) => {
@@ -176,7 +178,12 @@ export function getDefaultToolboxButtons(): Object {
176 178
                         const place = _getToolbarButtonPlace(buttonName);
177 179
 
178 180
                         button.buttonName = buttonName;
179
-                        acc[place].set(buttonName, button);
181
+
182
+                        // In filmstrip-only mode we only add a button if it's
183
+                        // filmstrip-only enabled.
184
+                        if (!filmStripOnly || button.filmstripOnlyEnabled) {
185
+                            acc[place].set(buttonName, button);
186
+                        }
180 187
                     }
181 188
 
182 189
                     return acc;
@@ -210,7 +217,11 @@ function _getToolbarButtonPlace(btn) {
210 217
  * @private
211 218
  */
212 219
 export function getToolbarClassNames(props: Object) {
213
-    const primaryToolbarClassNames = [ 'toolbar_primary' ];
220
+    const primaryToolbarClassNames = [
221
+        interfaceConfig.filmStripOnly
222
+            ? 'toolbar_filmstrip-only'
223
+            : 'toolbar_primary'
224
+    ];
214 225
     const secondaryToolbarClassNames = [ 'toolbar_secondary' ];
215 226
 
216 227
     if (props._visible) {

+ 12
- 0
react/features/toolbox/reducer.js Переглянути файл

@@ -207,6 +207,18 @@ function _setButton(state, { button, buttonName }): Object {
207 207
         ...button
208 208
     };
209 209
 
210
+    // In filmstrip-only mode we only show buttons if they're filmstrip-only
211
+    // enabled, so we don't need to update if this isn't the case.
212
+    // FIXME A reducer should be a pure function of the current state and the
213
+    // specified action so it should not use the global variable
214
+    // interfaceConfig. Anyway, we'll move interfaceConfig into the (redux)
215
+    // store so we'll surely revisit the source code bellow.
216
+    if (interfaceConfig.filmStripOnly && !selectedButton.filmstripOnlyEnabled) {
217
+        return {
218
+            ...state
219
+        };
220
+    }
221
+
210 222
     const updatedToolbar = state[place].set(buttonName, selectedButton);
211 223
 
212 224
     return {

Завантаження…
Відмінити
Зберегти