[RN] Add an example how to consume the public SDK invite API
This commit is contained in:
parent
85612b9ae1
commit
7ffdaf59c7
|
@ -23,11 +23,15 @@ import org.jitsi.meet.sdk.JitsiMeetActivity;
|
|||
import org.jitsi.meet.sdk.JitsiMeetView;
|
||||
import org.jitsi.meet.sdk.JitsiMeetViewListener;
|
||||
import org.jitsi.meet.sdk.invite.AddPeopleController;
|
||||
import org.jitsi.meet.sdk.invite.AddPeopleControllerListener;
|
||||
import org.jitsi.meet.sdk.invite.InviteController;
|
||||
import org.jitsi.meet.sdk.invite.InviteControllerListener;
|
||||
|
||||
import com.calendarevents.CalendarEventsPackage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -43,6 +47,14 @@ import java.util.Map;
|
|||
* {@code react-native run-android}.
|
||||
*/
|
||||
public class MainActivity extends JitsiMeetActivity {
|
||||
/**
|
||||
* The query to perform through {@link AddPeopleController} when the
|
||||
* {@code InviteButton} is tapped in order to exercise the public API of the
|
||||
* feature invite. If {@code null}, the {@code InviteButton} will not be
|
||||
* rendered.
|
||||
*/
|
||||
private static final String ADD_PEOPLE_CONTROLLER_QUERY = null;
|
||||
|
||||
@Override
|
||||
protected JitsiMeetView initializeView() {
|
||||
JitsiMeetView view = super.initializeView();
|
||||
|
@ -93,23 +105,68 @@ public class MainActivity extends JitsiMeetActivity {
|
|||
}
|
||||
});
|
||||
|
||||
view.getInviteController().setListener(
|
||||
new InviteControllerListener() {
|
||||
public void beginAddPeople(
|
||||
AddPeopleController addPeopleController) {
|
||||
// Log with the tag "ReactNative" in order to have the
|
||||
// log visible in react-native log-android as well.
|
||||
Log.d(
|
||||
"ReactNative",
|
||||
InviteControllerListener.class.getSimpleName()
|
||||
+ ".beginAddPeople");
|
||||
}
|
||||
});
|
||||
// inviteController
|
||||
final InviteController inviteController
|
||||
= view.getInviteController();
|
||||
|
||||
inviteController.setListener(new InviteControllerListener() {
|
||||
public void beginAddPeople(
|
||||
AddPeopleController addPeopleController) {
|
||||
onInviteControllerBeginAddPeople(
|
||||
inviteController,
|
||||
addPeopleController);
|
||||
}
|
||||
});
|
||||
inviteController.setAddPeopleEnabled(
|
||||
ADD_PEOPLE_CONTROLLER_QUERY != null);
|
||||
inviteController.setDialOutEnabled(
|
||||
inviteController.isAddPeopleEnabled());
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private void onAddPeopleControllerInviteSettled(
|
||||
AddPeopleController addPeopleController,
|
||||
List<Map<String, Object>> failedInvitees) {
|
||||
// XXX Explicitly invoke endAddPeople on addPeopleController; otherwise,
|
||||
// it is going to be memory-leaked in the associated InviteController
|
||||
// and no subsequent InviteButton clicks/taps will be delivered.
|
||||
// Technically, endAddPeople will automatically be invoked if there are
|
||||
// no failedInviteees i.e. the invite succeeeded for all specified
|
||||
// invitees.
|
||||
addPeopleController.endAddPeople();
|
||||
}
|
||||
|
||||
private void onAddPeopleControllerReceivedResults(
|
||||
AddPeopleController addPeopleController,
|
||||
List<Map<String, Object>> results,
|
||||
String query) {
|
||||
int size = results.size();
|
||||
|
||||
if (size > 0) {
|
||||
// Exercise AddPeopleController's inviteById implementation.
|
||||
List<String> ids = new ArrayList<>(size);
|
||||
|
||||
for (Map<String, Object> result : results) {
|
||||
Object id = result.get("id");
|
||||
|
||||
if (id != null) {
|
||||
ids.add(id.toString());
|
||||
}
|
||||
}
|
||||
|
||||
addPeopleController.inviteById(ids);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX Explicitly invoke endAddPeople on addPeopleController; otherwise,
|
||||
// it is going to be memory-leaked in the associated InviteController
|
||||
// and no subsequent InviteButton clicks/taps will be delivered.
|
||||
addPeopleController.endAddPeople();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
// As this is the Jitsi Meet app (i.e. not the Jitsi Meet SDK), we do
|
||||
|
@ -122,9 +179,61 @@ public class MainActivity extends JitsiMeetActivity {
|
|||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
private void onInviteControllerBeginAddPeople(
|
||||
InviteController inviteController,
|
||||
AddPeopleController addPeopleController) {
|
||||
// Log with the tag "ReactNative" in order to have the log visible in
|
||||
// react-native log-android as well.
|
||||
Log.d(
|
||||
"ReactNative",
|
||||
InviteControllerListener.class.getSimpleName() + ".beginAddPeople");
|
||||
|
||||
String query = ADD_PEOPLE_CONTROLLER_QUERY;
|
||||
|
||||
if (query != null
|
||||
&& (inviteController.isAddPeopleEnabled()
|
||||
|| inviteController.isDialOutEnabled())) {
|
||||
addPeopleController.setListener(new AddPeopleControllerListener() {
|
||||
public void onInviteSettled(
|
||||
AddPeopleController addPeopleController,
|
||||
List<Map<String, Object>> failedInvitees) {
|
||||
onAddPeopleControllerInviteSettled(
|
||||
addPeopleController,
|
||||
failedInvitees);
|
||||
}
|
||||
|
||||
public void onReceivedResults(
|
||||
AddPeopleController addPeopleController,
|
||||
List<Map<String, Object>> results,
|
||||
String query) {
|
||||
onAddPeopleControllerReceivedResults(
|
||||
addPeopleController,
|
||||
results, query);
|
||||
}
|
||||
});
|
||||
addPeopleController.performQuery(query);
|
||||
} else {
|
||||
// XXX Explicitly invoke endAddPeople on addPeopleController;
|
||||
// otherwise, it is going to be memory-leaked in the associated
|
||||
// InviteController and no subsequent InviteButton clicks/taps will
|
||||
// be delivered.
|
||||
addPeopleController.endAddPeople();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
CalendarEventsPackage.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
public void onRequestPermissionsResult(
|
||||
int requestCode,
|
||||
String[] permissions,
|
||||
int[] grantResults) {
|
||||
CalendarEventsPackage.onRequestPermissionsResult(
|
||||
requestCode,
|
||||
permissions,
|
||||
grantResults);
|
||||
|
||||
super.onRequestPermissionsResult(
|
||||
requestCode,
|
||||
permissions,
|
||||
grantResults);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,6 +122,11 @@ public class JitsiMeetActivity extends AppCompatActivity {
|
|||
JitsiMeetView view = initializeView();
|
||||
|
||||
if (view != null) {
|
||||
// XXX Allow extenders who override initializeView() to configure
|
||||
// the view before the first loadURL(). Probably works around a
|
||||
// problem related to ReactRootView#setAppProperties().
|
||||
view.loadURL(null);
|
||||
|
||||
this.view = view;
|
||||
setContentView(this.view);
|
||||
}
|
||||
|
@ -144,8 +149,6 @@ public class JitsiMeetActivity extends AppCompatActivity {
|
|||
}
|
||||
view.setWelcomePageEnabled(welcomePageEnabled);
|
||||
|
||||
view.loadURL(null);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ public class AddPeopleController {
|
|||
|
||||
if(items.containsKey(id)) {
|
||||
WritableNativeMap map = new WritableNativeMap();
|
||||
map.merge(items.get(ids));
|
||||
map.merge(items.get(id));
|
||||
invitees.pushMap(map);
|
||||
} else {
|
||||
// If the id doesn't exist in the map, we can't do anything,
|
||||
|
@ -138,14 +138,14 @@ public class AddPeopleController {
|
|||
jFailedInvitees.add(failedInvitees.getMap(i).toHashMap());
|
||||
}
|
||||
|
||||
listener.inviteSettled(this, jFailedInvitees);
|
||||
listener.onInviteSettled(this, jFailedInvitees);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a search for entities to invite with the given query. Results will
|
||||
* be returned through the associated AddPeopleControllerListener's
|
||||
* onReceiveResults method.
|
||||
* onReceivedResults method.
|
||||
*
|
||||
* @param query
|
||||
*/
|
||||
|
@ -188,7 +188,7 @@ public class AddPeopleController {
|
|||
jvmResults.add(map.toHashMap());
|
||||
}
|
||||
|
||||
listener.onReceiveResults(this, jvmResults, query);
|
||||
listener.onReceivedResults(this, jvmResults, query);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,29 +21,36 @@ import java.util.Map;
|
|||
|
||||
public interface AddPeopleControllerListener {
|
||||
/**
|
||||
* Called when results are received for a query called through AddPeopleController.query()
|
||||
* Called when the call to {@link AddPeopleController#inviteById(List)}
|
||||
* completes.
|
||||
*
|
||||
* @param addPeopleController
|
||||
* @param results a List of Map<String, Object> objects that represent items returned by the query.
|
||||
* The object at key "type" describes the type of item: "user", "videosipgw" (conference room), or "phone".
|
||||
* "user" types have properties at "id", "name", and "avatar"
|
||||
* "videosipgw" types have properties at "id" and "name"
|
||||
* "phone" types have properties at "number", "title", "and "subtitle"
|
||||
* @param query the query that generated the given results
|
||||
* @param addPeopleController the active {@link AddPeopleController} for
|
||||
* this invite flow. This object should be cleaned up by calling
|
||||
* {@link AddPeopleController#endAddPeople()} if the user exits the invite
|
||||
* flow. Otherwise, it can stay active if the user will attempt to invite
|
||||
* @param failedInvitees a {@code List} of {@code Map<String, Object>}
|
||||
* dictionaries that represent the invitations that failed. The data type of
|
||||
* the objects is identical to the results returned in onReceivedResuls.
|
||||
*/
|
||||
void onReceiveResults(AddPeopleController addPeopleController, List<Map<String, Object>> results, String query);
|
||||
void onInviteSettled(
|
||||
AddPeopleController addPeopleController,
|
||||
List<Map<String, Object>> failedInvitees);
|
||||
|
||||
/**
|
||||
* Called when the call to {@link AddPeopleController#inviteById(List)} completes, but the
|
||||
* invitation fails for one or more of the selected items.
|
||||
* Called when results are received for a query called through
|
||||
* AddPeopleController.query().
|
||||
*
|
||||
* @param addPeopleController the active {@link AddPeopleController} for this invite flow. This object
|
||||
* should be cleaned up by calling {@link AddPeopleController#endAddPeople()} if
|
||||
* the user exits the invite flow. Otherwise, it can stay active if the user
|
||||
* will attempt to invite
|
||||
* @param failedInvitees a {@code List} of {@code Map<String, Object>} dictionaries that represent the
|
||||
* invitations that failed. The data type of the objects is identical to the results
|
||||
* returned in onReceiveResuls.
|
||||
* @param addPeopleController
|
||||
* @param results a List of Map<String, Object> objects that represent items
|
||||
* returned by the query. The object at key "type" describes the type of
|
||||
* item: "user", "videosipgw" (conference room), or "phone". "user" types
|
||||
* have properties at "id", "name", and "avatar". "videosipgw" types have
|
||||
* properties at "id" and "name". "phone" types have properties at "number",
|
||||
* "title", "and "subtitle"
|
||||
* @param query the query that generated the given results
|
||||
*/
|
||||
void inviteSettled(AddPeopleController addPeopleController, List<Map<String, Object>> failedInvitees);
|
||||
void onReceivedResults(
|
||||
AddPeopleController addPeopleController,
|
||||
List<Map<String, Object>> results,
|
||||
String query);
|
||||
}
|
||||
|
|
|
@ -61,10 +61,6 @@ public class InviteController {
|
|||
this.externalAPIScope = externalAPIScope;
|
||||
}
|
||||
|
||||
public InviteControllerListener getListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
void beginAddPeople(ReactApplicationContext reactContext) {
|
||||
InviteControllerListener listener = getListener();
|
||||
|
||||
|
@ -102,6 +98,10 @@ public class InviteController {
|
|||
}
|
||||
}
|
||||
|
||||
public InviteControllerListener getListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends JavaScript event to submit invitations to the given item ids
|
||||
*
|
||||
|
@ -203,7 +203,7 @@ public class InviteController {
|
|||
|
||||
/**
|
||||
* Starts a query for users to invite to the conference. Results will be
|
||||
* returned through the {@link AddPeopleControllerListener#onReceiveResults(AddPeopleController, List, String)}
|
||||
* returned through the {@link AddPeopleControllerListener#onReceivedResults(AddPeopleController, List, String)}
|
||||
* method.
|
||||
*
|
||||
* @param query {@code String} to use for the query
|
||||
|
@ -211,8 +211,8 @@ public class InviteController {
|
|||
void performQuery(AddPeopleController addPeopleController, String query) {
|
||||
WritableNativeMap params = new WritableNativeMap();
|
||||
|
||||
params.putString("externalAPIScope", externalAPIScope);
|
||||
params.putString("addPeopleControllerScope", addPeopleController.getUuid());
|
||||
params.putString("externalAPIScope", externalAPIScope);
|
||||
params.putString("query", query);
|
||||
ReactContextUtils.emitEvent(
|
||||
addPeopleController.getReactApplicationContext(),
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
#import <JitsiMeet/JitsiMeet.h>
|
||||
|
||||
@interface ViewController : UIViewController<JitsiMeetViewDelegate, JMInviteControllerDelegate>
|
||||
@interface ViewController
|
||||
: UIViewController<
|
||||
JitsiMeetViewDelegate,
|
||||
JMAddPeopleControllerDelegate,
|
||||
JMInviteControllerDelegate>
|
||||
|
||||
@end
|
||||
|
|
|
@ -16,6 +16,13 @@
|
|||
|
||||
#import "ViewController.h"
|
||||
|
||||
/**
|
||||
* The query to perform through JMAddPeopleController when the InviteButton is
|
||||
* tapped in order to exercise the public API of the feature invite. If nil, the
|
||||
* InviteButton will not be rendered.
|
||||
*/
|
||||
static NSString * const ADD_PEOPLE_CONTROLLER_QUERY = nil;
|
||||
|
||||
@interface ViewController ()
|
||||
|
||||
@end
|
||||
|
@ -31,7 +38,12 @@
|
|||
|
||||
view.delegate = self;
|
||||
|
||||
view.inviteController.delegate = self;
|
||||
// inviteController
|
||||
JMInviteController *inviteController = view.inviteController;
|
||||
inviteController.delegate = self;
|
||||
inviteController.addPeopleEnabled
|
||||
= inviteController.dialOutEnabled
|
||||
= ADD_PEOPLE_CONTROLLER_QUERY != nil;
|
||||
|
||||
#endif // #ifdef DEBUG
|
||||
|
||||
|
@ -46,6 +58,8 @@
|
|||
|
||||
#if DEBUG
|
||||
|
||||
// JitsiMeetViewDelegate
|
||||
|
||||
void _onJitsiMeetViewDelegateEvent(NSString *name, NSDictionary *data) {
|
||||
NSLog(
|
||||
@"[%s:%d] JitsiMeetViewDelegate %@ %@",
|
||||
|
@ -76,14 +90,72 @@ void _onJitsiMeetViewDelegateEvent(NSString *name, NSDictionary *data) {
|
|||
_onJitsiMeetViewDelegateEvent(@"LOAD_CONFIG_ERROR", data);
|
||||
}
|
||||
|
||||
// JMInviteControllerDelegate
|
||||
|
||||
- (void)beginAddPeople:(JMAddPeopleController *)addPeopleController {
|
||||
NSLog(
|
||||
@"[%s:%d] JMInviteControllerDelegate %s",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
NSString *query = ADD_PEOPLE_CONTROLLER_QUERY;
|
||||
JitsiMeetView *view = (JitsiMeetView *) self.view;
|
||||
JMInviteController *inviteController = view.inviteController;
|
||||
|
||||
if (query
|
||||
&& (inviteController.addPeopleEnabled
|
||||
|| inviteController.dialOutEnabled)) {
|
||||
addPeopleController.delegate = self;
|
||||
[addPeopleController performQuery:query];
|
||||
} else {
|
||||
// XXX Explicitly invoke endAddPeople on addPeopleController; otherwise,
|
||||
// it is going to be memory-leaked in the associated JMInviteController
|
||||
// and no subsequent InviteButton clicks/taps will be delivered.
|
||||
[addPeopleController endAddPeople];
|
||||
}
|
||||
}
|
||||
|
||||
// JMAddPeopleControllerDelegate
|
||||
|
||||
- (void)addPeopleController:(JMAddPeopleController * _Nonnull)controller
|
||||
didReceiveResults:(NSArray<NSDictionary *> * _Nonnull)results
|
||||
forQuery:(NSString * _Nonnull)query {
|
||||
NSUInteger count = results.count;
|
||||
|
||||
if (count) {
|
||||
// Exercise JMAddPeopleController's inviteById: implementation.
|
||||
NSMutableArray *ids = [NSMutableArray arrayWithCapacity:count];
|
||||
|
||||
for (NSUInteger i = 0; i < count; ++i) {
|
||||
ids[i] = results[i][@"id"];
|
||||
}
|
||||
|
||||
[controller inviteById:ids];
|
||||
|
||||
// Exercise JMInviteController's invite:withCompletion: implementation.
|
||||
//
|
||||
// XXX Technically, only at most one of the two exercises will result in
|
||||
// an actual invitation eventually.
|
||||
JitsiMeetView *view = (JitsiMeetView *) self.view;
|
||||
JMInviteController *inviteController = view.inviteController;
|
||||
|
||||
[inviteController invite:results withCompletion:nil];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX Explicitly invoke endAddPeople on addPeopleController; otherwise, it
|
||||
// is going to be memory-leaked in the associated JMInviteController and no
|
||||
// subsequent InviteButton clicks/taps will be delivered.
|
||||
[controller endAddPeople];
|
||||
}
|
||||
|
||||
- (void) inviteSettled:(NSArray<NSDictionary *> * _Nonnull)failedInvitees
|
||||
fromSearchController:(JMAddPeopleController * _Nonnull)addPeopleController {
|
||||
// XXX Explicitly invoke endAddPeople on addPeopleController; otherwise, it
|
||||
// is going to be memory-leaked in the associated JMInviteController and no
|
||||
// subsequent InviteButton clicks/taps will be delivered. Technically,
|
||||
// endAddPeople will automatically be invoked if there are no
|
||||
// failedInviteees i.e. the invite succeeeded for all specified invitees.
|
||||
[addPeopleController endAddPeople];
|
||||
}
|
||||
|
||||
|
|
|
@ -70,15 +70,6 @@ class InviteButton extends Component<Props> {
|
|||
...props
|
||||
} = this.props;
|
||||
|
||||
if (_SHARE_ROOM_TOOLBAR_BUTTON) {
|
||||
return (
|
||||
<ToolbarButton
|
||||
iconName = 'link'
|
||||
onClick = { _onShareRoom }
|
||||
{ ...props } />
|
||||
);
|
||||
}
|
||||
|
||||
if (_addPeopleEnabled || _dialOutEnabled) {
|
||||
return (
|
||||
<ToolbarButton
|
||||
|
@ -88,6 +79,15 @@ class InviteButton extends Component<Props> {
|
|||
);
|
||||
}
|
||||
|
||||
if (_SHARE_ROOM_TOOLBAR_BUTTON) {
|
||||
return (
|
||||
<ToolbarButton
|
||||
iconName = 'link'
|
||||
onClick = { _onShareRoom }
|
||||
{ ...props } />
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue