login refactoring

This commit is contained in:
Minecon724 2024-08-04 09:25:31 +02:00
parent fff16ca0fb
commit 5b27c8783e
Signed by: Minecon724
GPG key ID: 3CCC4D267742C8E8
3 changed files with 93 additions and 40 deletions

View file

@ -21,6 +21,7 @@ android {
}
// don't forget to add another "s this is counter intuitive I know but not my fault
buildConfigField("Boolean", "AUTO_LOGIN", "true")
buildConfigField("String", "VASTAI_KEY", "\"\"")
buildConfigField("String", "VASIAI_API_ENDPOINT", "\"https://cloud.vast.ai/api/v0\"")
}

View file

@ -92,6 +92,7 @@ class LoginActivity : ComponentActivity() {
}
}
if (BuildConfig.AUTO_LOGIN)
loginViewModel.loadKey()
enableEdgeToEdge()
@ -128,17 +129,11 @@ class LoginActivity : ComponentActivity() {
fun LoginApp(loginViewModel: LoginViewModel) {
val uiState by loginViewModel.uiState.collectAsState()
val loginErrorMessage by loginViewModel.error.observeAsState() // TODO put this in uiState
val apiKey by loginViewModel.apiKey.collectAsState()
val isIdle by remember(uiState) { derivedStateOf { uiState !is LoginUiState.Loading } }
var apiKey by rememberSaveable { mutableStateOf(BuildConfig.VASTAI_KEY) }
var advancedOpen by rememberSaveable { mutableStateOf(false) }
val transition = updateTransition(targetState = advancedOpen, label = "Advanced Menu Transition")
val arrowRotation by transition.animateFloat(label = "Advanced Menu Arrow Rotation") { state ->
if (state) 180f else 0f
}
Column(
modifier = Modifier
.width(300.dp)
@ -146,38 +141,25 @@ fun LoginApp(loginViewModel: LoginViewModel) {
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
TextField(
modifier = Modifier.fillMaxWidth(),
KeyTextField(
enabled = isIdle,
value = apiKey,
onValueChange = { apiKey = it },
label = { Text(text = stringResource(id = R.string.api_key)) },
visualTransformation = PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
textStyle = if (uiState is LoginUiState.Success) rainbowTextStyle() else LocalTextStyle.current,
singleLine = true,
apiKey = apiKey,
onValueChange = { loginViewModel.onApiKeyChange(it) },
rainbowText = uiState is LoginUiState.Success,
isError = loginErrorMessage != null
)
Spacer(modifier = Modifier.height(10.dp))
Row {
TextButton(
AdvancedOptionsButton(
enabled = isIdle,
onClick = {
advancedOpen = !advancedOpen
}
) {
Text(text = stringResource(id = R.string.advanced_options))
Icon(
imageVector = Icons.Filled.KeyboardArrowDown,
contentDescription = null,
modifier = Modifier.rotate(arrowRotation)
onClick = { advancedOpen = !advancedOpen },
isOpen = advancedOpen
)
}
Spacer(modifier = Modifier.weight(1f))
Button(
enabled = isIdle,
onClick = {
loginViewModel.tryLogin(apiKey)
loginViewModel.tryLogin()
}
) {
if (uiState is LoginUiState.Loading) {
@ -187,12 +169,62 @@ fun LoginApp(loginViewModel: LoginViewModel) {
}
}
}
AnimatedVisibility(visible = advancedOpen) {
AdvancedOptions()
}
}
}
@Composable
fun KeyTextField(
enabled: Boolean,
apiKey: String,
onValueChange: (String) -> Unit,
rainbowText: Boolean,
isError: Boolean
) {
TextField(
modifier = Modifier.fillMaxWidth(),
label = { Text(text = stringResource(id = R.string.api_key)) },
visualTransformation = PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
textStyle = if (rainbowText) rainbowTextStyle() else LocalTextStyle.current,
singleLine = true,
enabled = enabled,
value = apiKey,
onValueChange = onValueChange,
isError = isError
)
}
@Composable
fun AdvancedOptionsButton(
enabled: Boolean,
onClick: () -> Unit,
isOpen: Boolean
) {
val transition = updateTransition(targetState = isOpen, label = "Advanced Menu Transition")
val arrowRotation by transition.animateFloat(label = "Advanced Menu Arrow Rotation") { state ->
if (state) 180f else 0f
}
TextButton(
enabled = enabled,
onClick = onClick
) {
Text(text = stringResource(id = R.string.advanced_options))
Icon(
imageVector = Icons.Filled.KeyboardArrowDown,
contentDescription = null,
modifier = Modifier.rotate(arrowRotation)
)
}
}
@Composable
fun rainbowTextStyle(): TextStyle {
return LocalTextStyle.current.copy(brush = Brush.linearGradient(colors = listOf(
@ -207,6 +239,6 @@ fun rainbowTextStyle(): TextStyle {
}
@Composable
fun AdvancedOptions() { // TODO put this in viewmodel
fun AdvancedOptions() {
FunGame()
}

View file

@ -11,6 +11,7 @@ import eu.m724.vastapp.vastai.api.UserUrlRequestCallback
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import org.chromium.net.CronetEngine
import java.util.concurrent.Executor
@ -25,7 +26,10 @@ class LoginViewModel(
_uiState.asStateFlow()
private val _error = MutableLiveData<String?>(null)
val error: LiveData<String?> = _error // TODO put this in uistate
val error: LiveData<String?> = _error
private val _apiKey = MutableStateFlow<String>("")
var apiKey: StateFlow<String> = _apiKey.asStateFlow()
private val applicationContext = getApplication<Application>().applicationContext
private val sharedPreferences = applicationContext.getSharedPreferences("login", Context.MODE_PRIVATE)
@ -34,19 +38,34 @@ class LoginViewModel(
val apiKey = sharedPreferences.getString("apiKey", null)
if (apiKey != null) {
tryLogin(apiKey)
_apiKey.value = apiKey
tryLogin(LoginUiState.FullLoading)
}
}
fun tryLogin(apiKey: String) {
fun tryLogin() {
tryLogin(LoginUiState.Loading)
}
fun onApiKeyChange(apiKey: String) {
_apiKey.update { apiKey }
}
private fun saveKey() {
with (sharedPreferences.edit()) {
putString("apiKey", apiKey.value) // TODO encrypt
apply()
}
}
private fun tryLogin(initialState: LoginUiState) {
val apiKey = apiKey.value
val vastApi = VastApi(apiKey, cronetEngine, executor)
val request = vastApi.buildRequest(
ApiRoute.SHOW_USER,
UserUrlRequestCallback({ user ->
with (sharedPreferences.edit()) {
putString("apiKey", apiKey) // TODO encrypt
apply()
} // TODO toggle for this
saveKey() // TODO toggle for this
_uiState.value = LoginUiState.Success(user)
}, { apiFailure ->
_uiState.value = LoginUiState.Idle
@ -54,7 +73,8 @@ class LoginViewModel(
})
)
_uiState.value = LoginUiState.Loading
_uiState.value = initialState
request.start()
}
}