From 8f790360bc77342073e752efa359304fca245140 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 12 Mar 2022 00:34:22 +0600 Subject: [PATCH 1/7] start 0.9.12 --- CHANGELOG.md | 2 ++ gradle.properties | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25e40580650..361f3d568c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +## 0.9.12 + ## 0.9.11 * `Versions`: diff --git a/gradle.properties b/gradle.properties index bf5149f9b48..624e13335ff 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,5 +14,5 @@ crypto_js_version=4.1.1 # Project data group=dev.inmo -version=0.9.11 -android_code_version=101 +version=0.9.12 +android_code_version=102 From 9e84dc50319645a85105041bd15a03e74aff8180 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 12 Mar 2022 00:55:03 +0600 Subject: [PATCH 2/7] add a set of tools for JS and Web Compose --- common/compose/build.gradle | 18 ++++++++ .../compose/DefaultDisposableEffectResult.kt | 16 +++++++ .../micro_utils/common/compose/OpenLink.kt | 10 +++++ common/compose/src/main/AndroidManifest.xml | 1 + .../dev/inmo/micro_utils/common/OpenLink.kt | 8 ++++ .../dev/inmo/micro_utils/common/SelectFile.kt | 29 +++++++++++++ .../micro_utils/common/TriggerDownload.kt | 14 +++++++ coroutines/build.gradle | 5 +++ coroutines/compose/build.gradle | 1 + .../coroutines/compose/FlowToState.kt | 22 ++++++++++ .../SelectFile.kt | 42 +++++++++++++++++++ settings.gradle | 1 + 12 files changed, 167 insertions(+) create mode 100644 common/compose/build.gradle create mode 100644 common/compose/src/commonMain/kotlin/dev/inmo/micro_utils/common/compose/DefaultDisposableEffectResult.kt create mode 100644 common/compose/src/jsMain/kotlin/dev/inmo/micro_utils/common/compose/OpenLink.kt create mode 100644 common/compose/src/main/AndroidManifest.xml create mode 100644 common/src/jsMain/kotlin/dev/inmo/micro_utils/common/OpenLink.kt create mode 100644 common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt create mode 100644 common/src/jsMain/kotlin/dev/inmo/micro_utils/common/TriggerDownload.kt create mode 100644 coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowToState.kt create mode 100644 coroutines/src/jsMain/kotlin/dev.inmo.micro_utils.coroutines/SelectFile.kt diff --git a/common/compose/build.gradle b/common/compose/build.gradle new file mode 100644 index 00000000000..0b3570ad169 --- /dev/null +++ b/common/compose/build.gradle @@ -0,0 +1,18 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.serialization" + id "com.android.library" + alias(libs.plugins.jb.compose) +} + +apply from: "$mppProjectWithSerializationAndComposePresetPath" + +kotlin { + sourceSets { + commonMain { + dependencies { + api project(":micro_utils.common") + } + } + } +} diff --git a/common/compose/src/commonMain/kotlin/dev/inmo/micro_utils/common/compose/DefaultDisposableEffectResult.kt b/common/compose/src/commonMain/kotlin/dev/inmo/micro_utils/common/compose/DefaultDisposableEffectResult.kt new file mode 100644 index 00000000000..82cf96bff4b --- /dev/null +++ b/common/compose/src/commonMain/kotlin/dev/inmo/micro_utils/common/compose/DefaultDisposableEffectResult.kt @@ -0,0 +1,16 @@ +package dev.inmo.micro_utils.common.compose + +import androidx.compose.runtime.DisposableEffectResult + +class DefaultDisposableEffectResult( + private val onDispose: () -> Unit +) : DisposableEffectResult { + override fun dispose() { + onDispose() + } + + companion object { + val DoNothing = DefaultDisposableEffectResult {} + } +} + diff --git a/common/compose/src/jsMain/kotlin/dev/inmo/micro_utils/common/compose/OpenLink.kt b/common/compose/src/jsMain/kotlin/dev/inmo/micro_utils/common/compose/OpenLink.kt new file mode 100644 index 00000000000..41ed545c41d --- /dev/null +++ b/common/compose/src/jsMain/kotlin/dev/inmo/micro_utils/common/compose/OpenLink.kt @@ -0,0 +1,10 @@ +package dev.inmo.micro_utils.common.compose + +import org.jetbrains.compose.web.attributes.ATarget + +fun openLink(link: String, mode: ATarget = ATarget.Blank, features: String = "") = dev.inmo.micro_utils.common.openLink( + link, + mode.targetStr, + features +) + diff --git a/common/compose/src/main/AndroidManifest.xml b/common/compose/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..65adc963cce --- /dev/null +++ b/common/compose/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/OpenLink.kt b/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/OpenLink.kt new file mode 100644 index 00000000000..24315e95559 --- /dev/null +++ b/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/OpenLink.kt @@ -0,0 +1,8 @@ +package dev.inmo.micro_utils.common + +import kotlinx.browser.window + +fun openLink(link: String, target: String = "_blank", features: String = "") { + window.open(link, target, features) ?.focus() +} + diff --git a/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt b/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt new file mode 100644 index 00000000000..89c7bc105dd --- /dev/null +++ b/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt @@ -0,0 +1,29 @@ +package dev.inmo.micro_utils.common + +import kotlinx.browser.document +import kotlinx.dom.createElement +import org.w3c.dom.HTMLElement +import org.w3c.dom.HTMLInputElement +import org.w3c.files.get + +fun selectFile( + inputSetup: HTMLInputElement.() -> Unit = {}, + onFailure: (Throwable) -> Unit = {}, + onFile: (MPPFile) -> Unit +) { + (document.createElement("input") { + (this as HTMLInputElement).apply { + inputSetup() + onchange = { + runCatching { + files ?.get(0) ?: error("File must not be null") + }.onSuccess { + onFile(it) + }.onFailure { + onFailure(it) + } + } + } + } as HTMLElement).click() +} + diff --git a/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/TriggerDownload.kt b/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/TriggerDownload.kt new file mode 100644 index 00000000000..369050cf196 --- /dev/null +++ b/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/TriggerDownload.kt @@ -0,0 +1,14 @@ +package dev.inmo.micro_utils.common + +import kotlinx.browser.document +import org.w3c.dom.HTMLAnchorElement + +fun triggerDownloadFile(filename: String, fileLink: String) { + val hiddenElement = document.createElement("a") as HTMLAnchorElement + + hiddenElement.href = fileLink + hiddenElement.target = "_blank" + hiddenElement.download = filename + hiddenElement.click() +} + diff --git a/coroutines/build.gradle b/coroutines/build.gradle index c614db7e76c..968d31e1521 100644 --- a/coroutines/build.gradle +++ b/coroutines/build.gradle @@ -13,6 +13,11 @@ kotlin { api libs.kt.coroutines } } + jsMain { + dependencies { + api project(":micro_utils.common") + } + } androidMain { dependencies { api libs.kt.coroutines.android diff --git a/coroutines/compose/build.gradle b/coroutines/compose/build.gradle index ca8aa5b5fce..c71171b88f3 100644 --- a/coroutines/compose/build.gradle +++ b/coroutines/compose/build.gradle @@ -12,6 +12,7 @@ kotlin { commonMain { dependencies { api libs.kt.coroutines + api project(":micro_utils.coroutines") } } } diff --git a/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowToState.kt b/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowToState.kt new file mode 100644 index 00000000000..22c1b7be83a --- /dev/null +++ b/coroutines/compose/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/compose/FlowToState.kt @@ -0,0 +1,22 @@ +package dev.inmo.micro_utils.coroutines.compose + +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.StateFlow + +fun Flow.toMutableState( + initial: T, + scope: CoroutineScope +): MutableState { + val state = mutableStateOf(initial) + subscribeSafelyWithoutExceptions(scope) { state.value = it } + return state +} + +inline fun StateFlow.toMutableState( + scope: CoroutineScope +): MutableState = toMutableState(value, scope) + diff --git a/coroutines/src/jsMain/kotlin/dev.inmo.micro_utils.coroutines/SelectFile.kt b/coroutines/src/jsMain/kotlin/dev.inmo.micro_utils.coroutines/SelectFile.kt new file mode 100644 index 00000000000..525a51b83df --- /dev/null +++ b/coroutines/src/jsMain/kotlin/dev.inmo.micro_utils.coroutines/SelectFile.kt @@ -0,0 +1,42 @@ +package dev.inmo.micro_utils.coroutines + +import dev.inmo.micro_utils.common.MPPFile +import dev.inmo.micro_utils.common.selectFile +import kotlinx.coroutines.CompletableDeferred +import org.w3c.dom.HTMLInputElement + +suspend fun selectFile( + inputSetup: HTMLInputElement.() -> Unit = {} +): MPPFile { + val result = CompletableDeferred() + + selectFile( + inputSetup, + { + result.completeExceptionally(it) + } + ) { + result.complete(it) + } + + return result.await() +} + +suspend fun selectOptionalFile( + inputSetup: HTMLInputElement.() -> Unit = {}, + onFailure: (Throwable) -> Unit = {} +): MPPFile? { + val result = CompletableDeferred() + + selectFile( + inputSetup, + { + result.complete(null) + onFailure(it) + } + ) { + result.complete(it) + } + + return result.await() +} diff --git a/settings.gradle b/settings.gradle index d22455ff9dd..d7471ac4ccc 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,6 +2,7 @@ rootProject.name='micro_utils' String[] includes = [ ":common", + ":common:compose", ":matrix", ":crypto", ":selector:common", From 6dbd12df59a9f4bbaf42d55161a548434451ccaf Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 12 Mar 2022 01:03:41 +0600 Subject: [PATCH 3/7] fill changelog and rename selectOptionalFile to selectFileOrNull --- CHANGELOG.md | 20 +++++++++++++++++++ .../dev/inmo/micro_utils/common/SelectFile.kt | 4 ++-- .../SelectFile.kt | 6 +++--- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 361f3d568c6..0896b84dfb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,26 @@ ## 0.9.12 +* `Common`: + * `JS`: + * New function `openLink` + * New function `selectFile` + * New function `triggerDownloadFile` + * `Compose`: + * Created :) + * `Common`: + * `DefaultDisposableEffectResult` as a default realization of `DisposableEffectResult` + * `JS`: + * `openLink` on top of `openLink` with `String` target from common +* `Coroutines`: + * `Compose`: + * `Common`: + * New extension `Flow.toMutableState` + * New extension `StateFlow.toMutableState` + * `JS`: + * New function `selectFile` on top of `selectFile` from `common` + * New function `selectFileOrNull` on top of `selectFile` from `common` + ## 0.9.11 * `Versions`: diff --git a/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt b/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt index 89c7bc105dd..bd85f4de52b 100644 --- a/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt +++ b/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt @@ -7,13 +7,13 @@ import org.w3c.dom.HTMLInputElement import org.w3c.files.get fun selectFile( - inputSetup: HTMLInputElement.() -> Unit = {}, + inputSetup: (HTMLInputElement) -> Unit = {}, onFailure: (Throwable) -> Unit = {}, onFile: (MPPFile) -> Unit ) { (document.createElement("input") { (this as HTMLInputElement).apply { - inputSetup() + inputSetup(this) onchange = { runCatching { files ?.get(0) ?: error("File must not be null") diff --git a/coroutines/src/jsMain/kotlin/dev.inmo.micro_utils.coroutines/SelectFile.kt b/coroutines/src/jsMain/kotlin/dev.inmo.micro_utils.coroutines/SelectFile.kt index 525a51b83df..e9ee57f3b42 100644 --- a/coroutines/src/jsMain/kotlin/dev.inmo.micro_utils.coroutines/SelectFile.kt +++ b/coroutines/src/jsMain/kotlin/dev.inmo.micro_utils.coroutines/SelectFile.kt @@ -6,7 +6,7 @@ import kotlinx.coroutines.CompletableDeferred import org.w3c.dom.HTMLInputElement suspend fun selectFile( - inputSetup: HTMLInputElement.() -> Unit = {} + inputSetup: (HTMLInputElement) -> Unit = {} ): MPPFile { val result = CompletableDeferred() @@ -22,8 +22,8 @@ suspend fun selectFile( return result.await() } -suspend fun selectOptionalFile( - inputSetup: HTMLInputElement.() -> Unit = {}, +suspend fun selectFileOrNull( + inputSetup: (HTMLInputElement) -> Unit = {}, onFailure: (Throwable) -> Unit = {} ): MPPFile? { val result = CompletableDeferred() From 4693483c2b67da1ffc0546311a0758ccc939b254 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 12 Mar 2022 01:12:17 +0600 Subject: [PATCH 4/7] rename selectFile with result MPPFile to selectFileOrThrow --- CHANGELOG.md | 2 +- .../jsMain/kotlin/dev.inmo.micro_utils.coroutines/SelectFile.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0896b84dfb3..1a8003d5c9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ * New extension `Flow.toMutableState` * New extension `StateFlow.toMutableState` * `JS`: - * New function `selectFile` on top of `selectFile` from `common` + * New function `selectFileOrThrow` on top of `selectFile` from `common` * New function `selectFileOrNull` on top of `selectFile` from `common` ## 0.9.11 diff --git a/coroutines/src/jsMain/kotlin/dev.inmo.micro_utils.coroutines/SelectFile.kt b/coroutines/src/jsMain/kotlin/dev.inmo.micro_utils.coroutines/SelectFile.kt index e9ee57f3b42..2e2ab2f95a9 100644 --- a/coroutines/src/jsMain/kotlin/dev.inmo.micro_utils.coroutines/SelectFile.kt +++ b/coroutines/src/jsMain/kotlin/dev.inmo.micro_utils.coroutines/SelectFile.kt @@ -5,7 +5,7 @@ import dev.inmo.micro_utils.common.selectFile import kotlinx.coroutines.CompletableDeferred import org.w3c.dom.HTMLInputElement -suspend fun selectFile( +suspend fun selectFileOrThrow( inputSetup: (HTMLInputElement) -> Unit = {} ): MPPFile { val result = CompletableDeferred() From 76813fae8e728fb513b4ff4d50294064c30da986 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 12 Mar 2022 01:28:41 +0600 Subject: [PATCH 5/7] hotfix in selectFile --- .../src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt b/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt index bd85f4de52b..c1b3a7c716c 100644 --- a/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt +++ b/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt @@ -13,6 +13,7 @@ fun selectFile( ) { (document.createElement("input") { (this as HTMLInputElement).apply { + type = "file" inputSetup(this) onchange = { runCatching { From 02520636add7acfa66d890e474a4d7305f9d8dc4 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 12 Mar 2022 01:28:53 +0600 Subject: [PATCH 6/7] hotfix in selectFile --- .../src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt b/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt index c1b3a7c716c..c2af68ad32d 100644 --- a/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt +++ b/common/src/jsMain/kotlin/dev/inmo/micro_utils/common/SelectFile.kt @@ -14,7 +14,6 @@ fun selectFile( (document.createElement("input") { (this as HTMLInputElement).apply { type = "file" - inputSetup(this) onchange = { runCatching { files ?.get(0) ?: error("File must not be null") @@ -24,6 +23,7 @@ fun selectFile( onFailure(it) } } + inputSetup(this) } } as HTMLElement).click() } From 00cc26d87489df668d6f57c384a7e6556f2907f3 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 12 Mar 2022 01:38:13 +0600 Subject: [PATCH 7/7] fix in publication scripts --- .github/workflows/packages_push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/packages_push.yml b/.github/workflows/packages_push.yml index f42c2d5a8e0..9fb2a736b8e 100644 --- a/.github/workflows/packages_push.yml +++ b/.github/workflows/packages_push.yml @@ -22,7 +22,7 @@ jobs: run: ./gradlew build - name: Publish continue-on-error: true - run: ./gradlew --no-parallel publishAllPublicationsToGithubPackagesRepository -x signJsPublication -x signJvmPublication -x signKotlinMultiplatformPublication -x signAndroidDebugPublication -x signAndroidReleasePublication -x signKotlinMultiplatformPublication + run: ./gradlew --no-parallel publishAllPublicationsToGithubPackagesRepository env: GITHUBPACKAGES_USER: ${{ github.actor }} GITHUBPACKAGES_PASSWORD: ${{ secrets.GITHUB_TOKEN }}