From 5b596c76e05edaf43bcc757bacd49421aab6a69d Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Tue, 10 Nov 2020 17:09:14 +0600 Subject: [PATCH] updates of dokka --- .../recyclerview}/build.gradle | 5 +- .../recyclerview/src/main/AndroidManifest.xml | 1 + .../AbstractStandardViewHolder.kt | 22 ++++++ .../recyclerview/AbstractViewHolder.kt | 10 +++ .../android/recyclerview/Divider.kt | 9 +++ .../android/recyclerview/LeftItems.kt | 47 +++++++++++ .../recyclerview/RecyclerViewAdapter.kt | 68 ++++++++++++++++ build.gradle | 1 + coroutines/build.gradle | 5 ++ .../dev/inmo/micro_utils/coroutines/DoInUI.kt | 10 +++ dokka/build.gradle | 77 +++++++++++++++---- dokka/gradle.properties | 2 - dokka/src/main/AndroidManifest.xml | 1 + gradle.properties | 7 ++ repos/android/src/main/AndroidManifest.xml | 1 - settings.gradle | 1 + 16 files changed, 246 insertions(+), 21 deletions(-) rename {repos/android => android/recyclerview}/build.gradle (66%) create mode 100644 android/recyclerview/src/main/AndroidManifest.xml create mode 100644 android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/AbstractStandardViewHolder.kt create mode 100644 android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/AbstractViewHolder.kt create mode 100644 android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/Divider.kt create mode 100644 android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/LeftItems.kt create mode 100644 android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/RecyclerViewAdapter.kt create mode 100644 coroutines/src/main/kotlin/dev/inmo/micro_utils/coroutines/DoInUI.kt create mode 100644 dokka/src/main/AndroidManifest.xml delete mode 100644 repos/android/src/main/AndroidManifest.xml diff --git a/repos/android/build.gradle b/android/recyclerview/build.gradle similarity index 66% rename from repos/android/build.gradle rename to android/recyclerview/build.gradle index aa5218eaf68..c130272d88d 100644 --- a/repos/android/build.gradle +++ b/android/recyclerview/build.gradle @@ -11,13 +11,12 @@ kotlin { sourceSets { commonMain { dependencies { - api internalProject("micro_utils.repos.common") - api internalProject("micro_utils.coroutines") + api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version" } } androidMain { dependencies { - implementation "androidx.core:core-ktx:$core_ktx_version" + api "androidx.recyclerview:recyclerview:$androidx_recycler_version" } } } diff --git a/android/recyclerview/src/main/AndroidManifest.xml b/android/recyclerview/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..d08d0502fee --- /dev/null +++ b/android/recyclerview/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/AbstractStandardViewHolder.kt b/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/AbstractStandardViewHolder.kt new file mode 100644 index 00000000000..ebcbb481015 --- /dev/null +++ b/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/AbstractStandardViewHolder.kt @@ -0,0 +1,22 @@ +package dev.inmo.micro_utils.android.recyclerview + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup + +abstract class AbstractStandardViewHolder( + inflater: LayoutInflater, + container: ViewGroup?, + viewId: Int, + onViewInflated: ((View) -> Unit)? = null +) : AbstractViewHolder( + inflater.inflate(viewId, container, false).also { + onViewInflated ?.invoke(it) + } +) { + constructor( + container: ViewGroup, + viewId: Int, + onViewInflated: ((View) -> Unit)? = null + ) : this(LayoutInflater.from(container.context), container, viewId, onViewInflated) +} diff --git a/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/AbstractViewHolder.kt b/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/AbstractViewHolder.kt new file mode 100644 index 00000000000..529bbbd4dd3 --- /dev/null +++ b/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/AbstractViewHolder.kt @@ -0,0 +1,10 @@ +package dev.inmo.micro_utils.android.recyclerview + +import android.view.View +import androidx.recyclerview.widget.RecyclerView + +abstract class AbstractViewHolder( + view: View +) : RecyclerView.ViewHolder(view) { + abstract fun onBind(item: T) +} diff --git a/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/Divider.kt b/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/Divider.kt new file mode 100644 index 00000000000..21b03ca80b0 --- /dev/null +++ b/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/Divider.kt @@ -0,0 +1,9 @@ +package dev.inmo.micro_utils.android.recyclerview + +import android.content.Context +import android.widget.LinearLayout +import androidx.recyclerview.widget.DividerItemDecoration + +val Context.recyclerViewItemsDecoration + get() = DividerItemDecoration(this, LinearLayout.VERTICAL) + diff --git a/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/LeftItems.kt b/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/LeftItems.kt new file mode 100644 index 00000000000..fc6d51b864e --- /dev/null +++ b/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/LeftItems.kt @@ -0,0 +1,47 @@ +package dev.inmo.micro_utils.android.recyclerview + +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.* + +fun RecyclerView.lastVisibleItemFlow( + completingScope: CoroutineScope +): Flow { + val lastVisibleElementFun: () -> Int = (layoutManager as? LinearLayoutManager) ?.let { it::findLastVisibleItemPosition } ?: error("Currently supported only linear layout manager") + val lastVisibleFlow = MutableStateFlow(lastVisibleElementFun()) + addOnScrollListener( + object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + lastVisibleFlow.value = lastVisibleElementFun() + } + }.also { scrollListener -> + lastVisibleFlow.onCompletion { + removeOnScrollListener(scrollListener) + }.launchIn(completingScope) + } + ) + return lastVisibleFlow.asStateFlow() +} + +inline fun Flow.mapLeftItems( + crossinline countGetter: () -> Int +): Flow = map { countGetter() - it } + +inline fun Flow.mapRequireFilling( + minimalLeftItems: Int, + crossinline countGetter: () -> Int +): Flow = mapLeftItems(countGetter).mapNotNull { + if (it < minimalLeftItems) { + it + } else { + null + } +} + +inline fun RecyclerView.mapRequireFilling( + minimalLeftItems: Int, + completingScope: CoroutineScope, + crossinline countGetter: () -> Int +): Flow = lastVisibleItemFlow(completingScope).mapRequireFilling(minimalLeftItems, countGetter) diff --git a/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/RecyclerViewAdapter.kt b/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/RecyclerViewAdapter.kt new file mode 100644 index 00000000000..96d1020fff6 --- /dev/null +++ b/android/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/recyclerview/RecyclerViewAdapter.kt @@ -0,0 +1,68 @@ +package dev.inmo.micro_utils.android.recyclerview + +import android.view.View +import androidx.recyclerview.widget.RecyclerView + + +abstract class RecyclerViewAdapter( + val data: List +): RecyclerView.Adapter>() { + var emptyView: View? = null + set(value) { + field = value + checkEmpty() + } + + init { + registerAdapterDataObserver( + object : RecyclerView.AdapterDataObserver() { + override fun onItemRangeChanged(positionStart: Int, itemCount: Int) { + super.onItemRangeChanged(positionStart, itemCount) + checkEmpty() + } + + override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) { + super.onItemRangeChanged(positionStart, itemCount, payload) + checkEmpty() + } + + override fun onChanged() { + super.onChanged() + checkEmpty() + } + + override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) { + super.onItemRangeRemoved(positionStart, itemCount) + checkEmpty() + } + + override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) { + super.onItemRangeMoved(fromPosition, toPosition, itemCount) + checkEmpty() + } + + override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { + super.onItemRangeInserted(positionStart, itemCount) + checkEmpty() + } + } + ) + checkEmpty() + } + + override fun getItemCount(): Int = data.size + + override fun onBindViewHolder(holder: AbstractViewHolder, position: Int) { + holder.onBind(data[position]) + } + + private fun checkEmpty() { + emptyView ?. let { + if (data.isEmpty()) { + it.visibility = View.VISIBLE + } else { + it.visibility = View.GONE + } + } + } +} diff --git a/build.gradle b/build.gradle index ced5e4a2e35..c6d3e1911c6 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,7 @@ buildscript { classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version" classpath "com.getkeepsafe.dexcount:dexcount-gradle-plugin:$dexcount_version" classpath "com.github.breadmoirai:github-release:$github_release_plugin_version" + classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version" } } diff --git a/coroutines/build.gradle b/coroutines/build.gradle index 6cfeab046d3..19bbfe5aaac 100644 --- a/coroutines/build.gradle +++ b/coroutines/build.gradle @@ -14,5 +14,10 @@ kotlin { api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version" } } + androidMain { + dependencies { + api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version" + } + } } } \ No newline at end of file diff --git a/coroutines/src/main/kotlin/dev/inmo/micro_utils/coroutines/DoInUI.kt b/coroutines/src/main/kotlin/dev/inmo/micro_utils/coroutines/DoInUI.kt new file mode 100644 index 00000000000..f938e53655f --- /dev/null +++ b/coroutines/src/main/kotlin/dev/inmo/micro_utils/coroutines/DoInUI.kt @@ -0,0 +1,10 @@ +package dev.inmo.micro_utils.coroutines + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +suspend inline fun doInUI(noinline block: suspend CoroutineScope.() -> T) = withContext( + Dispatchers.Main, + block +) diff --git a/dokka/build.gradle b/dokka/build.gradle index b619aa90912..fee10660b29 100644 --- a/dokka/build.gradle +++ b/dokka/build.gradle @@ -1,26 +1,15 @@ -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" + id "com.android.library" + id "kotlin-android-extensions" + id "org.jetbrains.dokka" } repositories { mavenLocal() jcenter() + google() mavenCentral() } @@ -30,6 +19,7 @@ kotlin { browser() nodejs() } + android {} sourceSets { commonMain { @@ -41,6 +31,57 @@ kotlin { it != project && it.hasProperty("kotlin") && it.kotlin.sourceSets.any { it.name.contains("commonMain") } + && it.kotlin.sourceSets.any { it.name.contains("jsMain") } + && it.kotlin.sourceSets.any { it.name.contains("jvmMain") } + && it.kotlin.sourceSets.any { it.name.contains("androidMain") } + ) { + api it + } + } + } + } + jsMain { + dependencies { + implementation kotlin('stdlib') + + project.parent.subprojects.forEach { + if ( + it != project + && it.hasProperty("kotlin") + && it.kotlin.sourceSets.any { it.name.contains("commonMain") } + && it.kotlin.sourceSets.any { it.name.contains("jsMain") } + ) { + api it + } + } + } + } + jvmMain { + dependencies { + implementation kotlin('stdlib') + + project.parent.subprojects.forEach { + if ( + it != project + && it.hasProperty("kotlin") + && it.kotlin.sourceSets.any { it.name.contains("commonMain") } + && it.kotlin.sourceSets.any { it.name.contains("jvmMain") } + ) { + api it + } + } + } + } + androidMain { + dependencies { + implementation kotlin('stdlib') + + project.parent.subprojects.forEach { + if ( + it != project + && it.hasProperty("kotlin") + && it.kotlin.sourceSets.any { it.name.contains("commonMain") } + && it.kotlin.sourceSets.any { it.name.contains("androidMain") } ) { api it } @@ -84,5 +125,11 @@ tasks.dokkaHtml { named("jvmMain") { sourceRoots.setFrom(findSourcesWithName("jvmMain", "commonMain")) } + + named("androidMain") { + sourceRoots.setFrom(findSourcesWithName("androidMain", "commonMain")) + } } } + +apply from: "$defaultAndroidSettingsPresetPath" diff --git a/dokka/gradle.properties b/dokka/gradle.properties index 55021b5f4e7..e9157af4da1 100644 --- a/dokka/gradle.properties +++ b/dokka/gradle.properties @@ -1,3 +1 @@ -dokka_version=1.4.0 - org.gradle.jvmargs=-Xmx1024m diff --git a/dokka/src/main/AndroidManifest.xml b/dokka/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..adef5c13dee --- /dev/null +++ b/dokka/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 250c56a1160..c0330ffc885 100644 --- a/gradle.properties +++ b/gradle.properties @@ -23,6 +23,7 @@ uuidVersion=0.2.2 # ANDROID core_ktx_version=1.3.2 +androidx_recycler_version=1.1.0 android_minSdkVersion=24 android_compileSdkVersion=30 @@ -32,6 +33,12 @@ junit_version=4.12 test_ext_junit_version=1.1.2 espresso_core=3.3.0 +# Dokka + +dokka_version=1.4.0 + +# Project data + group=dev.inmo version=0.3.1 android_code_version=1 diff --git a/repos/android/src/main/AndroidManifest.xml b/repos/android/src/main/AndroidManifest.xml deleted file mode 100644 index cbd8db25bb7..00000000000 --- a/repos/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 4bfb57df815..811699ed9eb 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,6 +17,7 @@ String[] includes = [ ":ktor:common", ":ktor:client", ":coroutines", + ":android:recyclerview", ":dokka" ]