diff options
author | 2023-05-24 20:59:33 +0000 | |
---|---|---|
committer | 2023-05-24 20:59:33 +0000 | |
commit | 2e2f02464ec29fab8d3d71088aa2c252e8c27465 (patch) | |
tree | 761e01f7a916fc53aecb7b8fbb35c3e21b5e7528 /java | |
parent | c60ca38567d795f011d9263b07c6147d1245795c (diff) | |
parent | 1f7a7a6a43cfd0f8a7d30a75a0c729879223b8f4 (diff) |
Merge "Move copy and edit actions into preview space." into udc-dev am: bc22d1898d am: 1f7a7a6a43
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/IntentResolver/+/23376460
Change-Id: If9708f3afe72a187aee5cafebe2bbbbb7751f80b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
Diffstat (limited to 'java')
15 files changed, 221 insertions, 269 deletions
diff --git a/java/res/drawable/edit_action_background.xml b/java/res/drawable/edit_action_background.xml new file mode 100644 index 00000000..91726f49 --- /dev/null +++ b/java/res/drawable/edit_action_background.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 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 + --> +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:color="?android:attr/colorControlHighlight" + > + <item> + <inset android:inset="8dp"> + <shape android:shape="rectangle"> + <corners android:radius="12dp" /> + <solid android:color="?androidprv:attr/materialColorSecondaryFixed"/> + </shape> + </inset> + </item> +</ripple> diff --git a/java/res/layout-h480dp/image_preview_image_item.xml b/java/res/layout-h480dp/image_preview_image_item.xml index db44c8be..ac63b2d5 100644 --- a/java/res/layout-h480dp/image_preview_image_item.xml +++ b/java/res/layout-h480dp/image_preview_image_item.xml @@ -17,6 +17,7 @@ <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:layout_width="wrap_content" android:layout_height="@dimen/chooser_preview_image_height_tall"> @@ -52,4 +53,25 @@ android:tint="@android:color/white" android:layout_gravity="top|end" /> </FrameLayout> + + <FrameLayout + android:id="@+id/edit" + android:layout_width="48dp" + android:layout_height="48dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + android:background="@drawable/edit_action_background" + android:drawableTint="?androidprv:attr/materialColorSecondaryFixed" + android:contentDescription="@string/screenshot_edit" + android:visibility="gone" + > + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:padding="4dp" + android:tint="?androidprv:attr/materialColorOnSecondaryFixed" + android:src="@androidprv:drawable/ic_screenshot_edit" + /> + </FrameLayout> </androidx.constraintlayout.widget.ConstraintLayout> diff --git a/java/res/layout/chooser_grid_preview_text.xml b/java/res/layout/chooser_grid_preview_text.xml index 44163b49..96496a30 100644 --- a/java/res/layout/chooser_grid_preview_text.xml +++ b/java/res/layout/chooser_grid_preview_text.xml @@ -29,7 +29,7 @@ <include layout="@layout/chooser_headline_row" /> - <RelativeLayout + <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" @@ -44,9 +44,9 @@ android:id="@androidprv:id/content_preview_thumbnail" android:layout_width="@dimen/width_text_image_preview_size" android:layout_height="@dimen/width_text_image_preview_size" - android:layout_alignParentStart="true" - android:layout_centerVertical="true" - android:layout_marginEnd="@dimen/chooser_edge_margin_normal_half" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" android:adjustViewBounds="true" android:gravity="center" app:radius="@dimen/chooser_corner_radius_small" @@ -54,11 +54,15 @@ <TextView android:id="@androidprv:id/content_preview_title" - android:layout_width="wrap_content" + android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_toEndOf="@androidprv:id/content_preview_thumbnail" - android:layout_alignParentTop="true" - android:layout_alignWithParentIfMissing="true" + app:layout_constraintStart_toEndOf="@androidprv:id/content_preview_thumbnail" + app:layout_constraintEnd_toStartOf="@id/copy" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@androidprv:id/content_preview_text" + android:layout_marginStart="@dimen/chooser_edge_margin_normal_half" + app:layout_goneMarginStart="0dp" + app:layout_constraintVertical_chainStyle="packed" android:ellipsize="end" android:maxLines="1" android:textAlignment="gravity" @@ -69,11 +73,14 @@ <TextView android:id="@androidprv:id/content_preview_text" - android:layout_width="match_parent" + android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_toEndOf="@androidprv:id/content_preview_thumbnail" - android:layout_below="@androidprv:id/content_preview_title" - android:layout_alignWithParentIfMissing="true" + app:layout_constraintStart_toEndOf="@androidprv:id/content_preview_thumbnail" + app:layout_constraintEnd_toStartOf="@id/copy" + app:layout_constraintTop_toBottomOf="@androidprv:id/content_preview_title" + app:layout_constraintBottom_toBottomOf="parent" + android:layout_marginStart="@dimen/chooser_edge_margin_normal_half" + app:layout_goneMarginStart="0dp" android:ellipsize="end" android:fontFamily="@androidprv:string/config_headlineFontFamily" android:textColor="?androidprv:attr/materialColorOnSurfaceVariant" @@ -81,7 +88,28 @@ android:textDirection="locale" android:maxLines="@integer/text_preview_lines" android:focusable="true"/> - </RelativeLayout> + + <FrameLayout + android:id="@+id/copy" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:layout_constraintStart_toEndOf="@androidprv:id/content_preview_text" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="1" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + android:layout_margin="8dp" + android:padding="8dp" + android:contentDescription="@android:string/copy" + > + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:tint="?androidprv:attr/materialColorOnSurfaceVariant" + android:src="@androidprv:drawable/ic_menu_copy_material" + /> + </FrameLayout> + </androidx.constraintlayout.widget.ConstraintLayout> <include layout="@layout/chooser_action_row" /> diff --git a/java/src/com/android/intentresolver/ChooserActionFactory.java b/java/src/com/android/intentresolver/ChooserActionFactory.java index f355d9d4..6ec62753 100644 --- a/java/src/com/android/intentresolver/ChooserActionFactory.java +++ b/java/src/com/android/intentresolver/ChooserActionFactory.java @@ -84,11 +84,8 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio private static final String IMAGE_EDITOR_SHARED_ELEMENT = "screenshot_preview_image"; private final Context mContext; - private final String mCopyButtonLabel; - private final Drawable mCopyButtonDrawable; - private final Runnable mOnCopyButtonClicked; - private final TargetInfo mEditSharingTarget; - private final Runnable mOnEditButtonClicked; + private final Runnable mCopyButtonRunnable; + private final Runnable mEditButtonRunnable; private final ImmutableList<ChooserAction> mCustomActions; private final @Nullable ChooserAction mModifyShareAction; private final Consumer<Boolean> mExcludeSharedTextAction; @@ -119,19 +116,13 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio Consumer</* @Nullable */ Integer> finishCallback) { this( context, - context.getString(com.android.internal.R.string.copy), - context.getDrawable(com.android.internal.R.drawable.ic_menu_copy_material), - makeOnCopyRunnable( + makeCopyButtonRunnable( context, chooserRequest.getTargetIntent(), chooserRequest.getReferrerPackageName(), finishCallback, logger), - getEditSharingTarget( - context, - chooserRequest.getTargetIntent(), - integratedDeviceComponents), - makeOnEditRunnable( + makeEditButtonRunnable( getEditSharingTarget( context, chooserRequest.getTargetIntent(), @@ -149,22 +140,16 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio @VisibleForTesting ChooserActionFactory( Context context, - String copyButtonLabel, - Drawable copyButtonDrawable, - Runnable onCopyButtonClicked, - TargetInfo editSharingTarget, - Runnable onEditButtonClicked, + Runnable copyButtonRunnable, + Runnable editButtonRunnable, List<ChooserAction> customActions, @Nullable ChooserAction modifyShareAction, Consumer<Boolean> onUpdateSharedTextIsExcluded, ChooserActivityLogger logger, Consumer</* @Nullable */ Integer> finishCallback) { mContext = context; - mCopyButtonLabel = copyButtonLabel; - mCopyButtonDrawable = copyButtonDrawable; - mOnCopyButtonClicked = onCopyButtonClicked; - mEditSharingTarget = editSharingTarget; - mOnEditButtonClicked = onEditButtonClicked; + mCopyButtonRunnable = copyButtonRunnable; + mEditButtonRunnable = editButtonRunnable; mCustomActions = ImmutableList.copyOf(customActions); mModifyShareAction = modifyShareAction; mExcludeSharedTextAction = onUpdateSharedTextIsExcluded; @@ -172,29 +157,16 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio mFinishCallback = finishCallback; } - /** Create an action that copies the share content to the clipboard. */ @Override - public ActionRow.Action createCopyButton() { - return new ActionRow.Action( - com.android.internal.R.id.chooser_copy_button, - mCopyButtonLabel, - mCopyButtonDrawable, - mOnCopyButtonClicked); + @Nullable + public Runnable getEditButtonRunnable() { + return mEditButtonRunnable; } - /** Create an action that opens the share content in a system-default editor. */ @Override @Nullable - public ActionRow.Action createEditButton() { - if (mEditSharingTarget == null) { - return null; - } - - return new ActionRow.Action( - com.android.internal.R.id.chooser_edit_button, - mEditSharingTarget.getDisplayLabel(), - mEditSharingTarget.getDisplayIconHolder().getDisplayIcon(), - mOnEditButtonClicked); + public Runnable getCopyButtonRunnable() { + return mCopyButtonRunnable; } /** Create custom actions */ @@ -247,7 +219,7 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio return mExcludeSharedTextAction; } - private static Runnable makeOnCopyRunnable( + private static Runnable makeCopyButtonRunnable( Context context, Intent targetIntent, String referrerPackageName, @@ -344,7 +316,7 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio return dri; } - private static Runnable makeOnEditRunnable( + private static Runnable makeEditButtonRunnable( TargetInfo editSharingTarget, Callable</* @Nullable */ View> firstVisibleImageQuery, ActionActivityStarter activityStarter, diff --git a/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java index 9100b392..e8367c4e 100644 --- a/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java @@ -53,12 +53,17 @@ public final class ChooserContentPreviewUi { * TODO: clarify why action buttons are part of preview logic. */ public interface ActionFactory { - /** Create an action that copies the share content to the clipboard. */ - ActionRow.Action createCopyButton(); + /** + * @return Runnable to be run when an edit button is clicked (if available). + */ + @Nullable + Runnable getEditButtonRunnable(); - /** Create an action that opens the share content in a system-default editor. */ + /** + * @return Runnable to be run when a copy button is clicked (if available). + */ @Nullable - ActionRow.Action createEditButton(); + Runnable getCopyButtonRunnable(); /** Create custom actions */ List<ActionRow.Action> createCustomActions(); diff --git a/java/src/com/android/intentresolver/contentpreview/ContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/ContentPreviewUi.java index 9699594e..07071236 100644 --- a/java/src/com/android/intentresolver/contentpreview/ContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/ContentPreviewUi.java @@ -32,9 +32,6 @@ import com.android.intentresolver.R; import com.android.intentresolver.widget.ActionRow; import com.android.intentresolver.widget.ScrollableImagePreviewView; -import java.util.ArrayList; -import java.util.List; - abstract class ContentPreviewUi { private static final int IMAGE_FADE_IN_MILLIS = 150; static final String TAG = "ChooserPreview"; @@ -45,19 +42,6 @@ abstract class ContentPreviewUi { public abstract ViewGroup display( Resources resources, LayoutInflater layoutInflater, ViewGroup parent); - protected static List<ActionRow.Action> createActions( - List<ActionRow.Action> systemActions, - List<ActionRow.Action> customActions) { - ArrayList<ActionRow.Action> actions = - new ArrayList<>(systemActions.size() + customActions.size()); - if (customActions.isEmpty()) { - actions.addAll(systemActions); - } else { - actions.addAll(customActions); - } - return actions; - } - protected static void updateViewWithImage(ImageView imageView, Bitmap image) { if (image == null) { imageView.setVisibility(View.GONE); diff --git a/java/src/com/android/intentresolver/contentpreview/FileContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/FileContentPreviewUi.java index 16ff6c23..8d3e62aa 100644 --- a/java/src/com/android/intentresolver/contentpreview/FileContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/FileContentPreviewUi.java @@ -30,7 +30,6 @@ import androidx.annotation.Nullable; import com.android.intentresolver.R; import com.android.intentresolver.widget.ActionRow; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -108,8 +107,7 @@ class FileContentPreviewUi extends ContentPreviewUi { final ActionRow actionRow = mContentPreview.findViewById(com.android.internal.R.id.chooser_action_row); - List<ActionRow.Action> actions = - createActions(new ArrayList<>(), mActionFactory.createCustomActions()); + List<ActionRow.Action> actions = mActionFactory.createCustomActions(); actionRow.setActions(actions); if (actions.isEmpty()) { mContentPreview.findViewById(R.id.actions_top_divider).setVisibility(View.GONE); diff --git a/java/src/com/android/intentresolver/contentpreview/FilesPlusTextContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/FilesPlusTextContentPreviewUi.java index e4e33839..61ca44e0 100644 --- a/java/src/com/android/intentresolver/contentpreview/FilesPlusTextContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/FilesPlusTextContentPreviewUi.java @@ -37,7 +37,6 @@ import com.android.intentresolver.R; import com.android.intentresolver.widget.ActionRow; import com.android.intentresolver.widget.ScrollableImagePreviewView; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.function.Consumer; @@ -123,9 +122,7 @@ class FilesPlusTextContentPreviewUi extends ContentPreviewUi { final ActionRow actionRow = mContentPreviewView.findViewById(com.android.internal.R.id.chooser_action_row); - List<ActionRow.Action> actions = createActions( - createImagePreviewActions(), - mActionFactory.createCustomActions()); + List<ActionRow.Action> actions = mActionFactory.createCustomActions(); actionRow.setActions(actions); if (actions.isEmpty()) { @@ -141,18 +138,6 @@ class FilesPlusTextContentPreviewUi extends ContentPreviewUi { return mContentPreviewView; } - private List<ActionRow.Action> createImagePreviewActions() { - ArrayList<ActionRow.Action> actions = new ArrayList<>(2); - //TODO: add copy action; - if (mIsSingleImage) { - ActionRow.Action action = mActionFactory.createEditButton(); - if (action != null) { - actions.add(action); - } - } - return actions; - } - private void updateUiWithMetadata(ViewGroup contentPreviewView) { prepareTextPreview(contentPreviewView, mActionFactory); updateHeadline(contentPreviewView); diff --git a/java/src/com/android/intentresolver/contentpreview/TextContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/TextContentPreviewUi.java index 19fd3bb4..c38ed03a 100644 --- a/java/src/com/android/intentresolver/contentpreview/TextContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/TextContentPreviewUi.java @@ -33,9 +33,6 @@ import androidx.lifecycle.Lifecycle; import com.android.intentresolver.R; import com.android.intentresolver.widget.ActionRow; -import java.util.ArrayList; -import java.util.List; - class TextContentPreviewUi extends ContentPreviewUi { private final Lifecycle mLifecycle; @Nullable @@ -85,10 +82,7 @@ class TextContentPreviewUi extends ContentPreviewUi { final ActionRow actionRow = contentPreviewLayout.findViewById(com.android.internal.R.id.chooser_action_row); - actionRow.setActions( - createActions( - createTextPreviewActions(), - mActionFactory.createCustomActions())); + actionRow.setActions(mActionFactory.createCustomActions()); if (mSharingText == null) { contentPreviewLayout @@ -129,14 +123,16 @@ class TextContentPreviewUi extends ContentPreviewUi { bitmap)); } + Runnable onCopy = mActionFactory.getCopyButtonRunnable(); + View copyButton = contentPreviewLayout.findViewById(R.id.copy); + if (onCopy != null) { + copyButton.setOnClickListener((v) -> onCopy.run()); + } else { + copyButton.setVisibility(View.GONE); + } + displayHeadline(contentPreviewLayout, mHeadlineGenerator.getTextHeadline(mSharingText)); return contentPreviewLayout; } - - private List<ActionRow.Action> createTextPreviewActions() { - ArrayList<ActionRow.Action> actions = new ArrayList<>(2); - actions.add(mActionFactory.createCopyButton()); - return actions; - } } diff --git a/java/src/com/android/intentresolver/contentpreview/UnifiedContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/UnifiedContentPreviewUi.java index 26f4d007..eb3e8e72 100644 --- a/java/src/com/android/intentresolver/contentpreview/UnifiedContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/UnifiedContentPreviewUi.java @@ -91,9 +91,7 @@ class UnifiedContentPreviewUi extends ContentPreviewUi { final ActionRow actionRow = mContentPreviewView.findViewById(com.android.internal.R.id.chooser_action_row); - List<ActionRow.Action> actions = createActions( - createImagePreviewActions(), - mActionFactory.createCustomActions()); + List<ActionRow.Action> actions = mActionFactory.createCustomActions(); actionRow.setActions(actions); if (actions.isEmpty()) { mContentPreviewView.findViewById(R.id.actions_top_divider).setVisibility(View.GONE); @@ -135,9 +133,11 @@ class UnifiedContentPreviewUi extends ContentPreviewUi { allVideos = allVideos && previewType == ScrollableImagePreviewView.PreviewType.Video; if (fileInfo.getPreviewUri() != null) { + Runnable editAction = + mShowEditAction ? mActionFactory.getEditButtonRunnable() : null; previews.add( new ScrollableImagePreviewView.Preview( - previewType, fileInfo.getPreviewUri())); + previewType, fileInfo.getPreviewUri(), editAction)); } } @@ -151,16 +151,4 @@ class UnifiedContentPreviewUi extends ContentPreviewUi { displayHeadline(contentPreviewView, mHeadlineGenerator.getFilesHeadline(count)); } } - - private List<ActionRow.Action> createImagePreviewActions() { - ArrayList<ActionRow.Action> actions = new ArrayList<>(1); - //TODO: add copy action; - if (mShowEditAction) { - ActionRow.Action action = mActionFactory.createEditButton(); - if (action != null) { - actions.add(action); - } - } - return actions; - } } diff --git a/java/src/com/android/intentresolver/widget/ScrollableImagePreviewView.kt b/java/src/com/android/intentresolver/widget/ScrollableImagePreviewView.kt index e761c0aa..9c948bd9 100644 --- a/java/src/com/android/intentresolver/widget/ScrollableImagePreviewView.kt +++ b/java/src/com/android/intentresolver/widget/ScrollableImagePreviewView.kt @@ -237,9 +237,14 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { internal constructor( val type: PreviewType, val uri: Uri, + val editAction: Runnable?, internal var aspectRatioString: String ) { - constructor(type: PreviewType, uri: Uri) : this(type, uri, "1:1") + constructor( + type: PreviewType, + uri: Uri, + editAction: Runnable? + ) : this(type, uri, editAction, "1:1") } enum class PreviewType { @@ -370,6 +375,7 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { val image = view.requireViewById<ImageView>(R.id.image) private val badgeFrame = view.requireViewById<View>(R.id.badge_frame) private val badge = view.requireViewById<ImageView>(R.id.badge) + private val editActionContainer = view.findViewById<View?>(R.id.edit) private var scope: CoroutineScope? = null fun bind( @@ -404,6 +410,12 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { badgeFrame.visibility = View.VISIBLE } } + preview.editAction?.also { onClick -> + editActionContainer?.apply { + setOnClickListener { onClick.run() } + visibility = View.VISIBLE + } + } resetScope().launch { loadImage(preview, imageLoader) if (preview.type == PreviewType.Image) { @@ -545,7 +557,8 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { bitmap.width, bitmap.height ) - } ?: 0 + } + ?: 0 } .getOrDefault(0) diff --git a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java index c2212bc2..99564ae3 100644 --- a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java +++ b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java @@ -868,8 +868,8 @@ public class UnbundledChooserActivityTest { mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); - onView(withId(com.android.internal.R.id.chooser_copy_button)).check(matches(isDisplayed())); - onView(withId(com.android.internal.R.id.chooser_copy_button)).perform(click()); + onView(withId(R.id.copy)).check(matches(isDisplayed())); + onView(withId(R.id.copy)).perform(click()); ClipboardManager clipboard = (ClipboardManager) activity.getSystemService( Context.CLIPBOARD_SERVICE); ClipData clipData = clipboard.getPrimaryClip(); @@ -892,8 +892,8 @@ public class UnbundledChooserActivityTest { mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); waitForIdle(); - onView(withId(com.android.internal.R.id.chooser_copy_button)).check(matches(isDisplayed())); - onView(withId(com.android.internal.R.id.chooser_copy_button)).perform(click()); + onView(withId(R.id.copy)).check(matches(isDisplayed())); + onView(withId(R.id.copy)).perform(click()); ChooserActivityLogger logger = activity.getChooserActivityLogger(); verify(logger, times(1)).logActionSelected(eq(ChooserActivityLogger.SELECTION_TYPE_COPY)); diff --git a/java/tests/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUiTest.kt b/java/tests/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUiTest.kt index c62f36ce..9bfd2052 100644 --- a/java/tests/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUiTest.kt +++ b/java/tests/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUiTest.kt @@ -51,8 +51,8 @@ class ChooserContentPreviewUiTest { } private val actionFactory = object : ActionFactory { - override fun createCopyButton() = ActionRow.Action(label = "Copy", icon = null) {} - override fun createEditButton(): ActionRow.Action? = null + override fun getCopyButtonRunnable(): Runnable? = null + override fun getEditButtonRunnable(): Runnable? = null override fun createCustomActions(): List<ActionRow.Action> = emptyList() override fun getModifyShareAction(): ActionRow.Action? = null override fun getExcludeSharedTextAction(): Consumer<Boolean> = Consumer<Boolean> {} @@ -103,12 +103,7 @@ class ChooserContentPreviewUiTest { whenever(previewData.previewType).thenReturn(ContentPreviewType.CONTENT_PREVIEW_IMAGE) whenever(previewData.uriCount).thenReturn(2) whenever(previewData.firstFileInfo) - .thenReturn( - FileInfo.Builder(uri) - .withPreviewUri(uri) - .withMimeType("image/png") - .build() - ) + .thenReturn(FileInfo.Builder(uri).withPreviewUri(uri).withMimeType("image/png").build()) val testSubject = ChooserContentPreviewUi( lifecycle, @@ -131,12 +126,7 @@ class ChooserContentPreviewUiTest { whenever(previewData.previewType).thenReturn(ContentPreviewType.CONTENT_PREVIEW_IMAGE) whenever(previewData.uriCount).thenReturn(2) whenever(previewData.firstFileInfo) - .thenReturn( - FileInfo.Builder(uri) - .withPreviewUri(uri) - .withMimeType("image/png") - .build() - ) + .thenReturn(FileInfo.Builder(uri).withPreviewUri(uri).withMimeType("image/png").build()) val testSubject = ChooserContentPreviewUi( lifecycle, diff --git a/java/tests/src/com/android/intentresolver/contentpreview/ContentPreviewUiTest.kt b/java/tests/src/com/android/intentresolver/contentpreview/ContentPreviewUiTest.kt index 6c30fc9e..6db53a9e 100644 --- a/java/tests/src/com/android/intentresolver/contentpreview/ContentPreviewUiTest.kt +++ b/java/tests/src/com/android/intentresolver/contentpreview/ContentPreviewUiTest.kt @@ -16,41 +16,18 @@ package com.android.intentresolver.contentpreview -import android.content.res.Resources -import android.view.LayoutInflater -import android.view.ViewGroup -import com.android.intentresolver.widget.ActionRow import com.android.intentresolver.widget.ScrollableImagePreviewView.PreviewType import com.google.common.truth.Truth.assertThat import org.junit.Test class ContentPreviewUiTest { - private class TestablePreview() : ContentPreviewUi() { - override fun getType() = 0 - - override fun display( - resources: Resources?, - layoutInflater: LayoutInflater?, - parent: ViewGroup? - ): ViewGroup { - throw IllegalStateException() - } - - // exposing for testing - fun makeActions( - system: List<ActionRow.Action>, - custom: List<ActionRow.Action> - ): List<ActionRow.Action> { - return createActions(system, custom) - } - } - @Test fun testPreviewTypes() { - val typeClassifier = object : MimeTypeClassifier { - override fun isImageType(type: String?) = (type == "image") - override fun isVideoType(type: String?) = (type == "video") - } + val typeClassifier = + object : MimeTypeClassifier { + override fun isImageType(type: String?) = (type == "image") + override fun isVideoType(type: String?) = (type == "video") + } assertThat(ContentPreviewUi.getPreviewType(typeClassifier, "image")) .isEqualTo(PreviewType.Image) @@ -61,15 +38,4 @@ class ContentPreviewUiTest { assertThat(ContentPreviewUi.getPreviewType(typeClassifier, null)) .isEqualTo(PreviewType.File) } - - @Test - fun testCreateActions() { - val preview = TestablePreview() - - val system = listOf(ActionRow.Action(label="system", icon=null) {}) - val custom = listOf(ActionRow.Action(label="custom", icon=null) {}) - - assertThat(preview.makeActions(system, custom)).isEqualTo(custom) - assertThat(preview.makeActions(system, listOf())).isEqualTo(system) - } } diff --git a/java/tests/src/com/android/intentresolver/widget/BatchPreviewLoaderTest.kt b/java/tests/src/com/android/intentresolver/widget/BatchPreviewLoaderTest.kt index c1d7451f..e65cba5f 100644 --- a/java/tests/src/com/android/intentresolver/widget/BatchPreviewLoaderTest.kt +++ b/java/tests/src/com/android/intentresolver/widget/BatchPreviewLoaderTest.kt @@ -18,29 +18,29 @@ package com.android.intentresolver.widget import android.graphics.Bitmap import android.net.Uri +import com.android.intentresolver.captureMany +import com.android.intentresolver.mock import com.android.intentresolver.widget.ScrollableImagePreviewView.BatchPreviewLoader import com.android.intentresolver.widget.ScrollableImagePreviewView.Preview import com.android.intentresolver.widget.ScrollableImagePreviewView.PreviewType +import com.android.intentresolver.withArgCaptor +import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.launch -import kotlinx.coroutines.cancel import kotlinx.coroutines.test.UnconfinedTestDispatcher -import org.junit.Test -import com.android.intentresolver.mock -import com.android.intentresolver.captureMany -import com.android.intentresolver.withArgCaptor -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.setMain import org.junit.After import org.junit.Before +import org.junit.Test import org.mockito.Mockito.atLeast import org.mockito.Mockito.times import org.mockito.Mockito.verify -import com.google.common.truth.Truth.assertThat @OptIn(ExperimentalCoroutinesApi::class) class BatchPreviewLoaderTest { @@ -67,22 +67,21 @@ class BatchPreviewLoaderTest { val uriOne = createUri(1) val uriTwo = createUri(2) imageLoader.setUriLoadingOrder(succeed(uriTwo), succeed(uriOne)) - val testSubject = BatchPreviewLoader( - imageLoader, - previews(uriOne, uriTwo), - 0, - onReset, - onUpdate, - onCompletion - ) + val testSubject = + BatchPreviewLoader( + imageLoader, + previews(uriOne, uriTwo), + 0, + onReset, + onUpdate, + onCompletion + ) testSubject.loadAspectRatios(200) { _, _, _ -> 100 } dispatcher.scheduler.advanceUntilIdle() verify(onCompletion, times(1)).invoke() verify(onReset, times(1)).invoke(2) - val list = withArgCaptor { - verify(onUpdate, times(1)).invoke(capture()) - }.map { it.uri } + val list = withArgCaptor { verify(onUpdate, times(1)).invoke(capture()) }.map { it.uri } assertThat(list).containsExactly(uriOne, uriTwo).inOrder() } @@ -93,22 +92,21 @@ class BatchPreviewLoaderTest { val uriTwo = createUri(2) val uriThree = createUri(3) imageLoader.setUriLoadingOrder(succeed(uriThree), fail(uriTwo), succeed(uriOne)) - val testSubject = BatchPreviewLoader( - imageLoader, - previews(uriOne, uriTwo, uriThree), - 0, - onReset, - onUpdate, - onCompletion - ) + val testSubject = + BatchPreviewLoader( + imageLoader, + previews(uriOne, uriTwo, uriThree), + 0, + onReset, + onUpdate, + onCompletion + ) testSubject.loadAspectRatios(200) { _, _, _ -> 100 } dispatcher.scheduler.advanceUntilIdle() verify(onCompletion, times(1)).invoke() verify(onReset, times(1)).invoke(3) - val list = withArgCaptor { - verify(onUpdate, times(1)).invoke(capture()) - }.map { it.uri } + val list = withArgCaptor { verify(onUpdate, times(1)).invoke(capture()) }.map { it.uri } assertThat(list).containsExactly(uriOne, uriThree).inOrder() } @@ -116,35 +114,28 @@ class BatchPreviewLoaderTest { fun test_imagesLoadedNotInOrder_updatedInOrder() { val imageLoader = TestImageLoader(testScope) val uris = Array(10) { createUri(it) } - val loadingOrder = Array(uris.size) { i -> - val uriIdx = when { - i % 2 == 1 -> i - 1 - i % 2 == 0 && i < uris.size - 1 -> i + 1 - else -> i + val loadingOrder = + Array(uris.size) { i -> + val uriIdx = + when { + i % 2 == 1 -> i - 1 + i % 2 == 0 && i < uris.size - 1 -> i + 1 + else -> i + } + succeed(uris[uriIdx]) } - succeed(uris[uriIdx]) - } imageLoader.setUriLoadingOrder(*loadingOrder) - val testSubject = BatchPreviewLoader( - imageLoader, - previews(*uris), - 0, - onReset, - onUpdate, - onCompletion - ) + val testSubject = + BatchPreviewLoader(imageLoader, previews(*uris), 0, onReset, onUpdate, onCompletion) testSubject.loadAspectRatios(200) { _, _, _ -> 100 } dispatcher.scheduler.advanceUntilIdle() verify(onCompletion, times(1)).invoke() verify(onReset, times(1)).invoke(uris.size) - val list = captureMany { - verify(onUpdate, atLeast(1)).invoke(capture()) - }.fold(ArrayList<Preview>()) { acc, update -> - acc.apply { - addAll(update) - } - }.map { it.uri } + val list = + captureMany { verify(onUpdate, atLeast(1)).invoke(capture()) } + .fold(ArrayList<Preview>()) { acc, update -> acc.apply { addAll(update) } } + .map { it.uri } assertThat(list).containsExactly(*uris).inOrder() } @@ -152,36 +143,29 @@ class BatchPreviewLoaderTest { fun test_imagesLoadedNotInOrderSomeFailed_updatedInOrder() { val imageLoader = TestImageLoader(testScope) val uris = Array(10) { createUri(it) } - val loadingOrder = Array(uris.size) { i -> - val uriIdx = when { - i % 2 == 1 -> i - 1 - i % 2 == 0 && i < uris.size - 1 -> i + 1 - else -> i + val loadingOrder = + Array(uris.size) { i -> + val uriIdx = + when { + i % 2 == 1 -> i - 1 + i % 2 == 0 && i < uris.size - 1 -> i + 1 + else -> i + } + if (uriIdx % 2 == 0) fail(uris[uriIdx]) else succeed(uris[uriIdx]) } - if (uriIdx % 2 == 0) fail(uris[uriIdx]) else succeed(uris[uriIdx]) - } val expectedUris = Array(uris.size / 2) { createUri(it * 2 + 1) } imageLoader.setUriLoadingOrder(*loadingOrder) - val testSubject = BatchPreviewLoader( - imageLoader, - previews(*uris), - 0, - onReset, - onUpdate, - onCompletion - ) + val testSubject = + BatchPreviewLoader(imageLoader, previews(*uris), 0, onReset, onUpdate, onCompletion) testSubject.loadAspectRatios(200) { _, _, _ -> 100 } dispatcher.scheduler.advanceUntilIdle() verify(onCompletion, times(1)).invoke() verify(onReset, times(1)).invoke(uris.size) - val list = captureMany { - verify(onUpdate, atLeast(1)).invoke(capture()) - }.fold(ArrayList<Preview>()) { acc, update -> - acc.apply { - addAll(update) - } - }.map { it.uri } + val list = + captureMany { verify(onUpdate, atLeast(1)).invoke(capture()) } + .fold(ArrayList<Preview>()) { acc, update -> acc.apply { addAll(update) } } + .map { it.uri } assertThat(list).containsExactly(*expectedUris).inOrder() } @@ -191,21 +175,15 @@ class BatchPreviewLoaderTest { private fun succeed(uri: Uri) = uri to true private fun previews(vararg uris: Uri) = uris.fold(ArrayList<Preview>(uris.size)) { acc, uri -> - acc.apply { - add(Preview(PreviewType.Image, uri)) - } + acc.apply { add(Preview(PreviewType.Image, uri, editAction = null)) } } } -private class TestImageLoader( - scope: CoroutineScope -) : suspend (Uri, Boolean) -> Bitmap? { +private class TestImageLoader(scope: CoroutineScope) : suspend (Uri, Boolean) -> Bitmap? { private val loadingOrder = ArrayDeque<Pair<Uri, Boolean>>() private val pendingRequests = LinkedHashMap<Uri, CompletableDeferred<Bitmap?>>() private val flow = MutableSharedFlow<Unit>(replay = 1) - private val bitmap by lazy { - Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888) - } + private val bitmap by lazy { Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888) } init { scope.launch { @@ -217,9 +195,7 @@ private class TestImageLoader( deferred.complete(if (isLoaded) bitmap else null) } if (loadingOrder.isEmpty()) { - pendingRequests.forEach { (uri, deferred) -> - deferred.complete(bitmap) - } + pendingRequests.forEach { (uri, deferred) -> deferred.complete(bitmap) } pendingRequests.clear() } } |