|
@@ -1,20 +1,22 @@
|
1
|
|
-/* @flow */
|
|
1
|
+// @flow
|
2
|
2
|
|
3
|
3
|
import { StatusBar } from 'react-native';
|
4
|
4
|
import { Immersive } from 'react-native-immersive';
|
5
|
5
|
|
6
|
|
-import { APP_STATE_CHANGED } from '../background';
|
|
6
|
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../app';
|
7
|
7
|
import {
|
8
|
8
|
CONFERENCE_FAILED,
|
|
9
|
+ CONFERENCE_JOINED,
|
9
|
10
|
CONFERENCE_LEFT,
|
10
|
11
|
CONFERENCE_WILL_JOIN,
|
11
|
12
|
SET_AUDIO_ONLY
|
12
|
13
|
} from '../../base/conference';
|
13
|
|
-import { HIDE_DIALOG } from '../../base/dialog';
|
14
|
14
|
import { Platform } from '../../base/react';
|
15
|
|
-import { SET_REDUCED_UI } from '../../base/responsive-ui';
|
16
|
15
|
import { MiddlewareRegistry } from '../../base/redux';
|
17
|
16
|
|
|
17
|
+import { _setImmersiveListener } from './actions';
|
|
18
|
+import { _SET_IMMERSIVE_LISTENER } from './actionTypes';
|
|
19
|
+
|
18
|
20
|
/**
|
19
|
21
|
* Middleware that captures conference actions and activates or deactivates the
|
20
|
22
|
* full screen mode. On iOS it hides the status bar, and on Android it uses the
|
|
@@ -26,26 +28,43 @@ import { MiddlewareRegistry } from '../../base/redux';
|
26
|
28
|
* @param {Store} store - The redux store.
|
27
|
29
|
* @returns {Function}
|
28
|
30
|
*/
|
29
|
|
-MiddlewareRegistry.register(({ getState }) => next => action => {
|
|
31
|
+MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
|
30
|
32
|
const result = next(action);
|
31
|
33
|
|
32
|
34
|
let fullScreen = null;
|
33
|
35
|
|
34
|
36
|
switch (action.type) {
|
35
|
|
- case APP_STATE_CHANGED:
|
36
|
|
- case CONFERENCE_WILL_JOIN:
|
37
|
|
- case HIDE_DIALOG:
|
38
|
|
- case SET_AUDIO_ONLY:
|
39
|
|
- case SET_REDUCED_UI: {
|
40
|
|
- // FIXME: Simplify this by listening to Immediate events.
|
41
|
|
- // Check if we just came back from the background and re-enable full
|
42
|
|
- // screen mode if necessary.
|
43
|
|
- const { appState } = action;
|
44
|
|
-
|
45
|
|
- if (typeof appState !== 'undefined' && appState !== 'active') {
|
46
|
|
- break;
|
|
37
|
+ case _SET_IMMERSIVE_LISTENER:
|
|
38
|
+ // XXX The React Native module Immersive is only implemented on Android
|
|
39
|
+ // and throws on other platforms.
|
|
40
|
+ if (Platform.OS === 'android') {
|
|
41
|
+ // Remove the current/old Immersive listener.
|
|
42
|
+ const { listener } = getState()['features/full-screen'];
|
|
43
|
+
|
|
44
|
+ listener && Immersive.removeImmersiveListener(listener);
|
|
45
|
+
|
|
46
|
+ // Add the new listener.
|
|
47
|
+ action.listener && Immersive.addImmersiveListener(action.listener);
|
47
|
48
|
}
|
|
49
|
+ break;
|
|
50
|
+
|
|
51
|
+ case APP_WILL_MOUNT: {
|
|
52
|
+ const context = {
|
|
53
|
+ dispatch,
|
|
54
|
+ getState
|
|
55
|
+ };
|
48
|
56
|
|
|
57
|
+ dispatch(
|
|
58
|
+ _setImmersiveListener(_onImmersiveChange.bind(undefined, context)));
|
|
59
|
+ break;
|
|
60
|
+ }
|
|
61
|
+ case APP_WILL_UNMOUNT:
|
|
62
|
+ _setImmersiveListener(undefined);
|
|
63
|
+ break;
|
|
64
|
+
|
|
65
|
+ case CONFERENCE_WILL_JOIN:
|
|
66
|
+ case CONFERENCE_JOINED:
|
|
67
|
+ case SET_AUDIO_ONLY: {
|
49
|
68
|
const { audioOnly, conference, joining }
|
50
|
69
|
= getState()['features/base/conference'];
|
51
|
70
|
|
|
@@ -59,15 +78,33 @@ MiddlewareRegistry.register(({ getState }) => next => action => {
|
59
|
78
|
break;
|
60
|
79
|
}
|
61
|
80
|
|
62
|
|
- if (fullScreen !== null) {
|
63
|
|
- _setFullScreen(fullScreen)
|
64
|
|
- .catch(err =>
|
65
|
|
- console.warn(`Failed to set full screen mode: ${err}`));
|
66
|
|
- }
|
|
81
|
+ fullScreen !== null && _setFullScreen(fullScreen);
|
67
|
82
|
|
68
|
83
|
return result;
|
69
|
84
|
});
|
70
|
85
|
|
|
86
|
+/**
|
|
87
|
+ * Handler for Immersive mode changes. This will be called when Android's
|
|
88
|
+ * immersive mode changes. This can happen without us wanting, so re-evaluate if
|
|
89
|
+ * immersive mode is desired and reactivate it if needed.
|
|
90
|
+ *
|
|
91
|
+ * @param {Object} store - The redux store.
|
|
92
|
+ * @private
|
|
93
|
+ * @returns {void}
|
|
94
|
+ */
|
|
95
|
+function _onImmersiveChange({ getState }) {
|
|
96
|
+ const state = getState();
|
|
97
|
+ const { appState } = state['features/background'];
|
|
98
|
+
|
|
99
|
+ if (appState === 'active') {
|
|
100
|
+ const { audioOnly, conference, joining }
|
|
101
|
+ = state['features/base/conference'];
|
|
102
|
+ const fullScreen = conference || joining ? !audioOnly : false;
|
|
103
|
+
|
|
104
|
+ _setFullScreen(fullScreen);
|
|
105
|
+ }
|
|
106
|
+}
|
|
107
|
+
|
71
|
108
|
/**
|
72
|
109
|
* Activates/deactivates the full screen mode. On iOS it will hide the status
|
73
|
110
|
* bar, and on Android it will turn immersive mode on.
|
|
@@ -75,18 +112,18 @@ MiddlewareRegistry.register(({ getState }) => next => action => {
|
75
|
112
|
* @param {boolean} fullScreen - True to set full screen mode, false to
|
76
|
113
|
* deactivate it.
|
77
|
114
|
* @private
|
78
|
|
- * @returns {Promise}
|
|
115
|
+ * @returns {void}
|
79
|
116
|
*/
|
80
|
117
|
function _setFullScreen(fullScreen: boolean) {
|
81
|
118
|
// XXX The React Native module Immersive is only implemented on Android and
|
82
|
119
|
// throws on other platforms.
|
83
|
120
|
if (Platform.OS === 'android') {
|
84
|
|
- return fullScreen ? Immersive.on() : Immersive.off();
|
|
121
|
+ fullScreen ? Immersive.on() : Immersive.off();
|
|
122
|
+
|
|
123
|
+ return;
|
85
|
124
|
}
|
86
|
125
|
|
87
|
126
|
// On platforms other than Android go with whatever React Native itself
|
88
|
127
|
// supports.
|
89
|
128
|
StatusBar.setHidden(fullScreen, 'slide');
|
90
|
|
-
|
91
|
|
- return Promise.resolve();
|
92
|
129
|
}
|