From 961bc24f2799355638ab839cbd72b31b3db2bdb4 Mon Sep 17 00:00:00 2001 From: Michael <5672750+mibac138@users.noreply.github.com> Date: Wed, 13 Mar 2024 19:13:56 +0100 Subject: [PATCH] Add docs to Resource, changing networkBoundResource generics naming (#2483) --- app/play-publish-lint.sh | 3 +- .../java/io/github/wulkanowy/data/Resource.kt | 51 +++++++++++++------ 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/app/play-publish-lint.sh b/app/play-publish-lint.sh index d3354b1a..5f0391de 100755 --- a/app/play-publish-lint.sh +++ b/app/play-publish-lint.sh @@ -1,7 +1,8 @@ #!/bin/bash - content=$(cat < "app/src/main/play/release-notes/pl-PL/default.txt") || exit -if [[ "${#content}" -gt 500 ]]; then +content2=echo "$content" | dos2unix +if [[ "${#content2}" -gt 500 ]]; then echo >&2 "Release notes content has reached the limit of 500 characters" exit 1 fi diff --git a/app/src/main/java/io/github/wulkanowy/data/Resource.kt b/app/src/main/java/io/github/wulkanowy/data/Resource.kt index 7c6c2a9f..712a946f 100644 --- a/app/src/main/java/io/github/wulkanowy/data/Resource.kt +++ b/app/src/main/java/io/github/wulkanowy/data/Resource.kt @@ -24,13 +24,34 @@ import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds sealed interface Resource { - + /** + * The initial value of a resource flow. Indicates no data that is currently available to be shown, + * however with the expectation that the state will transition to another one soon. + */ open class Loading : Resource + /** + * A semi-loading state with some data available to be displayed (usually cached data loaded from + * the database). Still not the target state and it's expected to transition into another one soon. + */ data class Intermediate(val data: T) : Loading() + /** + * The happy-path target state. Data can either be: + * - loaded from the database - while it may seem like this case is already handled by the + * Intermediate state, the difference here is semantic. Cached data is returned as Intermediate + * when there's a API request in progress (or soon expected to be), however when there is no + * intention of immediately querying the API, the cached data is returned as a Success. + * - fetched from the API. + */ data class Success(val data: T) : Resource + /** + * Something bad happened and we were unable to get the requested data. This can be caused by + * a database error, a network error, or really just any other error. Upon receiving this state + * the UI can either: display a full screen error, or, when it has received any data previously, + * display a snack bar informing of the problem. + */ data class Error(val error: Throwable) : Resource } @@ -215,14 +236,14 @@ fun Flow>.debounceIntermediates(timeout: Duration = 5.seconds) = } -inline fun networkBoundResource( +inline fun networkBoundResource( mutex: Mutex = Mutex(), - crossinline isResultEmpty: (ResultType) -> Boolean, - crossinline query: () -> Flow, - crossinline fetch: suspend () -> RequestType, - crossinline saveFetchResult: suspend (old: ResultType, new: RequestType) -> Unit, - crossinline shouldFetch: (ResultType) -> Boolean = { true }, - crossinline filterResult: (ResultType) -> ResultType = { it } + crossinline isResultEmpty: (OutputType) -> Boolean, + crossinline query: () -> Flow, + crossinline fetch: suspend () -> ApiType, + crossinline saveFetchResult: suspend (old: OutputType, new: ApiType) -> Unit, + crossinline shouldFetch: (OutputType) -> Boolean = { true }, + crossinline filterResult: (OutputType) -> OutputType = { it } ) = networkBoundResource( mutex = mutex, isResultEmpty = isResultEmpty, @@ -234,14 +255,14 @@ inline fun networkBoundResource( ) @JvmName("networkBoundResourceWithMap") -inline fun networkBoundResource( +inline fun networkBoundResource( mutex: Mutex = Mutex(), - crossinline isResultEmpty: (MappedResultType) -> Boolean, - crossinline query: () -> Flow, - crossinline fetch: suspend () -> RequestType, - crossinline saveFetchResult: suspend (old: ResultType, new: RequestType) -> Unit, - crossinline shouldFetch: (ResultType) -> Boolean = { true }, - crossinline mapResult: (ResultType) -> MappedResultType, + crossinline isResultEmpty: (OutputType) -> Boolean, + crossinline query: () -> Flow, + crossinline fetch: suspend () -> ApiType, + crossinline saveFetchResult: suspend (old: DatabaseType, new: ApiType) -> Unit, + crossinline shouldFetch: (DatabaseType) -> Boolean = { true }, + crossinline mapResult: (DatabaseType) -> OutputType, ) = flow { emit(Resource.Loading())