feat(mobile) adds ToggleScreenShare event and action.

This commit is contained in:
Titus-Andrei Moldovan 2021-01-21 14:07:00 +02:00 committed by tmoldovan8x8
parent 745879c447
commit 45f4643469
17 changed files with 159 additions and 15 deletions

View File

@ -61,7 +61,8 @@ public class BroadcastAction {
enum Type { enum Type {
SET_AUDIO_MUTED("org.jitsi.meet.SET_AUDIO_MUTED"), SET_AUDIO_MUTED("org.jitsi.meet.SET_AUDIO_MUTED"),
HANG_UP("org.jitsi.meet.HANG_UP"), HANG_UP("org.jitsi.meet.HANG_UP"),
SEND_ENDPOINT_TEXT_MESSAGE("org.jitsi.meet.SEND_ENDPOINT_TEXT_MESSAGE"); SEND_ENDPOINT_TEXT_MESSAGE("org.jitsi.meet.SEND_ENDPOINT_TEXT_MESSAGE"),
TOGGLE_SCREEN_SHARE("org.jitsi.meet.TOGGLE_SCREEN_SHARE");
private final String action; private final String action;

View File

@ -81,7 +81,8 @@ public class BroadcastEvent {
AUDIO_MUTED_CHANGED("org.jitsi.meet.AUDIO_MUTED_CHANGED"), AUDIO_MUTED_CHANGED("org.jitsi.meet.AUDIO_MUTED_CHANGED"),
PARTICIPANT_JOINED("org.jitsi.meet.PARTICIPANT_JOINED"), PARTICIPANT_JOINED("org.jitsi.meet.PARTICIPANT_JOINED"),
PARTICIPANT_LEFT("org.jitsi.meet.PARTICIPANT_LEFT"), PARTICIPANT_LEFT("org.jitsi.meet.PARTICIPANT_LEFT"),
ENDPOINT_TEXT_MESSAGE_RECEIVED("org.jitsi.meet.ENDPOINT_TEXT_MESSAGE_RECEIVED"); ENDPOINT_TEXT_MESSAGE_RECEIVED("org.jitsi.meet.ENDPOINT_TEXT_MESSAGE_RECEIVED"),
SCREEN_SHARE_TOGGLED("org.jitsi.meet.SCREEN_SHARE_TOGGLED");
private static final String CONFERENCE_WILL_JOIN_NAME = "CONFERENCE_WILL_JOIN"; private static final String CONFERENCE_WILL_JOIN_NAME = "CONFERENCE_WILL_JOIN";
private static final String CONFERENCE_JOINED_NAME = "CONFERENCE_JOINED"; private static final String CONFERENCE_JOINED_NAME = "CONFERENCE_JOINED";
@ -90,6 +91,7 @@ public class BroadcastEvent {
private static final String PARTICIPANT_JOINED_NAME = "PARTICIPANT_JOINED"; private static final String PARTICIPANT_JOINED_NAME = "PARTICIPANT_JOINED";
private static final String PARTICIPANT_LEFT_NAME = "PARTICIPANT_LEFT"; private static final String PARTICIPANT_LEFT_NAME = "PARTICIPANT_LEFT";
private static final String ENDPOINT_TEXT_MESSAGE_RECEIVED_NAME = "ENDPOINT_TEXT_MESSAGE_RECEIVED"; private static final String ENDPOINT_TEXT_MESSAGE_RECEIVED_NAME = "ENDPOINT_TEXT_MESSAGE_RECEIVED";
private static final String SCREEN_SHARE_TOGGLED_NAME= "SCREEN_SHARE_TOGGLED";
private final String action; private final String action;
@ -126,6 +128,8 @@ public class BroadcastEvent {
return PARTICIPANT_LEFT; return PARTICIPANT_LEFT;
case ENDPOINT_TEXT_MESSAGE_RECEIVED_NAME: case ENDPOINT_TEXT_MESSAGE_RECEIVED_NAME:
return ENDPOINT_TEXT_MESSAGE_RECEIVED; return ENDPOINT_TEXT_MESSAGE_RECEIVED;
case SCREEN_SHARE_TOGGLED_NAME:
return SCREEN_SHARE_TOGGLED;
} }
return null; return null;

View File

@ -19,4 +19,8 @@ public class BroadcastIntentHelper {
intent.putExtra("message", message); intent.putExtra("message", message);
return intent; return intent;
} }
public static Intent buildToggleScreenShareIntent() {
return new Intent(BroadcastAction.Type.TOGGLE_SCREEN_SHARE.getAction());
}
} }

View File

@ -16,9 +16,10 @@ public class BroadcastReceiver extends android.content.BroadcastReceiver {
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context); LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
IntentFilter intentFilter = new IntentFilter(); IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BroadcastAction.Type.SET_AUDIO_MUTED.getAction());
intentFilter.addAction(BroadcastAction.Type.HANG_UP.getAction()); for (BroadcastAction.Type type : BroadcastAction.Type.values()) {
intentFilter.addAction(BroadcastAction.Type.SEND_ENDPOINT_TEXT_MESSAGE.getAction()); intentFilter.addAction(type.getAction());
}
localBroadcastManager.registerReceiver(this, intentFilter); localBroadcastManager.registerReceiver(this, intentFilter);
} }

View File

@ -78,6 +78,7 @@ class ExternalAPIModule
constants.put("SET_AUDIO_MUTED", BroadcastAction.Type.SET_AUDIO_MUTED.getAction()); constants.put("SET_AUDIO_MUTED", BroadcastAction.Type.SET_AUDIO_MUTED.getAction());
constants.put("HANG_UP", BroadcastAction.Type.HANG_UP.getAction()); constants.put("HANG_UP", BroadcastAction.Type.HANG_UP.getAction());
constants.put("SEND_ENDPOINT_TEXT_MESSAGE", BroadcastAction.Type.SEND_ENDPOINT_TEXT_MESSAGE.getAction()); constants.put("SEND_ENDPOINT_TEXT_MESSAGE", BroadcastAction.Type.SEND_ENDPOINT_TEXT_MESSAGE.getAction());
constants.put("TOGGLE_SCREEN_SHARE", BroadcastAction.Type.TOGGLE_SCREEN_SHARE.getAction());
return constants; return constants;
} }

View File

@ -266,12 +266,10 @@ public class JitsiMeetActivity extends FragmentActivity
private void registerForBroadcastMessages() { private void registerForBroadcastMessages() {
IntentFilter intentFilter = new IntentFilter(); IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BroadcastEvent.Type.CONFERENCE_JOINED.getAction());
intentFilter.addAction(BroadcastEvent.Type.CONFERENCE_WILL_JOIN.getAction()); for (BroadcastEvent.Type type : BroadcastEvent.Type.values()) {
intentFilter.addAction(BroadcastEvent.Type.CONFERENCE_TERMINATED.getAction()); intentFilter.addAction(type.getAction());
intentFilter.addAction(BroadcastEvent.Type.PARTICIPANT_JOINED.getAction()); }
intentFilter.addAction(BroadcastEvent.Type.PARTICIPANT_LEFT.getAction());
intentFilter.addAction(BroadcastEvent.Type.ENDPOINT_TEXT_MESSAGE_RECEIVED.getAction());
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, intentFilter); LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, intentFilter);
} }

View File

@ -115,10 +115,14 @@
NSLog(@"%@%@", @"Audio muted changed: ", data[@"muted"]); NSLog(@"%@%@", @"Audio muted changed: ", data[@"muted"]);
} }
- (void)endpointTextMessageReceived:(NSDictionary *)data; { - (void)endpointTextMessageReceived:(NSDictionary *)data {
NSLog(@"%@%@", @"Endpoint text message received: ", data); NSLog(@"%@%@", @"Endpoint text message received: ", data);
} }
- (void)screenShareToggled:(NSDictionary *)data {
NSLog(@"%@%@", @"Screen share toggled: ", data);
}
#pragma mark - Helpers #pragma mark - Helpers
- (void)terminate { - (void)terminate {

View File

@ -21,5 +21,6 @@
- (void)sendHangUp; - (void)sendHangUp;
- (void)sendSetAudioMuted: (BOOL)muted; - (void)sendSetAudioMuted: (BOOL)muted;
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message; - (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message;
- (void)toggleScreenShare;
@end @end

View File

@ -21,6 +21,7 @@
static NSString * const hangUpAction = @"org.jitsi.meet.HANG_UP"; static NSString * const hangUpAction = @"org.jitsi.meet.HANG_UP";
static NSString * const setAudioMutedAction = @"org.jitsi.meet.SET_AUDIO_MUTED"; static NSString * const setAudioMutedAction = @"org.jitsi.meet.SET_AUDIO_MUTED";
static NSString * const sendEndpointTextMessageAction = @"org.jitsi.meet.SEND_ENDPOINT_TEXT_MESSAGE"; static NSString * const sendEndpointTextMessageAction = @"org.jitsi.meet.SEND_ENDPOINT_TEXT_MESSAGE";
static NSString * const toggleScreenShareAction = @"org.jitsi.meet.TOGGLE_SCREEN_SHARE";
@implementation ExternalAPI @implementation ExternalAPI
@ -30,7 +31,8 @@ RCT_EXPORT_MODULE();
return @{ return @{
@"HANG_UP": hangUpAction, @"HANG_UP": hangUpAction,
@"SET_AUDIO_MUTED" : setAudioMutedAction, @"SET_AUDIO_MUTED" : setAudioMutedAction,
@"SEND_ENDPOINT_TEXT_MESSAGE": sendEndpointTextMessageAction @"SEND_ENDPOINT_TEXT_MESSAGE": sendEndpointTextMessageAction,
@"TOGGLE_SCREEN_SHARE": toggleScreenShareAction
}; };
}; };
@ -46,7 +48,7 @@ RCT_EXPORT_MODULE();
} }
- (NSArray<NSString *> *)supportedEvents { - (NSArray<NSString *> *)supportedEvents {
return @[ hangUpAction, setAudioMutedAction, sendEndpointTextMessageAction ]; return @[ hangUpAction, setAudioMutedAction, sendEndpointTextMessageAction, toggleScreenShareAction ];
} }
/** /**
@ -123,4 +125,8 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
[self sendEventWithName:sendEndpointTextMessageAction body:data]; [self sendEventWithName:sendEndpointTextMessageAction body:data];
} }
- (void)toggleScreenShare {
[self sendEventWithName:toggleScreenShareAction body:nil];
}
@end @end

View File

@ -43,4 +43,6 @@
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message; - (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message;
- (void)toggleScreenShare;
@end @end

View File

@ -130,6 +130,11 @@ static void initializeViewsMap() {
[externalAPI sendEndpointTextMessage:to :message]; [externalAPI sendEndpointTextMessage:to :message];
} }
- (void)toggleScreenShare {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI toggleScreenShare];
}
#pragma mark Private methods #pragma mark Private methods
/** /**

View File

@ -83,4 +83,11 @@
*/ */
- (void)endpointTextMessageReceived:(NSDictionary *)data; - (void)endpointTextMessageReceived:(NSDictionary *)data;
/**
* Called when a participant toggled shared screen.
*
* The `data` dictionary contains a `participantId` key with the id of the participant and a 'sharing' key with boolean value.
*/
- (void)screenShareToggled:(NSDictionary *)data;
@end @end

View File

@ -4,6 +4,7 @@ import '../authentication/reducer';
import '../mobile/audio-mode/reducer'; import '../mobile/audio-mode/reducer';
import '../mobile/background/reducer'; import '../mobile/background/reducer';
import '../mobile/call-integration/reducer'; import '../mobile/call-integration/reducer';
import '../mobile/external-api/reducer';
import '../mobile/full-screen/reducer'; import '../mobile/full-screen/reducer';
import '../mobile/incoming-call/reducer'; import '../mobile/incoming-call/reducer';
import '../mobile/watchos/reducer'; import '../mobile/watchos/reducer';

View File

@ -0,0 +1,11 @@
/**
* The type of the action which sets the list of known participant IDs which
* have an active screen share.
*
* @returns {{
* type: SCREEN_SHARE_PARTICIPANTS_UPDATED,
* participantIds: Array<string>
* }}
*/
export const SCREEN_SHARE_PARTICIPANTS_UPDATED
= 'SCREEN_SHARE_PARTICIPANTS_UPDATED';

View File

@ -0,0 +1,21 @@
// @flow
import { SCREEN_SHARE_PARTICIPANTS_UPDATED } from './actionTypes';
/**
* Creates a (redux) action which signals that the list of known participants
* with screen shares has changed.
*
* @param {string} participantIds - The participants which currently have active
* screen share streams.
* @returns {{
* type: SCREEN_SHARE_PARTICIPANTS_UPDATED,
* participantId: string
* }}
*/
export function setParticipantsWithScreenShare(participantIds: Array<string>) {
return {
type: SCREEN_SHARE_PARTICIPANTS_UPDATED,
participantIds
};
}

View File

@ -1,5 +1,6 @@
// @flow // @flow
import debounce from 'lodash/debounce';
import { NativeEventEmitter, NativeModules } from 'react-native'; import { NativeEventEmitter, NativeModules } from 'react-native';
import { ENDPOINT_TEXT_MESSAGE_NAME } from '../../../../modules/API/constants'; import { ENDPOINT_TEXT_MESSAGE_NAME } from '../../../../modules/API/constants';
@ -27,10 +28,12 @@ import {
import { JitsiConferenceEvents } from '../../base/lib-jitsi-meet'; import { JitsiConferenceEvents } from '../../base/lib-jitsi-meet';
import { SET_AUDIO_MUTED } from '../../base/media/actionTypes'; import { SET_AUDIO_MUTED } from '../../base/media/actionTypes';
import { PARTICIPANT_JOINED, PARTICIPANT_LEFT } from '../../base/participants'; import { PARTICIPANT_JOINED, PARTICIPANT_LEFT } from '../../base/participants';
import { MiddlewareRegistry } from '../../base/redux'; import { MiddlewareRegistry, StateListenerRegistry } from '../../base/redux';
import { toggleScreensharing } from '../../base/tracks';
import { muteLocal } from '../../remote-video-menu/actions'; import { muteLocal } from '../../remote-video-menu/actions';
import { ENTER_PICTURE_IN_PICTURE } from '../picture-in-picture'; import { ENTER_PICTURE_IN_PICTURE } from '../picture-in-picture';
import { setParticipantsWithScreenShare } from './actions';
import { sendEvent } from './functions'; import { sendEvent } from './functions';
import logger from './logger'; import logger from './logger';
@ -46,6 +49,12 @@ const CONFERENCE_TERMINATED = 'CONFERENCE_TERMINATED';
*/ */
const ENDPOINT_TEXT_MESSAGE_RECEIVED = 'ENDPOINT_TEXT_MESSAGE_RECEIVED'; const ENDPOINT_TEXT_MESSAGE_RECEIVED = 'ENDPOINT_TEXT_MESSAGE_RECEIVED';
/**
* Event which will be emitted on the native side to indicate a participant togggles
* the screen share.
*/
const SCREEN_SHARE_TOGGLED = 'SCREEN_SHARE_TOGGLED';
const { ExternalAPI } = NativeModules; const { ExternalAPI } = NativeModules;
const eventEmitter = new NativeEventEmitter(ExternalAPI); const eventEmitter = new NativeEventEmitter(ExternalAPI);
@ -171,6 +180,48 @@ MiddlewareRegistry.register(store => next => action => {
return result; return result;
}); });
/**
* Listen for changes to the known media tracks and look
* for updates to screen shares for emitting native events.
* The listener is debounced to avoid state thrashing that might occur,
* especially when switching in or out of p2p.
*/
StateListenerRegistry.register(
/* selector */ state => state['features/base/tracks'],
/* listener */ debounce((tracks, store) => {
const oldScreenShares = store.getState()['features/mobile/external-api'].screenShares || [];
const newScreenShares = tracks
.filter(track => track.mediaType === 'video' && track.videoType === 'desktop')
.map(track => track.participantId);
oldScreenShares.forEach(participantId => {
if (!newScreenShares.includes(participantId)) {
sendEvent(
store,
SCREEN_SHARE_TOGGLED,
/* data */ {
participantId,
sharing: false
});
}
});
newScreenShares.forEach(participantId => {
if (!oldScreenShares.includes(participantId)) {
sendEvent(
store,
SCREEN_SHARE_TOGGLED,
/* data */ {
participantId,
sharing: true
});
}
});
store.dispatch(setParticipantsWithScreenShare(newScreenShares));
}, 100));
/** /**
* Registers for events sent from the native side via NativeEventEmitter. * Registers for events sent from the native side via NativeEventEmitter.
* *
@ -199,6 +250,10 @@ function _registerForNativeEvents({ getState, dispatch }) {
logger.warn('Cannot send endpointMessage', error); logger.warn('Cannot send endpointMessage', error);
} }
}); });
eventEmitter.addListener(ExternalAPI.TOGGLE_SCREEN_SHARE, () => {
dispatch(toggleScreensharing());
});
} }
/** /**

View File

@ -0,0 +1,22 @@
// @flow
import { ReducerRegistry } from '../../base/redux';
import { SCREEN_SHARE_PARTICIPANTS_UPDATED } from './actionTypes';
const DEFAULT_STATE = {
screenShares: []
};
ReducerRegistry.register('features/mobile/external-api', (state = DEFAULT_STATE, action) => {
switch (action.type) {
case SCREEN_SHARE_PARTICIPANTS_UPDATED: {
return {
...state,
screenShares: action.participantIds
};
}
}
return state;
});