diff options
author | 2024-02-08 23:34:46 -0800 | |
---|---|---|
committer | 2024-02-12 21:43:49 -0800 | |
commit | fbde775360396f6e9df8d6cb8abd8189b75d0979 (patch) | |
tree | 85f576f208c2eba11d259746b7e23b08bed98b64 /java | |
parent | 7c3a34ea571c1c8571f33d3fe72afac7a175c055 (diff) |
Show payload toggling UI
Show payload toggling UI if the flag is enabled.
Bug: 302691505
Test: enable feature flag and verify that payload toggling UI is gets
shown
Change-Id: If3c70088e58977f5345066d5abec31e298e1f4fe
Diffstat (limited to 'java')
6 files changed, 87 insertions, 4 deletions
diff --git a/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java b/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java index 471a33e6..acdf6ec6 100644 --- a/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java +++ b/java/src/com/android/intentresolver/contentpreview/ChooserContentPreviewUi.java @@ -18,12 +18,14 @@ package com.android.intentresolver.contentpreview; import static com.android.intentresolver.contentpreview.ContentPreviewType.CONTENT_PREVIEW_FILE; import static com.android.intentresolver.contentpreview.ContentPreviewType.CONTENT_PREVIEW_IMAGE; +import static com.android.intentresolver.contentpreview.ContentPreviewType.CONTENT_PREVIEW_PAYLOAD_SELECTION; import static com.android.intentresolver.contentpreview.ContentPreviewType.CONTENT_PREVIEW_TEXT; import android.content.ClipData; import android.content.Intent; import android.content.res.Resources; import android.net.Uri; +import android.service.chooser.Flags; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; @@ -154,6 +156,13 @@ public final class ChooserContentPreviewUi { } return fileContentPreviewUi; } + + //TODO: use flags injection + if (previewType == CONTENT_PREVIEW_PAYLOAD_SELECTION && Flags.chooserPayloadToggling()) { + transitionElementStatusCallback.onAllTransitionElementsReady(); // TODO + return new ShareouselContentPreviewUi(actionFactory); + } + boolean isSingleImageShare = previewData.getUriCount() == 1 && typeClassifier.isImageType(previewData.getFirstFileInfo().getMimeType()); CharSequence text = targetIntent.getCharSequenceExtra(Intent.EXTRA_TEXT); diff --git a/java/src/com/android/intentresolver/contentpreview/PayloadToggleInteractor.kt b/java/src/com/android/intentresolver/contentpreview/PayloadToggleInteractor.kt index 3393dcfc..8a34e6a9 100644 --- a/java/src/com/android/intentresolver/contentpreview/PayloadToggleInteractor.kt +++ b/java/src/com/android/intentresolver/contentpreview/PayloadToggleInteractor.kt @@ -27,6 +27,7 @@ import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicReference import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.channels.BufferOverflow.DROP_LATEST @@ -40,6 +41,7 @@ import kotlinx.coroutines.launch private const val TAG = "PayloadToggleInteractor" +@OptIn(ExperimentalCoroutinesApi::class) class PayloadToggleInteractor( // must use single-thread dispatcher (or we should enforce it with a lock) private val scope: CoroutineScope, diff --git a/java/src/com/android/intentresolver/contentpreview/ShareouselContentPreviewUi.kt b/java/src/com/android/intentresolver/contentpreview/ShareouselContentPreviewUi.kt index 51a3cb14..4dd0d3f5 100644 --- a/java/src/com/android/intentresolver/contentpreview/ShareouselContentPreviewUi.kt +++ b/java/src/com/android/intentresolver/contentpreview/ShareouselContentPreviewUi.kt @@ -63,7 +63,7 @@ internal class ShareouselContentPreviewUi( val vm: BasePreviewViewModel = viewModel() val interactor = requireNotNull(vm.payloadToggleInteractor) { "Should not be null" } - val viewModel = interactor.toShareouselViewModel(vm.imageLoader) + val viewModel = interactor.toShareouselViewModel(vm.imageLoader, actionFactory) if (headlineViewParent != null) { LaunchedEffect(Unit) { diff --git a/java/src/com/android/intentresolver/contentpreview/shareousel/ui/viewmodel/ShareouselViewModel.kt b/java/src/com/android/intentresolver/contentpreview/shareousel/ui/viewmodel/ShareouselViewModel.kt index 05523c7e..fae439e5 100644 --- a/java/src/com/android/intentresolver/contentpreview/shareousel/ui/viewmodel/ShareouselViewModel.kt +++ b/java/src/com/android/intentresolver/contentpreview/shareousel/ui/viewmodel/ShareouselViewModel.kt @@ -16,11 +16,17 @@ package com.android.intentresolver.contentpreview.shareousel.ui.viewmodel import android.graphics.Bitmap +import androidx.core.graphics.drawable.toBitmap +import com.android.intentresolver.contentpreview.ChooserContentPreviewUi.ActionFactory import com.android.intentresolver.contentpreview.ImageLoader +import com.android.intentresolver.contentpreview.MutableActionFactory import com.android.intentresolver.contentpreview.PayloadToggleInteractor +import com.android.intentresolver.icon.BitmapIcon import com.android.intentresolver.icon.ComposeIcon +import com.android.intentresolver.widget.ActionRow.Action import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map data class ShareouselViewModel( @@ -41,11 +47,23 @@ data class ShareouselImageViewModel( val setSelected: (Boolean) -> Unit, ) -fun PayloadToggleInteractor.toShareouselViewModel(imageLoader: ImageLoader): ShareouselViewModel { +fun PayloadToggleInteractor.toShareouselViewModel( + imageLoader: ImageLoader, + actionFactory: ActionFactory +): ShareouselViewModel { return ShareouselViewModel( headline = MutableStateFlow("Shareousel"), previewKeys = previewKeys, - actions = MutableStateFlow(emptyList()), + actions = + if (actionFactory is MutableActionFactory) { + actionFactory.customActionsFlow.map { actions -> + actions.map { it.toActionChipViewModel() } + } + } else { + flow { + emit(actionFactory.createCustomActions().map { it.toActionChipViewModel() }) + } + }, centerIndex = targetPosition, previewForKey = { key -> val previewInteractor = previewInteractor(key) @@ -59,3 +77,10 @@ fun PayloadToggleInteractor.toShareouselViewModel(imageLoader: ImageLoader): Sha previewRowKey = { getKey(it) }, ) } + +private fun Action.toActionChipViewModel() = + ActionChipViewModel( + label?.toString() ?: "", + icon?.let { BitmapIcon(it.toBitmap()) }, + onClick = { onClicked.run() } + ) diff --git a/java/src/com/android/intentresolver/v2/ChooserActivity.java b/java/src/com/android/intentresolver/v2/ChooserActivity.java index 2ffd31d8..cdc05b95 100644 --- a/java/src/com/android/intentresolver/v2/ChooserActivity.java +++ b/java/src/com/android/intentresolver/v2/ChooserActivity.java @@ -29,6 +29,7 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTE import static androidx.lifecycle.LifecycleKt.getCoroutineScope; +import static com.android.intentresolver.contentpreview.ContentPreviewType.CONTENT_PREVIEW_PAYLOAD_SELECTION; import static com.android.intentresolver.v2.ext.CreationExtrasExtKt.addDefaultArgs; import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED; import static com.android.internal.util.LatencyTracker.ACTION_LOAD_SHARE_SHEET; @@ -122,6 +123,7 @@ import com.android.intentresolver.chooser.TargetInfo; import com.android.intentresolver.contentpreview.BasePreviewViewModel; import com.android.intentresolver.contentpreview.ChooserContentPreviewUi; import com.android.intentresolver.contentpreview.HeadlineGeneratorImpl; +import com.android.intentresolver.contentpreview.PayloadToggleInteractor; import com.android.intentresolver.contentpreview.PreviewViewModel; import com.android.intentresolver.emptystate.CompositeEmptyStateProvider; import com.android.intentresolver.emptystate.CrossProfileIntentsChecker; @@ -487,12 +489,29 @@ public class ChooserActivity extends Hilt_ChooserActivity implements chooserRequest.getAdditionalContentUri(), chooserRequest.getFocusedItemPosition(), mChooserServiceFeatureFlags.chooserPayloadToggling()); + ChooserActionFactory chooserActionFactory = createChooserActionFactory(); + ChooserContentPreviewUi.ActionFactory actionFactory = chooserActionFactory; + if (previewViewModel.getPreviewDataProvider().getPreviewType() + == CONTENT_PREVIEW_PAYLOAD_SELECTION + && android.service.chooser.Flags.chooserPayloadToggling()) { + PayloadToggleInteractor payloadToggleInteractor = + previewViewModel.getPayloadToggleInteractor(); + if (payloadToggleInteractor != null) { + ChooserMutableActionFactory mutableActionFactory = + new ChooserMutableActionFactory(chooserActionFactory); + actionFactory = mutableActionFactory; + JavaFlowHelper.collect( + getCoroutineScope(getLifecycle()), + payloadToggleInteractor.getCustomActions(), + mutableActionFactory::updateCustomActions); + } + } mChooserContentPreviewUi = new ChooserContentPreviewUi( getCoroutineScope(getLifecycle()), previewViewModel.getPreviewDataProvider(), chooserRequest.getTargetIntent(), previewViewModel.getImageLoader(), - createChooserActionFactory(), + actionFactory, mEnterTransitionAnimationDelegate, new HeadlineGeneratorImpl(this), chooserRequest.getContentTypeHint(), diff --git a/java/src/com/android/intentresolver/v2/JavaFlowHelper.kt b/java/src/com/android/intentresolver/v2/JavaFlowHelper.kt new file mode 100644 index 00000000..c6c977f6 --- /dev/null +++ b/java/src/com/android/intentresolver/v2/JavaFlowHelper.kt @@ -0,0 +1,28 @@ +/* + * Copyright 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. + */ + +@file:JvmName("JavaFlowHelper") + +package com.android.intentresolver.v2 + +import java.util.function.Consumer +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.launch + +fun <T> collect(scope: CoroutineScope, flow: Flow<T>, collector: Consumer<T>): Job = + scope.launch { flow.collect { collector.accept(it) } } |