Some work on group/public calls

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2018-02-20 18:16:45 +01:00
parent 1aa89387a8
commit 517e74820f
10 changed files with 233 additions and 15 deletions

View File

@ -42,6 +42,7 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.LinearLayout;
@ -50,6 +51,7 @@ import com.bluelinelabs.conductor.RouterTransaction;
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
import com.bluelinelabs.conductor.internal.NoOpControllerChangeHandler;
import com.kennyc.bottomsheet.BottomSheet;
import com.nextcloud.talk.R;
import com.nextcloud.talk.activities.CallActivity;
import com.nextcloud.talk.adapters.items.EmptyFooterItem;
@ -59,9 +61,11 @@ import com.nextcloud.talk.adapters.items.UserItem;
import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.base.BaseController;
import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController;
import com.nextcloud.talk.models.RetrofitBucket;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.participants.Participant;
import com.nextcloud.talk.models.json.rooms.Room;
import com.nextcloud.talk.models.json.rooms.RoomOverall;
import com.nextcloud.talk.models.json.sharees.Sharee;
import com.nextcloud.talk.models.json.sharees.ShareesOverall;
@ -110,6 +114,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
@Inject
NcApi ncApi;
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@ -132,6 +137,8 @@ public class ContactsController extends BaseController implements SearchView.OnQ
private Disposable cacheQueryDisposable;
private FlexibleAdapter adapter;
private List<AbstractFlexibleItem> contactItems = new ArrayList<>();
private BottomSheet bottomSheet;
private View view;
private SmoothScrollLinearLayoutManager layoutManager;
@ -232,8 +239,27 @@ public class ContactsController extends BaseController implements SearchView.OnQ
@Optional
@OnClick(R.id.done_button)
public void onDoneButtonClick() {
Bundle bundle = new Bundle();
Room.RoomType roomType;
if (isPublicCall) {
roomType = Room.RoomType.ROOM_PUBLIC_CALL;
} else {
roomType = Room.RoomType.ROOM_GROUP_CALL;
}
bundle.putParcelable(BundleKeys.KEY_CONVERSATION_TYPE, Parcels.wrap(roomType));
ArrayList<String> userIds = new ArrayList<>();
Set<Integer> selectedPositions = adapter.getSelectedPositionsAsSet();
for (int selectedPosition : selectedPositions) {
if (adapter.getItem(selectedPosition) instanceof UserItem) {
UserItem userItem = (UserItem) adapter.getItem(selectedPosition);
userIds.add(userItem.getModel().getUserId());
}
}
bundle.putStringArrayList(BundleKeys.KEY_INVITED_PARTICIPANTS, userIds);
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, 11);
prepareAndShowBottomSheetWithBundle(bundle);
}
private void initSearchView() {
if (getActivity() != null) {
@ -541,7 +567,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
if (!isNewConversationView) {
UserItem userItem = (UserItem) adapter.getItem(position);
RetrofitBucket retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(userEntity.getBaseUrl(), "1",
userItem.getModel().getUserId());
userItem.getModel().getUserId(), null);
ncApi.createRoom(ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken()),
retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
.subscribeOn(Schedulers.newThread())
@ -635,4 +661,25 @@ public class ContactsController extends BaseController implements SearchView.OnQ
public void onFastScrollerStateChange(boolean scrolling) {
swipeRefreshLayout.setEnabled(!scrolling);
}
private void prepareAndShowBottomSheetWithBundle(Bundle bundle) {
if (view == null) {
view = getActivity().getLayoutInflater().inflate(R.layout.bottom_sheet, null, false);
}
getChildRouter((ViewGroup) view).setRoot(
RouterTransaction.with(new EntryMenuController(bundle))
.popChangeHandler(new VerticalChangeHandler())
.pushChangeHandler(new VerticalChangeHandler()));
if (bottomSheet == null) {
bottomSheet = new BottomSheet.Builder(getActivity()).setView(view).create();
}
bottomSheet.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
bottomSheet.show();
bottomSheet.findViewById(R.id.extended_edit_text).invalidate();
}
}

View File

@ -82,8 +82,12 @@ public class EntryMenuController extends BaseController {
private String name;
private String callUrl;
private Bundle originalBundle;
public EntryMenuController(Bundle args) {
super(args);
originalBundle = args;
this.operationCode = args.getInt(BundleKeys.KEY_OPERATION_CODE);
if (args.containsKey(BundleKeys.KEY_ROOM)) {
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
@ -130,7 +134,7 @@ public class EntryMenuController extends BaseController {
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else if (operationCode != 7 && operationCode != 10) {
} else if (operationCode != 7 && operationCode != 10 && operationCode != 11) {
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
bundle = new Bundle();
if (operationCode == 4 || operationCode == 6) {
@ -153,7 +157,7 @@ public class EntryMenuController extends BaseController {
getActivity().startActivity(intent);
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
}
} else {
} else if (operationCode != 11) {
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
bundle = new Bundle();
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode);
@ -162,6 +166,13 @@ public class EntryMenuController extends BaseController {
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
} else if (operationCode == 11) {
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
originalBundle.putString(BundleKeys.KEY_CONVERSATION_NAME, editText.getText().toString());
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(originalBundle))
.pushChangeHandler(new HorizontalChangeHandler())
.popChangeHandler(new HorizontalChangeHandler()));
}
}
@ -239,6 +250,7 @@ public class EntryMenuController extends BaseController {
String labelText = "";
switch (operationCode) {
case 11:
case 2:
labelText = getResources().getString(R.string.nc_call_name);
break;

View File

@ -42,9 +42,12 @@ import com.nextcloud.talk.api.NcApi;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.base.BaseController;
import com.nextcloud.talk.events.BottomSheetLockEvent;
import com.nextcloud.talk.models.RetrofitBucket;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.call.CallOverall;
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall;
import com.nextcloud.talk.models.json.generic.GenericOverall;
import com.nextcloud.talk.models.json.participants.AddParticipantOverall;
import com.nextcloud.talk.models.json.rooms.Room;
import com.nextcloud.talk.models.json.rooms.RoomOverall;
import com.nextcloud.talk.utils.ApiUtils;
@ -56,6 +59,8 @@ import com.nextcloud.talk.utils.database.user.UserUtils;
import org.greenrobot.eventbus.EventBus;
import org.parceler.Parcels;
import java.util.ArrayList;
import javax.inject.Inject;
import autodagger.AutoInjector;
@ -106,6 +111,12 @@ public class OperationsMenuController extends BaseController {
private Disposable disposable;
private Room.RoomType conversationType;
private ArrayList<String> invitedUsers = new ArrayList<>();
private String conversationName;
private String credentials;
public OperationsMenuController(Bundle args) {
super(args);
this.operationCode = args.getInt(BundleKeys.KEY_OPERATION_CODE);
@ -115,6 +126,15 @@ public class OperationsMenuController extends BaseController {
this.callPassword = args.getString(BundleKeys.KEY_CALL_PASSWORD, "");
this.callUrl = args.getString(BundleKeys.KEY_CALL_URL, "");
this.conversationName = args.getString(BundleKeys.KEY_CONVERSATION_NAME, "");
if (args.containsKey(BundleKeys.KEY_INVITED_PARTICIPANTS)) {
this.invitedUsers = args.getStringArrayList(BundleKeys.KEY_INVITED_PARTICIPANTS);
}
if (args.containsKey(BundleKeys.KEY_CONVERSATION_TYPE)) {
this.conversationType = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_CONVERSATION_TYPE));
}
}
@Override
@ -144,7 +164,7 @@ public class OperationsMenuController extends BaseController {
}
if (userEntity != null) {
String credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
if (!TextUtils.isEmpty(baseUrl) && !baseUrl.equals(userEntity.getBaseUrl())) {
credentials = null;
@ -282,6 +302,84 @@ public class OperationsMenuController extends BaseController {
}
});
break;
case 11:
RetrofitBucket retrofitBucket;
boolean isGroupCallWorkaround = false;
if (conversationType.equals(Room.RoomType.ROOM_PUBLIC_CALL) ||
!userEntity.hasSpreedCapabilityWithName("empty-group-room")) {
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(userEntity.getBaseUrl(),
"3", null, conversationName);
} else {
String roomType = "2";
if (!userEntity.hasSpreedCapabilityWithName("empty-group-room")) {
isGroupCallWorkaround = true;
roomType = "3";
}
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(userEntity.getBaseUrl(),
roomType, null, conversationName);
}
String finalCredentials1 = credentials;
final boolean isGroupCallWorkaroundFinal = isGroupCallWorkaround;
ncApi.createRoom(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(new Observer<RoomOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(RoomOverall roomOverall) {
room = roomOverall.getOcs().getData();
if (conversationType.equals(Room.RoomType.ROOM_PUBLIC_CALL) && isGroupCallWorkaroundFinal) {
ncApi.makeRoomPrivate(finalCredentials1, ApiUtils.getUrlForRoomVisibility
(userEntity.getBaseUrl(), room.getToken()))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(new Observer<GenericOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(GenericOverall genericOverall) {
inviteUsersToAConversation();
}
@Override
public void onError(Throwable e) {
showResultImage(false, false);
dispose();
}
@Override
public void onComplete() {
dispose();
}
});
} else {
inviteUsersToAConversation();
}
}
@Override
public void onError(Throwable e) {
showResultImage(false, false);
dispose();
}
@Override
public void onComplete() {
dispose();
}
});
break;
case 99:
ncApi.joinRoom(credentials, ApiUtils.getUrlForRoomParticipants(baseUrl, conversationToken),
callPassword)
@ -353,12 +451,59 @@ public class OperationsMenuController extends BaseController {
dispose();
}
private void inviteUsersToAConversation() {
RetrofitBucket retrofitBucket;
final ArrayList<String> localInvitedUsers = invitedUsers;
if (localInvitedUsers.size() > 0) {
for (int i = 0; i < invitedUsers.size(); i++) {
final String userId = invitedUsers.get(i);
retrofitBucket = ApiUtils.getRetrofitBucketForAddParticipant(userEntity.getBaseUrl(), room.getToken(),
userId);
ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(new Observer<AddParticipantOverall>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(AddParticipantOverall addParticipantOverall) {
}
@Override
public void onError(Throwable e) {
dispose();
}
@Override
public void onComplete() {
synchronized (localInvitedUsers) {
localInvitedUsers.remove(userId);
}
if (localInvitedUsers.size() == 0) {
initiateCall();
}
dispose();
}
});
}
} else {
showResultImage(true, false);
}
}
private void initiateCall() {
eventBus.post(new BottomSheetLockEvent(true, 0, true, true));
Bundle bundle = new Bundle();
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, room.getToken());
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap(userEntity));
if (!baseUrl.equals(userEntity.getBaseUrl())) {
if (baseUrl != null && !baseUrl.equals(userEntity.getBaseUrl())) {
bundle.putString(BundleKeys.KEY_MODIFIED_BASE_URL, baseUrl);
}
bundle.putString(BundleKeys.KEY_CALL_SESSION, callSession);

View File

@ -59,7 +59,7 @@ public interface User extends Parcelable, Persistable, Serializable {
boolean getScheduledForDeletion();
default boolean checkForSpreedCapability(String capabilityName) {
default boolean hasSpreedCapabilityWithName(String capabilityName) {
try {
Capabilities capabilities = LoganSquare.parse(this.getCapabilities(), Capabilities.class);
if (capabilities.getSpreedCapability() != null && capabilities.getSpreedCapability().getFeatures() != null) {

View File

@ -86,6 +86,7 @@ public class Room {
return (canModerate() && ((participants != null && participants.size() > 2) || numberOfGuests > 0));
}
@Parcel
public enum RoomType {
DUMMY,
ROOM_TYPE_ONE_TO_ONE_CALL,

View File

@ -88,7 +88,8 @@ public class AccountUtils {
PackageManager packageManager = context.getPackageManager();
String appName = "";
try {
appName = (String) packageManager.getApplicationLabel(packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA));
appName = (String) packageManager.getApplicationLabel(packageManager.getApplicationInfo(packageName,
PackageManager.GET_META_DATA));
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Failed to get app name based on package");
}

View File

@ -20,6 +20,7 @@
package com.nextcloud.talk.utils;
import android.net.Uri;
import android.support.annotation.Nullable;
import com.nextcloud.talk.BuildConfig;
import com.nextcloud.talk.R;
@ -73,13 +74,21 @@ public class ApiUtils {
return baseUrl + ocsApiVersion + spreedApiVersion + "/room/" + token;
}
public static RetrofitBucket getRetrofitBucketForCreateRoom(String baseUrl, String roomType, String invite) {
public static RetrofitBucket getRetrofitBucketForCreateRoom(String baseUrl, String roomType,
@Nullable String invite,
@Nullable String conversationName) {
RetrofitBucket retrofitBucket = new RetrofitBucket();
retrofitBucket.setUrl(baseUrl + ocsApiVersion + spreedApiVersion + "/room");
Map<String, String> queryMap = new HashMap<>();
queryMap.put("roomType", roomType);
if (invite != null) {
queryMap.put("invite", invite);
}
if (conversationName != null) {
queryMap.put("roomName", conversationName);
}
retrofitBucket.setQueryMap(queryMap);

View File

@ -40,8 +40,8 @@ public class DeviceUtils {
try {
@SuppressLint("PrivateApi") Class<?> appOpsUtilsClass = Class.forName("android.miui.AppOpsUtils");
if (appOpsUtilsClass != null) {
Method setApplicationAutoStartMethod = appOpsUtilsClass.getDeclaredMethod("setApplicationAutoStart", Context.class, String
.class, Boolean.TYPE);
Method setApplicationAutoStartMethod = appOpsUtilsClass.getMethod("setApplicationAutoStart", Context
.class, String.class, Boolean.TYPE);
if (setApplicationAutoStartMethod != null) {
Context applicationContext = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
setApplicationAutoStartMethod.invoke(appOpsUtilsClass, applicationContext, applicationContext

View File

@ -26,14 +26,14 @@ public class BundleKeys {
public static final String KEY_BASE_URL = "KEY_BASE_URL";
public static final String KEY_IS_ACCOUNT_IMPORT = "KEY_IS_ACCOUNT_IMPORT";
public static final String KEY_ORIGINAL_PROTOCOL = "KEY_ORIGINAL_PROTOCOL";
public static final String KEY_ROOM = "KEY_ROOM";
public static final String KEY_ROOM = "KEY_CONVERSATION";
public static final String KEY_OPERATION_CODE = "KEY_OPERATION_CODE";
public static final String KEY_MENU_TYPE = "KEY_MENU_TYPE";
public static final String KEY_SHARE_INTENT = "KEY_SHARE_INTENT";
public static final String KEY_APP_ITEM_PACKAGE_NAME = "KEY_APP_ITEM_PACKAGE_NAME";
public static final String KEY_APP_ITEM_NAME = "KEY_APP_ITEM_NAME";
public static final String KEY_CALL_PASSWORD = "KEY_CALL_PASSWORD";
public static final String KEY_CALL_SESSION = "KEY_CALL_SESSION";
public static final String KEY_CALL_PASSWORD = "KEY_CONVERSATION_PASSWORD";
public static final String KEY_CALL_SESSION = "KEY_CONVERSATION_SESSION";
public static final String KEY_ROOM_TOKEN = "KEY_ROOM_TOKEN";
public static final String KEY_USER_ENTITY = "KEY_USER_ENTITY";
public static final String KEY_NEW_CONVERSATION = "KEY_NEW_CONVERSATION";
@ -43,4 +43,7 @@ public class BundleKeys {
public static final String KEY_NOTIFICATION_SUBJECT = "KEY_NOTIFICATION_SUBJECT";
public static final String KEY_NOTIFICATION_SIGNATURE = "KEY_NOTIFICATION_SIGNATURE";
public static final String KEY_INTERNAL_USER_ID = "KEY_INTERNAL_USER_ID";
public static final String KEY_CONVERSATION_TYPE = "KEY_CONVERSATION_TYPE";
public static final String KEY_INVITED_PARTICIPANTS = "KEY_INVITED_PARTICIPANTS";
public static final String KEY_CONVERSATION_NAME = "KEY_CONVERSATION_NAME";
}

View File

@ -122,7 +122,7 @@
You may attempt to join the call via web browser.</string>
<string name="nc_all_ok_operation">OK, all done!</string>
<string name="nc_ok">OK</string>
<string name="nc_call_name">Call name</string>
<string name="nc_call_name">Conversation name</string>
<string name="nc_proceed">Proceed</string>
<string name="nc_call_name_is_same">The name you entered is the same as the existing one</string>
<string name="nc_wrong_link">Conversation link is not valid</string>