diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/EmailLogin.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/EmailLogin.kt index eb29f52c9..c30b53790 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/EmailLogin.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/EmailLogin.kt @@ -2,8 +2,6 @@ package app.omnivore.omnivore.ui.auth import android.annotation.SuppressLint import android.widget.Toast -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.text.KeyboardActions @@ -15,142 +13,98 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.unit.dp -import androidx.navigation.NavHostController -import app.omnivore.omnivore.R -import kotlinx.coroutines.launch - -//@Composable -//fun EmailLoginViewContainer(viewModel: LoginViewModel, navController: NavHostController) { -// Column( -// verticalArrangement = Arrangement.Center, -// horizontalAlignment = Alignment.CenterHorizontally, -// modifier = Modifier -// .background(MaterialTheme.colorScheme.background) -// .fillMaxSize() -// .navigationBarsPadding() -// ) { -// EmailLoginView(viewModel) -// } -//} @SuppressLint("CoroutineCreationDuringComposition") @Composable fun EmailLoginView(viewModel: LoginViewModel, onAuthProviderButtonTap: () -> Unit) { - var email by rememberSaveable { mutableStateOf("") } - var password by rememberSaveable { mutableStateOf("") } + var email by rememberSaveable { mutableStateOf("") } + var password by rememberSaveable { mutableStateOf("") } - Row( - horizontalArrangement = Arrangement.Center + Row( + horizontalArrangement = Arrangement.Center + ) { + Spacer(modifier = Modifier.weight(1.0F)) + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally ) { - Spacer(modifier = Modifier.weight(1.0F)) - Column( - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - LoginFields( - email, - password, - onEmailChange = { email = it }, - onPasswordChange = { password = it }, - onLoginClick = { viewModel.login(email, password) } - ) + LoginFields( + email, + password, + onEmailChange = { email = it }, + onPasswordChange = { password = it }, + onLoginClick = { viewModel.login(email, password) } + ) - // TODO: add a activity indicator (maybe after a delay?) - if (viewModel.isLoading) { - Text("Loading...") - } + // TODO: add a activity indicator (maybe after a delay?) + if (viewModel.isLoading) { + Text("Loading...") + } - ClickableText( - text = AnnotatedString("Continue with Google/Apple ->"), - onClick = { onAuthProviderButtonTap() } - ) - } - Spacer(modifier = Modifier.weight(1.0F)) + ClickableText( + text = AnnotatedString("Continue with Google/Apple ->"), + onClick = { onAuthProviderButtonTap() } + ) } - -// Column( -// verticalArrangement = Arrangement.Center, -// horizontalAlignment = Alignment.CenterHorizontally, -// modifier = Modifier -// .fillMaxSize() -// .clickable { focusManager.clearFocus() } -// ) { -// LoginFields( -// email, -// password, -// onEmailChange = { email = it }, -// onPasswordChange = { password = it }, -// onLoginClick = { viewModel.login(email, password) } -// ) -// -// // TODO: add a activity indicator (maybe after a delay?) -// if (viewModel.isLoading) { -// Text("Loading...") -// } -// -// ClickableText( -// text = AnnotatedString("Continue with Google/Apple ->"), -// onClick = { onAuthProviderButtonTap() } -// ) -// } + Spacer(modifier = Modifier.weight(1.0F)) + } } @OptIn(ExperimentalMaterial3Api::class) @Composable fun LoginFields( - email: String, - password: String, - onEmailChange: (String) -> Unit, - onPasswordChange: (String) -> Unit, - onLoginClick: () -> Unit + email: String, + password: String, + onEmailChange: (String) -> Unit, + onPasswordChange: (String) -> Unit, + onLoginClick: () -> Unit ) { - val context = LocalContext.current - val focusManager = LocalFocusManager.current + val context = LocalContext.current + val focusManager = LocalFocusManager.current - Column( - modifier = Modifier - .fillMaxWidth() - .height(300.dp), - verticalArrangement = Arrangement.spacedBy(25.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - OutlinedTextField( - value = email, - placeholder = { Text(text = "user@email.com") }, - label = { Text(text = "email") }, - onValueChange = onEmailChange, - keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), - keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }) - ) + Column( + modifier = Modifier + .fillMaxWidth() + .height(300.dp), + verticalArrangement = Arrangement.spacedBy(25.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + OutlinedTextField( + value = email, + placeholder = { Text(text = "user@email.com") }, + label = { Text(text = "email") }, + onValueChange = onEmailChange, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), + keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }) + ) - OutlinedTextField( - value = password, - placeholder = { Text(text = "password") }, - label = { Text(text = "password") }, - onValueChange = onPasswordChange, - visualTransformation = PasswordVisualTransformation(), - keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), - keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }) - ) + OutlinedTextField( + value = password, + placeholder = { Text(text = "password") }, + label = { Text(text = "password") }, + onValueChange = onPasswordChange, + visualTransformation = PasswordVisualTransformation(), + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), + keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }) + ) - Button(onClick = { - if (email.isNotBlank() && password.isNotBlank()) { - onLoginClick() - focusManager.clearFocus() - } else { - Toast.makeText( - context, - "Please enter an email address and password.", - Toast.LENGTH_SHORT - ).show() - } - }) { - Text(text = "Login") - } + Button(onClick = { + if (email.isNotBlank() && password.isNotBlank()) { + onLoginClick() + focusManager.clearFocus() + } else { + Toast.makeText( + context, + "Please enter an email address and password.", + Toast.LENGTH_SHORT + ).show() + } + }) { + Text(text = "Login") } + } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/WelcomeScreen.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/WelcomeScreen.kt index a0f77a040..dadfd961f 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/WelcomeScreen.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/auth/WelcomeScreen.kt @@ -29,138 +29,137 @@ import kotlinx.coroutines.launch @Composable fun WelcomeScreen(viewModel: LoginViewModel) { - Surface(modifier = Modifier.fillMaxSize(), color = Color(0xFFFBEAA8 )) { - WelcomeScreenContent(viewModel = viewModel) - } + Surface(modifier = Modifier.fillMaxSize(), color = Color(0xFFFBEAA8 )) { + WelcomeScreenContent(viewModel = viewModel) + } } @SuppressLint("CoroutineCreationDuringComposition") @Composable fun WelcomeScreenContent(viewModel: LoginViewModel) { - var registrationState by rememberSaveable { mutableStateOf(RegistrationState.AuthProviderButtons) } + var registrationState by rememberSaveable { mutableStateOf(RegistrationState.AuthProviderButtons) } - val onRegistrationStateChange = { state: RegistrationState -> - registrationState = state + val onRegistrationStateChange = { state: RegistrationState -> + registrationState = state + } + + val snackBarHostState = remember { SnackbarHostState() } + val coroutineScope = rememberCoroutineScope() + val focusManager = LocalFocusManager.current + + Column( + verticalArrangement = Arrangement.SpaceAround, + horizontalAlignment = Alignment.Start, + modifier = Modifier + .background(Color(0xFFFBEAA8)) + .fillMaxSize() + .navigationBarsPadding() + .padding(horizontal = 16.dp) + .clickable { focusManager.clearFocus() } + ) { + Spacer(modifier = Modifier.height(50.dp)) + Image( + painter = painterResource(id = R.drawable.ic_omnivore_name_logo), + contentDescription = "Omnivore Icon with Name" + ) + Spacer(modifier = Modifier.height(50.dp)) + + when(registrationState) { + RegistrationState.EmailSignIn -> { + EmailLoginView( + viewModel = viewModel, + onAuthProviderButtonTap = { + onRegistrationStateChange(RegistrationState.AuthProviderButtons) + } + ) + } + RegistrationState.AuthProviderButtons -> { + Text( + text = stringResource(id = R.string.welcome_title), + style = MaterialTheme.typography.headlineLarge + ) + + MoreInfoButton() + + Spacer(modifier = Modifier.height(50.dp)) + + AuthProviderView( + viewModel = viewModel, + onEmailButtonTap = { onRegistrationStateChange(RegistrationState.EmailSignIn) } + ) + } } - val snackBarHostState = remember { SnackbarHostState() } - val coroutineScope = rememberCoroutineScope() - val focusManager = LocalFocusManager.current + Spacer(modifier = Modifier.weight(1.0F)) + } - - Column( - verticalArrangement = Arrangement.SpaceAround, - horizontalAlignment = Alignment.Start, - modifier = Modifier - .background(Color(0xFFFBEAA8)) - .fillMaxSize() - .navigationBarsPadding() - .padding(horizontal = 16.dp) - .clickable { focusManager.clearFocus() } - ) { - Spacer(modifier = Modifier.height(50.dp)) - Image( - painter = painterResource(id = R.drawable.ic_omnivore_name_logo), - contentDescription = "Omnivore Icon with Name" - ) - Spacer(modifier = Modifier.height(50.dp)) - - Text( - text = stringResource(id = R.string.welcome_title), - style = MaterialTheme.typography.headlineLarge - ) - - MoreInfoButton() - - Spacer(modifier = Modifier.height(50.dp)) - - when(registrationState) { - RegistrationState.EmailSignIn -> { - EmailLoginView( - viewModel = viewModel, - onAuthProviderButtonTap = { - onRegistrationStateChange(RegistrationState.AuthProviderButtons) - } - ) - } - RegistrationState.AuthProviderButtons -> { - AuthProviderView( - viewModel = viewModel, - onEmailButtonTap = { onRegistrationStateChange(RegistrationState.EmailSignIn) } - ) - } - } - - Spacer(modifier = Modifier.weight(1.0F)) - } - - if (viewModel.errorMessage != null) { - coroutineScope.launch { - val result = snackBarHostState - .showSnackbar( - viewModel.errorMessage!!, - actionLabel = "Dismiss", - duration = SnackbarDuration.Indefinite - ) - when (result) { - SnackbarResult.ActionPerformed -> viewModel.resetErrorMessage() - } - } - - SnackbarHost(hostState = snackBarHostState) + if (viewModel.errorMessage != null) { + coroutineScope.launch { + val result = snackBarHostState + .showSnackbar( + viewModel.errorMessage!!, + actionLabel = "Dismiss", + duration = SnackbarDuration.Indefinite + ) + when (result) { + SnackbarResult.ActionPerformed -> viewModel.resetErrorMessage() + } } + + SnackbarHost(hostState = snackBarHostState) + } } @Composable fun AuthProviderView( - viewModel: LoginViewModel, - onEmailButtonTap: () -> Unit + viewModel: LoginViewModel, + onEmailButtonTap: () -> Unit ) { - val isGoogleAuthAvailable: Boolean = GoogleApiAvailability - .getInstance() - .isGooglePlayServicesAvailable(LocalContext.current) == 0 + val isGoogleAuthAvailable: Boolean = GoogleApiAvailability + .getInstance() + .isGooglePlayServicesAvailable(LocalContext.current) == 0 - Row( - horizontalArrangement = Arrangement.Center + Row( + horizontalArrangement = Arrangement.Center + ) { + Spacer(modifier = Modifier.weight(1.0F)) + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally ) { - Spacer(modifier = Modifier.weight(1.0F)) - Column( - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - if (isGoogleAuthAvailable) { - GoogleAuthButton(viewModel) - } + if (isGoogleAuthAvailable) { + GoogleAuthButton(viewModel) + } - LoadingButtonWithIcon( - text = "Continue with Apple", - loadingText = "Signing in...", - icon = painterResource(id = R.drawable.ic_logo_apple), - modifier = Modifier.padding(vertical = 6.dp), - onClick = {} - ) + LoadingButtonWithIcon( + text = "Continue with Apple", + loadingText = "Signing in...", + icon = painterResource(id = R.drawable.ic_logo_apple), + modifier = Modifier.padding(vertical = 6.dp), + onClick = {} + ) - ClickableText( - text = AnnotatedString("Continue with Email ->"), - onClick = { onEmailButtonTap() } - ) - } - Spacer(modifier = Modifier.weight(1.0F)) + ClickableText( + text = AnnotatedString("Continue with Email ->"), + onClick = { onEmailButtonTap() } + ) } + Spacer(modifier = Modifier.weight(1.0F)) + } } @Composable fun MoreInfoButton() { - val context = LocalContext.current - val intent = remember { Intent(Intent.ACTION_VIEW, Uri.parse("https://omnivore.app/about")) } + val context = LocalContext.current + val intent = remember { Intent(Intent.ACTION_VIEW, Uri.parse("https://omnivore.app/about")) } - ClickableText( - text = AnnotatedString("Learn More ->"), - style = MaterialTheme.typography.titleLarge, - onClick = { - context.startActivity(intent) - }, - modifier = Modifier.padding(vertical = 6.dp) - ) + ClickableText( + text = AnnotatedString("Learn More ->"), + style = MaterialTheme.typography.titleLarge, + onClick = { + context.startActivity(intent) + }, + modifier = Modifier.padding(vertical = 6.dp) + ) } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt index 1015fad71..11ce48e54 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/ui/home/HomeView.kt @@ -4,12 +4,14 @@ 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.padding import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import androidx.navigation.NavHostController import app.omnivore.omnivore.ui.auth.LoginViewModel @@ -21,6 +23,7 @@ fun HomeView(viewModel: LoginViewModel) { modifier = Modifier .background(MaterialTheme.colorScheme.background) .fillMaxSize() + .padding(horizontal = 6.dp) ) { Text("You have a valid auth token. Nice. Go save something in Chrome!")