feat(overview): replace home screen with overview screen
Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
parent
d5d3d13ee5
commit
cbf5e06898
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue