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 {
SET_AUDIO_MUTED("org.jitsi.meet.SET_AUDIO_MUTED"),
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;

View File

@ -81,7 +81,8 @@ public class BroadcastEvent {
AUDIO_MUTED_CHANGED("org.jitsi.meet.AUDIO_MUTED_CHANGED"),
PARTICIPANT_JOINED("org.jitsi.meet.PARTICIPANT_JOINED"),
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_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_LEFT_NAME = "PARTICIPANT_LEFT";
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;
@ -126,6 +128,8 @@ public class BroadcastEvent {
return PARTICIPANT_LEFT;
case ENDPOINT_TEXT_MESSAGE_RECEIVED_NAME:
return ENDPOINT_TEXT_MESSAGE_RECEIVED;
case SCREEN_SHARE_TOGGLED_NAME:
return SCREEN_SHARE_TOGGLED;
}
return null;

View File

@ -19,4 +19,8 @@ public class BroadcastIntentHelper {
intent.putExtra("message", message);
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);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BroadcastAction.Type.SET_AUDIO_MUTED.getAction());
intentFilter.addAction(BroadcastAction.Type.HANG_UP.getAction());
intentFilter.addAction(BroadcastAction.Type.SEND_ENDPOINT_TEXT_MESSAGE.getAction());
for (BroadcastAction.Type type : BroadcastAction.Type.values()) {
intentFilter.addAction(type.getAction());
}
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("HANG_UP", BroadcastAction.Type.HANG_UP.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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -83,4 +83,11 @@
*/
- (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

View File

@ -4,6 +4,7 @@ import '../authentication/reducer';
import '../mobile/audio-mode/reducer';
import '../mobile/background/reducer';
import '../mobile/call-integration/reducer';
import '../mobile/external-api/reducer';
import '../mobile/full-screen/reducer';
import '../mobile/incoming-call/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
import debounce from 'lodash/debounce';
import { NativeEventEmitter, NativeModules } from 'react-native';
import { ENDPOINT_TEXT_MESSAGE_NAME } from '../../../../modules/API/constants';
@ -27,10 +28,12 @@ import {
import { JitsiConferenceEvents } from '../../base/lib-jitsi-meet';
import { SET_AUDIO_MUTED } from '../../base/media/actionTypes';
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 { ENTER_PICTURE_IN_PICTURE } from '../picture-in-picture';
import { setParticipantsWithScreenShare } from './actions';
import { sendEvent } from './functions';
import logger from './logger';
@ -46,6 +49,12 @@ const CONFERENCE_TERMINATED = 'CONFERENCE_TERMINATED';
*/
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 eventEmitter = new NativeEventEmitter(ExternalAPI);
@ -171,6 +180,48 @@ MiddlewareRegistry.register(store => next => action => {
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.
*
@ -199,6 +250,10 @@ function _registerForNativeEvents({ getState, dispatch }) {
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;
});