
me.aartikov.sesame.loading.paged.internal.PagedLoadingLoop.kt Maven / Gradle / Ivy
package me.aartikov.sesame.loading.paged.internal
import me.aartikov.sesame.loading.paged.DataMerger
import me.aartikov.sesame.loading.paged.Page
import me.aartikov.sesame.loading.paged.PagedLoading.*
import me.aartikov.sesame.loading.paged.PagingInfo
import me.aartikov.sesame.loop.*
internal sealed class Action {
data class LoadFirstPage(val fresh: Boolean, val reset: Boolean) : Action()
object LoadMore : Action()
data class Cancel(val reset: Boolean) : Action()
data class MutateData(val transform: (List) -> List) : Action()
data class NewPageLoaded(val page: Page) : Action()
object EmptyPageLoaded : Action()
data class LoadingError(val throwable: Throwable) : Action()
}
internal sealed class Effect {
data class LoadFirstPage(val fresh: Boolean) : Effect()
data class LoadNextPage(val pagingInfo: PagingInfo) : Effect()
object CancelLoading : Effect()
data class EmitEvent(val event: Event) : Effect()
}
internal typealias PagedLoadingLoop = Loop, Action, Effect>
internal class PagedLoadingReducer(
private val dataMerger: DataMerger
) : Reducer, Action, Effect> {
override fun reduce(state: State, action: Action): Next, Effect> = when (action) {
is Action.LoadFirstPage -> {
if (action.reset) {
next(
State.Loading,
Effect.LoadFirstPage(action.fresh)
)
} else {
when (state) {
is State.Empty -> next(
State.Loading,
Effect.LoadFirstPage(action.fresh)
)
is State.Error -> next(
State.Loading,
Effect.LoadFirstPage(action.fresh)
)
is State.Data -> when (state.status) {
DataStatus.Normal, DataStatus.LoadingMore, DataStatus.FullData -> next(
State.Data(state.pageCount, state.data, status = DataStatus.Refreshing),
Effect.LoadFirstPage(action.fresh)
)
else -> nothing()
}
else -> nothing()
}
}
}
is Action.LoadMore -> {
when (state) {
is State.Data -> when (state.status) {
DataStatus.Normal -> next(
State.Data(state.pageCount, state.data, status = DataStatus.LoadingMore),
Effect.LoadNextPage(PagingInfo(state.pageCount, state.data))
)
else -> nothing()
}
else -> nothing()
}
}
is Action.Cancel -> {
if (action.reset) {
next(
State.Empty,
Effect.CancelLoading
)
} else {
when (state) {
is State.Loading -> next(
State.Empty,
Effect.CancelLoading
)
is State.Data -> when (state.status) {
DataStatus.Refreshing, DataStatus.LoadingMore -> next(
State.Data(state.pageCount, state.data),
Effect.CancelLoading
)
else -> nothing()
}
else -> nothing()
}
}
}
is Action.NewPageLoaded -> {
when (state) {
is State.Loading -> next(
State.Data(
1,
action.page.data,
status = if (action.page.hasNextPage) DataStatus.Normal else DataStatus.FullData
)
)
is State.Data -> when (state.status) {
DataStatus.Refreshing -> next(
State.Data(
1,
action.page.data,
status = if (action.page.hasNextPage) DataStatus.Normal else DataStatus.FullData
)
)
DataStatus.LoadingMore -> next(
State.Data(
state.pageCount + 1,
dataMerger.merge(state.data, action.page.data),
status = if (action.page.hasNextPage) DataStatus.Normal else DataStatus.FullData
)
)
else -> nothing()
}
else -> nothing()
}
}
is Action.EmptyPageLoaded -> {
when (state) {
is State.Loading -> next(State.Empty)
is State.Data -> when (state.status) {
DataStatus.Refreshing -> next(State.Empty)
DataStatus.LoadingMore -> next(
State.Data(
state.pageCount,
state.data,
DataStatus.FullData
)
)
else -> nothing()
}
else -> nothing()
}
}
is Action.LoadingError -> {
when (state) {
is State.Loading -> next(
State.Error(action.throwable),
Effect.EmitEvent(Event.Error(action.throwable, state))
)
is State.Data -> when (state.status) {
DataStatus.Refreshing, DataStatus.LoadingMore -> next(
State.Data(state.pageCount, state.data),
Effect.EmitEvent(Event.Error(action.throwable, state))
)
else -> nothing()
}
else -> nothing()
}
}
is Action.MutateData -> {
when (state) {
is State.Data -> {
val newData = action.transform(state.data)
when {
newData.isNotEmpty() -> next(state.copy(data = newData))
state.status == DataStatus.Refreshing -> next(State.Loading)
else -> next(State.Empty)
}
}
else -> nothing()
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy