Clean up library download chapters logic

We can probably clean up the same logic in the manga controller at some point too, but that stuff's messy.
Also fixes the spacing issue that the new icon introduced.
This commit is contained in:
arkon 2022-10-30 22:56:07 -04:00
parent 50b17d5d34
commit 33e90d6449
5 changed files with 34 additions and 48 deletions

View File

@ -94,7 +94,7 @@ class DomainModule : InjektModule {
addFactory { GetLibraryManga(get()) } addFactory { GetLibraryManga(get()) }
addFactory { GetMangaWithChapters(get(), get()) } addFactory { GetMangaWithChapters(get(), get()) }
addFactory { GetManga(get()) } addFactory { GetManga(get()) }
addFactory { GetNextUnreadChapters(get(), get(), get(), get()) } addFactory { GetNextUnreadChapters(get(), get(), get()) }
addFactory { ResetViewerFlags(get()) } addFactory { ResetViewerFlags(get()) }
addFactory { SetMangaChapterFlags(get()) } addFactory { SetMangaChapterFlags(get()) }
addFactory { SetMangaDefaultChapterFlags(get(), get(), get()) } addFactory { SetMangaDefaultChapterFlags(get(), get(), get()) }

View File

@ -1,14 +1,13 @@
package eu.kanade.domain.history.interactor package eu.kanade.domain.history.interactor
import eu.kanade.domain.chapter.interactor.GetChapter
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.model.Chapter import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.history.repository.HistoryRepository import eu.kanade.domain.history.repository.HistoryRepository
import eu.kanade.domain.manga.interactor.GetManga import eu.kanade.domain.manga.interactor.GetManga
import eu.kanade.tachiyomi.util.chapter.getChapterSort import eu.kanade.tachiyomi.util.chapter.getChapterSort
import kotlin.math.max
class GetNextUnreadChapters( class GetNextUnreadChapters(
private val getChapter: GetChapter,
private val getChapterByMangaId: GetChapterByMangaId, private val getChapterByMangaId: GetChapterByMangaId,
private val getManga: GetManga, private val getManga: GetManga,
private val historyRepository: HistoryRepository, private val historyRepository: HistoryRepository,
@ -19,15 +18,16 @@ class GetNextUnreadChapters(
return await(history.mangaId, history.chapterId).firstOrNull() return await(history.mangaId, history.chapterId).firstOrNull()
} }
suspend fun await(mangaId: Long, chapterId: Long): List<Chapter> { suspend fun await(mangaId: Long): List<Chapter> {
val chapter = getChapter.await(chapterId) ?: return emptyList()
val manga = getManga.await(mangaId) ?: return emptyList() val manga = getManga.await(mangaId) ?: return emptyList()
return getChapterByMangaId.await(mangaId)
val chapters = getChapterByMangaId.await(mangaId)
.sortedWith(getChapterSort(manga, sortDescending = false)) .sortedWith(getChapterSort(manga, sortDescending = false))
val currChapterIndex = chapters.indexOfFirst { chapter.id == it.id }
return chapters
.subList(currChapterIndex, chapters.size)
.filterNot { it.read } .filterNot { it.read }
} }
suspend fun await(mangaId: Long, fromChapterId: Long): List<Chapter> {
val unreadChapters = await(mangaId)
val currChapterIndex = unreadChapters.indexOfFirst { it.id == fromChapterId }
return unreadChapters.subList(max(0, currChapterIndex), unreadChapters.size)
}
} }

View File

@ -9,7 +9,6 @@ import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.RowScope
@ -174,6 +173,7 @@ private fun RowScope.Button(
toConfirm: Boolean, toConfirm: Boolean,
onLongClick: () -> Unit, onLongClick: () -> Unit,
onClick: () -> Unit, onClick: () -> Unit,
content: (@Composable () -> Unit)? = null,
) { ) {
val animatedWeight by animateFloatAsState(if (toConfirm) 2f else 1f) val animatedWeight by animateFloatAsState(if (toConfirm) 2f else 1f)
Column( Column(
@ -205,6 +205,7 @@ private fun RowScope.Button(
style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelSmall,
) )
} }
content?.invoke()
} }
} }
@ -274,15 +275,14 @@ fun LibraryBottomActionMenu(
) )
} }
if (onDownloadClicked != null) { if (onDownloadClicked != null) {
Box { var downloadExpanded by remember { mutableStateOf(false) }
var downloadExpanded by remember { mutableStateOf(false) } Button(
this@Row.Button( title = stringResource(R.string.action_download),
title = stringResource(R.string.action_download), icon = Icons.Outlined.Download,
icon = Icons.Outlined.Download, toConfirm = confirm[3],
toConfirm = confirm[3], onLongClick = { onLongClickItem(3) },
onLongClick = { onLongClickItem(3) }, onClick = { downloadExpanded = !downloadExpanded },
onClick = { downloadExpanded = !downloadExpanded }, ) {
)
val onDismissRequest = { downloadExpanded = false } val onDismissRequest = { downloadExpanded = false }
DownloadDropdownMenu( DownloadDropdownMenu(
expanded = downloadExpanded, expanded = downloadExpanded,

View File

@ -28,7 +28,6 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.presentation.components.AppStateBanners import eu.kanade.presentation.components.AppStateBanners
import eu.kanade.presentation.components.DownloadDropdownMenu import eu.kanade.presentation.components.DownloadDropdownMenu
import eu.kanade.presentation.components.DropdownMenu
import eu.kanade.presentation.components.OverflowMenu import eu.kanade.presentation.components.OverflowMenu
import eu.kanade.presentation.manga.DownloadAction import eu.kanade.presentation.manga.DownloadAction
import eu.kanade.presentation.theme.active import eu.kanade.presentation.theme.active

View File

@ -17,10 +17,9 @@ import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.domain.category.interactor.GetCategories
import eu.kanade.domain.category.interactor.SetMangaCategories import eu.kanade.domain.category.interactor.SetMangaCategories
import eu.kanade.domain.category.model.Category import eu.kanade.domain.category.model.Category
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.interactor.SetReadStatus import eu.kanade.domain.chapter.interactor.SetReadStatus
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.chapter.model.toDbChapter import eu.kanade.domain.chapter.model.toDbChapter
import eu.kanade.domain.history.interactor.GetNextUnreadChapters
import eu.kanade.domain.library.model.LibraryManga import eu.kanade.domain.library.model.LibraryManga
import eu.kanade.domain.library.model.LibrarySort import eu.kanade.domain.library.model.LibrarySort
import eu.kanade.domain.library.model.sort import eu.kanade.domain.library.model.sort
@ -40,13 +39,11 @@ import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.models.toDomainManga import eu.kanade.tachiyomi.data.database.models.toDomainManga
import eu.kanade.tachiyomi.data.download.DownloadCache import eu.kanade.tachiyomi.data.download.DownloadCache
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.chapter.getChapterSort
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchNonCancellable import eu.kanade.tachiyomi.util.lang.launchNonCancellable
import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.lang.withIOContext
@ -81,7 +78,7 @@ class LibraryPresenter(
private val getLibraryManga: GetLibraryManga = Injekt.get(), private val getLibraryManga: GetLibraryManga = Injekt.get(),
private val getTracksPerManga: GetTracksPerManga = Injekt.get(), private val getTracksPerManga: GetTracksPerManga = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(), private val getCategories: GetCategories = Injekt.get(),
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(), private val getNextUnreadChapters: GetNextUnreadChapters = Injekt.get(),
private val setReadStatus: SetReadStatus = Injekt.get(), private val setReadStatus: SetReadStatus = Injekt.get(),
private val updateManga: UpdateManga = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(),
private val setMangaCategories: SetMangaCategories = Injekt.get(), private val setMangaCategories: SetMangaCategories = Injekt.get(),
@ -404,25 +401,6 @@ class LibraryPresenter(
return mangaCategories.flatten().distinct().subtract(common) return mangaCategories.flatten().distinct().subtract(common)
} }
fun shouldDownloadChapter(manga: Manga, chapter: Chapter): Boolean {
val activeDownload = downloadManager.queue.find { chapter.id == it.chapter.id }
val downloaded = downloadManager.isChapterDownloaded(chapter.name, chapter.scanlator, manga.title, manga.source)
val state = when {
activeDownload != null -> activeDownload.status
downloaded -> Download.State.DOWNLOADED
else -> Download.State.NOT_DOWNLOADED
}
return state == Download.State.NOT_DOWNLOADED
}
suspend fun getNotDownloadedUnreadChapters(manga: Manga): List<Chapter> {
return getChapterByMangaId.await(manga.id)
.filter { chapter ->
!chapter.read && shouldDownloadChapter(manga, chapter)
}
.sortedWith(getChapterSort(manga, sortDescending = false))
}
/** /**
* Queues the amount specified of unread chapters from the list of mangas given. * Queues the amount specified of unread chapters from the list of mangas given.
* *
@ -432,10 +410,19 @@ class LibraryPresenter(
fun downloadUnreadChapters(mangas: List<Manga>, amount: Int?) { fun downloadUnreadChapters(mangas: List<Manga>, amount: Int?) {
presenterScope.launchNonCancellable { presenterScope.launchNonCancellable {
mangas.forEach { manga -> mangas.forEach { manga ->
val chapters = getNotDownloadedUnreadChapters(manga) val chapters = getNextUnreadChapters.await(manga.id)
.filterNot { chapter ->
downloadManager.queue.any { chapter.id == it.chapter.id } ||
downloadManager.isChapterDownloaded(
chapter.name,
chapter.scanlator,
manga.title,
manga.source,
)
}
.let { if (amount != null) it.take(amount) else it } .let { if (amount != null) it.take(amount) else it }
.map { it.toDbChapter() }
downloadManager.downloadChapters(manga, chapters) downloadManager.downloadChapters(manga, chapters.map { it.toDbChapter() })
} }
} }
} }