diff options
| author | 2023-04-11 17:21:22 +0000 | |
|---|---|---|
| committer | 2023-04-11 17:21:22 +0000 | |
| commit | 11b9cf84dc1c3a8bf1add401423e48cb44293a10 (patch) | |
| tree | 9820a39d7de64f4c17eca4bfd96c2155161ed31d /java | |
| parent | fc7ddd61dd62105dae67594517b9344afca163ff (diff) | |
| parent | 8ae8c4a3f25cc5c0da3196fa0a3f0f07dfe87066 (diff) | |
Merge "Hide thumbnail prview if no preview has loaded" into udc-dev
Diffstat (limited to 'java')
8 files changed, 145 insertions, 49 deletions
diff --git a/java/res/layout/chooser_grid_preview_image.xml b/java/res/layout/chooser_grid_preview_image.xml index 43f6f4d1..2cfab2a8 100644 --- a/java/res/layout/chooser_grid_preview_image.xml +++ b/java/res/layout/chooser_grid_preview_image.xml @@ -32,7 +32,9 @@ android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_horizontal" - android:layout_marginBottom="@dimen/chooser_view_spacing"> + android:layout_marginBottom="@dimen/chooser_view_spacing" + android:paddingStart="@dimen/chooser_edge_margin_normal_half" + android:paddingEnd="@dimen/chooser_edge_margin_normal_half"> <com.android.intentresolver.widget.ScrollableImagePreviewView android:id="@+id/scrollable_image_preview" @@ -42,7 +44,7 @@ android:layout_marginBottom="@dimen/chooser_view_spacing" android:background="?android:attr/colorBackground" app:itemInnerSpacing="3dp" - app:itemOuterSpacing="@dimen/chooser_edge_margin_normal" + app:itemOuterSpacing="@dimen/chooser_edge_margin_normal_half" app:maxWidthHint="@dimen/chooser_width" /> <TextView @@ -51,7 +53,8 @@ android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" - android:paddingEnd="@dimen/chooser_edge_margin_normal" + android:layout_marginStart="@dimen/chooser_edge_margin_normal_half" + android:layout_marginEnd="@dimen/chooser_edge_margin_normal_half" android:maxLines="6" android:ellipsize="end" android:linksClickable="false" diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml index 44fc3c38..8636f742 100644 --- a/java/res/values/dimens.xml +++ b/java/res/values/dimens.xml @@ -24,6 +24,7 @@ <dimen name="chooser_view_spacing">18dp</dimen> <dimen name="chooser_edge_margin_thin">8dp</dimen> <dimen name="chooser_edge_margin_normal">24dp</dimen> + <dimen name="chooser_edge_margin_normal_half">12dp</dimen> <dimen name="chooser_preview_image_font_size">20sp</dimen> <dimen name="chooser_preview_image_border">1dp</dimen> <dimen name="chooser_preview_image_width">120dp</dimen> diff --git a/java/src/com/android/intentresolver/contentpreview/UnifiedContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/UnifiedContentPreviewUi.java index 748f7421..2e6ecb0e 100644 --- a/java/src/com/android/intentresolver/contentpreview/UnifiedContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/UnifiedContentPreviewUi.java @@ -91,6 +91,7 @@ class UnifiedContentPreviewUi extends ContentPreviewUi { R.layout.chooser_grid_preview_image, parent, false); ScrollableImagePreviewView imagePreview = contentPreviewLayout.findViewById(R.id.scrollable_image_preview); + imagePreview.setOnNoPreviewCallback(() -> imagePreview.setVisibility(View.GONE)); final ActionRow actionRow = contentPreviewLayout.findViewById(com.android.internal.R.id.chooser_action_row); @@ -132,7 +133,7 @@ class UnifiedContentPreviewUi extends ContentPreviewUi { mImageLoader); if (!TextUtils.isEmpty(mText) && mFiles.size() == 1 && allImages) { - setTextInImagePreviewVisibility(contentPreviewLayout, mActionFactory); + setTextInImagePreviewVisibility(contentPreviewLayout, imagePreview, mActionFactory); updateTextWithImageHeadline(contentPreviewLayout); } else { if (allImages) { @@ -175,7 +176,9 @@ class UnifiedContentPreviewUi extends ContentPreviewUi { } private void setTextInImagePreviewVisibility( - ViewGroup contentPreview, ChooserContentPreviewUi.ActionFactory actionFactory) { + ViewGroup contentPreview, + ScrollableImagePreviewView imagePreview, + ChooserContentPreviewUi.ActionFactory actionFactory) { final TextView textView = contentPreview .requireViewById(com.android.internal.R.id.content_preview_text); CheckBox actionView = contentPreview @@ -194,8 +197,12 @@ class UnifiedContentPreviewUi extends ContentPreviewUi { shareTextAction.accept(false); actionView.setOnCheckedChangeListener((view, isChecked) -> { view.setText(actionLabels[isChecked ? 1 : 0]); - TransitionManager.beginDelayedTransition((ViewGroup) textView.getParent()); - textView.setVisibility(isChecked ? View.VISIBLE : View.GONE); + textView.setEnabled(isChecked); + if (imagePreview.getVisibility() == View.VISIBLE) { + // animate only only if we have preview + TransitionManager.beginDelayedTransition((ViewGroup) textView.getParent()); + textView.setVisibility(isChecked ? View.VISIBLE : View.GONE); + } shareTextAction.accept(!isChecked); updateTextWithImageHeadline(contentPreview); }); diff --git a/java/src/com/android/intentresolver/widget/ScrollableImagePreviewView.kt b/java/src/com/android/intentresolver/widget/ScrollableImagePreviewView.kt index d1b0f5b4..8dcaacb8 100644 --- a/java/src/com/android/intentresolver/widget/ScrollableImagePreviewView.kt +++ b/java/src/com/android/intentresolver/widget/ScrollableImagePreviewView.kt @@ -40,6 +40,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.MainScope import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.takeWhile import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch @@ -129,13 +130,18 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { imageLoader, previews, otherItemCount, - ).apply { + ) { + onNoPreviewCallback?.run() + } + .apply { if (isMeasured) { loadAspectRatios(getMaxWidth(), this@ScrollableImagePreviewView::calcPreviewWidth) } } } + var onNoPreviewCallback: Runnable? = null + private fun getMaxWidth(): Int = when { maxWidthHint > 0 -> maxWidthHint @@ -187,6 +193,7 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { private var totalItemCount: Int = 0 private val hasOtherItem get() = previews.size < totalItemCount + val hasPreviews: Boolean get() = previews.isNotEmpty() var transitionStatusElementCallback: TransitionElementStatusCallback? = null @@ -369,6 +376,7 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { private val imageLoader: ImageLoader, previews: List<Preview>, otherItemCount: Int, + private val onNoPreviewCallback: (() -> Unit) ) { private val pendingPreviews = ArrayDeque<Preview>(previews) private val totalItemCount = previews.size + otherItemCount @@ -393,6 +401,11 @@ class ScrollableImagePreviewView : RecyclerView, ImagePreviewView { reportFlow .takeWhile { it !== completedEvent } .throttle(ADAPTER_UPDATE_INTERVAL_MS) + .onCompletion { cause -> + if (cause == null && !adapter.hasPreviews) { + onNoPreviewCallback() + } + } .collect { if (isFirstUpdate) { isFirstUpdate = false diff --git a/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java b/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java index f9093b8f..2a4d654a 100644 --- a/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java +++ b/java/tests/src/com/android/intentresolver/ChooserActivityOverrideData.java @@ -24,7 +24,6 @@ import static org.mockito.Mockito.when; import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.Cursor; -import android.graphics.Bitmap; import android.os.UserHandle; import com.android.intentresolver.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker; @@ -64,7 +63,7 @@ public class ChooserActivityOverrideData { public boolean isImageType; public Cursor resolverCursor; public boolean resolverForceException; - public Bitmap previewThumbnail; + public ImageLoader imageLoader; public ChooserActivityLogger chooserActivityLogger; public int alternateProfileSetting; public Resources resources; @@ -83,7 +82,7 @@ public class ChooserActivityOverrideData { onSafelyStartInternalCallback = null; isVoiceInteraction = null; createPackageManager = null; - previewThumbnail = null; + imageLoader = null; isImageType = false; resolverCursor = null; resolverForceException = false; diff --git a/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java b/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java index 8886892f..dc9baade 100644 --- a/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java +++ b/java/tests/src/com/android/intentresolver/ChooserWrapperActivity.java @@ -194,9 +194,9 @@ public class ChooserWrapperActivity @Override protected ImageLoader createPreviewImageLoader() { - return new TestPreviewImageLoader( - super.createPreviewImageLoader(), - () -> sOverrides.previewThumbnail); + return sOverrides.imageLoader == null + ? super.createPreviewImageLoader() + : sOverrides.imageLoader; } @Override diff --git a/java/tests/src/com/android/intentresolver/TestPreviewImageLoader.kt b/java/tests/src/com/android/intentresolver/TestPreviewImageLoader.kt index cfe041dd..2f240d58 100644 --- a/java/tests/src/com/android/intentresolver/TestPreviewImageLoader.kt +++ b/java/tests/src/com/android/intentresolver/TestPreviewImageLoader.kt @@ -21,18 +21,12 @@ import android.net.Uri import java.util.function.Consumer internal class TestPreviewImageLoader( - private val imageLoader: ImageLoader, - private val imageOverride: () -> Bitmap? + private val bitmaps: Map<Uri, Bitmap> ) : ImageLoader { override fun loadImage(uri: Uri, callback: Consumer<Bitmap?>) { - val override = imageOverride() - if (override != null) { - callback.accept(override) - } else { - imageLoader.loadImage(uri, callback) - } + callback.accept(bitmaps[uri]) } - override suspend fun invoke(uri: Uri): Bitmap? = imageOverride() ?: imageLoader(uri) + override suspend fun invoke(uri: Uri): Bitmap? = bitmaps[uri] override fun prePopulate(uris: List<Uri>) = Unit } diff --git a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java index 39357a4d..0a60b8c7 100644 --- a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java +++ b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java @@ -26,6 +26,7 @@ import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.hasSibling; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.isEnabled; import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; @@ -125,6 +126,7 @@ import org.mockito.Mockito; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -422,10 +424,12 @@ public class UnbundledChooserActivityTest { @Test public void visiblePreviewTitleAndThumbnail() throws InterruptedException { String previewTitle = "My Content Preview Title"; - Intent sendIntent = createSendTextIntentWithPreview(previewTitle, - Uri.parse("android.resource://com.android.frameworks.coretests/" - + R.drawable.test320x240)); - ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + Uri uri = Uri.parse( + "android.resource://com.android.frameworks.coretests/" + + R.drawable.test320x240); + Intent sendIntent = createSendTextIntentWithPreview(previewTitle, uri); + ChooserActivityOverrideData.getInstance().imageLoader = + createImageLoader(uri, createBitmap()); List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); setupResolverControllers(resolvedComponentInfos); @@ -688,10 +692,12 @@ public class UnbundledChooserActivityTest { @Test public void testImagePlusTextSharing_ExcludeText() { - Intent sendIntent = createSendImageIntent( - Uri.parse("android.resource://com.android.frameworks.coretests/" - + R.drawable.test320x240)); - ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + Uri uri = Uri.parse( + "android.resource://com.android.frameworks.coretests/" + + R.drawable.test320x240); + Intent sendIntent = createSendImageIntent(uri); + ChooserActivityOverrideData.getInstance().imageLoader = + createImageLoader(uri, createBitmap()); ChooserActivityOverrideData.getInstance().isImageType = true; sendIntent.putExtra(Intent.EXTRA_TEXT, "https://google.com/search?q=google"); @@ -728,10 +734,12 @@ public class UnbundledChooserActivityTest { @Test public void testImagePlusTextSharing_RemoveAndAddBackText() { - Intent sendIntent = createSendImageIntent( - Uri.parse("android.resource://com.android.frameworks.coretests/" - + R.drawable.test320x240)); - ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + Uri uri = Uri.parse( + "android.resource://com.android.frameworks.coretests/" + + R.drawable.test320x240); + Intent sendIntent = createSendImageIntent(uri); + ChooserActivityOverrideData.getInstance().imageLoader = + createImageLoader(uri, createBitmap()); ChooserActivityOverrideData.getInstance().isImageType = true; final String text = "https://google.com/search?q=google"; sendIntent.putExtra(Intent.EXTRA_TEXT, text); @@ -772,10 +780,12 @@ public class UnbundledChooserActivityTest { @Test public void testImagePlusTextSharing_TextExclusionDoesNotAffectAlternativeIntent() { - Intent sendIntent = createSendImageIntent( - Uri.parse("android.resource://com.android.frameworks.coretests/" - + R.drawable.test320x240)); - ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + Uri uri = Uri.parse( + "android.resource://com.android.frameworks.coretests/" + + R.drawable.test320x240); + Intent sendIntent = createSendImageIntent(uri); + ChooserActivityOverrideData.getInstance().imageLoader = + createImageLoader(uri, createBitmap()); ChooserActivityOverrideData.getInstance().isImageType = true; sendIntent.putExtra(Intent.EXTRA_TEXT, "https://google.com/search?q=google"); @@ -815,6 +825,42 @@ public class UnbundledChooserActivityTest { } @Test + public void testImagePlusTextSharing_failedThumbnailAndExcludedText_textRemainsVisible() { + Uri uri = Uri.parse( + "android.resource://com.android.frameworks.coretests/" + + R.drawable.test320x240); + Intent sendIntent = createSendImageIntent(uri); + ChooserActivityOverrideData.getInstance().imageLoader = + new TestPreviewImageLoader(Collections.emptyMap()); + ChooserActivityOverrideData.getInstance().isImageType = true; + sendIntent.putExtra(Intent.EXTRA_TEXT, "https://google.com/search?q=google"); + + List<ResolvedComponentInfo> resolvedComponentInfos = Arrays.asList( + ResolverDataProvider.createResolvedComponentInfo( + new ComponentName("org.imageviewer", "ImageTarget"), + sendIntent, PERSONAL_USER_HANDLE), + ResolverDataProvider.createResolvedComponentInfo( + new ComponentName("org.textviewer", "UriTarget"), + new Intent("VIEW_TEXT"), PERSONAL_USER_HANDLE) + ); + + setupResolverControllers(resolvedComponentInfos); + + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + waitForIdle(); + + onView(withId(R.id.include_text_action)) + .check(matches(isDisplayed())) + .perform(click()); + waitForIdle(); + + onView(withId(R.id.scrollable_image_preview)) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + onView(withId(com.android.internal.R.id.content_preview_text)) + .check(matches(allOf(isDisplayed(), not(isEnabled())))); + } + + @Test public void copyTextToClipboard() throws Exception { Intent sendIntent = createSendTextIntent(); List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); @@ -879,11 +925,12 @@ public class UnbundledChooserActivityTest { @Test @Ignore public void testEditImageLogs() throws Exception { - Intent sendIntent = createSendImageIntent( - Uri.parse("android.resource://com.android.frameworks.coretests/" - + R.drawable.test320x240)); - - ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + Uri uri = Uri.parse( + "android.resource://com.android.frameworks.coretests/" + + R.drawable.test320x240); + Intent sendIntent = createSendImageIntent(uri); + ChooserActivityOverrideData.getInstance().imageLoader = + createImageLoader(uri, createBitmap()); ChooserActivityOverrideData.getInstance().isImageType = true; List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); @@ -910,7 +957,8 @@ public class UnbundledChooserActivityTest { uris.add(uri); Intent sendIntent = createSendUriIntentWithPreview(uris); - ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + ChooserActivityOverrideData.getInstance().imageLoader = + createImageLoader(uri, createBitmap()); ChooserActivityOverrideData.getInstance().isImageType = true; List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); @@ -933,6 +981,29 @@ public class UnbundledChooserActivityTest { } @Test + public void allThumbnailsFailedToLoad_hidePreview() { + Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/" + + R.drawable.test320x240); + + ArrayList<Uri> uris = new ArrayList<>(); + uris.add(uri); + uris.add(uri); + + Intent sendIntent = createSendUriIntentWithPreview(uris); + ChooserActivityOverrideData.getInstance().imageLoader = + new TestPreviewImageLoader(Collections.emptyMap()); + ChooserActivityOverrideData.getInstance().isImageType = true; + + List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); + + setupResolverControllers(resolvedComponentInfos); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + waitForIdle(); + onView(withId(R.id.scrollable_image_preview)) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE))); + } + + @Test public void testManyVisibleImagePreview_ScrollableImagePreview() { Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/" + R.drawable.test320x240); @@ -950,7 +1021,8 @@ public class UnbundledChooserActivityTest { uris.add(uri); Intent sendIntent = createSendUriIntentWithPreview(uris); - ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + ChooserActivityOverrideData.getInstance().imageLoader = + createImageLoader(uri, createBitmap()); ChooserActivityOverrideData.getInstance().isImageType = true; List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); @@ -980,7 +1052,8 @@ public class UnbundledChooserActivityTest { Intent sendIntent = createSendUriIntentWithPreview(uris); sendIntent.putExtra(Intent.EXTRA_TEXT, sharedText); - ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + ChooserActivityOverrideData.getInstance().imageLoader = + createImageLoader(uri, createBitmap()); ChooserActivityOverrideData.getInstance().isImageType = true; List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); @@ -1004,7 +1077,8 @@ public class UnbundledChooserActivityTest { Intent sendIntent = createSendUriIntentWithPreview(uris); sendIntent.putExtra(Intent.EXTRA_TEXT, sharedText); - ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + ChooserActivityOverrideData.getInstance().imageLoader = + createImageLoader(uri, createBitmap()); ChooserActivityOverrideData.getInstance().isImageType = true; List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); @@ -1093,7 +1167,8 @@ public class UnbundledChooserActivityTest { uris.add(uri); Intent sendIntent = createSendUriIntentWithPreview(uris); - ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + ChooserActivityOverrideData.getInstance().imageLoader = + createImageLoader(uri, createBitmap()); ChooserActivityOverrideData.getInstance().isImageType = true; List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); @@ -2866,4 +2941,8 @@ public class UnbundledChooserActivityTest { }; return shortcutLoaders; } + + private static ImageLoader createImageLoader(Uri uri, Bitmap bitmap) { + return new TestPreviewImageLoader(Collections.singletonMap(uri, bitmap)); + } } |