Sfoglia il codice sorgente

Implements a filmstrip-only mode for the toolbox

j8
yanas 8 anni fa
parent
commit
77b789e26a

+ 31
- 9
css/_toolbars.scss Vedi File

19
     vertical-align: middle;
19
     vertical-align: middle;
20
 }
20
 }
21
 
21
 
22
-/**
23
-* Toolbar button styles.
24
-*/
22
+ /**
23
+  * Toolbar button styles.
24
+  */
25
 .button {
25
 .button {
26
     color: #FFFFFF;
26
     color: #FFFFFF;
27
     cursor: pointer;
27
     cursor: pointer;
97
 }
97
 }
98
 
98
 
99
 /**
99
 /**
100
-* Common toolbar styles.
101
-*/
100
+ * Common toolbar styles.
101
+ */
102
 .toolbar {
102
 .toolbar {
103
     background-color: $toolbarBackground;
103
     background-color: $toolbarBackground;
104
     height: 100%;
104
     height: 100%;
119
     }
119
     }
120
 
120
 
121
     /**
121
     /**
122
-    * Primary toolbar styles.
123
-    */
122
+     * Primary toolbar styles.
123
+     */
124
     &_primary {
124
     &_primary {
125
         position: absolute;
125
         position: absolute;
126
         left: 50%;
126
         left: 50%;
148
     }
148
     }
149
 
149
 
150
     /**
150
     /**
151
-    * Secondary toolbar styles.
152
-    */
151
+     * Secondary toolbar styles.
152
+     */
153
     &_secondary {
153
     &_secondary {
154
         position: absolute;
154
         position: absolute;
155
         align-items: center;
155
         align-items: center;
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
      * Toolbar specific round badge.
212
      * Toolbar specific round badge.
191
      */
213
      */

+ 11
- 10
react/features/toolbox/actions.web.js Vedi File

233
  */
233
  */
234
 export function showToolbox(timeout: number = 0): Object {
234
 export function showToolbox(timeout: number = 0): Object {
235
     return (dispatch: Dispatch<*>, getState: Function) => {
235
     return (dispatch: Dispatch<*>, getState: Function) => {
236
-        if (interfaceConfig.filmStripOnly) {
237
-            return;
238
-        }
239
-
240
         const state = getState();
236
         const state = getState();
241
-        const { timeoutMS, visible } = state['features/toolbox'];
237
+        const { alwaysVisible, timeoutMS, visible } = state['features/toolbox'];
242
 
238
 
243
         if (!visible) {
239
         if (!visible) {
244
             dispatch(setToolboxVisible(true));
240
             dispatch(setToolboxVisible(true));
245
             dispatch(setSubjectSlideIn(true));
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 Vedi File

101
      *
101
      *
102
      * @returns {ReactElement}
102
      * @returns {ReactElement}
103
      */
103
      */
104
-    render() {
105
-        const { buttonHandlers, splitterIndex } = this.state;
104
+    render(): ReactElement<*> | null {
106
         const { _primaryToolbarButtons } = this.props;
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
         const { primaryToolbarClassName } = getToolbarClassNames(this.props);
115
         const { primaryToolbarClassName } = getToolbarClassNames(this.props);
108
 
116
 
109
         return (
117
         return (

+ 10
- 2
react/features/toolbox/components/SecondaryToolbar.web.js Vedi File

150
      *
150
      *
151
      * @returns {ReactElement}
151
      * @returns {ReactElement}
152
      */
152
      */
153
-    render(): ReactElement<*> {
154
-        const { buttonHandlers } = this.state;
153
+    render(): ReactElement<*> | null {
155
         const { _secondaryToolbarButtons } = this.props;
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
         const { secondaryToolbarClassName } = getToolbarClassNames(this.props);
164
         const { secondaryToolbarClassName } = getToolbarClassNames(this.props);
157
 
165
 
158
         return (
166
         return (

+ 9
- 4
react/features/toolbox/components/Toolbar.web.js Vedi File

8
 } from '../actions';
8
 } from '../actions';
9
 import ToolbarButton from './ToolbarButton';
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
  * Implements a toolbar in React/Web. It is a strip that contains a set of
12
  * Implements a toolbar in React/Web. It is a strip that contains a set of
17
  * toolbar items such as buttons. Toolbar is commonly placed inside of a
13
  * toolbar items such as buttons. Toolbar is commonly placed inside of a
153
             toolbarButtons
149
             toolbarButtons
154
         } = this.props;
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
         Object.keys(buttonHandlers).forEach(key => {
161
         Object.keys(buttonHandlers).forEach(key => {
157
             let button = toolbarButtons.get(key);
162
             let button = toolbarButtons.get(key);
158
 
163
 

+ 24
- 7
react/features/toolbox/components/Toolbox.web.js Vedi File

31
      * @static
31
      * @static
32
      */
32
      */
33
     static propTypes = {
33
     static propTypes = {
34
+        /**
35
+         * Indicates if the toolbox should always be visible.
36
+         */
37
+        _alwaysVisible: React.PropTypes.bool,
38
+
34
         /**
39
         /**
35
          * Handler dispatching setting default buttons action.
40
          * Handler dispatching setting default buttons action.
36
          */
41
          */
159
      * @private
164
      * @private
160
      */
165
      */
161
     _renderToolbars(): ReactElement<*> | null {
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
             return null;
170
             return null;
165
         }
171
         }
166
 
172
 
202
          * @returns {Object} Dispatched action.
208
          * @returns {Object} Dispatched action.
203
          */
209
          */
204
         _setToolboxAlwaysVisible() {
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
  * @param {Object} state - Redux state.
221
  * @param {Object} state - Redux state.
215
  * @private
222
  * @private
216
  * @returns {{
223
  * @returns {{
224
+ *     _alwaysVisible: boolean,
217
  *     _audioMuted: boolean,
225
  *     _audioMuted: boolean,
218
  *     _locked: boolean,
226
  *     _locked: boolean,
219
  *     _subjectSlideIn: boolean,
227
  *     _subjectSlideIn: boolean,
222
  */
230
  */
223
 function _mapStateToProps(state: Object): Object {
231
 function _mapStateToProps(state: Object): Object {
224
     const {
232
     const {
233
+        alwaysVisible,
225
         subject,
234
         subject,
226
         subjectSlideIn,
235
         subjectSlideIn,
227
         timeoutID
236
         timeoutID
230
     return {
239
     return {
231
         ...abstractMapStateToProps(state),
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
          * Property containing conference subject.
251
          * Property containing conference subject.
235
          *
252
          *
236
-         * @protected
253
+         * @private
237
          * @type {string}
254
          * @type {string}
238
          */
255
          */
239
         _subject: subject,
256
         _subject: subject,
241
         /**
258
         /**
242
          * Flag showing whether to set subject slide in animation.
259
          * Flag showing whether to set subject slide in animation.
243
          *
260
          *
244
-         * @protected
261
+         * @private
245
          * @type {boolean}
262
          * @type {boolean}
246
          */
263
          */
247
         _subjectSlideIn: subjectSlideIn,
264
         _subjectSlideIn: subjectSlideIn,
249
         /**
266
         /**
250
          * Property containing toolbox timeout id.
267
          * Property containing toolbox timeout id.
251
          *
268
          *
252
-         * @protected
269
+         * @private
253
          * @type {number}
270
          * @type {number}
254
          */
271
          */
255
         _timeoutID: timeoutID
272
         _timeoutID: timeoutID

+ 3
- 0
react/features/toolbox/defaultToolbarButtons.js Vedi File

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

+ 13
- 2
react/features/toolbox/functions.js Vedi File

167
 
167
 
168
     if (typeof interfaceConfig !== 'undefined'
168
     if (typeof interfaceConfig !== 'undefined'
169
             && interfaceConfig.TOOLBAR_BUTTONS) {
169
             && interfaceConfig.TOOLBAR_BUTTONS) {
170
+        const { filmStripOnly } = interfaceConfig;
171
+
170
         toolbarButtons
172
         toolbarButtons
171
             = interfaceConfig.TOOLBAR_BUTTONS.reduce(
173
             = interfaceConfig.TOOLBAR_BUTTONS.reduce(
172
                 (acc, buttonName) => {
174
                 (acc, buttonName) => {
176
                         const place = _getToolbarButtonPlace(buttonName);
178
                         const place = _getToolbarButtonPlace(buttonName);
177
 
179
 
178
                         button.buttonName = buttonName;
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
                     return acc;
189
                     return acc;
210
  * @private
217
  * @private
211
  */
218
  */
212
 export function getToolbarClassNames(props: Object) {
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
     const secondaryToolbarClassNames = [ 'toolbar_secondary' ];
225
     const secondaryToolbarClassNames = [ 'toolbar_secondary' ];
215
 
226
 
216
     if (props._visible) {
227
     if (props._visible) {

+ 12
- 0
react/features/toolbox/reducer.js Vedi File

207
         ...button
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
     const updatedToolbar = state[place].set(buttonName, selectedButton);
222
     const updatedToolbar = state[place].set(buttonName, selectedButton);
211
 
223
 
212
     return {
224
     return {

Loading…
Annulla
Salva