From ce9a21b2540f14478d326875f13b4156327f1fe4 Mon Sep 17 00:00:00 2001 From: Andrey Epin Date: Thu, 26 Jan 2023 18:13:17 -0800 Subject: A simple UI for Image + Text sharing Add a simple UI for Image + Text sharing under a feature flag. Bug: 262277421 Test: manual test Change-Id: Id7ee55c0d6e7bb21791e5f75a2acb78ce2eac79f --- java/res/layout/chooser_grid_preview_image.xml | 33 ++++++++++++---- .../intentresolver/ChooserContentPreviewUi.java | 23 ++++++++++- .../com/android/intentresolver/HttpUriMatcher.kt | 29 ++++++++++++++ java/src/com/android/intentresolver/flags/Flags.kt | 6 +++ .../UnbundledChooserActivityTest.java | 45 ++++++++++++++++++++++ 5 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 java/src/com/android/intentresolver/HttpUriMatcher.kt (limited to 'java') diff --git a/java/res/layout/chooser_grid_preview_image.xml b/java/res/layout/chooser_grid_preview_image.xml index 23bc25d7..d43a26de 100644 --- a/java/res/layout/chooser_grid_preview_image.xml +++ b/java/res/layout/chooser_grid_preview_image.xml @@ -25,13 +25,33 @@ android:orientation="vertical" android:background="?android:attr/colorBackground"> - + android:orientation="horizontal" + android:gravity="center_horizontal" + android:layout_marginBottom="@dimen/chooser_view_spacing"> + + + + + - diff --git a/java/src/com/android/intentresolver/ChooserContentPreviewUi.java b/java/src/com/android/intentresolver/ChooserContentPreviewUi.java index 26c08e36..553a36c6 100644 --- a/java/src/com/android/intentresolver/ChooserContentPreviewUi.java +++ b/java/src/com/android/intentresolver/ChooserContentPreviewUi.java @@ -32,6 +32,7 @@ import android.provider.DocumentsContract; import android.provider.Downloads; import android.provider.OpenableColumns; import android.text.TextUtils; +import android.text.util.Linkify; import android.util.Log; import android.util.PluralsMessageFormatter; import android.view.LayoutInflater; @@ -350,7 +351,7 @@ public final class ChooserContentPreviewUi { return actions; } - private static ViewGroup displayImageContentPreview( + private ViewGroup displayImageContentPreview( Intent targetIntent, LayoutInflater layoutInflater, List actions, @@ -389,12 +390,32 @@ public final class ChooserContentPreviewUi { return contentPreviewLayout; } + setTextInImagePreviewVisibility( + contentPreviewLayout, + targetIntent.getCharSequenceExtra(Intent.EXTRA_TEXT)); imagePreview.setTransitionElementStatusCallback(transitionElementStatusCallback); imagePreview.setImages(imageUris, imageLoader); return contentPreviewLayout; } + private void setTextInImagePreviewVisibility( + ViewGroup contentPreview, CharSequence text) { + int visibility = mFeatureFlagRepository.isEnabled(Flags.SHARESHEET_IMAGE_AND_TEXT_PREVIEW) + && !TextUtils.isEmpty(text) + ? View.VISIBLE + : View.GONE; + + TextView textView = contentPreview + .requireViewById(com.android.internal.R.id.content_preview_text); + textView.setVisibility(visibility); + int linkMask = visibility == View.VISIBLE && HttpUriMatcher.isHttpUri(text.toString()) + ? Linkify.WEB_URLS + : 0; + textView.setAutoLinkMask(linkMask); + textView.setText(text); + } + private static List createImagePreviewActions( ActionFactory buttonFactory) { ArrayList actions = new ArrayList<>(2); diff --git a/java/src/com/android/intentresolver/HttpUriMatcher.kt b/java/src/com/android/intentresolver/HttpUriMatcher.kt new file mode 100644 index 00000000..0f59df2b --- /dev/null +++ b/java/src/com/android/intentresolver/HttpUriMatcher.kt @@ -0,0 +1,29 @@ +/* + * 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. + */ + +@file:JvmName("HttpUriMatcher") +package com.android.intentresolver + +import com.android.internal.annotations.VisibleForTesting +import java.net.URI + +@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) +fun String.isHttpUri() = + kotlin.runCatching { + URI(this).scheme.takeIf { scheme -> + "http".compareTo(scheme, true) == 0 || "https".compareTo(scheme, true) == 0 + } + }.getOrNull() != null \ No newline at end of file diff --git a/java/src/com/android/intentresolver/flags/Flags.kt b/java/src/com/android/intentresolver/flags/Flags.kt index 6962b1c3..92ee5115 100644 --- a/java/src/com/android/intentresolver/flags/Flags.kt +++ b/java/src/com/android/intentresolver/flags/Flags.kt @@ -29,6 +29,12 @@ object Flags { @JvmField val SHARESHEET_RESELECTION_ACTION = unreleasedFlag(1502, "sharesheet_reselection_action") + // TODO(b/266983474) Tracking Bug + @JvmField + val SHARESHEET_IMAGE_AND_TEXT_PREVIEW = unreleasedFlag( + id = 1503, name = "sharesheet_image_text_preview" + ) + private fun unreleasedFlag(id: Int, name: String, teamfood: Boolean = false) = UnreleasedFlag(id, name, "systemui", teamfood) } diff --git a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java index 53c357d6..f06812f1 100644 --- a/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java +++ b/java/tests/src/com/android/intentresolver/UnbundledChooserActivityTest.java @@ -971,6 +971,51 @@ public class UnbundledChooserActivityTest { .check(matches(isDisplayed())); } + @Test + public void testImageAndTextPreview() { + ChooserActivityOverrideData.getInstance().featureFlagRepository = + new FeatureFlagRepository() { + @Override + public boolean isEnabled(@NonNull UnreleasedFlag flag) { + return Flags.SHARESHEET_IMAGE_AND_TEXT_PREVIEW.equals(flag) + || flag.getDefault(); + } + + @Override + public boolean isEnabled(@NonNull ReleasedFlag flag) { + return false; + } + }; + final Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/" + + R.drawable.test320x240); + final String sharedText = "text-" + System.currentTimeMillis(); + + ArrayList uris = new ArrayList<>(); + uris.add(uri); + + Intent sendIntent = createSendUriIntentWithPreview(uris); + sendIntent.putExtra(Intent.EXTRA_TEXT, sharedText); + ChooserActivityOverrideData.getInstance().previewThumbnail = createBitmap(); + ChooserActivityOverrideData.getInstance().isImageType = true; + + List resolvedComponentInfos = createResolvedComponentsForTest(2); + + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + waitForIdle(); + onView(withText(sharedText)) + .check(matches(isDisplayed())); + } + @Test public void testOnCreateLogging() { Intent sendIntent = createSendTextIntent(); -- cgit v1.2.3-59-g8ed1b