Skip to content

Instantly share code, notes, and snippets.

@samrayner
Created October 4, 2025 06:40
Show Gist options
  • Select an option

  • Save samrayner/7eba8938e05a5018cd881e855b7b096b to your computer and use it in GitHub Desktop.

Select an option

Save samrayner/7eba8938e05a5018cd881e855b7b096b to your computer and use it in GitHub Desktop.
public class SignUpSystem(
initialState: State,
scopeProvider: ScopeProvider,
) : FeedbackSystem<SignUpSystem.State, SignUpSystem.Event> by feedbackSystem(
dependencies = Dependencies(),
initialState = initialState,
scope = scopeProvider.scope
) {
internal class Dependencies {
val form = FormSystem.Dependencies()
}
public data class State(
val isSubmitting: Boolean = false,
val form: FormSystem.State = FormSystem.State()
) : EffectsProvider<Effect> {
override fun effects(): Set<Effect> {
val result = mutableSetOf<Effect>()
result.addAll(form.effects().embed(Effect::Form))
if (isSubmitting) {
result.add(Effect.SubmitSignUp)
}
return result
}
}
public sealed class Event : Reducer<State, Event> {
public data object DidTapSubmitButton : Event()
public data object DidFinishSubmitting : Event()
public data class Form(val formEvent: FormSystem.Event) : Event()
override fun State.reduce(event: Event): State =
when (event) {
DidTapSubmitButton -> copy(isSubmitting = true)
DidFinishSubmitting -> copy(isSubmitting = false)
is Form -> copy(form = form.reduce(event.formEvent))
}
}
public sealed class Effect : EffectRunner<Dependencies, Event> {
internal data class Form(val formEffect: FormSystem.Effect) : Effect(), EffectRunner<Dependencies, Event> by embed(
effect = formEffect,
dependencies = Dependencies::form,
event = Event::Form
)
internal data object SubmitSignUp : Effect() {
override fun Dependencies.runEffect(): InfallibleFlow<Event> =
flow<Event> {
delay(2.seconds)
emit(Event.DidFinishSubmitting)
}.onExceptionLog()
}
}
}
// In the view:
@Composable
fun SignUpView(viewModelFactory: SystemViewModel.Factory<SignUpSystem.State, SignUpSystem.Event>) {
val viewModel = systemViewModel(viewModelFactory)
val state by viewModel.stateFlow.collectAsState()
SignUpFormView(
viewModel.scoped(
state = SignUpSystem.State::form,
event = SignUpSystem.Event::Form
)
)
if (state.isSubmitting) {
CircularProgressIndicator()
} else {
Button(onClick = {
viewModel.send(SignUpSystem.Event.DidTapSubmitButton)
}) {
Text("Submit")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment