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" /> <option name="myName" value="Project Default" />
<inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
<option name="composableFile" value="true" /> <option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool> </inspection_tool>
<inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true"> <inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" /> <option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool> </inspection_tool>
<inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true"> <inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" /> <option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool> </inspection_tool>
<inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true"> <inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" /> <option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool> </inspection_tool>
<inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
<option name="composableFile" value="true" /> <option name="composableFile" value="true" />

View File

@ -277,6 +277,9 @@ dependencies {
// Firebase - Cloud Messaging // Firebase - Cloud Messaging
implementation(platform("com.google.firebase:firebase-bom:33.1.1")) implementation(platform("com.google.firebase:firebase-bom:33.1.1"))
implementation("com.google.firebase:firebase-messaging") implementation("com.google.firebase:firebase-messaging")
// Shimmer - loading animations
implementation "com.valentinilk.shimmer:compose-shimmer:1.3.1"
} }
sqldelight { 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.ChannelIcon
import chat.revolt.components.screens.chat.ReplyManager import chat.revolt.components.screens.chat.ReplyManager
import chat.revolt.components.screens.chat.TypingIndicator 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.BottomSheetInsets
import chat.revolt.internals.extensions.rememberChannelPermissions import chat.revolt.internals.extensions.rememberChannelPermissions
import chat.revolt.internals.extensions.zero import chat.revolt.internals.extensions.zero
import chat.revolt.sheets.ChannelInfoSheet import chat.revolt.sheets.ChannelInfoSheet
import chat.revolt.sheets.MessageContextSheet import chat.revolt.sheets.MessageContextSheet
import chat.revolt.sheets.ReactSheet 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.flow.distinctUntilChanged
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.datetime.Instant import kotlinx.datetime.Instant
@ -699,14 +704,16 @@ fun ChannelScreen(
} }
is ChannelScreenItem.Loading -> { is ChannelScreenItem.Loading -> {
Box( Column(
modifier = Modifier.fillMaxWidth(), modifier = Modifier
contentAlignment = Alignment.Center .fillMaxWidth()
.shimmer(rememberShimmer(ShimmerBounds.Window)),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(8.dp)
) { ) {
CircularProgressIndicator( MessageSkeleton(MessageSkeletonVariant.One)
modifier = Modifier MessageSkeleton(MessageSkeletonVariant.Two)
.padding(16.dp) MessageSkeleton(MessageSkeletonVariant.Three)
)
} }
} }
} }