Guilherme Delgado
12/09/2023, 8:34 PMJacob Rhoda
01/19/2024, 4:16 PMJacob Rhoda
01/22/2024, 7:13 PMMikolaj
01/24/2024, 2:31 PMMikolaj Leszczynski
02/16/2024, 2:20 PMMikolaj Leszczynski
02/21/2024, 11:02 AMMikolaj Leszczynski
02/21/2024, 11:02 AMGuilherme Delgado
02/26/2024, 10:51 PMGuilherme Delgado
02/26/2024, 10:51 PMvicky7230
03/14/2024, 12:17 PMvicky7230
03/15/2024, 7:09 AMreduce
thread safe?vicky7230
03/16/2024, 10:45 AMGuilherme Delgado
05/09/2024, 3:14 PMGuilherme Delgado
05/09/2024, 3:15 PMappmattus
05/12/2024, 5:07 PMKshitij Patil
06/05/2024, 11:05 AMrunBlocking { }
in it's intent { }
extension function. runBlocking can throw InterruptedException
when thread being used for executing the coroutine gets interrupted for some reason. This results in a runtime crash. Is there any way to get around this crash?twisterrob
07/06/2024, 9:41 PMstefanus ayudha
07/16/2024, 12:48 PMstefanus ayudha
07/16/2024, 12:49 PM@Composable
fun LoginScreen(
/** States **/
viewModel: LoginViewModel = viewModel(),
onSuccess: (LoginResult) -> Unit,
onNavigateToRegistration: () -> Unit,
) {
val context = LocalContext.current
viewModel.collectSideEffect {
when (it) {
is LoginScreenEffect.LoginSuccess -> onSuccess.invoke(LoginResult())
is LoginScreenEffect.ShowToastError -> Toast.makeText(
context,
it.message,
Toast.LENGTH_SHORT
).show()
}
}
Box {
Column(modifier = Modifier.fillMaxSize()) {
Text(text = "Login Screen")
val state by viewModel.collectAsState()
val showLoading by remember(state.showLoginLoading) { derivedStateOf { state.showLoginLoading } }
if (showLoading)
CircularProgressIndicator()
Spacer(modifier = Modifier.weight(1f))
val emailError by remember(state.emailError) { derivedStateOf { state.emailError } }
val passwordError by remember(state.passwordError) { derivedStateOf { state.passwordError } }
LoginForm(
emailError = emailError,
passwordError = passwordError,
onEmailInput = { viewModel.updateEmail(it) },
onPasswordInput = { viewModel.updatePassword(it) }
)
val enableButton by remember(state) { derivedStateOf { state.enableSubmitButton } }
Button(
onClick = { viewModel.submitLogin() },
enabled = enableButton
) {
Text(text = "Login")
}
Spacer(modifier = Modifier.height(24.dp))
Button(
onClick = { onNavigateToRegistration.invoke() },
colors = ButtonDefaults.filledTonalButtonColors()
) {
Text(text = "Go To Registration")
}
Spacer(modifier = Modifier.weight(1f))
}
}
}
@Composable
fun LoginForm(
emailError: String,
passwordError: String,
onEmailInput: (String) -> Unit,
onPasswordInput: (String) -> Unit,
) {
Column {
var emailBuffer by remember { mutableStateOf("") }
TextField(
value = emailBuffer,
onValueChange = {
emailBuffer = it
onEmailInput.invoke(it)
},
isError = emailError.isNotBlank(),
)
if (emailError.isNotBlank())
Text(text = emailError, color = MaterialTheme.colorScheme.error)
var passwordBuffer by remember { mutableStateOf("") }
TextField(
value = passwordBuffer,
onValueChange = {
passwordBuffer = it
onPasswordInput.invoke(it)
},
isError = passwordError.isNotBlank()
)
if (passwordError.isNotBlank())
Text(text = passwordError, color = MaterialTheme.colorScheme.error)
}
}
The State:
@Immutable
@optics
data class LoginScreenSate(
val email: String = "",
val password: String = "",
val submitLoginDataState: VmState<LoginCredential> = VmIdle()
) {
companion object
val showLoginLoading: Boolean = submitLoginDataState is VmProcessing
val emailError: String
get() = when {
!email.matches(EmailPattern.toRegex()) -> "Format Salah"
else -> ""
}
val passwordError: String = when {
password.length < 10 -> "Pasword kurang panjang"
else -> ""
}
val enableSubmitButton =
emailError.isBlank() && passwordError.isBlank() && submitLoginDataState.fold(ifProcessing = { false }) { true }
}
The ViewModel
class LoginViewModel : ContainerHost<LoginScreenSate, LoginScreenEffect>, ViewModel() {
override val container: Container<LoginScreenSate, LoginScreenEffect> =
container(LoginScreenSate())
fun updateEmail(email: String) = intent {
reduce {
val lens = LoginScreenSate.email::set
lens(state, email)
}
}
fun updatePassword(password: String) = intent {
reduce {
val lens = LoginScreenSate.password
lens.set(state, password)
}
}
fun submitLogin() = intent {
val lens = LoginScreenSate.submitLoginDataState
reduce { lens.set(state, VmProcessing()) }
// do login stuff
val loginResultState = runBlocking {
delay(3000)
VmSuccess(LoginCredential())
}
// assume success
reduce { lens.set(state, loginResultState) }
postSideEffect(LoginScreenEffect.LoginSuccess(loginResultState.data))
}
}
stefanus ayudha
07/16/2024, 12:50 PMGuilherme Delgado
09/13/2024, 9:53 AMMikolaj Leszczynski
10/01/2024, 9:46 AMappmattus
10/02/2024, 11:39 AMappmattus
10/02/2024, 1:56 PMLaurence Muller
10/03/2024, 1:04 PMmacosX64
& macosArm64
)? Are there specific dependencies that need to be made compatible?
I got a macos desktop app using compose that builds in kotlin native (not jvm) and would love to use orbit in itdave08
10/07/2024, 2:03 PMDaniel (danflo)
10/25/2024, 6:46 PMKrzysiek Skorcz
11/26/2024, 11:39 AMSonu Sourav
12/04/2024, 1:16 PMfun example() {
intent {
fun1()
}
Log.d("sonusourav","intent 1")
intent {
fun2()
}
Log.d("sonusourav","intent 2")
intent {
fun3()
}
Log.d("sonusourav","intent 3")
}
Will the three functions be launched in parallel like launch? Sorry if this is very naive question, couldn't found a clear answer for this written anywhereStew Boling
03/03/2025, 1:53 AM