summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/res/values-it/strings.xml9
-rw-r--r--java/res/values-sq/strings.xml9
-rw-r--r--java/src/com/android/intentresolver/ChooserActionFactory.java14
-rw-r--r--java/src/com/android/intentresolver/ChooserActivity.java3
-rw-r--r--java/src/com/android/intentresolver/ChooserListAdapter.java14
-rw-r--r--java/src/com/android/intentresolver/contentpreview/CachingImagePreviewImageLoader.kt5
-rw-r--r--java/src/com/android/intentresolver/contentpreview/ImageLoader.kt3
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselComposable.kt78
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselPreviewViewModel.kt4
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselViewModel.kt19
-rw-r--r--java/src/com/android/intentresolver/icons/CachingTargetDataLoader.kt36
-rw-r--r--java/src/com/android/intentresolver/icons/DefaultTargetDataLoader.kt5
-rw-r--r--java/src/com/android/intentresolver/icons/LoadDirectShareIconTask.java5
-rw-r--r--java/src/com/android/intentresolver/icons/TargetDataLoader.kt4
-rw-r--r--java/src/com/android/intentresolver/widget/ViewExtensions.kt7
15 files changed, 149 insertions, 66 deletions
diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml
index 277d03d9..75fe0b77 100644
--- a/java/res/values-it/strings.xml
+++ b/java/res/values-it/strings.xml
@@ -102,10 +102,7 @@
<string name="exclude_link" msgid="1332778255031992228">"Escludi link"</string>
<string name="include_link" msgid="827855767220339802">"Includi link"</string>
<string name="pinned" msgid="7623664001331394139">"Elemento fissato"</string>
- <!-- no translation found for selectable_image (3157858923437182271) -->
- <skip />
- <!-- no translation found for selectable_video (1271768647699300826) -->
- <skip />
- <!-- no translation found for selectable_item (7557320816744205280) -->
- <skip />
+ <string name="selectable_image" msgid="3157858923437182271">"Immagine selezionabile"</string>
+ <string name="selectable_video" msgid="1271768647699300826">"Video selezionabile"</string>
+ <string name="selectable_item" msgid="7557320816744205280">"Elemento selezionabile"</string>
</resources>
diff --git a/java/res/values-sq/strings.xml b/java/res/values-sq/strings.xml
index dc4257b2..faf27da5 100644
--- a/java/res/values-sq/strings.xml
+++ b/java/res/values-sq/strings.xml
@@ -102,10 +102,7 @@
<string name="exclude_link" msgid="1332778255031992228">"Përjashto lidhjen"</string>
<string name="include_link" msgid="827855767220339802">"Përfshi lidhjen"</string>
<string name="pinned" msgid="7623664001331394139">"U gozhdua"</string>
- <!-- no translation found for selectable_image (3157858923437182271) -->
- <skip />
- <!-- no translation found for selectable_video (1271768647699300826) -->
- <skip />
- <!-- no translation found for selectable_item (7557320816744205280) -->
- <skip />
+ <string name="selectable_image" msgid="3157858923437182271">"Imazh që mund të zgjidhet"</string>
+ <string name="selectable_video" msgid="1271768647699300826">"Video që mund të zgjidhet"</string>
+ <string name="selectable_item" msgid="7557320816744205280">"Artikull që mund të zgjidhet"</string>
</resources>
diff --git a/java/src/com/android/intentresolver/ChooserActionFactory.java b/java/src/com/android/intentresolver/ChooserActionFactory.java
index dae1ab52..cc7091e4 100644
--- a/java/src/com/android/intentresolver/ChooserActionFactory.java
+++ b/java/src/com/android/intentresolver/ChooserActionFactory.java
@@ -16,6 +16,8 @@
package com.android.intentresolver;
+import static com.android.intentresolver.widget.ViewExtensionsKt.isFullyVisible;
+
import android.app.Activity;
import android.app.ActivityOptions;
import android.app.PendingIntent;
@@ -131,7 +133,8 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio
ActionActivityStarter activityStarter,
@Nullable ShareResultSender shareResultSender,
Consumer</* @Nullable */ Integer> finishCallback,
- ClipboardManager clipboardManager) {
+ ClipboardManager clipboardManager,
+ FeatureFlags featureFlags) {
this(
context,
makeCopyButtonRunnable(
@@ -147,7 +150,8 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio
imageEditor),
firstVisibleImageQuery,
activityStarter,
- log),
+ log,
+ featureFlags.fixPartialImageEditTransition()),
chooserActions,
onUpdateSharedTextIsExcluded,
log,
@@ -336,7 +340,8 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio
@Nullable TargetInfo editSharingTarget,
Callable</* @Nullable */ View> firstVisibleImageQuery,
ActionActivityStarter activityStarter,
- EventLog log) {
+ EventLog log,
+ boolean requireFullVisibility) {
if (editSharingTarget == null) return null;
return () -> {
// Log share completion via edit.
@@ -347,7 +352,8 @@ public final class ChooserActionFactory implements ChooserContentPreviewUi.Actio
firstImageView = firstVisibleImageQuery.call();
} catch (Exception e) { /* ignore */ }
// Action bar is user-independent; always start as primary.
- if (firstImageView == null) {
+ if (firstImageView == null
+ || (requireFullVisibility && !isFullyVisible(firstImageView))) {
activityStarter.safelyStartActivityAsPersonalProfileUser(editSharingTarget);
} else {
activityStarter.safelyStartActivityAsPersonalProfileUserWithSharedElementTransition(
diff --git a/java/src/com/android/intentresolver/ChooserActivity.java b/java/src/com/android/intentresolver/ChooserActivity.java
index 7353ff37..670512ac 100644
--- a/java/src/com/android/intentresolver/ChooserActivity.java
+++ b/java/src/com/android/intentresolver/ChooserActivity.java
@@ -2212,7 +2212,8 @@ public class ChooserActivity extends Hilt_ChooserActivity implements
},
mShareResultSender,
this::finishWithStatus,
- mClipboardManager);
+ mClipboardManager,
+ mFeatureFlags);
}
private Supplier<ActionRow.Action> createModifyShareActionFactory() {
diff --git a/java/src/com/android/intentresolver/ChooserListAdapter.java b/java/src/com/android/intentresolver/ChooserListAdapter.java
index 8b848e55..ff0c40d7 100644
--- a/java/src/com/android/intentresolver/ChooserListAdapter.java
+++ b/java/src/com/android/intentresolver/ChooserListAdapter.java
@@ -479,17 +479,23 @@ public class ChooserListAdapter extends ResolverListAdapter {
private void loadDirectShareIcon(SelectableTargetInfo info) {
if (mRequestedIcons.add(info)) {
- mTargetDataLoader.loadDirectShareIcon(
+ Drawable icon = mTargetDataLoader.getOrLoadDirectShareIcon(
info,
getUserHandle(),
- (drawable) -> onDirectShareIconLoaded(info, drawable));
+ (drawable) -> onDirectShareIconLoaded(info, drawable, true));
+ if (icon != null) {
+ onDirectShareIconLoaded(info, icon, false);
+ }
}
}
- private void onDirectShareIconLoaded(SelectableTargetInfo mTargetInfo, Drawable icon) {
+ private void onDirectShareIconLoaded(
+ SelectableTargetInfo mTargetInfo, @Nullable Drawable icon, boolean notify) {
if (icon != null && !mTargetInfo.hasDisplayIcon()) {
mTargetInfo.getDisplayIconHolder().setDisplayIcon(icon);
- notifyDataSetChanged();
+ if (notify) {
+ notifyDataSetChanged();
+ }
}
}
diff --git a/java/src/com/android/intentresolver/contentpreview/CachingImagePreviewImageLoader.kt b/java/src/com/android/intentresolver/contentpreview/CachingImagePreviewImageLoader.kt
index ce064cdf..2e2aa938 100644
--- a/java/src/com/android/intentresolver/contentpreview/CachingImagePreviewImageLoader.kt
+++ b/java/src/com/android/intentresolver/contentpreview/CachingImagePreviewImageLoader.kt
@@ -28,6 +28,7 @@ import javax.inject.Qualifier
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch
@@ -104,6 +105,10 @@ constructor(
// [CancellationExceptions]s so that they don't cancel the calling coroutine/scope.
runCatching { cache[uri].await() }.getOrNull()
+ @OptIn(ExperimentalCoroutinesApi::class)
+ override fun getCachedBitmap(uri: Uri): Bitmap? =
+ kotlin.runCatching { cache[uri].getCompleted() }.getOrNull()
+
companion object {
private const val TAG = "CachingImgPrevLoader"
}
diff --git a/java/src/com/android/intentresolver/contentpreview/ImageLoader.kt b/java/src/com/android/intentresolver/contentpreview/ImageLoader.kt
index 629651a3..81913a8e 100644
--- a/java/src/com/android/intentresolver/contentpreview/ImageLoader.kt
+++ b/java/src/com/android/intentresolver/contentpreview/ImageLoader.kt
@@ -35,6 +35,9 @@ interface ImageLoader : suspend (Uri) -> Bitmap?, suspend (Uri, Boolean) -> Bitm
/** Prepopulate the image loader cache. */
fun prePopulate(uris: List<Uri>)
+ /** Returns a bitmap for the given URI if it's already cached, otherwise null */
+ fun getCachedBitmap(uri: Uri): Bitmap? = null
+
/** Load preview image; caching is allowed. */
override suspend fun invoke(uri: Uri) = invoke(uri, true)
diff --git a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselComposable.kt b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselComposable.kt
index 8e2626bf..c63055d2 100644
--- a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselComposable.kt
+++ b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselComposable.kt
@@ -15,6 +15,7 @@
*/
package com.android.intentresolver.contentpreview.payloadtoggle.ui.composable
+import androidx.compose.animation.Crossfade
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@@ -57,6 +58,8 @@ import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.intentresolver.R
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ValueUpdate
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.getOrDefault
import com.android.intentresolver.contentpreview.payloadtoggle.shared.ContentType
import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewsModel
import com.android.intentresolver.contentpreview.payloadtoggle.ui.viewmodel.ShareouselPreviewViewModel
@@ -124,14 +127,14 @@ private fun PreviewCarousel(
}
}
- ShareouselCard(viewModel.preview(model, previewIndex))
+ ShareouselCard(viewModel.preview(model, previewIndex, rememberCoroutineScope()))
}
}
}
@Composable
private fun ShareouselCard(viewModel: ShareouselPreviewViewModel) {
- val bitmap by viewModel.bitmap.collectAsStateWithLifecycle(initialValue = null)
+ val bitmapLoadState by viewModel.bitmapLoadState.collectAsStateWithLifecycle()
val selected by viewModel.isSelected.collectAsStateWithLifecycle(initialValue = false)
val borderColor = MaterialTheme.colorScheme.primary
val scope = rememberCoroutineScope()
@@ -141,39 +144,56 @@ private fun ShareouselCard(viewModel: ShareouselPreviewViewModel) {
ContentType.Video -> stringResource(R.string.selectable_video)
else -> stringResource(R.string.selectable_item)
}
- ShareouselCard(
- image = {
- // TODO: max ratio is actually equal to the viewport ratio
- val aspectRatio = viewModel.aspectRatio.coerceIn(MIN_ASPECT_RATIO, MAX_ASPECT_RATIO)
- bitmap?.let { bitmap ->
- Image(
- bitmap = bitmap.asImageBitmap(),
- contentDescription = null,
- contentScale = ContentScale.Crop,
- modifier = Modifier.aspectRatio(aspectRatio),
- )
- }
- ?: run {
- // TODO: look at ScrollableImagePreviewView.setLoading()
- Box(modifier = Modifier.fillMaxHeight().aspectRatio(aspectRatio))
- }
- },
- contentType = viewModel.contentType,
- selected = selected,
+ Crossfade(
+ targetState = bitmapLoadState,
modifier =
- Modifier.thenIf(selected) {
- Modifier.border(
- width = 4.dp,
- color = borderColor,
- shape = RoundedCornerShape(size = 12.dp),
- )
- }
- .semantics { this.contentDescription = contentDescription }
+ Modifier.semantics { this.contentDescription = contentDescription }
.clip(RoundedCornerShape(size = 12.dp))
.toggleable(
value = selected,
onValueChange = { scope.launch { viewModel.setSelected(it) } },
)
+ ) { state ->
+ // TODO: max ratio is actually equal to the viewport ratio
+ val aspectRatio = viewModel.aspectRatio.coerceIn(MIN_ASPECT_RATIO, MAX_ASPECT_RATIO)
+ if (state is ValueUpdate.Value) {
+ state.getOrDefault(null).let { bitmap ->
+ ShareouselCard(
+ image = {
+ bitmap?.let {
+ Image(
+ bitmap = bitmap.asImageBitmap(),
+ contentDescription = null,
+ contentScale = ContentScale.Crop,
+ modifier = Modifier.aspectRatio(aspectRatio),
+ )
+ } ?: PlaceholderBox(aspectRatio)
+ },
+ contentType = viewModel.contentType,
+ selected = selected,
+ modifier =
+ Modifier.thenIf(selected) {
+ Modifier.border(
+ width = 4.dp,
+ color = borderColor,
+ shape = RoundedCornerShape(size = 12.dp),
+ )
+ }
+ )
+ }
+ } else {
+ PlaceholderBox(aspectRatio)
+ }
+ }
+}
+
+@Composable
+private fun PlaceholderBox(aspectRatio: Float) {
+ Box(
+ modifier =
+ Modifier.fillMaxHeight()
+ .aspectRatio(aspectRatio)
+ .background(color = MaterialTheme.colorScheme.surfaceContainerHigh)
)
}
diff --git a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselPreviewViewModel.kt b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselPreviewViewModel.kt
index 540229c9..de435290 100644
--- a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselPreviewViewModel.kt
+++ b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselPreviewViewModel.kt
@@ -17,13 +17,15 @@
package com.android.intentresolver.contentpreview.payloadtoggle.ui.viewmodel
import android.graphics.Bitmap
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ValueUpdate
import com.android.intentresolver.contentpreview.payloadtoggle.shared.ContentType
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
/** An individual preview within Shareousel. */
data class ShareouselPreviewViewModel(
/** Image to be shared. */
- val bitmap: Flow<Bitmap?>,
+ val bitmapLoadState: StateFlow<ValueUpdate<Bitmap?>>,
/** Type of data to be shared. */
val contentType: ContentType,
/** Whether this preview has been selected by the user. */
diff --git a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselViewModel.kt b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselViewModel.kt
index c3ad7b6c..d0b89860 100644
--- a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselViewModel.kt
+++ b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/viewmodel/ShareouselViewModel.kt
@@ -24,6 +24,7 @@ import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor
import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.CustomActionsInteractor
import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.SelectablePreviewsInteractor
import com.android.intentresolver.contentpreview.payloadtoggle.domain.interactor.SelectionInteractor
+import com.android.intentresolver.contentpreview.payloadtoggle.domain.model.ValueUpdate
import com.android.intentresolver.contentpreview.payloadtoggle.shared.ContentType
import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewModel
import com.android.intentresolver.contentpreview.payloadtoggle.shared.model.PreviewsModel
@@ -55,7 +56,8 @@ data class ShareouselViewModel(
/** List of action chips presented underneath Shareousel. */
val actions: Flow<List<ActionChipViewModel>>,
/** Creates a [ShareouselPreviewViewModel] for a [PreviewModel] present in [previews]. */
- val preview: (key: PreviewModel, index: Int?) -> ShareouselPreviewViewModel,
+ val preview:
+ (key: PreviewModel, index: Int?, scope: CoroutineScope) -> ShareouselPreviewViewModel,
)
@Module
@@ -112,7 +114,7 @@ interface ShareouselViewModelModule {
}
}
},
- preview = { key, index ->
+ preview = { key, index, previewScope ->
keySet.value?.maybeLoad(index)
val previewInteractor = interactor.preview(key)
val contentType =
@@ -121,8 +123,19 @@ interface ShareouselViewModelModule {
mimeTypeClassifier.isVideoType(key.mimeType) -> ContentType.Video
else -> ContentType.Other
}
+ val initialBitmapValue =
+ key.previewUri?.let {
+ imageLoader.getCachedBitmap(it)?.let { ValueUpdate.Value(it) }
+ } ?: ValueUpdate.Absent
ShareouselPreviewViewModel(
- bitmap = flow { emit(key.previewUri?.let { imageLoader(it) }) },
+ bitmapLoadState =
+ flow {
+ emit(
+ key.previewUri?.let { ValueUpdate.Value(imageLoader(it)) }
+ ?: ValueUpdate.Absent
+ )
+ }
+ .stateIn(previewScope, SharingStarted.Eagerly, initialBitmapValue),
contentType = contentType,
isSelected = previewInteractor.isSelected,
setSelected = previewInteractor::setSelected,
diff --git a/java/src/com/android/intentresolver/icons/CachingTargetDataLoader.kt b/java/src/com/android/intentresolver/icons/CachingTargetDataLoader.kt
index b3054231..8474b4c3 100644
--- a/java/src/com/android/intentresolver/icons/CachingTargetDataLoader.kt
+++ b/java/src/com/android/intentresolver/icons/CachingTargetDataLoader.kt
@@ -28,7 +28,7 @@ import javax.inject.Qualifier
@Qualifier @MustBeDocumented @Retention(AnnotationRetention.BINARY) annotation class Caching
-private typealias IconCache = LruCache<ComponentName, Drawable>
+private typealias IconCache = LruCache<String, Drawable>
class CachingTargetDataLoader(
private val targetDataLoader: TargetDataLoader,
@@ -49,18 +49,27 @@ class CachingTargetDataLoader(
}
}
- override fun loadDirectShareIcon(
+ override fun getOrLoadDirectShareIcon(
info: SelectableTargetInfo,
userHandle: UserHandle,
callback: Consumer<Drawable>
- ) = targetDataLoader.loadDirectShareIcon(info, userHandle, callback)
+ ): Drawable? {
+ val cacheKey = info.toCacheKey()
+ return cacheKey?.let { getCachedAppIcon(it, userHandle) }
+ ?: targetDataLoader.getOrLoadDirectShareIcon(info, userHandle) { drawable ->
+ if (cacheKey != null) {
+ getProfileIconCache(userHandle).put(cacheKey, drawable)
+ }
+ callback.accept(drawable)
+ }
+ }
override fun loadLabel(info: DisplayResolveInfo, callback: Consumer<LabelInfo>) =
targetDataLoader.loadLabel(info, callback)
override fun getOrLoadLabel(info: DisplayResolveInfo) = targetDataLoader.getOrLoadLabel(info)
- private fun getCachedAppIcon(component: ComponentName, userHandle: UserHandle): Drawable? =
+ private fun getCachedAppIcon(component: String, userHandle: UserHandle): Drawable? =
getProfileIconCache(userHandle)[component]
private fun getProfileIconCache(userHandle: UserHandle): IconCache =
@@ -70,7 +79,20 @@ class CachingTargetDataLoader(
private fun DisplayResolveInfo.toCacheKey() =
ComponentName(
- resolveInfo.activityInfo.packageName,
- resolveInfo.activityInfo.name,
- )
+ resolveInfo.activityInfo.packageName,
+ resolveInfo.activityInfo.name,
+ )
+ .flattenToString()
+
+ private fun SelectableTargetInfo.toCacheKey(): String? =
+ if (chooserTargetIcon != null) {
+ // do not cache icons for caller-provided targets
+ null
+ } else {
+ buildString {
+ append(chooserTargetComponentName?.flattenToString() ?: "")
+ append("|")
+ append(directShareShortcutInfo?.id ?: "")
+ }
+ }
}
diff --git a/java/src/com/android/intentresolver/icons/DefaultTargetDataLoader.kt b/java/src/com/android/intentresolver/icons/DefaultTargetDataLoader.kt
index 1a724d73..e7392f58 100644
--- a/java/src/com/android/intentresolver/icons/DefaultTargetDataLoader.kt
+++ b/java/src/com/android/intentresolver/icons/DefaultTargetDataLoader.kt
@@ -77,11 +77,11 @@ class DefaultTargetDataLoader(
return null
}
- override fun loadDirectShareIcon(
+ override fun getOrLoadDirectShareIcon(
info: SelectableTargetInfo,
userHandle: UserHandle,
callback: Consumer<Drawable>,
- ) {
+ ): Drawable? {
val taskId = nextTaskId.getAndIncrement()
LoadDirectShareIconTask(
context.createContextAsUser(userHandle, 0),
@@ -93,6 +93,7 @@ class DefaultTargetDataLoader(
}
.also { addTask(taskId, it) }
.executeOnExecutor(executor)
+ return null
}
override fun loadLabel(info: DisplayResolveInfo, callback: Consumer<LabelInfo>) {
diff --git a/java/src/com/android/intentresolver/icons/LoadDirectShareIconTask.java b/java/src/com/android/intentresolver/icons/LoadDirectShareIconTask.java
index 0f135d63..e2c0362d 100644
--- a/java/src/com/android/intentresolver/icons/LoadDirectShareIconTask.java
+++ b/java/src/com/android/intentresolver/icons/LoadDirectShareIconTask.java
@@ -57,7 +57,7 @@ class LoadDirectShareIconTask extends BaseLoadIconTask {
@Override
protected Drawable doInBackground(Void... voids) {
- Drawable drawable;
+ Drawable drawable = null;
Trace.beginSection("shortcut-icon");
try {
final Icon icon = mTargetInfo.getChooserTargetIcon();
@@ -70,6 +70,8 @@ class LoadDirectShareIconTask extends BaseLoadIconTask {
} else {
Log.e(TAG, "Failed to load shortcut icon for "
+ mTargetInfo.getChooserTargetComponentName() + "; no access");
+ }
+ if (drawable == null) {
drawable = loadIconPlaceholder();
}
} catch (Exception e) {
@@ -86,6 +88,7 @@ class LoadDirectShareIconTask extends BaseLoadIconTask {
}
@WorkerThread
+ @Nullable
private Drawable getChooserTargetIconDrawable(
Context context,
@Nullable Icon icon,
diff --git a/java/src/com/android/intentresolver/icons/TargetDataLoader.kt b/java/src/com/android/intentresolver/icons/TargetDataLoader.kt
index 7789df44..935b527a 100644
--- a/java/src/com/android/intentresolver/icons/TargetDataLoader.kt
+++ b/java/src/com/android/intentresolver/icons/TargetDataLoader.kt
@@ -32,11 +32,11 @@ abstract class TargetDataLoader {
): Drawable?
/** Load a shortcut icon */
- abstract fun loadDirectShareIcon(
+ abstract fun getOrLoadDirectShareIcon(
info: SelectableTargetInfo,
userHandle: UserHandle,
callback: Consumer<Drawable>,
- )
+ ): Drawable?
/** Load target label */
abstract fun loadLabel(info: DisplayResolveInfo, callback: Consumer<LabelInfo>)
diff --git a/java/src/com/android/intentresolver/widget/ViewExtensions.kt b/java/src/com/android/intentresolver/widget/ViewExtensions.kt
index d19933f5..64aa9352 100644
--- a/java/src/com/android/intentresolver/widget/ViewExtensions.kt
+++ b/java/src/com/android/intentresolver/widget/ViewExtensions.kt
@@ -16,6 +16,7 @@
package com.android.intentresolver.widget
+import android.graphics.Rect
import android.util.Log
import android.view.View
import androidx.core.view.OneShotPreDrawListener
@@ -42,3 +43,9 @@ internal suspend fun View.waitForPreDraw(): Unit = suspendCancellableCoroutine {
)
continuation.invokeOnCancellation { callback.removeListener() }
}
+
+internal fun View.isFullyVisible(): Boolean {
+ val rect = Rect()
+ val isVisible = getLocalVisibleRect(rect)
+ return isVisible && rect.width() == width && rect.height() == height
+}