mirror of https://github.com/jitsi/jitsi-meet
We are going to implement the invite dialog *inside* the SDK, so there is no need to have all this machinery anymore.pull/3817/head jitsi-meet_3541
parent
b7133f5717
commit
5f7a515610
@ -1,211 +0,0 @@ |
||||
/* |
||||
* Copyright @ 2017-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.jitsi.meet.sdk.invite; |
||||
|
||||
import android.util.Log; |
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext; |
||||
import com.facebook.react.bridge.ReadableArray; |
||||
import com.facebook.react.bridge.ReadableMap; |
||||
import com.facebook.react.bridge.WritableArray; |
||||
import com.facebook.react.bridge.WritableNativeArray; |
||||
import com.facebook.react.bridge.WritableNativeMap; |
||||
|
||||
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; |
||||
|
||||
/** |
||||
* Controller object used by native code to query and submit user selections for |
||||
* the user invitation flow. |
||||
*/ |
||||
public class AddPeopleController { |
||||
|
||||
/** |
||||
* The AddPeopleControllerListener for this controller, used to pass query |
||||
* results back to the native code that initiated the query. |
||||
*/ |
||||
private AddPeopleControllerListener listener; |
||||
|
||||
/** |
||||
* Local cache of search query results. Used to re-hydrate the list of |
||||
* selected items based on their ids passed to inviteById in order to pass |
||||
* the full item maps back to the JitsiMeetView during submission. |
||||
*/ |
||||
private final Map<String, ReadableMap> items = new HashMap<>(); |
||||
|
||||
private final WeakReference<InviteController> owner; |
||||
|
||||
private final WeakReference<ReactApplicationContext> reactContext; |
||||
|
||||
/** |
||||
* Randomly generated UUID, used for identification in the InviteModule. |
||||
*/ |
||||
private final String uuid = UUID.randomUUID().toString(); |
||||
|
||||
public AddPeopleController( |
||||
InviteController owner, |
||||
ReactApplicationContext reactContext) { |
||||
this.owner = new WeakReference<>(owner); |
||||
this.reactContext = new WeakReference<>(reactContext); |
||||
} |
||||
|
||||
/** |
||||
* Cancel the invitation flow and free memory allocated to the |
||||
* AddPeopleController. After calling this method, this object is invalid - |
||||
* a new AddPeopleController will be passed to the caller through |
||||
* beginAddPeople. |
||||
*/ |
||||
public void endAddPeople() { |
||||
InviteController owner = this.owner.get(); |
||||
|
||||
if (owner != null) { |
||||
owner.endAddPeople(this); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @return the AddPeopleControllerListener for this controller, used to pass |
||||
* query results back to the native code that initiated the query. |
||||
*/ |
||||
public AddPeopleControllerListener getListener() { |
||||
return listener; |
||||
} |
||||
|
||||
final ReactApplicationContext getReactApplicationContext() { |
||||
return reactContext.get(); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @return the unique identifier for this AddPeopleController |
||||
*/ |
||||
public String getUuid() { |
||||
return uuid; |
||||
} |
||||
|
||||
/** |
||||
* Send invites to selected users based on their item ids |
||||
* |
||||
* @param ids |
||||
*/ |
||||
public void inviteById(List<String> ids) { |
||||
InviteController owner = this.owner.get(); |
||||
|
||||
if (owner != null) { |
||||
WritableArray invitees = new WritableNativeArray(); |
||||
|
||||
for(int i = 0, size = ids.size(); i < size; i++) { |
||||
String id = ids.get(i); |
||||
|
||||
if(items.containsKey(id)) { |
||||
WritableNativeMap map = new WritableNativeMap(); |
||||
map.merge(items.get(id)); |
||||
invitees.pushMap(map); |
||||
} else { |
||||
// If the id doesn't exist in the map, we can't do anything,
|
||||
// so just skip it.
|
||||
} |
||||
} |
||||
|
||||
owner.invite(this, invitees); |
||||
} |
||||
} |
||||
|
||||
void inviteSettled(ReadableArray failedInvitees) { |
||||
AddPeopleControllerListener listener = getListener(); |
||||
|
||||
if (listener != null) { |
||||
ArrayList<Map<String, Object>> jFailedInvitees = new ArrayList<>(); |
||||
|
||||
for (int i = 0, size = failedInvitees.size(); i < size; ++i) { |
||||
jFailedInvitees.add(failedInvitees.getMap(i).toHashMap()); |
||||
} |
||||
|
||||
listener.onInviteSettled(this, jFailedInvitees); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Start a search for entities to invite with the given query. Results will |
||||
* be returned through the associated AddPeopleControllerListener's |
||||
* onReceivedResults method. |
||||
* |
||||
* @param query |
||||
*/ |
||||
public void performQuery(String query) { |
||||
InviteController owner = this.owner.get(); |
||||
|
||||
if (owner != null) { |
||||
owner.performQuery(this, query); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Caches results received by the search into a local map for use later when |
||||
* the items are submitted. Submission requires the full map of |
||||
* information, but only the IDs are returned back to the delegate. Using |
||||
* this map means we don't have to send the whole map back to the delegate. |
||||
* |
||||
* @param results |
||||
* @param query |
||||
*/ |
||||
void receivedResultsForQuery(ReadableArray results, String query) { |
||||
AddPeopleControllerListener listener = getListener(); |
||||
|
||||
if (listener != null) { |
||||
List<Map<String, Object>> jvmResults = new ArrayList<>(); |
||||
|
||||
// cache results for use in submission later
|
||||
// convert to jvm array
|
||||
for(int i = 0; i < results.size(); i++) { |
||||
ReadableMap map = results.getMap(i); |
||||
|
||||
if(map.hasKey("id")) { |
||||
items.put(map.getString("id"), map); |
||||
} else if(map.hasKey("type") |
||||
&& map.getString("type").equals("phone") |
||||
&& map.hasKey("number")) { |
||||
items.put(map.getString("number"), map); |
||||
} else { |
||||
Log.w( |
||||
"AddPeopleController", |
||||
"Received result without id and that was not a phone number, so not adding it to suggestions: " |
||||
+ map); |
||||
} |
||||
|
||||
jvmResults.add(map.toHashMap()); |
||||
} |
||||
|
||||
listener.onReceivedResults(this, jvmResults, query); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Sets the AddPeopleControllerListener for this controller, used to pass |
||||
* query results back to the native code that initiated the query. |
||||
* |
||||
* @param listener |
||||
*/ |
||||
public void setListener(AddPeopleControllerListener listener) { |
||||
this.listener = listener; |
||||
} |
||||
} |
@ -1,56 +0,0 @@ |
||||
/* |
||||
* Copyright @ 2017-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.jitsi.meet.sdk.invite; |
||||
|
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
public interface AddPeopleControllerListener { |
||||
/** |
||||
* Called when the call to {@link AddPeopleController#inviteById(List)} |
||||
* completes. |
||||
* |
||||
* @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 onInviteSettled( |
||||
AddPeopleController addPeopleController, |
||||
List<Map<String, Object>> failedInvitees); |
||||
|
||||
/** |
||||
* Called when results are received for a query called through |
||||
* AddPeopleController.query(). |
||||
* |
||||
* @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 onReceivedResults( |
||||
AddPeopleController addPeopleController, |
||||
List<Map<String, Object>> results, |
||||
String query); |
||||
} |
@ -1,265 +0,0 @@ |
||||
/* |
||||
* Copyright @ 2017-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.jitsi.meet.sdk.invite; |
||||
|
||||
import com.facebook.react.bridge.Arguments; |
||||
import com.facebook.react.bridge.ReactApplicationContext; |
||||
import com.facebook.react.bridge.ReactContext; |
||||
import com.facebook.react.bridge.ReadableArray; |
||||
import com.facebook.react.bridge.WritableArray; |
||||
import com.facebook.react.bridge.WritableNativeMap; |
||||
|
||||
import org.jitsi.meet.sdk.ReactContextUtils; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.UUID; |
||||
import java.util.concurrent.Callable; |
||||
import java.util.concurrent.Future; |
||||
import java.util.concurrent.FutureTask; |
||||
|
||||
/** |
||||
* Represents the entry point into the invite feature of Jitsi Meet and is the |
||||
* Java counterpart of the JavaScript {@code InviteButton}. |
||||
*/ |
||||
public class InviteController { |
||||
private AddPeopleController addPeopleController; |
||||
|
||||
/** |
||||
* Whether adding/inviting people by name (as opposed to phone number) is |
||||
* enabled. |
||||
*/ |
||||
private Boolean addPeopleEnabled; |
||||
|
||||
/** |
||||
* Whether adding/inviting people by phone number (as opposed to name) is |
||||
* enabled. |
||||
*/ |
||||
private Boolean dialOutEnabled; |
||||
|
||||
private final String externalAPIScope; |
||||
|
||||
private InviteControllerListener listener; |
||||
|
||||
public InviteController(String externalAPIScope) { |
||||
this.externalAPIScope = externalAPIScope; |
||||
} |
||||
|
||||
void beginAddPeople(ReactApplicationContext reactContext) { |
||||
InviteControllerListener listener = getListener(); |
||||
|
||||
if (listener != null) { |
||||
// XXX For the sake of simplicity and in order to reduce the risk of
|
||||
// memory leaks, allow a single AddPeopleController at a time.
|
||||
AddPeopleController addPeopleController = this.addPeopleController; |
||||
|
||||
if (addPeopleController != null) { |
||||
return; |
||||
} |
||||
|
||||
// Initialize a new AddPeopleController to represent the click/tap
|
||||
// on the InviteButton and notify the InviteControllerListener
|
||||
// about the event.
|
||||
addPeopleController = new AddPeopleController(this, reactContext); |
||||
|
||||
boolean success = false; |
||||
|
||||
this.addPeopleController = addPeopleController; |
||||
try { |
||||
listener.beginAddPeople(addPeopleController); |
||||
success = true; |
||||
} finally { |
||||
if (!success) { |
||||
endAddPeople(addPeopleController); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void endAddPeople(AddPeopleController addPeopleController) { |
||||
if (this.addPeopleController == addPeopleController) { |
||||
this.addPeopleController = null; |
||||
} |
||||
} |
||||
|
||||
public InviteControllerListener getListener() { |
||||
return listener; |
||||
} |
||||
|
||||
/** |
||||
* Sends JavaScript event to submit invitations to the given item ids |
||||
* |
||||
* @param invitees a WritableArray of WritableNativeMaps representing |
||||
* selected items. Each map representing a selected item should match the |
||||
* data passed back in the return from a query. |
||||
*/ |
||||
boolean invite( |
||||
AddPeopleController addPeopleController, |
||||
WritableArray invitees) { |
||||
return |
||||
invite( |
||||
addPeopleController.getUuid(), |
||||
addPeopleController.getReactApplicationContext(), |
||||
invitees); |
||||
} |
||||
|
||||
public Future<List<Map<String, Object>>> invite( |
||||
final List<Map<String, Object>> invitees) { |
||||
final boolean inviteBegan |
||||
= invite( |
||||
UUID.randomUUID().toString(), |
||||
/* reactContext */ null, |
||||
Arguments.makeNativeArray(invitees)); |
||||
FutureTask futureTask |
||||
= new FutureTask(new Callable() { |
||||
@Override |
||||
public List<Map<String, Object>> call() { |
||||
if (inviteBegan) { |
||||
// TODO Complete the returned Future when the invite
|
||||
// settles.
|
||||
return Collections.emptyList(); |
||||
} else { |
||||
// The invite failed to even begin so report that all
|
||||
// invitees failed.
|
||||
return invitees; |
||||
} |
||||
} |
||||
}); |
||||
|
||||
// If the invite failed to even begin, complete the returned Future
|
||||
// already and the Future implementation will report that all invitees
|
||||
// failed.
|
||||
if (!inviteBegan) { |
||||
futureTask.run(); |
||||
} |
||||
|
||||
return futureTask; |
||||
} |
||||
|
||||
private boolean invite( |
||||
String addPeopleControllerScope, |
||||
ReactContext reactContext, |
||||
WritableArray invitees) { |
||||
WritableNativeMap data = new WritableNativeMap(); |
||||
|
||||
data.putString("addPeopleControllerScope", addPeopleControllerScope); |
||||
data.putString("externalAPIScope", externalAPIScope); |
||||
data.putArray("invitees", invitees); |
||||
|
||||
return |
||||
ReactContextUtils.emitEvent( |
||||
reactContext, |
||||
"org.jitsi.meet:features/invite#invite", |
||||
data); |
||||
} |
||||
|
||||
void inviteSettled( |
||||
String addPeopleControllerScope, |
||||
ReadableArray failedInvitees) { |
||||
AddPeopleController addPeopleController = this.addPeopleController; |
||||
|
||||
if (addPeopleController != null |
||||
&& addPeopleController.getUuid().equals( |
||||
addPeopleControllerScope)) { |
||||
try { |
||||
addPeopleController.inviteSettled(failedInvitees); |
||||
} finally { |
||||
if (failedInvitees.size() == 0) { |
||||
endAddPeople(addPeopleController); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public boolean isAddPeopleEnabled() { |
||||
Boolean b = this.addPeopleEnabled; |
||||
|
||||
return |
||||
(b == null || b.booleanValue()) ? (getListener() != null) : false; |
||||
} |
||||
|
||||
public boolean isDialOutEnabled() { |
||||
Boolean b = this.dialOutEnabled; |
||||
|
||||
return |
||||
(b == null || b.booleanValue()) ? (getListener() != null) : false; |
||||
} |
||||
|
||||
/** |
||||
* Starts a query for users to invite to the conference. Results will be |
||||
* returned through |
||||
* {@link AddPeopleControllerListener#onReceivedResults(AddPeopleController, List, String)}. |
||||
* |
||||
* @param query {@code String} to use for the query |
||||
*/ |
||||
void performQuery(AddPeopleController addPeopleController, String query) { |
||||
WritableNativeMap params = new WritableNativeMap(); |
||||
|
||||
params.putString("addPeopleControllerScope", addPeopleController.getUuid()); |
||||
params.putString("externalAPIScope", externalAPIScope); |
||||
params.putString("query", query); |
||||
ReactContextUtils.emitEvent( |
||||
addPeopleController.getReactApplicationContext(), |
||||
"org.jitsi.meet:features/invite#performQuery", |
||||
params); |
||||
} |
||||
|
||||
void receivedResultsForQuery( |
||||
String addPeopleControllerScope, |
||||
String query, |
||||
ReadableArray results) { |
||||
AddPeopleController addPeopleController = this.addPeopleController; |
||||
|
||||
if (addPeopleController != null |
||||
&& addPeopleController.getUuid().equals( |
||||
addPeopleControllerScope)) { |
||||
addPeopleController.receivedResultsForQuery(results, query); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Sets whether the ability to add users to the call is enabled. If this is |
||||
* enabled, an add user button will appear on the {@link JitsiMeetView}. If |
||||
* enabled, and the user taps the add user button, |
||||
* {@link InviteControllerListener#beginAddPeople(AddPeopleController)} |
||||
* will be called. |
||||
* |
||||
* @param addPeopleEnabled {@code true} to enable the add people button; |
||||
* otherwise, {@code false} |
||||
*/ |
||||
public void setAddPeopleEnabled(boolean addPeopleEnabled) { |
||||
this.addPeopleEnabled = Boolean.valueOf(addPeopleEnabled); |
||||
} |
||||
|
||||
/** |
||||
* Sets whether the ability to add phone numbers to the call is enabled. |
||||
* Must be enabled along with {@link #setAddPeopleEnabled(boolean)} to be |
||||
* effective. |
||||
* |
||||
* @param dialOutEnabled {@code true} to enable the ability to add phone |
||||
* numbers to the call; otherwise, {@code false} |
||||
*/ |
||||
public void setDialOutEnabled(boolean dialOutEnabled) { |
||||
this.dialOutEnabled = Boolean.valueOf(dialOutEnabled); |
||||
} |
||||
|
||||
public void setListener(InviteControllerListener listener) { |
||||
this.listener = listener; |
||||
} |
||||
} |
@ -1,29 +0,0 @@ |
||||
/* |
||||
* Copyright @ 2017-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.jitsi.meet.sdk.invite; |
||||
|
||||
public interface InviteControllerListener { |
||||
/** |
||||
* Called when the add user button is tapped. |
||||
* |
||||
* @param addPeopleController {@code AddPeopleController} scoped for this |
||||
* user invite flow. The {@code AddPeopleController} is used to start user |
||||
* queries and accepts an {@code AddPeopleControllerListener} for receiving |
||||
* user query responses. |
||||
*/ |
||||
void beginAddPeople(AddPeopleController addPeopleController); |
||||
} |
@ -1,171 +0,0 @@ |
||||
/* |
||||
* Copyright @ 2017-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.jitsi.meet.sdk.invite; |
||||
|
||||
import android.util.Log; |
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext; |
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule; |
||||
import com.facebook.react.bridge.ReactMethod; |
||||
import com.facebook.react.bridge.ReadableArray; |
||||
import com.facebook.react.bridge.UiThreadUtil; |
||||
|
||||
import org.jitsi.meet.sdk.BaseReactView; |
||||
import org.jitsi.meet.sdk.JitsiMeetView; |
||||
|
||||
/** |
||||
* Implements the react-native module of the feature invite. |
||||
*/ |
||||
public class InviteModule |
||||
extends ReactContextBaseJavaModule { |
||||
|
||||
public InviteModule(ReactApplicationContext reactContext) { |
||||
super(reactContext); |
||||
} |
||||
|
||||
/** |
||||
* Signals that a click/tap has been performed on {@code InviteButton} and |
||||
* that the execution flow for adding/inviting people to the current |
||||
* conference/meeting is to begin |
||||
* |
||||
* @param externalAPIScope the unique identifier of the |
||||
* {@code JitsiMeetView} whose {@code InviteButton} was clicked/tapped. |
||||
*/ |
||||
@ReactMethod |
||||
public void beginAddPeople(final String externalAPIScope) { |
||||
// Make sure InviteControllerListener (like all other listeners of the
|
||||
// SDK) is invoked on the UI thread. It was requested by SDK consumers.
|
||||
if (!UiThreadUtil.isOnUiThread()) { |
||||
UiThreadUtil.runOnUiThread(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
beginAddPeople(externalAPIScope); |
||||
} |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
InviteController inviteController |
||||
= findInviteControllerByExternalAPIScope(externalAPIScope); |
||||
|
||||
if (inviteController != null) { |
||||
inviteController.beginAddPeople(getReactApplicationContext()); |
||||
} |
||||
} |
||||
|
||||
private InviteController findInviteControllerByExternalAPIScope( |
||||
String externalAPIScope) { |
||||
JitsiMeetView view |
||||
= (JitsiMeetView) |
||||
BaseReactView.findViewByExternalAPIScope(externalAPIScope); |
||||
|
||||
return view == null ? null : view.getInviteController(); |
||||
} |
||||
|
||||
@Override |
||||
public String getName() { |
||||
return "Invite"; |
||||
} |
||||
|
||||
/** |
||||
* Callback for invitation failures |
||||
* |
||||
* @param failedInvitees the items for which the invitation failed |
||||
* @param addPeopleControllerScope a string that represents a connection to |
||||
* a specific AddPeopleController |
||||
*/ |
||||
@ReactMethod |
||||
public void inviteSettled( |
||||
final String externalAPIScope, |
||||
final String addPeopleControllerScope, |
||||
final ReadableArray failedInvitees) { |
||||
// Make sure AddPeopleControllerListener (like all other listeners of
|
||||
// the SDK) is invoked on the UI thread. It was requested by SDK
|
||||
// consumers.
|
||||
if (!UiThreadUtil.isOnUiThread()) { |
||||
UiThreadUtil.runOnUiThread(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
inviteSettled( |
||||
externalAPIScope, |
||||
addPeopleControllerScope, |
||||
failedInvitees); |
||||
} |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
InviteController inviteController |
||||
= findInviteControllerByExternalAPIScope(externalAPIScope); |
||||
|
||||
if (inviteController == null) { |
||||
Log.w( |
||||
"InviteModule", |
||||
"Invite settled, but failed to find active controller to notify"); |
||||
} else { |
||||
inviteController.inviteSettled( |
||||
addPeopleControllerScope, |
||||
failedInvitees); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Callback for results received from the JavaScript invite search call |
||||
* |
||||
* @param results the results in a ReadableArray of ReadableMap objects |
||||
* @param query the query associated with the search |
||||
* @param addPeopleControllerScope a string that represents a connection to |
||||
* a specific AddPeopleController |
||||
*/ |
||||
@ReactMethod |
||||
public void receivedResults( |
||||
final String externalAPIScope, |
||||
final String addPeopleControllerScope, |
||||
final String query, |
||||
final ReadableArray results) { |
||||
// Make sure AddPeopleControllerListener (like all other listeners of
|
||||
// the SDK) is invoked on the UI thread. It was requested by SDK
|
||||
// consumers.
|
||||
if (!UiThreadUtil.isOnUiThread()) { |
||||
UiThreadUtil.runOnUiThread(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
receivedResults( |
||||
externalAPIScope, |
||||
addPeopleControllerScope, |
||||
query, |
||||
results); |
||||
} |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
InviteController inviteController |
||||
= findInviteControllerByExternalAPIScope(externalAPIScope); |
||||
|
||||
if (inviteController == null) { |
||||
Log.w( |
||||
"InviteModule", |
||||
"Received results, but failed to find active controller to send results back"); |
||||
} else { |
||||
inviteController.receivedResultsForQuery( |
||||
addPeopleControllerScope, |
||||
query, |
||||
results); |
||||
} |
||||
} |
||||
} |
@ -1,33 +0,0 @@ |
||||
/*
|
||||
* Copyright @ 2018-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#import "AddPeopleController.h" |
||||
#import "InviteController.h" |
||||
|
||||
@interface JMAddPeopleController () |
||||
|
||||
@property (nonatomic, strong) NSMutableDictionary* _Nonnull items; |
||||
@property (nonatomic, weak, nullable) JMInviteController *owner; |
||||
@property (nonatomic, readonly) NSString* _Nonnull uuid; |
||||
|
||||
- (instancetype _Nonnull)initWithOwner:(JMInviteController * _Nonnull)owner; |
||||
|
||||
- (void)inviteSettled:(NSArray<NSDictionary *> * _Nonnull)failedInvitees; |
||||
|
||||
- (void)receivedResults:(NSArray<NSDictionary*> * _Nonnull)results |
||||
forQuery:(NSString * _Nonnull)query; |
||||
|
||||
@end |
@ -1,31 +0,0 @@ |
||||
/*
|
||||
* Copyright @ 2018-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#import <Foundation/Foundation.h> |
||||
|
||||
#import "AddPeopleControllerDelegate.h" |
||||
|
||||
@interface JMAddPeopleController: NSObject |
||||
|
||||
@property (nonatomic, nullable, weak) id<JMAddPeopleControllerDelegate> delegate; |
||||
|
||||
- (void)endAddPeople; |
||||
|
||||
- (void)inviteById:(NSArray<NSString *> * _Nonnull)ids; |
||||
|
||||
- (void)performQuery:(NSString * _Nonnull)query; |
||||
|
||||
@end |
@ -1,82 +0,0 @@ |
||||
/* |
||||
* Copyright @ 2018-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#import "AddPeopleController+Private.h" |
||||
#import "InviteController+Private.h" |
||||
|
||||
@implementation JMAddPeopleController |
||||
|
||||
- (instancetype)initWithOwner:(JMInviteController *)owner { |
||||
self = [super init]; |
||||
if (self) { |
||||
_uuid = [[NSUUID UUID] UUIDString]; |
||||
_items = [[NSMutableDictionary alloc] init]; |
||||
_owner = owner; |
||||
} |
||||
return self; |
||||
} |
||||
|
||||
#pragma mark API |
||||
|
||||
- (void)endAddPeople { |
||||
[self.owner endAddPeopleForController:self]; |
||||
} |
||||
|
||||
- (void)inviteById:(NSArray<NSString *> * _Nonnull)ids { |
||||
NSMutableArray* invitees = [[NSMutableArray alloc] init]; |
||||
|
||||
for (NSString* itemId in ids) { |
||||
id invitee = [self.items objectForKey:itemId]; |
||||
|
||||
if (invitee) { |
||||
[invitees addObject:invitee]; |
||||
} |
||||
} |
||||
|
||||
[self.owner invite:invitees forController:self]; |
||||
} |
||||
|
||||
- (void)performQuery:(NSString *)query { |
||||
[self.owner performQuery:query forController:self]; |
||||
} |
||||
|
||||
#pragma mark Internal API, used to call the delegate and report to the user |
||||
|
||||
- (void)receivedResults:(NSArray<NSDictionary *> *)results |
||||
forQuery:(NSString *)query { |
||||
for (NSDictionary* item in results) { |
||||
NSString* itemId = item[@"id"]; |
||||
NSString* itemType = item[@"type"]; |
||||
if (itemId) { |
||||
[self.items setObject:item forKey:itemId]; |
||||
} else if (itemType != nil && [itemType isEqualToString: @"phone"]) { |
||||
NSString* number = item[@"number"]; |
||||
if (number) { |
||||
[self.items setObject:item forKey:number]; |
||||
} |
||||
} |
||||
} |
||||
|
||||
[self.delegate addPeopleController:self |
||||
didReceiveResults:results |
||||
forQuery:query]; |
||||
} |
||||
|
||||
- (void)inviteSettled:(NSArray<NSDictionary *> *)failedInvitees { |
||||
[self.delegate inviteSettled:failedInvitees fromSearchController:self]; |
||||
} |
||||
|
||||
@end |
@ -1,41 +0,0 @@ |
||||
/*
|
||||
* Copyright @ 2018-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#import <Foundation/Foundation.h> |
||||
|
||||
#import "AddPeopleController.h" |
||||
|
||||
@class JMAddPeopleController; |
||||
|
||||
@protocol JMAddPeopleControllerDelegate |
||||
|
||||
/**
|
||||
* Called when a JMAddPeopleController has results for a query that was |
||||
* previously provided. |
||||
*/ |
||||
- (void)addPeopleController:(JMAddPeopleController * _Nonnull)controller |
||||
didReceiveResults:(NSArray<NSDictionary *> * _Nonnull)results |
||||
forQuery:(NSString * _Nonnull)query; |
||||
|
||||
/**
|
||||
* Called when a JMAddPeopleController has finished the inviting process, either |
||||
* succesfully or not. In case of failure the failedInvitees array will contain |
||||
* the items for which invitations failed. |
||||
*/ |
||||
- (void) inviteSettled:(NSArray<NSDictionary *> * _Nonnull)failedInvitees |
||||
fromSearchController:(JMAddPeopleController * _Nonnull)addPeopleController; |
||||
|
||||
@end |
@ -1,30 +0,0 @@ |
||||
/*
|
||||
* Copyright @ 2018-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#import <React/RCTBridge.h> |
||||
#import <React/RCTEventEmitter.h> |
||||
|
||||
@interface Invite : RCTEventEmitter <RCTBridgeModule> |
||||
|
||||
- (void) invite:(NSArray<NSDictionary *> * _Nonnull)invitees |
||||
externalAPIScope:(NSString * _Nonnull)externalAPIScope |
||||
addPeopleControllerScope:(NSString * _Nonnull)addPeopleControllerScope; |
||||
|
||||
- (void) performQuery:(NSString * _Nonnull)query |
||||
externalAPIScope:(NSString * _Nonnull)externalAPIScope |
||||
addPeopleControllerScope:(NSString * _Nonnull)addPeopleControllerScope; |
||||
|
||||
@end |
@ -1,127 +0,0 @@ |
||||
/* |
||||
* Copyright @ 2018-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#import "Invite+Private.h" |
||||
#import "InviteController+Private.h" |
||||
#import "JitsiMeetView+Private.h" |
||||
|
||||
// The events emitted/supported by the Invite react-native module: |
||||
// |
||||
// XXX The event names are ridiculous on purpose. Even though iOS makes it look |
||||
// like it emits within the bounderies of a react-native module ony, it actually |
||||
// also emits through DeviceEventEmitter. (Of course, Android emits only through |
||||
// DeviceEventEmitter.) |
||||
static NSString * const InviteEmitterEvent |
||||
= @"org.jitsi.meet:features/invite#invite"; |
||||
static NSString * const PerformQueryEmitterEvent |
||||
= @"org.jitsi.meet:features/invite#performQuery"; |
||||
|
||||
@implementation Invite |
||||
|
||||
RCT_EXPORT_MODULE(); |
||||
|
||||
/** |
||||
* Make sure all methods in this module are invoked on the main/UI thread. |
||||
*/ |
||||
- (dispatch_queue_t)methodQueue { |
||||
return dispatch_get_main_queue(); |
||||
} |
||||
|
||||
- (NSArray<NSString *> *)supportedEvents { |
||||
return @[ |
||||
InviteEmitterEvent, |
||||
PerformQueryEmitterEvent |
||||
]; |
||||
} |
||||
|
||||
/** |
||||
* Initiates the process to add people. This involves calling a delegate method |
||||
* in the JMInviteControllerDelegate so the native host application can start |
||||
* the query process. |
||||
* |
||||
* @param externalAPIScope - Scope identifying the JitsiMeetView where the |
||||
* calling JS code is being executed. |
||||
*/ |
||||
RCT_EXPORT_METHOD(beginAddPeople:(NSString *)externalAPIScope) { |
||||
JitsiMeetView *view |
||||
= [JitsiMeetView viewForExternalAPIScope:externalAPIScope]; |
||||
JMInviteController *inviteController = view.inviteController; |
||||
[inviteController beginAddPeople]; |
||||
} |
||||
|
||||
/** |
||||
* Indicates the the invite process has settled / finished. |
||||
* |
||||
* @param externalAPIScope - Scope identifying the JitsiMeetView where the |
||||
* calling JS code is being executed. |
||||
* @param addPeopleControllerScope - Scope identifying the JMAddPeopleController |
||||
* wich was settled. |
||||
* @param failedInvitees - Array with the invitees which were not invited due |
||||
* to a failure. |
||||
*/ |
||||
RCT_EXPORT_METHOD(inviteSettled:(NSString *)externalAPIScope |
||||
addPeopleControllerScope:(NSString *)addPeopleControllerScope |
||||
failedInvitees:(NSArray *)failedInvitees) { |
||||
JitsiMeetView *view |
||||
= [JitsiMeetView viewForExternalAPIScope:externalAPIScope]; |
||||
JMInviteController *inviteController = view.inviteController; |
||||
[inviteController inviteSettled:addPeopleControllerScope |
||||
failedInvitees:failedInvitees]; |
||||
} |
||||
|
||||
/** |
||||
* Process results received for the given query. This involves calling a |
||||
* delegate method in JMAddPeopleControllerDelegate so the native host |
||||
* application is made aware of the query results. |
||||
* |
||||
* @param externalAPIScope - Scope identifying the JitsiMeetView where the |
||||
* calling JS code is being executed. |
||||
* @param addPeopleControllerScope - Scope identifying the JMAddPeopleController |
||||
* for which the results were received. |
||||
* @param query - The actual query for which the results were received. |
||||
* @param results - The query results. |
||||
*/ |
||||
RCT_EXPORT_METHOD(receivedResults:(NSString *)externalAPIScope |
||||
addPeopleControllerScope:(NSString *)addPeopleControllerScope |
||||
query:(NSString *)query |
||||
results:(NSArray *)results) { |
||||
JitsiMeetView *view |
||||
= [JitsiMeetView viewForExternalAPIScope:externalAPIScope]; |
||||
JMInviteController *inviteController = view.inviteController; |
||||
[inviteController receivedResults:addPeopleControllerScope |
||||
query:query |
||||
results:results]; |
||||
} |
||||
|
||||
- (void) invite:(NSArray<NSDictionary *> * _Nonnull)invitees |
||||
externalAPIScope:(NSString * _Nonnull)externalAPIScope |
||||
addPeopleControllerScope:(NSString * _Nonnull) addPeopleControllerScope { |
||||
[self sendEventWithName:InviteEmitterEvent |
||||
body:@{ @"addPeopleControllerScope": addPeopleControllerScope, |
||||
@"externalAPIScope": externalAPIScope, |
||||
@"invitees": invitees }]; |
||||
} |
||||
|
||||
- (void) performQuery:(NSString * _Nonnull)query |
||||
externalAPIScope:(NSString * _Nonnull)externalAPIScope |
||||
addPeopleControllerScope:(NSString * _Nonnull) addPeopleControllerScope { |
||||
[self sendEventWithName:PerformQueryEmitterEvent |
||||
body:@{ @"addPeopleControllerScope": addPeopleControllerScope, |
||||
@"externalAPIScope": externalAPIScope, |
||||
@"query": query }]; |
||||
} |
||||
|
||||
@end |
@ -1,53 +0,0 @@ |
||||
/*
|
||||
* Copyright @ 2018-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#import "InviteController.h" |
||||
|
||||
#import "AddPeopleController.h" |
||||
#import "Invite+Private.h" |
||||
#import "RCTBridgeWrapper.h" |
||||
|
||||
@interface JMInviteController () |
||||
|
||||
@property (nonatomic, nullable) JMAddPeopleController *addPeopleController; |
||||
|
||||
@property (nonatomic) NSString * _Nonnull externalAPIScope; |
||||
|
||||
@property (nonatomic, nullable, weak) RCTBridgeWrapper *bridgeWrapper; |
||||
|
||||
@property (nonatomic, readonly) Invite * _Nullable inviteModule; |
||||
|
||||
- (instancetype _Nonnull)initWithExternalAPIScope:(NSString * _Nonnull)externalAPIScope |
||||
bridgeWrapper:(RCTBridgeWrapper * _Nullable)bridgeWrapper; |
||||
|
||||
- (void)beginAddPeople; |
||||
|
||||
- (void)endAddPeopleForController:(JMAddPeopleController * _Nonnull)controller; |
||||
|
||||
- (void) invite:(NSArray * _Nonnull)invitees |
||||
forController:(JMAddPeopleController * _Nonnull)controller; |
||||
|
||||
- (void)inviteSettled:(NSString * _Nonnull)addPeopleControllerScope |
||||
failedInvitees:(NSArray * _Nonnull)failedInvitees; |
||||
|
||||
- (void)performQuery:(NSString * _Nonnull)query |
||||
forController:(JMAddPeopleController * _Nonnull)controller; |
||||
|
||||
- (void)receivedResults:(NSString * _Nonnull)addPeopleControllerScope |
||||
query:(NSString * _Nonnull)query |
||||
results:(NSArray * _Nonnull)results; |
||||
|
||||
@end |
@ -1,32 +0,0 @@ |
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#import <Foundation/Foundation.h> |
||||
|
||||
#import "InviteControllerDelegate.h" |
||||
|
||||
@interface JMInviteController : NSObject |
||||
|
||||
@property (nonatomic) BOOL addPeopleEnabled; |
||||
|
||||
@property (nonatomic) BOOL dialOutEnabled; |
||||
|
||||
@property (nonatomic, nullable, weak) id<JMInviteControllerDelegate> delegate; |
||||
|
||||
- (void) invite:(NSArray * _Nonnull)invitees |
||||
withCompletion:(void (^ _Nullable)(NSArray<NSDictionary *> * _Nonnull failedInvitees))completion; |
||||
|
||||
@end |
@ -1,160 +0,0 @@ |
||||
/* |
||||
* Copyright @ 2017-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#import "InviteController+Private.h" |
||||
#import "AddPeopleController+Private.h" |
||||
|
||||
@implementation JMInviteController { |
||||
NSNumber *_addPeopleEnabled; |
||||
NSNumber *_dialOutEnabled; |
||||
} |
||||
|
||||
@dynamic addPeopleEnabled; |
||||
@dynamic dialOutEnabled; |
||||
|
||||
#pragma mark Constructor |
||||
|
||||
-(instancetype)initWithExternalAPIScope:(NSString * _Nonnull)externalAPIScope |
||||
bridgeWrapper:(RCTBridgeWrapper * _Nullable)bridgeWrapper { |
||||
self = [super init]; |
||||
if (self) { |
||||
self.externalAPIScope = externalAPIScope; |
||||
self.bridgeWrapper = bridgeWrapper; |
||||
} |
||||
|
||||
return self; |
||||
} |
||||
|
||||
#pragma mark Public API |
||||
|
||||
-(Invite * _Nullable)inviteModule { |
||||
return [self.bridgeWrapper.bridge moduleForName:@"Invite"]; |
||||
} |
||||
|
||||
-(void)beginAddPeople { |
||||
if (_delegate == nil) { |
||||
return; |
||||
} |
||||
|
||||
if (_addPeopleController != nil) { |
||||
return; |
||||
} |
||||
|
||||
_addPeopleController = [[JMAddPeopleController alloc] initWithOwner:self]; |
||||
|
||||
@try { |
||||
if (self.delegate |
||||
&& [self.delegate respondsToSelector:@selector(beginAddPeople:)]) { |
||||
[self.delegate beginAddPeople:_addPeopleController]; |
||||
} |
||||
} @catch (NSException *e) { |
||||
[self endAddPeopleForController:_addPeopleController]; |
||||
} |
||||
} |
||||
|
||||
-(void)endAddPeopleForController:(JMAddPeopleController *)controller { |
||||
if (self.addPeopleController == controller) { |
||||
self.addPeopleController = nil; |
||||
} |
||||
} |
||||
|
||||
#pragma mark Property getters / setters |
||||
|
||||
- (void) setAddPeopleEnabled:(BOOL)addPeopleEnabled { |
||||
_addPeopleEnabled = [NSNumber numberWithBool:addPeopleEnabled]; |
||||
} |
||||
|
||||
- (BOOL) addPeopleEnabled { |
||||
if (_addPeopleEnabled == nil || [_addPeopleEnabled boolValue]) { |
||||
return self.delegate |
||||
&& [self.delegate respondsToSelector:@selector(beginAddPeople:)]; |
||||
} |
||||
|
||||
return NO; |
||||
} |
||||
|
||||
- (void) setDialOutEnabled:(BOOL)dialOutEnabled { |
||||
_dialOutEnabled = [NSNumber numberWithBool:dialOutEnabled]; |
||||
} |
||||
|
||||
- (BOOL) dialOutEnabled { |
||||
if (_dialOutEnabled == nil || [_dialOutEnabled boolValue]) { |
||||
return self.delegate |
||||
&& [self.delegate respondsToSelector:@selector(beginAddPeople:)]; |
||||
} |
||||
|
||||
return NO; |
||||
} |
||||
|
||||
#pragma mark Result handling |
||||
|
||||
- (void)inviteSettled:(NSString *)addPeopleControllerScope |
||||
failedInvitees:(NSArray *)failedInvitees { |
||||
JMAddPeopleController *controller = self.addPeopleController; |
||||
|
||||
if (controller != nil |
||||
&& [controller.uuid isEqualToString:addPeopleControllerScope]) { |
||||
@try { |
||||
[controller inviteSettled:failedInvitees]; |
||||
} @finally { |
||||
if ([failedInvitees count] == 0) { |
||||
[self endAddPeopleForController:controller]; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
- (void)receivedResults:(NSString *)addPeopleControllerScope |
||||
query:(NSString *)query |
||||
results:(NSArray *)results { |
||||
JMAddPeopleController *controller = self.addPeopleController; |
||||
|
||||
if (controller != nil |
||||
&& [controller.uuid isEqualToString:addPeopleControllerScope]) { |
||||
[controller receivedResults:results forQuery:query]; |
||||
} |
||||
} |
||||
|
||||
#pragma mark Use the Invite react-native module to emit the search / submission events |
||||
|
||||
- (void) invite:(NSArray *)invitees |
||||
forController:(JMAddPeopleController * _Nonnull)controller { |
||||
[self invite:invitees |
||||
forControllerScope:controller.uuid]; |
||||
} |
||||
|
||||
- (void) invite:(NSArray *)invitees |
||||
forControllerScope:(NSString * _Nonnull)controllerScope { |
||||
[self.inviteModule invite:invitees |
||||
externalAPIScope:self.externalAPIScope |
||||
addPeopleControllerScope:controllerScope]; |
||||
} |
||||
|
||||
- (void) invite:(NSArray *)invitees |
||||
withCompletion:(void (^)(NSArray<NSDictionary *> *failedInvitees))completion { |
||||
// TODO Execute the specified completion block when the invite settles. |
||||
[self invite:invitees |
||||
forControllerScope:[[NSUUID UUID] UUIDString]]; |
||||
} |
||||
|
||||
- (void)performQuery:(NSString * _Nonnull)query |
||||
forController:(JMAddPeopleController * _Nonnull)controller { |
||||
[self.inviteModule performQuery:query |
||||
externalAPIScope:self.externalAPIScope |
||||
addPeopleControllerScope:controller.uuid]; |
||||
} |
||||
|
||||
@end |
@ -1,29 +0,0 @@ |
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
#import "AddPeopleController.h" |
||||
|
||||
@protocol JMInviteControllerDelegate <NSObject> |
||||
|
||||
/**
|
||||
* Called when the invite button in the conference is tapped. |
||||
* |
||||
* The search controller provided can be used to query user search within the |
||||
* conference. |
||||
*/ |
||||
- (void)beginAddPeople:(JMAddPeopleController *)addPeopleController; |
||||
|
||||
@end |
@ -1,232 +0,0 @@ |
||||
// @flow
|
||||
|
||||
import i18next from 'i18next'; |
||||
import { NativeEventEmitter, NativeModules } from 'react-native'; |
||||
|
||||
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT, getAppProp } from '../base/app'; |
||||
import { MiddlewareRegistry } from '../base/redux'; |
||||
|
||||
import { invite } from './actions'; |
||||
import { |
||||
BEGIN_ADD_PEOPLE, |
||||
_SET_EMITTER_SUBSCRIPTIONS |
||||
} from './actionTypes'; |
||||
import { |
||||
getInviteResultsForQuery, |
||||
isAddPeopleEnabled, |
||||
isDialOutEnabled |
||||
} from './functions'; |
||||
import './middleware.any'; |
||||
|
||||
/** |
||||
* The react-native module of the feature invite. |
||||
*/ |
||||
const { Invite } = NativeModules; |
||||
|
||||
/** |
||||
* The middleware of the feature invite specific to mobile/react-native. |
||||
* |
||||
* @param {Store} store - The redux store. |
||||
* @returns {Function} |
||||
*/ |
||||
Invite && MiddlewareRegistry.register(store => next => action => { |
||||
switch (action.type) { |
||||
case _SET_EMITTER_SUBSCRIPTIONS: |
||||
return _setEmitterSubscriptions(store, next, action); |
||||
|
||||
case APP_WILL_MOUNT: |
||||
return _appWillMount(store, next, action); |
||||
|
||||
case APP_WILL_UNMOUNT: { |
||||
const result = next(action); |
||||
|
||||
store.dispatch({ |
||||
type: _SET_EMITTER_SUBSCRIPTIONS, |
||||
emitterSubscriptions: undefined |
||||
}); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
case BEGIN_ADD_PEOPLE: |
||||
return _beginAddPeople(store, next, action); |
||||
} |
||||
|
||||
return next(action); |
||||
}); |
||||
|
||||
/** |
||||
* Notifies the feature jwt that the action {@link APP_WILL_MOUNT} is being |
||||
* dispatched within a specific redux {@code store}. |
||||
* |
||||
* @param {Store} store - The redux store in which the specified {@code action} |
||||
* is being dispatched. |
||||
* @param {Dispatch} next - The redux dispatch function to dispatch the |
||||
* specified {@code action} to the specified {@code store}. |
||||
* @param {Action} action - The redux action {@code APP_WILL_MOUNT} which is |
||||
* being dispatched in the specified {@code store}. |
||||
* @private |
||||
* @returns {*} The value returned by {@code next(action)}. |
||||
*/ |
||||
function _appWillMount({ dispatch, getState }, next, action) { |
||||
const result = next(action); |
||||
|
||||
const emitter = new NativeEventEmitter(Invite); |
||||
const context = { |
||||
dispatch, |
||||
getState |
||||
}; |
||||
|
||||
dispatch({ |
||||
type: _SET_EMITTER_SUBSCRIPTIONS, |
||||
emitterSubscriptions: [ |
||||
emitter.addListener( |
||||
'org.jitsi.meet:features/invite#invite', |
||||
_onInvite, |
||||
context), |
||||
emitter.addListener( |
||||
'org.jitsi.meet:features/invite#performQuery', |
||||
_onPerformQuery, |
||||
context) |
||||
] |
||||
}); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* Notifies the feature invite that the action {@link BEGIN_ADD_PEOPLE} is being |
||||
* dispatched within a specific redux {@code store}. |
||||
* |
||||
* @param {Store} store - The redux store in which the specified {@code action} |
||||
* is being dispatched. |
||||
* @param {Dispatch} next - The redux {@code dispatch} function to dispatch the |
||||
* specified {@code action} to the specified {@code store}. |
||||
* @param {Action} action - The redux action {@code BEGIN_ADD_PEOPLE} which is |
||||
* being dispatched in the specified {@code store}. |
||||
* @private |
||||
* @returns {*} The value returned by {@code next(action)}. |
||||
*/ |
||||
function _beginAddPeople(store, next, action) { |
||||
const result = next(action); |
||||
|
||||
// The JavaScript App needs to provide uniquely identifying information to
|
||||
// the native Invite module so that the latter may match the former to the
|
||||
// native JitsiMeetView which hosts it.
|
||||
const externalAPIScope = getAppProp(store, 'externalAPIScope'); |
||||
|
||||
externalAPIScope && Invite.beginAddPeople(externalAPIScope); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* Handles the {@code invite} event of the feature invite and invites specific |
||||
* invitees to the current, ongoing conference. |
||||
* |
||||
* @param {Object} event - The details of the event. |
||||
* @returns {void} |
||||
*/ |
||||
function _onInvite({ addPeopleControllerScope, externalAPIScope, invitees }) { |
||||
const { dispatch, getState } = this; // eslint-disable-line no-invalid-this
|
||||
|
||||
// If there are multiple JitsiMeetView instances alive, they will all get
|
||||
// the event, since there is a single bridge, so make sure we don't act if
|
||||
// the event is not for us.
|
||||
if (getAppProp(getState, 'externalAPIScope') !== externalAPIScope) { |
||||
return; |
||||
} |
||||
|
||||
dispatch(invite(invitees)) |
||||
.then(failedInvitees => |
||||
Invite.inviteSettled( |
||||
externalAPIScope, |
||||
addPeopleControllerScope, |
||||
failedInvitees)); |
||||
} |
||||
|
||||
/** |
||||
* Handles the {@code performQuery} event of the feature invite and queries for |
||||
* invitees who may subsequently be invited to the current, ongoing conference. |
||||
* |
||||
* @param {Object} event - The details of the event. |
||||
* @returns {void} |
||||
*/ |
||||
function _onPerformQuery( |
||||
{ addPeopleControllerScope, externalAPIScope, query }) { |
||||
const { getState } = this; // eslint-disable-line no-invalid-this
|
||||
const state = getState(); |
||||
|
||||
// If there are multiple JitsiMeetView instances alive, they will all get
|
||||
// the event, since there is a single bridge, so make sure we don't act if
|
||||
// the event is not for us.
|
||||
if (getAppProp(state, 'externalAPIScope') !== externalAPIScope) { |
||||
return; |
||||
} |
||||
|
||||
const { |
||||
dialOutAuthUrl, |
||||
peopleSearchQueryTypes, |
||||
peopleSearchUrl |
||||
} = state['features/base/config']; |
||||
const options = { |
||||
dialOutAuthUrl, |
||||
addPeopleEnabled: isAddPeopleEnabled(state), |
||||
dialOutEnabled: isDialOutEnabled(state), |
||||
jwt: state['features/base/jwt'].jwt, |
||||
peopleSearchQueryTypes, |
||||
peopleSearchUrl |
||||
}; |
||||
|
||||
getInviteResultsForQuery(query, options) |
||||
.catch(() => []) |
||||
.then(results => { |
||||
const translatedResults = results.map(result => { |
||||
if (result.type === 'phone') { |
||||
result.title = i18next.t('addPeople.telephone', { |
||||
number: result.number |
||||
}); |
||||
|
||||
if (result.showCountryCodeReminder) { |
||||
result.subtitle = i18next.t( |
||||
'addPeople.countryReminder' |
||||
); |
||||
} |
||||
} |
||||
|
||||
return result; |
||||
}).filter(result => result.type !== 'phone' || result.allowed); |
||||
|
||||
Invite.receivedResults( |
||||
externalAPIScope, |
||||
addPeopleControllerScope, |
||||
query, |
||||
translatedResults); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Notifies the feature invite that the action |
||||
* {@link _SET_EMITTER_SUBSCRIPTIONS} is being dispatched within a specific |
||||
* redux {@code store}. |
||||
* |
||||
* @param {Store} store - The redux store in which the specified {@code action} |
||||
* is being dispatched. |
||||
* @param {Dispatch} next - The redux dispatch function to dispatch the |
||||
* specified {@code action} to the specified {@code store}. |
||||
* @param {Action} action - The redux action {@code _SET_EMITTER_SUBSCRIPTIONS} |
||||
* which is being dispatched in the specified {@code store}. |
||||
* @private |
||||
* @returns {*} |
||||
*/ |
||||
function _setEmitterSubscriptions({ getState }, next, action) { |
||||
const { emitterSubscriptions } = getState()['features/invite']; |
||||
|
||||
if (emitterSubscriptions) { |
||||
for (const subscription of emitterSubscriptions) { |
||||
subscription.remove(); |
||||
} |
||||
} |
||||
|
||||
return next(action); |
||||
} |
Loading…
Reference in new issue