Skip to content

Instantly share code, notes, and snippets.

View motorro's full-sized avatar

Nikolai Kotchetkov motorro

View GitHub Profile
@motorro
motorro / LoginStateFactory.kt
Created August 7, 2022 13:22
Login state factory interface
interface LoginStateFactory {
/**
* Creates a state to handle existing user's password entry
* @param data Login data state
*/
fun passwordEntry(data: LoginDataState): LoginState
/**
* Creates a state to check email/password
* @param data Data state
@motorro
motorro / CredentialsCheckState.kt
Created August 7, 2022 13:15
Complete state with dependencies
class CredentialsCheckState(
context: LoginContext,
private val data: LoginDataState,
private val checkCredentials: CheckCredentials
) : LoginState(context) {
override fun doStart() {
// Use a context-provided dependency
setUiState(renderer.renderLoading(data))
}
@motorro
motorro / LoginState.kt
Created August 7, 2022 13:08
Base state with context
abstract class LoginState(
context: LoginContext
): CoroutineState<LoginGesture, LoginUiState>(), LoginContext by context {
override fun doProcess(gesture: LoginGesture) {
Timber.w("Unsupported gesture: %s", gesture)
}
}
@motorro
motorro / LoginContext.kt
Created August 7, 2022 12:59
Login context
interface LoginContext {
/**
* Common state factory (see below)
*/
val factory: LoginStateFactory
/**
* External interface
*/
val host: WelcomeFeatureHost
@motorro
motorro / InterStateToConstructor.kt
Last active August 7, 2022 13:09
Inter-state data passing
class CredentialsCheckState(data: LoginDataState): CoroutineState<LoginGesture, LoginUiState>() {
/**
* Should have valid email at this point passed with inter-state data
*/
private val email = requireNotNull(data.commonData.email) {
"Email is not provided"
}
/**
@motorro
motorro / DedicatedStateFactory.kt
Last active August 7, 2022 19:23
Dedicated state factory
class CredentialsCheckState(
data: LoginDataState,
private val checkCredentials: CheckCredentials
) : CoroutineState<LoginGesture, LoginUiState>() {
// State logic
/**
* Dedicated state factory
*/
@motorro
motorro / LoginStateRenderer.kt
Created July 31, 2022 18:39
UI-state renderer
internal class LoginRenderer {
/**
* Renders password form
*/
fun renderPassword(
data: LoginDataState,
isValid: Boolean
): LoginUiState.PasswordEntry = LoginUiState.PasswordEntry(
data.email,
data.password.orEmpty(),
@motorro
motorro / CredentialsCheckState.kt
Created July 31, 2022 18:27
Injecting use-case to your state
class CredentialsCheckState(private val checkCredentials: CheckCredentials) {
// State logic
override fun doStart() {
stateScope.launch {
// Runs use-case
val valid = checkCredentials()
}
}
@motorro
motorro / LceScreen.kt
Created July 31, 2022 17:26
LCE view
@Composable
fun LceScreen(onExit: @Composable () -> Unit) {
val model: LceViewModel = viewModel()
val state = model.state.collectAsState(LceUiState.Loading)
BackHandler(onBack = { model.process(Back) })
Scaffold(
modifier = Modifier.fillMaxSize(),
backgroundColor = MaterialTheme.colors.background,
@motorro
motorro / LceViewModel.kt
Created July 31, 2022 16:38
LCE view model
class LceViewModel : ViewModel() {
private fun initStateMachine(): CommonMachineState<LceGesture, LceUiState> = ItemListState()
private val stateMachine = FlowStateMachine(::initStateMachine)
val state: SharedFlow<LceUiState> = stateMachine.uiState
fun process(gesture: LceGesture) {
stateMachine.process(gesture)