store

Enables state management using a reducer pattern, focusing on handling actions, states, and side effects. Offers a structured approach to building applications with a clear state flow.

JVM
iOS
Android Native
macOS
watchOS
tvOS
Linux
Windows
Wasm
JS
GitHub stars1
Authorsfloschu
Dependents0
LicenseApache License 2.0
Creation datealmost 5 years ago

Last activity4 days ago
Latest release0.5.0 (8 months ago)

flow

version

build last commit license

installation

repositories {
    mavenCentral()
}

dependencies {
    implementation("at.florianschuster.store:store:$version")
}

see changelog for versions

usage

Go to store as entry point for more information.

class LoginEnvironment(
    val authenticationService: AuthenticationService,
    val tokenRepository: TokenRepository,
)

sealed interface LoginAction {
    data class EmailChanged(val value: String): LoginAction
    data class PasswordChanged(val value: String): LoginAction
    data object Login: LoginAction
    data class LoginResult(val result: Result<Token>): LoginAction
}

data class LoginState(
    val emailAddress: String = "",
    val password: String = "",
    val loading: Boolean = false,
    val displayLoginError: Boolean = false,
) {
    val isInputValid = emailAddress.isNotEmpty() && password.isNotEmpty()
}

val LoginReducer = Reducer<LoginEnvironment, LoginAction, LoginState> { previousState, action ->
    when(action) {
        is LoginAction.EmailChanged -> previousState.copy(emailAddress = action.value)
        is LoginAction.PasswordChanged -> previousState.copy(password = action.value)
        is LoginAction.Login -> {
            if(!previousState.isInputValid) return@Reducer previousState
            cancelEffect(id = LoginAction.Login) // if an authentication is already in progress, we cancel it
            effect(id = LoginAction.Login) {
                val result = environment.authenticationService.authenticate(
                    previousState.emailAddress,
                    previousState.password,
                )
                dispatch(LoginAction.LoginResult(result))
            }
            previousState.copy(
                loading = true,
                displayLoginError = false
            )
        }
        is LoginAction.LoginResult -> {
            action.result.onSuccess { token ->
                effect(id = LoginAction.LoginResult::class) {
                    environment.tokenRepository.store(token)
                }
            }
            previousState.copy(
                loading = false,
                displayLoginError = action.result.isFailure
            )
        }
    }
}

class LoginStore(
    effectScope: CoroutineScope,
    environment: LoginEnvironment,
): Store<LoginEnvironment, LoginAction, LoginState> by Store(
    initialState = LoginState(),
    environment = environment,
    effectScope = effectScope,
    reducer = LoginReducer,
)

A more complex Compose Multiplatform example can be found in the example directory.

Check out the store skill to implement and test store with your AI agents.

author

visit my website.

JVM
iOS
Android Native
macOS
watchOS
tvOS
Linux
Windows
Wasm
JS
GitHub stars1
Authorsfloschu
Dependents0
LicenseApache License 2.0
Creation datealmost 5 years ago

Last activity4 days ago
Latest release0.5.0 (8 months ago)

flow

version

build last commit license

installation

repositories {
    mavenCentral()
}

dependencies {
    implementation("at.florianschuster.store:store:$version")
}

see changelog for versions

usage

Go to store as entry point for more information.

class LoginEnvironment(
    val authenticationService: AuthenticationService,
    val tokenRepository: TokenRepository,
)

sealed interface LoginAction {
    data class EmailChanged(val value: String): LoginAction
    data class PasswordChanged(val value: String): LoginAction
    data object Login: LoginAction
    data class LoginResult(val result: Result<Token>): LoginAction
}

data class LoginState(
    val emailAddress: String = "",
    val password: String = "",
    val loading: Boolean = false,
    val displayLoginError: Boolean = false,
) {
    val isInputValid = emailAddress.isNotEmpty() && password.isNotEmpty()
}

val LoginReducer = Reducer<LoginEnvironment, LoginAction, LoginState> { previousState, action ->
    when(action) {
        is LoginAction.EmailChanged -> previousState.copy(emailAddress = action.value)
        is LoginAction.PasswordChanged -> previousState.copy(password = action.value)
        is LoginAction.Login -> {
            if(!previousState.isInputValid) return@Reducer previousState
            cancelEffect(id = LoginAction.Login) // if an authentication is already in progress, we cancel it
            effect(id = LoginAction.Login) {
                val result = environment.authenticationService.authenticate(
                    previousState.emailAddress,
                    previousState.password,
                )
                dispatch(LoginAction.LoginResult(result))
            }
            previousState.copy(
                loading = true,
                displayLoginError = false
            )
        }
        is LoginAction.LoginResult -> {
            action.result.onSuccess { token ->
                effect(id = LoginAction.LoginResult::class) {
                    environment.tokenRepository.store(token)
                }
            }
            previousState.copy(
                loading = false,
                displayLoginError = action.result.isFailure
            )
        }
    }
}

class LoginStore(
    effectScope: CoroutineScope,
    environment: LoginEnvironment,
): Store<LoginEnvironment, LoginAction, LoginState> by Store(
    initialState = LoginState(),
    environment = environment,
    effectScope = effectScope,
    reducer = LoginReducer,
)

A more complex Compose Multiplatform example can be found in the example directory.

Check out the store skill to implement and test store with your AI agents.

author

visit my website.