Skip to content

Instantly share code, notes, and snippets.

View euri16's full-sized avatar

Eury Perez euri16

View GitHub Profile
custom-rules:
ManualEffectHandling:
active: true
your.package.name.MyCustomRuleSetProvider
class MyCustomRuleSetProvider : RuleSetProvider {
override val ruleSetId: String = "custom-rules"
override fun instance(config: Config) =
RuleSet(ruleSetId, listOf(LaunchedEffectWithEffectParamRule(config)))
}
class LaunchedEffectWithEffectParamRule(config: Config) : Rule(config) {
// ...
override fun visitCallExpression(expression: KtCallExpression) {
super.visitCallExpression(expression)
val calleeName = expression.calleeExpression?.text ?: return
if (calleeName != "LaunchedEffect") return
class LaunchedEffectWithEffectParamRule(config: Config) : Rule(config) {
private val effectNameCandidates = setOf(
"effect", "effects", "viewEffect", "uiEffect", "event", "viewEvent",
"viewModel.effect", "viewModel.effects", "viewModel.viewEffect",
"viewModel.event", "viewModel.viewEvent", "viewModel.uiEffect",
)
override val issue = Issue(
id = "ManualEffectHandling",
plugins {
kotlin("jvm") version "2.1.0" // Use version catalog
}
dependencies {
// Use version catalog instead
compileOnly("io.gitlab.arturbosch.detekt:detekt-api:1.23.8")
}
sealed interface UserProfileEvent {
data object DeleteAccount : UserProfileEvent
data object ConsumeEffect : UserProfileEvent
}
sealed interface UserProfileEffect {
data class ShowError(val message: String) : UserProfileEffect
data object NavigateToLogin : UserProfileEffect
}
@Composable
fun UserProfileScreen(
viewModel: UserProfileViewModel = hiltViewModel()
) {
// ...
EffectHandler(viewModel.viewEffect, viewModel::processEvent)
}
@Composable
@Composable
fun <EFFECT> LaunchedUiEffectHandler(
effectFlow: Flow<EFFECT?>,
onEffect: suspend (EFFECT) -> Unit,
onConsumeEffect: () -> Unit,
) {
val effect by effectFlow.collectAsStateWithLifecycle(null)
val currentOnEffect by rememberUpdatedState(onEffect)
val currentOnConsumeEffect by rememberUpdatedState(onConsumeEffect)
private fun deleteAccount() {
viewModelScope.launch {
// ...
try {
userRepository.deleteAccount()
_uiState.update {
it.copy(
isLoading = false,
effect = UserProfileEffect.NavigateToLogin