add create user profile view

This commit is contained in:
Satindar Dhillon
2022-09-08 13:49:34 -07:00
parent 868a24a608
commit 7d1f1ef6fc
5 changed files with 154 additions and 3 deletions

View File

@ -9,6 +9,7 @@ object Constants {
object DatastoreKeys {
const val omnivoreAuthToken = "omnivoreAuthToken"
const val omnivoreAuthCookieString = "omnivoreAuthCookieString"
const val omnivorePendingUserToken = "omnivorePendingUserToken"
}
object AppleConstants {

View File

@ -16,6 +16,7 @@ interface DatastoreRepository {
suspend fun putInt(key: String, value: Int)
suspend fun getString(key: String): String?
suspend fun getInt(key: String): Int?
suspend fun clearValue(key: String)
}
class OmnivoreDatastore @Inject constructor(
@ -55,6 +56,11 @@ class OmnivoreDatastore @Inject constructor(
context.dataStore.edit { it.clear() }
}
override suspend fun clearValue(key: String) {
val preferencesKey = stringPreferencesKey(key)
context.dataStore.edit { it.remove(preferencesKey) }
}
override val hasAuthTokenFlow: Flow<Boolean> = context
.dataStore.data.map { preferences ->
val key = stringPreferencesKey(DatastoreKeys.omnivoreAuthToken)

View File

@ -0,0 +1,127 @@
package app.omnivore.omnivore.ui.auth
import android.annotation.SuppressLint
import android.widget.Toast
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.ClickableText
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.dp
import app.omnivore.omnivore.R
@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun CreateUserProfileView(viewModel: LoginViewModel) {
var name by rememberSaveable { mutableStateOf("") }
var username by rememberSaveable { mutableStateOf("") }
Row(
horizontalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.weight(1.0F))
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Create Your Profile",
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.padding(bottom = 8.dp)
)
UserProfileFields(
name = name,
username = username,
onNameChange = { name = it },
onUsernameChange = { username = it },
onSubmit = { } // TODO: add viewModel function
)
// TODO: add a activity indicator (maybe after a delay?)
if (viewModel.isLoading) {
Text("Loading...")
}
ClickableText(
text = AnnotatedString("Cancel Sign Up"),
style = MaterialTheme.typography.titleMedium
.plus(TextStyle(textDecoration = TextDecoration.Underline)),
onClick = { viewModel.cancelNewUserSignUp() }
)
}
Spacer(modifier = Modifier.weight(1.0F))
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun UserProfileFields(
name: String,
username: String,
onNameChange: (String) -> Unit,
onUsernameChange: (String) -> Unit,
onSubmit: () -> Unit
) {
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 = username,
placeholder = { Text(text = "Username") },
label = { Text(text = "Username") },
onValueChange = onUsernameChange,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() })
)
OutlinedTextField(
value = name,
placeholder = { Text(text = "Name") },
label = { Text(text = "Name") },
onValueChange = onNameChange,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() })
)
Button(onClick = {
if (name.isNotBlank() && username.isNotBlank()) {
onSubmit()
focusManager.clearFocus()
} else {
Toast.makeText(
context,
"Please enter a valid username and password.",
Toast.LENGTH_SHORT
).show()
}
}, colors = ButtonDefaults.buttonColors(
contentColor = Color(0xFF3D3D3D),
containerColor = Color(0xffffd234)
)
) {
Text(
text = "Submit",
modifier = Modifier.padding(horizontal = 100.dp)
)
}
}
}

View File

@ -17,7 +17,8 @@ import javax.inject.Inject
enum class RegistrationState {
SocialLogin,
EmailSignIn
EmailSignIn,
PendingUser
}
@HiltViewModel
@ -35,7 +36,7 @@ class LoginViewModel @Inject constructor(
.distinctUntilChanged()
.asLiveData()
val registrationStateLiveData = MutableLiveData(RegistrationState.SocialLogin)
val registrationStateLiveData = MutableLiveData(RegistrationState.PendingUser) // TODO: set back to social login
fun getAuthCookieString(): String? = runBlocking {
datastoreRepo.getString(DatastoreKeys.omnivoreAuthCookieString)
@ -49,6 +50,13 @@ class LoginViewModel @Inject constructor(
registrationStateLiveData.value = RegistrationState.EmailSignIn
}
fun cancelNewUserSignUp() {
viewModelScope.launch {
datastoreRepo.clearValue(DatastoreKeys.omnivorePendingUserToken)
}
showSocialLogin()
}
fun login(email: String, password: String) {
val emailLogin = RetrofitHelper.getInstance().create(EmailLoginSubmit::class.java)
@ -163,9 +171,15 @@ class LoginViewModel @Inject constructor(
isLoading = false
if (result.body()?.pendingUserToken != null) {
// store in datastore
datastoreRepo.putString(
DatastoreKeys.omnivorePendingUserToken, result.body()?.pendingUserToken!!
)
registrationStateLiveData.value = RegistrationState.PendingUser
} else {
errorMessage = "Something went wrong. Please check your credentials and try again"
}
}
}
// TODO: set registrationState to pending if user has pending token

View File

@ -80,6 +80,9 @@ fun WelcomeScreenContent(viewModel: LoginViewModel) {
AuthProviderView(viewModel = viewModel)
}
RegistrationState.PendingUser -> {
CreateUserProfileView(viewModel = viewModel)
}
}
Spacer(modifier = Modifier.weight(1.0F))