From cbf1fe64c45585866496ad74bcbbe31e04078dff Mon Sep 17 00:00:00 2001 From: HuanCheng65 <22636177+HuanCheng65@users.noreply.github.com> Date: Thu, 21 Sep 2023 16:10:27 +0800 Subject: [PATCH] =?UTF-8?q?pref:=20=E7=9C=8B=E5=9B=BE=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 1 - .../ui/page/photoview/PhotoViewActivity.kt | 119 +++++++----------- .../ui/page/photoview/PhotoViewViewModel.kt | 38 ++++-- app/src/main/res/values-v27/styles.xml | 12 ++ 4 files changed, 81 insertions(+), 89 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 03550b70..9874b4bc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -157,7 +157,6 @@ dependencies { implementation "io.github.panpf.sketch3:sketch-compose:$sketch_version" implementation "io.github.panpf.sketch3:sketch-extensions:$sketch_version" implementation "io.github.panpf.sketch3:sketch-gif-movie:$sketch_version" - implementation "io.github.panpf.sketch3:sketch-zoom:$sketch_version" implementation "io.github.panpf.sketch3:sketch-okhttp:$sketch_version" def zoomimage_version = "1.0.0-alpha03" diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/photoview/PhotoViewActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/photoview/PhotoViewActivity.kt index 31e6224a..97ee5cf5 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/photoview/PhotoViewActivity.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/photoview/PhotoViewActivity.kt @@ -29,22 +29,22 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.compose.ui.viewinterop.AndroidView -import com.github.panpf.sketch.displayImage -import com.github.panpf.sketch.zoom.Edge -import com.github.panpf.sketch.zoom.ReadModeDecider -import com.github.panpf.sketch.zoom.SketchZoomImageView +import com.github.panpf.sketch.request.DisplayRequest +import com.github.panpf.zoomimage.SketchZoomAsyncImage +import com.google.accompanist.systemuicontroller.SystemUiController import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.arch.BaseComposeActivityWithParcelable import com.huanchengfly.tieba.post.arch.collectPartialAsState @@ -56,65 +56,40 @@ import com.huanchengfly.tieba.post.ui.widgets.compose.LazyLoad import com.huanchengfly.tieba.post.ui.widgets.compose.ProvideContentColor import com.huanchengfly.tieba.post.utils.ImageUtil import com.huanchengfly.tieba.post.utils.download -import kotlinx.coroutines.launch -import kotlin.math.abs +import kotlinx.collections.immutable.persistentListOf import kotlin.math.roundToInt -object MyReadModeDecider : ReadModeDecider { - override fun should( - imageWidth: Int, - imageHeight: Int, - viewWidth: Int, - viewHeight: Int - ): Boolean { - val imageAspectRatio = imageHeight.toFloat() / imageWidth - val viewAspectRatio = viewHeight.toFloat() / viewWidth - return if (viewAspectRatio > 1f) { - imageAspectRatio >= viewAspectRatio * 1.25f - } else { - imageAspectRatio >= (1f / viewAspectRatio) * 3f - } - } -} - @Composable private fun ViewPhoto( imageUri: String, modifier: Modifier = Modifier, - onDrag: ((dx: Float, dy: Float, isAtEdge: Boolean) -> Unit)? = null + onTap: (offset: Offset) -> Unit = {}, ) { Box( modifier = modifier, contentAlignment = Alignment.Center ) { - var progress by remember { mutableStateOf(0f) } + val context = LocalContext.current + var progress by remember { mutableFloatStateOf(0f) } var showProgress by remember { mutableStateOf(true) } - AndroidView( - factory = { - SketchZoomImageView(it).apply { - readModeEnabled = true - readModeDecider = MyReadModeDecider - allowParentInterceptOnEdge = true - addOnViewDragListener { dx, dy -> - val isAtEdge = horScrollEdge != Edge.NONE - onDrag?.invoke(dx, dy, isAtEdge) - } + val request = remember(imageUri) { + DisplayRequest.Builder(context, imageUri) + .listener( + onStart = { showProgress = true }, + onSuccess = { _, _ -> showProgress = false }, + onError = { _, _ -> showProgress = false }, + onCancel = { showProgress = false } + ) + .progressListener { _, totalLength, completedLength -> + progress = completedLength.toFloat() / totalLength } - }, + .build() + } + SketchZoomAsyncImage( + request = request, + contentDescription = null, modifier = Modifier.fillMaxSize(), - update = { - it.displayImage(imageUri) { - listener( - onStart = { showProgress = true }, - onSuccess = { _, _ -> showProgress = false }, - onError = { _, _ -> showProgress = false }, - onCancel = { showProgress = false } - ) - progressListener { _, totalLength: Long, completedLength: Long -> - progress = (completedLength.toDouble() / totalLength).toFloat() - } - } - } + onTap = onTap, ) if (showProgress) { Box( @@ -150,7 +125,7 @@ class PhotoViewActivity : BaseComposeActivityWithParcelable() { } val items by viewModel.uiState.collectPartialAsState( prop1 = PhotoViewUiState::data, - initial = emptyList() + initial = persistentListOf() ) val initialIndex by viewModel.uiState.collectPartialAsState( prop1 = PhotoViewUiState::initialIndex, @@ -172,14 +147,17 @@ class PhotoViewActivity : BaseComposeActivityWithParcelable() { prop1 = PhotoViewUiState::loadPicPageData, initial = LoadPicPageData() ) + val pageCount by remember { derivedStateOf { items.size } } + + val pagerState = rememberPagerState(initialPage = initialIndex) { pageCount } + + LaunchedEffect(initialIndex) { + if (pagerState.currentPage != initialIndex) pagerState.scrollToPage(initialIndex) + } + Surface(color = Color.Black) { if (items.isNotEmpty()) { - val coroutineScope = rememberCoroutineScope() - val pagerState = rememberPagerState(initialPage = initialIndex) { pageCount } - LaunchedEffect(initialIndex) { - if (pagerState.currentPage != initialIndex) pagerState.scrollToPage(initialIndex) - } LaunchedEffect(pagerState.currentPage, pageCount, loadPicPageData) { loadPicPageData?.let { val item = items[pagerState.currentPage] @@ -205,30 +183,15 @@ class PhotoViewActivity : BaseComposeActivityWithParcelable() { Box(modifier = Modifier.fillMaxSize()) { HorizontalPager( state = pagerState, - key = { - "${items[it].overallIndex}" - } + key = { items[it].picId } ) { val item = items[it] ViewPhoto( imageUri = item.originUrl, modifier = Modifier.fillMaxSize(), - onDrag = { dx, dy, isAtEdge -> - val currentPage = pagerState.currentPage - if (abs(dy) < 15 && abs(dx) > 30 && isAtEdge) { - val prevPage = currentPage - 1 - val nextPage = currentPage + 1 - if (dx > 0 && prevPage >= 0) { - coroutineScope.launch { - pagerState.animateScrollToPage(prevPage) - } - } else if (dx < 0 && nextPage < items.size) { - coroutineScope.launch { - pagerState.animateScrollToPage(nextPage) - } - } - } - } + onTap = { + finish() + }, ) } Box( @@ -313,6 +276,10 @@ class PhotoViewActivity : BaseComposeActivityWithParcelable() { } } + override fun onCreateContent(systemUiController: SystemUiController) { + systemUiController.isSystemBarsVisible = false + } + override fun dispatchTouchEvent(ev: MotionEvent): Boolean { return try { super.dispatchTouchEvent(ev) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/photoview/PhotoViewViewModel.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/photoview/PhotoViewViewModel.kt index f1ccab3f..2d7952b9 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/photoview/PhotoViewViewModel.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/photoview/PhotoViewViewModel.kt @@ -10,6 +10,9 @@ import com.huanchengfly.tieba.post.arch.UiIntent import com.huanchengfly.tieba.post.arch.UiState import com.huanchengfly.tieba.post.models.protos.LoadPicPageData import com.huanchengfly.tieba.post.models.protos.PhotoViewData +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch @@ -62,6 +65,7 @@ class PhotoViewViewModel : val hasPrev = items.first().overallIndex > 1 PhotoViewPartialChange.LoadPrev.Success( hasPrev = hasPrev, + currentPicId = picId, items = items ) } @@ -159,12 +163,15 @@ class PhotoViewViewModel : val items = localItems + fetchedItems val hasNext = items.last().overallIndex < picAmount val hasPrev = items.first().overallIndex > 1 + val initialIndex = + items.indexOfFirst { it.picId == data.data_.picId }.takeIf { it != -1 } + ?: (data.data_.picIndex - 1) PhotoViewPartialChange.Init.Success( hasPrev = hasPrev, hasNext = hasNext, totalAmount = picAmount, items = items, - initialIndex = data.data_.picIndex - 1, + initialIndex = initialIndex, loadPicPageData = data.data_ ) } @@ -198,7 +205,7 @@ sealed interface PhotoViewPartialChange : PartialChange { override fun reduce(oldState: PhotoViewUiState): PhotoViewUiState = when (this) { is Success -> oldState.copy( - data = items, + data = items.toImmutableList(), hasNext = hasNext, hasPrev = hasPrev, totalAmount = totalAmount, @@ -216,7 +223,7 @@ sealed interface PhotoViewPartialChange : PartialChange { url = if (item.showOriginBtn) item.url else null, overallIndex = index + 1 ) - }, + }.toImmutableList(), hasNext = false, hasPrev = false, totalAmount = data.picItems.size, @@ -246,19 +253,26 @@ sealed interface PhotoViewPartialChange : PartialChange { when (this) { Start -> oldState.copy(isLoading = true) - is Success -> oldState.copy( - data = items.filterNot { item -> oldState.data.any { item.picId == it.picId } } + oldState.data, - hasPrev = hasPrev, - isLoading = false - ) + is Success -> { + val items = + (items.filterNot { item -> oldState.data.any { item.picId == it.picId } } + oldState.data).toImmutableList() + val newIndex = items.indexOfFirst { it.picId == currentPicId } + oldState.copy( + data = items, + hasPrev = hasPrev, + isLoading = false, + initialIndex = newIndex + ) + } is Failure -> oldState.copy(isLoading = false) } - object Start : LoadPrev() + data object Start : LoadPrev() data class Success( val items: List, + val currentPicId: String, val hasPrev: Boolean, ) : LoadPrev() @@ -273,7 +287,7 @@ sealed interface PhotoViewPartialChange : PartialChange { Start -> oldState.copy(isLoading = true) is Success -> oldState.copy( - data = oldState.data + items.filterNot { item -> oldState.data.any { item.picId == it.picId } }, + data = (oldState.data + items.filterNot { item -> oldState.data.any { item.picId == it.picId } }).toImmutableList(), hasNext = hasNext, isLoading = false ) @@ -281,7 +295,7 @@ sealed interface PhotoViewPartialChange : PartialChange { is Failure -> oldState.copy(isLoading = false) } - object Start : LoadMore() + data object Start : LoadMore() data class Success( val items: List, @@ -296,7 +310,7 @@ sealed interface PhotoViewPartialChange : PartialChange { data class PhotoViewUiState( val isLoading: Boolean = false, - val data: List = emptyList(), + val data: ImmutableList = persistentListOf(), val totalAmount: Int = 0, val hasNext: Boolean = false, val hasPrev: Boolean = false, diff --git a/app/src/main/res/values-v27/styles.xml b/app/src/main/res/values-v27/styles.xml index fa732742..075f601b 100644 --- a/app/src/main/res/values-v27/styles.xml +++ b/app/src/main/res/values-v27/styles.xml @@ -24,4 +24,16 @@ ?colorNavBar true + + \ No newline at end of file