From 7925c36f07ef75586e2eec49e1f725280a555726 Mon Sep 17 00:00:00 2001 From: HuanCheng65 <22636177+HuanCheng65@users.noreply.github.com> Date: Sun, 23 Jul 2023 23:00:06 +0800 Subject: [PATCH] =?UTF-8?q?pref:=20=E5=8A=A0=E8=BD=BD=E6=9B=B4=E5=A4=9A?= =?UTF-8?q?=E9=98=B2=E6=8A=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tieba/post/ui/widgets/compose/LoadMore.kt | 63 ++++++++++++++++--- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/LoadMore.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/LoadMore.kt index 6b275848..15bd5f33 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/LoadMore.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/LoadMore.kt @@ -2,15 +2,30 @@ package com.huanchengfly.tieba.post.ui.widgets.compose import androidx.compose.animation.animateContentSize import androidx.compose.foundation.gestures.Orientation -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.* +import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.FractionalThreshold +import androidx.compose.material.Surface +import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment @@ -27,12 +42,17 @@ import androidx.compose.ui.unit.dp import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme import com.huanchengfly.tieba.post.ui.common.theme.compose.loadMoreIndicator +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.sample +import kotlinx.coroutines.launch import kotlin.math.abs import kotlin.math.roundToInt private val LoadDistance = 70.dp -@OptIn(ExperimentalMaterialApi::class) +@OptIn(ExperimentalMaterialApi::class, FlowPreview::class) @Composable fun LoadMoreLayout( isLoading: Boolean, @@ -50,17 +70,42 @@ fun LoadMoreLayout( ) { val loadDistance = with(LocalDensity.current) { LoadDistance.toPx() } + val curOnLoadMore by rememberUpdatedState(newValue = onLoadMore) + var lastTriggerTime by remember { mutableStateOf(0L) } + var waitingStateReset by remember { mutableStateOf(false) } + val loadMoreFlow = remember { + MutableSharedFlow( + extraBufferCapacity = 1, + onBufferOverflow = BufferOverflow.DROP_LATEST + ) + } + val coroutineScope = rememberCoroutineScope() + DisposableEffect(Unit) { + val job = coroutineScope.launch { + loadMoreFlow + .sample(500) + .collect { + curOnLoadMore() + waitingStateReset = true + lastTriggerTime = it + } + } + + onDispose { job.cancel() } + } + val canLoadMore = remember(enableLoadMore, loadEnd) { enableLoadMore && !loadEnd } val curIsLoading by rememberUpdatedState(newValue = isLoading) val curCanLoadMore by rememberUpdatedState(newValue = canLoadMore) - var waitingStateReset by remember { mutableStateOf(false) } val swipeableState = rememberSwipeableState(false) { newValue -> if (newValue && !curIsLoading && curCanLoadMore) { - onLoadMore() - waitingStateReset = true - true + val curTime = System.currentTimeMillis() + coroutineScope.launch { + loadMoreFlow.emit(curTime) + } + curTime - lastTriggerTime >= 500 } else !newValue } @@ -71,6 +116,8 @@ fun LoadMoreLayout( } } + LaunchedEffect(isLoading) { swipeableState.animateTo(isLoading) } + Box( modifier = Modifier .nestedScroll(swipeableState.LoadPreUpPostDownNestedScrollConnection) @@ -96,8 +143,6 @@ fun LoadMoreLayout( indicator(isLoading, loadEnd, swipeableState.targetValue) } } - - LaunchedEffect(isLoading) { swipeableState.animateTo(isLoading) } } }