|
|
@@ -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));
|