diff --git a/android/Omnivore/app/build.gradle b/android/Omnivore/app/build.gradle index 106ef9db4..86c1239ca 100644 --- a/android/Omnivore/app/build.gradle +++ b/android/Omnivore/app/build.gradle @@ -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' diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/GoogleAuth.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/GoogleAuth.kt index dcdaffe44..ba8b9eae0 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/GoogleAuth.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/GoogleAuth.kt @@ -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") - } + ) } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/GoogleSignInButton.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/GoogleSignInButton.kt new file mode 100644 index 000000000..e80f8c0ce --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/GoogleSignInButton.kt @@ -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 + ) + } + } + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/LoginViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/LoginViewModel.kt index d5f788438..14db1873b 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/LoginViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/LoginViewModel.kt @@ -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( } } } - - } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt index 3723d293a..fbdd52768 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt @@ -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, diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Routes.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Routes.kt new file mode 100644 index 000000000..c6ca342c8 --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/Routes.kt @@ -0,0 +1,6 @@ +package app.omnivore.omnivore + +sealed class Routes(val route: String) { + object Splash : Routes("Splash") + object EmailLogin : Routes("EmailLogin") +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/SaveContent.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/SaveContent.kt index e6697d94a..4a569178b 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/SaveContent.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/SaveContent.kt @@ -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 diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ScreenMain.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ScreenMain.kt new file mode 100644 index 000000000..a2248f02e --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ScreenMain.kt @@ -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) + } + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/screen/EmailLogin.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/screen/EmailLogin.kt new file mode 100644 index 000000000..8d2784eb8 --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/screen/EmailLogin.kt @@ -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) + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/screen/SplashPage.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/screen/SplashPage.kt new file mode 100644 index 000000000..8e79e6930 --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/screen/SplashPage.kt @@ -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) + } + ) +} diff --git a/android/Omnivore/app/src/main/res/drawable/ic_logo_google.xml b/android/Omnivore/app/src/main/res/drawable/ic_logo_google.xml new file mode 100644 index 000000000..d9425d95c --- /dev/null +++ b/android/Omnivore/app/src/main/res/drawable/ic_logo_google.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/android/Omnivore/app/src/main/res/values/colors.xml b/android/Omnivore/app/src/main/res/values/colors.xml index 234f693f1..ee4d3d2e0 100644 --- a/android/Omnivore/app/src/main/res/values/colors.xml +++ b/android/Omnivore/app/src/main/res/values/colors.xml @@ -1,10 +1,5 @@ - #FFBB86FC - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 #FF000000 #FFFFFFFF #F7F7F7 diff --git a/android/Omnivore/app/src/main/res/values/strings.xml b/android/Omnivore/app/src/main/res/values/strings.xml index 78d5305f7..90a5ab700 100644 --- a/android/Omnivore/app/src/main/res/values/strings.xml +++ b/android/Omnivore/app/src/main/res/values/strings.xml @@ -1,4 +1,4 @@ - Save to Omnivore + Omnivore 590528454690-ovh9ku5r3fojgr1pp5kgaimr43o96btb.apps.googleusercontent.com diff --git a/android/Omnivore/app/src/main/res/values/themes.xml b/android/Omnivore/app/src/main/res/values/themes.xml index 0b211c476..f5b5ca333 100644 --- a/android/Omnivore/app/src/main/res/values/themes.xml +++ b/android/Omnivore/app/src/main/res/values/themes.xml @@ -1,8 +1,8 @@ -