feat(mobile) adds ability to retrieve participantsInfo array
This commit is contained in:
parent
20c6115c38
commit
d2568b874b
|
@ -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')) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -22,5 +22,6 @@
|
|||
- (void)sendSetAudioMuted: (BOOL)muted;
|
||||
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message;
|
||||
- (void)toggleScreenShare;
|
||||
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completion;
|
||||
|
||||
@end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -45,4 +45,6 @@
|
|||
|
||||
- (void)toggleScreenShare;
|
||||
|
||||
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler;
|
||||
|
||||
@end
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue