diff --git a/CHANGELOG.md b/CHANGELOG.md index db3fc88a875..1d78a750c5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 0.4.5 + +* `Android` + * `Alerts` + * `Common` + * Project has been created + * `RecyclerView` + * Project has been created +* `Common` + * Annotation `PreviewFeature` has been added + * `Android` + * Added tools to work with visibility in more comfortable way + * Added tools to work with disabled/enabled state in more comfortable way + * Added tools to work with expanded/collapsed state in more comfortable way (in preview mode) + ## 0.4.4 * `Versions`: diff --git a/android/alerts/common/build.gradle b/android/alerts/common/build.gradle new file mode 100644 index 00000000000..b60575bd26f --- /dev/null +++ b/android/alerts/common/build.gradle @@ -0,0 +1,17 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.serialization" + id "com.android.library" +} + +apply from: "$mppAndroidProjectPresetPath" + +kotlin { + sourceSets { + androidMain { + dependencies { + api "androidx.appcompat:appcompat-resources:$appcompat_version" + } + } + } +} diff --git a/android/alerts/common/src/main/AndroidManifest.xml b/android/alerts/common/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..59c21c66815 --- /dev/null +++ b/android/alerts/common/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/android/alerts/common/src/main/kotlin/dev/inmo/micro_utils/android/alerts/common/AlertDialog.kt b/android/alerts/common/src/main/kotlin/dev/inmo/micro_utils/android/alerts/common/AlertDialog.kt new file mode 100644 index 00000000000..7277b23c819 --- /dev/null +++ b/android/alerts/common/src/main/kotlin/dev/inmo/micro_utils/android/alerts/common/AlertDialog.kt @@ -0,0 +1,55 @@ +@file:Suppress("NOTHING_TO_INLINE", "unused") + +package dev.inmo.micro_utils.android.alerts.common + +import android.app.AlertDialog +import android.content.Context +import android.content.DialogInterface + +typealias AlertDialogCallback = (DialogInterface) -> Unit + +inline fun Context.createAlertDialogTemplate( + title: String? = null, + positivePair: Pair? = null, + neutralPair: Pair? = null, + negativePair: Pair? = null +): AlertDialog.Builder { + val builder = AlertDialog.Builder(this) + + title ?.let { + builder.setTitle(title) + } + + positivePair ?. let { + builder.setPositiveButton(it.first) { di, _ -> it.second ?. invoke(di) } + } + negativePair ?. let { + builder.setNegativeButton(it.first) { di, _ -> it.second ?. invoke(di) } + } + neutralPair ?. let { + builder.setNeutralButton(it.first) { di, _ -> it.second ?. invoke(di) } + } + + return builder +} + +inline fun Context.createAlertDialogTemplateWithResources( + title: Int? = null, + positivePair: Pair? = null, + neutralPair: Pair? = null, + negativePair: Pair? = null +): AlertDialog.Builder = createAlertDialogTemplate( + title ?.let { getString(it) }, + positivePair ?.let { getString(it.first) to it.second }, + neutralPair ?.let { getString(it.first) to it.second }, + negativePair ?.let { getString(it.first) to it.second } +) + +inline fun AlertDialog.setDismissChecker(noinline checker: () -> Boolean) : AlertDialog { + setOnDismissListener { + if (!checker()) { + show() + } + } + return this +} diff --git a/android/alerts/common/src/main/kotlin/dev/inmo/micro_utils/android/alerts/common/CustomAlertDialog.kt b/android/alerts/common/src/main/kotlin/dev/inmo/micro_utils/android/alerts/common/CustomAlertDialog.kt new file mode 100644 index 00000000000..9fc8b180a94 --- /dev/null +++ b/android/alerts/common/src/main/kotlin/dev/inmo/micro_utils/android/alerts/common/CustomAlertDialog.kt @@ -0,0 +1,38 @@ +@file:Suppress("NOTHING_TO_INLINE", "unused") + +package dev.inmo.micro_utils.android.alerts.common + +import android.app.AlertDialog +import android.content.Context +import android.view.View + +inline fun Context.createCustomViewAlertDialog( + title: String? = null, + positivePair: Pair? = null, + neutralPair: Pair? = null, + negativePair: Pair? = null, + show: Boolean = true, + viewCreator: (Context) -> T +): AlertDialog = createAlertDialogTemplate( + title, positivePair, neutralPair, negativePair +).apply { + setView(viewCreator(this@createCustomViewAlertDialog)) +}.create().apply { + if (show) show() +} + +inline fun Context.createCustomViewAlertDialogWithResources( + title: Int? = null, + positivePair: Pair? = null, + neutralPair: Pair? = null, + negativePair: Pair? = null, + show: Boolean = true, + viewCreator: (Context) -> T +): AlertDialog = createCustomViewAlertDialog( + title ?.let { getString(it) }, + positivePair ?.let { getString(it.first) to it.second }, + neutralPair ?.let { getString(it.first) to it.second }, + negativePair ?.let { getString(it.first) to it.second }, + show, + viewCreator +) diff --git a/android/alerts/common/src/main/kotlin/dev/inmo/micro_utils/android/alerts/common/SimpleTextAlert.kt b/android/alerts/common/src/main/kotlin/dev/inmo/micro_utils/android/alerts/common/SimpleTextAlert.kt new file mode 100644 index 00000000000..36f7b6bb7a7 --- /dev/null +++ b/android/alerts/common/src/main/kotlin/dev/inmo/micro_utils/android/alerts/common/SimpleTextAlert.kt @@ -0,0 +1,45 @@ +@file:Suppress("NOTHING_TO_INLINE", "unused") + +package dev.inmo.micro_utils.android.alerts.common + +import android.app.AlertDialog +import android.content.Context +import androidx.annotation.StringRes + +inline fun Context.createSimpleTextAlertDialog( + text: String, + title: String? = null, + positivePair: Pair? = null, + neutralPair: Pair? = null, + negativePair: Pair? = null, + show: Boolean = true +): AlertDialog = createAlertDialogTemplate( + title, + positivePair, + neutralPair, + negativePair +).apply { + setMessage(text) +}.create().apply { + if (show) { + show() + } +} + +inline fun Context.createSimpleTextAlertDialog( + @StringRes + text: Int, + @StringRes + title: Int? = null, + positivePair: Pair? = null, + neutralPair: Pair? = null, + negativePair: Pair? = null, + show: Boolean = true +): AlertDialog = createSimpleTextAlertDialog( + getString(text), + title ?.let { getString(it) }, + positivePair ?.let { getString(it.first) to it.second }, + neutralPair ?.let { getString(it.first) to it.second }, + negativePair ?.let { getString(it.first) to it.second }, + show +) diff --git a/android/alerts/recyclerview/build.gradle b/android/alerts/recyclerview/build.gradle new file mode 100644 index 00000000000..af7d2b0b2cc --- /dev/null +++ b/android/alerts/recyclerview/build.gradle @@ -0,0 +1,18 @@ +plugins { + id "org.jetbrains.kotlin.multiplatform" + id "org.jetbrains.kotlin.plugin.serialization" + id "com.android.library" +} + +apply from: "$mppAndroidProjectPresetPath" + +kotlin { + sourceSets { + commonMain { + dependencies { + api internalProject("micro_utils.android.alerts.common") + api internalProject("micro_utils.android.recyclerview") + } + } + } +} diff --git a/android/alerts/recyclerview/src/main/AndroidManifest.xml b/android/alerts/recyclerview/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..41c01e3ee69 --- /dev/null +++ b/android/alerts/recyclerview/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/android/alerts/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/alerts/recyclerview/ActionsAlerts.kt b/android/alerts/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/alerts/recyclerview/ActionsAlerts.kt new file mode 100644 index 00000000000..99efd6ebe41 --- /dev/null +++ b/android/alerts/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/alerts/recyclerview/ActionsAlerts.kt @@ -0,0 +1,65 @@ +@file:Suppress("unused") + +package dev.inmo.micro_utils.android.alerts.recyclerview + +import android.app.AlertDialog +import android.content.Context +import android.content.DialogInterface +import android.view.ViewGroup +import android.widget.TextView +import dev.inmo.micro_utils.android.alerts.common.AlertDialogCallback +import dev.inmo.micro_utils.android.recyclerview.* + +data class AlertAction( + val title: String, + val callback: (DialogInterface) -> Unit +) + +private class ActionViewHolder( + container: ViewGroup, dialogInterfaceGetter: () -> DialogInterface +) : AbstractStandardViewHolder(container, android.R.layout.simple_list_item_1) { + private lateinit var action: AlertAction + private val textView: TextView + get() = itemView.findViewById(android.R.id.text1) + + init { + itemView.setOnClickListener { + action.callback(dialogInterfaceGetter()) + } + } + + override fun onBind(item: AlertAction) { + action = item + textView.text = item.title + } +} + +private class ActionsRecyclerViewAdapter( + data: List, + private val dialogInterfaceGetter: () -> DialogInterface +) : RecyclerViewAdapter(data) { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AbstractViewHolder = ActionViewHolder( + parent, dialogInterfaceGetter + ) +} + +fun Context.createActionsAlertDialog( + actions: List, + title: Int? = null, + positivePair: Pair? = null, + neutralPair: Pair? = null, + negativePair: Pair? = null, + show: Boolean = true +): AlertDialog { + lateinit var dialogInterface: DialogInterface + + return createRecyclerViewDialog( + title, positivePair, neutralPair, negativePair, show + ) { + ActionsRecyclerViewAdapter( + actions + ) { + dialogInterface + } + }.also { dialogInterface = it } +} diff --git a/android/alerts/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/alerts/recyclerview/RecyclerViewDialog.kt b/android/alerts/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/alerts/recyclerview/RecyclerViewDialog.kt new file mode 100644 index 00000000000..24e53dda218 --- /dev/null +++ b/android/alerts/recyclerview/src/main/kotlin/dev/inmo/micro_utils/android/alerts/recyclerview/RecyclerViewDialog.kt @@ -0,0 +1,43 @@ +package dev.inmo.micro_utils.android.alerts.recyclerview + +import android.app.AlertDialog +import android.content.Context +import android.widget.LinearLayout +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import dev.inmo.micro_utils.android.alerts.common.AlertDialogCallback +import dev.inmo.micro_utils.android.alerts.common.createCustomViewAlertDialogWithResources + +fun Context.createRecyclerViewDialog( + title: Int? = null, + positivePair: Pair? = null, + neutralPair: Pair? = null, + negativePair: Pair? = null, + show: Boolean = true, + layoutManager: RecyclerView.LayoutManager = LinearLayoutManager(this), + marginOfRecyclerView: Int = 8, // dp + recyclerViewSetUp: RecyclerView.() -> Unit = {}, + adapterFactory: () -> RecyclerView.Adapter<*> +): AlertDialog { + val recyclerView = RecyclerView(this).apply { + layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ).apply { + setMargins(marginOfRecyclerView, marginOfRecyclerView, marginOfRecyclerView, marginOfRecyclerView) + } + this.layoutManager = layoutManager + adapter = adapterFactory() + recyclerViewSetUp() + } + + return createCustomViewAlertDialogWithResources( + title, + positivePair, + neutralPair, + negativePair, + show + ) { + recyclerView + } +} diff --git a/android/recyclerview/build.gradle b/android/recyclerview/build.gradle index c130272d88d..e0ca77546ee 100644 --- a/android/recyclerview/build.gradle +++ b/android/recyclerview/build.gradle @@ -2,7 +2,6 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" id "com.android.library" - id "kotlin-android-extensions" } apply from: "$mppAndroidProjectPresetPath" diff --git a/common/build.gradle b/common/build.gradle index 2ab8e52cd06..7c54502f100 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -2,7 +2,6 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" id "com.android.library" - id "kotlin-android-extensions" } apply from: "$mppProjectWithSerializationPresetPath" 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 new file mode 100644 index 00000000000..a05f4360397 --- /dev/null +++ b/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/Annotations.kt @@ -0,0 +1,19 @@ +package dev.inmo.micro_utils.common + +@RequiresOptIn( + "It is possible, that behaviour of this thing will be changed or removed in future releases", + 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 PreviewFeature diff --git a/common/src/main/kotlin/dev/inmo/micro_utils/common/ExpandCollapse.kt b/common/src/main/kotlin/dev/inmo/micro_utils/common/ExpandCollapse.kt new file mode 100644 index 00000000000..4fba2b56349 --- /dev/null +++ b/common/src/main/kotlin/dev/inmo/micro_utils/common/ExpandCollapse.kt @@ -0,0 +1,76 @@ +package dev.inmo.micro_utils.common + +import android.view.View +import android.view.ViewGroup +import android.view.animation.Animation +import android.view.animation.Transformation + +@PreviewFeature +fun View.expand( + duration: Long = 500, + targetWidth: Int = ViewGroup.LayoutParams.MATCH_PARENT, + targetHeight: Int = ViewGroup.LayoutParams.WRAP_CONTENT +) { + measure(targetWidth, targetHeight) + val measuredHeight: Int = measuredHeight + layoutParams.height = 0 + visibility = View.VISIBLE + val a: Animation = object : Animation() { + override fun applyTransformation(interpolatedTime: Float, t: Transformation?) { + super.applyTransformation(interpolatedTime, t) + layoutParams.height = if (interpolatedTime == 1f) targetHeight else (measuredHeight * interpolatedTime).toInt() + requestLayout() + } + + override fun willChangeBounds(): Boolean { + return true + } + } + + a.duration = duration + + startAnimation(a) +} + +@PreviewFeature +fun View.collapse(duration: Long = 500) { + val initialHeight: Int = measuredHeight + val a: Animation = object : Animation() { + override fun applyTransformation(interpolatedTime: Float, t: Transformation?) { + if (interpolatedTime == 1f) { + visibility = View.GONE + } else { + layoutParams.height = initialHeight - (initialHeight * interpolatedTime).toInt() + requestLayout() + } + } + + override fun willChangeBounds(): Boolean { + return true + } + } + + a.duration = duration + + startAnimation(a) +} + +@PreviewFeature +inline val View.isCollapsed + get() = visibility == View.GONE + +@PreviewFeature +inline val View.isExpanded + get() = !isCollapsed + +/** + * @return true in case of expanding + */ +@PreviewFeature +fun View.toggleExpandState(duration: Long = 500): Boolean = if (isCollapsed) { + expand(duration) + true +} else { + collapse(duration) + false +} diff --git a/common/src/main/kotlin/dev/inmo/micro_utils/common/ViewDisable.kt b/common/src/main/kotlin/dev/inmo/micro_utils/common/ViewDisable.kt new file mode 100644 index 00000000000..59c8afe9a7e --- /dev/null +++ b/common/src/main/kotlin/dev/inmo/micro_utils/common/ViewDisable.kt @@ -0,0 +1,34 @@ +@file:Suppress("NOTHING_TO_INLINE", "unused") + +package dev.inmo.micro_utils.common + +import android.view.View +import android.view.ViewGroup + +inline val View.enabled + get() = isEnabled + +inline val View.disabled + get() = !enabled + +fun View.disable() { + if (this is ViewGroup) { + (0 until childCount).forEach { getChildAt(it).disable() } + } + isEnabled = false +} + +fun View.enable() { + if (this is ViewGroup) { + (0 until childCount).forEach { getChildAt(it).enable() } + } + isEnabled = true +} + +fun View.toggleEnabledState(enabled: Boolean) { + if (enabled) { + enable() + } else { + disable() + } +} diff --git a/common/src/main/kotlin/dev/inmo/micro_utils/common/ViewVisibility.kt b/common/src/main/kotlin/dev/inmo/micro_utils/common/ViewVisibility.kt new file mode 100644 index 00000000000..3bdc1f3868a --- /dev/null +++ b/common/src/main/kotlin/dev/inmo/micro_utils/common/ViewVisibility.kt @@ -0,0 +1,35 @@ +@file:Suppress("NOTHING_TO_INLINE", "unused") + +package dev.inmo.micro_utils.common + +import android.view.View + +inline val View.gone + get() = visibility == View.GONE +inline fun View.gone() { + visibility = View.GONE +} + +inline val View.hidden + get() = visibility == View.INVISIBLE +inline fun View.hide() { + visibility = View.INVISIBLE +} + +inline val View.shown + get() = visibility == View.VISIBLE +inline fun View.show() { + visibility = View.VISIBLE +} + +fun View.toggleVisibility(goneOnHide: Boolean = true) { + if (isShown) { + if (goneOnHide) { + gone() + } else { + hide() + } + } else { + show() + } +} diff --git a/coroutines/build.gradle b/coroutines/build.gradle index 19bbfe5aaac..1db1b17ee79 100644 --- a/coroutines/build.gradle +++ b/coroutines/build.gradle @@ -2,7 +2,6 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" id "com.android.library" - id "kotlin-android-extensions" } apply from: "$mppProjectWithSerializationPresetPath" diff --git a/dokka/build.gradle b/dokka/build.gradle index fee10660b29..8c26bdb6884 100644 --- a/dokka/build.gradle +++ b/dokka/build.gradle @@ -2,7 +2,6 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" id "com.android.library" - id "kotlin-android-extensions" id "org.jetbrains.dokka" } diff --git a/gradle.properties b/gradle.properties index 0e57629edc6..7e25e2c12df 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ kotlin.incremental=true kotlin.incremental.js=true android.useAndroidX=true android.enableJetifier=true -org.gradle.jvmargs=-Xmx3072m +org.gradle.jvmargs=-Xmx2048m kotlin_version=1.4.20 kotlin_coroutines_version=1.4.1 @@ -24,6 +24,7 @@ uuidVersion=0.2.2 core_ktx_version=1.3.2 androidx_recycler_version=1.1.0 +appcompat_version=1.2.0 android_minSdkVersion=19 android_compileSdkVersion=30 @@ -40,5 +41,5 @@ dokka_version=1.4.0 # Project data group=dev.inmo -version=0.4.4 -android_code_version=8 +version=0.4.5 +android_code_version=9 diff --git a/ktor/client/build.gradle b/ktor/client/build.gradle index 6983e6f63b4..7b24b0efa3f 100644 --- a/ktor/client/build.gradle +++ b/ktor/client/build.gradle @@ -2,7 +2,6 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" id "com.android.library" - id "kotlin-android-extensions" } apply from: "$mppProjectWithSerializationPresetPath" diff --git a/ktor/common/build.gradle b/ktor/common/build.gradle index 3413a1a4877..64cbbd21ac2 100644 --- a/ktor/common/build.gradle +++ b/ktor/common/build.gradle @@ -2,7 +2,6 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" id "com.android.library" - id "kotlin-android-extensions" } apply from: "$mppProjectWithSerializationPresetPath" diff --git a/mime_types/build.gradle b/mime_types/build.gradle index 2ab8e52cd06..7c54502f100 100644 --- a/mime_types/build.gradle +++ b/mime_types/build.gradle @@ -2,7 +2,6 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" id "com.android.library" - id "kotlin-android-extensions" } apply from: "$mppProjectWithSerializationPresetPath" diff --git a/pagination/common/build.gradle b/pagination/common/build.gradle index 2ab8e52cd06..7c54502f100 100644 --- a/pagination/common/build.gradle +++ b/pagination/common/build.gradle @@ -2,7 +2,6 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" id "com.android.library" - id "kotlin-android-extensions" } apply from: "$mppProjectWithSerializationPresetPath" diff --git a/pagination/ktor/common/build.gradle b/pagination/ktor/common/build.gradle index 18c9967a1ab..9eb226de884 100644 --- a/pagination/ktor/common/build.gradle +++ b/pagination/ktor/common/build.gradle @@ -2,7 +2,6 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" id "com.android.library" - id "kotlin-android-extensions" } apply from: "$mppProjectWithSerializationPresetPath" diff --git a/repos/common/build.gradle b/repos/common/build.gradle index e78548f9238..cd8a5615d26 100644 --- a/repos/common/build.gradle +++ b/repos/common/build.gradle @@ -2,7 +2,6 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" id "com.android.library" - id "kotlin-android-extensions" } apply from: "$mppProjectWithSerializationPresetPath" diff --git a/repos/inmemory/build.gradle b/repos/inmemory/build.gradle index 2e766c6966f..01f0a6f24ea 100644 --- a/repos/inmemory/build.gradle +++ b/repos/inmemory/build.gradle @@ -2,7 +2,6 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" id "com.android.library" - id "kotlin-android-extensions" } apply from: "$mppProjectWithSerializationPresetPath" diff --git a/repos/ktor/client/build.gradle b/repos/ktor/client/build.gradle index 30fea42d54c..9d6e599d90c 100644 --- a/repos/ktor/client/build.gradle +++ b/repos/ktor/client/build.gradle @@ -2,7 +2,6 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" id "com.android.library" - id "kotlin-android-extensions" } apply from: "$mppProjectWithSerializationPresetPath" diff --git a/repos/ktor/common/build.gradle b/repos/ktor/common/build.gradle index 7449b67d2fb..1881ecbcc12 100644 --- a/repos/ktor/common/build.gradle +++ b/repos/ktor/common/build.gradle @@ -2,7 +2,6 @@ plugins { id "org.jetbrains.kotlin.multiplatform" id "org.jetbrains.kotlin.plugin.serialization" id "com.android.library" - id "kotlin-android-extensions" } apply from: "$mppProjectWithSerializationPresetPath" diff --git a/settings.gradle b/settings.gradle index 811699ed9eb..320b82da2da 100644 --- a/settings.gradle +++ b/settings.gradle @@ -18,6 +18,8 @@ String[] includes = [ ":ktor:client", ":coroutines", ":android:recyclerview", + ":android:alerts:common", + ":android:alerts:recyclerview", ":dokka" ]