Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work on generics in ResourceState #152

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/mvvm-state/scripts/pages.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions mvvm-state/api/mvvm-state.api
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public abstract class dev/icerock/moko/mvvm/ResourceState {
}

public final class dev/icerock/moko/mvvm/ResourceState$Empty : dev/icerock/moko/mvvm/ResourceState {
public fun <init> ()V
public static final field INSTANCE Ldev/icerock/moko/mvvm/ResourceState$Empty;
}

public final class dev/icerock/moko/mvvm/ResourceState$Failed : dev/icerock/moko/mvvm/ResourceState {
Expand All @@ -23,7 +23,7 @@ public final class dev/icerock/moko/mvvm/ResourceState$Failed : dev/icerock/moko
}

public final class dev/icerock/moko/mvvm/ResourceState$Loading : dev/icerock/moko/mvvm/ResourceState {
public fun <init> ()V
public static final field INSTANCE Ldev/icerock/moko/mvvm/ResourceState$Loading;
}

public final class dev/icerock/moko/mvvm/ResourceState$Success : dev/icerock/moko/mvvm/ResourceState {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@

package dev.icerock.moko.mvvm

sealed class ResourceState<out T, out E> {
data class Success<out T, out E>(val data: T) : ResourceState<T, E>()
data class Failed<out T, out E>(val error: E) : ResourceState<T, E>()
class Loading<out T, out E> : ResourceState<T, E>()
class Empty<out T, out E> : ResourceState<T, E>()
sealed class ResourceState<out TData, out TError> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this change should support simple automatically migration if we want to merge it...try to write some regexp which will allow us and others migrate to new version in minutes on any size of project codebase

data class Success<out TData>(val data: TData) : ResourceState<TData, Nothing>()
data class Failed<out TError>(val error: TError) : ResourceState<Nothing, TError>()
object Loading : ResourceState<Nothing, Nothing>()
object Empty : ResourceState<Nothing, Nothing>()
Comment on lines +8 to +11
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in common:

class Test {
    val myData: ResourceState<Int, String> = ResourceState.Success(10)
}

try on swift:

func test() {
    let test = Test()
    let data = test.myData as? ResourceStateSuccess<Int>
    let data2: ResourceStateSuccess<Int> = test.myData.asSuccess()
}


fun isLoading(): Boolean = this is Loading
fun isSuccess(): Boolean = this is Success
fun isEmpty(): Boolean = this is Empty
fun isFailed(): Boolean = this is Failed

fun dataValue(): T? = (this as? Success)?.data
fun dataValue(): TData? = (this as? Success)?.data

fun errorValue(): E? = (this as? Failed)?.error
fun errorValue(): TError? = (this as? Failed)?.error
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fun <T, E> T?.asState(whenNull: () -> ResourceState<T, E>): ResourceState<T, E>
this?.asState() ?: whenNull()

fun <T, E> List<T>.asState(): ResourceState<List<T>, E> = if (this.isEmpty()) {
ResourceState.Empty()
ResourceState.Empty
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should also add into release notes guide to migration. please add migration regexp to pr description, we will add it into release notes later

} else {
ResourceState.Success(this)
}
Expand All @@ -20,7 +20,7 @@ fun <T, E> List<T>?.asState(whenNull: () -> ResourceState<List<T>, E>): Resource
this?.asState() ?: whenNull()

inline fun <reified T, reified E> ResourceState<T, E>?.nullAsEmpty(): ResourceState<T, E> =
this ?: ResourceState.Empty()
this ?: ResourceState.Empty

inline fun <reified T, reified E> ResourceState<T, E>?.nullAsLoading(): ResourceState<T, E> =
this ?: ResourceState.Loading()
this ?: ResourceState.Loading
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,23 @@ fun <T, E> LiveData<ResourceState<T, E>>.isEmptyState(): LiveData<Boolean> = map
fun <T, E, ST : ResourceState<T, E>, LD : LiveData<out ST>> List<LD>.isSuccessState(): LiveData<Boolean> =
MediatorLiveData(false)
.composition(this) { list ->
list.firstOrNull { it !is ResourceState.Success<*, *> } == null
list.firstOrNull { it !is ResourceState.Success<*> } == null
}

fun <T, E, ST : ResourceState<T, E>, LD : LiveData<out ST>> List<LD>.isLoadingState(): LiveData<Boolean> =
MediatorLiveData(false)
.composition(this) { list ->
list.firstOrNull { it is ResourceState.Loading<*, *> } != null
list.firstOrNull { it is ResourceState.Loading } != null
}

fun <T, E, ST : ResourceState<T, E>, LD : LiveData<out ST>> List<LD>.isErrorState(): LiveData<Boolean> =
MediatorLiveData(false)
.composition(this) { list ->
list.firstOrNull { it is ResourceState.Failed<*, *> } != null
list.firstOrNull { it is ResourceState.Failed<*> } != null
}

fun <T, E, ST : ResourceState<T, E>, LD : LiveData<out ST>> List<LD>.isEmptyState(): LiveData<Boolean> =
MediatorLiveData(false)
.composition(this) { list ->
list.firstOrNull { it is ResourceState.Empty<*, *> } != null
list.firstOrNull { it is ResourceState.Empty } != null
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ fun <T, E> LiveData<ResourceState<T, E>>.error(): LiveData<E?> = map { it.errorV

fun <T, E> LiveData<ResourceState<T, E>>.errorValue(): E? = value.errorValue()

fun <T, E, ST : ResourceState<T, E>, LD : LiveData<out ST>> List<LD>.error(): LiveData<E?> =
fun <E, ST : ResourceState<Nothing, E>, LD : LiveData<out ST>> List<LD>.error(): LiveData<E?> =
MediatorLiveData<E?>(null)
.composition(this) { list ->
@Suppress("UNCHECKED_CAST")
val errorItem = list.firstOrNull {
(it is ResourceState.Failed<*, *>)
} as? ResourceState.Failed<T, E>
(it is ResourceState.Failed<*>)
} as? ResourceState.Failed<E>
errorItem?.error
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ fun <T1, E, T2, OT> LiveData<ResourceState<T1, E>>.concatData(
): LiveData<ResourceState<OT, E>> =
mergeWith(liveData) { firstState, secondState ->
val state: ResourceState<OT, E> = when {
(firstState is ResourceState.Loading || secondState is ResourceState.Loading) -> ResourceState.Loading()
(firstState is ResourceState.Loading || secondState is ResourceState.Loading) -> ResourceState.Loading
(firstState is ResourceState.Failed) -> ResourceState.Failed(firstState.error)
(secondState is ResourceState.Failed) -> ResourceState.Failed(secondState.error)
(firstState is ResourceState.Empty || secondState is ResourceState.Empty) -> ResourceState.Empty()
(firstState is ResourceState.Empty || secondState is ResourceState.Empty) -> ResourceState.Empty
(firstState is ResourceState.Success && secondState is ResourceState.Success) -> ResourceState.Success(
function(
firstState.data,
secondState.data
)
)
else -> ResourceState.Empty()
else -> ResourceState.Empty
}

state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ fun <IT, E, OT> LiveData<ResourceState<IT, E>>.dataTransform(transform: LiveData
when (state) {
is ResourceState.Success -> transform.invoke(MutableLiveData(state.data))
.map { ResourceState.Success(it) }
is ResourceState.Loading -> MutableLiveData(ResourceState.Loading())
is ResourceState.Empty -> MutableLiveData(ResourceState.Empty())
is ResourceState.Loading -> MutableLiveData(ResourceState.Loading)
is ResourceState.Empty -> MutableLiveData(ResourceState.Empty)
is ResourceState.Failed -> MutableLiveData(ResourceState.Failed(state.error))
}
}
Expand All @@ -21,10 +21,10 @@ fun <T, IE, OE> LiveData<ResourceState<T, IE>>.errorTransform(transform: LiveDat
LiveData<ResourceState<T, OE>> = flatMap { state ->
when (state) {
is ResourceState.Success -> MutableLiveData(ResourceState.Success(state.data))
is ResourceState.Loading -> MutableLiveData(ResourceState.Loading())
is ResourceState.Empty -> MutableLiveData(ResourceState.Empty())
is ResourceState.Loading -> MutableLiveData(ResourceState.Loading)
is ResourceState.Empty -> MutableLiveData(ResourceState.Empty)
is ResourceState.Failed -> transform.invoke(MutableLiveData(state.error))
.map { ResourceState.Failed<T, OE>(it) }
.map { ResourceState.Failed(it) }
}
}

Expand All @@ -47,7 +47,7 @@ fun <T, E> LiveData<ResourceState<T, E>>.emptyAsData(dataBuilder: () -> T):
fun <T, E> LiveData<ResourceState<T, E>>.emptyIf(emptyPredicate: (T) -> Boolean):
LiveData<ResourceState<T, E>> = map {
when {
it is ResourceState.Success && emptyPredicate(it.data) -> ResourceState.Empty()
it is ResourceState.Success && emptyPredicate(it.data) -> ResourceState.Empty
else -> it
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class LiveDataTest {
@Test
fun `dataTransform + mergeWith test`() {
val vmIsAuthorized = MutableLiveData(true)
val state: MutableLiveData<ResourceState<Int, Throwable>> = MutableLiveData(ResourceState.Empty())
val state: MutableLiveData<ResourceState<Int, Throwable>> = MutableLiveData(ResourceState.Empty)
val isLoading: MutableLiveData<Boolean> = MutableLiveData<Boolean>(false)

var dataTransformCounter = 0
Expand Down Expand Up @@ -91,7 +91,7 @@ class LiveDataTest {
assertEquals(actual = mergeWithIsAuthorizedCounter, expected = 3)
assertTrue { result.value.isEmpty() }

state.value = ResourceState.Loading()
state.value = ResourceState.Loading

assertEquals(actual = dataTransformCounter, expected = 0)
assertEquals(actual = mergeWithDataTransformCounter, expected = 0)
Expand Down