mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-11-26 12:08:45 +00:00
commit
210e32bed4
12
CHANGELOG.md
12
CHANGELOG.md
@ -1,5 +1,17 @@
|
|||||||
# Changelog
|
# 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
|
## 0.2.2
|
||||||
|
|
||||||
* `Repos`
|
* `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.channels.Channel
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
|
const val defaultBroadcastStateFlowReplayCacheSize = 1
|
||||||
|
|
||||||
class BroadcastStateFlow<T> internal constructor(
|
class BroadcastStateFlow<T> internal constructor(
|
||||||
parentFlow: Flow<T>,
|
parentFlow: Flow<T>,
|
||||||
private val stateGetter: () -> T
|
initial: T,
|
||||||
|
replayCacheSize: Int = defaultBroadcastStateFlowReplayCacheSize,
|
||||||
|
replayScope: CoroutineScope
|
||||||
) : StateFlow<T>, Flow<T> by parentFlow {
|
) : 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
|
override val value: T
|
||||||
get() = stateGetter()
|
get() = deque.last()
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> BroadcastChannel<T>.asStateFlow(value: T, scope: CoroutineScope): StateFlow<T> = asFlow().let {
|
init {
|
||||||
var state: T = value
|
if (replayCacheSize < 1) {
|
||||||
it.onEach { state = it }.launchIn(scope)
|
error("Replay cache size can't be less than 1, but was $replayCacheSize")
|
||||||
BroadcastStateFlow(it) {
|
}
|
||||||
state
|
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
|
channelSize
|
||||||
).let {
|
).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.incremental.js=true
|
||||||
|
|
||||||
kotlin_version=1.4.10
|
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_serialisation_core_version=1.0.0
|
||||||
kotlin_exposed_version=0.27.1
|
kotlin_exposed_version=0.28.1
|
||||||
|
|
||||||
ktor_version=1.4.1
|
ktor_version=1.4.1
|
||||||
|
|
||||||
@ -19,4 +19,4 @@ github_release_plugin_version=2.2.12
|
|||||||
uuidVersion=0.2.2
|
uuidVersion=0.2.2
|
||||||
|
|
||||||
group=dev.inmo
|
group=dev.inmo
|
||||||
version=0.2.2
|
version=0.2.3
|
||||||
|
@ -16,7 +16,9 @@ String[] includes = [
|
|||||||
":ktor:server",
|
":ktor:server",
|
||||||
":ktor:common",
|
":ktor:common",
|
||||||
":ktor:client",
|
":ktor:client",
|
||||||
":coroutines"
|
":coroutines",
|
||||||
|
|
||||||
|
":dokka"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user