瀏覽代碼

Sharing handling

Signed-off-by: Mario Danic <mario@lovelyhq.com>
Mario Danic 7 年之前
父節點
當前提交
30aea14646

+ 1 - 1
app/build.gradle

@@ -111,7 +111,7 @@ dependencies {
 
     debugImplementation "javax.transaction:transaction-api:1.1-rev-1"
 
-    implementation 'com.github.HITGIF:TextFieldBoxes:1.3.7'
+    implementation 'com.github.HITGIF:TextFieldBoxes:1.3.8'
 
     implementation 'eu.davidea:flexible-adapter:5.0.0-rc4'
     implementation 'eu.davidea:flexible-adapter-ui:1.0.0-b1'

+ 125 - 0
app/src/main/java/com/nextcloud/talk/adapters/items/AppItem.java

@@ -0,0 +1,125 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.adapters.items;
+
+import android.graphics.drawable.Drawable;
+import android.support.annotation.Nullable;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.ForegroundColorSpan;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.nextcloud.talk.R;
+import com.nextcloud.talk.application.NextcloudTalkApplication;
+
+import java.util.List;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import eu.davidea.flexibleadapter.FlexibleAdapter;
+import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
+import eu.davidea.viewholders.FlexibleViewHolder;
+
+public class AppItem extends AbstractFlexibleItem<AppItem.AppItemViewHolder> {
+    private String title;
+    private String packageName;
+    private String name;
+    @Nullable private Drawable drawable;
+
+    public AppItem(String title, String packageName, String name, @Nullable Drawable drawable) {
+        this.title = title;
+        this.packageName = packageName;
+        this.name = name;
+        this.drawable = drawable;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof AppItem) {
+            AppItem inItem = (AppItem) o;
+            return title.equals(inItem.getTitle()) && packageName.equals(inItem.getPackageName()) && name.equals(inItem
+                    .getName());
+        }
+
+        return false;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public int getLayoutRes() {
+        return R.layout.rv_item_app;
+    }
+
+    @Override
+    public AppItem.AppItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
+        return new AppItemViewHolder(view, adapter);
+    }
+
+    @Override
+    public void bindViewHolder(FlexibleAdapter adapter, AppItem.AppItemViewHolder holder, int position, List<Object> payloads) {
+        if (drawable != null) {
+            holder.iconImageView.setVisibility(View.VISIBLE);
+            holder.iconImageView.setImageDrawable(drawable);
+        } else {
+            holder.iconImageView.setVisibility(View.GONE);
+        }
+
+        if (position == 0) {
+            Spannable spannableString = new SpannableString(title);
+            spannableString.setSpan(new ForegroundColorSpan(NextcloudTalkApplication.getSharedApplication()
+                            .getResources().getColor(R.color.colorPrimary)), 0,
+                    spannableString.length(),
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            holder.appTitleTextView.setText(spannableString);
+        } else {
+            holder.appTitleTextView.setText(title);
+        }
+    }
+
+    static class AppItemViewHolder extends FlexibleViewHolder {
+        @BindView(R.id.icon_image_view)
+        public ImageView iconImageView;
+        @BindView(R.id.app_title_text_view)
+        public TextView appTitleTextView;
+
+        /**
+         * Default constructor.
+         */
+        AppItemViewHolder(View view, FlexibleAdapter adapter) {
+            super(view, adapter);
+            ButterKnife.bind(this, view);
+        }
+    }
+
+}

+ 1 - 1
app/src/main/java/com/nextcloud/talk/adapters/items/MenuItem.java

@@ -72,7 +72,7 @@ public class MenuItem extends AbstractFlexibleItem<MenuItem.MenuItemViewHolder>
 
     @Override
     public void bindViewHolder(FlexibleAdapter adapter, MenuItem.MenuItemViewHolder holder, int position, List payloads) {
-        if (title.equals(NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_what))) {
+        if (position == 0) {
             Spannable spannableString = new SpannableString(NextcloudTalkApplication.getSharedApplication()
                     .getString(R.string.nc_what));
             spannableString.setSpan(new ForegroundColorSpan(NextcloudTalkApplication.getSharedApplication()

+ 12 - 6
app/src/main/java/com/nextcloud/talk/controllers/CallsListController.java

@@ -43,6 +43,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 com.bluelinelabs.conductor.RouterTransaction;
@@ -416,6 +417,9 @@ public class CallsListController extends BaseController implements SearchView.On
 
         if (bottomSheet == null) {
             bottomSheet = new BottomSheet.Builder(getActivity()).setView(view).create();
+            if (bottomSheet.getWindow() != null) {
+                bottomSheet.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
+            }
         }
 
         bottomSheet.show();
@@ -426,12 +430,14 @@ public class CallsListController extends BaseController implements SearchView.On
         overridePushHandler(new NoOpControllerChangeHandler());
         overridePopHandler(new NoOpControllerChangeHandler());
         CallItem callItem = adapter.getItem(position);
-        Intent callIntent = new Intent(getActivity(), CallActivity.class);
-        BundleBuilder bundleBuilder = new BundleBuilder(new Bundle());
-        bundleBuilder.putString("roomToken", callItem.getModel().getToken());
-        bundleBuilder.putParcelable("userEntity", Parcels.wrap(userEntity));
-        callIntent.putExtras(bundleBuilder.build());
-        startActivity(callIntent);
+        if (callItem != null && getActivity() != null) {
+            Intent callIntent = new Intent(getActivity(), CallActivity.class);
+            BundleBuilder bundleBuilder = new BundleBuilder(new Bundle());
+            bundleBuilder.putString("roomToken", callItem.getModel().getToken());
+            bundleBuilder.putParcelable("userEntity", Parcels.wrap(userEntity));
+            callIntent.putExtras(bundleBuilder.build());
+            startActivity(callIntent);
+        }
 
         return true;
     }

+ 93 - 36
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/CallMenuController.java

@@ -20,6 +20,8 @@
 
 package com.nextcloud.talk.controllers.bottomsheet;
 
+import android.content.ComponentName;
+import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.v7.widget.DividerItemDecoration;
@@ -30,13 +32,17 @@ import android.view.View;
 import android.view.ViewGroup;
 
 import com.bluelinelabs.conductor.RouterTransaction;
+import com.kennyc.bottomsheet.adapters.AppAdapter;
 import com.nextcloud.talk.R;
+import com.nextcloud.talk.adapters.items.AppItem;
 import com.nextcloud.talk.adapters.items.MenuItem;
 import com.nextcloud.talk.api.models.json.rooms.Room;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.controllers.base.BaseController;
 import com.nextcloud.talk.events.BottomSheetLockEvent;
+import com.nextcloud.talk.utils.ShareUtils;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
+import com.nextcloud.talk.utils.database.user.UserUtils;
 
 import org.greenrobot.eventbus.EventBus;
 import org.parceler.Parcels;
@@ -60,13 +66,22 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
     @Inject
     EventBus eventBus;
 
+    @Inject
+    UserUtils userUtils;
+
     private Room room;
     private List<AbstractFlexibleItem> menuItems;
     private FlexibleAdapter<AbstractFlexibleItem> adapter;
 
+    private boolean isShare;
+    private Intent shareIntent;
+
     public CallMenuController(Bundle args) {
         super(args);
         this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
+        if (args.containsKey(BundleKeys.KEY_IS_SHARE)) {
+            this.isShare = true;
+        }
     }
 
     @Override
@@ -100,67 +115,109 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
         ));
     }
 
+    private void prepareIntent() {
+        shareIntent = new Intent(Intent.ACTION_SEND);
+        shareIntent.setType("text/plain");
+        shareIntent.putExtra(Intent.EXTRA_SUBJECT, getResources().getString(R.string.nc_share_subject));
+    }
+
     private void prepareMenu() {
         menuItems = new ArrayList<>();
 
-        menuItems.add(new MenuItem(getResources().getString(R.string.nc_what), 0));
+        if (!isShare) {
+            menuItems.add(new MenuItem(getResources().getString(R.string.nc_what), 0));
 
-        menuItems.add(new MenuItem(getResources().getString(R.string.nc_leave), 1));
+            menuItems.add(new MenuItem(getResources().getString(R.string.nc_leave), 1));
 
-        if (room.isNameEditable()) {
-            menuItems.add(new MenuItem(getResources().getString(R.string.nc_rename), 2));
-        }
+            if (room.isNameEditable()) {
+                menuItems.add(new MenuItem(getResources().getString(R.string.nc_rename), 2));
+            }
 
-        if (room.canModerate()) {
-            if (!room.isPublic()) {
-                menuItems.add(new MenuItem(getResources().getString(R.string.nc_make_call_public), 3));
-            } else {
-                if (room.isHasPassword()) {
-                    menuItems.add(new MenuItem(getResources().getString(R.string.nc_change_password), 4));
-                    menuItems.add(new MenuItem(getResources().getString(R.string.nc_clear_password), 5));
+            if (room.canModerate()) {
+                if (!room.isPublic()) {
+                    menuItems.add(new MenuItem(getResources().getString(R.string.nc_make_call_public), 3));
                 } else {
-                    menuItems.add(new MenuItem(getResources().getString(R.string.nc_set_password), 6));
+                    if (room.isHasPassword()) {
+                        menuItems.add(new MenuItem(getResources().getString(R.string.nc_change_password), 4));
+                        menuItems.add(new MenuItem(getResources().getString(R.string.nc_clear_password), 5));
+                    } else {
+                        menuItems.add(new MenuItem(getResources().getString(R.string.nc_set_password), 6));
+                    }
                 }
             }
-        }
 
-        if (room.isPublic()) {
-            menuItems.add(new MenuItem(getResources().getString(R.string.nc_share_link), 7));
-            if (room.canModerate()) {
-                menuItems.add(new MenuItem(getResources().getString(R.string.nc_make_call_private), 8));
+            if (room.isPublic()) {
+                menuItems.add(new MenuItem(getResources().getString(R.string.nc_share_link), 7));
+                if (room.canModerate()) {
+                    menuItems.add(new MenuItem(getResources().getString(R.string.nc_make_call_private), 8));
+                }
             }
-        }
 
-        if (room.isDeletable()) {
-            menuItems.add(new MenuItem(getResources().getString(R.string.nc_delete_call), 9));
+            if (room.isDeletable()) {
+                menuItems.add(new MenuItem(getResources().getString(R.string.nc_delete_call), 9));
+            }
+        } else {
+            prepareIntent();
+            List<AppAdapter.AppInfo> appInfoList = ShareUtils.getShareApps(getActivity(), shareIntent, null,
+                    null);
+            menuItems.add(new AppItem(getResources().getString(R.string.nc_share_link_via), "", "",
+                    null));
+            if (appInfoList != null) {
+                for (AppAdapter.AppInfo appInfo : appInfoList) {
+                    menuItems.add(new AppItem(appInfo.title, appInfo.packageName, appInfo.name, appInfo.drawable));
+                }
+            }
         }
     }
 
     @Override
     public boolean onItemClick(int position) {
-        MenuItem menuItem = (MenuItem) adapter.getItem(position);
         Bundle bundle = new Bundle();
-        if (menuItem != null) {
-            int tag = menuItem.getTag();
+        bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
+
+        if (!isShare) {
+            MenuItem menuItem = (MenuItem) adapter.getItem(position);
+            if (menuItem != null) {
 
-            if (tag == 5) {
-                room.setPassword("");
+                int tag = menuItem.getTag();
+                if (tag == 5) {
+                    room.setPassword("");
+                }
+
+                if (tag > 0 && tag < 10) {
+                    bundle.putInt(BundleKeys.KEY_OPERATION_CODE, tag);
+                    if (tag != 2 && tag != 4 && tag != 6 && tag != 7) {
+                        eventBus.post(new BottomSheetLockEvent(false, 0, false));
+                        getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
+                    } else if (tag != 7) {
+                        getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle)));
+                    } else {
+                        bundle.putBoolean(BundleKeys.KEY_IS_SHARE, true);
+                        getRouter().pushController(RouterTransaction.with(new CallMenuController(bundle)));
+                    }
+                }
             }
-            bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
-
-            if (tag > 0 && tag < 10) {
-                bundle.putInt(BundleKeys.KEY_OPERATION_CODE, tag);
-                if (tag != 2 && tag != 4 && tag != 6 && tag != 7) {
-                    eventBus.post(new BottomSheetLockEvent(false, 0, false));
-                    getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
-                } else if (tag != 7) {
-                    getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle)));
+        } else if (position != 0) {
+            AppItem appItem = (AppItem) adapter.getItem(position);
+            if (appItem != null && getActivity() != null) {
+                if (!room.hasPassword) {
+                    shareIntent.putExtra(Intent.EXTRA_TEXT, ShareUtils.getStringForIntent(getActivity(), null,
+                            userUtils, room));
+                    Intent intent = new Intent(shareIntent);
+                    intent.setComponent(new ComponentName(appItem.getPackageName(), appItem.getName()));
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    getActivity().startActivity(intent);
                 } else {
-                    // do nothing for now, this is share
+                    bundle.putInt(BundleKeys.KEY_OPERATION_CODE, 7);
+                    bundle.putParcelable(BundleKeys.KEY_SHARE_INTENT, Parcels.wrap(shareIntent));
+                    bundle.putString(BundleKeys.KEY_APP_ITEM_PACKAGE_NAME, appItem.getPackageName());
+                    bundle.putString(BundleKeys.KEY_APP_ITEM_NAME, appItem.getName());
+                    getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle)));
                 }
             }
         }
 
+
         return true;
     }
 }

+ 43 - 15
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.java

@@ -20,6 +20,8 @@
 
 package com.nextcloud.talk.controllers.bottomsheet;
 
+import android.content.ComponentName;
+import android.content.Intent;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.text.Editable;
@@ -36,7 +38,9 @@ import com.nextcloud.talk.api.models.json.rooms.Room;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.controllers.base.BaseController;
 import com.nextcloud.talk.events.BottomSheetLockEvent;
+import com.nextcloud.talk.utils.ShareUtils;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
+import com.nextcloud.talk.utils.database.user.UserUtils;
 
 import org.greenrobot.eventbus.EventBus;
 import org.parceler.Parcels;
@@ -65,13 +69,26 @@ public class EntryMenuController extends BaseController {
     @Inject
     EventBus eventBus;
 
+    @Inject
+    UserUtils userUtils;
+
     private int operationCode;
     private Room room;
+    private Intent shareIntent;
+    private String packageName;
+    private String name;
 
     public EntryMenuController(Bundle args) {
         super(args);
         this.operationCode = args.getInt(BundleKeys.KEY_OPERATION_CODE);
         this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
+
+        if (args.containsKey(BundleKeys.KEY_SHARE_INTENT)) {
+            this.shareIntent = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_SHARE_INTENT));
+        }
+
+        this.name = args.getString(BundleKeys.KEY_APP_ITEM_NAME, "");
+        this.packageName = args.getString(BundleKeys.KEY_APP_ITEM_PACKAGE_NAME, "");
     }
 
     @Override
@@ -81,17 +98,28 @@ public class EntryMenuController extends BaseController {
 
     @OnClick(R.id.ok_button)
     public void onProceedButtonClick() {
-        eventBus.post(new BottomSheetLockEvent(false, 0, false));
-
-        Bundle bundle = new Bundle();
-        if (operationCode == 4 || operationCode == 6) {
-            room.setPassword(editText.getText().toString());
+        if (operationCode != 7) {
+            eventBus.post(new BottomSheetLockEvent(false, 0, false));
+
+            Bundle bundle = new Bundle();
+            if (operationCode == 4 || operationCode == 6) {
+                room.setPassword(editText.getText().toString());
+            } else {
+                room.setName(editText.getText().toString());
+            }
+            bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
+            bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode);
+            getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
         } else {
-            room.setName(editText.getText().toString());
+            if (getActivity() != null) {
+                shareIntent.putExtra(Intent.EXTRA_TEXT, ShareUtils.getStringForIntent(getActivity(),
+                        editText.getText().toString(), userUtils, room));
+                Intent intent = new Intent(shareIntent);
+                intent.setComponent(new ComponentName(packageName, name));
+                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                getActivity().startActivity(intent);
+            }
         }
-        bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
-        bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode);
-        getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
     }
 
     @Override
@@ -142,23 +170,23 @@ public class EntryMenuController extends BaseController {
             }
         });
 
-        String helperText = "";
+        String labelText = "";
         switch (operationCode) {
             case 2:
-                helperText = getResources().getString(R.string.nc_call_name);
+                labelText = getResources().getString(R.string.nc_call_name);
                 break;
             case 4:
-                helperText = getResources().getString(R.string.nc_new_password);
+                labelText = getResources().getString(R.string.nc_new_password);
                 break;
             case 6:
-                helperText = getResources().getString(R.string.nc_password);
+            case 7:
+                labelText = getResources().getString(R.string.nc_password);
                 break;
             default:
                 break;
         }
 
-        textFieldBoxes.setHelperText(helperText);
+        textFieldBoxes.setLabelText(labelText);
         editText.requestFocus();
     }
-
 }

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

@@ -150,7 +150,7 @@ public class OperationsMenuController extends BaseController {
                             .subscribe(operationsObserver);
                     break;
                 case 7:
-                    // Operation 6 is sharing, so we handle this differently
+                    // Operation 7 is sharing, so we handle this differently
                     break;
                 case 8:
                     ncApi.makeRoomPrivate(credentials, ApiHelper.getUrlForRoomVisibility(userEntity.getBaseUrl(), room

+ 112 - 0
app/src/main/java/com/nextcloud/talk/utils/ShareUtils.java

@@ -0,0 +1,112 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Part of the code in ShareUtils was inspired by BottomSheet under the Apache licence
+ * located here: https://github.com/Kennyc1012/BottomSheet/blob/master/library/src/main/java/com/kennyc/bottomsheet/BottomSheet.java#L425
+ */
+
+package com.nextcloud.talk.utils;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+
+import com.kennyc.bottomsheet.adapters.AppAdapter;
+import com.nextcloud.talk.R;
+import com.nextcloud.talk.api.models.json.rooms.Room;
+import com.nextcloud.talk.persistence.entities.UserEntity;
+import com.nextcloud.talk.utils.database.user.UserUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public class ShareUtils {
+    private static final String TAG = "ShareUtils";
+
+    public static String getStringForIntent(Context context, @Nullable String password, UserUtils userUtils, Room
+            room) {
+        UserEntity userEntity = userUtils.getCurrentUser();
+
+        String shareString = "";
+        if (userEntity != null && context != null) {
+            shareString = String.format(context.getResources().getString(R.string.nc_share_text),
+                    userEntity.getBaseUrl(), room.getToken());
+
+            if (!TextUtils.isEmpty(password)) {
+                shareString += String.format(context.getResources().getString(R.string.nc_share_text_pass), password);
+            }
+
+            shareString += String.format(context.getResources().getString(R.string.nc_talk_soon), userEntity
+                    .getDisplayName()
+            );
+        }
+
+        return shareString;
+    }
+
+    public static List<AppAdapter.AppInfo> getShareApps(Context context, Intent intent,
+                                                        @Nullable Set<String> appsFilter, @Nullable Set<String> toExclude) {
+
+        if (context == null || intent == null) return null;
+
+        PackageManager manager = context.getPackageManager();
+        List<ResolveInfo> apps = manager.queryIntentActivities(intent, 0);
+
+        if (apps != null && !apps.isEmpty()) {
+            List<AppAdapter.AppInfo> appResources = new ArrayList<>(apps.size());
+            boolean shouldCheckPackages = appsFilter != null && !appsFilter.isEmpty();
+
+            for (ResolveInfo resolveInfo : apps) {
+                String packageName = resolveInfo.activityInfo.packageName;
+
+                if (shouldCheckPackages && !appsFilter.contains(packageName)) {
+                    continue;
+                }
+
+                String title = resolveInfo.loadLabel(manager).toString();
+                String name = resolveInfo.activityInfo.name;
+                Drawable drawable = resolveInfo.loadIcon(manager);
+                appResources.add(new AppAdapter.AppInfo(title, packageName, name, drawable));
+            }
+
+            if (toExclude != null && !toExclude.isEmpty()) {
+                List<AppAdapter.AppInfo> toRemove = new ArrayList<>();
+
+                for (AppAdapter.AppInfo appInfo : appResources) {
+                    if (toExclude.contains(appInfo.packageName)) {
+                        toRemove.add(appInfo);
+                    }
+                }
+
+                if (!toRemove.isEmpty()) appResources.removeAll(toRemove);
+            }
+
+            return appResources;
+
+        }
+
+        return null;
+    }
+
+}

+ 4 - 0
app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.java

@@ -28,4 +28,8 @@ public class BundleKeys {
     public static final String KEY_ORIGINAL_PROTOCOL = "KEY_ORIGINAL_PROTOCOL";
     public static final String KEY_ROOM = "KEY_ROOM";
     public static final String KEY_OPERATION_CODE = "KEY_OPERATION_CODE";
+    public static final String KEY_IS_SHARE = "KEY_IS_SHARE";
+    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";
 }

+ 1 - 1
app/src/main/res/layout/controller_entry_menu.xml

@@ -28,7 +28,7 @@
     <studio.carbonylgroup.textfieldboxes.TextFieldBoxes
         android:id="@+id/text_field_boxes"
         android:layout_width="match_parent"
-        android:layout_height="80dp"
+        android:layout_height="96dp"
         android:layout_marginEnd="@dimen/activity_horizontal_margin"
         android:layout_marginStart="@dimen/activity_horizontal_margin"
         app:errorColor="@color/nc_darkRed"

+ 50 - 0
app/src/main/res/layout/rv_item_app.xml

@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Nextcloud Talk application
+  ~
+  ~ @author Mario Danic
+  ~ Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
+  ~
+  ~ This program is free software: you can redistribute it and/or modify
+  ~ it under the terms of the GNU General Public License as published by
+  ~ the Free Software Foundation, either version 3 of the License, or
+  ~ at your option) any later version.
+  ~
+  ~ This program is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  ~ GNU General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU General Public License
+  ~ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                xmlns:tools="http://schemas.android.com/tools"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="16dp"
+                android:layout_marginTop="16dp"
+                android:background="@color/nc_white_color"
+                android:orientation="horizontal">
+
+    <ImageView
+        android:id="@+id/icon_image_view"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:layout_centerVertical="true"
+        android:layout_marginStart="16dp"/>
+
+    <TextView
+        android:id="@+id/app_title_text_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginEnd="16dp"
+        android:layout_centerVertical="true"
+        android:layout_toEndOf="@id/icon_image_view"
+        android:textAlignment="center"
+        android:textSize="12sp"
+        tools:text="App title"/>
+
+</RelativeLayout>

+ 4 - 1
app/src/main/res/layout/rv_item_menu.xml

@@ -22,13 +22,16 @@
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:layout_marginTop="16dp"
+                android:layout_marginBottom="16dp"
                 android:orientation="vertical">
 
     <TextView
         android:id="@+id/menu_text"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_margin="16dp"
+        android:layout_marginStart="16dp"
+        android:layout_marginEnd="16dp"
         android:textSize="12sp"/>
 
 </RelativeLayout>

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

@@ -77,6 +77,7 @@
     <string name="nc_change_password">Change a password</string>
     <string name="nc_clear_password">Clear password</string>
     <string name="nc_share_link">Share link</string>
+    <string name="nc_share_link_via">Share link via</string>
     <string name="nc_make_call_public">Make call public</string>
     <string name="nc_make_call_private">Make call private</string>
     <string name="nc_delete_call">Delete call</string>
@@ -110,5 +111,9 @@
     <string name="nc_call_name">Call 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_share_text">Hello,\n\nI would like you to join a call with me.\n\nYou can join this call via
+        %1$s/index.php/call/%2$s</string>
+    <string name="nc_talk_soon">\n\nTalk soon,\n %1$s</string>
+    <string name="nc_share_subject">Call invitation</string>
+    <string name="nc_share_text_pass">\n\nPassword for the call is: %1$s</string>
 </resources>