-
-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* refactor(base) * refactor(base) * refactor(main): MainVM * refactor(main): MainVM * refactor(base) * refactor(base): sealed interface * refactor(add): viewmodel * refactor(add): fix viewmodel * refactor(add): vm * refactor(add): fix tests * refactor(main): MainVM * refactor(main): MainVM * refactor(add): vm * refactor(search): vm * refactor(search): fix tests * done * done * rename * validated nes * fix tests * fix tests * fix tests * rename
- Loading branch information
Showing
44 changed files
with
919 additions
and
511 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Project-wide Gradle settings. | ||
# IDE (e.g. Android Studio) users: | ||
# Gradle settings configured through the IDE *will override* | ||
# any settings specified in this file. | ||
# For more details on how to configure your build environment visit | ||
# http://www.gradle.org/docs/current/userguide/build_environment.html | ||
# Specifies the JVM arguments used for the daemon process. | ||
# The setting is particularly useful for tweaking memory settings. | ||
org.gradle.jvmargs=-Xmx2048m | ||
|
||
# When configured, Gradle will run in incubating parallel mode. | ||
# This option should only be used with decoupled projects. More details, visit | ||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects | ||
org.gradle.parallel=true | ||
|
||
# Enable the Build Cache | ||
org.gradle.caching=true | ||
|
||
# AndroidX package structure to make it clearer which packages are bundled with the | ||
# Android operating system, and which are packaged with your app's APK | ||
# https://developer.android.com/topic/libraries/support-library/androidx-rn | ||
android.useAndroidX=true | ||
|
||
# Automatically convert third-party libraries to use AndroidX | ||
android.enableJetifier=false | ||
|
||
# Kotlin code style for this project: "official" or "obsolete": | ||
kotlin.code.style=official | ||
|
||
# Enable Kotlin incremental compilation | ||
kotlin.incremental=true |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
distributionBase=GRADLE_USER_HOME | ||
distributionPath=wrapper/dists | ||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip | ||
networkTimeout=10000 | ||
zipStoreBase=GRADLE_USER_HOME | ||
zipStorePath=wrapper/dists |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
core-ui/src/main/java/com/hoc/flowmvi/core_ui/debugCheckImmediateMainDispatcher.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.hoc.flowmvi.core_ui | ||
|
||
import kotlin.coroutines.ContinuationInterceptor | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.currentCoroutineContext | ||
import timber.log.Timber | ||
|
||
suspend fun debugCheckImmediateMainDispatcher() { | ||
if (BuildConfig.DEBUG) { | ||
val interceptor = currentCoroutineContext()[ContinuationInterceptor] | ||
Timber.d("debugCheckImmediateMainDispatcher: interceptor=$interceptor") | ||
|
||
check(interceptor === Dispatchers.Main.immediate) { | ||
"Expected ContinuationInterceptor to be Dispatchers.Main.immediate but was $interceptor" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package com.hoc.flowmvi.core | ||
|
||
/** | ||
* `NonEmptySet` is a data type used to model sets that guarantee to have at least one value. | ||
*/ | ||
class NonEmptySet<out T> | ||
@Throws(IllegalArgumentException::class) | ||
private constructor(val set: Set<T>) : AbstractSet<T>() { | ||
init { | ||
require(set.isNotEmpty()) { "Set must not be empty" } | ||
require(set !is NonEmptySet<T>) { "Set must not be NonEmptySet" } | ||
} | ||
|
||
override val size: Int get() = set.size | ||
override fun iterator(): Iterator<T> = set.iterator() | ||
override fun isEmpty(): Boolean = false | ||
|
||
operator fun plus(l: NonEmptySet<@UnsafeVariance T>): NonEmptySet<T> = | ||
NonEmptySet(set + l.set) | ||
|
||
@Suppress("RedundantOverride") | ||
override fun equals(other: Any?): Boolean = super.equals(other) | ||
|
||
@Suppress("RedundantOverride") | ||
override fun hashCode(): Int = super.hashCode() | ||
|
||
override fun toString(): String = | ||
"NonEmptySet(${set.joinToString()})" | ||
|
||
companion object { | ||
/** | ||
* Creates a [NonEmptySet] from the given [Collection]. | ||
* @return null if [this] is empty. | ||
*/ | ||
@JvmStatic | ||
fun <T> Collection<T>.toNonEmptySetOrNull(): NonEmptySet<T>? = | ||
if (isEmpty()) null else NonEmptySet(toSet()) | ||
|
||
/** | ||
* Creates a [NonEmptySet] from the given [Set]. | ||
* @return null if [this] is empty. | ||
*/ | ||
@JvmStatic | ||
fun <T> Set<T>.toNonEmptySetOrNull(): NonEmptySet<T>? = (this as? NonEmptySet<T>) | ||
?: if (isEmpty()) null else NonEmptySet(this) | ||
|
||
/** | ||
* Creates a [NonEmptySet] from the given values. | ||
*/ | ||
@JvmStatic | ||
fun <T> of(element: T, vararg elements: T): NonEmptySet<T> = NonEmptySet( | ||
buildSet(capacity = 1 + elements.size) { | ||
add(element) | ||
addAll(elements) | ||
} | ||
) | ||
|
||
/** | ||
* Creates a [NonEmptySet] that contains only the specified [element]. | ||
*/ | ||
@JvmStatic | ||
fun <T> of(element: T): NonEmptySet<T> = NonEmptySet(setOf(element)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.hoc.flowmvi.core | ||
|
||
import arrow.core.Validated | ||
import arrow.typeclasses.Semigroup | ||
|
||
typealias ValidatedNes<E, A> = Validated<NonEmptySet<E>, A> | ||
|
||
@Suppress("NOTHING_TO_INLINE") | ||
inline fun <A> A.validNes(): ValidatedNes<Nothing, A> = | ||
Validated.Valid(this) | ||
|
||
@Suppress("NOTHING_TO_INLINE") | ||
inline fun <E> E.invalidNes(): ValidatedNes<E, Nothing> = | ||
Validated.Invalid(NonEmptySet.of(this)) | ||
|
||
object NonEmptySetSemigroup : Semigroup<NonEmptySet<Any?>> { | ||
override fun NonEmptySet<Any?>.combine(b: NonEmptySet<Any?>): NonEmptySet<Any?> = this + b | ||
} | ||
|
||
@Suppress("UNCHECKED_CAST") | ||
fun <T> Semigroup.Companion.nonEmptySet(): Semigroup<NonEmptySet<T>> = | ||
NonEmptySetSemigroup as Semigroup<NonEmptySet<T>> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package com.hoc.flowmvi.core | ||
|
||
import kotlin.properties.ReadOnlyProperty | ||
import kotlin.reflect.KProperty | ||
|
||
// Generic inline classes is an Experimental feature. | ||
// It may be dropped or changed at any time. | ||
// Opt-in is required with the -language-version 1.8 compiler option. | ||
// See https://kotlinlang.org/docs/inline-classes.html for more information. | ||
@JvmInline | ||
value class SelfReference<T>(val value: T) : ReadOnlyProperty<Any?, T> { | ||
override fun getValue(thisRef: Any?, property: KProperty<*>): T = value | ||
} | ||
|
||
/** | ||
* A delegate that allows to reference the object itself. | ||
* This is useful to avoid initialization order issues. | ||
* | ||
* This is a alternative way to: | ||
* - `lateinit var` (mutable variables can be modified by mistake). | ||
* - [lazy] (lazy evaluation is unnecessary in this case). | ||
* | ||
* NOTE: Do **NOT** access the value of the return delegate synchronously inside [initializer]. | ||
* Eg: `val x: Int by selfReferenced { x + 1 }` is a wrong usage, it will cause an exception. | ||
* | ||
* ### Example | ||
* Below is an example of how to use it: | ||
* | ||
* ```kotlin | ||
* import kotlinx.coroutines.flow.* | ||
* import kotlinx.coroutines.* | ||
* | ||
* class Demo { | ||
* private val trigger = MutableSharedFlow<Unit>() | ||
* private val scope = CoroutineScope(Dispatchers.Default) | ||
* | ||
* val intStateFlow: StateFlow<Int?> by selfReferenced { | ||
* merge( | ||
* flow { | ||
* var c = 0 | ||
* while (true) { emit(c++); delay(300) } | ||
* }, | ||
* trigger.mapNotNull { | ||
* println("access to $intStateFlow") | ||
* intStateFlow.value?.minus(1) | ||
* } | ||
* ) | ||
* .stateIn(scope, SharingStarted.Eagerly, null) | ||
* } | ||
* | ||
* fun trigger() = scope.launch { trigger.emit(Unit) } | ||
* } | ||
* | ||
* fun main(): Unit = runBlocking { | ||
* val demo = Demo() | ||
* val job = demo.intStateFlow | ||
* .onEach(::println) | ||
* .launchIn(this) | ||
* | ||
* delay(1_000) | ||
* demo.trigger() | ||
* | ||
* delay(500) | ||
* demo.trigger() | ||
* | ||
* delay(500) | ||
* job.cancel() | ||
* | ||
* // null | ||
* // 0 | ||
* // 1 | ||
* // 2 | ||
* // 3 | ||
* // access to kotlinx.coroutines.flow.ReadonlyStateFlow@2cfeac11 | ||
* // 2 | ||
* // 4 | ||
* // access to kotlinx.coroutines.flow.ReadonlyStateFlow@2cfeac11 | ||
* // 3 | ||
* // 5 | ||
* // 6 | ||
* } | ||
* ``` | ||
*/ | ||
fun <T> selfReferenced(initializer: () -> T) = SelfReference(initializer()) |
Oops, something went wrong.