Bläddra i källkod

android: enter PiP mode when pressing back button

When in a conference, try to enter PiP when pressing the back button. If this is
not possible (because it's unsupported, not enabled, etc.) fall back to the
previous behavior of simply hanging up.
master
Saúl Ibarra Corretgé 6 år sedan
förälder
incheckning
cb3419ba2a
1 ändrade filer med 67 tillägg och 66 borttagningar
  1. 67
    66
      react/features/conference/components/native/Conference.js

+ 67
- 66
react/features/conference/components/native/Conference.js Visa fil

@@ -1,13 +1,13 @@
1 1
 // @flow
2 2
 
3 3
 import React from 'react';
4
-
5
-import { BackHandler, SafeAreaView, StatusBar, View } from 'react-native';
4
+import { BackHandler, NativeModules, SafeAreaView, StatusBar, View } from 'react-native';
6 5
 
7 6
 import { appNavigate } from '../../../app';
7
+import { getAppProp } from '../../../base/app';
8 8
 import { getParticipantCount } from '../../../base/participants';
9 9
 import { Container, LoadingIndicator, TintedView } from '../../../base/react';
10
-import { connect as reactReduxConnect } from '../../../base/redux';
10
+import { connect } from '../../../base/redux';
11 11
 import {
12 12
     isNarrowAspectRatio,
13 13
     makeAspectRatioAware
@@ -65,22 +65,18 @@ type Props = AbstractProps & {
65 65
     _largeVideoParticipantId: string,
66 66
 
67 67
     /**
68
-     * Handles a hardware button press for back navigation. Leaves the
69
-     * associated {@code Conference}.
68
+     * The number of participants in the conference.
70 69
      *
71 70
      * @private
72
-     * @returns {boolean} As the associated conference is unconditionally left
73
-     * and exiting the app while it renders a {@code Conference} is undesired,
74
-     * {@code true} is always returned.
75 71
      */
76
-    _onHardwareBackPress: Function,
72
+    _participantCount: number,
77 73
 
78 74
     /**
79
-     * The number of participants in the conference.
75
+     * Whether Picture-in-Picture is enabled.
80 76
      *
81 77
      * @private
82 78
      */
83
-    _participantCount: number,
79
+    _pictureInPictureEnabled: boolean,
84 80
 
85 81
     /**
86 82
      * The indicator which determines whether the UI is reduced (to accommodate
@@ -113,7 +109,12 @@ type Props = AbstractProps & {
113 109
      *
114 110
      * @private
115 111
      */
116
-    _toolboxAlwaysVisible: boolean
112
+    _toolboxAlwaysVisible: boolean,
113
+
114
+    /**
115
+     * The redux {@code dispatch} function.
116
+     */
117
+    dispatch: Function
117 118
 };
118 119
 
119 120
 /**
@@ -131,6 +132,8 @@ class Conference extends AbstractConference<Props, *> {
131 132
 
132 133
         // Bind event handlers so they are only bound once per instance.
133 134
         this._onClick = this._onClick.bind(this);
135
+        this._onHardwareBackPress = this._onHardwareBackPress.bind(this);
136
+        this._setToolboxVisible = this._setToolboxVisible.bind(this);
134 137
     }
135 138
 
136 139
     /**
@@ -141,15 +144,11 @@ class Conference extends AbstractConference<Props, *> {
141 144
      * @returns {void}
142 145
      */
143 146
     componentDidMount() {
144
-        BackHandler.addEventListener(
145
-            'hardwareBackPress',
146
-            this.props._onHardwareBackPress);
147
+        BackHandler.addEventListener('hardwareBackPress', this._onHardwareBackPress);
147 148
 
148 149
         // Show the toolbox if we are the only participant; otherwise, the whole
149 150
         // UI looks too unpopulated the LargeVideo visible.
150
-        const { _participantCount, _setToolboxVisible } = this.props;
151
-
152
-        _participantCount === 1 && _setToolboxVisible(true);
151
+        this.props._participantCount === 1 && this._setToolboxVisible(true);
153 152
     }
154 153
 
155 154
     /**
@@ -163,18 +162,17 @@ class Conference extends AbstractConference<Props, *> {
163 162
         } = prevProps;
164 163
         const {
165 164
             _participantCount: newParticipantCount,
166
-            _setToolboxVisible,
167 165
             _toolboxVisible
168 166
         } = this.props;
169 167
 
170 168
         if (oldParticipantCount === 1
171 169
                 && newParticipantCount > 1
172 170
                 && _toolboxVisible) {
173
-            _setToolboxVisible(false);
171
+            this._setToolboxVisible(false);
174 172
         } else if (oldParticipantCount > 1
175 173
                 && newParticipantCount === 1
176 174
                 && !_toolboxVisible) {
177
-            _setToolboxVisible(true);
175
+            this._setToolboxVisible(true);
178 176
         }
179 177
     }
180 178
 
@@ -188,9 +186,7 @@ class Conference extends AbstractConference<Props, *> {
188 186
      */
189 187
     componentWillUnmount() {
190 188
         // Tear handling any hardware button presses for back navigation down.
191
-        BackHandler.removeEventListener(
192
-            'hardwareBackPress',
193
-            this.props._onHardwareBackPress);
189
+        BackHandler.removeEventListener('hardwareBackPress', this._onHardwareBackPress);
194 190
     }
195 191
 
196 192
     /**
@@ -299,9 +295,33 @@ class Conference extends AbstractConference<Props, *> {
299 295
             return;
300 296
         }
301 297
 
302
-        const toolboxVisible = !this.props._toolboxVisible;
298
+        this._setToolboxVisible(!this.props._toolboxVisible);
299
+    }
300
+
301
+    _onHardwareBackPress: () => boolean;
302
+
303
+    /**
304
+     * Handles a hardware button press for back navigation. Enters Picture-in-Picture mode
305
+     * (if supported) or leaves the associated {@code Conference} otherwise.
306
+     *
307
+     * @returns {boolean} Exiting the app is undesired, so {@code true} is always returned.
308
+     */
309
+    _onHardwareBackPress() {
310
+        let p;
311
+
312
+        if (this.props._pictureInPictureEnabled) {
313
+            const { PictureInPicture } = NativeModules;
314
+
315
+            p = PictureInPicture.enterPictureInPicture();
316
+        } else {
317
+            p = Promise.reject(new Error('PiP not enabled'));
318
+        }
319
+
320
+        p.catch(() => {
321
+            this.props.dispatch(appNavigate(undefined));
322
+        });
303 323
 
304
-        this.props._setToolboxVisible(toolboxVisible);
324
+        return true;
305 325
     }
306 326
 
307 327
     /**
@@ -349,46 +369,20 @@ class Conference extends AbstractConference<Props, *> {
349 369
             }
350 370
         );
351 371
     }
352
-}
353 372
 
354
-/**
355
- * Maps dispatching of some action to React component props.
356
- *
357
- * @param {Function} dispatch - Redux action dispatcher.
358
- * @private
359
- * @returns {{
360
- *     _onHardwareBackPress: Function,
361
- *     _setToolboxVisible: Function
362
- * }}
363
- */
364
-function _mapDispatchToProps(dispatch) {
365
-    return {
366
-        /**
367
-         * Handles a hardware button press for back navigation. Leaves the
368
-         * associated {@code Conference}.
369
-         *
370
-         * @returns {boolean} As the associated conference is unconditionally
371
-         * left and exiting the app while it renders a {@code Conference} is
372
-         * undesired, {@code true} is always returned.
373
-         */
374
-        _onHardwareBackPress() {
375
-            dispatch(appNavigate(undefined));
376
-
377
-            return true;
378
-        },
373
+    _setToolboxVisible: (boolean) => void;
379 374
 
380
-        /**
381
-         * Dispatches an action changing the visibility of the {@link Toolbox}.
382
-         *
383
-         * @private
384
-         * @param {boolean} visible - Pass {@code true} to show the
385
-         * {@code Toolbox} or {@code false} to hide it.
386
-         * @returns {void}
387
-         */
388
-        _setToolboxVisible(visible) {
389
-            dispatch(setToolboxVisible(visible));
390
-        }
391
-    };
375
+    /**
376
+     * Dispatches an action changing the visibility of the {@link Toolbox}.
377
+     *
378
+     * @private
379
+     * @param {boolean} visible - Pass {@code true} to show the
380
+     * {@code Toolbox} or {@code false} to hide it.
381
+     * @returns {void}
382
+     */
383
+    _setToolboxVisible(visible) {
384
+        this.props.dispatch(setToolboxVisible(visible));
385
+    }
392 386
 }
393 387
 
394 388
 /**
@@ -452,6 +446,14 @@ function _mapStateToProps(state) {
452 446
          */
453 447
         _participantCount: getParticipantCount(state),
454 448
 
449
+        /**
450
+         * Whether Picture-in-Picture is enabled.
451
+         *
452
+         * @private
453
+         * @type {boolean}
454
+         */
455
+        _pictureInPictureEnabled: getAppProp(state, 'pictureInPictureEnabled'),
456
+
455 457
         /**
456 458
          * The indicator which determines whether the UI is reduced (to
457 459
          * accommodate smaller display areas).
@@ -479,5 +481,4 @@ function _mapStateToProps(state) {
479 481
     };
480 482
 }
481 483
 
482
-export default reactReduxConnect(_mapStateToProps, _mapDispatchToProps)(
483
-    makeAspectRatioAware(Conference));
484
+export default connect(_mapStateToProps)(makeAspectRatioAware(Conference));

Laddar…
Avbryt
Spara