add create user profile view
This commit is contained in:
@ -9,6 +9,7 @@ object Constants {
|
||||
object DatastoreKeys {
|
||||
const val omnivoreAuthToken = "omnivoreAuthToken"
|
||||
const val omnivoreAuthCookieString = "omnivoreAuthCookieString"
|
||||
const val omnivorePendingUserToken = "omnivorePendingUserToken"
|
||||
}
|
||||
|
||||
object AppleConstants {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -80,6 +80,9 @@ fun WelcomeScreenContent(viewModel: LoginViewModel) {
|
||||
|
||||
AuthProviderView(viewModel = viewModel)
|
||||
}
|
||||
RegistrationState.PendingUser -> {
|
||||
CreateUserProfileView(viewModel = viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.weight(1.0F))
|
||||
|
||||
Reference in New Issue
Block a user