diff --git a/app/src/main/java/eu/kanade/core/util/CollectionUtils.kt b/app/src/main/java/eu/kanade/core/util/CollectionUtils.kt index 8dab8a054..baf369e39 100644 --- a/app/src/main/java/eu/kanade/core/util/CollectionUtils.kt +++ b/app/src/main/java/eu/kanade/core/util/CollectionUtils.kt @@ -5,7 +5,7 @@ import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract fun List.insertSeparators( - generator: (T?, T?) -> R?, + generator: (before: T?, after: T?) -> R?, ): List { if (isEmpty()) return emptyList() val newList = mutableListOf() @@ -19,6 +19,24 @@ fun List.insertSeparators( return newList } +/** + * Similar to [eu.kanade.core.util.insertSeparators] but iterates from last to first element + */ +fun List.insertSeparatorsReversed( + generator: (before: T?, after: T?) -> R?, +): List { + if (isEmpty()) return emptyList() + val newList = mutableListOf() + for (i in size downTo 0) { + val after = getOrNull(i) + after?.let(newList::add) + val before = getOrNull(i - 1) + val separator = generator.invoke(before, after) + separator?.let(newList::add) + } + return newList.asReversed() +} + fun HashSet.addOrRemove(value: E, shouldAdd: Boolean) { if (shouldAdd) { add(value) diff --git a/app/src/main/java/mihon/feature/upcoming/UpcomingScreenContent.kt b/app/src/main/java/mihon/feature/upcoming/UpcomingScreenContent.kt index 32090f2fa..479d02be6 100644 --- a/app/src/main/java/mihon/feature/upcoming/UpcomingScreenContent.kt +++ b/app/src/main/java/mihon/feature/upcoming/UpcomingScreenContent.kt @@ -25,7 +25,6 @@ import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.relativeDateText import eu.kanade.presentation.util.isTabletUi -import eu.kanade.tachiyomi.util.lang.toLocalDate import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableMap import kotlinx.coroutines.launch @@ -175,12 +174,9 @@ private fun UpcomingScreenSmallImpl( ) } is UpcomingUIModel.Header -> { - val mangaCount = items.filterIsInstance() - .count { it.manga.expectedNextUpdate?.toLocalDate() == item.date } - DateHeading( date = item.date, - mangaCount = mangaCount, + mangaCount = item.mangaCount, ) } } @@ -229,12 +225,9 @@ private fun UpcomingScreenLargeImpl( ) } is UpcomingUIModel.Header -> { - val mangaCount = items.filterIsInstance() - .count { it.manga.expectedNextUpdate?.toLocalDate() == item.date } - DateHeading( date = item.date, - mangaCount = mangaCount, + mangaCount = item.mangaCount, ) } } diff --git a/app/src/main/java/mihon/feature/upcoming/UpcomingScreenModel.kt b/app/src/main/java/mihon/feature/upcoming/UpcomingScreenModel.kt index b404a7f96..e72bb548d 100644 --- a/app/src/main/java/mihon/feature/upcoming/UpcomingScreenModel.kt +++ b/app/src/main/java/mihon/feature/upcoming/UpcomingScreenModel.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.util.fastMap import androidx.compose.ui.util.fastMapIndexedNotNull import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.screenModelScope -import eu.kanade.core.util.insertSeparators +import eu.kanade.core.util.insertSeparatorsReversed import eu.kanade.tachiyomi.util.lang.toLocalDate import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableMap @@ -33,7 +33,7 @@ class UpcomingScreenModel( val upcomingItems = it.toUpcomingUIModels() state.copy( items = upcomingItems, - events = it.toEvents(), + events = upcomingItems.toEvents(), headerIndexes = upcomingItems.getHeaderIndexes(), ) } @@ -42,13 +42,16 @@ class UpcomingScreenModel( } private fun List.toUpcomingUIModels(): ImmutableList { + var mangaCount = 0 return fastMap { UpcomingUIModel.Item(it) } - .insertSeparators { before, after -> + .insertSeparatorsReversed { before, after -> + if (after != null) mangaCount++ + val beforeDate = before?.manga?.expectedNextUpdate?.toLocalDate() val afterDate = after?.manga?.expectedNextUpdate?.toLocalDate() if (beforeDate != afterDate && afterDate != null) { - UpcomingUIModel.Header(afterDate) + UpcomingUIModel.Header(afterDate, mangaCount).also { mangaCount = 0 } } else { null } @@ -56,9 +59,9 @@ class UpcomingScreenModel( .toImmutableList() } - private fun List.toEvents(): ImmutableMap { - return groupBy { it.expectedNextUpdate?.toLocalDate() ?: LocalDate.MAX } - .mapValues { it.value.size } + private fun List.toEvents(): ImmutableMap { + return filterIsInstance() + .associate { it.date to it.mangaCount } .toImmutableMap() } diff --git a/app/src/main/java/mihon/feature/upcoming/UpcomingUIModel.kt b/app/src/main/java/mihon/feature/upcoming/UpcomingUIModel.kt index c394f45f6..758e1686e 100644 --- a/app/src/main/java/mihon/feature/upcoming/UpcomingUIModel.kt +++ b/app/src/main/java/mihon/feature/upcoming/UpcomingUIModel.kt @@ -4,6 +4,6 @@ import tachiyomi.domain.manga.model.Manga import java.time.LocalDate sealed interface UpcomingUIModel { - data class Header(val date: LocalDate) : UpcomingUIModel + data class Header(val date: LocalDate, val mangaCount: Int) : UpcomingUIModel data class Item(val manga: Manga) : UpcomingUIModel }