diff --git a/app/src/main/kotlin/top/fatweb/oxygen/toolbox/icon/Loading.kt b/app/src/main/kotlin/top/fatweb/oxygen/toolbox/icon/Loading.kt deleted file mode 100644 index 8714f04..0000000 --- a/app/src/main/kotlin/top/fatweb/oxygen/toolbox/icon/Loading.kt +++ /dev/null @@ -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() diff --git a/app/src/main/kotlin/top/fatweb/oxygen/toolbox/ui/store/ToolStoreScreen.kt b/app/src/main/kotlin/top/fatweb/oxygen/toolbox/ui/store/ToolStoreScreen.kt index 1b709e7..553455f 100644 --- a/app/src/main/kotlin/top/fatweb/oxygen/toolbox/ui/store/ToolStoreScreen.kt +++ b/app/src/main/kotlin/top/fatweb/oxygen/toolbox/ui/store/ToolStoreScreen.kt @@ -1,11 +1,6 @@ package top.fatweb.oxygen.toolbox.ui.store 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.layout.Arrangement 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.padding import androidx.compose.foundation.layout.safeDrawing -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.systemBars import androidx.compose.foundation.layout.width 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.items 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.CircularProgressIndicator +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.Text 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.LaunchedEffect import androidx.compose.runtime.collectAsState @@ -45,7 +44,8 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment 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.unit.dp import androidx.hilt.navigation.compose.hiltViewModel @@ -53,7 +53,6 @@ import androidx.paging.LoadState import androidx.paging.compose.LazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems 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.model.tool.ToolEntity import top.fatweb.oxygen.toolbox.ui.component.ToolCard @@ -90,6 +89,7 @@ internal fun ToolStoreRoute( ) } +@OptIn(ExperimentalMaterial3Api::class) @Composable internal fun ToolStoreScreen( modifier: Modifier = Modifier, @@ -107,13 +107,25 @@ internal fun ToolStoreScreen( 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 state = rememberLazyStaggeredGridState() val scrollbarState = state.scrollbarState(itemsAvailable = itemsAvailable) - val infiniteTransition = rememberInfiniteTransition(label = "infiniteTransition") - var installTool by remember { mutableStateOf( ToolEntity( @@ -125,7 +137,10 @@ internal fun ToolStoreScreen( } Box( - modifier.fillMaxSize() + modifier + .fillMaxSize() + .clipToBounds() + .nestedScroll(pullToRefreshState.nestedScrollConnection) ) { LazyVerticalStaggeredGrid( modifier = Modifier @@ -154,28 +169,11 @@ internal fun ToolStoreScreen( } } - if (toolStorePagingItems.loadState.refresh is LoadState.Loading) { - 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 - .size(32.dp) - .graphicsLayer { rotationZ = angle }, - imageVector = Loading, - contentDescription = "" - ) - } - } + PullToRefreshContainer( + modifier = Modifier + .align(Alignment.TopCenter), + state = pullToRefreshState, + ) if (itemsAvailable == 0 && !isToolLoading) { Column(