summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
author Android Build Coastguard Worker <android-build-coastguard-worker@google.com> 2024-06-15 21:22:58 +0000
committer Android Build Coastguard Worker <android-build-coastguard-worker@google.com> 2024-06-15 21:22:58 +0000
commit91615a2daee535144ae42fbe76356574bb9f6276 (patch)
treefa795a7da53691a21e9659d924de79a627ba8594 /java/src
parentebaed5c1bccae61032a6249453b91d28fd0d32a1 (diff)
parent468ae8749759dfdb58175e5ea431ca36a588876e (diff)
Snap for 11975806 from 468ae8749759dfdb58175e5ea431ca36a588876e to 24Q3-release
Change-Id: Id8df002a3225ffb562364ac360a3a4a083a7c953
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselComposable.kt10
-rw-r--r--java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselLazyListPrefetchStrategy.kt120
2 files changed, 129 insertions, 1 deletions
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 c63055d2..c40ed266 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
@@ -16,12 +16,14 @@
package com.android.intentresolver.contentpreview.payloadtoggle.ui.composable
import androidx.compose.animation.Crossfade
+import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
@@ -92,18 +94,24 @@ private fun Shareousel(viewModel: ShareouselViewModel, keySet: PreviewsModel) {
}
}
+@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun PreviewCarousel(
previews: PreviewsModel,
viewModel: ShareouselViewModel,
) {
val centerIdx = previews.startIdx
- val carouselState = rememberLazyListState(initialFirstVisibleItemIndex = centerIdx)
+ val carouselState =
+ rememberLazyListState(
+ initialFirstVisibleItemIndex = centerIdx,
+ prefetchStrategy = remember { ShareouselLazyListPrefetchStrategy() }
+ )
// TODO: start item needs to be centered, check out ScalingLazyColumn impl or see if
// HorizontalPager works for our use-case
LazyRow(
state = carouselState,
horizontalArrangement = Arrangement.spacedBy(4.dp),
+ contentPadding = PaddingValues(start = 16.dp, end = 16.dp),
modifier =
Modifier.fillMaxWidth()
.height(dimensionResource(R.dimen.chooser_preview_image_height_tall))
diff --git a/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselLazyListPrefetchStrategy.kt b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselLazyListPrefetchStrategy.kt
new file mode 100644
index 00000000..e47700f1
--- /dev/null
+++ b/java/src/com/android/intentresolver/contentpreview/payloadtoggle/ui/composable/ShareouselLazyListPrefetchStrategy.kt
@@ -0,0 +1,120 @@
+/*
+ * 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.contentpreview.payloadtoggle.ui.composable
+
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.lazy.LazyListItemInfo
+import androidx.compose.foundation.lazy.LazyListLayoutInfo
+import androidx.compose.foundation.lazy.LazyListPrefetchScope
+import androidx.compose.foundation.lazy.LazyListPrefetchStrategy
+import androidx.compose.foundation.lazy.layout.LazyLayoutPrefetchState
+import androidx.compose.foundation.lazy.layout.NestedPrefetchScope
+
+/** Prefetch strategy to fetch items ahead and behind the current scroll position. */
+@OptIn(ExperimentalFoundationApi::class)
+class ShareouselLazyListPrefetchStrategy(
+ private val lookAhead: Int = 4,
+ private val lookBackward: Int = 1
+) : LazyListPrefetchStrategy {
+ // Map of index -> prefetch handle
+ private val prefetchHandles: MutableMap<Int, LazyLayoutPrefetchState.PrefetchHandle> =
+ mutableMapOf()
+
+ private var prefetchRange = IntRange.EMPTY
+
+ private enum class ScrollDirection {
+ UNKNOWN, // The user hasn't scrolled in either direction yet.
+ FORWARD,
+ BACKWARD,
+ }
+
+ private var scrollDirection: ScrollDirection = ScrollDirection.UNKNOWN
+
+ override fun LazyListPrefetchScope.onScroll(delta: Float, layoutInfo: LazyListLayoutInfo) {
+ if (layoutInfo.visibleItemsInfo.isNotEmpty()) {
+ scrollDirection = if (delta < 0) ScrollDirection.FORWARD else ScrollDirection.BACKWARD
+ updatePrefetchSet(layoutInfo.visibleItemsInfo)
+ }
+
+ if (scrollDirection == ScrollDirection.FORWARD) {
+ val lastItem = layoutInfo.visibleItemsInfo.last()
+ val spacing = layoutInfo.mainAxisItemSpacing
+ val distanceToPrefetchItem =
+ lastItem.offset + lastItem.size + spacing - layoutInfo.viewportEndOffset
+ // if in the next frame we will get the same delta will we reach the item?
+ if (distanceToPrefetchItem < -delta) {
+ prefetchHandles.get(lastItem.index + 1)?.markAsUrgent()
+ }
+ } else {
+ val firstItem = layoutInfo.visibleItemsInfo.first()
+ val distanceToPrefetchItem = layoutInfo.viewportStartOffset - firstItem.offset
+ // if in the next frame we will get the same delta will we reach the item?
+ if (distanceToPrefetchItem < delta) {
+ prefetchHandles.get(firstItem.index - 1)?.markAsUrgent()
+ }
+ }
+ }
+
+ override fun LazyListPrefetchScope.onVisibleItemsUpdated(layoutInfo: LazyListLayoutInfo) {
+ if (layoutInfo.visibleItemsInfo.isNotEmpty()) {
+ updatePrefetchSet(layoutInfo.visibleItemsInfo)
+ }
+ }
+
+ override fun NestedPrefetchScope.onNestedPrefetch(firstVisibleItemIndex: Int) {}
+
+ private fun getVisibleRange(visibleItems: List<LazyListItemInfo>) =
+ if (visibleItems.isEmpty()) IntRange.EMPTY
+ else IntRange(visibleItems.first().index, visibleItems.last().index)
+
+ /** Update prefetchRange based upon the visible item range and scroll direction. */
+ private fun updatePrefetchRange(visibleRange: IntRange) {
+ prefetchRange =
+ when (scrollDirection) {
+ // Prefetch in both directions
+ ScrollDirection.UNKNOWN ->
+ visibleRange.first - lookAhead / 2..visibleRange.last + lookAhead / 2
+ ScrollDirection.FORWARD ->
+ visibleRange.first - lookBackward..visibleRange.last + lookAhead
+ ScrollDirection.BACKWARD ->
+ visibleRange.first - lookAhead..visibleRange.last + lookBackward
+ }
+ }
+
+ private fun LazyListPrefetchScope.updatePrefetchSet(visibleItems: List<LazyListItemInfo>) {
+ val visibleRange = getVisibleRange(visibleItems)
+ updatePrefetchRange(visibleRange)
+ updatePrefetchOperations(visibleRange)
+ }
+
+ private fun LazyListPrefetchScope.updatePrefetchOperations(visibleItemsRange: IntRange) {
+ // Remove any fetches outside of the prefetch range or inside the visible range
+ prefetchHandles
+ .filterKeys { it !in prefetchRange || it in visibleItemsRange }
+ .forEach {
+ it.value.cancel()
+ prefetchHandles.remove(it.key)
+ }
+
+ // Ensure all non-visible items in the range are being prefetched
+ prefetchRange.forEach {
+ if (it !in visibleItemsRange && !prefetchHandles.containsKey(it)) {
+ prefetchHandles[it] = schedulePrefetch(it)
+ }
+ }
+ }
+}