Feat(ToolStore): Support pull down to refresh

This commit is contained in:
2024-08-26 14:55:04 +08:00
parent 402965503f
commit e9232631de
2 changed files with 31 additions and 147 deletions

View File

@@ -1,114 +0,0 @@
package top.fatweb.oxygen.toolbox.icon
import androidx.compose.foundation.Image
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathFillType
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.StrokeJoin
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.path
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@Preview
@Composable
private fun VectorPreview() {
Image(Loading, null)
}
val Loading: ImageVector
get() = ImageVector.Builder(
name = "Loading",
defaultWidth = 1024.dp,
defaultHeight = 1024.dp,
viewportWidth = 1024f,
viewportHeight = 1024f
).apply {
path(
fill = SolidColor(Color.Black),
fillAlpha = 1.0f,
stroke = null,
strokeAlpha = 1.0f,
strokeLineWidth = 1.0f,
strokeLineCap = StrokeCap.Butt,
strokeLineJoin = StrokeJoin.Miter,
strokeLineMiter = 1.0f,
pathFillType = PathFillType.NonZero
) {
moveTo(x = 988f, y = 548f)
curveToRelative(
dx1 = -19.9f,
dy1 = 0f,
dx2 = -36f,
dy2 = -16.1f,
dx3 = -36f,
dy3 = -36f
)
curveToRelative(
dx1 = 0f,
dy1 = -59.4f,
dx2 = -11.6f,
dy2 = -117f,
dx3 = -34.6f,
dy3 = -171.3f
)
arcToRelative(
a = 440.45f,
b = 440.45f,
theta = 0f,
isMoreThanHalf = false,
isPositiveArc = false,
dx1 = -94.3f,
dy1 = -139.9f
)
arcToRelative(
a = 437.71f,
b = 437.71f,
theta = 0f,
isMoreThanHalf = false,
isPositiveArc = false,
dx1 = -139.9f,
dy1 = -94.3f
)
curveTo(x1 = 629f, y1 = 83.6f, x2 = 571.4f, y2 = 72f, x3 = 512f, y3 = 72f)
curveToRelative(
dx1 = -19.9f,
dy1 = 0f,
dx2 = -36f,
dy2 = -16.1f,
dx3 = -36f,
dy3 = -36f
)
reflectiveCurveToRelative(dx1 = 16.1f, dy1 = -36f, dx2 = 36f, dy2 = -36f)
curveToRelative(
dx1 = 69.1f,
dy1 = 0f,
dx2 = 136.2f,
dy2 = 13.5f,
dx3 = 199.3f,
dy3 = 40.3f
)
curveTo(x1 = 772.3f, y1 = 66f, x2 = 827f, y2 = 103f, x3 = 874f, y3 = 150f)
curveToRelative(
dx1 = 47f,
dy1 = 47f,
dx2 = 83.9f,
dy2 = 101.8f,
dx3 = 109.7f,
dy3 = 162.7f
)
curveToRelative(
dx1 = 26.7f,
dy1 = 63.1f,
dx2 = 40.2f,
dy2 = 130.2f,
dx3 = 40.2f,
dy3 = 199.3f
)
curveToRelative(dx1 = 0.1f, dy1 = 19.9f, dx2 = -16f, dy2 = 36f, dx3 = -35.9f, dy3 = 36f)
close()
}
}.build()

View File

@@ -1,11 +1,6 @@
package top.fatweb.oxygen.toolbox.ui.store package top.fatweb.oxygen.toolbox.ui.store
import androidx.activity.compose.ReportDrawnWhen import androidx.activity.compose.ReportDrawnWhen
import androidx.compose.animation.core.Ease
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -20,7 +15,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.systemBars import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.windowInsetsBottomHeight import androidx.compose.foundation.layout.windowInsetsBottomHeight
@@ -31,11 +25,16 @@ import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridItemSpan import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridItemSpan
import androidx.compose.foundation.lazy.staggeredgrid.items import androidx.compose.foundation.lazy.staggeredgrid.items
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.material3.pulltorefresh.PullToRefreshContainer
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
@@ -45,7 +44,8 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
@@ -53,7 +53,6 @@ import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems
import top.fatweb.oxygen.toolbox.R import top.fatweb.oxygen.toolbox.R
import top.fatweb.oxygen.toolbox.icon.Loading
import top.fatweb.oxygen.toolbox.icon.OxygenIcons import top.fatweb.oxygen.toolbox.icon.OxygenIcons
import top.fatweb.oxygen.toolbox.model.tool.ToolEntity import top.fatweb.oxygen.toolbox.model.tool.ToolEntity
import top.fatweb.oxygen.toolbox.ui.component.ToolCard import top.fatweb.oxygen.toolbox.ui.component.ToolCard
@@ -90,6 +89,7 @@ internal fun ToolStoreRoute(
) )
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
internal fun ToolStoreScreen( internal fun ToolStoreScreen(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@@ -107,13 +107,25 @@ internal fun ToolStoreScreen(
ReportDrawnWhen { !isToolLoading } ReportDrawnWhen { !isToolLoading }
val pullToRefreshState = rememberPullToRefreshState()
LaunchedEffect(pullToRefreshState.isRefreshing) {
if (pullToRefreshState.isRefreshing) {
toolStorePagingItems.refresh()
}
}
LaunchedEffect(toolStorePagingItems.loadState.refresh) {
if (toolStorePagingItems.loadState.refresh is LoadState.Loading) {
pullToRefreshState.startRefresh()
} else {
pullToRefreshState.endRefresh()
}
}
val itemsAvailable = toolStorePagingItems.itemCount val itemsAvailable = toolStorePagingItems.itemCount
val state = rememberLazyStaggeredGridState() val state = rememberLazyStaggeredGridState()
val scrollbarState = state.scrollbarState(itemsAvailable = itemsAvailable) val scrollbarState = state.scrollbarState(itemsAvailable = itemsAvailable)
val infiniteTransition = rememberInfiniteTransition(label = "infiniteTransition")
var installTool by remember { var installTool by remember {
mutableStateOf( mutableStateOf(
ToolEntity( ToolEntity(
@@ -125,7 +137,10 @@ internal fun ToolStoreScreen(
} }
Box( Box(
modifier.fillMaxSize() modifier
.fillMaxSize()
.clipToBounds()
.nestedScroll(pullToRefreshState.nestedScrollConnection)
) { ) {
LazyVerticalStaggeredGrid( LazyVerticalStaggeredGrid(
modifier = Modifier modifier = Modifier
@@ -154,28 +169,11 @@ internal fun ToolStoreScreen(
} }
} }
if (toolStorePagingItems.loadState.refresh is LoadState.Loading) { PullToRefreshContainer(
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
val angle by infiniteTransition.animateFloat(
initialValue = 0F,
targetValue = 360F,
animationSpec = infiniteRepeatable(
animation = tween(durationMillis = 800, easing = Ease),
), label = "angle"
)
Icon(
modifier = Modifier modifier = Modifier
.size(32.dp) .align(Alignment.TopCenter),
.graphicsLayer { rotationZ = angle }, state = pullToRefreshState,
imageVector = Loading,
contentDescription = ""
) )
}
}
if (itemsAvailable == 0 && !isToolLoading) { if (itemsAvailable == 0 && !isToolLoading) {
Column( Column(