From a5288e4ed7d35e70bdd6e8d366bd5da166d25d88 Mon Sep 17 00:00:00 2001 From: Infi Date: Fri, 23 Dec 2022 16:41:43 +0100 Subject: [PATCH] feat: splash screen, move login branching logic out of greeter --- app/src/main/java/chat/revolt/MainActivity.kt | 5 +- .../main/java/chat/revolt/api/RevoltAPI.kt | 11 ++- .../java/chat/revolt/screens/SplashScreen.kt | 92 +++++++++++++++++++ .../chat/revolt/screens/chat/HomeScreen.kt | 1 - .../revolt/screens/login/GreeterScreen.kt | 83 +---------------- 5 files changed, 103 insertions(+), 89 deletions(-) create mode 100644 app/src/main/java/chat/revolt/screens/SplashScreen.kt diff --git a/app/src/main/java/chat/revolt/MainActivity.kt b/app/src/main/java/chat/revolt/MainActivity.kt index 086bc509..ec21ecb9 100644 --- a/app/src/main/java/chat/revolt/MainActivity.kt +++ b/app/src/main/java/chat/revolt/MainActivity.kt @@ -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 -> diff --git a/app/src/main/java/chat/revolt/api/RevoltAPI.kt b/app/src/main/java/chat/revolt/api/RevoltAPI.kt index 3b7cdd1a..10aa66f6 100644 --- a/app/src/main/java/chat/revolt/api/RevoltAPI.kt +++ b/app/src/main/java/chat/revolt/api/RevoltAPI.kt @@ -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() - val serverCache = mutableMapOf() - val channelCache = mutableMapOf() - val emojiCache = mutableMapOf() - val messageCache = mutableMapOf() + val userCache = mutableStateMapOf() + val serverCache = mutableStateMapOf() + val channelCache = mutableStateMapOf() + val emojiCache = mutableStateMapOf() + val messageCache = mutableStateMapOf() var selfId: String? = null diff --git a/app/src/main/java/chat/revolt/screens/SplashScreen.kt b/app/src/main/java/chat/revolt/screens/SplashScreen.kt new file mode 100644 index 00000000..b47d223c --- /dev/null +++ b/app/src/main/java/chat/revolt/screens/SplashScreen.kt @@ -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("") + } +} \ No newline at end of file diff --git a/app/src/main/java/chat/revolt/screens/chat/HomeScreen.kt b/app/src/main/java/chat/revolt/screens/chat/HomeScreen.kt index 9cbeacb0..8f5de315 100644 --- a/app/src/main/java/chat/revolt/screens/chat/HomeScreen.kt +++ b/app/src/main/java/chat/revolt/screens/chat/HomeScreen.kt @@ -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( diff --git a/app/src/main/java/chat/revolt/screens/login/GreeterScreen.kt b/app/src/main/java/chat/revolt/screens/login/GreeterScreen.kt index 892d05d9..02668265 100644 --- a/app/src/main/java/chat/revolt/screens/login/GreeterScreen.kt +++ b/app/src/main/java/chat/revolt/screens/login/GreeterScreen.kt @@ -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()