diff options
| author | 2024-02-09 15:16:02 +0000 | |
|---|---|---|
| committer | 2024-02-09 15:16:02 +0000 | |
| commit | 13b9c24c24381dfadbec63936b02ea72cae43a3e (patch) | |
| tree | d6dab99181787d941028f7c5e1d2bb8ff3bd0eaf /java/src | |
| parent | 1831ffd4f04f1be892fe6b69ddd4d687cb0f67c8 (diff) | |
| parent | ac931a751ce024dfcd603a4ef9899dfe152927a6 (diff) | |
Merge "Add album headline override support to Chooser" into main
Diffstat (limited to 'java/src')
10 files changed, 88 insertions, 18 deletions
diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java index c3b13527..708538de 100644 --- a/java/src/com/android/intentresolver/ChooserActivity.java +++ b/java/src/com/android/intentresolver/ChooserActivity.java @@ -310,7 +310,8 @@ public class ChooserActivity extends Hilt_ChooserActivity implements previewViewModel.getImageLoader(), createChooserActionFactory(), mEnterTransitionAnimationDelegate, - new HeadlineGeneratorImpl(this)); + new HeadlineGeneratorImpl(this), + ContentTypeHint.NONE); updateStickyContentPreview(); if (shouldShowStickyContentPreview() diff --git a/java/src/com/android/intentresolver/ContentTypeHint.kt b/java/src/com/android/intentresolver/ContentTypeHint.kt new file mode 100644 index 00000000..f607e4ae --- /dev/null +++ b/java/src/com/android/intentresolver/ContentTypeHint.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 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 + +import android.content.Intent + +/** Enum reflecting the value of [Intent.EXTRA_CHOOSER_CONTENT_TYPE_HINT]. */ +enum class ContentTypeHint { + NONE, + ALBUM, +} diff --git a/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java index a015147d..5b4cb682 100644 --- a/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java @@ -32,6 +32,7 @@ import android.view.ViewGroup; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import com.android.intentresolver.ContentTypeHint; import com.android.intentresolver.widget.ActionRow; import com.android.intentresolver.widget.ImagePreviewView.TransitionElementStatusCallback; @@ -98,7 +99,8 @@ public final class ChooserContentPreviewUi { ImageLoader imageLoader, ActionFactory actionFactory, TransitionElementStatusCallback transitionElementStatusCallback, - HeadlineGenerator headlineGenerator) { + HeadlineGenerator headlineGenerator, + ContentTypeHint contentTypeHint) { mScope = scope; mContentPreviewUi = createContentPreview( previewData, @@ -107,7 +109,8 @@ public final class ChooserContentPreviewUi { imageLoader, actionFactory, transitionElementStatusCallback, - headlineGenerator); + headlineGenerator, + contentTypeHint); if (mContentPreviewUi.getType() != CONTENT_PREVIEW_IMAGE) { transitionElementStatusCallback.onAllTransitionElementsReady(); } @@ -120,7 +123,8 @@ public final class ChooserContentPreviewUi { ImageLoader imageLoader, ActionFactory actionFactory, TransitionElementStatusCallback transitionElementStatusCallback, - HeadlineGenerator headlineGenerator) { + HeadlineGenerator headlineGenerator, + ContentTypeHint contentTypeHint) { int previewType = previewData.getPreviewType(); if (previewType == CONTENT_PREVIEW_TEXT) { @@ -129,7 +133,8 @@ public final class ChooserContentPreviewUi { targetIntent, actionFactory, imageLoader, - headlineGenerator); + headlineGenerator, + contentTypeHint); } if (previewType == CONTENT_PREVIEW_FILE) { FileContentPreviewUi fileContentPreviewUi = new FileContentPreviewUi( @@ -142,7 +147,7 @@ public final class ChooserContentPreviewUi { return fileContentPreviewUi; } boolean isSingleImageShare = previewData.getUriCount() == 1 - && typeClassifier.isImageType(previewData.getFirstFileInfo().getMimeType()); + && typeClassifier.isImageType(previewData.getFirstFileInfo().getMimeType()); CharSequence text = targetIntent.getCharSequenceExtra(Intent.EXTRA_TEXT); if (!TextUtils.isEmpty(text)) { FilesPlusTextContentPreviewUi previewUi = @@ -200,7 +205,8 @@ public final class ChooserContentPreviewUi { Intent targetIntent, ChooserContentPreviewUi.ActionFactory actionFactory, ImageLoader imageLoader, - HeadlineGenerator headlineGenerator) { + HeadlineGenerator headlineGenerator, + ContentTypeHint contentTypeHint) { CharSequence sharingText = targetIntent.getCharSequenceExtra(Intent.EXTRA_TEXT); CharSequence previewTitle = targetIntent.getCharSequenceExtra(Intent.EXTRA_TITLE); ClipData previewData = targetIntent.getClipData(); @@ -211,6 +217,7 @@ public final class ChooserContentPreviewUi { previewThumbnail = previewDataItem.getUri(); } } + return new TextContentPreviewUi( scope, sharingText, @@ -218,6 +225,7 @@ public final class ChooserContentPreviewUi { previewThumbnail, actionFactory, imageLoader, - headlineGenerator); + headlineGenerator, + contentTypeHint); } } diff --git a/java/src/com/android/intentresolver/contentpreview/HeadlineGenerator.kt b/java/src/com/android/intentresolver/contentpreview/HeadlineGenerator.kt index 5f87c924..21308341 100644 --- a/java/src/com/android/intentresolver/contentpreview/HeadlineGenerator.kt +++ b/java/src/com/android/intentresolver/contentpreview/HeadlineGenerator.kt @@ -17,12 +17,14 @@ package com.android.intentresolver.contentpreview /** - * HeadlineGenerator generates the text to show at the top of the sharesheet as a brief - * description of the content being shared. + * HeadlineGenerator generates the text to show at the top of the sharesheet as a brief description + * of the content being shared. */ interface HeadlineGenerator { fun getTextHeadline(text: CharSequence): String + fun getAlbumHeadline(): String + fun getImagesWithTextHeadline(text: CharSequence, count: Int): String fun getVideosWithTextHeadline(text: CharSequence, count: Int): String diff --git a/java/src/com/android/intentresolver/contentpreview/HeadlineGeneratorImpl.kt b/java/src/com/android/intentresolver/contentpreview/HeadlineGeneratorImpl.kt index ef1e55d8..6e126822 100644 --- a/java/src/com/android/intentresolver/contentpreview/HeadlineGeneratorImpl.kt +++ b/java/src/com/android/intentresolver/contentpreview/HeadlineGeneratorImpl.kt @@ -34,6 +34,10 @@ class HeadlineGeneratorImpl(private val context: Context) : HeadlineGenerator { ) } + override fun getAlbumHeadline(): String { + return context.getString(R.string.sharing_album) + } + override fun getImagesWithTextHeadline(text: CharSequence, count: Int): String { return getPluralString( getTemplateResource( diff --git a/java/src/com/android/intentresolver/contentpreview/TextContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/TextContentPreviewUi.java index b0dc3c58..df2896d7 100644 --- a/java/src/com/android/intentresolver/contentpreview/TextContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/TextContentPreviewUi.java @@ -30,6 +30,7 @@ import android.widget.TextView; import androidx.annotation.Nullable; +import com.android.intentresolver.ContentTypeHint; import com.android.intentresolver.R; import com.android.intentresolver.widget.ActionRow; @@ -46,6 +47,7 @@ class TextContentPreviewUi extends ContentPreviewUi { private final ImageLoader mImageLoader; private final ChooserContentPreviewUi.ActionFactory mActionFactory; private final HeadlineGenerator mHeadlineGenerator; + private final ContentTypeHint mContentTypeHint; TextContentPreviewUi( CoroutineScope scope, @@ -54,7 +56,8 @@ class TextContentPreviewUi extends ContentPreviewUi { @Nullable Uri previewThumbnail, ChooserContentPreviewUi.ActionFactory actionFactory, ImageLoader imageLoader, - HeadlineGenerator headlineGenerator) { + HeadlineGenerator headlineGenerator, + ContentTypeHint contentTypeHint) { mScope = scope; mSharingText = sharingText; mPreviewTitle = previewTitle; @@ -62,6 +65,7 @@ class TextContentPreviewUi extends ContentPreviewUi { mImageLoader = imageLoader; mActionFactory = actionFactory; mHeadlineGenerator = headlineGenerator; + mContentTypeHint = contentTypeHint; } @Override @@ -139,7 +143,10 @@ class TextContentPreviewUi extends ContentPreviewUi { copyButton.setVisibility(View.GONE); } - displayHeadline(headlineViewParent, mHeadlineGenerator.getTextHeadline(mSharingText)); + String headlineText = (mContentTypeHint == ContentTypeHint.ALBUM) + ? mHeadlineGenerator.getAlbumHeadline() + : mHeadlineGenerator.getTextHeadline(mSharingText); + displayHeadline(headlineViewParent, headlineText); return contentPreviewLayout; } diff --git a/java/src/com/android/intentresolver/v2/ChooserActivity.java b/java/src/com/android/intentresolver/v2/ChooserActivity.java index b9cf53b6..247f6529 100644 --- a/java/src/com/android/intentresolver/v2/ChooserActivity.java +++ b/java/src/com/android/intentresolver/v2/ChooserActivity.java @@ -477,7 +477,8 @@ public class ChooserActivity extends Hilt_ChooserActivity implements previewViewModel.getImageLoader(), createChooserActionFactory(), mEnterTransitionAnimationDelegate, - new HeadlineGeneratorImpl(this)); + new HeadlineGeneratorImpl(this), + chooserRequest.getContentTypeHint()); updateStickyContentPreview(); if (shouldShowStickyContentPreview() || mChooserMultiProfilePagerAdapter diff --git a/java/src/com/android/intentresolver/v2/ui/model/ChooserRequest.kt b/java/src/com/android/intentresolver/v2/ui/model/ChooserRequest.kt index 5c785675..4fc2e46a 100644 --- a/java/src/com/android/intentresolver/v2/ui/model/ChooserRequest.kt +++ b/java/src/com/android/intentresolver/v2/ui/model/ChooserRequest.kt @@ -27,6 +27,7 @@ import android.os.Bundle import android.service.chooser.ChooserAction import android.service.chooser.ChooserTarget import androidx.annotation.StringRes +import com.android.intentresolver.ContentTypeHint import com.android.intentresolver.v2.ext.hasAction const val ANDROID_APP_SCHEME = "android-app" @@ -169,6 +170,9 @@ data class ChooserRequest( /** Focused item index (from target intent's STREAM_EXTRA) */ val focusedItemPosition: Int = 0, + + /** Value for [Intent.EXTRA_CHOOSER_CONTENT_TYPE_HINT] on the incoming chooser intent. */ + val contentTypeHint: ContentTypeHint = ContentTypeHint.NONE ) { val referrerPackage = referrer?.takeIf { it.scheme == ANDROID_APP_SCHEME }?.authority diff --git a/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt b/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt index 167c441f..558e54c9 100644 --- a/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt +++ b/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt @@ -40,9 +40,10 @@ import android.net.Uri import android.os.Bundle import android.service.chooser.ChooserAction import android.service.chooser.ChooserTarget -import android.service.chooser.Flags import com.android.intentresolver.ChooserActivity +import com.android.intentresolver.ContentTypeHint import com.android.intentresolver.R +import com.android.intentresolver.inject.ChooserServiceFlags import com.android.intentresolver.util.hasValidIcon import com.android.intentresolver.v2.ext.hasAction import com.android.intentresolver.v2.ext.ifMatch @@ -72,7 +73,10 @@ internal fun Intent.maybeAddSendActionFlags() = addFlags(FLAG_ACTIVITY_MULTIPLE_TASK) } -fun readChooserRequest(launch: ActivityLaunch): ValidationResult<ChooserRequest> { +fun readChooserRequest( + launch: ActivityLaunch, + flags: ChooserServiceFlags +): ValidationResult<ChooserRequest> { val extras = launch.intent.extras ?: Bundle() @Suppress("DEPRECATION") return validateFrom(extras::get) { @@ -135,7 +139,7 @@ fun readChooserRequest(launch: ActivityLaunch): ValidationResult<ChooserRequest> val additionalContentUri: Uri? val focusedItemPos: Int - if (isSendAction && Flags.chooserPayloadToggling()) { + if (isSendAction && flags.chooserPayloadToggling()) { additionalContentUri = optional(value<Uri>(EXTRA_CHOOSER_ADDITIONAL_CONTENT_URI)) focusedItemPos = optional(value<Int>(EXTRA_CHOOSER_FOCUSED_ITEM_POSITION)) ?: 0 } else { @@ -143,6 +147,16 @@ fun readChooserRequest(launch: ActivityLaunch): ValidationResult<ChooserRequest> focusedItemPos = 0 } + val contentTypeHint = + if (flags.chooserAlbumText()) { + when (optional(value<Int>(Intent.EXTRA_CHOOSER_CONTENT_TYPE_HINT))) { + Intent.CHOOSER_CONTENT_TYPE_ALBUM -> ContentTypeHint.ALBUM + else -> ContentTypeHint.NONE + } + } else { + ContentTypeHint.NONE + } + ChooserRequest( targetIntent = targetIntent, targetAction = targetIntent.action, @@ -169,6 +183,7 @@ fun readChooserRequest(launch: ActivityLaunch): ValidationResult<ChooserRequest> shareTargetFilter = targetIntent.toShareTargetFilter(), additionalContentUri = additionalContentUri, focusedItemPosition = focusedItemPos, + contentTypeHint = contentTypeHint, ) } } diff --git a/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserViewModel.kt b/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserViewModel.kt index 17b1e664..776bc1cb 100644 --- a/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserViewModel.kt +++ b/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserViewModel.kt @@ -18,6 +18,7 @@ package com.android.intentresolver.v2.ui.viewmodel import android.util.Log import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel +import com.android.intentresolver.inject.ChooserServiceFlags import com.android.intentresolver.v2.ui.model.ActivityLaunch import com.android.intentresolver.v2.ui.model.ActivityLaunch.Companion.ACTIVITY_LAUNCH_KEY import com.android.intentresolver.v2.ui.model.ChooserRequest @@ -28,7 +29,8 @@ import javax.inject.Inject private const val TAG = "ChooserViewModel" @HiltViewModel -class ChooserViewModel @Inject constructor(args: SavedStateHandle) : ViewModel() { +class ChooserViewModel @Inject constructor(args: SavedStateHandle, flags: ChooserServiceFlags) : + ViewModel() { private val mActivityLaunch: ActivityLaunch = requireNotNull(args[ACTIVITY_LAUNCH_KEY]) { @@ -36,7 +38,8 @@ class ChooserViewModel @Inject constructor(args: SavedStateHandle) : ViewModel() } /** The result of reading and validating the inputs provided in savedState. */ - private val status: ValidationResult<ChooserRequest> = readChooserRequest(mActivityLaunch) + private val status: ValidationResult<ChooserRequest> = + readChooserRequest(mActivityLaunch, flags) val chooserRequest: ChooserRequest by lazy { status.getOrThrow() } |