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 index d7a1de7ba48..2fab342c66c 100644 --- 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 @@ -35,9 +35,9 @@ class ActionViewHolder( } class ActionsRecyclerViewAdapter( - data: List, + override val data: List, private val dialogInterfaceGetter: () -> DialogInterface -) : RecyclerViewAdapter(data) { +) : RecyclerViewAdapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AbstractViewHolder = ActionViewHolder( parent, dialogInterfaceGetter ) 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 index 96d1020fff6..a5dc0e93450 100644 --- 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 @@ -1,12 +1,13 @@ package dev.inmo.micro_utils.android.recyclerview import android.view.View +import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView -abstract class RecyclerViewAdapter( - val data: List -): RecyclerView.Adapter>() { +abstract class RecyclerViewAdapter: RecyclerView.Adapter>() { + protected abstract val data: List + var emptyView: View? = null set(value) { field = value @@ -66,3 +67,11 @@ abstract class RecyclerViewAdapter( } } } + +fun RecyclerViewAdapter( + data: List, + onCreateViewHolder: (parent: ViewGroup, viewType: Int) -> AbstractViewHolder +) = object : RecyclerViewAdapter() { + override val data: List = data + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AbstractViewHolder = onCreateViewHolder(parent, viewType) +} 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 index 3bdc1f3868a..5c842f98883 100644 --- a/common/src/main/kotlin/dev/inmo/micro_utils/common/ViewVisibility.kt +++ b/common/src/main/kotlin/dev/inmo/micro_utils/common/ViewVisibility.kt @@ -33,3 +33,15 @@ fun View.toggleVisibility(goneOnHide: Boolean = true) { show() } } + +fun View.changeVisibility(show: Boolean = !isShown, goneOnHide: Boolean = true) { + if (show) { + if (goneOnHide) { + gone() + } else { + hide() + } + } else { + show() + } +} 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 001c618851b..df5bafa86d5 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 @@ -1,6 +1,7 @@ package dev.inmo.micro_utils.repos import dev.inmo.micro_utils.pagination.* +import dev.inmo.micro_utils.pagination.utils.doForAllWithCurrentPaging import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging import kotlinx.coroutines.flow.Flow @@ -47,6 +48,7 @@ interface WriteOneToManyKeyValueRepo : Repo { suspend fun remove(toRemove: Map>) suspend fun clear(k: Key) + suspend fun clearWithValue(v: Value) suspend fun set(toSet: Map>) { toSet.keys.forEach { key -> clear(key) } @@ -87,7 +89,19 @@ suspend inline fun WriteOneToManyKeyValueRepo.set( k: Key, vararg v: Value ) = set(k, v.toList()) -interface OneToManyKeyValueRepo : ReadOneToManyKeyValueRepo, WriteOneToManyKeyValueRepo +interface OneToManyKeyValueRepo : ReadOneToManyKeyValueRepo, WriteOneToManyKeyValueRepo { + override suspend fun clearWithValue(v: Value) { + doWithPagination { + val keysResult = keys(v, it) + + if (keysResult.results.isNotEmpty()) { + remove(keysResult.results.map { it to listOf(v) }) + } + + keysResult.currentPageIfNotEmpty() + } + } +} typealias KeyValuesRepo = OneToManyKeyValueRepo suspend inline fun WriteOneToManyKeyValueRepo.remove( diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/mappers/OneToManyKeyValueMappers.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/mappers/OneToManyKeyValueMappers.kt index dd777d15088..97b872a7b1c 100644 --- a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/mappers/OneToManyKeyValueMappers.kt +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/mappers/OneToManyKeyValueMappers.kt @@ -114,6 +114,7 @@ open class MapperWriteOneToManyKeyValueRepo( } override suspend fun clear(k: FromKey) = to.clear(k.toOutKey()) + override suspend fun clearWithValue(v: FromValue) = to.clearWithValue(v.toOutValue()) } @Suppress("NOTHING_TO_INLINE") diff --git a/repos/common/src/main/kotlin/dev/inmo/micro_utils/repos/DatabaseOperations.kt b/repos/common/src/main/kotlin/dev/inmo/micro_utils/repos/DatabaseOperations.kt index 35b04fa0c4b..d473afd0255 100644 --- a/repos/common/src/main/kotlin/dev/inmo/micro_utils/repos/DatabaseOperations.kt +++ b/repos/common/src/main/kotlin/dev/inmo/micro_utils/repos/DatabaseOperations.kt @@ -74,6 +74,19 @@ fun SQLiteDatabase.select( table, columns, selection, selectionArgs, groupBy, having, orderBy, limit ) +fun SQLiteDatabase.selectDistinct( + table: String, + columns: Array? = null, + selection: String? = null, + selectionArgs: Array? = null, + groupBy: String? = null, + having: String? = null, + orderBy: String? = null, + limit: String? = null +) = query( + true, table, columns, selection, selectionArgs, groupBy, having, orderBy, limit +) + fun makePlaceholders(count: Int): String { return (0 until count).joinToString { "?" } } diff --git a/repos/common/src/main/kotlin/dev/inmo/micro_utils/repos/onetomany/OneToManyAndroidRepo.kt b/repos/common/src/main/kotlin/dev/inmo/micro_utils/repos/onetomany/OneToManyAndroidRepo.kt index eeda9af65af..31c7be0ac99 100644 --- a/repos/common/src/main/kotlin/dev/inmo/micro_utils/repos/onetomany/OneToManyAndroidRepo.kt +++ b/repos/common/src/main/kotlin/dev/inmo/micro_utils/repos/onetomany/OneToManyAndroidRepo.kt @@ -35,7 +35,9 @@ class OneToManyAndroidRepo( override val onDataCleared: Flow = _onDataCleared.asSharedFlow() private val idColumnName = "id" + private val idColumnArray = arrayOf(idColumnName) private val valueColumnName = "value" + private val valueColumnArray = arrayOf(valueColumnName) init { helper.blockingWritableTransaction { @@ -105,7 +107,7 @@ class OneToManyAndroidRepo( } override suspend fun contains(k: Key): Boolean = helper.blockingReadableTransaction { - select(tableName, selection = "$idColumnName=?", selectionArgs = arrayOf(k.keyAsString()), limit = FirstPagePagination(1).limitClause()).use { + select(tableName, selection = "$idColumnName=?", selectionArgs = arrayOf(k.keyAsString()), limit = firstPageWithOneElementPagination.limitClause()).use { it.count > 0 } } @@ -121,7 +123,7 @@ class OneToManyAndroidRepo( } } - override suspend fun count(): Long =helper.blockingReadableTransaction { + override suspend fun count(): Long = helper.blockingReadableTransaction { select( tableName ).use { @@ -130,7 +132,7 @@ class OneToManyAndroidRepo( }.toLong() override suspend fun count(k: Key): Long = helper.blockingReadableTransaction { - select(tableName, selection = "$idColumnName=?", selectionArgs = arrayOf(k.keyAsString()), limit = FirstPagePagination(1).limitClause()).use { + selectDistinct(tableName, columns = valueColumnArray, selection = "$idColumnName=?", selectionArgs = arrayOf(k.keyAsString()), limit = FirstPagePagination(1).limitClause()).use { it.count } }.toLong() @@ -150,6 +152,7 @@ class OneToManyAndroidRepo( helper.blockingReadableTransaction { select( tableName, + valueColumnArray, selection = "$idColumnName=?", selectionArgs = arrayOf(k.keyAsString()), limit = resultPagination.limitClause() @@ -180,8 +183,9 @@ class OneToManyAndroidRepo( } val resultPagination = pagination.let { if (reversed) pagination.reverse(count) else pagination } helper.blockingReadableTransaction { - select( + selectDistinct( tableName, + idColumnArray, limit = resultPagination.limitClause() ).use { c -> mutableListOf().also { @@ -205,8 +209,9 @@ class OneToManyAndroidRepo( ): PaginationResult = count().let { count -> val resultPagination = pagination.let { if (reversed) pagination.reverse(count) else pagination } helper.blockingReadableTransaction { - select( + selectDistinct( tableName, + idColumnArray, selection = "$valueColumnName=?", selectionArgs = arrayOf(v.valueAsString()), limit = resultPagination.limitClause() diff --git a/repos/inmemory/src/commonMain/kotlin/dev/inmo/micro_utils/repos/MapOneToManyKeyValueRepo.kt b/repos/inmemory/src/commonMain/kotlin/dev/inmo/micro_utils/repos/MapOneToManyKeyValueRepo.kt index 48bc9c697e0..08ebbb45f90 100644 --- a/repos/inmemory/src/commonMain/kotlin/dev/inmo/micro_utils/repos/MapOneToManyKeyValueRepo.kt +++ b/repos/inmemory/src/commonMain/kotlin/dev/inmo/micro_utils/repos/MapOneToManyKeyValueRepo.kt @@ -86,6 +86,12 @@ class MapWriteOneToManyKeyValueRepo( override suspend fun clear(k: Key) { map.remove(k) ?.also { _onDataCleared.emit(k) } } + + override suspend fun clearWithValue(v: Value) { + map.forEach { (k, values) -> + if (values.remove(v)) _onValueRemoved.emit(k to v) + } + } } class MapOneToManyKeyValueRepo( diff --git a/repos/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/repos/ktor/client/one_to_many/KtorWriteOneToManyKeyValueRepo.kt b/repos/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/repos/ktor/client/one_to_many/KtorWriteOneToManyKeyValueRepo.kt index 5263c53f83c..1a2122d25d7 100644 --- a/repos/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/repos/ktor/client/one_to_many/KtorWriteOneToManyKeyValueRepo.kt +++ b/repos/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/repos/ktor/client/one_to_many/KtorWriteOneToManyKeyValueRepo.kt @@ -67,6 +67,15 @@ class KtorWriteOneToManyKeyValueRepo ( Unit.serializer(), ) + override suspend fun clearWithValue(v: Value) = unifiedRequester.unipost( + buildStandardUrl( + baseUrl, + clearWithValueRoute, + ), + BodyPair(valueSerializer, v), + Unit.serializer(), + ) + override suspend fun set(toSet: Map>) = unifiedRequester.unipost( buildStandardUrl( baseUrl, @@ -75,4 +84,4 @@ class KtorWriteOneToManyKeyValueRepo ( BodyPair(keyValueMapSerializer, toSet), Unit.serializer(), ) -} \ No newline at end of file +} diff --git a/repos/ktor/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/ktor/common/one_to_many/OneToManyRoutes.kt b/repos/ktor/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/ktor/common/one_to_many/OneToManyRoutes.kt index c1a2df1eac1..b10a45476ff 100644 --- a/repos/ktor/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/ktor/common/one_to_many/OneToManyRoutes.kt +++ b/repos/ktor/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/ktor/common/one_to_many/OneToManyRoutes.kt @@ -14,4 +14,5 @@ const val onDataClearedRoute = "onDataCleared" const val addRoute = "add" const val removeRoute = "remove" const val clearRoute = "clear" -const val setRoute = "set" \ No newline at end of file +const val clearWithValueRoute = "clearWithValue" +const val setRoute = "set" diff --git a/repos/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/ktor/server/one_to_many/ConfigureOneToManyWriteKeyValueRepoRoutes.kt b/repos/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/ktor/server/one_to_many/ConfigureOneToManyWriteKeyValueRepoRoutes.kt index c9039bb87cb..2ef6ee6c450 100644 --- a/repos/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/ktor/server/one_to_many/ConfigureOneToManyWriteKeyValueRepoRoutes.kt +++ b/repos/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/repos/ktor/server/one_to_many/ConfigureOneToManyWriteKeyValueRepoRoutes.kt @@ -72,6 +72,17 @@ fun Route.configureOneToManyWriteKeyValueRepoRoutes( } } + post(clearWithValueRoute) { + unifiedRouter.apply { + val v = uniload(valueSerializer) + + unianswer( + Unit.serializer(), + originalRepo.clearWithValue(v), + ) + } + } + post(setRoute) { unifiedRouter.apply { val obj = uniload(keyValueMapSerializer)