mirror of
				https://github.com/InsanusMokrassar/MicroUtils.git
				synced 2025-11-04 06:00:22 +00:00 
			
		
		
		
	
							
								
								
									
										12
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -1,5 +1,17 @@
 | 
			
		||||
# Changelog
 | 
			
		||||
 | 
			
		||||
## 0.2.3
 | 
			
		||||
 | 
			
		||||
* `Versions`
 | 
			
		||||
    * `Coroutines`: `1.3.9` -> `1.4.0`
 | 
			
		||||
    * `Exposed`: `0.27.1` -> `0.28.1`
 | 
			
		||||
* `Common`
 | 
			
		||||
    * `K/JS`
 | 
			
		||||
        * Add several extensions for `Element` objects to detect that object is on screen viewport
 | 
			
		||||
        * Add several extensions for `Element` objects to detect object visibility
 | 
			
		||||
* `Coroutines`
 | 
			
		||||
    * `BroadcastStateFlow` now use different strategy for getting of state and implements `replayCache`
 | 
			
		||||
 | 
			
		||||
## 0.2.2
 | 
			
		||||
 | 
			
		||||
* `Repos`
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,43 @@
 | 
			
		||||
package dev.inmo.micro_utils.common
 | 
			
		||||
 | 
			
		||||
import kotlinx.browser.window
 | 
			
		||||
import org.w3c.dom.DOMRect
 | 
			
		||||
import org.w3c.dom.Element
 | 
			
		||||
 | 
			
		||||
val DOMRect.isOnScreenByLeftEdge: Boolean
 | 
			
		||||
    get() = left >= 0 && left <= window.innerWidth
 | 
			
		||||
inline val Element.isOnScreenByLeftEdge
 | 
			
		||||
    get() = getBoundingClientRect().isOnScreenByLeftEdge
 | 
			
		||||
 | 
			
		||||
val DOMRect.isOnScreenByRightEdge: Boolean
 | 
			
		||||
    get() = right >= 0 && right <= window.innerWidth
 | 
			
		||||
inline val Element.isOnScreenByRightEdge
 | 
			
		||||
    get() = getBoundingClientRect().isOnScreenByRightEdge
 | 
			
		||||
 | 
			
		||||
internal val DOMRect.isOnScreenHorizontally: Boolean
 | 
			
		||||
    get() = isOnScreenByLeftEdge || isOnScreenByRightEdge
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
val DOMRect.isOnScreenByTopEdge: Boolean
 | 
			
		||||
    get() = top >= 0 && top <= window.innerHeight
 | 
			
		||||
inline val Element.isOnScreenByTopEdge
 | 
			
		||||
    get() = getBoundingClientRect().isOnScreenByTopEdge
 | 
			
		||||
 | 
			
		||||
val DOMRect.isOnScreenByBottomEdge: Boolean
 | 
			
		||||
    get() = bottom >= 0 && bottom <= window.innerHeight
 | 
			
		||||
inline val Element.isOnScreenByBottomEdge
 | 
			
		||||
    get() = getBoundingClientRect().isOnScreenByBottomEdge
 | 
			
		||||
 | 
			
		||||
internal val DOMRect.isOnScreenVertically: Boolean
 | 
			
		||||
    get() = isOnScreenByLeftEdge || isOnScreenByRightEdge
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
val DOMRect.isOnScreenFully: Boolean
 | 
			
		||||
    get() = isOnScreenByLeftEdge && isOnScreenByTopEdge && isOnScreenByRightEdge && isOnScreenByBottomEdge
 | 
			
		||||
val Element.isOnScreenFully: Boolean
 | 
			
		||||
    get() = getBoundingClientRect().isOnScreenFully
 | 
			
		||||
 | 
			
		||||
val DOMRect.isOnScreen: Boolean
 | 
			
		||||
    get() = isOnScreenFully || (isOnScreenHorizontally && isOnScreenVertically)
 | 
			
		||||
inline val Element.isOnScreen: Boolean
 | 
			
		||||
    get() = getBoundingClientRect().isOnScreen
 | 
			
		||||
@@ -0,0 +1,48 @@
 | 
			
		||||
package dev.inmo.micro_utils.common
 | 
			
		||||
 | 
			
		||||
import kotlinx.browser.window
 | 
			
		||||
import org.w3c.dom.Element
 | 
			
		||||
import org.w3c.dom.css.CSSStyleDeclaration
 | 
			
		||||
 | 
			
		||||
sealed class Visibility
 | 
			
		||||
object Visible : Visibility()
 | 
			
		||||
object Invisible : Visibility()
 | 
			
		||||
object Gone : Visibility()
 | 
			
		||||
 | 
			
		||||
var CSSStyleDeclaration.visibilityState: Visibility
 | 
			
		||||
    get() = when {
 | 
			
		||||
        display == "none" -> Gone
 | 
			
		||||
        visibility == "hidden" -> Invisible
 | 
			
		||||
        else -> Visible
 | 
			
		||||
    }
 | 
			
		||||
    set(value) {
 | 
			
		||||
        when (value) {
 | 
			
		||||
            Visible -> {
 | 
			
		||||
                if (display == "none") {
 | 
			
		||||
                    display = "initial"
 | 
			
		||||
                }
 | 
			
		||||
                visibility = "visible"
 | 
			
		||||
            }
 | 
			
		||||
            Invisible -> {
 | 
			
		||||
                if (display == "none") {
 | 
			
		||||
                    display = "initial"
 | 
			
		||||
                }
 | 
			
		||||
                visibility = "hidden"
 | 
			
		||||
            }
 | 
			
		||||
            Gone -> {
 | 
			
		||||
                display = "none"
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
inline var Element.visibilityState: Visibility
 | 
			
		||||
    get() = window.getComputedStyle(this).visibilityState
 | 
			
		||||
    set(value) {
 | 
			
		||||
        window.getComputedStyle(this).visibilityState = value
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
inline val Element.isVisible: Boolean
 | 
			
		||||
    get() = visibilityState == Visible
 | 
			
		||||
inline val Element.isInvisible: Boolean
 | 
			
		||||
    get() = visibilityState == Invisible
 | 
			
		||||
inline val Element.isGone: Boolean
 | 
			
		||||
    get() = visibilityState == Gone
 | 
			
		||||
@@ -5,29 +5,59 @@ import kotlinx.coroutines.channels.BroadcastChannel
 | 
			
		||||
import kotlinx.coroutines.channels.Channel
 | 
			
		||||
import kotlinx.coroutines.flow.*
 | 
			
		||||
 | 
			
		||||
const val defaultBroadcastStateFlowReplayCacheSize = 1
 | 
			
		||||
 | 
			
		||||
class BroadcastStateFlow<T> internal constructor(
 | 
			
		||||
    parentFlow: Flow<T>,
 | 
			
		||||
    private val stateGetter: () -> T
 | 
			
		||||
    initial: T,
 | 
			
		||||
    replayCacheSize: Int = defaultBroadcastStateFlowReplayCacheSize,
 | 
			
		||||
    replayScope: CoroutineScope
 | 
			
		||||
) : StateFlow<T>, Flow<T> by parentFlow {
 | 
			
		||||
    private val deque = ArrayDeque<T>(1).also {
 | 
			
		||||
        it.add(initial)
 | 
			
		||||
    }
 | 
			
		||||
    override val replayCache: List<T>
 | 
			
		||||
        get() = deque.toList()
 | 
			
		||||
    override val value: T
 | 
			
		||||
        get() = stateGetter()
 | 
			
		||||
}
 | 
			
		||||
        get() = deque.last()
 | 
			
		||||
 | 
			
		||||
fun <T> BroadcastChannel<T>.asStateFlow(value: T, scope: CoroutineScope): StateFlow<T> = asFlow().let {
 | 
			
		||||
    var state: T = value
 | 
			
		||||
    it.onEach { state = it }.launchIn(scope)
 | 
			
		||||
    BroadcastStateFlow(it) {
 | 
			
		||||
        state
 | 
			
		||||
    init {
 | 
			
		||||
        if (replayCacheSize < 1) {
 | 
			
		||||
            error("Replay cache size can't be less than 1, but was $replayCacheSize")
 | 
			
		||||
        }
 | 
			
		||||
        parentFlow.onEach {
 | 
			
		||||
            deque.addLast(it)
 | 
			
		||||
            if (deque.size > replayCacheSize) {
 | 
			
		||||
                deque.removeFirst()
 | 
			
		||||
            }
 | 
			
		||||
        }.launchIn(replayScope)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <T> BroadcastChannel<T?>.asStateFlow(scope: CoroutineScope): StateFlow<T?> = asStateFlow(null, scope)
 | 
			
		||||
fun <T> BroadcastChannel<T>.asStateFlow(
 | 
			
		||||
    value: T,
 | 
			
		||||
    scope: CoroutineScope,
 | 
			
		||||
    replayCacheSize: Int = defaultBroadcastStateFlowReplayCacheSize
 | 
			
		||||
): StateFlow<T> = BroadcastStateFlow(asFlow(), value, replayCacheSize, scope)
 | 
			
		||||
 | 
			
		||||
fun <T> broadcastStateFlow(initial: T, scope: CoroutineScope, channelSize: Int = Channel.BUFFERED) = BroadcastChannel<T>(
 | 
			
		||||
fun <T> BroadcastChannel<T?>.asStateFlow(
 | 
			
		||||
    scope: CoroutineScope,
 | 
			
		||||
    replayCacheSize: Int = defaultBroadcastStateFlowReplayCacheSize
 | 
			
		||||
): StateFlow<T?> = asStateFlow(null, scope, replayCacheSize)
 | 
			
		||||
 | 
			
		||||
fun <T> broadcastStateFlow(
 | 
			
		||||
    initial: T, scope: CoroutineScope,
 | 
			
		||||
    channelSize: Int = Channel.BUFFERED,
 | 
			
		||||
    replayCacheSize: Int = defaultBroadcastStateFlowReplayCacheSize
 | 
			
		||||
) = BroadcastChannel<T>(
 | 
			
		||||
    channelSize
 | 
			
		||||
).let {
 | 
			
		||||
    it to it.asStateFlow(initial, scope)
 | 
			
		||||
    it to it.asStateFlow(initial, scope, replayCacheSize)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun <T> broadcastStateFlow(scope: CoroutineScope, channelSize: Int = Channel.BUFFERED) = broadcastStateFlow<T?>(null, scope, channelSize)
 | 
			
		||||
fun <T> broadcastStateFlow(
 | 
			
		||||
    scope: CoroutineScope,
 | 
			
		||||
    channelSize: Int = Channel.BUFFERED,
 | 
			
		||||
    replayCacheSize: Int = defaultBroadcastStateFlowReplayCacheSize
 | 
			
		||||
) = broadcastStateFlow<T?>(null, scope, channelSize, replayCacheSize)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										88
									
								
								dokka/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								dokka/build.gradle
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
			
		||||
buildscript {
 | 
			
		||||
    repositories {
 | 
			
		||||
        mavenLocal()
 | 
			
		||||
        jcenter()
 | 
			
		||||
        mavenCentral()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dependencies {
 | 
			
		||||
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 | 
			
		||||
        classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
 | 
			
		||||
        classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
plugins {
 | 
			
		||||
    id "org.jetbrains.kotlin.multiplatform"
 | 
			
		||||
    id "org.jetbrains.kotlin.plugin.serialization"
 | 
			
		||||
    id "org.jetbrains.dokka" version "$dokka_version"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
repositories {
 | 
			
		||||
    mavenLocal()
 | 
			
		||||
    jcenter()
 | 
			
		||||
    mavenCentral()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
kotlin {
 | 
			
		||||
    jvm()
 | 
			
		||||
    js(BOTH) {
 | 
			
		||||
        browser()
 | 
			
		||||
        nodejs()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sourceSets {
 | 
			
		||||
        commonMain {
 | 
			
		||||
            dependencies {
 | 
			
		||||
                implementation kotlin('stdlib')
 | 
			
		||||
 | 
			
		||||
                project.parent.subprojects.forEach {
 | 
			
		||||
                    if (
 | 
			
		||||
                        it != project
 | 
			
		||||
                        && it.hasProperty("kotlin")
 | 
			
		||||
                        && it.kotlin.sourceSets.any { it.name.contains("commonMain") }
 | 
			
		||||
                    ) {
 | 
			
		||||
                        api it
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
private List<SourceDirectorySet> findSourcesWithName(String... approximateNames) {
 | 
			
		||||
    return parent.subprojects
 | 
			
		||||
            .findAll { it != project && it.hasProperty("kotlin") }
 | 
			
		||||
            .collectMany { it.kotlin.sourceSets }
 | 
			
		||||
            .findAll { sourceSet ->
 | 
			
		||||
                approximateNames.any { nameToFilter ->
 | 
			
		||||
                    sourceSet.name.contains(nameToFilter)
 | 
			
		||||
                }
 | 
			
		||||
            }.collect { it.kotlin }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
tasks.dokkaHtml {
 | 
			
		||||
    dokkaSourceSets {
 | 
			
		||||
        configureEach {
 | 
			
		||||
            skipDeprecated.set(true)
 | 
			
		||||
 | 
			
		||||
            sourceLink {
 | 
			
		||||
                localDirectory.set(file("./"))
 | 
			
		||||
                remoteUrl.set(new URL("https://github.com/InsanusMokrassar/MicroUtils/blob/master/"))
 | 
			
		||||
                remoteLineSuffix.set("#L")
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        named("commonMain") {
 | 
			
		||||
            sourceRoots.setFrom(findSourcesWithName("commonMain"))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        named("jsMain") {
 | 
			
		||||
            sourceRoots.setFrom(findSourcesWithName("jsMain", "commonMain"))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        named("jvmMain") {
 | 
			
		||||
            sourceRoots.setFrom(findSourcesWithName("jvmMain", "commonMain"))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								dokka/gradle.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								dokka/gradle.properties
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
dokka_version=1.4.0
 | 
			
		||||
 | 
			
		||||
org.gradle.jvmargs=-Xmx1024m
 | 
			
		||||
@@ -5,9 +5,9 @@ kotlin.incremental=true
 | 
			
		||||
kotlin.incremental.js=true
 | 
			
		||||
 | 
			
		||||
kotlin_version=1.4.10
 | 
			
		||||
kotlin_coroutines_version=1.3.9
 | 
			
		||||
kotlin_coroutines_version=1.4.0
 | 
			
		||||
kotlin_serialisation_core_version=1.0.0
 | 
			
		||||
kotlin_exposed_version=0.27.1
 | 
			
		||||
kotlin_exposed_version=0.28.1
 | 
			
		||||
 | 
			
		||||
ktor_version=1.4.1
 | 
			
		||||
 | 
			
		||||
@@ -19,4 +19,4 @@ github_release_plugin_version=2.2.12
 | 
			
		||||
uuidVersion=0.2.2
 | 
			
		||||
 | 
			
		||||
group=dev.inmo
 | 
			
		||||
version=0.2.2
 | 
			
		||||
version=0.2.3
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,9 @@ String[] includes = [
 | 
			
		||||
    ":ktor:server",
 | 
			
		||||
    ":ktor:common",
 | 
			
		||||
    ":ktor:client",
 | 
			
		||||
    ":coroutines"
 | 
			
		||||
    ":coroutines",
 | 
			
		||||
 | 
			
		||||
    ":dokka"
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user