Skip to content

Commit

Permalink
Add coroutines/flow support
Browse files Browse the repository at this point in the history
  • Loading branch information
Jawnnypoo committed Jun 3, 2024
1 parent 70e8eb4 commit 592d379
Show file tree
Hide file tree
Showing 22 changed files with 582 additions and 67 deletions.
1 change: 1 addition & 0 deletions .buildscript/upload_archives.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
./gradlew clean
./gradlew :lce:build -PreleaseBuild
./gradlew :lce-rxjava3:build -PreleaseBuild
./gradlew :lce-coroutines:build -PreleaseBuild
./gradlew :lce-test:build -PreleaseBuild

# Disabling parallelism and daemon sharing is required by the vanniktech maven publish plugin.
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ jobs:
steps:
- uses: actions/checkout@v2
- uses: gradle/wrapper-validation-action@v1
- uses: actions/setup-java@v1
- uses: actions/setup-java@v3
with:
java-version: 11
distribution: 'zulu'
java-version: 17
- uses: actions/cache@v2
with:
path: ~/.gradle/caches
Expand All @@ -24,5 +25,7 @@ jobs:
run: ./gradlew :lce:test
- name: RxJava3 Module Unit Tests
run: ./gradlew :lce-rxjava3:test
- name: Coroutine/Flow Module Unit Tests
run: ./gradlew :lce-coroutines:test
- name: Test Library tests
run: ./gradlew :lce-test:test
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Changelog
## [0.4.0] - June 3, 2024
- Added `lce-flow` module for Coroutine Flow support.

## [0.3.4] - January 10, 2024
- Added `asUCE` map operation for `UCT`.

Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,11 @@ Add the library to your list of dependencies:
```groovy
dependencies {
implementation("com.laimiux.lce:lce:0.3.4")
// For RxJava 3 support
implementation("com.laimiux.lce:lce-rxjava3:0.3.4")
// For Coroutines/Flow support
implementation("com.laimiux.lce:lce-coroutines:0.3.4")
// Helper functions for assertions in tests
implementation("com.laimiux.lce:lce-test:0.3.4")
}
```
Expand Down
20 changes: 3 additions & 17 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,50 +1,37 @@
apply from: 'dependencies.gradle'
apply plugin: "com.github.ben-manes.versions"
apply plugin: "org.jetbrains.dokka"

buildscript {
ext {
kotlinVersion = '1.5.21'
kotlinVersion = '1.9.20'

versions = [:]
libraries = [:]
constants = [
minSdk : 21,
targetSdk : 29,
compileSdk : 29
]
}

repositories {
google()
mavenCentral()
jcenter()
maven { url 'https://jitpack.io' }
}

dependencies {
classpath 'com.android.tools.build:gradle:7.0.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
classpath "com.vanniktech:gradle-android-junit-jacoco-plugin:0.16.0"
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
classpath "com.github.ben-manes:gradle-versions-plugin:0.28.0"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.4.32"
classpath "org.jetbrains.dokka:android-documentation-plugin:1.4.32"
classpath "com.vanniktech:gradle-maven-publish-plugin:0.14.2"
}
}

allprojects {
repositories {
google()
mavenCentral()
jcenter()
}

tasks.withType(org.jetbrains.dokka.gradle.DokkaTaskPartial).configureEach {
dokkaSourceSets.named("main") {
configuration {
jdkVersion.set(8)
jdkVersion.set(17)
skipDeprecated.set(true)
skipEmptyPackages.set(true)
reportUndocumented.set(false)
Expand All @@ -59,8 +46,7 @@ task clean(type: Delete) {

apply plugin: "com.vanniktech.android.junit.jacoco"
junitJacoco {
// WARNING! Don't upgrade unless https://github.com/Malinskiy/danger-jacoco/issues/10 is fixed
jacocoVersion = '0.8.2'
jacocoVersion = '0.8.12'
excludes = [
// Defaults
'**/androidx/**/*.*',
Expand Down
7 changes: 2 additions & 5 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ ext {

libraries = [
junit : "junit:junit:$junitVersion",
kotlin : "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion",
kotlinReflect : "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion",
robolectric : "org.robolectric:robolectric:$robolectricVersion",
rxjava : "io.reactivex.rxjava3:rxjava:3.0.4",
rxrelays : "com.jakewharton.rxrelay3:rxrelay:3.0.0",
coroutines : "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1",
rxjava : "io.reactivex.rxjava3:rxjava:3.1.8",
truth : "com.google.truth:truth:$truthVersion"
]
}
1 change: 1 addition & 0 deletions lce-coroutines/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
6 changes: 6 additions & 0 deletions lce-coroutines/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# lce-coroutines
Coroutines/Flow support for LCE.

If coming over from RxJava, here is the typical mapping

- `switchMapContent` -> `flatMapLatestContent`
25 changes: 25 additions & 0 deletions lce-coroutines/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apply plugin: 'kotlin'
apply plugin: 'org.jetbrains.dokka'

apply from: rootProject.file('.buildscript/configure-signing.gradle')

repositories {
mavenCentral()
}

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
kotlin {
jvmToolchain(17)
}

dependencies {
api(libraries.coroutines)
api(project(":lce"))

testImplementation(libraries.truth)
testImplementation(libraries.junit)
}
3 changes: 3 additions & 0 deletions lce-coroutines/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
POM_ARTIFACT_ID=lce-coroutines
POM_NAME=LCE type Flow Support
POM_PACKAGING=jar
145 changes: 145 additions & 0 deletions lce-coroutines/src/main/java/com/laimiux/lce/flow/ContentEvents.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
@file:OptIn(ExperimentalCoroutinesApi::class)

package com.laimiux.lce.flow

import com.laimiux.lce.CT
import com.laimiux.lce.LC
import com.laimiux.lce.LCE
import com.laimiux.lce.UC
import com.laimiux.lce.UCE
import com.laimiux.lce.UCT
import com.laimiux.lce.fold
import com.laimiux.lce.foldTypes
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flatMapMerge
import kotlinx.coroutines.flow.flowOf

@JvmName("onlyContentEventsUCE")
fun <C : Any, E> Flow<UCE<C, E>>.onlyContentEvents(): Flow<C> {
return flatMapMerge {
it.fold(
onLoading = { emptyFlow() },
onError = { emptyFlow() },
onContent = { flowOf(it) }
)
}
}

@JvmName("onlyContentEventsUCT")
fun <C : Any> Flow<UCT<C>>.onlyContentEvents(): Flow<C> {
return flatMapMerge {
it.fold(
onLoading = { emptyFlow() },
onError = { emptyFlow() },
onContent = { flowOf(it) }
)
}
}

@JvmName("onlyContentEventsCT")
fun <C : Any> Flow<CT<C>>.onlyContentEvents(): Flow<C> {
return flatMapMerge {
it.fold(
onError = { emptyFlow() },
onContent = { flowOf(it) }
)
}
}

@JvmName("onlyContentEventsLC")
fun <L, C : Any> Flow<LC<L, C>>.onlyContentEvents(): Flow<C> {
return flatMapMerge {
it.fold(
onLoading = { emptyFlow() },
onContent = { flowOf(it) }
)
}
}

@JvmName("onlyContentEventsUC")
fun <C : Any> Flow<UC<C>>.onlyContentEvents(): Flow<C> {
return flatMapMerge {
it.fold(
onLoading = { emptyFlow() },
onContent = { flowOf(it) }
)
}
}

@JvmName("flatMapLatestContentLCE")
inline fun <L, C, E, NewC> Flow<LCE<L, C, E>>.flatMapLatestContent(
crossinline transform: (C) -> Flow<LCE<L, NewC, E>>
): Flow<LCE<L, NewC, E>> {
return flatMapLatest {
it.foldTypes(
onLoading = { flowOf(it) },
onContent = { transform(it.value) },
onError = { flowOf(it) }
)
}
}

@JvmName("flatMapLatestContentContentUCE")
inline fun <C, E, NewC> Flow<UCE<C, E>>.flatMapLatestContent(
crossinline transform: (C) -> Flow<UCE<NewC, E>>
): Flow<UCE<NewC, E>> {
return flatMapLatest {
it.foldTypes(
onLoading = { flowOf(it) },
onContent = { transform(it.value) },
onError = { flowOf(it) }
)
}
}

@JvmName("flatMapLatestContentContentUCT")
inline fun <C, NewC> Flow<UCT<C>>.flatMapLatestContent(
crossinline transform: (C) -> Flow<UCT<NewC>>
): Flow<UCT<NewC>> {
return flatMapLatest {
it.foldTypes(
onLoading = { flowOf(it) },
onContent = { transform(it.value) },
onError = { flowOf(it) }
)
}
}

@JvmName("flatMapLatestContentContentCT")
inline fun <C, NewC> Flow<CT<C>>.flatMapLatestContent(
crossinline transform: (C) -> Flow<CT<NewC>>
): Flow<CT<NewC>> {
return flatMapLatest {
it.foldTypes(
onContent = { transform(it.value) },
onError = { flowOf(it) }
)
}
}

@JvmName("flatMapLatestContentContentLC")
inline fun <L, C, NewC> Flow<LC<L, C>>.flatMapLatestContent(
crossinline transform: (C) -> Flow<LC<L, NewC>>
): Flow<LC<L, NewC>> {
return flatMapLatest {
it.foldTypes(
onLoading = { flowOf(it) },
onContent = { transform(it.value) }
)
}
}

@JvmName("flatMapLatestContentContentUC")
inline fun <C, NewC> Flow<UC<C>>.flatMapLatestContent(
crossinline transform: (C) -> Flow<UC<NewC>>
): Flow<UC<NewC>> {
return flatMapLatest {
it.foldTypes(
onLoading = { flowOf(it) },
onContent = { transform(it.value) }
)
}
}
26 changes: 26 additions & 0 deletions lce-coroutines/src/main/java/com/laimiux/lce/flow/Convert.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@file:OptIn(ExperimentalCoroutinesApi::class)

package com.laimiux.lce.flow

import com.laimiux.lce.CT
import com.laimiux.lce.UCT
import com.laimiux.lce.asCT
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf

/**
* Converts [UCT] type to [CT]. Essentially it ignores loading events.
*/
fun <C> Flow<UCT<C>>.toCT(): Flow<CT<C>> {
return flatMapLatest {
val ct = it.asCT()
if (ct != null) {
flowOf(ct)
} else {
emptyFlow()
}
}
}
Loading

0 comments on commit 592d379

Please sign in to comment.