mirror of
				https://github.com/InsanusMokrassar/MicroUtils.git
				synced 2025-10-29 19:20:26 +00:00 
			
		
		
		
	Compare commits
	
		
			20 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| caf9c821f3 | |||
| ca4c6db96f | |||
| 6b2298c752 | |||
| a1bf43def9 | |||
| 15e9254e00 | |||
| afe5a72c6f | |||
| 750a8b9ecf | |||
| 27fc3f93e0 | |||
| 8166d4b99b | |||
| b61d2ae2eb | |||
| 4790fe0aea | |||
| bc37b11cee | |||
| 223fed910f | |||
| b85ab7b061 | |||
| 888dc299c9 | |||
| e113dc28ed | |||
| 31e55d2307 | |||
| e90645f248 | |||
| 4bb7ba2571 | |||
| 8d31c25bf8 | 
							
								
								
									
										26
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,5 +1,31 @@ | ||||
| # Changelog | ||||
|  | ||||
| ## 0.9.21 | ||||
|  | ||||
| * `Repos`: | ||||
|     * `Exposed`: | ||||
|         * fixes in `AbstractExposedWriteCRUDRepo` | ||||
|  | ||||
| ## 0.9.20 | ||||
|  | ||||
| * `Repos`: | ||||
|     * `Common`: | ||||
|         * Fixes in `OneToManyAndroidRepo` | ||||
|         * New `CursorIterator` | ||||
|  | ||||
| ## 0.9.19 | ||||
|  | ||||
| * `Versions`: | ||||
|     * `Coroutines`: `1.6.0` -> `1.6.1` | ||||
| * `Repos`: | ||||
|     * `Exposed`: | ||||
|         * Fixes in `ExposedStandardVersionsRepoProxy` | ||||
|  | ||||
| ## 0.9.18 | ||||
|  | ||||
| * `Common` | ||||
|     * New extensions for `Element`: `Element#onActionOutside` and `Element#onClickOutside` | ||||
|  | ||||
| ## 0.9.17 | ||||
|  | ||||
| * `Common`: | ||||
|   | ||||
| @@ -51,7 +51,6 @@ class EitherSerializer<T1, T2>( | ||||
|     private val t1EitherSerializer = EitherFirst.serializer(t1Serializer, t2Serializer) | ||||
|     private val t2EitherSerializer = EitherSecond.serializer(t1Serializer, t2Serializer) | ||||
|  | ||||
|     @OptIn(ExperimentalSerializationApi::class, InternalSerializationApi::class) | ||||
|     override fun deserialize(decoder: Decoder): Either<T1, T2> { | ||||
|         return decoder.decodeStructure(descriptor) { | ||||
|             var type: String? = null | ||||
| @@ -83,7 +82,6 @@ class EitherSerializer<T1, T2>( | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @OptIn(ExperimentalSerializationApi::class, InternalSerializationApi::class) | ||||
|     override fun serialize(encoder: Encoder, value: Either<T1, T2>) { | ||||
|         encoder.encodeStructure(descriptor) { | ||||
|             when (value) { | ||||
|   | ||||
| @@ -0,0 +1,38 @@ | ||||
| package dev.inmo.micro_utils.common | ||||
|  | ||||
| import kotlinx.browser.document | ||||
| import org.w3c.dom.* | ||||
| import org.w3c.dom.events.Event | ||||
| import org.w3c.dom.events.EventListener | ||||
|  | ||||
| fun Element.onActionOutside(type: String, options: dynamic = null, callback: (Event) -> Unit): EventListener { | ||||
|     lateinit var observer: MutationObserver | ||||
|     val listener = EventListener { | ||||
|         val elementsToCheck = mutableListOf<Element>(this@onActionOutside) | ||||
|         while (it.target != this@onActionOutside && elementsToCheck.isNotEmpty()) { | ||||
|             val childrenGettingElement = elementsToCheck.removeFirst() | ||||
|             for (i in 0 until childrenGettingElement.childElementCount) { | ||||
|                 elementsToCheck.add(childrenGettingElement.children[i] ?: continue) | ||||
|             } | ||||
|         } | ||||
|         if (elementsToCheck.isEmpty()) { | ||||
|             callback(it) | ||||
|         } | ||||
|     } | ||||
|     if (options == null) { | ||||
|         document.addEventListener(type, listener) | ||||
|     } else { | ||||
|         document.addEventListener(type, listener, options) | ||||
|     } | ||||
|     observer = onRemoved { | ||||
|         if (options == null) { | ||||
|             document.removeEventListener(type, listener) | ||||
|         } else { | ||||
|             document.removeEventListener(type, listener, options) | ||||
|         } | ||||
|         observer.disconnect() | ||||
|     } | ||||
|     return listener | ||||
| } | ||||
|  | ||||
| fun Element.onClickOutside(options: dynamic = null, callback: (Event) -> Unit) = onActionOutside("click", options, callback) | ||||
| @@ -14,5 +14,5 @@ crypto_js_version=4.1.1 | ||||
| # Project data | ||||
|  | ||||
| group=dev.inmo | ||||
| version=0.9.17 | ||||
| android_code_version=107 | ||||
| version=0.9.21 | ||||
| android_code_version=111 | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| kt = "1.6.10" | ||||
| kt-serialization = "1.3.2" | ||||
| kt-coroutines = "1.6.0" | ||||
| kt-coroutines = "1.6.1" | ||||
|  | ||||
| jb-compose = "1.1.1" | ||||
| jb-exposed = "0.37.3" | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import dev.inmo.micro_utils.pagination.* | ||||
|  * Example: | ||||
|  * | ||||
|  * * `|__f__l_______________________|` will be transformed to `|_______________________f__l__|` | ||||
|  * * `|__f__l_|` will be transformed to `|__f__l_|` | ||||
|  * * `|__f__l_|` will be transformed to `|_f__l__|` | ||||
|  * | ||||
|  * @return Reversed version of this [Pagination] | ||||
|  */ | ||||
|   | ||||
| @@ -13,12 +13,12 @@ interface VersionsRepo<T> : Repo { | ||||
|      * By default, instance of this interface will check that version of table with name [tableName] is less than | ||||
|      * [version] or is absent | ||||
|      * | ||||
|      * * In case if [tableName] didn't found, will be called [onCreate] and version of table will be set up to [version] | ||||
|      * * In case if [tableName] have version less than parameter [version], it will increase version one-by-one | ||||
|      * until database version will be equal to [version] | ||||
|      * In case if [tableName] didn't found, will be called [onCreate]. Then in case if [tableName] have version less | ||||
|      * than parameter [version] or null, it will increase version one-by-one until database version will be equal to | ||||
|      * [version] | ||||
|      * | ||||
|      * @param version Current version of table | ||||
|      * @param onCreate This callback will be called in case when table have no information about table | ||||
|      * @param onCreate This callback will be called in case when repo have no information about table | ||||
|      * @param onUpdate This callback will be called after **iterative** changing of version. It is expected that parameter | ||||
|      * "to" will always be greater than "from" | ||||
|      */ | ||||
|   | ||||
| @@ -0,0 +1,27 @@ | ||||
| package dev.inmo.micro_utils.repos | ||||
|  | ||||
| import android.database.Cursor | ||||
|  | ||||
| class CursorIterator( | ||||
|     private val c: Cursor | ||||
| ) : Iterator<Cursor> { | ||||
|     private var i = 0 | ||||
|  | ||||
|     init { | ||||
|         c.moveToFirst() | ||||
|     } | ||||
|     override fun hasNext(): Boolean { | ||||
|         return i < c.count | ||||
|     } | ||||
|  | ||||
|     override fun next(): Cursor { | ||||
|         i++ | ||||
|         return if (c.moveToNext()) { | ||||
|             c | ||||
|         } else { | ||||
|             throw NoSuchElementException() | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| operator fun Cursor.iterator(): CursorIterator = CursorIterator(this) | ||||
| @@ -143,7 +143,12 @@ class OneToManyAndroidRepo<Key, Value>( | ||||
|     }.toLong() | ||||
|  | ||||
|     override suspend fun count(k: Key): Long = helper.blockingReadableTransaction { | ||||
|         selectDistinct(tableName, columns = valueColumnArray, selection = "$idColumnName=?", selectionArgs = arrayOf(k.keyAsString()), limit = FirstPagePagination(1).limitClause()).use { | ||||
|         selectDistinct( | ||||
|             tableName, | ||||
|             columns = valueColumnArray, | ||||
|             selection = "$idColumnName=?", | ||||
|             selectionArgs = arrayOf(k.keyAsString()) | ||||
|         ).use { | ||||
|             it.count | ||||
|         } | ||||
|     }.toLong() | ||||
|   | ||||
| @@ -17,13 +17,19 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>( | ||||
|     ExposedCRUDRepo<ObjectType, IdType>, | ||||
|     WriteStandardCRUDRepo<ObjectType, IdType, InputValueType> | ||||
| { | ||||
|     protected val newObjectsChannel = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize) | ||||
|     protected val updateObjectsChannel = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize) | ||||
|     protected val deleteObjectsIdsChannel = MutableSharedFlow<IdType>(replyCacheInFlows, flowsChannelsSize) | ||||
|     protected val _newObjectsFlow = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize) | ||||
|     protected val _updatedObjectsFlow = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize) | ||||
|     protected val _deletedObjectsIdsFlow = MutableSharedFlow<IdType>(replyCacheInFlows, flowsChannelsSize) | ||||
|     @Deprecated("Renamed", ReplaceWith("_newObjectsFlow")) | ||||
|     protected val newObjectsChannel = _newObjectsFlow | ||||
|     @Deprecated("Renamed", ReplaceWith("_updatedObjectsFlow")) | ||||
|     protected val updateObjectsChannel = _updatedObjectsFlow | ||||
|     @Deprecated("Renamed", ReplaceWith("_deletedObjectsIdsFlow")) | ||||
|     protected val deleteObjectsIdsChannel = _deletedObjectsIdsFlow | ||||
|  | ||||
|     override val newObjectsFlow: Flow<ObjectType> = newObjectsChannel.asSharedFlow() | ||||
|     override val updatedObjectsFlow: Flow<ObjectType> = updateObjectsChannel.asSharedFlow() | ||||
|     override val deletedObjectsIdsFlow: Flow<IdType> = deleteObjectsIdsChannel.asSharedFlow() | ||||
|     override val newObjectsFlow: Flow<ObjectType> = _newObjectsFlow.asSharedFlow() | ||||
|     override val updatedObjectsFlow: Flow<ObjectType> = _updatedObjectsFlow.asSharedFlow() | ||||
|     override val deletedObjectsIdsFlow: Flow<IdType> = _deletedObjectsIdsFlow.asSharedFlow() | ||||
|  | ||||
|     protected abstract fun InsertStatement<Number>.asObject(value: InputValueType): ObjectType | ||||
|     abstract val selectByIds: SqlExpressionBuilder.(List<IdType>) -> Op<Boolean> | ||||
| @@ -43,7 +49,7 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>( | ||||
|         return transaction(db = database) { | ||||
|             values.map { value -> createWithoutNotification(value) } | ||||
|         }.onEach { | ||||
|             newObjectsChannel.emit(it) | ||||
|             _newObjectsFlow.emit(it) | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -74,7 +80,7 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>( | ||||
|         onBeforeUpdate(listOf(id to value)) | ||||
|         return updateWithoutNotification(id, value).also { | ||||
|             if (it != null) { | ||||
|                 updateObjectsChannel.emit(it) | ||||
|                 _updatedObjectsFlow.emit(it) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -85,16 +91,25 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>( | ||||
|                 values.map { (id, value) -> updateWithoutNotification(id, value) } | ||||
|             }.filterNotNull() | ||||
|         ).onEach { | ||||
|             updateObjectsChannel.emit(it) | ||||
|             _updatedObjectsFlow.emit(it) | ||||
|         } | ||||
|     } | ||||
|     protected open suspend fun onBeforeDelete(ids: List<IdType>) {} | ||||
|     override suspend fun deleteById(ids: List<IdType>) { | ||||
|         onBeforeDelete(ids) | ||||
|         transaction(db = database) { | ||||
|             deleteWhere(null, null) { | ||||
|             val deleted = deleteWhere(null, null) { | ||||
|                 selectByIds(ids) | ||||
|             } | ||||
|             if (deleted == ids.size) { | ||||
|                 ids | ||||
|             } else { | ||||
|                 ids.filter { | ||||
|                     select { selectById(it) }.limit(1).none() | ||||
|                 } | ||||
|             } | ||||
|         }.forEach { | ||||
|             _deletedObjectsIdsFlow.emit(it) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -19,7 +19,7 @@ class ExposedStandardVersionsRepoProxy( | ||||
|     override val database: Database | ||||
| ) : StandardVersionsRepoProxy<Database>, Table("ExposedVersionsProxy"), ExposedRepo { | ||||
|     val tableNameColumn = text("tableName") | ||||
|     val tableVersionColumn = integer("tableName") | ||||
|     val tableVersionColumn = integer("tableVersion") | ||||
|  | ||||
|     init { | ||||
|         initTable() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user