package org.fdroid.fdroid.views; import android.app.Dialog; import android.content.ComponentName; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ResolveInfo; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.BottomSheetDialogFragment; import android.support.design.widget.CoordinatorLayout; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import org.fdroid.fdroid.BuildConfig; import org.fdroid.fdroid.R; import org.fdroid.fdroid.Utils; import java.util.ArrayList; import java.util.List; public class ShareChooserDialog extends BottomSheetDialogFragment { private static final String ARG_WIDTH = "width"; private static final String ARG_INTENT = "intent"; private static final String ARG_SHOW_NEARBY = "showNearby"; private static final int VIEWTYPE_SWAP = 1; private static final int VIEWTYPE_INTENT = 0; private RecyclerView recyclerView; private ArrayList<ResolveInfo> targets; private int parentWidth; private Intent shareIntent; private boolean showNearby; public interface ShareChooserDialogListener { void onNearby(); void onResolvedShareIntent(Intent shareIntent); } private ShareChooserDialogListener listener; private void setListener(ShareChooserDialogListener listener) { this.listener = listener; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); parentWidth = getArguments().getInt(ARG_WIDTH, 640); shareIntent = getArguments().getParcelable(ARG_INTENT); showNearby = getArguments().getBoolean(ARG_SHOW_NEARBY, false); targets = new ArrayList<>(); List<ResolveInfo> resInfo = getContext().getPackageManager().queryIntentActivities(shareIntent, 0); if (resInfo != null && resInfo.size() > 0) { for (ResolveInfo resolveInfo : resInfo) { String packageName = resolveInfo.activityInfo.packageName; if (!packageName.equals(BuildConfig.APPLICATION_ID)) { // Remove ourselves targets.add(resolveInfo); } } } } @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Dialog dialog = super.onCreateDialog(savedInstanceState); dialog.setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialogInterface) { dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); dialog.getWindow().setLayout( parentWidth - Utils.dpToPx(0, getContext()), // Set margins here! ViewGroup.LayoutParams.MATCH_PARENT); } }); return dialog; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.share_chooser, container, false); setupView(v); return v; } private void setupView(View v) { recyclerView = (RecyclerView) v.findViewById(R.id.recycler_view_apps); // Figure out how many columns that fit in the given parent width. Give them 100dp. int appWidth = Utils.dpToPx(80, getContext()); final int nCols = (parentWidth - /* padding */ Utils.dpToPx(8, getContext())) / appWidth; GridLayoutManager glm = new GridLayoutManager(getContext(), nCols); // Ensure that if available, the "Nearby Swap" item spans the entire width. glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { if (recyclerView.getAdapter() != null) { if (recyclerView.getAdapter().getItemViewType(position) == VIEWTYPE_SWAP) { return nCols; } return 1; } return 0; } }); recyclerView.setLayoutManager(glm); class VH extends RecyclerView.ViewHolder { public final ImageView icon; public final TextView label; VH(View itemView) { super(itemView); icon = (ImageView) itemView.findViewById(R.id.ivShare); label = (TextView) itemView.findViewById(R.id.tvShare); } } recyclerView.setAdapter(new RecyclerView.Adapter<VH>() { private ArrayList<ResolveInfo> intents; RecyclerView.Adapter init(List<ResolveInfo> targetedShareIntents) { intents = new ArrayList<>(); if (showNearby) { intents.add(null); } for (ResolveInfo ri : targetedShareIntents) { intents.add(ri); } return this; } @Override public int getItemViewType(int position) { if (intents.get(position) == null) { return VIEWTYPE_SWAP; } return VIEWTYPE_INTENT; } @Override public VH onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate((viewType == 1) ? R.layout.share_header_item : R.layout.share_item, parent, false); return new VH(view); } @Override public void onBindViewHolder(VH holder, int position) { if (getItemViewType(position) == VIEWTYPE_SWAP) { holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (listener != null) { listener.onNearby(); } dismiss(); } }); return; } final ResolveInfo ri = intents.get(position); holder.icon.setImageDrawable(ri.loadIcon(getContext().getPackageManager())); holder.label.setText(ri.loadLabel(getContext().getPackageManager())); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (listener != null) { Intent intent = new Intent(shareIntent); ComponentName name = new ComponentName(ri.activityInfo.applicationInfo.packageName, ri.activityInfo.name); intent.setComponent(name); listener.onResolvedShareIntent(intent); } dismiss(); } }); } @Override public int getItemCount() { return intents.size(); } }.init(targets)); } public static void createChooser(CoordinatorLayout rootView, ShareChooserDialog.ShareChooserDialogListener listener, final AppCompatActivity parent, final Intent shareIntent, boolean showNearbyItem) { ShareChooserDialog d = new ShareChooserDialog(); d.setListener(listener); Bundle args = new Bundle(); args.putInt(ARG_WIDTH, rootView.getWidth()); args.putParcelable(ARG_INTENT, shareIntent); args.putBoolean(ARG_SHOW_NEARBY, showNearbyItem); d.setArguments(args); d.show(parent.getSupportFragmentManager(), "Share"); } }