enhancement: placeholder with shimmer effect

This commit is contained in:
Diego Beraldin 2023-10-03 09:03:26 +02:00
parent 1bb8095cea
commit 2214fd1404
25 changed files with 586 additions and 54 deletions

View File

@ -6,6 +6,7 @@ import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
@ -64,6 +65,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycl
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communityInfo.CommunityInfoScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommunityHeader
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCardPlaceholder
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SwipeableCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createcomment.CreateCommentScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createpost.CreatePostScreen
@ -253,6 +255,15 @@ class CommunityDetailScreen(
},
)
}
if (uiState.posts.isEmpty() && uiState.loading) {
items(5) {
Column {
PostCardPlaceholder(
postLayout = uiState.postLayout,
)
}
}
}
itemsIndexed(uiState.posts) { idx, post ->
SwipeableCard(
modifier = Modifier.fillMaxWidth(),

View File

@ -0,0 +1,76 @@
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components
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.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.CornerSize
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
import com.github.diegoberaldin.raccoonforlemmy.core.utils.shimmerEffect
@Composable
fun CommentCardPlaceholder(
hideAuthor: Boolean = false,
) {
Column(
modifier = Modifier.background(MaterialTheme.colorScheme.background),
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
) {
if (!hideAuthor) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(Spacing.s)
) {
Box(
modifier = Modifier.size(20.dp)
.clip(CircleShape)
.shimmerEffect()
)
Column(
modifier = Modifier.padding(vertical = Spacing.xxxs),
verticalArrangement = Arrangement.spacedBy(Spacing.xxxs),
) {
Box(
modifier = Modifier.height(20.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
Box(
modifier = Modifier.height(20.dp)
.fillMaxWidth(0.5f)
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
}
}
}
Box(
modifier = Modifier
.height(80.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.s))
.shimmerEffect()
)
Box(
modifier = Modifier
.height(32.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
}
}

View File

@ -0,0 +1,62 @@
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components
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.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.PostLayout
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.CornerSize
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
import com.github.diegoberaldin.raccoonforlemmy.core.utils.shimmerEffect
@Composable
fun InboxCardPlaceholder(
postLayout: PostLayout = PostLayout.Card,
) {
Column(
modifier = Modifier.let {
if (postLayout == PostLayout.Card) {
it.padding(horizontal = Spacing.xs).background(
color = MaterialTheme.colorScheme.surfaceColorAtElevation(5.dp),
shape = RoundedCornerShape(CornerSize.l),
).padding(Spacing.s)
} else {
it
}
},
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
) {
Box(
modifier = Modifier
.height(32.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
Box(
modifier = Modifier
.padding(vertical = Spacing.xxxs)
.height(50.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
Box(
modifier = Modifier
.height(32.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
}
}

View File

@ -41,7 +41,7 @@ fun PostCard(
hideAuthor: Boolean = false,
postLayout: PostLayout = PostLayout.Card,
withOverflowBlurred: Boolean = true,
blurNsfw: Boolean,
blurNsfw: Boolean = true,
options: List<String> = emptyList(),
onOpenCommunity: ((CommunityModel) -> Unit)? = null,
onOpenCreator: ((UserModel) -> Unit)? = null,
@ -63,12 +63,10 @@ fun PostCard(
Box(
modifier = modifier.let {
if (postLayout == PostLayout.Card) {
it.padding(horizontal = Spacing.xs)
.background(
color = MaterialTheme.colorScheme.surfaceColorAtElevation(5.dp),
shape = RoundedCornerShape(CornerSize.l),
)
.padding(Spacing.s)
it.padding(horizontal = Spacing.xs).background(
color = MaterialTheme.colorScheme.surfaceColorAtElevation(5.dp),
shape = RoundedCornerShape(CornerSize.l),
).padding(Spacing.s)
} else {
it
}
@ -146,9 +144,7 @@ private fun CompactPost(
horizontalArrangement = Arrangement.spacedBy(Spacing.xs)
) {
PostCardImage(
modifier = Modifier
.weight(0.2f)
.clip(RoundedCornerShape(CornerSize.s)),
modifier = Modifier.weight(0.2f).clip(RoundedCornerShape(CornerSize.s)),
minHeight = Dp.Unspecified,
maxHeight = Dp.Unspecified,
imageUrl = post.imageUrl,
@ -156,8 +152,7 @@ private fun CompactPost(
onImageClick = onImageClick,
)
PostCardTitle(
modifier = Modifier.weight(1f),
text = post.title
modifier = Modifier.weight(1f), text = post.title
)
}
PostCardFooter(
@ -210,8 +205,7 @@ private fun ExtendedPost(
modifier = Modifier.padding(
vertical = Spacing.xs,
horizontal = Spacing.xs,
),
text = post.title
), text = post.title
)
PostCardImage(
@ -222,22 +216,18 @@ private fun ExtendedPost(
)
Box {
PostCardBody(
modifier = Modifier
.let {
if (withOverflowBlurred) {
it.heightIn(max = 200.dp)
} else {
it
}
modifier = Modifier.let {
if (withOverflowBlurred) {
it.heightIn(max = 200.dp)
} else {
it
}
.padding(horizontal = Spacing.xs),
}.padding(horizontal = Spacing.xs),
text = post.text,
)
if (withOverflowBlurred) {
Box(
modifier = Modifier
.height(Spacing.xxl)
.fillMaxWidth()
modifier = Modifier.height(Spacing.xxl).fillMaxWidth()
.align(Alignment.BottomCenter).background(
brush = Brush.verticalGradient(
colors = listOf(

View File

@ -0,0 +1,212 @@
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components
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.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.PostLayout
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.CornerSize
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
import com.github.diegoberaldin.raccoonforlemmy.core.utils.shimmerEffect
@Composable
fun PostCardPlaceholder(
postLayout: PostLayout = PostLayout.Card,
) {
when (postLayout) {
PostLayout.Compact -> {
Column(
modifier = Modifier.background(MaterialTheme.colorScheme.background),
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(Spacing.s)
) {
Box(
modifier = Modifier.size(20.dp)
.clip(CircleShape)
.shimmerEffect()
)
Column(
modifier = Modifier.padding(vertical = Spacing.xxxs),
verticalArrangement = Arrangement.spacedBy(Spacing.xxxs),
) {
Box(
modifier = Modifier.height(20.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
Box(
modifier = Modifier.height(20.dp)
.fillMaxWidth(0.5f)
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
}
}
Row(
verticalAlignment = Alignment.Top,
horizontalArrangement = Arrangement.spacedBy(Spacing.xs)
) {
Box(
modifier = Modifier
.weight(0.2f)
.aspectRatio(1.33f)
.clip(RoundedCornerShape(CornerSize.s))
.shimmerEffect()
)
Box(
modifier = Modifier
.height(40.dp)
.weight(1f)
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
}
Box(
modifier = Modifier
.height(32.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.s))
.shimmerEffect()
)
}
}
PostLayout.Card -> {
Column(
modifier = Modifier
.padding(horizontal = Spacing.xs).background(
color = MaterialTheme.colorScheme.surfaceColorAtElevation(5.dp),
shape = RoundedCornerShape(CornerSize.l),
).padding(Spacing.s),
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(Spacing.s)
) {
Box(
modifier = Modifier
.size(32.dp)
.clip(CircleShape)
.shimmerEffect()
)
Column(
modifier = Modifier.padding(vertical = Spacing.xxxs),
verticalArrangement = Arrangement.spacedBy(Spacing.xxxs),
) {
Box(
modifier = Modifier.height(20.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
Box(
modifier = Modifier.height(20.dp)
.fillMaxWidth(0.5f)
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
}
}
Box(
modifier = Modifier.height(32.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
Box(
modifier = Modifier
.height(200.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.s))
.shimmerEffect()
)
Box(
modifier = Modifier
.height(32.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
}
}
PostLayout.Full -> {
Column(
modifier = Modifier.background(MaterialTheme.colorScheme.background),
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(Spacing.s)
) {
Box(
modifier = Modifier
.size(32.dp)
.clip(CircleShape)
.shimmerEffect()
)
Column(
modifier = Modifier.padding(vertical = Spacing.xxxs),
verticalArrangement = Arrangement.spacedBy(Spacing.xxxs),
) {
Box(
modifier = Modifier.height(20.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
Box(
modifier = Modifier.height(20.dp)
.fillMaxWidth(0.5f)
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
}
}
Box(
modifier = Modifier
.height(32.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
Box(
modifier = Modifier
.height(200.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.s))
.shimmerEffect()
)
Box(
modifier = Modifier
.height(32.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.m))
.shimmerEffect()
)
}
}
else -> Unit
}
}

View File

@ -68,6 +68,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommentCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommentCardPlaceholder
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SwipeableCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createcomment.CreateCommentScreen
@ -328,6 +329,11 @@ class PostDetailScreen(
}
}
}
if (uiState.comments.isEmpty() && uiState.loading) {
items(5) {
CommentCardPlaceholder()
}
}
itemsIndexed(uiState.comments) { idx, comment ->
val themeRepository = remember { getThemeRepository() }
val fontScale by themeRepository.contentFontScale.collectAsState()

View File

@ -63,7 +63,9 @@ import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycl
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.chat.InboxChatScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommentCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommentCardPlaceholder
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCardPlaceholder
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SectionSelector
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SwipeableCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.UserHeader
@ -242,6 +244,15 @@ class UserDetailScreen(
}
}
if (uiState.section == UserDetailSection.Posts) {
if (uiState.posts.isEmpty() && uiState.loading) {
items(5) {
Column {
PostCardPlaceholder(
postLayout = uiState.postLayout,
)
}
}
}
itemsIndexed(uiState.posts) { idx, post ->
SwipeableCard(
modifier = Modifier.fillMaxWidth(),
@ -379,6 +390,11 @@ class UserDetailScreen(
}
}
} else {
if (uiState.comments.isEmpty() && uiState.loading) {
items(5) {
CommentCardPlaceholder()
}
}
itemsIndexed(uiState.comments) { idx, comment ->
SwipeableCard(
modifier = Modifier.fillMaxWidth(),

View File

@ -1,11 +1,6 @@
package com.github.diegoberaldin.raccoonforlemmy.core.utils
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
@ -23,15 +18,6 @@ import kotlinx.coroutines.IO
import kotlinx.coroutines.withContext
import kotlin.math.roundToInt
fun Modifier.onClick(onClick: () -> Unit): Modifier = composed {
clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() },
) {
onClick()
}
}
@Composable
fun String.toLanguageName() = when (this) {
"es" -> stringResource(MR.strings.language_es)

View File

@ -0,0 +1,16 @@
package com.github.diegoberaldin.raccoonforlemmy.core.utils
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
fun Modifier.onClick(onClick: () -> Unit): Modifier = composed {
clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() },
) {
onClick()
}
}

View File

@ -0,0 +1,50 @@
package com.github.diegoberaldin.raccoonforlemmy.core.utils
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.background
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.unit.IntSize
fun Modifier.shimmerEffect(
duration: Int = 1000,
colors: List<Color> = listOf(
Color(0xFF333333),
Color(0xFF999999),
Color(0xFF333333),
),
): Modifier = composed {
var size by remember {
mutableStateOf(IntSize.Zero)
}
val transition = rememberInfiniteTransition()
val startOffsetX by transition.animateFloat(
initialValue = -2 * size.width.toFloat(),
targetValue = 2 * size.width.toFloat(),
animationSpec = infiniteRepeatable(
animation = tween(duration)
)
)
background(
brush = Brush.linearGradient(
colors = colors,
start = Offset(startOffsetX, 0f),
end = Offset(startOffsetX + size.width.toFloat(), size.height.toFloat())
)
).alpha(0.5f).onGloballyPositioned {
size = it.size
}
}

View File

@ -1,6 +1,7 @@
package com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
@ -48,6 +49,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCardPlaceholder
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SwipeableCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createcomment.CreateCommentScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createpost.CreatePostScreen
@ -151,6 +153,15 @@ class PostListScreen : Screen {
LazyColumn(
state = lazyListState,
) {
if (uiState.posts.isEmpty() && uiState.loading) {
items(5) {
Column {
PostCardPlaceholder(
postLayout = uiState.postLayout,
)
}
}
}
itemsIndexed(uiState.posts) { idx, post ->
val themeRepository = remember { getThemeRepository() }
val fontScale by themeRepository.contentFontScale.collectAsState()

View File

@ -2,10 +2,8 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.di
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.main.InboxViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.mentions.InboxMentionsViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.chat.InboxChatViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list.InboxMessagesViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.InboxMessagesViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.replies.InboxRepliesViewModel
import org.koin.core.parameter.parametersOf
import org.koin.java.KoinJavaComponent.inject
actual fun getInboxViewModel(): InboxViewModel {

View File

@ -7,8 +7,8 @@ import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.main.InboxMviModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.main.InboxViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.mentions.InboxMentionsMviModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.mentions.InboxMentionsViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list.InboxMessagesMviModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list.InboxMessagesViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.InboxMessagesMviModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.InboxMessagesViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.replies.InboxRepliesMviModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.replies.InboxRepliesViewModel
import org.koin.dsl.module

View File

@ -2,8 +2,7 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.di
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.main.InboxViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.mentions.InboxMentionsViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.chat.InboxChatViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list.InboxMessagesViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.InboxMessagesViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.replies.InboxRepliesViewModel
expect fun getInboxViewModel(): InboxViewModel

View File

@ -38,7 +38,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.notifications.di.getNotific
import com.github.diegoberaldin.raccoonforlemmy.core.utils.onClick
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.di.getInboxViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.mentions.InboxMentionsScreen
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list.InboxMessagesScreen
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.InboxMessagesScreen
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.replies.InboxRepliesScreen
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
import com.github.diegoberaldin.raccoonforlemmy.resources.di.getLanguageRepository

View File

@ -40,6 +40,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCardPlaceholder
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCardType
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SwipeableCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getNavigationCoordinator
@ -85,6 +86,13 @@ class InboxMentionsScreen : Tab {
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
) {
if (uiState.mentions.isEmpty() && uiState.loading) {
items(3) {
InboxCardPlaceholder(
postLayout = uiState.postLayout,
)
}
}
itemsIndexed(uiState.mentions) { idx, mention ->
SwipeableCard(
modifier = Modifier.fillMaxWidth(),

View File

@ -1,4 +1,4 @@
package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list
package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement

View File

@ -0,0 +1,54 @@
package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages
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.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.CornerSize
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
import com.github.diegoberaldin.raccoonforlemmy.core.utils.shimmerEffect
@Composable
internal fun ChatCardPlaceholder() {
Row(
modifier = Modifier.padding(Spacing.xs),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(Spacing.m),
) {
Box(
modifier = Modifier
.size(46.dp)
.clip(CircleShape)
.shimmerEffect()
)
Column(
verticalArrangement = Arrangement.spacedBy(Spacing.xs)
) {
Box(
modifier = Modifier
.height(50.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.s))
.shimmerEffect()
)
Box(
modifier = Modifier
.height(28.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(CornerSize.s))
.shimmerEffect()
)
}
}
}

View File

@ -1,4 +1,4 @@
package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list
package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PrivateMessageModel

View File

@ -1,4 +1,4 @@
package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list
package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@ -76,6 +76,11 @@ class InboxMessagesScreen : Tab {
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
) {
if (uiState.chats.isEmpty() && uiState.loading) {
items(1) {
ChatCardPlaceholder()
}
}
items(uiState.chats) { chat ->
val themeRepository = remember { getThemeRepository() }
val fontScale by themeRepository.contentFontScale.collectAsState()

View File

@ -1,4 +1,4 @@
package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list
package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages
import cafe.adriel.voyager.core.model.ScreenModel
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel

View File

@ -46,6 +46,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCardPlaceholder
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCardType
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SwipeableCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getNavigationCoordinator
@ -90,6 +91,13 @@ class InboxRepliesScreen : Tab {
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
) {
if (uiState.replies.isEmpty() && uiState.loading) {
items(3) {
InboxCardPlaceholder(
postLayout = uiState.postLayout,
)
}
}
itemsIndexed(uiState.replies) { idx, mention ->
val themeRepository = remember { getThemeRepository() }
val fontScale by themeRepository.contentFontScale.collectAsState()

View File

@ -2,12 +2,10 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.di
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.main.InboxViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.mentions.InboxMentionsViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.chat.InboxChatViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list.InboxMessagesViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.InboxMessagesViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.replies.InboxRepliesViewModel
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.koin.core.parameter.parametersOf
actual fun getInboxViewModel() = InboxScreenModelHelper.model

View File

@ -35,7 +35,9 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommentCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommentCardPlaceholder
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCardPlaceholder
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SectionSelector
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.UserHeader
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createcomment.CreateCommentScreen
@ -126,6 +128,15 @@ internal object ProfileLoggedScreen : Tab {
}
}
if (uiState.section == ProfileLoggedSection.Posts) {
if (uiState.posts.isEmpty() && uiState.loading) {
items(5) {
Column {
PostCardPlaceholder(
postLayout = uiState.postLayout,
)
}
}
}
itemsIndexed(uiState.posts) { idx, post ->
PostCard(
modifier = Modifier.onClick {
@ -210,6 +221,11 @@ internal object ProfileLoggedScreen : Tab {
}
}
} else {
if (uiState.comments.isEmpty() && uiState.loading) {
items(5) {
CommentCardPlaceholder(hideAuthor = true)
}
}
itemsIndexed(uiState.comments) { idx, comment ->
CommentCard(
modifier = Modifier.onClick {

View File

@ -57,6 +57,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.Co
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommentCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommunityItem
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCard
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCardPlaceholder
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.UserItem
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createcomment.CreateCommentScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getNavigationCoordinator
@ -233,6 +234,15 @@ class ExploreScreen : Screen {
modifier = Modifier.padding(Spacing.xxs).pullRefresh(pullRefreshState),
) {
LazyColumn {
if (uiState.results.isEmpty() && uiState.loading) {
items(5) {
Column {
PostCardPlaceholder(
postLayout = uiState.postLayout,
)
}
}
}
itemsIndexed(uiState.results) { idx, result ->
val themeRepository = remember { getThemeRepository() }
val fontScale by themeRepository.contentFontScale.collectAsState()