mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-11-22 16:23:50 +00:00
commit
fa8a5bcd97
11
CHANGELOG.md
11
CHANGELOG.md
@ -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`:
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
@ -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,
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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> {
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user