feat: skeletons on channel load

Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
Infi 2024-09-28 11:04:32 +02:00
parent 6e9b3dc93c
commit 87bedf0553
5 changed files with 112 additions and 7 deletions

View File

@ -3,15 +3,19 @@
<option name="myName" value="Project Default" />
<inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
<option name="composableFile" value="true" />

View File

@ -277,6 +277,9 @@ dependencies {
// Firebase - Cloud Messaging
implementation(platform("com.google.firebase:firebase-bom:33.1.1"))
implementation("com.google.firebase:firebase-messaging")
// Shimmer - loading animations
implementation "com.valentinilk.shimmer:compose-shimmer:1.3.1"
}
sqldelight {

View File

@ -0,0 +1,84 @@
package chat.revolt.components.skeletons
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
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.layout.width
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 chat.revolt.api.settings.GlobalState
enum class MessageSkeletonVariant {
One,
Two,
Three
}
@Composable
fun MessageSkeleton(variant: MessageSkeletonVariant, modifier: Modifier = Modifier) {
Row(
modifier = Modifier
.padding(horizontal = 10.dp)
.fillMaxWidth()
) {
Column {
Spacer(modifier = Modifier.height(4.dp))
Box(
Modifier
.clip(RoundedCornerShape(GlobalState.avatarRadius))
.size(40.dp)
.background(skeletonColourOnBackground())
)
}
Column(modifier = Modifier.padding(start = 10.dp, top = 4.dp)) {
Row(verticalAlignment = Alignment.CenterVertically) {
Box(
Modifier
.width(
when (variant) {
// Chaotic widths. Boo!
MessageSkeletonVariant.One -> 66.dp
MessageSkeletonVariant.Two -> 29.dp
MessageSkeletonVariant.Three -> 97.dp
}
)
.height(16.dp)
.background(skeletonColourOnBackground())
)
Spacer(modifier = Modifier.width(5.dp))
Box(
Modifier
.width(42.dp)
.height(13.dp)
.background(skeletonColourOnBackground())
)
}
Spacer(modifier = Modifier.height(4.dp))
Box(
Modifier
.fillMaxWidth(
1 / when (variant) {
MessageSkeletonVariant.One -> 1.5f
MessageSkeletonVariant.Two -> 1.2f
MessageSkeletonVariant.Three -> 1.8f
}
)
.height(16.dp)
.background(skeletonColourOnBackground())
)
}
}
}

View File

@ -0,0 +1,7 @@
package chat.revolt.components.skeletons
import androidx.compose.material3.LocalContentColor
import androidx.compose.runtime.Composable
@Composable
fun skeletonColourOnBackground() = LocalContentColor.current.copy(alpha = 0.4f)

View File

@ -120,12 +120,17 @@ import chat.revolt.components.screens.chat.AttachmentManager
import chat.revolt.components.screens.chat.ChannelIcon
import chat.revolt.components.screens.chat.ReplyManager
import chat.revolt.components.screens.chat.TypingIndicator
import chat.revolt.components.skeletons.MessageSkeleton
import chat.revolt.components.skeletons.MessageSkeletonVariant
import chat.revolt.internals.extensions.BottomSheetInsets
import chat.revolt.internals.extensions.rememberChannelPermissions
import chat.revolt.internals.extensions.zero
import chat.revolt.sheets.ChannelInfoSheet
import chat.revolt.sheets.MessageContextSheet
import chat.revolt.sheets.ReactSheet
import com.valentinilk.shimmer.ShimmerBounds
import com.valentinilk.shimmer.rememberShimmer
import com.valentinilk.shimmer.shimmer
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
import kotlinx.datetime.Instant
@ -699,14 +704,16 @@ fun ChannelScreen(
}
is ChannelScreenItem.Loading -> {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.Center
Column(
modifier = Modifier
.fillMaxWidth()
.shimmer(rememberShimmer(ShimmerBounds.Window)),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
CircularProgressIndicator(
modifier = Modifier
.padding(16.dp)
)
MessageSkeleton(MessageSkeletonVariant.One)
MessageSkeleton(MessageSkeletonVariant.Two)
MessageSkeleton(MessageSkeletonVariant.Three)
}
}
}