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.
This commit is contained in:
parent
763d975445
commit
d7b581e338
|
@ -182,11 +182,6 @@ public class MainActivity extends JitsiMeetActivity {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onConferenceTerminated(HashMap<String, Object> extraData) {
|
||||
Log.d(TAG, "Conference terminated: " + extraData);
|
||||
}
|
||||
|
||||
// Activity lifecycle method overrides
|
||||
//
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ public class BroadcastEvent {
|
|||
CHAT_MESSAGE_RECEIVED("org.jitsi.meet.CHAT_MESSAGE_RECEIVED"),
|
||||
CHAT_TOGGLED("org.jitsi.meet.CHAT_TOGGLED"),
|
||||
VIDEO_MUTED_CHANGED("org.jitsi.meet.VIDEO_MUTED_CHANGED");
|
||||
|
||||
READY_TO_CLOSE("org.jitsi.meet.READY_TO_CLOSE");
|
||||
|
||||
private static final String CONFERENCE_WILL_JOIN_NAME = "CONFERENCE_WILL_JOIN";
|
||||
private static final String CONFERENCE_JOINED_NAME = "CONFERENCE_JOINED";
|
||||
|
@ -101,6 +101,7 @@ public class BroadcastEvent {
|
|||
private static final String CHAT_MESSAGE_RECEIVED_NAME = "CHAT_MESSAGE_RECEIVED";
|
||||
private static final String CHAT_TOGGLED_NAME = "CHAT_TOGGLED";
|
||||
private static final String VIDEO_MUTED_CHANGED_NAME = "VIDEO_MUTED_CHANGED";
|
||||
private static final String READY_TO_CLOSE_NAME = "READY_TO_CLOSE";
|
||||
|
||||
private final String action;
|
||||
|
||||
|
@ -147,6 +148,8 @@ public class BroadcastEvent {
|
|||
return CHAT_TOGGLED;
|
||||
case VIDEO_MUTED_CHANGED_NAME:
|
||||
return VIDEO_MUTED_CHANGED;
|
||||
case READY_TO_CLOSE_NAME:
|
||||
return READY_TO_CLOSE;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -194,7 +194,6 @@ public class JitsiMeetActivity extends AppCompatActivity
|
|||
|
||||
protected void onConferenceTerminated(HashMap<String, Object> extraData) {
|
||||
JitsiMeetLogger.i("Conference terminated: " + extraData);
|
||||
finish();
|
||||
}
|
||||
|
||||
protected void onConferenceWillJoin(HashMap<String, Object> extraData) {
|
||||
|
@ -217,6 +216,11 @@ public class JitsiMeetActivity extends AppCompatActivity
|
|||
}
|
||||
}
|
||||
|
||||
protected void onReadyToClose() {
|
||||
JitsiMeetLogger.i("SDK is ready to close");
|
||||
finish();
|
||||
}
|
||||
|
||||
// Activity lifecycle methods
|
||||
//
|
||||
|
||||
|
@ -298,6 +302,9 @@ public class JitsiMeetActivity extends AppCompatActivity
|
|||
case PARTICIPANT_LEFT:
|
||||
onParticipantLeft(event.getData());
|
||||
break;
|
||||
case READY_TO_CLOSE:
|
||||
onReadyToClose();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,10 +91,13 @@
|
|||
#if 0
|
||||
- (void)enterPictureInPicture:(NSDictionary *)data {
|
||||
[self _onJitsiMeetViewDelegateEvent:@"ENTER_PICTURE_IN_PICTURE" withData:data];
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)readyToClose:(NSDictionary *)data {
|
||||
[self _onJitsiMeetViewDelegateEvent:@"READY_TO_CLOSE" withData:data];
|
||||
}
|
||||
|
||||
- (void)participantJoined:(NSDictionary *)data {
|
||||
NSLog(@"%@%@", @"Participant joined: ", data[@"participantId"]);
|
||||
}
|
||||
|
|
|
@ -111,4 +111,9 @@
|
|||
*/
|
||||
- (void)videoMutedChanged:(NSDictionary *)data;
|
||||
|
||||
/**
|
||||
* Called when the SDK is ready to be closed. No meeting is happening at this point.
|
||||
*/
|
||||
- (void)readyToClose:(NSDictionary *)data;
|
||||
|
||||
@end
|
||||
|
|
|
@ -39,6 +39,9 @@
|
|||
"audioOnly": {
|
||||
"audioOnly": "Low bandwidth"
|
||||
},
|
||||
"blankPage": {
|
||||
"meetingEnded": "Meeting ended."
|
||||
},
|
||||
"breakoutRooms": {
|
||||
"defaultName": "Breakout room #{{index}}",
|
||||
"mainRoom": "Main room",
|
||||
|
|
|
@ -43,9 +43,6 @@ export default {
|
|||
'LargeVideo': {
|
||||
background: '#040404'
|
||||
},
|
||||
'LoadConfigOverlay': {
|
||||
background: 'rgb(249, 249, 249)'
|
||||
},
|
||||
'Thumbnail': {
|
||||
activeParticipantHighlight: 'rgb(81, 214, 170)',
|
||||
activeParticipantTint: 'rgba(49, 183, 106, 0.3)',
|
||||
|
|
|
@ -14,7 +14,12 @@ import { isRoomValid, SET_ROOM } from '../conference';
|
|||
import { getLocalParticipant } from '../participants';
|
||||
import { MiddlewareRegistry } from '../redux';
|
||||
import { getPropertyValue } from '../settings';
|
||||
import { isLocalVideoTrackDesktop, setTrackMuted, TRACK_ADDED } from '../tracks';
|
||||
import {
|
||||
destroyLocalTracks,
|
||||
isLocalVideoTrackDesktop,
|
||||
setTrackMuted,
|
||||
TRACK_ADDED
|
||||
} from '../tracks';
|
||||
|
||||
import { SET_AUDIO_MUTED, SET_VIDEO_MUTED } from './actionTypes';
|
||||
import { setAudioMuted, setCameraFacingMode, setVideoMuted } from './actions';
|
||||
|
@ -217,6 +222,10 @@ function _setRoom({ dispatch, getState }, next, action) {
|
|||
|
||||
dispatch(setAudioOnly(audioOnly, false));
|
||||
|
||||
if (!roomIsValid) {
|
||||
dispatch(destroyLocalTracks());
|
||||
}
|
||||
|
||||
return next(action);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
/**
|
||||
* The type of the action which indicates the SDK is ready to be closed.
|
||||
*
|
||||
* @returns {{
|
||||
* type: READY_TO_CLOSE
|
||||
* }}
|
||||
*/
|
||||
export const READY_TO_CLOSE = 'READY_TO_CLOSE';
|
||||
|
||||
/**
|
||||
* The type of the action which sets the list of known participant IDs which
|
||||
* have an active screen share.
|
||||
|
|
|
@ -1,6 +1,22 @@
|
|||
// @flow
|
||||
|
||||
import { SCREEN_SHARE_PARTICIPANTS_UPDATED } from './actionTypes';
|
||||
import {
|
||||
READY_TO_CLOSE,
|
||||
SCREEN_SHARE_PARTICIPANTS_UPDATED
|
||||
} from './actionTypes';
|
||||
|
||||
/**
|
||||
* Creates a (redux) action which signals that the SDK is ready to be closed.
|
||||
*
|
||||
* @returns {{
|
||||
* type: READY_TO_CLOSE
|
||||
* }}
|
||||
*/
|
||||
export function readyToClose() {
|
||||
return {
|
||||
type: READY_TO_CLOSE
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a (redux) action which signals that the list of known participants
|
||||
|
@ -9,10 +25,10 @@ import { SCREEN_SHARE_PARTICIPANTS_UPDATED } from './actionTypes';
|
|||
* @param {string} participantIds - The participants which currently have active
|
||||
* screen share streams.
|
||||
* @returns {{
|
||||
* type: SCREEN_SHARE_PARTICIPANTS_UPDATED,
|
||||
* participantId: string
|
||||
* }}
|
||||
*/
|
||||
* type: SCREEN_SHARE_PARTICIPANTS_UPDATED,
|
||||
* participantId: string
|
||||
* }}
|
||||
*/
|
||||
export function setParticipantsWithScreenShare(participantIds: Array<string>) {
|
||||
return {
|
||||
type: SCREEN_SHARE_PARTICIPANTS_UPDATED,
|
||||
|
|
|
@ -24,8 +24,6 @@ import {
|
|||
getURLWithoutParams
|
||||
} from '../../base/connection';
|
||||
import {
|
||||
isFatalJitsiConferenceError,
|
||||
isFatalJitsiConnectionError,
|
||||
JitsiConferenceEvents } from '../../base/lib-jitsi-meet';
|
||||
import { MEDIA_TYPE } from '../../base/media';
|
||||
import { SET_AUDIO_MUTED, SET_VIDEO_MUTED } from '../../base/media/actionTypes';
|
||||
|
@ -45,6 +43,7 @@ import { SET_PAGE_RELOAD_OVERLAY_CANCELED } from '../../overlay/actionTypes';
|
|||
import { muteLocal } from '../../video-menu/actions';
|
||||
import { ENTER_PICTURE_IN_PICTURE } from '../picture-in-picture';
|
||||
|
||||
import { READY_TO_CLOSE } from './actionTypes';
|
||||
import { setParticipantsWithScreenShare } from './actions';
|
||||
import { sendEvent } from './functions';
|
||||
import logger from './logger';
|
||||
|
@ -116,7 +115,7 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
// counterpart of the External API (or at least not in the
|
||||
// fatality/finality semantics attributed to
|
||||
// conferenceFailed:/onConferenceFailed).
|
||||
if (!error.recoverable && !isFatalJitsiConnectionError(error) && !isFatalJitsiConferenceError(error)) {
|
||||
if (!error.recoverable) {
|
||||
_sendConferenceEvent(store, /* action */ {
|
||||
error: _toErrorString(error),
|
||||
...data
|
||||
|
@ -190,6 +189,10 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
break;
|
||||
}
|
||||
|
||||
case READY_TO_CLOSE:
|
||||
sendEvent(store, type, /* data */ {});
|
||||
break;
|
||||
|
||||
case SET_ROOM:
|
||||
_maybeTriggerEarlyConferenceWillJoin(store, action);
|
||||
break;
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import React, { PureComponent } from 'react';
|
||||
import { SafeAreaView, Text, View } from 'react-native';
|
||||
|
||||
import { ColorSchemeRegistry } from '../../../base/color-scheme';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { LoadingIndicator } from '../../../base/react';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { StyleType } from '../../../base/styles';
|
||||
|
||||
import OverlayFrame from './OverlayFrame';
|
||||
import styles from './styles';
|
||||
import styles, { TEXT_COLOR } from './styles';
|
||||
|
||||
type Props = {
|
||||
|
||||
|
@ -29,7 +27,7 @@ type Props = {
|
|||
* Implements an overlay to tell the user that there is an operation in progress in the background during connect
|
||||
* so then the app doesn't seem hung.
|
||||
*/
|
||||
class LoadConfigOverlay extends Component<Props> {
|
||||
class LoadConfigOverlay extends PureComponent<Props> {
|
||||
/**
|
||||
* Determines whether this overlay needs to be rendered (according to a
|
||||
* specific redux state). Called by {@link OverlayContainer}.
|
||||
|
@ -49,25 +47,15 @@ class LoadConfigOverlay extends Component<Props> {
|
|||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const { _styles } = this.props;
|
||||
|
||||
return (
|
||||
<OverlayFrame>
|
||||
<View
|
||||
style = { [
|
||||
styles.loadingOverlayWrapper,
|
||||
_styles.loadingOverlayWrapper
|
||||
] }>
|
||||
<View style = { styles.loadingOverlayWrapper }>
|
||||
<SafeAreaView>
|
||||
<LoadingIndicator
|
||||
color = { _styles.indicatorColor }
|
||||
color = { TEXT_COLOR }
|
||||
size = 'large'
|
||||
style = { styles.connectIndicator } />
|
||||
<Text
|
||||
style = { [
|
||||
styles.loadingOverlayText,
|
||||
_styles.loadingOverlayText
|
||||
] }>
|
||||
<Text style = { styles.loadingOverlayText }>
|
||||
{ this.props.t('connectingOverlay.joiningRoom') }
|
||||
</Text>
|
||||
</SafeAreaView>
|
||||
|
@ -77,18 +65,5 @@ class LoadConfigOverlay extends Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps part of the Redux state to the props of this component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @returns {{
|
||||
* _styles: StyleType
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
return {
|
||||
_styles: ColorSchemeRegistry.get(state, 'LoadConfigOverlay')
|
||||
};
|
||||
}
|
||||
|
||||
export default translate(connect(_mapStateToProps)(LoadConfigOverlay));
|
||||
export default translate(LoadConfigOverlay);
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import { ColorSchemeRegistry, schemeColor } from '../../../base/color-scheme';
|
||||
import { BoxModel, ColorPalette } from '../../../base/styles';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
|
||||
|
||||
export const TEXT_COLOR = BaseTheme.palette.text01;
|
||||
|
||||
/**
|
||||
* The React {@code Component} styles of the overlay feature.
|
||||
|
@ -23,12 +25,13 @@ export default {
|
|||
},
|
||||
|
||||
loadingOverlayText: {
|
||||
color: ColorPalette.white
|
||||
color: TEXT_COLOR
|
||||
},
|
||||
|
||||
loadingOverlayWrapper: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
alignItems: 'center',
|
||||
backgroundColor: BaseTheme.palette.uiBackground,
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center'
|
||||
|
@ -38,18 +41,3 @@ export default {
|
|||
flex: 1
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Color schemed styles for all the component based on the abstract dialog.
|
||||
*/
|
||||
ColorSchemeRegistry.register('LoadConfigOverlay', {
|
||||
indicatorColor: schemeColor('text'),
|
||||
|
||||
loadingOverlayText: {
|
||||
color: schemeColor('text')
|
||||
},
|
||||
|
||||
loadingOverlayWrapper: {
|
||||
backgroundColor: schemeColor('background')
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,80 +1,34 @@
|
|||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { View } from 'react-native';
|
||||
import type { Dispatch } from 'redux';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Text, View } from 'react-native';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import { ColorSchemeRegistry } from '../../base/color-scheme';
|
||||
import { LoadingIndicator } from '../../base/react';
|
||||
import { connect } from '../../base/redux';
|
||||
import { StyleType } from '../../base/styles';
|
||||
import { destroyLocalTracks } from '../../base/tracks';
|
||||
import { readyToClose } from '../../mobile/external-api/actions';
|
||||
|
||||
import styles from './styles';
|
||||
|
||||
/**
|
||||
* The type of React {@code Component} props of {@link BlankPage}.
|
||||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The color schemed style of the component.
|
||||
*/
|
||||
_styles: StyleType,
|
||||
const BlankPage = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
dispatch: Dispatch<any>
|
||||
};
|
||||
|
||||
/**
|
||||
* The React {@code Component} displayed by {@code AbstractApp} when it has no
|
||||
* {@code Route} to render. Renders a progress indicator when there are ongoing
|
||||
* network requests.
|
||||
*/
|
||||
class BlankPage extends Component<Props> {
|
||||
/**
|
||||
* Destroys the local tracks (if any) since no media is desired when this
|
||||
* component is rendered.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {void}
|
||||
*/
|
||||
componentDidMount() {
|
||||
this.props.dispatch(destroyLocalTracks());
|
||||
}
|
||||
useEffect(() => {
|
||||
dispatch(readyToClose());
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const { _styles } = this.props;
|
||||
return (
|
||||
<View style = { styles.blankPageWrapper }>
|
||||
<Text style = { styles.blankPageText }>
|
||||
{ t('blankPage.meetingEnded') }
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
style = { [
|
||||
styles.blankPageWrapper,
|
||||
_styles.loadingOverlayWrapper
|
||||
] }>
|
||||
<LoadingIndicator
|
||||
color = { _styles.indicatorColor }
|
||||
size = 'large' />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps part of the Redux state to the props of this component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @returns {Props}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
return {
|
||||
_styles: ColorSchemeRegistry.get(state, 'LoadConfigOverlay')
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(_mapStateToProps)(BlankPage);
|
||||
export default BlankPage;
|
||||
|
|
|
@ -18,7 +18,6 @@ import { Icon, IconMenu, IconWarning } from '../../base/icons';
|
|||
import JitsiStatusBar from '../../base/modal/components/JitsiStatusBar';
|
||||
import { LoadingIndicator, Text } from '../../base/react';
|
||||
import { connect } from '../../base/redux';
|
||||
import { destroyLocalTracks } from '../../base/tracks';
|
||||
import BaseTheme from '../../base/ui/components/BaseTheme.native';
|
||||
|
||||
import {
|
||||
|
@ -108,7 +107,6 @@ class WelcomePage extends AbstractWelcomePage<*> {
|
|||
|
||||
const {
|
||||
_headerStyles,
|
||||
dispatch,
|
||||
navigation
|
||||
} = this.props;
|
||||
|
||||
|
@ -129,8 +127,6 @@ class WelcomePage extends AbstractWelcomePage<*> {
|
|||
headerRight: () =>
|
||||
<VideoSwitch />
|
||||
});
|
||||
|
||||
dispatch(destroyLocalTracks());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -42,12 +42,18 @@ export default {
|
|||
marginRight: BaseTheme.spacing[2]
|
||||
},
|
||||
|
||||
blankPageText: {
|
||||
color: TEXT_COLOR,
|
||||
fontSize: 18
|
||||
},
|
||||
|
||||
/**
|
||||
* View that is rendered when there is no welcome page.
|
||||
*/
|
||||
blankPageWrapper: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
alignItems: 'center',
|
||||
backgroundColor: BaseTheme.palette.uiBackground,
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center'
|
||||
|
|
Loading…
Reference in New Issue