Move to ScreenModel Antsy style

This commit is contained in:
AntsyLich 2024-10-12 08:06:32 +06:00
parent 6e5d498ea5
commit 1a1621c99d
No known key found for this signature in database
4 changed files with 32 additions and 18 deletions

View File

@ -5,7 +5,7 @@ import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract import kotlin.contracts.contract
fun <T : R, R : Any> List<T>.insertSeparators( fun <T : R, R : Any> List<T>.insertSeparators(
generator: (T?, T?) -> R?, generator: (before: T?, after: T?) -> R?,
): List<R> { ): List<R> {
if (isEmpty()) return emptyList() if (isEmpty()) return emptyList()
val newList = mutableListOf<R>() val newList = mutableListOf<R>()
@ -19,6 +19,24 @@ fun <T : R, R : Any> List<T>.insertSeparators(
return newList return newList
} }
/**
* Similar to [eu.kanade.core.util.insertSeparators] but iterates from last to first element
*/
fun <T : R, R : Any> List<T>.insertSeparatorsReversed(
generator: (before: T?, after: T?) -> R?,
): List<R> {
if (isEmpty()) return emptyList()
val newList = mutableListOf<R>()
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 <E> HashSet<E>.addOrRemove(value: E, shouldAdd: Boolean) { fun <E> HashSet<E>.addOrRemove(value: E, shouldAdd: Boolean) {
if (shouldAdd) { if (shouldAdd) {
add(value) add(value)

View File

@ -25,7 +25,6 @@ import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.relativeDateText import eu.kanade.presentation.components.relativeDateText
import eu.kanade.presentation.util.isTabletUi import eu.kanade.presentation.util.isTabletUi
import eu.kanade.tachiyomi.util.lang.toLocalDate
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.ImmutableMap
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -175,12 +174,9 @@ private fun UpcomingScreenSmallImpl(
) )
} }
is UpcomingUIModel.Header -> { is UpcomingUIModel.Header -> {
val mangaCount = items.filterIsInstance<UpcomingUIModel.Item>()
.count { it.manga.expectedNextUpdate?.toLocalDate() == item.date }
DateHeading( DateHeading(
date = item.date, date = item.date,
mangaCount = mangaCount, mangaCount = item.mangaCount,
) )
} }
} }
@ -229,12 +225,9 @@ private fun UpcomingScreenLargeImpl(
) )
} }
is UpcomingUIModel.Header -> { is UpcomingUIModel.Header -> {
val mangaCount = items.filterIsInstance<UpcomingUIModel.Item>()
.count { it.manga.expectedNextUpdate?.toLocalDate() == item.date }
DateHeading( DateHeading(
date = item.date, date = item.date,
mangaCount = mangaCount, mangaCount = item.mangaCount,
) )
} }
} }

View File

@ -4,7 +4,7 @@ import androidx.compose.ui.util.fastMap
import androidx.compose.ui.util.fastMapIndexedNotNull import androidx.compose.ui.util.fastMapIndexedNotNull
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.screenModelScope 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 eu.kanade.tachiyomi.util.lang.toLocalDate
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.ImmutableMap
@ -33,7 +33,7 @@ class UpcomingScreenModel(
val upcomingItems = it.toUpcomingUIModels() val upcomingItems = it.toUpcomingUIModels()
state.copy( state.copy(
items = upcomingItems, items = upcomingItems,
events = it.toEvents(), events = upcomingItems.toEvents(),
headerIndexes = upcomingItems.getHeaderIndexes(), headerIndexes = upcomingItems.getHeaderIndexes(),
) )
} }
@ -42,13 +42,16 @@ class UpcomingScreenModel(
} }
private fun List<Manga>.toUpcomingUIModels(): ImmutableList<UpcomingUIModel> { private fun List<Manga>.toUpcomingUIModels(): ImmutableList<UpcomingUIModel> {
var mangaCount = 0
return fastMap { UpcomingUIModel.Item(it) } return fastMap { UpcomingUIModel.Item(it) }
.insertSeparators { before, after -> .insertSeparatorsReversed { before, after ->
if (after != null) mangaCount++
val beforeDate = before?.manga?.expectedNextUpdate?.toLocalDate() val beforeDate = before?.manga?.expectedNextUpdate?.toLocalDate()
val afterDate = after?.manga?.expectedNextUpdate?.toLocalDate() val afterDate = after?.manga?.expectedNextUpdate?.toLocalDate()
if (beforeDate != afterDate && afterDate != null) { if (beforeDate != afterDate && afterDate != null) {
UpcomingUIModel.Header(afterDate) UpcomingUIModel.Header(afterDate, mangaCount).also { mangaCount = 0 }
} else { } else {
null null
} }
@ -56,9 +59,9 @@ class UpcomingScreenModel(
.toImmutableList() .toImmutableList()
} }
private fun List<Manga>.toEvents(): ImmutableMap<LocalDate, Int> { private fun List<UpcomingUIModel>.toEvents(): ImmutableMap<LocalDate, Int> {
return groupBy { it.expectedNextUpdate?.toLocalDate() ?: LocalDate.MAX } return filterIsInstance<UpcomingUIModel.Header>()
.mapValues { it.value.size } .associate { it.date to it.mangaCount }
.toImmutableMap() .toImmutableMap()
} }

View File

@ -4,6 +4,6 @@ import tachiyomi.domain.manga.model.Manga
import java.time.LocalDate import java.time.LocalDate
sealed interface UpcomingUIModel { 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 data class Item(val manga: Manga) : UpcomingUIModel
} }