Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c9875bd7 authored by Mike Digman's avatar Mike Digman Committed by Automerger Merge Worker
Browse files

Merge "Add icons to Sharesheet pin and group selection UI" into rvc-dev am:...

Merge "Add icons to Sharesheet pin and group selection UI" into rvc-dev am: 29dfff42 am: a7266103 am: ee0ed5f8 am: 863c20f3

Change-Id: I07d82d02c40f5a5c21a352f22ae1c620f9a7c4b4
parents 110b476e 863c20f3
Loading
Loading
Loading
Loading
+19 −26
Original line number Diff line number Diff line
@@ -1614,7 +1614,7 @@ public class ChooserActivity extends ResolverActivity implements
            targetList = Collections.singletonList(ti);
        }

        ResolverTargetActionsDialogFragment f = new ResolverTargetActionsDialogFragment(
        ChooserTargetActionsDialogFragment f = new ChooserTargetActionsDialogFragment(
                targetList, mChooserMultiProfilePagerAdapter.getCurrentUserHandle());

        f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG);
@@ -1674,15 +1674,9 @@ public class ChooserActivity extends ResolverActivity implements
        if (targetInfo instanceof MultiDisplayResolveInfo) {
            MultiDisplayResolveInfo mti = (MultiDisplayResolveInfo) targetInfo;
            if (!mti.hasSelected()) {
                // Stacked apps get a disambiguation first
                CharSequence[] labels = new CharSequence[mti.getTargets().size()];
                int i = 0;
                for (TargetInfo ti : mti.getTargets()) {
                    labels[i++] = ti.getResolveInfo().loadLabel(getPackageManager());
                }
                ChooserStackedAppDialogFragment f = new ChooserStackedAppDialogFragment(
                        targetInfo.getDisplayLabel(),
                        ((MultiDisplayResolveInfo) targetInfo), labels, which);
                        mti, which,
                        mChooserMultiProfilePagerAdapter.getCurrentUserHandle());

                f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG);
                return;
@@ -2973,19 +2967,19 @@ public class ChooserActivity extends ResolverActivity implements
                itemView.setOnClickListener(v -> startSelected(mListPosition,
                        false/* always */, true/* filterd */));

                TargetInfo ti = mChooserMultiProfilePagerAdapter.getActiveListAdapter()
                itemView.setOnLongClickListener(v -> {
                    final TargetInfo ti = mChooserMultiProfilePagerAdapter.getActiveListAdapter()
                            .targetInfoForPosition(mListPosition, /* filtered */ true);

                    // This should always be the case for ItemViewHolder, check for sanity
                    if (ti instanceof DisplayResolveInfo) {
                    itemView.setOnLongClickListener(v -> {
                        showTargetDetails((DisplayResolveInfo) ti);
                    }
                    return true;
                });
            }
        }
    }
    }

    /**
     * Add a footer to the list, to support scrolling behavior below the navbar.
@@ -3310,17 +3304,16 @@ public class ChooserActivity extends ResolverActivity implements

                // Direct Share targets should not show any menu
                if (!isDirectShare) {
                    v.setOnLongClickListener(v1 -> {
                        final TargetInfo ti = mChooserListAdapter.targetInfoForPosition(
                                holder.getItemIndex(column), true);

                        // This should always be the case for non-DS targets, check for sanity
                        if (ti instanceof DisplayResolveInfo) {
                        v.setOnLongClickListener(v1 -> {
                            showTargetDetails((DisplayResolveInfo) ti);
                        }
                        return true;
                    });
                }
                }

                holder.addView(i, v);

+19 −33
Original line number Diff line number Diff line
@@ -17,64 +17,50 @@

package com.android.internal.app;

import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.res.Configuration;
import android.os.Bundle;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;

import com.android.internal.app.chooser.DisplayResolveInfo;
import com.android.internal.app.chooser.MultiDisplayResolveInfo;

/**
 * Shows individual actions for a "stacked" app target - such as an app with multiple posting
 * streams represented in the Sharesheet.
 */
public class ChooserStackedAppDialogFragment extends DialogFragment
public class ChooserStackedAppDialogFragment extends ChooserTargetActionsDialogFragment
        implements DialogInterface.OnClickListener {
    private static final String TITLE_KEY = "title";
    private static final String PINNED_KEY = "pinned";

    private MultiDisplayResolveInfo mTargetInfos;
    private CharSequence[] mLabels;
    private MultiDisplayResolveInfo mMultiDisplayResolveInfo;
    private int mParentWhich;

    public ChooserStackedAppDialogFragment() {
    }

    public ChooserStackedAppDialogFragment(CharSequence title,
            MultiDisplayResolveInfo targets, CharSequence[] labels, int parentWhich) {
        Bundle args = new Bundle();
        args.putCharSequence(TITLE_KEY, title);
        mTargetInfos = targets;
        mLabels = labels;
    public ChooserStackedAppDialogFragment(MultiDisplayResolveInfo targets,
            int parentWhich, UserHandle userHandle) {
        super(targets.getTargets(), userHandle);
        mMultiDisplayResolveInfo = targets;
        mParentWhich = parentWhich;
        setArguments(args);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final Bundle args = getArguments();
        return new Builder(getContext())
                .setCancelable(true)
                .setItems(mLabels, this)
                .setTitle(args.getCharSequence(TITLE_KEY))
                .create();
    protected CharSequence getItemLabel(DisplayResolveInfo dri) {
        final PackageManager pm = getContext().getPackageManager();
        return dri.getResolveInfo().loadLabel(pm);
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        final Bundle args = getArguments();
        mTargetInfos.setSelected(which);
        ((ChooserActivity) getActivity()).startSelected(mParentWhich, false, true);
        dismiss();
    protected Drawable getItemIcon(DisplayResolveInfo dri) {
        // Show no icon for the group disambig dialog, null hides the imageview
        return null;
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        // Dismiss on config changed (eg: rotation)
        // TODO: Maintain state on config change
        super.onConfigurationChanged(newConfig);
    public void onClick(DialogInterface dialog, int which) {
        mMultiDisplayResolveInfo.setSelected(which);
        ((ChooserActivity) getActivity()).startSelected(mParentWhich, false, true);
        dismiss();
    }
}
+173 −0
Original line number Diff line number Diff line
@@ -21,6 +21,10 @@ import static android.content.Context.ACTIVITY_SERVICE;

import static com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter;

import static java.util.stream.Collectors.toList;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
@@ -30,12 +34,18 @@ import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.android.internal.R;
import com.android.internal.app.chooser.DisplayResolveInfo;
import com.android.internal.app.chooser.TargetInfo;

import java.util.ArrayList;
import java.util.List;
@@ -43,16 +53,16 @@ import java.util.List;
/**
 * Shows a dialog with actions to take on a chooser target.
 */
public class ResolverTargetActionsDialogFragment extends DialogFragment
public class ChooserTargetActionsDialogFragment extends DialogFragment
        implements DialogInterface.OnClickListener {

    private List<DisplayResolveInfo> mTargetInfos = new ArrayList<>();
    private UserHandle mUserHandle;
    protected List<DisplayResolveInfo> mTargetInfos = new ArrayList<>();
    protected UserHandle mUserHandle;

    public ResolverTargetActionsDialogFragment() {
    public ChooserTargetActionsDialogFragment() {
    }

    public ResolverTargetActionsDialogFragment(List<DisplayResolveInfo> targets,
    public ChooserTargetActionsDialogFragment(List<DisplayResolveInfo> targets,
            UserHandle userHandle) {
        mUserHandle = userHandle;
        mTargetInfos = targets;
@@ -60,34 +70,47 @@ public class ResolverTargetActionsDialogFragment extends DialogFragment

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final Bundle args = getArguments();
        final PackageManager pm = getContext().getPackageManager();

        // Pin item for each sub-item
        CharSequence[] items = new CharSequence[mTargetInfos.size()];
        for (int i = 0; i < mTargetInfos.size(); i++) {
            final TargetInfo ti = mTargetInfos.get(i);
            final CharSequence label = ti.getResolveInfo().loadLabel(pm);
            items[i] = ti.isPinned()
                     ? getResources().getString(R.string.unpin_specific_target, label)
                     : getResources().getString(R.string.pin_specific_target, label);
        }

        // Use the matching application icon and label for the title, any TargetInfo will do
        final ActivityManager am = (ActivityManager) getContext()
                .getSystemService(ACTIVITY_SERVICE);
        final int iconDpi = am.getLauncherLargeIconDensity();
        final ResolveInfoPresentationGetter pg = new ResolveInfoPresentationGetter(getContext(),
                iconDpi, mTargetInfos.get(0).getResolveInfo());
        // Fetch UI details from target info
        List<Pair<CharSequence, Drawable>> items = mTargetInfos.stream().map(dri -> {
            return new Pair<>(getItemLabel(dri), getItemIcon(dri));
        }).collect(toList());

        final ResolveInfoPresentationGetter pg = getProvidingAppPresentationGetter();
        return new Builder(getContext())
                .setTitle(pg.getLabel())
                .setIcon(pg.getIcon(mUserHandle))
                .setCancelable(true)
                .setItems(items, this)
                .setAdapter(getAdapterForContent(items), this)
                .create();
    }

    protected ArrayAdapter<Pair<CharSequence, Drawable>> getAdapterForContent(
            List<Pair<CharSequence, Drawable>> items) {
        return new ArrayAdapter<Pair<CharSequence, Drawable>>(getContext(),
                R.layout.chooser_dialog_item, R.id.text, items) {
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View v =  super.getView(position, convertView, parent); // super recycles views
                TextView label = v.findViewById(R.id.text);
                ImageView icon = v.findViewById(R.id.icon);

                Pair<CharSequence, Drawable> pair = getItem(position);
                label.setText(pair.first);

                // Hide icon view if one isn't available
                if (pair.second == null) {
                    icon.setVisibility(View.GONE);
                } else {
                    icon.setImageDrawable(pair.second);
                    icon.setVisibility(View.VISIBLE);
                }

                return v;
            }
        };
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        pinComponent(mTargetInfos.get(which).getResolvedComponentName());
@@ -106,6 +129,39 @@ public class ResolverTargetActionsDialogFragment extends DialogFragment
        }
    }

    private Drawable getPinIcon(boolean isPinned) {
        return isPinned
                ? getContext().getDrawable(R.drawable.ic_close)
                : getContext().getDrawable(R.drawable.ic_chooser_pin_dialog);
    }

    private CharSequence getPinLabel(boolean isPinned, CharSequence targetLabel) {
        return isPinned
                ? getResources().getString(R.string.unpin_specific_target, targetLabel)
                : getResources().getString(R.string.pin_specific_target, targetLabel);
    }

    @NonNull
    protected CharSequence getItemLabel(DisplayResolveInfo dri) {
        final PackageManager pm = getContext().getPackageManager();
        return getPinLabel(dri.isPinned(), dri.getResolveInfo().loadLabel(pm));
    }

    @Nullable
    protected Drawable getItemIcon(DisplayResolveInfo dri) {
        return getPinIcon(dri.isPinned());
    }

    private ResolveInfoPresentationGetter getProvidingAppPresentationGetter() {
        final ActivityManager am = (ActivityManager) getContext()
                .getSystemService(ACTIVITY_SERVICE);
        final int iconDpi = am.getLauncherLargeIconDensity();

        // Use the matching application icon and label for the title, any TargetInfo will do
        return new ResolveInfoPresentationGetter(getContext(), iconDpi,
                mTargetInfos.get(0).getResolveInfo());
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        // Dismiss on config changed (eg: rotation)
+25 −0
Original line number Diff line number Diff line
<!--
  ~ Copyright (C) 2020 The Android Open Source Project
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24"
        android:viewportHeight="24">
    <path
        android:pathData="M14,4v5c0,1.12 0.37,2.16 1,3H9c0.65,-0.86 1,-1.9 1,-3V4H14M17,2H7C6.45,2 6,2.45 6,3c0,0.55 0.45,1 1,1c0,0 0,0 0,0l1,0v5c0,1.66 -1.34,3 -3,3v2h5.97v7l1,1l1,-1v-7H19v-2c0,0 0,0 0,0c-1.66,0 -3,-1.34 -3,-3V4l1,0c0,0 0,0 0,0c0.55,0 1,-0.45 1,-1C18,2.45 17.55,2 17,2L17,2z"
        android:fillColor="#FF000000"/>
</vector>
+44 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2020 The Android Open Source Project
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="horizontal"
              android:gravity="start|center_vertical"
              android:paddingStart="?attr/dialogPreferredPadding"
              android:paddingEnd="?attr/dialogPreferredPadding"
              android:minHeight="48dp"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <!-- Icon and text aligns with aligns with alert_dialog_title_material -->
    <ImageView android:id="@+id/icon"
               android:tint="?android:attr/textColorAlertDialogListItem"
               android:padding="4dp"
               android:layout_marginEnd="8dp"
               android:layout_width="32dp"
               android:layout_height="32dp"/>

    <!-- Using text style from select_dialog_item_material -->
    <TextView android:id="@+id/text"
              android:textAppearance="?android:attr/textAppearanceListItemSmall"
              android:textColor="?android:attr/textColorAlertDialogListItem"
              android:lines="1"
              android:ellipsize="end"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"/>

</LinearLayout>
 No newline at end of file
Loading