feat(mobile) adds ability to retrieve participantsInfo array

This commit is contained in:
tmoldovan8x8 2021-02-04 14:26:35 +02:00 committed by GitHub
parent 20c6115c38
commit d2568b874b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 208 additions and 7 deletions

View File

@ -47,6 +47,7 @@ dependencies {
implementation 'com.dropbox.core:dropbox-core-sdk:3.0.8'
implementation 'com.jakewharton.timber:timber:4.7.1'
implementation 'com.squareup.duktape:duktape-android:1.3.0'
implementation 'com.google.code.gson:gson:2.8.6'
if (rootProject.ext.libreBuild) {
implementation(project(':react-native-device-info')) {

View File

@ -62,7 +62,8 @@ public class BroadcastAction {
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"),
TOGGLE_SCREEN_SHARE("org.jitsi.meet.TOGGLE_SCREEN_SHARE");
TOGGLE_SCREEN_SHARE("org.jitsi.meet.TOGGLE_SCREEN_SHARE"),
RETRIEVE_PARTICIPANTS_INFO("org.jitsi.meet.RETRIEVE_PARTICIPANTS_INFO");
private final String action;

View File

@ -82,7 +82,8 @@ public class BroadcastEvent {
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"),
SCREEN_SHARE_TOGGLED("org.jitsi.meet.SCREEN_SHARE_TOGGLED");
SCREEN_SHARE_TOGGLED("org.jitsi.meet.SCREEN_SHARE_TOGGLED"),
PARTICIPANTS_INFO_RETRIEVED("org.jitsi.meet.PARTICIPANTS_INFO_RETRIEVED");
private static final String CONFERENCE_WILL_JOIN_NAME = "CONFERENCE_WILL_JOIN";
private static final String CONFERENCE_JOINED_NAME = "CONFERENCE_JOINED";
@ -91,7 +92,8 @@ 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 static final String SCREEN_SHARE_TOGGLED_NAME = "SCREEN_SHARE_TOGGLED";
private static final String PARTICIPANTS_INFO_RETRIEVED_NAME = "PARTICIPANTS_INFO_RETRIEVED";
private final String action;
@ -130,6 +132,8 @@ public class BroadcastEvent {
return ENDPOINT_TEXT_MESSAGE_RECEIVED;
case SCREEN_SHARE_TOGGLED_NAME:
return SCREEN_SHARE_TOGGLED;
case PARTICIPANTS_INFO_RETRIEVED_NAME:
return PARTICIPANTS_INFO_RETRIEVED;
}
return null;

View File

@ -53,6 +53,8 @@ class ExternalAPIModule
broadcastEmitter = new BroadcastEmitter(reactContext);
broadcastReceiver = new BroadcastReceiver(reactContext);
ParticipantsService.init(reactContext);
}
/**
@ -79,6 +81,7 @@ class ExternalAPIModule
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());
constants.put("RETRIEVE_PARTICIPANTS_INFO", BroadcastAction.Type.RETRIEVE_PARTICIPANTS_INFO.getAction());
return constants;
}

View File

@ -0,0 +1,27 @@
package org.jitsi.meet.sdk;
import com.google.gson.annotations.SerializedName;
public class ParticipantInfo {
@SerializedName("participantId")
public String id;
@SerializedName("displayName")
public String displayName;
@SerializedName("avatarUrl")
public String avatarUrl;
@SerializedName("email")
public String email;
@SerializedName("name")
public String name;
@SerializedName("isLocal")
public boolean isLocal;
@SerializedName("role")
public String role;
}

View File

@ -0,0 +1,90 @@
package org.jitsi.meet.sdk;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Nullable;
public class ParticipantsService extends android.content.BroadcastReceiver {
private static final String TAG = ParticipantsService.class.getSimpleName();
private static final String REQUEST_ID = "requestId";
private final Map<String, WeakReference<ParticipantsInfoCallback>> participantsInfoCallbackMap = new HashMap<>();
private static ParticipantsService instance;
@Nullable
public static ParticipantsService getInstance() {
return instance;
}
private ParticipantsService(Context context) {
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BroadcastEvent.Type.PARTICIPANTS_INFO_RETRIEVED.getAction());
localBroadcastManager.registerReceiver(this, intentFilter);
}
static void init(Context context) {
instance = new ParticipantsService(context);
}
public void retrieveParticipantsInfo(ParticipantsInfoCallback participantsInfoCallback) {
String callbackKey = UUID.randomUUID().toString();
this.participantsInfoCallbackMap.put(callbackKey, new WeakReference<>(participantsInfoCallback));
String actionName = BroadcastAction.Type.RETRIEVE_PARTICIPANTS_INFO.getAction();
WritableMap data = Arguments.createMap();
data.putString(REQUEST_ID, callbackKey);
ReactInstanceManagerHolder.emitEvent(actionName, data);
}
@Override
public void onReceive(Context context, Intent intent) {
BroadcastEvent event = new BroadcastEvent(intent);
switch (event.getType()) {
case PARTICIPANTS_INFO_RETRIEVED:
try {
List<ParticipantInfo> participantInfoList = new Gson().fromJson(
event.getData().get("participantsInfo").toString(),
new TypeToken<ArrayList<ParticipantInfo>>() {
}.getType());
ParticipantsInfoCallback participantsInfoCallback = this.participantsInfoCallbackMap.get(event.getData().get(REQUEST_ID).toString()).get();
if (participantsInfoCallback != null) {
participantsInfoCallback.onReceived(participantInfoList);
this.participantsInfoCallbackMap.remove(participantsInfoCallback);
}
} catch (Exception e) {
JitsiMeetLogger.w(TAG + "error parsing participantsList", e);
}
break;
}
}
public interface ParticipantsInfoCallback {
void onReceived(List<ParticipantInfo> participantInfoList);
}
}

View File

@ -22,5 +22,6 @@
- (void)sendSetAudioMuted: (BOOL)muted;
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message;
- (void)toggleScreenShare;
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completion;
@end

View File

@ -22,9 +22,17 @@ 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";
static NSString * const retrieveParticipantsInfoAction = @"org.jitsi.meet.RETRIEVE_PARTICIPANTS_INFO";
@implementation ExternalAPI
static NSMapTable<NSString*, void (^)(NSArray* participantsInfo)> *participantInfoCompletionHandlers;
__attribute__((constructor))
static void initializeViewsMap() {
participantInfoCompletionHandlers = [NSMapTable strongToWeakObjectsMapTable];
}
RCT_EXPORT_MODULE();
- (NSDictionary *)constantsToExport {
@ -32,7 +40,8 @@ RCT_EXPORT_MODULE();
@"HANG_UP": hangUpAction,
@"SET_AUDIO_MUTED" : setAudioMutedAction,
@"SEND_ENDPOINT_TEXT_MESSAGE": sendEndpointTextMessageAction,
@"TOGGLE_SCREEN_SHARE": toggleScreenShareAction
@"TOGGLE_SCREEN_SHARE": toggleScreenShareAction,
@"RETRIEVE_PARTICIPANTS_INFO": retrieveParticipantsInfoAction
};
};
@ -48,7 +57,11 @@ RCT_EXPORT_MODULE();
}
- (NSArray<NSString *> *)supportedEvents {
return @[ hangUpAction, setAudioMutedAction, sendEndpointTextMessageAction, toggleScreenShareAction ];
return @[ hangUpAction,
setAudioMutedAction,
sendEndpointTextMessageAction,
toggleScreenShareAction,
retrieveParticipantsInfoAction];
}
/**
@ -76,6 +89,11 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
if (!delegate) {
return;
}
if ([name isEqual: @"PARTICIPANTS_INFO_RETRIEVED"]) {
[self onParticipantsInfoRetrieved: data];
return;
}
SEL sel = NSSelectorFromString([self methodNameFromEventName:name]);
@ -84,6 +102,15 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
}
}
- (void) onParticipantsInfoRetrieved:(NSDictionary *)data {
NSArray *participantsInfoArray = [data objectForKey:@"participantsInfo"];
NSString *completionHandlerId = [data objectForKey:@"requestId"];
void (^completionHandler)(NSArray*) = [participantInfoCompletionHandlers objectForKey:completionHandlerId];
completionHandler(participantsInfoArray);
[participantInfoCompletionHandlers removeObjectForKey:completionHandlerId];
}
/**
* Converts a specific event name i.e. redux action type description to a
* method name.
@ -129,4 +156,12 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
[self sendEventWithName:toggleScreenShareAction body:nil];
}
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler {
NSString *completionHandlerId = [[NSUUID UUID] UUIDString];
NSDictionary *data = @{ @"requestId": completionHandlerId};
[participantInfoCompletionHandlers setObject:completionHandler forKey:completionHandlerId];
[self sendEventWithName:retrieveParticipantsInfoAction body:data];
}
@end

View File

@ -45,4 +45,6 @@
- (void)toggleScreenShare;
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler;
@end

View File

@ -135,6 +135,11 @@ static void initializeViewsMap() {
[externalAPI toggleScreenShare];
}
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI retrieveParticipantsInfo:completionHandler];
}
#pragma mark Private methods
/**

View File

@ -27,7 +27,7 @@ import {
} from '../../base/connection';
import { JitsiConferenceEvents } from '../../base/lib-jitsi-meet';
import { SET_AUDIO_MUTED } from '../../base/media/actionTypes';
import { PARTICIPANT_JOINED, PARTICIPANT_LEFT } from '../../base/participants';
import { PARTICIPANT_JOINED, PARTICIPANT_LEFT, getParticipants } from '../../base/participants';
import { MiddlewareRegistry, StateListenerRegistry } from '../../base/redux';
import { toggleScreensharing } from '../../base/tracks';
import { muteLocal } from '../../remote-video-menu/actions';
@ -55,6 +55,11 @@ const ENDPOINT_TEXT_MESSAGE_RECEIVED = 'ENDPOINT_TEXT_MESSAGE_RECEIVED';
*/
const SCREEN_SHARE_TOGGLED = 'SCREEN_SHARE_TOGGLED';
/**
* Event which will be emitted on the native side with the participant info array.
*/
const PARTICIPANTS_INFO_RETRIEVED = 'PARTICIPANTS_INFO_RETRIEVED';
const { ExternalAPI } = NativeModules;
const eventEmitter = new NativeEventEmitter(ExternalAPI);
@ -158,7 +163,10 @@ MiddlewareRegistry.register(store => next => action => {
isLocal: participant.local,
email: participant.email,
name: participant.name,
participantId: participant.id
participantId: participant.id,
displayName: participant.displayName,
avatarUrl: participant.avatarURL,
role: participant.role
});
break;
}
@ -254,6 +262,30 @@ function _registerForNativeEvents({ getState, dispatch }) {
eventEmitter.addListener(ExternalAPI.TOGGLE_SCREEN_SHARE, () => {
dispatch(toggleScreensharing());
});
eventEmitter.addListener(ExternalAPI.RETRIEVE_PARTICIPANTS_INFO, ({ requestId }) => {
const store = getState();
const participantsInfo = getParticipants(store).map(participant => {
return {
isLocal: participant.local,
email: participant.email,
name: participant.name,
participantId: participant.id,
displayName: participant.displayName,
avatarUrl: participant.avatarURL,
role: participant.role
};
});
sendEvent(
store,
PARTICIPANTS_INFO_RETRIEVED,
/* data */ {
participantsInfo,
requestId
});
});
}
/**