Merge pull request #453 from InsanusMokrassar/0.20.51

0.20.51
This commit is contained in:
InsanusMokrassar 2024-05-26 23:53:46 +06:00 committed by GitHub
commit fa8a5bcd97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 165 additions and 42 deletions

View File

@ -1,5 +1,16 @@
# Changelog # Changelog
## 0.20.51
* `Versions`:
* `Android Fragment`: `1.7.0` -> `1.7.1`
* `Pagination`:
* Add `Pagination.nextPageIfTrue` and `Pagination.thisPageIftrue` extensions to get the page according to condition
pass status
* Add `PaginationResult.nextPageIfNotEmptyOrLastPage` and `PaginationResult.thisPageIfNotEmptyOrLastPage`
* Change all `doForAll` and `getAll` extensions fo pagination to work basing on `nextPageIfNotEmptyOrLastPage` and
`thisPageIfNotEmptyOrLastPage`
## 0.20.50 ## 0.20.50
* `Versions`: * `Versions`:

View File

@ -15,5 +15,5 @@ crypto_js_version=4.1.1
# Project data # Project data
group=dev.inmo group=dev.inmo
version=0.20.50 version=0.20.51
android_code_version=256 android_code_version=257

View File

@ -26,13 +26,13 @@ kotlin-poet = "1.16.0"
versions = "0.51.0" versions = "0.51.0"
android-gradle = "8.3.2" android-gradle = "8.2.0"
dexcount = "4.0.0" dexcount = "4.0.0"
android-coreKtx = "1.13.1" android-coreKtx = "1.13.1"
android-recyclerView = "1.3.2" android-recyclerView = "1.3.2"
android-appCompat = "1.6.1" android-appCompat = "1.6.1"
android-fragment = "1.7.0" android-fragment = "1.7.1"
android-espresso = "3.5.1" android-espresso = "3.5.1"
android-test = "1.1.5" android-test = "1.1.5"
android-compose-material3 = "1.2.1" android-compose-material3 = "1.2.1"

View File

@ -20,7 +20,13 @@ data class PaginationResult<T>(
* Amount of pages for current pagination * Amount of pages for current pagination
*/ */
@EncodeDefault @EncodeDefault
val pagesNumber: Int = ceil(objectsNumber / size.toFloat()).toInt() @SerialName("pagesNumber")
val pagesNumberLong: Long = ceil(objectsNumber / size.toFloat()).toLong()
/**
* Amount of pages for current pagination
*/
@Transient
val pagesNumber: Int = pagesNumberLong.toInt()
constructor( constructor(
page: Int, page: Int,
@ -35,31 +41,58 @@ data class PaginationResult<T>(
) )
} }
fun <T> emptyPaginationResult() = PaginationResult<T>(0, 0, emptyList(), 0L) val PaginationResult<*>.lastPageLong
get() = pagesNumberLong - 1
val PaginationResult<*>.lastPage
get() = lastPageLong.toInt()
val PaginationResult<*>.isLastPage
get() = page.toLong() == lastPageLong
fun <T> emptyPaginationResult( fun <T> emptyPaginationResult(
basePagination: Pagination basePagination: Pagination,
objectsNumber: Number
) = PaginationResult<T>( ) = PaginationResult<T>(
basePagination.page, basePagination.page,
basePagination.size, basePagination.size,
emptyList(), emptyList(),
0L objectsNumber.toLong()
) )
fun <T> emptyPaginationResult(
basePagination: Pagination,
) = emptyPaginationResult<T>(basePagination, 0)
fun <T> emptyPaginationResult() = emptyPaginationResult<T>(FirstPagePagination(0))
/**
* @return New [PaginationResult] with [data] without checking of data sizes equality
*/
inline fun <I, O> PaginationResult<I>.changeResultsUnchecked(
block: PaginationResult<I>.() -> List<O>
): PaginationResult<O> = PaginationResult(page, size, block(), objectsNumber)
/** /**
* @return New [PaginationResult] with [data] without checking of data sizes equality * @return New [PaginationResult] with [data] without checking of data sizes equality
*/ */
fun <I, O> PaginationResult<I>.changeResultsUnchecked( fun <I, O> PaginationResult<I>.changeResultsUnchecked(
data: List<O> data: List<O>
): PaginationResult<O> = PaginationResult(page, size, data, objectsNumber) ): PaginationResult<O> = changeResultsUnchecked { data }
/**
* @return New [PaginationResult] with [data] <b>with</b> checking of data sizes equality
*/
inline fun <I, O> PaginationResult<I>.changeResults(
block: PaginationResult<I>.() -> List<O>
): PaginationResult<O> {
val data = block()
require(data.size == results.size)
return changeResultsUnchecked(data)
}
/** /**
* @return New [PaginationResult] with [data] <b>with</b> checking of data sizes equality * @return New [PaginationResult] with [data] <b>with</b> checking of data sizes equality
*/ */
fun <I, O> PaginationResult<I>.changeResults( fun <I, O> PaginationResult<I>.changeResults(
data: List<O> data: List<O>
): PaginationResult<O> { ): PaginationResult<O> = changeResults { data }
require(data.size == results.size)
return changeResultsUnchecked(data)
}
fun <T> List<T>.createPaginationResult( fun <T> List<T>.createPaginationResult(
pagination: Pagination, pagination: Pagination,

View File

@ -10,8 +10,7 @@ inline fun doWithPagination(
} }
} }
@Suppress("NOTHING_TO_INLINE") inline fun <T, PR: PaginationResult<T>> PR.nextPageIfTrue(condition: PR.() -> Boolean) = if (condition()) {
inline fun PaginationResult<*>.nextPageIfNotEmpty() = if (results.isNotEmpty()) {
SimplePagination( SimplePagination(
page + 1, page + 1,
size size
@ -20,12 +19,28 @@ inline fun PaginationResult<*>.nextPageIfNotEmpty() = if (results.isNotEmpty())
null null
} }
@Suppress("NOTHING_TO_INLINE") inline fun <T, PR: PaginationResult<T>> PR.thisPageIfTrue(condition: PR.() -> Boolean): PR? = if (condition()) {
inline fun <T> PaginationResult<T>.thisPageIfNotEmpty(): PaginationResult<T>? = if (results.isNotEmpty()) {
this this
} else { } else {
null null
} }
@Suppress("NOTHING_TO_INLINE") fun PaginationResult<*>.nextPageIfNotEmpty() = nextPageIfTrue { results.isNotEmpty() }
inline fun <T> PaginationResult<T>.currentPageIfNotEmpty() = thisPageIfNotEmpty()
fun <T> PaginationResult<T>.thisPageIfNotEmpty(): PaginationResult<T>? = thisPageIfTrue { results.isNotEmpty() }
fun <T> PaginationResult<T>.currentPageIfNotEmpty() = thisPageIfNotEmpty()
fun PaginationResult<*>.nextPageIfNotEmptyOrLastPage() = nextPageIfTrue { results.isNotEmpty() && !this.isLastPage }
fun <T> PaginationResult<T>.thisPageIfNotEmptyOrLastPage(): PaginationResult<T>? = thisPageIfTrue { results.isNotEmpty() && !this.isLastPage }
fun <T> PaginationResult<T>.currentPageIfNotEmptyOrLastPage() = thisPageIfNotEmptyOrLastPage()
fun PaginationResult<*>.nextPageIfNotLastPage() = nextPageIfTrue { !this.isLastPage }
fun <T> PaginationResult<T>.thisPageIfNotLastPage(): PaginationResult<T>? = thisPageIfTrue { !this.isLastPage }
fun <T> PaginationResult<T>.currentPageIfNotLastPage() = thisPageIfNotLastPage()

View File

@ -18,7 +18,7 @@ inline fun <T> doForAllWithNextPaging(
) { ) {
doForAll( doForAll(
initialPagination, initialPagination,
{ it.nextPageIfNotEmpty() }, { it.nextPageIfNotEmptyOrLastPage() },
block block
) )
} }
@ -29,7 +29,7 @@ inline fun <T> doAllWithCurrentPaging(
) { ) {
doForAll( doForAll(
initialPagination, initialPagination,
{ it.currentPageIfNotEmpty() }, { it.nextPageIfNotEmptyOrLastPage() },
block block
) )
} }

View File

@ -31,7 +31,7 @@ inline fun <T> getAllWithNextPaging(
block: (Pagination) -> PaginationResult<T> block: (Pagination) -> PaginationResult<T>
): List<T> = getAll( ): List<T> = getAll(
initialPagination, initialPagination,
{ it.nextPageIfNotEmpty() }, { it.nextPageIfNotEmptyOrLastPage() },
block block
) )
@ -48,7 +48,7 @@ inline fun <T> getAllWithCurrentPaging(
block: (Pagination) -> PaginationResult<T> block: (Pagination) -> PaginationResult<T>
): List<T> = getAll( ): List<T> = getAll(
initialPagination, initialPagination,
{ it.currentPageIfNotEmpty() }, { it.thisPageIfNotEmptyOrLastPage() },
block block
) )

View File

@ -21,33 +21,25 @@ fun <T> Iterable<T>.paginate(with: Pagination): PaginationResult<T> {
} }
fun <T> List<T>.paginate(with: Pagination): PaginationResult<T> { fun <T> List<T>.paginate(with: Pagination): PaginationResult<T> {
val firstIndex = maxOf(with.firstIndex, 0) if (with.firstIndex >= size || with.lastIndex < 0) {
val lastIndex = minOf(with.lastIndexExclusive, size) return emptyPaginationResult(with, size.toLong())
if (firstIndex > lastIndex) {
return emptyPaginationResult()
} }
return subList(firstIndex, lastIndex).createPaginationResult( return asSequence().drop(with.firstIndex).take(with.size).toList().createPaginationResult(
with, with,
size.toLong() size.toLong()
) )
} }
fun <T> List<T>.paginate(with: Pagination, reversed: Boolean): PaginationResult<T> { fun <T> List<T>.paginate(with: Pagination, reversed: Boolean): PaginationResult<T> {
val actualPagination = with.optionallyReverse( return if (reversed) {
size, val actualPagination = with.optionallyReverse(
reversed size,
) reversed
)
val firstIndex = maxOf(actualPagination.firstIndex, 0) paginate(actualPagination).changeResultsUnchecked { results.reversed() }
val lastIndex = minOf(actualPagination.lastIndexExclusive, size) } else {
if (firstIndex > lastIndex) { paginate(with)
return emptyPaginationResult()
} }
return subList(firstIndex, lastIndex).optionallyReverse(reversed).createPaginationResult(
with,
size.toLong()
)
} }
fun <T> Set<T>.paginate(with: Pagination): PaginationResult<T> { fun <T> Set<T>.paginate(with: Pagination): PaginationResult<T> {

View File

@ -0,0 +1,72 @@
package dev.inmo.micro_utils.pagination.utils
import dev.inmo.micro_utils.pagination.*
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class PaginationPaging {
@Test
fun testPaginateOnList() {
val list = (0 until 7).toList()
val startPagination = FirstPagePagination(2)
var lastPageHappened = false
doForAllWithNextPaging(startPagination) {
val result = list.paginate(it)
if (result.isLastPage) {
lastPageHappened = true
assertTrue(result.results.size == 1)
}
val testSublist = list.subList(it.firstIndex, minOf(it.lastIndexExclusive, list.size))
assertEquals(result.results, testSublist)
result
}
assertTrue(lastPageHappened)
}
@Test
fun testEmptyPaginateOnList() {
val list = listOf<Int>()
val startPagination = FirstPagePagination(2)
var paginationHappend = false
doForAllWithNextPaging(startPagination) {
val resultPagination = list.paginate(it)
assertEquals(resultPagination, emptyPaginationResult(it, list.size))
assertFalse(paginationHappend)
paginationHappend = true
resultPagination
}
assertTrue(paginationHappend)
}
@Test
fun testRightOutPaginateOnList() {
val list = (0 until 7).toList()
val startPagination = SimplePagination(page = 4, size = 2)
var paginationHappend = false
doForAllWithNextPaging(startPagination) {
val resultPagination = list.paginate(it)
assertEquals(resultPagination, emptyPaginationResult(it, list.size))
assertFalse(paginationHappend)
paginationHappend = true
resultPagination
}
assertTrue(paginationHappend)
}
}