Browse Source

feat)rn,sdk) introduce a "ready to close" event

This event is the event host applications need to listen to for knowing when to
dispose the SDK from now on.

Since the introduction of breakout rooms it's possible that we navigate from one
meeting to another, so there will be several conference join / terminations.

In addition, local track destruction is now moved to SET_ROOM when there is no
room, aka, we are going back to the welcome page or to the black page.
master
Saúl Ibarra Corretgé 3 years ago
parent
commit
d7b581e338

+ 0
- 5
android/app/src/main/java/org/jitsi/meet/MainActivity.java View File

@@ -182,11 +182,6 @@ public class MainActivity extends JitsiMeetActivity {
182 182
         }
183 183
     }
184 184
 
185
-    @Override
186
-    protected void onConferenceTerminated(HashMap<String, Object> extraData) {
187
-        Log.d(TAG, "Conference terminated: " + extraData);
188
-    }
189
-
190 185
     // Activity lifecycle method overrides
191 186
     //
192 187
 

+ 4
- 1
android/sdk/src/main/java/org/jitsi/meet/sdk/BroadcastEvent.java View File

@@ -87,7 +87,7 @@ public class BroadcastEvent {
87 87
         CHAT_MESSAGE_RECEIVED("org.jitsi.meet.CHAT_MESSAGE_RECEIVED"),
88 88
         CHAT_TOGGLED("org.jitsi.meet.CHAT_TOGGLED"),
89 89
         VIDEO_MUTED_CHANGED("org.jitsi.meet.VIDEO_MUTED_CHANGED");
90
-
90
+        READY_TO_CLOSE("org.jitsi.meet.READY_TO_CLOSE");
91 91
 
92 92
         private static final String CONFERENCE_WILL_JOIN_NAME = "CONFERENCE_WILL_JOIN";
93 93
         private static final String CONFERENCE_JOINED_NAME = "CONFERENCE_JOINED";
@@ -101,6 +101,7 @@ public class BroadcastEvent {
101 101
         private static final String CHAT_MESSAGE_RECEIVED_NAME = "CHAT_MESSAGE_RECEIVED";
102 102
         private static final String CHAT_TOGGLED_NAME = "CHAT_TOGGLED";
103 103
         private static final String VIDEO_MUTED_CHANGED_NAME = "VIDEO_MUTED_CHANGED";
104
+        private static final String READY_TO_CLOSE_NAME = "READY_TO_CLOSE";
104 105
 
105 106
         private final String action;
106 107
 
@@ -147,6 +148,8 @@ public class BroadcastEvent {
147 148
                     return CHAT_TOGGLED;
148 149
                 case VIDEO_MUTED_CHANGED_NAME:
149 150
                     return VIDEO_MUTED_CHANGED;
151
+                case READY_TO_CLOSE_NAME:
152
+                    return READY_TO_CLOSE;
150 153
             }
151 154
 
152 155
             return null;

+ 8
- 1
android/sdk/src/main/java/org/jitsi/meet/sdk/JitsiMeetActivity.java View File

@@ -194,7 +194,6 @@ public class JitsiMeetActivity extends AppCompatActivity
194 194
 
195 195
     protected void onConferenceTerminated(HashMap<String, Object> extraData) {
196 196
         JitsiMeetLogger.i("Conference terminated: " + extraData);
197
-        finish();
198 197
     }
199 198
 
200 199
     protected void onConferenceWillJoin(HashMap<String, Object> extraData) {
@@ -217,6 +216,11 @@ public class JitsiMeetActivity extends AppCompatActivity
217 216
         }
218 217
     }
219 218
 
219
+    protected void onReadyToClose() {
220
+        JitsiMeetLogger.i("SDK is ready to close");
221
+        finish();
222
+    }
223
+
220 224
     // Activity lifecycle methods
221 225
     //
222 226
 
@@ -298,6 +302,9 @@ public class JitsiMeetActivity extends AppCompatActivity
298 302
                 case PARTICIPANT_LEFT:
299 303
                     onParticipantLeft(event.getData());
300 304
                     break;
305
+                case READY_TO_CLOSE:
306
+                    onReadyToClose();
307
+                    break;
301 308
             }
302 309
         }
303 310
     }

+ 4
- 1
ios/app/src/ViewController.m View File

@@ -91,10 +91,13 @@
91 91
 #if 0
92 92
 - (void)enterPictureInPicture:(NSDictionary *)data {
93 93
     [self _onJitsiMeetViewDelegateEvent:@"ENTER_PICTURE_IN_PICTURE" withData:data];
94
-
95 94
 }
96 95
 #endif
97 96
 
97
+- (void)readyToClose:(NSDictionary *)data {
98
+    [self _onJitsiMeetViewDelegateEvent:@"READY_TO_CLOSE" withData:data];
99
+}
100
+
98 101
 - (void)participantJoined:(NSDictionary *)data {
99 102
   NSLog(@"%@%@", @"Participant joined: ", data[@"participantId"]);
100 103
 }

+ 5
- 0
ios/sdk/src/JitsiMeetViewDelegate.h View File

@@ -111,4 +111,9 @@
111 111
  */
112 112
 - (void)videoMutedChanged:(NSDictionary *)data;
113 113
 
114
+/**
115
+ * Called when the SDK is ready to be closed. No meeting is happening at this point.
116
+ */
117
+- (void)readyToClose:(NSDictionary *)data;
118
+
114 119
 @end

+ 3
- 0
lang/main.json View File

@@ -39,6 +39,9 @@
39 39
     "audioOnly": {
40 40
         "audioOnly": "Low bandwidth"
41 41
     },
42
+    "blankPage": {
43
+        "meetingEnded": "Meeting ended."
44
+    },
42 45
     "breakoutRooms": {
43 46
         "defaultName": "Breakout room #{{index}}",
44 47
         "mainRoom": "Main room",

+ 0
- 3
react/features/base/color-scheme/defaultScheme.js View File

@@ -43,9 +43,6 @@ export default {
43 43
     'LargeVideo': {
44 44
         background: '#040404'
45 45
     },
46
-    'LoadConfigOverlay': {
47
-        background: 'rgb(249, 249, 249)'
48
-    },
49 46
     'Thumbnail': {
50 47
         activeParticipantHighlight: 'rgb(81, 214, 170)',
51 48
         activeParticipantTint: 'rgba(49, 183, 106, 0.3)',

+ 10
- 1
react/features/base/media/middleware.js View File

@@ -14,7 +14,12 @@ import { isRoomValid, SET_ROOM } from '../conference';
14 14
 import { getLocalParticipant } from '../participants';
15 15
 import { MiddlewareRegistry } from '../redux';
16 16
 import { getPropertyValue } from '../settings';
17
-import { isLocalVideoTrackDesktop, setTrackMuted, TRACK_ADDED } from '../tracks';
17
+import {
18
+    destroyLocalTracks,
19
+    isLocalVideoTrackDesktop,
20
+    setTrackMuted,
21
+    TRACK_ADDED
22
+} from '../tracks';
18 23
 
19 24
 import { SET_AUDIO_MUTED, SET_VIDEO_MUTED } from './actionTypes';
20 25
 import { setAudioMuted, setCameraFacingMode, setVideoMuted } from './actions';
@@ -217,6 +222,10 @@ function _setRoom({ dispatch, getState }, next, action) {
217 222
 
218 223
     dispatch(setAudioOnly(audioOnly, false));
219 224
 
225
+    if (!roomIsValid) {
226
+        dispatch(destroyLocalTracks());
227
+    }
228
+
220 229
     return next(action);
221 230
 }
222 231
 

+ 9
- 0
react/features/mobile/external-api/actionTypes.js View File

@@ -1,3 +1,12 @@
1
+/**
2
+ * The type of the action which indicates the SDK is ready to be closed.
3
+ *
4
+ * @returns {{
5
+ *     type: READY_TO_CLOSE
6
+ * }}
7
+ */
8
+export const READY_TO_CLOSE = 'READY_TO_CLOSE';
9
+
1 10
 /**
2 11
  * The type of the action which sets the list of known participant IDs which
3 12
  * have an active screen share.

+ 21
- 5
react/features/mobile/external-api/actions.js View File

@@ -1,6 +1,22 @@
1 1
 // @flow
2 2
 
3
-import { SCREEN_SHARE_PARTICIPANTS_UPDATED } from './actionTypes';
3
+import {
4
+    READY_TO_CLOSE,
5
+    SCREEN_SHARE_PARTICIPANTS_UPDATED
6
+} from './actionTypes';
7
+
8
+/**
9
+ * Creates a (redux) action which signals that the SDK is ready to be closed.
10
+ *
11
+ * @returns {{
12
+ *     type: READY_TO_CLOSE
13
+ * }}
14
+ */
15
+export function readyToClose() {
16
+    return {
17
+        type: READY_TO_CLOSE
18
+    };
19
+}
4 20
 
5 21
 /**
6 22
  * Creates a (redux) action which signals that the list of known participants
@@ -9,10 +25,10 @@ import { SCREEN_SHARE_PARTICIPANTS_UPDATED } from './actionTypes';
9 25
  * @param {string} participantIds - The participants which currently have active
10 26
  * screen share streams.
11 27
  * @returns {{
12
-    *     type: SCREEN_SHARE_PARTICIPANTS_UPDATED,
13
-    *     participantId: string
14
-    * }}
15
-    */
28
+ *     type: SCREEN_SHARE_PARTICIPANTS_UPDATED,
29
+ *     participantId: string
30
+ * }}
31
+ */
16 32
 export function setParticipantsWithScreenShare(participantIds: Array<string>) {
17 33
     return {
18 34
         type: SCREEN_SHARE_PARTICIPANTS_UPDATED,

+ 6
- 3
react/features/mobile/external-api/middleware.js View File

@@ -24,8 +24,6 @@ import {
24 24
     getURLWithoutParams
25 25
 } from '../../base/connection';
26 26
 import {
27
-    isFatalJitsiConferenceError,
28
-    isFatalJitsiConnectionError,
29 27
     JitsiConferenceEvents } from '../../base/lib-jitsi-meet';
30 28
 import { MEDIA_TYPE } from '../../base/media';
31 29
 import { SET_AUDIO_MUTED, SET_VIDEO_MUTED } from '../../base/media/actionTypes';
@@ -45,6 +43,7 @@ import { SET_PAGE_RELOAD_OVERLAY_CANCELED } from '../../overlay/actionTypes';
45 43
 import { muteLocal } from '../../video-menu/actions';
46 44
 import { ENTER_PICTURE_IN_PICTURE } from '../picture-in-picture';
47 45
 
46
+import { READY_TO_CLOSE } from './actionTypes';
48 47
 import { setParticipantsWithScreenShare } from './actions';
49 48
 import { sendEvent } from './functions';
50 49
 import logger from './logger';
@@ -116,7 +115,7 @@ MiddlewareRegistry.register(store => next => action => {
116 115
         // counterpart of the External API (or at least not in the
117 116
         // fatality/finality semantics attributed to
118 117
         // conferenceFailed:/onConferenceFailed).
119
-        if (!error.recoverable && !isFatalJitsiConnectionError(error) && !isFatalJitsiConferenceError(error)) {
118
+        if (!error.recoverable) {
120 119
             _sendConferenceEvent(store, /* action */ {
121 120
                 error: _toErrorString(error),
122 121
                 ...data
@@ -190,6 +189,10 @@ MiddlewareRegistry.register(store => next => action => {
190 189
         break;
191 190
     }
192 191
 
192
+    case READY_TO_CLOSE:
193
+        sendEvent(store, type, /* data */ {});
194
+        break;
195
+
193 196
     case SET_ROOM:
194 197
         _maybeTriggerEarlyConferenceWillJoin(store, action);
195 198
         break;

+ 7
- 32
react/features/overlay/components/native/LoadConfigOverlay.js View File

@@ -1,16 +1,14 @@
1 1
 // @flow
2 2
 
3
-import React, { Component } from 'react';
3
+import React, { PureComponent } from 'react';
4 4
 import { SafeAreaView, Text, View } from 'react-native';
5 5
 
6
-import { ColorSchemeRegistry } from '../../../base/color-scheme';
7 6
 import { translate } from '../../../base/i18n';
8 7
 import { LoadingIndicator } from '../../../base/react';
9
-import { connect } from '../../../base/redux';
10 8
 import { StyleType } from '../../../base/styles';
11 9
 
12 10
 import OverlayFrame from './OverlayFrame';
13
-import styles from './styles';
11
+import styles, { TEXT_COLOR } from './styles';
14 12
 
15 13
 type Props = {
16 14
 
@@ -29,7 +27,7 @@ type Props = {
29 27
  * Implements an overlay to tell the user that there is an operation in progress in the background during connect
30 28
  * so then the app doesn't seem hung.
31 29
  */
32
-class LoadConfigOverlay extends Component<Props> {
30
+class LoadConfigOverlay extends PureComponent<Props> {
33 31
     /**
34 32
      * Determines whether this overlay needs to be rendered (according to a
35 33
      * specific redux state). Called by {@link OverlayContainer}.
@@ -49,25 +47,15 @@ class LoadConfigOverlay extends Component<Props> {
49 47
      * @returns {ReactElement}
50 48
      */
51 49
     render() {
52
-        const { _styles } = this.props;
53
-
54 50
         return (
55 51
             <OverlayFrame>
56
-                <View
57
-                    style = { [
58
-                        styles.loadingOverlayWrapper,
59
-                        _styles.loadingOverlayWrapper
60
-                    ] }>
52
+                <View style = { styles.loadingOverlayWrapper }>
61 53
                     <SafeAreaView>
62 54
                         <LoadingIndicator
63
-                            color = { _styles.indicatorColor }
55
+                            color = { TEXT_COLOR }
64 56
                             size = 'large'
65 57
                             style = { styles.connectIndicator } />
66
-                        <Text
67
-                            style = { [
68
-                                styles.loadingOverlayText,
69
-                                _styles.loadingOverlayText
70
-                            ] }>
58
+                        <Text style = { styles.loadingOverlayText }>
71 59
                             { this.props.t('connectingOverlay.joiningRoom') }
72 60
                         </Text>
73 61
                     </SafeAreaView>
@@ -77,18 +65,5 @@ class LoadConfigOverlay extends Component<Props> {
77 65
     }
78 66
 }
79 67
 
80
-/**
81
- * Maps part of the Redux state to the props of this component.
82
- *
83
- * @param {Object} state - The Redux state.
84
- * @returns {{
85
- *     _styles: StyleType
86
- * }}
87
- */
88
-function _mapStateToProps(state) {
89
-    return {
90
-        _styles: ColorSchemeRegistry.get(state, 'LoadConfigOverlay')
91
-    };
92
-}
93 68
 
94
-export default translate(connect(_mapStateToProps)(LoadConfigOverlay));
69
+export default translate(LoadConfigOverlay);

+ 5
- 17
react/features/overlay/components/native/styles.js View File

@@ -2,8 +2,10 @@
2 2
 
3 3
 import { StyleSheet } from 'react-native';
4 4
 
5
-import { ColorSchemeRegistry, schemeColor } from '../../../base/color-scheme';
6 5
 import { BoxModel, ColorPalette } from '../../../base/styles';
6
+import BaseTheme from '../../../base/ui/components/BaseTheme.native';
7
+
8
+export const TEXT_COLOR = BaseTheme.palette.text01;
7 9
 
8 10
 /**
9 11
  * The React {@code Component} styles of the overlay feature.
@@ -23,12 +25,13 @@ export default {
23 25
     },
24 26
 
25 27
     loadingOverlayText: {
26
-        color: ColorPalette.white
28
+        color: TEXT_COLOR
27 29
     },
28 30
 
29 31
     loadingOverlayWrapper: {
30 32
         ...StyleSheet.absoluteFillObject,
31 33
         alignItems: 'center',
34
+        backgroundColor: BaseTheme.palette.uiBackground,
32 35
         flex: 1,
33 36
         flexDirection: 'column',
34 37
         justifyContent: 'center'
@@ -38,18 +41,3 @@ export default {
38 41
         flex: 1
39 42
     }
40 43
 };
41
-
42
-/**
43
- * Color schemed styles for all the component based on the abstract dialog.
44
- */
45
-ColorSchemeRegistry.register('LoadConfigOverlay', {
46
-    indicatorColor: schemeColor('text'),
47
-
48
-    loadingOverlayText: {
49
-        color: schemeColor('text')
50
-    },
51
-
52
-    loadingOverlayWrapper: {
53
-        backgroundColor: schemeColor('background')
54
-    }
55
-});

+ 21
- 67
react/features/welcome/components/BlankPage.native.js View File

@@ -1,80 +1,34 @@
1 1
 // @flow
2 2
 
3
-import React, { Component } from 'react';
4
-import { View } from 'react-native';
5
-import type { Dispatch } from 'redux';
3
+import React, { useEffect } from 'react';
4
+import { useTranslation } from 'react-i18next';
5
+import { Text, View } from 'react-native';
6
+import { useDispatch } from 'react-redux';
6 7
 
7
-import { ColorSchemeRegistry } from '../../base/color-scheme';
8
-import { LoadingIndicator } from '../../base/react';
9
-import { connect } from '../../base/redux';
10
-import { StyleType } from '../../base/styles';
11
-import { destroyLocalTracks } from '../../base/tracks';
8
+import { readyToClose } from '../../mobile/external-api/actions';
12 9
 
13 10
 import styles from './styles';
14 11
 
15
-/**
16
- * The type of React {@code Component} props of {@link BlankPage}.
17
- */
18
-type Props = {
19 12
 
20
-    /**
21
-     * The color schemed style of the component.
22
-     */
23
-    _styles: StyleType,
13
+const BlankPage = () => {
14
+    const dispatch = useDispatch();
15
+    const { t } = useTranslation();
24 16
 
25
-    dispatch: Dispatch<any>
26
-};
27
-
28
-/**
29
- * The React {@code Component} displayed by {@code AbstractApp} when it has no
30
- * {@code Route} to render. Renders a progress indicator when there are ongoing
31
- * network requests.
32
- */
33
-class BlankPage extends Component<Props> {
34 17
     /**
35 18
      * Destroys the local tracks (if any) since no media is desired when this
36 19
      * component is rendered.
37
-     *
38
-     * @inheritdoc
39
-     * @returns {void}
40
-     */
41
-    componentDidMount() {
42
-        this.props.dispatch(destroyLocalTracks());
43
-    }
44
-
45
-    /**
46
-     * Implements React's {@link Component#render()}.
47
-     *
48
-     * @inheritdoc
49
-     * @returns {ReactElement}
50 20
      */
51
-    render() {
52
-        const { _styles } = this.props;
53
-
54
-        return (
55
-            <View
56
-                style = { [
57
-                    styles.blankPageWrapper,
58
-                    _styles.loadingOverlayWrapper
59
-                ] }>
60
-                <LoadingIndicator
61
-                    color = { _styles.indicatorColor }
62
-                    size = 'large' />
63
-            </View>
64
-        );
65
-    }
66
-}
67
-
68
-/**
69
- * Maps part of the Redux state to the props of this component.
70
- *
71
- * @param {Object} state - The Redux state.
72
- * @returns {Props}
73
- */
74
-function _mapStateToProps(state) {
75
-    return {
76
-        _styles: ColorSchemeRegistry.get(state, 'LoadConfigOverlay')
77
-    };
78
-}
21
+    useEffect(() => {
22
+        dispatch(readyToClose());
23
+    }, []);
24
+
25
+    return (
26
+        <View style = { styles.blankPageWrapper }>
27
+            <Text style = { styles.blankPageText }>
28
+                { t('blankPage.meetingEnded') }
29
+            </Text>
30
+        </View>
31
+    );
32
+};
79 33
 
80
-export default connect(_mapStateToProps)(BlankPage);
34
+export default BlankPage;

+ 0
- 4
react/features/welcome/components/WelcomePage.native.js View File

@@ -18,7 +18,6 @@ import { Icon, IconMenu, IconWarning } from '../../base/icons';
18 18
 import JitsiStatusBar from '../../base/modal/components/JitsiStatusBar';
19 19
 import { LoadingIndicator, Text } from '../../base/react';
20 20
 import { connect } from '../../base/redux';
21
-import { destroyLocalTracks } from '../../base/tracks';
22 21
 import BaseTheme from '../../base/ui/components/BaseTheme.native';
23 22
 
24 23
 import {
@@ -108,7 +107,6 @@ class WelcomePage extends AbstractWelcomePage<*> {
108 107
 
109 108
         const {
110 109
             _headerStyles,
111
-            dispatch,
112 110
             navigation
113 111
         } = this.props;
114 112
 
@@ -129,8 +127,6 @@ class WelcomePage extends AbstractWelcomePage<*> {
129 127
             headerRight: () =>
130 128
                 <VideoSwitch />
131 129
         });
132
-
133
-        dispatch(destroyLocalTracks());
134 130
     }
135 131
 
136 132
     /**

+ 6
- 0
react/features/welcome/components/styles.js View File

@@ -42,12 +42,18 @@ export default {
42 42
         marginRight: BaseTheme.spacing[2]
43 43
     },
44 44
 
45
+    blankPageText: {
46
+        color: TEXT_COLOR,
47
+        fontSize: 18
48
+    },
49
+
45 50
     /**
46 51
      * View that is rendered when there is no welcome page.
47 52
      */
48 53
     blankPageWrapper: {
49 54
         ...StyleSheet.absoluteFillObject,
50 55
         alignItems: 'center',
56
+        backgroundColor: BaseTheme.palette.uiBackground,
51 57
         flex: 1,
52 58
         flexDirection: 'column',
53 59
         justifyContent: 'center'

Loading…
Cancel
Save