From 76102e9ab37ceb3b42eab46fb57223b1f3889e5e Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 26 Nov 2020 15:00:32 +0600 Subject: [PATCH 1/6] start 0.4.6 --- CHANGELOG.md | 2 ++ gradle.properties | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d78a750c5b..f56277219be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +## 0.4.6 + ## 0.4.5 * `Android` diff --git a/gradle.properties b/gradle.properties index 7e25e2c12df..5d73253b5e1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -41,5 +41,5 @@ dokka_version=1.4.0 # Project data group=dev.inmo -version=0.4.5 -android_code_version=9 +version=0.4.6 +android_code_version=10 From 023f841fb595fbdff362e02233d1060522631bdd Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 26 Nov 2020 15:01:45 +0600 Subject: [PATCH 2/6] Pagination#isFirstPage --- CHANGELOG.md | 4 ++++ .../kotlin/dev/inmo/micro_utils/pagination/Pagination.kt | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f56277219be..5491320f880 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## 0.4.6 +* `Pagination` + * `Common` + * `Pagination` got new extension: `Pagination#isFirstPage` + ## 0.4.5 * `Android` diff --git a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/Pagination.kt b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/Pagination.kt index adfa364f0fc..69bb2138c64 100644 --- a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/Pagination.kt +++ b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/Pagination.kt @@ -22,6 +22,12 @@ interface Pagination { val size: Int } +/** + * Logical shortcut for comparison that page is 0 + */ +inline val Pagination.isFirstPage + get() = page == 0 + /** * First number in index of objects. It can be used as offset for databases or other data sources */ From c201866c5166b55ebe5607c1c4ae611af6225a0e Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 26 Nov 2020 15:02:30 +0600 Subject: [PATCH 3/6] FlowCollector#invoke --- CHANGELOG.md | 2 ++ .../dev/inmo/micro_utils/coroutines/FlowCollectorInvoking.kt | 5 +++++ 2 files changed, 7 insertions(+) create mode 100644 coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/FlowCollectorInvoking.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 5491320f880..9076a6f3a37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ * `Pagination` * `Common` * `Pagination` got new extension: `Pagination#isFirstPage` +* `Coroutines`: + * New extension `FlowCollector#invoke` has been added ## 0.4.5 diff --git a/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/FlowCollectorInvoking.kt b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/FlowCollectorInvoking.kt new file mode 100644 index 00000000000..8ae54ebfc75 --- /dev/null +++ b/coroutines/src/commonMain/kotlin/dev/inmo/micro_utils/coroutines/FlowCollectorInvoking.kt @@ -0,0 +1,5 @@ +package dev.inmo.micro_utils.coroutines + +import kotlinx.coroutines.flow.FlowCollector + +suspend inline operator fun FlowCollector.invoke(value: T) = emit(value) From 49ee38a93637e67bbe017f11d116931ecb29b3d2 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 26 Nov 2020 15:03:40 +0600 Subject: [PATCH 4/6] FileStandardKeyValueRepo --- CHANGELOG.md | 4 + .../repos/FileStandardKeyValueRepo.kt | 168 ++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileStandardKeyValueRepo.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 9076a6f3a37..f69a5c3bdd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ * `Pagination` got new extension: `Pagination#isFirstPage` * `Coroutines`: * New extension `FlowCollector#invoke` has been added +* `Repos` + * `Common` + * `JVM` (and `Android` since `Android API 26`): + * `FileStandardKeyValueRepo` has been added ## 0.4.5 diff --git a/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileStandardKeyValueRepo.kt b/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileStandardKeyValueRepo.kt new file mode 100644 index 00000000000..3e698df4e29 --- /dev/null +++ b/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileStandardKeyValueRepo.kt @@ -0,0 +1,168 @@ +package dev.inmo.micro_utils.repos + +import dev.inmo.micro_utils.pagination.* +import dev.inmo.micro_utils.pagination.utils.reverse +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import java.io.File +import java.nio.file.FileSystems +import java.nio.file.Path +import java.nio.file.StandardWatchEventKinds.* + +private inline val String.isAbsolute + get() = startsWith(File.separator) + +class FileReadStandardKeyValueRepo( + private val folder: File +) : ReadStandardKeyValueRepo { + init { + folder.mkdirs() + } + + override suspend fun get(k: String): File? { + val file = File(folder, k) + if (file.exists()) { + return file + } + return null + } + + override suspend fun values(pagination: Pagination, reversed: Boolean): PaginationResult { + val count = count() + val resultPagination = if (reversed) pagination.reverse(count) else pagination + val filesPaths = folder.list() ?.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndex) ?: return emptyPaginationResult() + if (reversed) { + filesPaths.reverse() + } + return filesPaths.map { File(folder, it) }.createPaginationResult( + resultPagination, + count + ) + } + + override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult { + val count = count() + val resultPagination = if (reversed) pagination.reverse(count) else pagination + val filesPaths = folder.list() ?.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndex) ?: return emptyPaginationResult() + if (reversed) { + filesPaths.reverse() + } + return filesPaths.toList().createPaginationResult( + resultPagination, + count + ) + } + + override suspend fun keys( + v: File, + pagination: Pagination, + reversed: Boolean + ): PaginationResult { + val resultPagination = if (reversed) pagination.reverse(1L) else pagination + return if (resultPagination.isFirstPage) { + val fileSubpath = v.absolutePath.removePrefix(folder.absolutePath) + if (fileSubpath == v.absolutePath) { + emptyList() + } else { + listOf(fileSubpath) + } + } else { + emptyList() + }.createPaginationResult(resultPagination, 1L) + } + + override suspend fun contains(key: String): Boolean { + return File(folder, key).exists() + } + + override suspend fun count(): Long = folder.list() ?.size ?.toLong() ?: 0L +} + +/** + * Files watching will not correctly works on Android with version of API lower than API 26 + */ +class FileWriteStandardKeyValueRepo( + private val folder: File, + filesChangedProcessingScope: CoroutineScope? = null +) : WriteStandardKeyValueRepo { + private val _onNewValue = MutableSharedFlow>() + override val onNewValue: Flow> = _onNewValue.asSharedFlow() + private val _onValueRemoved = MutableSharedFlow() + override val onValueRemoved: Flow = _onValueRemoved.asSharedFlow() + + init { + folder.mkdirs() + filesChangedProcessingScope ?.let { + it.launch { + try { + val folderPath = folder.toPath() + while (isActive) { + val key = try { + folderPath.register(FileSystems.getDefault().newWatchService(), ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE) + } catch (e: Exception) { + // add verbose way to show that file watching is not working + return@launch + } + + for (event in key.pollEvents()) { + val relativeFilePath = (event.context() as? Path) ?: continue + val file = relativeFilePath.toFile() + val relativePath = file.toRelativeString(folder) + + when (event.kind()) { + ENTRY_CREATE, ENTRY_MODIFY -> { + launch { + _onNewValue.emit(relativePath to file) + } + } + ENTRY_DELETE -> { + launch { + _onValueRemoved.emit(relativePath) + } + } + } + } + + if (key.isValid || folder.exists()) { + continue + } + break + } + } catch (e: Throwable) { + // add verbose way to notify that this functionality is disabled + } + } + } + } + + override suspend fun set(toSet: Map) { + supervisorScope { + toSet.map { (filename, fileSource) -> + launch { + val file = File(folder, filename) + + file.delete() + fileSource.copyTo(file, overwrite = true) + _onNewValue.emit(filename to file) + } + } + }.joinAll() + } + + override suspend fun unset(toUnset: List) { + toUnset.forEach { + val file = File(folder, it) + if (file.exists()) { + file.delete() + _onValueRemoved.emit(it) + } + } + } +} + +class FileStandardKeyValueRepo( + folder: File, + filesChangedProcessingScope: CoroutineScope? = null +) : StandardKeyValueRepo, + WriteStandardKeyValueRepo by FileWriteStandardKeyValueRepo(folder, filesChangedProcessingScope), + ReadStandardKeyValueRepo by FileReadStandardKeyValueRepo(folder) \ No newline at end of file From b82c3864a02c169c97e728be3dc4135c5070f471 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 26 Nov 2020 15:32:00 +0600 Subject: [PATCH 5/6] typealiases for repos --- CHANGELOG.md | 1 + .../dev/inmo/micro_utils/repos/OneToManyKeyValueRepo.kt | 3 +++ .../kotlin/dev/inmo/micro_utils/repos/StandartCRUDRepo.kt | 5 ++++- .../dev/inmo/micro_utils/repos/StandartKeyValueRepo.kt | 5 ++++- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f69a5c3bdd6..d9a89e74d13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * `Common` * `JVM` (and `Android` since `Android API 26`): * `FileStandardKeyValueRepo` has been added + * Add several `typealias`es for each type of repos ## 0.4.5 diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/OneToManyKeyValueRepo.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/OneToManyKeyValueRepo.kt index 12137c06c74..b08e10ff5da 100644 --- a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/OneToManyKeyValueRepo.kt +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/OneToManyKeyValueRepo.kt @@ -36,6 +36,7 @@ interface ReadOneToManyKeyValueRepo : Repo { } } } +typealias ReadKeyValuesRepo = ReadOneToManyKeyValueRepo interface WriteOneToManyKeyValueRepo : Repo { val onNewValue: Flow> @@ -53,6 +54,7 @@ interface WriteOneToManyKeyValueRepo : Repo { add(toSet) } } +typealias WriteKeyValuesRepo = WriteOneToManyKeyValueRepo suspend inline fun > REPO.add( keysAndValues: List>> @@ -87,6 +89,7 @@ suspend inline fun WriteOneToManyKeyValueRepo.set( ) = set(k, v.toList()) interface OneToManyKeyValueRepo : ReadOneToManyKeyValueRepo, WriteOneToManyKeyValueRepo +typealias KeyValuesRepo = OneToManyKeyValueRepo suspend inline fun WriteOneToManyKeyValueRepo.remove( keysAndValues: List>> diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/StandartCRUDRepo.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/StandartCRUDRepo.kt index 28ad1ac34c7..df64fc47de7 100644 --- a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/StandartCRUDRepo.kt +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/StandartCRUDRepo.kt @@ -10,6 +10,7 @@ interface ReadStandardCRUDRepo : Repo { suspend fun contains(id: IdType): Boolean suspend fun count(): Long } +typealias ReadCRUDRepo = ReadStandardCRUDRepo typealias UpdatedValuePair = Pair val UpdatedValuePair.id @@ -27,6 +28,7 @@ interface WriteStandardCRUDRepo : Repo { suspend fun update(values: List>): List suspend fun deleteById(ids: List) } +typealias WriteCRUDRepo = WriteStandardCRUDRepo suspend fun WriteStandardCRUDRepo.create( vararg values: InputValueType @@ -39,4 +41,5 @@ suspend fun WriteStandardCRUDRepo : ReadStandardCRUDRepo, - WriteStandardCRUDRepo \ No newline at end of file + WriteStandardCRUDRepo +typealias CRUDRepo = StandardCRUDRepo \ No newline at end of file diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/StandartKeyValueRepo.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/StandartKeyValueRepo.kt index e66ee7bd2f3..a9ae6adfd1c 100644 --- a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/StandartKeyValueRepo.kt +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/StandartKeyValueRepo.kt @@ -12,6 +12,7 @@ interface ReadStandardKeyValueRepo : Repo { suspend fun contains(key: Key): Boolean suspend fun count(): Long } +typealias ReadKeyValueRepo = ReadStandardKeyValueRepo interface WriteStandardKeyValueRepo : Repo { val onNewValue: Flow> @@ -20,6 +21,7 @@ interface WriteStandardKeyValueRepo : Repo { suspend fun set(toSet: Map) suspend fun unset(toUnset: List) } +typealias WriteKeyValueRepo = WriteStandardKeyValueRepo suspend inline fun WriteStandardKeyValueRepo.set( vararg toSet: Pair @@ -33,4 +35,5 @@ suspend inline fun WriteStandardKeyValueRepo.unset( vararg k: Key ) = unset(k.toList()) -interface StandardKeyValueRepo : ReadStandardKeyValueRepo, WriteStandardKeyValueRepo \ No newline at end of file +interface StandardKeyValueRepo : ReadStandardKeyValueRepo, WriteStandardKeyValueRepo +typealias KeyValueRepo = StandardKeyValueRepo From 091bb1394f10a3b756f96c4a288074af00b8b813 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Thu, 26 Nov 2020 18:01:12 +0600 Subject: [PATCH 6/6] Warning annotation --- CHANGELOG.md | 2 ++ .../dev/inmo/micro_utils/common/Annotations.kt | 18 ++++++++++++++++++ repos/common/build.gradle | 5 +++++ .../repos/FileStandardKeyValueRepo.kt | 3 +++ 4 files changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9a89e74d13..fb248dad33a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## 0.4.6 +* `Common` + * New annotation `Warning` has been added * `Pagination` * `Common` * `Pagination` got new extension: `Pagination#isFirstPage` diff --git a/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/Annotations.kt b/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/Annotations.kt index a05f4360397..7873443768c 100644 --- a/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/Annotations.kt +++ b/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/Annotations.kt @@ -17,3 +17,21 @@ package dev.inmo.micro_utils.common AnnotationTarget.TYPE_PARAMETER ) annotation class PreviewFeature + +@RequiresOptIn( + "This thing is marked as warned. See message of warn to get more info", + RequiresOptIn.Level.WARNING +) +@Target( + AnnotationTarget.CLASS, + AnnotationTarget.CONSTRUCTOR, + AnnotationTarget.FIELD, + AnnotationTarget.PROPERTY, + AnnotationTarget.PROPERTY_GETTER, + AnnotationTarget.PROPERTY_SETTER, + AnnotationTarget.FUNCTION, + AnnotationTarget.TYPE, + AnnotationTarget.TYPEALIAS, + AnnotationTarget.TYPE_PARAMETER +) +annotation class Warning(val message: String) diff --git a/repos/common/build.gradle b/repos/common/build.gradle index cd8a5615d26..3a41642d0cd 100644 --- a/repos/common/build.gradle +++ b/repos/common/build.gradle @@ -17,6 +17,11 @@ kotlin { } } + jvmMain { + dependencies { + api internalProject("micro_utils.common") + } + } androidMain { dependencies { api "androidx.core:core-ktx:$core_ktx_version" diff --git a/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileStandardKeyValueRepo.kt b/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileStandardKeyValueRepo.kt index 3e698df4e29..99553103c5a 100644 --- a/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileStandardKeyValueRepo.kt +++ b/repos/common/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/FileStandardKeyValueRepo.kt @@ -1,5 +1,6 @@ package dev.inmo.micro_utils.repos +import dev.inmo.micro_utils.common.Warning import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.pagination.utils.reverse import kotlinx.coroutines.* @@ -81,6 +82,7 @@ class FileReadStandardKeyValueRepo( /** * Files watching will not correctly works on Android with version of API lower than API 26 */ +@Warning("Files watching will not correctly works on Android Platform with version of API lower than API 26") class FileWriteStandardKeyValueRepo( private val folder: File, filesChangedProcessingScope: CoroutineScope? = null @@ -160,6 +162,7 @@ class FileWriteStandardKeyValueRepo( } } +@Warning("Files watching will not correctly works on Android Platform with version of API lower than API 26") class FileStandardKeyValueRepo( folder: File, filesChangedProcessingScope: CoroutineScope? = null