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