diff --git a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/EmptyList.kt b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/EmptyList.kt deleted file mode 100644 index d1e20809..00000000 --- a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/EmptyList.kt +++ /dev/null @@ -1,41 +0,0 @@ -package dev.msfjarvis.lobsters.ui.posts - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import dev.msfjarvis.lobsters.R -import dev.msfjarvis.lobsters.util.IconResource - -@Composable -fun EmptyList(saved: Boolean) { - Column( - modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - if (saved) { - IconResource( - R.drawable.ic_favorite_border_24px, - tint = Color(0xFFD97373), - modifier = Modifier.padding(16.dp), - contentDescription = stringResource(R.string.add_to_saved_posts), - ) - Text(stringResource(R.string.no_saved_posts)) - } else { - IconResource( - R.drawable.ic_sync_problem_24px, - modifier = Modifier.padding(16.dp), - contentDescription = stringResource(R.string.remove_from_saved_posts), - ) - Text(stringResource(R.string.loading)) - } - } -} diff --git a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/HottestPosts.kt b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/HottestPosts.kt index ae3371b4..6f81db0d 100644 --- a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/HottestPosts.kt +++ b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/HottestPosts.kt @@ -27,7 +27,11 @@ fun HottestPosts( val urlLauncher = LocalUrlLauncher.current if (posts.loadState.refresh == LoadState.Loading) { - EmptyList(saved = false) + LazyColumn { + items(15) { + LoadingLobstersItem() + } + } } else { LazyColumn( state = listState, diff --git a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/SavedPosts.kt b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/SavedPosts.kt index 518658bc..c62bd16e 100644 --- a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/SavedPosts.kt +++ b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/SavedPosts.kt @@ -1,13 +1,24 @@ package dev.msfjarvis.lobsters.ui.posts import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import dev.msfjarvis.lobsters.R import dev.msfjarvis.lobsters.data.local.SavedPost import dev.msfjarvis.lobsters.ui.urllauncher.LocalUrlLauncher +import dev.msfjarvis.lobsters.util.IconResource import dev.msfjarvis.lobsters.util.asZonedDateTime @OptIn(ExperimentalFoundationApi::class) @@ -21,7 +32,19 @@ fun SavedPosts( val urlLauncher = LocalUrlLauncher.current if (posts.isEmpty()) { - EmptyList(saved = true) + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + IconResource( + R.drawable.ic_favorite_border_24px, + tint = Color(0xFFD97373), + modifier = Modifier.padding(16.dp), + contentDescription = stringResource(R.string.add_to_saved_posts), + ) + Text(stringResource(R.string.no_saved_posts)) + } } else { LazyColumn( state = listState, diff --git a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/ShimmeringList.kt b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/ShimmeringList.kt new file mode 100644 index 00000000..bb7f0ca5 --- /dev/null +++ b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/ShimmeringList.kt @@ -0,0 +1,95 @@ +package dev.msfjarvis.lobsters.ui.posts + +import androidx.compose.animation.core.RepeatMode +import androidx.compose.animation.core.animateFloat +import androidx.compose.animation.core.infiniteRepeatable +import androidx.compose.animation.core.keyframes +import androidx.compose.animation.core.rememberInfiniteTransition +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.absoluteOffset +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredHeight +import androidx.compose.foundation.layout.requiredSize +import androidx.compose.foundation.layout.requiredWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +@Composable +fun LoadingLobstersItem() { + val infiniteTransition = rememberInfiniteTransition() + val alpha by infiniteTransition.animateFloat( + initialValue = 0.2f, + targetValue = 1f, + animationSpec = infiniteRepeatable( + animation = keyframes { + durationMillis = 1000 + 0.7f at 500 + }, + repeatMode = RepeatMode.Reverse + ) + ) + val color = Color.LightGray.copy(alpha = alpha) + Surface( + modifier = Modifier.height(70.dp), + ) { + Row( + modifier = Modifier.padding(start = 12.dp, end = 12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Column( + verticalArrangement = Arrangement.SpaceEvenly, + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .requiredHeight(12.dp) + .background(color) + .padding(8.dp), + ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + modifier = Modifier + .absoluteOffset(y = 12.dp), + ) { + Box( + modifier = Modifier + .requiredSize(30.dp) + .background(color = color, shape = CircleShape), + ) + Box( + modifier = Modifier + .requiredHeight(12.dp) + .requiredWidth(40.dp) + .absoluteOffset(x = 12.dp) + .background(color), + ) + } + } + } + } +} + +@Preview +@Composable +fun ShimmerListPreview() { + LazyColumn { + items(10) { + LoadingLobstersItem() + } + } +}