parent
c1ac207809
commit
8a74faa4f0
@ -0,0 +1,42 @@
|
||||
package org.koitharu.kotatsu.favourites.domain
|
||||
|
||||
import dagger.Reusable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
import org.koitharu.kotatsu.core.db.entity.toManga
|
||||
import org.koitharu.kotatsu.core.db.entity.toMangaTags
|
||||
import org.koitharu.kotatsu.favourites.data.FavouriteManga
|
||||
import org.koitharu.kotatsu.list.domain.ListFilterOption
|
||||
import org.koitharu.kotatsu.list.domain.ListSortOrder
|
||||
import org.koitharu.kotatsu.local.data.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.local.domain.LocalObserveMapper
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import javax.inject.Inject
|
||||
|
||||
@Reusable
|
||||
class LocalFavoritesObserver @Inject constructor(
|
||||
localMangaRepository: LocalMangaRepository,
|
||||
private val db: MangaDatabase,
|
||||
) : LocalObserveMapper<FavouriteManga, Manga>(localMangaRepository, limitStep = 10) {
|
||||
|
||||
fun observeAll(
|
||||
order: ListSortOrder,
|
||||
filterOptions: Set<ListFilterOption>,
|
||||
limit: Int
|
||||
): Flow<List<Manga>> = observe(limit) { newLimit ->
|
||||
db.getFavouritesDao().observeAll(order, filterOptions, newLimit)
|
||||
}
|
||||
|
||||
fun observeAll(
|
||||
categoryId: Long,
|
||||
order: ListSortOrder,
|
||||
filterOptions: Set<ListFilterOption>,
|
||||
limit: Int
|
||||
): Flow<List<Manga>> = observe(limit) { newLimit ->
|
||||
db.getFavouritesDao().observeAll(categoryId, order, filterOptions, newLimit)
|
||||
}
|
||||
|
||||
override fun toManga(e: FavouriteManga) = e.manga.toManga(e.tags.toMangaTags())
|
||||
|
||||
override fun toResult(e: FavouriteManga, manga: Manga) = manga
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package org.koitharu.kotatsu.history.data
|
||||
|
||||
import dagger.Reusable
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
import org.koitharu.kotatsu.core.db.entity.toManga
|
||||
import org.koitharu.kotatsu.core.db.entity.toMangaTags
|
||||
import org.koitharu.kotatsu.history.domain.model.MangaWithHistory
|
||||
import org.koitharu.kotatsu.list.domain.ListFilterOption
|
||||
import org.koitharu.kotatsu.list.domain.ListSortOrder
|
||||
import org.koitharu.kotatsu.local.data.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.local.domain.LocalObserveMapper
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import javax.inject.Inject
|
||||
|
||||
@Reusable
|
||||
class HistoryLocalObserver @Inject constructor(
|
||||
localMangaRepository: LocalMangaRepository,
|
||||
private val db: MangaDatabase,
|
||||
) : LocalObserveMapper<HistoryWithManga, MangaWithHistory>(localMangaRepository, limitStep = 10) {
|
||||
|
||||
fun observeAll(
|
||||
order: ListSortOrder,
|
||||
filterOptions: Set<ListFilterOption>,
|
||||
limit: Int
|
||||
) = observe(limit) { newLimit ->
|
||||
db.getHistoryDao().observeAll(order, filterOptions, newLimit)
|
||||
}
|
||||
|
||||
override fun toManga(e: HistoryWithManga) = e.manga.toManga(e.tags.toMangaTags())
|
||||
|
||||
override fun toResult(e: HistoryWithManga, manga: Manga) = MangaWithHistory(
|
||||
manga = manga,
|
||||
history = e.history.toMangaHistory(),
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package org.koitharu.kotatsu.local.domain
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
import org.koitharu.kotatsu.core.model.isLocal
|
||||
import org.koitharu.kotatsu.local.data.LocalMangaRepository
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
|
||||
abstract class LocalObserveMapper<E, R>(
|
||||
private val localMangaRepository: LocalMangaRepository,
|
||||
private val limitStep: Int,
|
||||
) {
|
||||
|
||||
protected fun observe(limit: Int, observer: (limit: Int) -> Flow<List<E>>): Flow<List<R>> {
|
||||
val floatingLimit = MutableStateFlow(limit)
|
||||
return floatingLimit.flatMapLatest { l ->
|
||||
observer(l)
|
||||
.transformLatest { fullList ->
|
||||
val mapped = fullList.mapToLocal()
|
||||
if (mapped.size < limit && fullList.size == l) {
|
||||
floatingLimit.value += limitStep
|
||||
} else {
|
||||
emit(mapped.take(limit))
|
||||
}
|
||||
}.distinctUntilChanged()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun List<E>.mapToLocal(): List<R> = coroutineScope {
|
||||
val dispatcher = Dispatchers.IO.limitedParallelism(6)
|
||||
map {
|
||||
async(dispatcher) {
|
||||
val m = toManga(it)
|
||||
val mapped = if (m.isLocal) {
|
||||
m
|
||||
} else {
|
||||
localMangaRepository.findSavedManga(m)?.manga
|
||||
}
|
||||
mapped?.let { mm -> toResult(it, mm) }
|
||||
}
|
||||
}.awaitAll().filterNotNull()
|
||||
}
|
||||
|
||||
protected abstract fun toManga(e: E): Manga
|
||||
|
||||
protected abstract fun toResult(e: E, manga: Manga): R
|
||||
}
|
||||
Loading…
Reference in New Issue