package com.novoda.priorityshare;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ListAdapter;
import com.novoda.priorityshare.mru.DisabledMruPersister;
import com.novoda.priorityshare.mru.MruPersister;
import com.novoda.priorityshare.mru.SharedPreferencesMruPersister;
import java.util.ArrayList;
import java.util.List;
public class PriorityShareDialog extends DialogFragment {
public static final String TAG_PRIORITY_SHARE_DIALOG = "priority_share_dialog";
private static final String ARGS_KEY_TITLE = "title";
private static final String ARGS_KEY_THEME_RES_ID = "theme_res_id";
private static final String ARGS_KEY_TARGET_APPS = "target_apps";
private static final String ARGS_KEY_SHARING_INTENT = "sharing_intent";
private static final String ARGS_KEY_SHOW_MRU = "show_mru";
private static final String KEY_SHOWING_ALL_SHARE_TARGETS = "showing_all";
private ShareTargetsAdapter adapter;
private Intent sharingIntent;
private OnPrepareSharingIntentListener listener;
private MruPersister persister;
private boolean showMru;
private boolean showingAllShareTargets;
private ViewGroup dialogView;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle args = getArguments();
sharingIntent = args.getParcelable(ARGS_KEY_SHARING_INTENT);
showMru = extractShowMruFrom(args);
persister = createMruPersister(getActivity(), showMru);
adapter = createShareTargetsAdapterFrom(args, sharingIntent);
int themeResId = getThemeResIdIfProvidedIn(args);
CharSequence title = getTitleIfProvidedIn(args);
dialogView = createDialogView();
setupGridView(dialogView, adapter);
restoreShowingAllShareTargetsState(savedInstanceState);
tryShowingContentOrSwitchToEmptyStateUi(adapter);
return createDialog(themeResId, title, dialogView);
}
private boolean extractShowMruFrom(Bundle args) {
return args.getBoolean(ARGS_KEY_SHOW_MRU);
}
private MruPersister createMruPersister(Context context, boolean showMru) {
if (showMru) {
return SharedPreferencesMruPersister.newInstance(context);
}
return new DisabledMruPersister();
}
private void restoreShowingAllShareTargetsState(Bundle savedState) {
if (savedState != null) {
showingAllShareTargets = savedState.getBoolean(KEY_SHOWING_ALL_SHARE_TARGETS, false);
if (showingAllShareTargets) {
onShowMoreButtonClicked();
}
}
}
private void tryShowingContentOrSwitchToEmptyStateUi(ShareTargetsAdapter adapter) {
if (adapter.isEmpty()) {
onShowMoreButtonClicked();
if (adapter.isEmpty()) {
showEmptyStateUiOnly();
}
}
}
private Dialog createDialog(int themeResId, CharSequence title, View dialogView) {
AlertDialog.Builder builder = createDialogBuilder(themeResId)
.setCancelable(true)
.setView(dialogView);
if (!TextUtils.isEmpty(title)) {
builder.setTitle(title);
}
return builder.create();
}
@SuppressLint("InflateParams")
private ViewGroup createDialogView() {
LayoutInflater inflater = getActivity().getLayoutInflater();
return (ViewGroup) inflater.inflate(R.layout.ps__share_dialog, null, false);
}
private void setupGridView(ViewGroup rootView, ListAdapter adapter) {
GridView gridView = (GridView) rootView.findViewById(R.id.ps__dialog_grid);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(createOnListItemClickListener());
}
private AdapterView.OnItemClickListener createOnListItemClickListener() {
return new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
startExplicitTargetShareIntentFor(position);
dismiss();
}
};
}
private AlertDialog.Builder createDialogBuilder(int themeResId) {
if (themeResId != 0) {
return new AlertDialog.Builder(getActivity(), themeResId);
} else {
return new AlertDialog.Builder(getActivity());
}
}
private ShareTargetsAdapter createShareTargetsAdapterFrom(Bundle args, Intent sharingIntent) {
TargetApps targetApps = extractTargetAppsFrom(args);
List<ResolveInfo> allShareTargets = getAvailableShareTargets(sharingIntent);
List<ResolveInfo> priorityAppInfos = createPriorityResolveInfoList(targetApps, allShareTargets);
List<ResolveInfo> otherAppInfos = createOtherAppsResolveInfoList(priorityAppInfos, allShareTargets);
return ShareTargetsAdapter.newInstance(getActivity(), priorityAppInfos, otherAppInfos);
}
private TargetApps extractTargetAppsFrom(Bundle args) {
if (args.containsKey(ARGS_KEY_TARGET_APPS)) {
return args.getParcelable(ARGS_KEY_TARGET_APPS);
} else {
return TargetApps.NONE;
}
}
private List<ResolveInfo> createPriorityResolveInfoList(TargetApps targetApps, List<ResolveInfo> allShareTargets) {
List<ResolveInfo> resolveInfos = targetApps.extractTargetResolveInfosFrom(allShareTargets);
if (showMru) {
ResolveInfo mruResolveInfo = findMruResolveInfoIn(allShareTargets);
if (mruResolveInfo != null) {
ensureListContainsItem(resolveInfos, mruResolveInfo);
}
}
return resolveInfos;
}
private List<ResolveInfo> createOtherAppsResolveInfoList(List<ResolveInfo> priorityAppInfos, List<ResolveInfo> allAppInfos) {
List<ResolveInfo> otherAppsInfos = new ArrayList<ResolveInfo>(allAppInfos);
for (ResolveInfo priorityAppInfo : priorityAppInfos) {
otherAppsInfos.remove(priorityAppInfo);
}
return otherAppsInfos;
}
private ResolveInfo findMruResolveInfoIn(List<ResolveInfo> resolveInfos) {
String mruPackageName = persister.getLastUsedTarget();
for (ResolveInfo resolveInfo : resolveInfos) {
String packageName = resolveInfo.activityInfo.packageName;
if (packageName.equals(mruPackageName)) {
return resolveInfo;
}
}
return null;
}
private void ensureListContainsItem(List<ResolveInfo> resolveInfos, ResolveInfo targetResolveInfo) {
if (!resolveInfos.contains(targetResolveInfo)) {
resolveInfos.add(targetResolveInfo);
}
}
private List<ResolveInfo> getAvailableShareTargets(Intent sharingIntent) {
PackageManager packageManager = getActivity().getPackageManager();
return packageManager.queryIntentActivities(sharingIntent, 0);
}
private void onShowMoreButtonClicked() {
showAllShareTargets();
}
private void showAllShareTargets() {
hideShowMoreButton();
adapter.showAllApps();
showingAllShareTargets = true;
}
private void showEmptyStateUiOnly() {
hideShowMoreButton();
hideGridView();
getEmptyStateView().setVisibility(View.VISIBLE);
}
private void hideShowMoreButton() {
View showMoreButton = getShowMoreButton();
if (showMoreButton != null) {
View buttonStrip = (View) showMoreButton.getParent();
buttonStrip.setVisibility(View.GONE);
}
}
private void hideGridView() {
GridView gridView = getGridView();
if (gridView != null) {
gridView.setVisibility(View.GONE);
}
}
private int getThemeResIdIfProvidedIn(Bundle args) {
return args.getInt(ARGS_KEY_THEME_RES_ID, 0);
}
private CharSequence getTitleIfProvidedIn(Bundle args) {
return args.getCharSequence(ARGS_KEY_TITLE, "");
}
private void startExplicitTargetShareIntentFor(int position) {
Intent intent = wrapIntentWithExplicitTargetComponentForItem(position, sharingIntent);
storeMruItemFrom(intent);
intent = tweakIntentUsingListenerIfAnyIsSet(intent);
startActivity(intent);
}
private void storeMruItemFrom(Intent intent) {
persister.storeLastUsedTarget(intent.getComponent().getPackageName());
}
private Intent wrapIntentWithExplicitTargetComponentForItem(int position, Intent sharingIntent) {
Intent intent = new Intent(sharingIntent);
ActivityInfo activity = adapter.getItem(position).activityInfo;
ComponentName name = new ComponentName(activity.applicationInfo.packageName, activity.name);
intent.setComponent(name);
return intent;
}
private Intent tweakIntentUsingListenerIfAnyIsSet(Intent intent) {
if (listener == null) {
return intent;
}
return listener.onPrepareSharingIntent(intent);
}
public void setOnPrepareSharingIntentListener(OnPrepareSharingIntentListener listener) {
this.listener = listener;
}
@Override
public void onStart() {
super.onStart();
// TODO show empty state?
setupShowMoreButtonOnClickListener();
}
private void setupShowMoreButtonOnClickListener() {
View showMoreButton = getShowMoreButton();
if (showMoreButton != null) {
showMoreButton.setOnClickListener(createOnShowMoreButtonClickListener());
}
}
private View.OnClickListener createOnShowMoreButtonClickListener() {
return new View.OnClickListener() {
@Override
public void onClick(View v) {
onShowMoreButtonClicked();
}
};
}
private View getShowMoreButton() {
if (dialogView == null) {
return null;
}
return dialogView.findViewById(R.id.ps__show_more_button);
}
private GridView getGridView() {
if (dialogView == null) {
return null;
}
return (GridView) dialogView.findViewById(R.id.ps__dialog_grid);
}
private View getEmptyStateView() {
if (dialogView == null) {
return null;
}
return dialogView.findViewById(android.R.id.empty);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(KEY_SHOWING_ALL_SHARE_TARGETS, showingAllShareTargets);
}
public static class Builder {
private CharSequence title;
private int themeResId;
private TargetApps targetApps;
private Intent sharingIntent;
private OnPrepareSharingIntentListener listener;
private boolean showMru;
public Builder setTitle(CharSequence title) {
this.title = title;
this.showMru = true;
return this;
}
public Builder setThemeResId(int themeResId) {
this.themeResId = themeResId;
return this;
}
public Builder setTargetApps(TargetApps targetApps) {
this.targetApps = targetApps;
return this;
}
public Builder setSharingIntent(Intent sharingIntent) {
this.sharingIntent = sharingIntent;
return this;
}
public Builder setOnPrepareSharingIntentListener(OnPrepareSharingIntentListener listener) {
this.listener = listener;
return this;
}
public Builder setShowMostRecentlyUsed(boolean showMostRecentlyUsed) {
this.showMru = showMostRecentlyUsed;
return this;
}
public PriorityShareDialog build() {
PriorityShareDialog dialog = new PriorityShareDialog();
Bundle args = new Bundle();
if (!TextUtils.isEmpty(title)) {
args.putCharSequence(ARGS_KEY_TITLE, title);
}
if (themeResId != 0) {
args.putInt(ARGS_KEY_THEME_RES_ID, themeResId);
}
if (targetApps != null) {
args.putParcelable(ARGS_KEY_TARGET_APPS, targetApps);
}
if (sharingIntent != null) {
args.putParcelable(ARGS_KEY_SHARING_INTENT, sharingIntent);
}
args.putBoolean(ARGS_KEY_SHOW_MRU, showMru);
dialog.setArguments(args);
dialog.setOnPrepareSharingIntentListener(listener);
return dialog;
}
}
}