diff --git a/CHANGELOG.md b/CHANGELOG.md index d5deb599ed8..bb99a5d0e5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # 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 * `Versions`: diff --git a/gradle.properties b/gradle.properties index d41c4edf0a1..3ba75f5b0ec 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,5 +15,5 @@ crypto_js_version=4.1.1 # Project data group=dev.inmo -version=0.20.50 -android_code_version=256 +version=0.20.51 +android_code_version=257 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c28a0158cd1..84313b0b175 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -26,13 +26,13 @@ kotlin-poet = "1.16.0" versions = "0.51.0" -android-gradle = "8.3.2" +android-gradle = "8.2.0" dexcount = "4.0.0" android-coreKtx = "1.13.1" android-recyclerView = "1.3.2" android-appCompat = "1.6.1" -android-fragment = "1.7.0" +android-fragment = "1.7.1" android-espresso = "3.5.1" android-test = "1.1.5" android-compose-material3 = "1.2.1" diff --git a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/PaginationResult.kt b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/PaginationResult.kt index 9c88e91c53a..217fff6006d 100644 --- a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/PaginationResult.kt +++ b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/PaginationResult.kt @@ -20,7 +20,13 @@ data class PaginationResult( * Amount of pages for current pagination */ @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( page: Int, @@ -35,31 +41,58 @@ data class PaginationResult( ) } -fun emptyPaginationResult() = PaginationResult(0, 0, emptyList(), 0L) +val PaginationResult<*>.lastPageLong + get() = pagesNumberLong - 1 + +val PaginationResult<*>.lastPage + get() = lastPageLong.toInt() + +val PaginationResult<*>.isLastPage + get() = page.toLong() == lastPageLong + fun emptyPaginationResult( - basePagination: Pagination + basePagination: Pagination, + objectsNumber: Number ) = PaginationResult( basePagination.page, basePagination.size, emptyList(), - 0L + objectsNumber.toLong() ) +fun emptyPaginationResult( + basePagination: Pagination, +) = emptyPaginationResult(basePagination, 0) +fun emptyPaginationResult() = emptyPaginationResult(FirstPagePagination(0)) + +/** + * @return New [PaginationResult] with [data] without checking of data sizes equality + */ +inline fun PaginationResult.changeResultsUnchecked( + block: PaginationResult.() -> List +): PaginationResult = PaginationResult(page, size, block(), objectsNumber) /** * @return New [PaginationResult] with [data] without checking of data sizes equality */ fun PaginationResult.changeResultsUnchecked( data: List -): PaginationResult = PaginationResult(page, size, data, objectsNumber) +): PaginationResult = changeResultsUnchecked { data } +/** + * @return New [PaginationResult] with [data] with checking of data sizes equality + */ +inline fun PaginationResult.changeResults( + block: PaginationResult.() -> List +): PaginationResult { + val data = block() + require(data.size == results.size) + return changeResultsUnchecked(data) +} /** * @return New [PaginationResult] with [data] with checking of data sizes equality */ fun PaginationResult.changeResults( data: List -): PaginationResult { - require(data.size == results.size) - return changeResultsUnchecked(data) -} +): PaginationResult = changeResults { data } fun List.createPaginationResult( pagination: Pagination, diff --git a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/WalkPagination.kt b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/WalkPagination.kt index e46baf20d68..2c39ff4588a 100644 --- a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/WalkPagination.kt +++ b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/WalkPagination.kt @@ -10,8 +10,7 @@ inline fun doWithPagination( } } -@Suppress("NOTHING_TO_INLINE") -inline fun PaginationResult<*>.nextPageIfNotEmpty() = if (results.isNotEmpty()) { +inline fun > PR.nextPageIfTrue(condition: PR.() -> Boolean) = if (condition()) { SimplePagination( page + 1, size @@ -20,12 +19,28 @@ inline fun PaginationResult<*>.nextPageIfNotEmpty() = if (results.isNotEmpty()) null } -@Suppress("NOTHING_TO_INLINE") -inline fun PaginationResult.thisPageIfNotEmpty(): PaginationResult? = if (results.isNotEmpty()) { +inline fun > PR.thisPageIfTrue(condition: PR.() -> Boolean): PR? = if (condition()) { this } else { null } -@Suppress("NOTHING_TO_INLINE") -inline fun PaginationResult.currentPageIfNotEmpty() = thisPageIfNotEmpty() +fun PaginationResult<*>.nextPageIfNotEmpty() = nextPageIfTrue { results.isNotEmpty() } + +fun PaginationResult.thisPageIfNotEmpty(): PaginationResult? = thisPageIfTrue { results.isNotEmpty() } + +fun PaginationResult.currentPageIfNotEmpty() = thisPageIfNotEmpty() + + +fun PaginationResult<*>.nextPageIfNotEmptyOrLastPage() = nextPageIfTrue { results.isNotEmpty() && !this.isLastPage } + +fun PaginationResult.thisPageIfNotEmptyOrLastPage(): PaginationResult? = thisPageIfTrue { results.isNotEmpty() && !this.isLastPage } + +fun PaginationResult.currentPageIfNotEmptyOrLastPage() = thisPageIfNotEmptyOrLastPage() + + +fun PaginationResult<*>.nextPageIfNotLastPage() = nextPageIfTrue { !this.isLastPage } + +fun PaginationResult.thisPageIfNotLastPage(): PaginationResult? = thisPageIfTrue { !this.isLastPage } + +fun PaginationResult.currentPageIfNotLastPage() = thisPageIfNotLastPage() diff --git a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/DoForAll.kt b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/DoForAll.kt index 63e8cb38eba..7bdb926e406 100644 --- a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/DoForAll.kt +++ b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/DoForAll.kt @@ -18,7 +18,7 @@ inline fun doForAllWithNextPaging( ) { doForAll( initialPagination, - { it.nextPageIfNotEmpty() }, + { it.nextPageIfNotEmptyOrLastPage() }, block ) } @@ -29,7 +29,7 @@ inline fun doAllWithCurrentPaging( ) { doForAll( initialPagination, - { it.currentPageIfNotEmpty() }, + { it.nextPageIfNotEmptyOrLastPage() }, block ) } diff --git a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/GetAll.kt b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/GetAll.kt index da50a9528e2..50ef92769c7 100644 --- a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/GetAll.kt +++ b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/GetAll.kt @@ -31,7 +31,7 @@ inline fun getAllWithNextPaging( block: (Pagination) -> PaginationResult ): List = getAll( initialPagination, - { it.nextPageIfNotEmpty() }, + { it.nextPageIfNotEmptyOrLastPage() }, block ) @@ -48,7 +48,7 @@ inline fun getAllWithCurrentPaging( block: (Pagination) -> PaginationResult ): List = getAll( initialPagination, - { it.currentPageIfNotEmpty() }, + { it.thisPageIfNotEmptyOrLastPage() }, block ) diff --git a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/Paginate.kt b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/Paginate.kt index 6414e4aa01d..3c11e0667b2 100644 --- a/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/Paginate.kt +++ b/pagination/common/src/commonMain/kotlin/dev/inmo/micro_utils/pagination/utils/Paginate.kt @@ -21,33 +21,25 @@ fun Iterable.paginate(with: Pagination): PaginationResult { } fun List.paginate(with: Pagination): PaginationResult { - val firstIndex = maxOf(with.firstIndex, 0) - val lastIndex = minOf(with.lastIndexExclusive, size) - if (firstIndex > lastIndex) { - return emptyPaginationResult() + if (with.firstIndex >= size || with.lastIndex < 0) { + return emptyPaginationResult(with, size.toLong()) } - return subList(firstIndex, lastIndex).createPaginationResult( + return asSequence().drop(with.firstIndex).take(with.size).toList().createPaginationResult( with, size.toLong() ) } fun List.paginate(with: Pagination, reversed: Boolean): PaginationResult { - val actualPagination = with.optionallyReverse( - size, - reversed - ) - - val firstIndex = maxOf(actualPagination.firstIndex, 0) - val lastIndex = minOf(actualPagination.lastIndexExclusive, size) - if (firstIndex > lastIndex) { - return emptyPaginationResult() + return if (reversed) { + val actualPagination = with.optionallyReverse( + size, + reversed + ) + paginate(actualPagination).changeResultsUnchecked { results.reversed() } + } else { + paginate(with) } - - return subList(firstIndex, lastIndex).optionallyReverse(reversed).createPaginationResult( - with, - size.toLong() - ) } fun Set.paginate(with: Pagination): PaginationResult { diff --git a/pagination/common/src/commonTest/kotlin/dev/inmo/micro_utils/pagination/utils/PaginationPaging.kt b/pagination/common/src/commonTest/kotlin/dev/inmo/micro_utils/pagination/utils/PaginationPaging.kt new file mode 100644 index 00000000000..0767b755e81 --- /dev/null +++ b/pagination/common/src/commonTest/kotlin/dev/inmo/micro_utils/pagination/utils/PaginationPaging.kt @@ -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() + 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) + } +}