mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
add username validation
This commit is contained in:
parent
721226c6cc
commit
20f618a1e6
2 changed files with 99 additions and 26 deletions
|
|
@ -44,8 +44,13 @@ fun CreateUserProfileView(viewModel: LoginViewModel) {
|
|||
UserProfileFields(
|
||||
name = name,
|
||||
username = username,
|
||||
usernameValidationErrorMessage = viewModel.usernameValidationErrorMessage,
|
||||
showUsernameAsAvailable = viewModel.hasValidUsername,
|
||||
onNameChange = { name = it },
|
||||
onUsernameChange = { username = it },
|
||||
onUsernameChange = {
|
||||
username = it
|
||||
viewModel.validateUsername(it)
|
||||
},
|
||||
onSubmit = { } // TODO: add viewModel function
|
||||
)
|
||||
|
||||
|
|
@ -70,6 +75,8 @@ fun CreateUserProfileView(viewModel: LoginViewModel) {
|
|||
fun UserProfileFields(
|
||||
name: String,
|
||||
username: String,
|
||||
usernameValidationErrorMessage: String?,
|
||||
showUsernameAsAvailable: Boolean, // TODO: use this to add green checkmark
|
||||
onNameChange: (String) -> Unit,
|
||||
onUsernameChange: (String) -> Unit,
|
||||
onSubmit: () -> Unit
|
||||
|
|
@ -84,15 +91,6 @@ fun UserProfileFields(
|
|||
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") },
|
||||
|
|
@ -102,21 +100,44 @@ fun UserProfileFields(
|
|||
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()
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(5.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() })
|
||||
)
|
||||
|
||||
if (usernameValidationErrorMessage != null) {
|
||||
Text(
|
||||
text = usernameValidationErrorMessage!!,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
}
|
||||
}, colors = ButtonDefaults.buttonColors(
|
||||
contentColor = Color(0xFF3D3D3D),
|
||||
containerColor = Color(0xffffd234)
|
||||
)
|
||||
}
|
||||
|
||||
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",
|
||||
|
|
|
|||
|
|
@ -5,16 +5,21 @@ import androidx.compose.runtime.mutableStateOf
|
|||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.*
|
||||
import app.omnivore.omnivore.*
|
||||
import app.omnivore.omnivore.graphql.generated.SearchQuery
|
||||
import app.omnivore.omnivore.graphql.generated.ValidateUsernameQuery
|
||||
import com.apollographql.apollo3.ApolloClient
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
||||
import com.google.android.gms.common.api.ApiException
|
||||
import com.google.android.gms.tasks.Task
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
enum class RegistrationState {
|
||||
SocialLogin,
|
||||
EmailSignIn,
|
||||
|
|
@ -25,18 +30,26 @@ enum class RegistrationState {
|
|||
class LoginViewModel @Inject constructor(
|
||||
private val datastoreRepo: DatastoreRepository
|
||||
): ViewModel() {
|
||||
private var validateUsernameJob: Job? = null
|
||||
|
||||
var isLoading by mutableStateOf(false)
|
||||
private set
|
||||
|
||||
var errorMessage by mutableStateOf<String?>(null)
|
||||
private set
|
||||
|
||||
var hasValidUsername by mutableStateOf<Boolean>(false)
|
||||
private set
|
||||
|
||||
var usernameValidationErrorMessage by mutableStateOf<String?>(null)
|
||||
private set
|
||||
|
||||
val hasAuthTokenLiveData: LiveData<Boolean> = datastoreRepo
|
||||
.hasAuthTokenFlow
|
||||
.distinctUntilChanged()
|
||||
.asLiveData()
|
||||
|
||||
val registrationStateLiveData = MutableLiveData(RegistrationState.SocialLogin)
|
||||
val registrationStateLiveData = MutableLiveData(RegistrationState.PendingUser) // TODO: switch back to Social
|
||||
|
||||
fun getAuthCookieString(): String? = runBlocking {
|
||||
datastoreRepo.getString(DatastoreKeys.omnivoreAuthCookieString)
|
||||
|
|
@ -57,6 +70,45 @@ class LoginViewModel @Inject constructor(
|
|||
showSocialLogin()
|
||||
}
|
||||
|
||||
fun validateUsername(potentialUsername: String) {
|
||||
validateUsernameJob?.cancel()
|
||||
|
||||
validateUsernameJob = viewModelScope.launch {
|
||||
delay(500)
|
||||
|
||||
// Check the username requirements first
|
||||
if (potentialUsername.isEmpty()) {
|
||||
usernameValidationErrorMessage = null
|
||||
hasValidUsername = false
|
||||
return@launch
|
||||
}
|
||||
|
||||
if (potentialUsername.length < 4 || potentialUsername.length > 15) {
|
||||
usernameValidationErrorMessage = "Username must be between 4 and 15 characters long."
|
||||
hasValidUsername = false
|
||||
return@launch
|
||||
}
|
||||
|
||||
// TODO: check email regex
|
||||
|
||||
val apolloClient = ApolloClient.Builder()
|
||||
.serverUrl("${Constants.apiURL}/api/graphql")
|
||||
.build()
|
||||
|
||||
val response = apolloClient.query(
|
||||
ValidateUsernameQuery(username = potentialUsername)
|
||||
).execute()
|
||||
|
||||
if (response.data?.validateUsername == true) {
|
||||
usernameValidationErrorMessage = null
|
||||
hasValidUsername = true
|
||||
} else {
|
||||
hasValidUsername = false
|
||||
usernameValidationErrorMessage = "This username is not available."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun login(email: String, password: String) {
|
||||
val emailLogin = RetrofitHelper.getInstance().create(EmailLoginSubmit::class.java)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue