Use navigation to have a separate splash and login view

This commit is contained in:
Jackson Harper
2022-08-19 18:03:06 +08:00
parent 2a84440917
commit fd69fd8aa7
14 changed files with 254 additions and 19 deletions

View File

@ -49,6 +49,8 @@ android {
}
dependencies {
def nav_version = "2.5.1"
implementation 'androidx.core:core-ktx:1.7.0'
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
@ -56,6 +58,9 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.3.1'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.gms:play-services-base:17.6.0'
implementation "androidx.navigation:navigation-compose:$nav_version"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'

View File

@ -4,10 +4,12 @@ import android.app.Activity
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
@ -15,6 +17,7 @@ import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.tasks.Task
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun GoogleAuthButton(viewModel: LoginViewModel) {
val context = LocalContext.current
@ -37,12 +40,14 @@ fun GoogleAuthButton(viewModel: LoginViewModel) {
}
}
Button(
GoogleSignInButton(
text = "Continue with Google",
loadingText = "Signing in...",
isLoading = viewModel.isLoading,
icon = painterResource(id = R.drawable.ic_logo_google),
onClick = {
val googleSignIn = GoogleSignIn.getClient(context, signInOptions)
startForResult.launch(googleSignIn.signInIntent)
}
) {
Text(text = "Continue With Google")
}
)
}

View File

@ -0,0 +1,70 @@
package app.omnivore.omnivore
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.material.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.unit.dp
@ExperimentalMaterialApi
@Composable
fun GoogleSignInButton(
text: String,
loadingText: String = "Signing in...",
icon: Painter,
isLoading: Boolean = false,
shape: Shape = Shapes().medium,
borderColor: Color = Color.LightGray,
backgroundColor: Color = MaterialTheme.colors.surface,
progressIndicatorColor: Color = MaterialTheme.colors.primary,
onClick: () -> Unit
) {
Surface(
modifier = Modifier.clickable(
enabled = !isLoading,
onClick = onClick
),
shape = shape,
border = BorderStroke(width = 1.dp, color = borderColor),
color = backgroundColor
) {
Row(
modifier = Modifier
.padding(
start = 12.dp,
end = 16.dp,
top = 12.dp,
bottom = 12.dp
),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
Icon(
painter = icon,
contentDescription = "SignInButton",
tint = Color.Unspecified
)
Spacer(modifier = Modifier.width(8.dp))
Text(text = if (isLoading) loadingText else text)
if (isLoading) {
Spacer(modifier = Modifier.width(16.dp))
CircularProgressIndicator(
modifier = Modifier
.height(16.dp)
.width(16.dp),
strokeWidth = 2.dp,
color = progressIndicatorColor
)
}
}
}
}

View File

@ -2,9 +2,11 @@ package app.omnivore.omnivore
import android.content.ContentValues
import android.util.Log
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalUriHandler
import androidx.lifecycle.*
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.common.api.ApiException
@ -106,6 +108,4 @@ class LoginViewModel @Inject constructor(
}
}
}
}

View File

@ -52,9 +52,10 @@ class MainActivity : ComponentActivity() {
setContent {
OmnivoreTheme {
// A surface container using the 'background' color from the theme
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
WelcomeView(viewModel)
}
ScreenMain(viewModel = viewModel)
// Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
// WelcomeView(viewModel)
// }
}
}
@ -91,7 +92,6 @@ fun LoginView(viewModel: LoginViewModel) {
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.background(MaterialTheme.colorScheme.background)
.fillMaxSize()
) {
if (isGoogleAuthAvailable) {
GoogleAuthButton(viewModel)
@ -186,7 +186,7 @@ fun LoginFields(
verticalArrangement = Arrangement.spacedBy(25.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Please login")
Text("Never miss a great read")
OutlinedTextField(
value = email,

View File

@ -0,0 +1,6 @@
package app.omnivore.omnivore
sealed class Routes(val route: String) {
object Splash : Routes("Splash")
object EmailLogin : Routes("EmailLogin")
}

View File

@ -8,6 +8,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.material.*
import androidx.compose.material.MaterialTheme.colors
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch

View File

@ -0,0 +1,22 @@
package app.omnivore.omnivore
import androidx.compose.runtime.Composable
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import app.omnivore.omnivore.screen.EmailLoginPage
import app.omnivore.omnivore.screen.SplashPage
@Composable
fun ScreenMain(viewModel: LoginViewModel){
val navController = rememberNavController()
NavHost(navController = navController, startDestination = Routes.Splash.route) {
composable(Routes.Splash.route) {
SplashPage(viewModel = viewModel, navController = navController)
}
composable(Routes.EmailLogin.route) {
EmailLoginPage(viewModel = viewModel, navController = navController)
}
}
}

View File

@ -0,0 +1,31 @@
package app.omnivore.omnivore.screen
import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import app.omnivore.omnivore.EmailLoginView
import app.omnivore.omnivore.LoginViewModel
@Composable
fun EmailLoginPage(viewModel: LoginViewModel, navController: NavHostController) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.background(MaterialTheme.colorScheme.background)
.fillMaxSize()
.navigationBarsPadding()
) {
EmailLoginView(viewModel)
}
}

View File

@ -0,0 +1,78 @@
package app.omnivore.omnivore.screen
import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.text.ClickableText
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.text.AnnotatedString
import androidx.core.content.ContextCompat.startActivity
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavHostController
import app.omnivore.omnivore.EmailLoginView
import app.omnivore.omnivore.GoogleAuthButton
import app.omnivore.omnivore.LoginViewModel
import app.omnivore.omnivore.Routes
import com.google.android.gms.common.GoogleApiAvailability
import kotlinx.coroutines.launch
@Composable
fun SplashPage(viewModel: LoginViewModel, navController: NavHostController) {
val isGoogleAuthAvailable: Boolean = GoogleApiAvailability
.getInstance()
.isGooglePlayServicesAvailable(LocalContext.current) == 0
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.background(MaterialTheme.colorScheme.background)
.fillMaxSize()
.navigationBarsPadding()
) {
Text("Never miss a great read")
MoreInfoButton()
if (isGoogleAuthAvailable) {
GoogleAuthButton(viewModel)
}
ContinueWithEmailButton(navController)
}
}
@Composable
fun MoreInfoButton() {
val context = LocalContext.current
val intent = remember { Intent(Intent.ACTION_VIEW, Uri.parse("https://omnivore.app/about")) }
ClickableText(
text = AnnotatedString("Learn More ->"),
onClick = {
context.startActivity(intent)
}
)
}
@Composable
fun ContinueWithEmailButton(navController: NavHostController) {
ClickableText(
text = AnnotatedString("Continue with Email ->"),
onClick = {
navController.navigate(Routes.EmailLogin.route)
}
)
}

View File

@ -0,0 +1,22 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M23.04,12.262C23.04,11.446 22.967,10.662 22.831,9.909H12V14.358H18.189C17.923,15.795 17.112,17.013 15.894,17.829V20.714H19.611C21.785,18.712 23.04,15.764 23.04,12.262Z"
android:fillColor="#4285F4"
android:fillType="evenOdd"/>
<path
android:pathData="M12,23.5C15.105,23.5 17.708,22.47 19.611,20.714L15.894,17.828C14.865,18.518 13.547,18.926 12,18.926C9.005,18.926 6.469,16.903 5.565,14.185H1.723V17.164C3.615,20.923 7.504,23.5 12,23.5Z"
android:fillColor="#34A853"
android:fillType="evenOdd"/>
<path
android:pathData="M5.565,14.185C5.335,13.495 5.205,12.758 5.205,12C5.205,11.242 5.335,10.505 5.565,9.815V6.835H1.723C0.944,8.388 0.5,10.144 0.5,12C0.5,13.856 0.944,15.612 1.723,17.164L5.565,14.185Z"
android:fillColor="#FBBC05"
android:fillType="evenOdd"/>
<path
android:pathData="M12,5.074C13.688,5.074 15.204,5.654 16.396,6.794L19.694,3.495C17.703,1.64 15.1,0.5 12,0.5C7.504,0.5 3.615,3.077 1.723,6.835L5.565,9.815C6.469,7.097 9.005,5.074 12,5.074Z"
android:fillColor="#EA4335"
android:fillType="evenOdd"/>
</vector>

View File

@ -1,10 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="cloud">#F7F7F7</color>

View File

@ -1,4 +1,4 @@
<resources>
<string name="app_name">Save to Omnivore</string>
<string name="app_name">Omnivore</string>
<string name="gcp_id">590528454690-ovh9ku5r3fojgr1pp5kgaimr43o96btb.apps.googleusercontent.com</string>
</resources>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.Omnivore" parent="android:Theme.Material.Light.NoActionBar">
<item name="android:statusBarColor">@color/purple_700</item>
<style name="Theme.Omnivore" parent="android:Theme.Material.Light">
</style>
<style name="Theme.AppCompat.Translucent" parent="Theme.AppCompat.NoActionBar">