feat(overview): replace home screen with overview screen

Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
Infi 2024-11-10 01:11:28 +01:00
parent d5d3d13ee5
commit cbf5e06898
12 changed files with 436 additions and 245 deletions

View File

@ -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")

View File

@ -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

View File

@ -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()
}

View File

@ -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(

View File

@ -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)
}

View File

@ -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>(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,

View File

@ -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)
)
}
}
}
}
}

View File

@ -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<User?>(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()
}
}
}
}
}

View File

@ -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")
}
}

View File

@ -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()

View File

@ -129,13 +129,26 @@
<string name="unknown">Unknown</string>
<string name="home">Home</string>
<string name="menu">Menu</string>
<string name="logout">Log out</string>
<string name="home_join_jenvolt">Join Jenvolt</string>
<string name="home_join_jenvolt_description">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! 👀</string>
<!-- This is the user's personal home page. Does not need to be translated as "You", you can also use "Me" or "Overview" etc. Use your judgement. -->
<string name="overview_screen_title">You</string>
<string name="overview_screen_error">Couldn\'t load your overview</string>
<string name="overview_screen_error_description">Please try again later.</string>
<string name="overview_screen_settings">Open Settings</string>
<string name="overview_screen_settings_description">Change your look, manage your account, and more</string>
<string name="overview_screen_share_profile">Share Profile</string>
<string name="overview_screen_share_profile_description">Take a look at your user card and get a special link to share</string>
<string name="overview_screen_changelog">Changelog</string>
<string name="overview_screen_changelog_description">Revolt never sleeps, take a look to see what\'s been in the works</string>
<string name="overview_screen_feedback">Provide Feedback</string>
<string name="overview_screen_feedback_description">Got something to say? We\'re all ears</string>
<!--Help shape the future of Revolt for Android by providing feedback-->
<string name="friends">Friends</string>
<string name="friends_incoming_requests">Incoming Requests</string>
<string name="friends_outgoing_requests">Outgoing Requests</string>
@ -547,11 +560,6 @@
<string name="emoji_picker_search_results_header">Search results</string>
<string name="emoji_picker_clear_search">Clear search</string>
<string name="spark_sidebar_settings_tutorial">The settings are in the sidebar</string>
<string name="spark_sidebar_settings_tutorial_description_1">You can open the sidebar by swiping from the left edge of the screen.</string>
<string name="spark_sidebar_settings_tutorial_description_2">Then long tap your profile picture to open the settings.</string>
<string name="spark_sidebar_settings_tutorial_acknowledge">Got it</string>
<string name="spark_notifications_rationale">Stay in the loop</string>
<string name="spark_notifications_rationale_description">Enable notifications to be kept up to date with messages and mentions.</string>
<string name="spark_notifications_rationale_cta">Enable notifications</string>