소스 검색

Some work on group/public calls

Signed-off-by: Mario Danic <mario@lovelyhq.com>
Mario Danic 7 년 전
부모
커밋
517e74820f

+ 48 - 1
app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java

@@ -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,7 +239,26 @@ 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() {
@@ -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();
+    }
 }

+ 14 - 2
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.java

@@ -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;

+ 147 - 2
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.java

@@ -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);

+ 1 - 1
app/src/main/java/com/nextcloud/talk/models/database/User.java

@@ -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) {

+ 1 - 0
app/src/main/java/com/nextcloud/talk/models/json/rooms/Room.java

@@ -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,

+ 2 - 1
app/src/main/java/com/nextcloud/talk/utils/AccountUtils.java

@@ -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");
         }

+ 11 - 2
app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java

@@ -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);
-        queryMap.put("invite", invite);
+        if (invite != null) {
+            queryMap.put("invite", invite);
+        }
+
+        if (conversationName != null) {
+            queryMap.put("roomName", conversationName);
+        }
 
         retrofitBucket.setQueryMap(queryMap);
 

+ 2 - 2
app/src/main/java/com/nextcloud/talk/utils/DeviceUtils.java

@@ -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

+ 6 - 3
app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.java

@@ -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";
 }

+ 1 - 1
app/src/main/res/values/strings.xml

@@ -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>