From 21ab7fb0b67fe3b5c16fc26b5cf6d016bfc0e248 Mon Sep 17 00:00:00 2001 From: Andrey Epin Date: Mon, 6 Mar 2023 12:01:27 -0800 Subject: Split ChooserContentPreviewUi into multiple components A prep step for the new preview UI: extract each preview logic from ChooserContentPreviewUi into individual components leaving the former as a facade for the latter. More specifically: * move ChooserContnetPreviewUi into a new package; * make #displayTextContentPreview() to be the core of the TextContentPreviewUI (with related methods); * make #displayFileContentPreview() to be the core of the FileContentPreviewUi (with related methods); * make #displayImageContentPreview() to the core of the ImageContentPreviewUi (with the related methods); * for all aforementioned new components, pass component specific dependencies as constructor arguments, capture the common component contract in the base abstract class, ContentPreviewUi, along with the static utility methods. Bug: 271613784 Test: Manual testing of * Text sharing with and without preview; * File sharing with and without preivew, single file and multiple fiels; * Image sharing, single and multiple files, image + text sharing; * Custom actions with text, image and files sharing; * Reselection action with text, image and files sharing. Test: screenshot transition animation Test: atest IntentResolverUnitTests Change-Id: I392de610b3d3e044e23c83d29fd11061fbc7192d --- .../intentresolver/ChooserActivityLoggerTest.java | 5 +- .../intentresolver/TestFeatureFlagRepository.kt | 2 +- .../contentpreview/ChooserContentPreviewUiTest.kt | 203 +++++++++++++++++++++ 3 files changed, 207 insertions(+), 3 deletions(-) create mode 100644 java/tests/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUiTest.kt (limited to 'java/tests') diff --git a/java/tests/src/com/android/intentresolver/ChooserActivityLoggerTest.java b/java/tests/src/com/android/intentresolver/ChooserActivityLoggerTest.java index 7d1b2488..aa42c24c 100644 --- a/java/tests/src/com/android/intentresolver/ChooserActivityLoggerTest.java +++ b/java/tests/src/com/android/intentresolver/ChooserActivityLoggerTest.java @@ -36,6 +36,7 @@ import com.android.intentresolver.ChooserActivityLogger.FrameworkStatsLogger; import com.android.intentresolver.ChooserActivityLogger.SharesheetStandardEvent; import com.android.intentresolver.ChooserActivityLogger.SharesheetStartedEvent; import com.android.intentresolver.ChooserActivityLogger.SharesheetTargetSelectedEvent; +import com.android.intentresolver.contentpreview.ContentPreviewType; import com.android.internal.logging.InstanceId; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; @@ -117,7 +118,7 @@ public final class ChooserActivityLoggerTest { final int appProvidedDirectTargets = 123; final int appProvidedAppTargets = 456; final boolean workProfile = true; - final int previewType = ChooserContentPreviewUi.CONTENT_PREVIEW_FILE; + final int previewType = ContentPreviewType.CONTENT_PREVIEW_FILE; final String intentAction = Intent.ACTION_SENDTO; final int numCustomActions = 3; final boolean modifyShareProvided = true; @@ -233,7 +234,7 @@ public final class ChooserActivityLoggerTest { @Test public void testLogActionShareWithPreview() { - final int previewType = ChooserContentPreviewUi.CONTENT_PREVIEW_TEXT; + final int previewType = ContentPreviewType.CONTENT_PREVIEW_TEXT; mChooserLogger.logActionShareWithPreview(previewType); diff --git a/java/tests/src/com/android/intentresolver/TestFeatureFlagRepository.kt b/java/tests/src/com/android/intentresolver/TestFeatureFlagRepository.kt index 5a159d24..b9047712 100644 --- a/java/tests/src/com/android/intentresolver/TestFeatureFlagRepository.kt +++ b/java/tests/src/com/android/intentresolver/TestFeatureFlagRepository.kt @@ -21,7 +21,7 @@ import com.android.systemui.flags.BooleanFlag import com.android.systemui.flags.ReleasedFlag import com.android.systemui.flags.UnreleasedFlag -internal class TestFeatureFlagRepository( +class TestFeatureFlagRepository( private val overrides: Map ) : FeatureFlagRepository { override fun isEnabled(flag: UnreleasedFlag): Boolean = getValue(flag) diff --git a/java/tests/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUiTest.kt b/java/tests/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUiTest.kt new file mode 100644 index 00000000..d870a8c2 --- /dev/null +++ b/java/tests/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUiTest.kt @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2023 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. + */ + +package com.android.intentresolver.contentpreview + +import android.content.ClipDescription +import android.content.ContentInterface +import android.content.Intent +import android.graphics.Bitmap +import android.net.Uri +import com.android.intentresolver.ImageLoader +import com.android.intentresolver.TestFeatureFlagRepository +import com.android.intentresolver.contentpreview.ChooserContentPreviewUi.ActionFactory +import com.android.intentresolver.flags.Flags +import com.android.intentresolver.mock +import com.android.intentresolver.whenever +import com.android.intentresolver.widget.ActionRow +import com.android.intentresolver.widget.ImagePreviewView +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.mockito.Mockito.never +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import java.util.function.Consumer + +private const val PROVIDER_NAME = "org.pkg.app" +class ChooserContentPreviewUiTest { + private val contentResolver = mock() + private val imageClassifier = ChooserContentPreviewUi.ImageMimeTypeClassifier { mimeType -> + mimeType != null && ClipDescription.compareMimeTypes(mimeType, "image/*") + } + private val imageLoader = object : ImageLoader { + override fun loadImage(uri: Uri, callback: Consumer) { + callback.accept(null) + } + override fun prePopulate(uris: List) = Unit + override suspend fun invoke(uri: Uri): Bitmap? = null + } + private val actionFactory = object : ActionFactory { + override fun createCopyButton() = ActionRow.Action(label = "Copy", icon = null) {} + override fun createEditButton(): ActionRow.Action? = null + override fun createNearbyButton(): ActionRow.Action? = null + override fun createCustomActions(): List = emptyList() + override fun getModifyShareAction(): Runnable? = null + override fun getExcludeSharedTextAction(): Consumer = Consumer {} + } + private val transitionCallback = mock() + private val featureFlagRepository = TestFeatureFlagRepository( + mapOf( + Flags.SHARESHEET_SCROLLABLE_IMAGE_PREVIEW to true + ) + ) + + @Test + fun test_ChooserContentPreview_non_send_intent_action_to_text_preview() { + val targetIntent = Intent(Intent.ACTION_VIEW) + val testSubject = ChooserContentPreviewUi( + targetIntent, + contentResolver, + imageClassifier, + imageLoader, + actionFactory, + transitionCallback, + featureFlagRepository + ) + assertThat(testSubject.preferredContentPreview) + .isEqualTo(ContentPreviewType.CONTENT_PREVIEW_TEXT) + verify(transitionCallback, times(1)).onAllTransitionElementsReady() + } + + @Test + fun test_ChooserContentPreview_text_mime_type_to_text_preview() { + val targetIntent = Intent(Intent.ACTION_SEND).apply { + type = "text/plain" + putExtra(Intent.EXTRA_TEXT, "Text Extra") + } + val testSubject = ChooserContentPreviewUi( + targetIntent, + contentResolver, + imageClassifier, + imageLoader, + actionFactory, + transitionCallback, + featureFlagRepository + ) + assertThat(testSubject.preferredContentPreview) + .isEqualTo(ContentPreviewType.CONTENT_PREVIEW_TEXT) + verify(transitionCallback, times(1)).onAllTransitionElementsReady() + } + + @Test + fun test_ChooserContentPreview_single_image_uri_to_image_preview() { + val uri = Uri.parse("content://$PROVIDER_NAME/test.png") + val targetIntent = Intent(Intent.ACTION_SEND).apply { + putExtra(Intent.EXTRA_STREAM, uri) + } + whenever(contentResolver.getType(uri)).thenReturn("image/png") + val testSubject = ChooserContentPreviewUi( + targetIntent, + contentResolver, + imageClassifier, + imageLoader, + actionFactory, + transitionCallback, + featureFlagRepository + ) + assertThat(testSubject.preferredContentPreview) + .isEqualTo(ContentPreviewType.CONTENT_PREVIEW_IMAGE) + verify(transitionCallback, never()).onAllTransitionElementsReady() + } + + @Test + fun test_ChooserContentPreview_single_non_image_uri_to_file_preview() { + val uri = Uri.parse("content://$PROVIDER_NAME/test.pdf") + val targetIntent = Intent(Intent.ACTION_SEND).apply { + putExtra(Intent.EXTRA_STREAM, uri) + } + whenever(contentResolver.getType(uri)).thenReturn("application/pdf") + val testSubject = ChooserContentPreviewUi( + targetIntent, + contentResolver, + imageClassifier, + imageLoader, + actionFactory, + transitionCallback, + featureFlagRepository + ) + assertThat(testSubject.preferredContentPreview) + .isEqualTo(ContentPreviewType.CONTENT_PREVIEW_FILE) + verify(transitionCallback, times(1)).onAllTransitionElementsReady() + } + + @Test + fun test_ChooserContentPreview_multiple_image_uri_to_image_preview() { + val uri1 = Uri.parse("content://$PROVIDER_NAME/test.png") + val uri2 = Uri.parse("content://$PROVIDER_NAME/test.jpg") + val targetIntent = Intent(Intent.ACTION_SEND_MULTIPLE).apply { + putExtra( + Intent.EXTRA_STREAM, + ArrayList().apply { + add(uri1) + add(uri2) + } + ) + } + whenever(contentResolver.getType(uri1)).thenReturn("image/png") + whenever(contentResolver.getType(uri2)).thenReturn("image/jpeg") + val testSubject = ChooserContentPreviewUi( + targetIntent, + contentResolver, + imageClassifier, + imageLoader, + actionFactory, + transitionCallback, + featureFlagRepository + ) + assertThat(testSubject.preferredContentPreview) + .isEqualTo(ContentPreviewType.CONTENT_PREVIEW_IMAGE) + verify(transitionCallback, never()).onAllTransitionElementsReady() + } + + @Test + fun test_ChooserContentPreview_some_non_image_uri_to_file_preview() { + val uri1 = Uri.parse("content://$PROVIDER_NAME/test.png") + val uri2 = Uri.parse("content://$PROVIDER_NAME/test.pdf") + val targetIntent = Intent(Intent.ACTION_SEND_MULTIPLE).apply { + putExtra( + Intent.EXTRA_STREAM, + ArrayList().apply { + add(uri1) + add(uri2) + } + ) + } + whenever(contentResolver.getType(uri1)).thenReturn("image/png") + whenever(contentResolver.getType(uri2)).thenReturn("application/pdf") + val testSubject = ChooserContentPreviewUi( + targetIntent, + contentResolver, + imageClassifier, + imageLoader, + actionFactory, + transitionCallback, + featureFlagRepository + ) + assertThat(testSubject.preferredContentPreview) + .isEqualTo(ContentPreviewType.CONTENT_PREVIEW_FILE) + verify(transitionCallback, times(1)).onAllTransitionElementsReady() + } +} -- cgit v1.2.3-59-g8ed1b