feat: splash screen, move login branching logic out of greeter
This commit is contained in:
parent
4356f759e0
commit
a5288e4ed7
|
|
@ -12,6 +12,7 @@ import androidx.compose.material3.*
|
|||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import chat.revolt.screens.SplashScreen
|
||||
import chat.revolt.screens.about.AboutScreen
|
||||
import chat.revolt.screens.about.AttributionScreen
|
||||
import chat.revolt.screens.about.PlaceholderScreen
|
||||
|
|
@ -52,7 +53,7 @@ fun AppEntrypoint() {
|
|||
|
||||
AnimatedNavHost(
|
||||
navController = navController,
|
||||
startDestination = "login/greeting",
|
||||
startDestination = "splash",
|
||||
enterTransition = {
|
||||
slideIntoContainer(
|
||||
AnimatedContentScope.SlideDirection.Left,
|
||||
|
|
@ -78,6 +79,8 @@ fun AppEntrypoint() {
|
|||
) + fadeOut(animationSpec = RevoltTweenFloat)
|
||||
}
|
||||
) {
|
||||
composable("splash") { SplashScreen(navController) }
|
||||
|
||||
composable("login/greeting") { GreeterScreen(navController) }
|
||||
composable("login/login") { LoginScreen(navController) }
|
||||
composable("login/mfa/{mfaTicket}/{allowedAuthTypes}") { backStackEntry ->
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package chat.revolt.api
|
|||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import chat.revolt.api.realtime.RealtimeSocket
|
||||
import chat.revolt.api.routes.user.fetchSelf
|
||||
import chat.revolt.api.schemas.*
|
||||
|
|
@ -61,11 +62,11 @@ object RevoltAPI {
|
|||
const val TOKEN_HEADER_NAME = "x-session-token"
|
||||
|
||||
// FIXME discount caching solutions! LRU would be better but this is fine for now
|
||||
val userCache = mutableMapOf<String, User>()
|
||||
val serverCache = mutableMapOf<String, Server>()
|
||||
val channelCache = mutableMapOf<String, Channel>()
|
||||
val emojiCache = mutableMapOf<String, Emoji>()
|
||||
val messageCache = mutableMapOf<String, Message>()
|
||||
val userCache = mutableStateMapOf<String, User>()
|
||||
val serverCache = mutableStateMapOf<String, Server>()
|
||||
val channelCache = mutableStateMapOf<String, Channel>()
|
||||
val emojiCache = mutableStateMapOf<String, Emoji>()
|
||||
val messageCache = mutableStateMapOf<String, Message>()
|
||||
|
||||
var selfId: String? = null
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
package chat.revolt.screens
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.NavController
|
||||
import chat.revolt.R
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.components.generic.RemoteImage
|
||||
import chat.revolt.components.generic.drawableResource
|
||||
import chat.revolt.persistence.KVStorage
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class SplashScreenViewModel @Inject constructor(
|
||||
private val kvStorage: KVStorage
|
||||
) : ViewModel() {
|
||||
private var _navigateTo by mutableStateOf("")
|
||||
val navigateTo: String
|
||||
get() = _navigateTo
|
||||
|
||||
fun setNavigateTo(value: String) {
|
||||
_navigateTo = value
|
||||
}
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
val token = kvStorage.get("sessionToken") ?: return@launch setNavigateTo("login")
|
||||
|
||||
val valid = RevoltAPI.checkSessionToken(token)
|
||||
|
||||
if (!valid) {
|
||||
kvStorage.remove("sessionToken")
|
||||
setNavigateTo("login")
|
||||
} else {
|
||||
RevoltAPI.loginAs(token)
|
||||
setNavigateTo("home")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SplashScreen(navController: NavController, viewModel: SplashScreenViewModel = hiltViewModel()) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
RemoteImage(
|
||||
url = drawableResource(R.drawable.revolt_logo_wide),
|
||||
description = "Revolt Logo",
|
||||
contentScale = ContentScale.Fit,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(60.dp)
|
||||
)
|
||||
}
|
||||
|
||||
if (viewModel.navigateTo.isNotEmpty()) {
|
||||
when (viewModel.navigateTo) {
|
||||
"login" -> {
|
||||
navController.navigate("login/greeting") {
|
||||
popUpTo("splash") {
|
||||
inclusive = true
|
||||
}
|
||||
}
|
||||
}
|
||||
"home" -> {
|
||||
navController.navigate("chat/home") {
|
||||
popUpTo("splash") {
|
||||
inclusive = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
viewModel.setNavigateTo("")
|
||||
}
|
||||
}
|
||||
|
|
@ -105,7 +105,6 @@ fun HomeScreen(navController: NavController, viewModel: HomeScreenViewModel = hi
|
|||
}
|
||||
}
|
||||
|
||||
// a scrollable list of all users in user cache
|
||||
Text(
|
||||
text = "User cache",
|
||||
style = MaterialTheme.typography.displaySmall.copy(
|
||||
|
|
|
|||
|
|
@ -7,9 +7,6 @@ import androidx.compose.material3.ElevatedButton
|
|||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
|
@ -19,90 +16,12 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.NavController
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.components.generic.RemoteImage
|
||||
import chat.revolt.components.generic.drawableResource
|
||||
import chat.revolt.persistence.KVStorage
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class GreeterViewModel @Inject constructor(
|
||||
private val kvStorage: KVStorage
|
||||
) : ViewModel() {
|
||||
private var _skipLogin by mutableStateOf(false)
|
||||
val skipLogin: Boolean
|
||||
get() = _skipLogin
|
||||
|
||||
private var _finishedLoading by mutableStateOf(false)
|
||||
val finishedLoading: Boolean
|
||||
get() = _finishedLoading
|
||||
|
||||
fun setSkipLogin(value: Boolean) {
|
||||
_skipLogin = value
|
||||
}
|
||||
|
||||
fun setFinishedLoading(value: Boolean) {
|
||||
_finishedLoading = value
|
||||
}
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
val token = kvStorage.get("sessionToken")
|
||||
if (token != null) {
|
||||
val valid = RevoltAPI.checkSessionToken(token)
|
||||
if (!valid) {
|
||||
kvStorage.remove("sessionToken")
|
||||
RevoltAPI.setSessionHeader("")
|
||||
}
|
||||
}
|
||||
|
||||
if (RevoltAPI.isLoggedIn()) {
|
||||
RevoltAPI.loginAs(token ?: "")
|
||||
_skipLogin = true
|
||||
}
|
||||
|
||||
setFinishedLoading(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun GreeterScreen(navController: NavController, viewModel: GreeterViewModel = hiltViewModel()) {
|
||||
if (viewModel.skipLogin) {
|
||||
navController.navigate("chat/home") {
|
||||
popUpTo("login/greeting") {
|
||||
inclusive = true
|
||||
}
|
||||
}
|
||||
viewModel.setSkipLogin(false)
|
||||
}
|
||||
|
||||
if (!viewModel.finishedLoading) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
RemoteImage(
|
||||
url = drawableResource(R.drawable.revolt_logo_wide),
|
||||
description = "Revolt Logo",
|
||||
contentScale = ContentScale.Fit,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(60.dp)
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fun GreeterScreen(navController: NavController) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
|
|||
Loading…
Reference in New Issue