From cbf5e068986d27d0e3738a61fdfb549c96d290c1 Mon Sep 17 00:00:00 2001 From: Infi Date: Sun, 10 Nov 2024 01:11:28 +0100 Subject: [PATCH] feat(overview): replace home screen with overview screen Signed-off-by: Infi --- app/build.gradle.kts | 3 - .../main/java/chat/revolt/api/schemas/User.kt | 17 +- .../screens/chat/drawer/ChannelSideDrawer.kt | 12 +- .../screens/settings/UserOverview.kt | 11 +- .../skeletons/UserOverviewSkeleton.kt | 74 +++++ .../revolt/screens/chat/ChatRouterScreen.kt | 88 +---- .../revolt/screens/chat/views/HomeScreen.kt | 130 -------- .../screens/chat/views/OverviewScreen.kt | 306 ++++++++++++++++++ .../screens/settings/DebugSettingsScreen.kt | 17 +- .../revolt/screens/settings/SettingsScreen.kt | 3 - .../res/raw/open_settings_tutorial.lottie | Bin 1647 -> 0 bytes app/src/main/res/values/strings.xml | 20 +- 12 files changed, 436 insertions(+), 245 deletions(-) create mode 100644 app/src/main/java/chat/revolt/components/skeletons/UserOverviewSkeleton.kt delete mode 100644 app/src/main/java/chat/revolt/screens/chat/views/HomeScreen.kt create mode 100644 app/src/main/java/chat/revolt/screens/chat/views/OverviewScreen.kt delete mode 100644 app/src/main/res/raw/open_settings_tutorial.lottie diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1b24df5a..eef03dee 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -284,9 +284,6 @@ dependencies { // AboutLibraries - automated OSS library attribution implementation("com.mikepenz:aboutlibraries-compose:$aboutlibrariesVersion") - // Lottie - animated vector graphics - implementation("com.airbnb.android:lottie-compose:6.0.0") - // Sentry - crash reporting implementation("io.sentry:sentry-android:7.16.0") implementation("io.sentry:sentry-compose-android:7.16.0") diff --git a/app/src/main/java/chat/revolt/api/schemas/User.kt b/app/src/main/java/chat/revolt/api/schemas/User.kt index 5ef061d3..848f4759 100644 --- a/app/src/main/java/chat/revolt/api/schemas/User.kt +++ b/app/src/main/java/chat/revolt/api/schemas/User.kt @@ -1,9 +1,12 @@ package chat.revolt.api.schemas +import android.os.Parcelable +import kotlinx.parcelize.Parcelize import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable +@Parcelize data class User( @SerialName("_id") val id: String? = null, @@ -21,7 +24,7 @@ data class User( val bot: Bot? = null, val relationship: String? = null, val online: Boolean? = null -) { +) : Parcelable { fun mergeWithPartial(partial: User): User { return User( id = partial.id ?: id, @@ -85,26 +88,30 @@ infix fun Long?.has(flag: UserBadges): Boolean { } @Serializable +@Parcelize data class Bot( val owner: String? = null -) +) : Parcelable @Serializable +@Parcelize data class Profile( val content: String? = null, val background: AutumnResource? = null -) +) : Parcelable @Serializable +@Parcelize data class Relation( @SerialName("_id") val id: String? = null, val status: String? = null -) +) : Parcelable @Serializable +@Parcelize data class Status( val text: String? = null, val presence: String? = null -) +) : Parcelable diff --git a/app/src/main/java/chat/revolt/components/screens/chat/drawer/ChannelSideDrawer.kt b/app/src/main/java/chat/revolt/components/screens/chat/drawer/ChannelSideDrawer.kt index e8a5d786..326d5bfb 100644 --- a/app/src/main/java/chat/revolt/components/screens/chat/drawer/ChannelSideDrawer.kt +++ b/app/src/main/java/chat/revolt/components/screens/chat/drawer/ChannelSideDrawer.kt @@ -579,17 +579,17 @@ fun ColumnScope.DirectMessagesChannelListRenderer( .fillMaxSize() .weight(1f) ) { - item(key = "home") { + item(key = "overview") { ChannelItem( channel = Channel( - id = "home", - name = stringResource(R.string.home), + id = "overview", + name = stringResource(R.string.overview_screen_title), channelType = ChannelType.TextChannel ), - iconType = ChannelItemIconType.Painter(painterResource(R.drawable.ic_home_24dp)), - isCurrent = currentDestination is ChatRouterDestination.Home, + iconType = ChannelItemIconType.Painter(painterResource(R.drawable.ic_creation_24dp)), + isCurrent = currentDestination is ChatRouterDestination.Overview, onDestinationChanged = { - onDestinationChanged(ChatRouterDestination.Home) + onDestinationChanged(ChatRouterDestination.Overview) scope.launch { drawerState?.close() } diff --git a/app/src/main/java/chat/revolt/components/screens/settings/UserOverview.kt b/app/src/main/java/chat/revolt/components/screens/settings/UserOverview.kt index d3af080f..8ef00d70 100644 --- a/app/src/main/java/chat/revolt/components/screens/settings/UserOverview.kt +++ b/app/src/main/java/chat/revolt/components/screens/settings/UserOverview.kt @@ -95,6 +95,7 @@ fun RawUserOverview( Box( contentAlignment = Alignment.BottomStart, modifier = Modifier + .height(128.dp) .padding(horizontal = if (internalPadding) 16.dp else 0.dp) .clip(MaterialTheme.shapes.large) .then( @@ -111,7 +112,8 @@ fun RawUserOverview( } ) ) { - (backgroundUrl ?: profile?.background)?.let { background -> + val background = backgroundUrl ?: profile?.background + if (background != null) { RemoteImage( url = backgroundUrl ?: "$REVOLT_FILES/backgrounds/${if (background is AutumnResource) background.id else null}", @@ -135,6 +137,13 @@ fun RawUserOverview( .height(128.dp) .fillMaxWidth() ) + } else { + Box( + modifier = Modifier + .background(MaterialTheme.colorScheme.surfaceContainer) + .height(128.dp) + .fillMaxWidth() + ) } Row( diff --git a/app/src/main/java/chat/revolt/components/skeletons/UserOverviewSkeleton.kt b/app/src/main/java/chat/revolt/components/skeletons/UserOverviewSkeleton.kt new file mode 100644 index 00000000..7ee58367 --- /dev/null +++ b/app/src/main/java/chat/revolt/components/skeletons/UserOverviewSkeleton.kt @@ -0,0 +1,74 @@ +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.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.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import chat.revolt.api.settings.LoadedSettings +import com.valentinilk.shimmer.shimmer + +@Composable +fun UserOverviewSkeleton(internalPadding: Boolean, modifier: Modifier = Modifier) { + Box( + contentAlignment = Alignment.BottomStart, modifier = Modifier + .shimmer() + .padding(horizontal = if (internalPadding) 16.dp else 0.dp) + .clip(MaterialTheme.shapes.large) + ) { + Box( + modifier = Modifier + .background(skeletonColourOnBackground()) + .height(128.dp) + .fillMaxWidth(), + ) + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .padding(16.dp) + .fillMaxWidth() + ) { + Box( + Modifier + .clip(RoundedCornerShape(LoadedSettings.avatarRadius)) + .size(48.dp) + .background(skeletonColourOnBackground()) + ) + Spacer(modifier = Modifier.width(12.dp)) + Column { + Box( + Modifier + .width(66.dp) + .height(16.dp) + .background(skeletonColourOnBackground()) + ) + Spacer(modifier = Modifier.height(4.dp)) + Box( + Modifier + .width(97.dp) + .height(16.dp) + .background(skeletonColourOnBackground()) + ) + } + } + } +} + +@Preview +@Composable +private fun UserOverviewSkeletonPreview() { + UserOverviewSkeleton(internalPadding = false) +} \ No newline at end of file diff --git a/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt b/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt index c964ccf6..8a7b7771 100644 --- a/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt +++ b/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt @@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.statusBars @@ -75,8 +74,8 @@ import chat.revolt.screens.chat.dialogs.safety.ReportMessageDialog import chat.revolt.screens.chat.dialogs.safety.ReportServerDialog import chat.revolt.screens.chat.dialogs.safety.ReportUserDialog import chat.revolt.screens.chat.views.FriendsScreen -import chat.revolt.screens.chat.views.HomeScreen import chat.revolt.screens.chat.views.NoCurrentChannelScreen +import chat.revolt.screens.chat.views.OverviewScreen import chat.revolt.screens.chat.views.channel.ChannelScreen import chat.revolt.sheets.AddServerSheet import chat.revolt.sheets.ChangelogSheet @@ -87,11 +86,6 @@ import chat.revolt.sheets.ServerContextSheet import chat.revolt.sheets.StatusSheet import chat.revolt.sheets.UserInfoSheet import chat.revolt.sheets.WebHookUserSheet -import com.airbnb.lottie.RenderMode -import com.airbnb.lottie.compose.LottieAnimation -import com.airbnb.lottie.compose.LottieCompositionSpec -import com.airbnb.lottie.compose.animateLottieCompositionAsState -import com.airbnb.lottie.compose.rememberLottieComposition import com.google.android.gms.tasks.OnCompleteListener import com.google.firebase.messaging.FirebaseMessaging import dagger.hilt.android.lifecycle.HiltViewModel @@ -102,14 +96,14 @@ import kotlinx.coroutines.launch import javax.inject.Inject sealed class ChatRouterDestination { - data object Home : ChatRouterDestination() + data object Overview : ChatRouterDestination() data object Friends : ChatRouterDestination() data class Channel(val channelId: String) : ChatRouterDestination() data class NoCurrentChannel(val serverId: String?) : ChatRouterDestination() fun asSerialisedString(): String { return when (this) { - is Home -> "home" + is Overview -> "overview" is Friends -> "friends" is Channel -> "channel/$channelId" is NoCurrentChannel -> "no_current_channel/$serverId" @@ -117,12 +111,13 @@ sealed class ChatRouterDestination { } companion object { - val default = Home - val defaultForDMList = Home + val default = Overview + val defaultForDMList = Overview fun fromString(destination: String): ChatRouterDestination { return when { - destination == "home" -> Home + destination == "home" -> Overview // previous name for overview + destination == "overview" -> Overview destination == "friends" -> Friends destination.startsWith("no_current_channel/") -> NoCurrentChannel( destination.removePrefix( @@ -144,7 +139,6 @@ class ChatRouterViewModel @Inject constructor( @ApplicationContext val context: Context ) : ViewModel() { var currentDestination by mutableStateOf(ChatRouterDestination.default) - var sidebarSparkDisplayed by mutableStateOf(true) var latestChangelogRead by mutableStateOf(true) var latestChangelog by mutableStateOf("") var latestChangelogBody by mutableStateOf("") @@ -157,12 +151,6 @@ class ChatRouterViewModel @Inject constructor( val current = kvStorage.get("currentDestination") setSaveDestination(ChatRouterDestination.fromString(current ?: "")) - sidebarSparkDisplayed = if (kvStorage.getBoolean("sidebarSpark") == null) { - false - } else { - kvStorage.getBoolean("sidebarSpark")!! - } - latestChangelogRead = changelogs.hasSeenCurrent() latestChangelog = changelogs.getLatestChangelogCode() latestChangelogBody = @@ -195,11 +183,6 @@ class ChatRouterViewModel @Inject constructor( } } - suspend fun setSettingsHintDisplayed() { - kvStorage.set("sidebarSpark", true) - sidebarSparkDisplayed = true - } - fun setRegisterForNotifications() { showNotificationRationale = false FirebaseMessaging.getInstance().token.addOnCompleteListener( @@ -255,14 +238,6 @@ fun ChatRouterScreen( val context = LocalContext.current val view = LocalView.current - val showSidebarSpark = remember { mutableStateOf(false) } - val sidebarSparkComposition by rememberLottieComposition( - LottieCompositionSpec.RawRes(R.raw.open_settings_tutorial) - ) - val sidebarSparkProgress by animateLottieCompositionAsState( - composition = sidebarSparkComposition - ) - var showPlatformModDMHint by remember { mutableStateOf(false) } var showStatusSheet by remember { mutableStateOf(false) } @@ -341,14 +316,6 @@ fun ChatRouterScreen( } } - LaunchedEffect(viewModel.sidebarSparkDisplayed) { - snapshotFlow { viewModel.sidebarSparkDisplayed } - .distinctUntilChanged() - .collect { displayed -> - showSidebarSpark.value = !displayed - } - } - LaunchedEffect(RevoltAPI.selfId) { snapshotFlow { RevoltAPI.selfId } .distinctUntilChanged() @@ -468,43 +435,6 @@ fun ChatRouterScreen( ) } - if (showSidebarSpark.value) { - AlertDialog( - onDismissRequest = {}, - title = { - Text(stringResource(id = R.string.spark_sidebar_settings_tutorial)) - }, - text = { - Column { - LottieAnimation( - composition = sidebarSparkComposition, - progress = { sidebarSparkProgress }, - modifier = Modifier - .fillMaxWidth() - .aspectRatio(1f), - renderMode = RenderMode.HARDWARE - ) - Text( - stringResource(id = R.string.spark_sidebar_settings_tutorial_description_1) - ) - Text( - stringResource(id = R.string.spark_sidebar_settings_tutorial_description_2) - ) - } - }, - confirmButton = { - TextButton(onClick = { - scope.launch { - viewModel.setSettingsHintDisplayed() - } - showSidebarSpark.value = false - }) { - Text(stringResource(id = R.string.spark_sidebar_settings_tutorial_acknowledge)) - } - } - ) - } - if (showPlatformModDMHint) { AlertDialog( onDismissRequest = {}, @@ -912,8 +842,8 @@ fun ChannelNavigator( Column(Modifier.fillMaxSize()) { when (dest) { - is ChatRouterDestination.Home -> { - HomeScreen( + is ChatRouterDestination.Overview -> { + OverviewScreen( navController = topNav, useDrawer = useDrawer, onDrawerClicked = toggleDrawer, diff --git a/app/src/main/java/chat/revolt/screens/chat/views/HomeScreen.kt b/app/src/main/java/chat/revolt/screens/chat/views/HomeScreen.kt deleted file mode 100644 index 8b16e4ec..00000000 --- a/app/src/main/java/chat/revolt/screens/chat/views/HomeScreen.kt +++ /dev/null @@ -1,130 +0,0 @@ -package chat.revolt.screens.chat.views - -import android.content.Intent -import android.net.Uri -import androidx.compose.animation.core.LinearEasing -import androidx.compose.animation.core.RepeatMode -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.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Menu -import androidx.compose.material.icons.filled.Star -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.material3.TopAppBar -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.rotate -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import chat.revolt.R -import chat.revolt.activities.InviteActivity -import chat.revolt.components.screens.home.LinkOnHome -import chat.revolt.internals.extensions.zero - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun HomeScreen(navController: NavController, useDrawer: Boolean, onDrawerClicked: () -> Unit) { - val context = LocalContext.current - - val catTransition = rememberInfiniteTransition(label = "cat") - val catRotation by catTransition.animateFloat( - initialValue = 0f, - targetValue = 360f, - animationSpec = infiniteRepeatable( - animation = tween(10000, easing = LinearEasing), - repeatMode = RepeatMode.Restart - ), - label = "catRotation" - ) - - Scaffold( - topBar = { - TopAppBar( - title = { - Text( - text = stringResource(R.string.home), - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - }, - navigationIcon = { - if (useDrawer) { - IconButton(onClick = { - onDrawerClicked() - }) { - Icon( - imageVector = Icons.Default.Menu, - contentDescription = stringResource(id = R.string.menu) - ) - } - } - }, - windowInsets = WindowInsets.zero - ) - }, - ) { pv -> - Column( - modifier = Modifier - .padding(pv) - .fillMaxHeight() - ) { - Box( - modifier = Modifier - .weight(1f) - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Text( - text = "🐈", - fontSize = 100.sp, - modifier = Modifier.rotate(catRotation) - ) - } - - Column(Modifier.padding(16.dp)) { - LinkOnHome( - icon = { modifier -> - Icon( - imageVector = Icons.Default.Star, - contentDescription = stringResource(id = R.string.home_join_jenvolt), - modifier = modifier - ) - }, - heading = { Text(text = stringResource(id = R.string.home_join_jenvolt)) }, - description = { - Text( - text = stringResource(id = R.string.home_join_jenvolt_description) - ) - } - ) { - context.startActivity( - Intent( - context, - InviteActivity::class.java - ) - .setData(Uri.parse("https://rvlt.gg/jen")) - .setAction(Intent.ACTION_VIEW) - ) - } - } - } - } -} diff --git a/app/src/main/java/chat/revolt/screens/chat/views/OverviewScreen.kt b/app/src/main/java/chat/revolt/screens/chat/views/OverviewScreen.kt new file mode 100644 index 00000000..1defcf48 --- /dev/null +++ b/app/src/main/java/chat/revolt/screens/chat/views/OverviewScreen.kt @@ -0,0 +1,306 @@ +package chat.revolt.screens.chat.views + +import android.util.Log +import android.widget.Toast +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +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.Spacer +import androidx.compose.foundation.layout.WindowInsets +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.lazy.staggeredgrid.LazyVerticalStaggeredGrid +import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.Menu +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ProvideTextStyle +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import chat.revolt.R +import chat.revolt.api.RevoltAPI +import chat.revolt.api.routes.user.fetchSelf +import chat.revolt.api.schemas.User +import chat.revolt.components.generic.NonIdealState +import chat.revolt.components.screens.settings.UserOverview +import chat.revolt.components.skeletons.UserOverviewSkeleton +import chat.revolt.internals.extensions.zero +import io.sentry.Sentry + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun OverviewScreen(navController: NavController, useDrawer: Boolean, onDrawerClicked: () -> Unit) { + val context = LocalContext.current + + var isLoading by rememberSaveable { mutableStateOf(true) } + var user by rememberSaveable { mutableStateOf(null) } + LaunchedEffect(Unit) { + val inCache = RevoltAPI.userCache[RevoltAPI.selfId] + if (inCache != null) { + user = inCache + isLoading = false + } else { + try { + fetchSelf().let { + user = it + isLoading = false + } + } catch (e: Exception) { + Log.e("OverviewScreen", "Failed to fetch self", e) + Sentry.captureException(e) + isLoading = false + } + } + } + + Scaffold( + topBar = { + CenterAlignedTopAppBar( + title = { Text("You") }, + navigationIcon = { + if (useDrawer) { + IconButton(onClick = { + onDrawerClicked() + }) { + Icon( + imageVector = Icons.Default.Menu, + contentDescription = stringResource(id = R.string.menu) + ) + } + } + }, + windowInsets = WindowInsets.zero + ) + }, + ) { pv -> + if (user == null && !isLoading) { + NonIdealState( + icon = { size -> + Icon( + imageVector = Icons.Default.Close, + contentDescription = null, + modifier = Modifier.size(size) + ) + }, + title = { Text(stringResource(R.string.overview_screen_error)) }, + description = { Text(stringResource(R.string.overview_screen_error_description)) } + ) + return@Scaffold + } + + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .padding(pv) + .padding(horizontal = 16.dp) + ) { + AnimatedContent(targetState = isLoading, label = "isLoading") { loading -> + Column( + horizontalAlignment = Alignment.CenterHorizontally, + ) { + if (loading) { + Spacer(modifier = Modifier.height(16.dp)) + UserOverviewSkeleton(false) + Spacer(modifier = Modifier.height(16.dp)) + } else { + Spacer(modifier = Modifier.height(16.dp)) + user?.let { user -> + UserOverview(user, internalPadding = false) + } + Spacer(modifier = Modifier.height(16.dp)) + } + } + } + + if (isLoading) { + CircularProgressIndicator(Modifier.size(48.dp)) + } + + AnimatedVisibility( + visible = isLoading + ) { + Spacer(modifier = Modifier.height(48.dp)) + } + + AnimatedVisibility( + visible = !isLoading, + enter = fadeIn(), + ) { + LazyVerticalStaggeredGrid( + columns = StaggeredGridCells.Adaptive(300.dp), + verticalItemSpacing = 16.dp, + horizontalArrangement = Arrangement.spacedBy(16.dp), + ) { + item(key = "settings") { + OverviewScreenLink( + onClick = { + navController.navigate("settings") + }, + backgroundColour = MaterialTheme.colorScheme.primaryContainer, + foregroundColour = MaterialTheme.colorScheme.onPrimaryContainer, + title = { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + imageVector = Icons.Default.Settings, + contentDescription = null, + modifier = Modifier.size(22.dp) + ) + Text(stringResource(R.string.overview_screen_settings)) + } + }, + body = { Text(stringResource(R.string.overview_screen_settings_description)) } + ) + } + item(key = "shareProfile") { + OverviewScreenLink( + onClick = { + Toast.makeText( + context, + context.getString(R.string.comingsoon_toast), + Toast.LENGTH_SHORT + ).show() + // navController.navigate("userCard") + }, + backgroundColour = MaterialTheme.colorScheme.tertiaryContainer, + foregroundColour = MaterialTheme.colorScheme.onTertiaryContainer, + title = { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + painter = painterResource(R.drawable.ic_share_24dp), + contentDescription = null, + modifier = Modifier.size(22.dp) + ) + Text(stringResource(R.string.overview_screen_share_profile)) + } + }, + body = { Text(stringResource(R.string.overview_screen_share_profile_description)) } + ) + } + + item(key = "changelog") { + OverviewScreenLink( + onClick = { + navController.navigate("settings/changelogs") + }, + backgroundColour = MaterialTheme.colorScheme.errorContainer, + foregroundColour = MaterialTheme.colorScheme.onErrorContainer, + title = { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + painter = painterResource(R.drawable.ic_flask_24dp), + contentDescription = null, + modifier = Modifier.size(22.dp) + ) + Text(stringResource(R.string.overview_screen_changelog)) + } + }, + body = { Text(stringResource(R.string.overview_screen_changelog_description)) } + ) + } + item(key = "feedback") { + OverviewScreenLink( + onClick = { + Toast.makeText( + context, + context.getString(R.string.comingsoon_toast), + Toast.LENGTH_SHORT + ).show() + // navController.navigate("feedback") + }, + backgroundColour = MaterialTheme.colorScheme.primary, + foregroundColour = MaterialTheme.colorScheme.onPrimary, + title = { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + painter = painterResource(R.drawable.ic_creation_24dp), + contentDescription = null, + modifier = Modifier.size(22.dp) + ) + Text(stringResource(R.string.overview_screen_feedback)) + } + }, + body = { Text(stringResource(R.string.overview_screen_feedback_description)) } + ) + } + } + } + } + } +} + +@Composable +fun OverviewScreenLink( + onClick: () -> Unit, + backgroundColour: Color, + foregroundColour: Color, + title: @Composable () -> Unit, + body: @Composable () -> Unit, +) { + Box( + modifier = Modifier + .clip(MaterialTheme.shapes.extraLarge) + .clickable(onClick = onClick) + .background(backgroundColour) + .padding(vertical = 32.dp) + .fillMaxWidth() + ) { + CompositionLocalProvider(LocalContentColor provides foregroundColour) { + Column( + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.spacedBy(8.dp), + modifier = Modifier.padding(horizontal = 24.dp) + ) { + ProvideTextStyle(MaterialTheme.typography.titleLarge) { + title() + } + ProvideTextStyle(MaterialTheme.typography.bodyMedium) { + body() + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/chat/revolt/screens/settings/DebugSettingsScreen.kt b/app/src/main/java/chat/revolt/screens/settings/DebugSettingsScreen.kt index 5cada2bc..4a90eeb7 100644 --- a/app/src/main/java/chat/revolt/screens/settings/DebugSettingsScreen.kt +++ b/app/src/main/java/chat/revolt/screens/settings/DebugSettingsScreen.kt @@ -53,7 +53,6 @@ import chat.revolt.persistence.Database import chat.revolt.persistence.KVStorage import chat.revolt.persistence.SqlStorage import chat.revolt.ui.theme.FragmentMono -import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.android.gms.common.ConnectionResult import com.google.android.gms.common.GoogleApiAvailabilityLight import com.google.android.gms.tasks.OnCompleteListener @@ -66,14 +65,9 @@ import javax.inject.Inject class DebugSettingsScreenViewModel @Inject constructor( private val kvStorage: KVStorage ) : ViewModel() { - fun forgetSidebarSparkShown() { - viewModelScope.launch { - kvStorage.remove("sidebarSpark") - } - } - fun forgetAllSparks() { - this.forgetSidebarSparkShown() + // No op because there are no active sparks + // psst, notifications will be the next one } fun forgetLatestChangelog() { @@ -215,11 +209,10 @@ fun DebugSettingsScreen( Row( modifier = Modifier.horizontalScroll(rememberScrollState()) ) { - TextButton(onClick = { viewModel.forgetSidebarSparkShown() }) { - Text("Forget sidebar spark") - } + + Text("There are no active sparks, but you can still try to ") ElevatedButton(onClick = { viewModel.forgetAllSparks() }) { - Text("Forget all sparks") + Text("forget all sparks") } } diff --git a/app/src/main/java/chat/revolt/screens/settings/SettingsScreen.kt b/app/src/main/java/chat/revolt/screens/settings/SettingsScreen.kt index 12fef2c2..f4c5adf7 100644 --- a/app/src/main/java/chat/revolt/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/chat/revolt/screens/settings/SettingsScreen.kt @@ -46,7 +46,6 @@ import chat.revolt.api.RevoltAPI import chat.revolt.api.settings.FeatureFlags import chat.revolt.api.settings.LoadedSettings import chat.revolt.components.generic.ListHeader -import chat.revolt.components.screens.settings.SelfUserOverview import chat.revolt.persistence.KVStorage import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.runBlocking @@ -105,8 +104,6 @@ fun SettingsScreen( .fillMaxSize() .verticalScroll(rememberScrollState()) ) { - SelfUserOverview() - Column( modifier = Modifier .fillMaxSize() diff --git a/app/src/main/res/raw/open_settings_tutorial.lottie b/app/src/main/res/raw/open_settings_tutorial.lottie deleted file mode 100644 index 082eb081378cac7d0e1719fb5a12e048a704bce4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1647 zcmWIWW@Zs#U|`??Vg`math}a^fb?D<<^|&1#JtS3)Z!Aotm6DU)pL$~O$Gw27j~by zC6%>;iM`+{Z%_9jpRHW7#%raVckEuPlm6-7`S}Og>~B7?ba`>kxT1w`gQ4%!sO4qInq``9a++zHu1TUrims)pfr)OKkzqO72WqYqI)9yTIJ(TIVUGf+17pF|2^X=8Q%Mj zo0{Fb%d)|xuK=nXwxmzPOjV`H6Sbr5~xT=ZfxZ4FB88`#0>^U6aTq=iHOZPMqMn z)%cWCJ3hiud`9oq4HDMQ$M#Eb%wXKdcQ(jE!(gGaWTwty`SzeA$_JBT_NFlwx~knw z`)oSXOiZYdi%Ij0xAykxVb^dN~-@7OGgA_r1sp*W5HY-j_N#Q{H>X5)-Yd0d_v@8`PnnBKPiyXi`8JY ze#G`ysjpO}B1gPwVQ5>-1^4+Z;pf@wmpryQDWAUbv*ya>YVOZ0pXJy6D|r2fHL0=1 z^n|>{5$<0ic?KU0swNbx8T%+3*e5bT<9v2c{St68V!oV?>YH4yJ_VCop+?&h+%$~%cF#S# z$+gsL*0wq8PlT*&;ackE=9Tj7-}2XbeLd$z2zHUbW0N zBY-nwwMNkx?+UWmu#=6eH$Wmx0i0YmD`eadGT`Y z4AbjJc1cdoGuig|LhpgL_g|Mi_P=)AYWLI)*Dt@0dvM9Ud#!tZ-G+q6wd~w4w|!2y z*|>Bw)6J4*-8CP2&fWf_xl-BQ!906&rD&V*`3=QU?pBk1+-?P*|JJwnUEy8(Q^(HE zaX-Yr!p5Y7D@6Ois+yP0pI5~>D*3Hf;8Kq^&TA9O{ZWb;c6@^xuY^%gcS@%+=VN>g%UY zvU7Oju9{ZQ62f&T?nSnod(6>_WT$4$PhM|7Y8>}(yHir6ycwAo7;u-~z%mdCpp@n4TG7i+gg#JJKu$>-;LXYgGKC2U=K|?H HtRNl$A1%vA diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d28516cd..d1d3fd1d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -129,13 +129,26 @@ Unknown - Home Menu Log out Join Jenvolt Jenvolt is the developer-run space for all things Android app and more. Support, feedback go here. Maybe you will get to try out new features! 👀 + + You + Couldn\'t load your overview + Please try again later. + Open Settings + Change your look, manage your account, and more + Share Profile + Take a look at your user card and get a special link to share + Changelog + Revolt never sleeps, take a look to see what\'s been in the works + Provide Feedback + Got something to say? We\'re all ears + + Friends Incoming Requests Outgoing Requests @@ -547,11 +560,6 @@ Search results Clear search - The settings are in the sidebar - You can open the sidebar by swiping from the left edge of the screen. - Then long tap your profile picture to open the settings. - Got it - Stay in the loop Enable notifications to be kept up to date with messages and mentions. Enable notifications