Skip to content

Commit

Permalink
Group download chapter logic inside the interactor GetChaptersToDownload
Browse files Browse the repository at this point in the history
  • Loading branch information
shabnix committed Aug 20, 2024
1 parent 5f31e4f commit 35bede5
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 113 deletions.
4 changes: 2 additions & 2 deletions app/src/main/java/eu/kanade/domain/DomainModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import eu.kanade.domain.track.interactor.RefreshTracks
import eu.kanade.domain.track.interactor.SyncChapterProgressWithTrack
import eu.kanade.domain.track.interactor.TrackChapter
import mihon.data.repository.ExtensionRepoRepositoryImpl
import mihon.domain.chapter.interactor.GetReadChapterCountByMangaIdAndChapterNumber
import mihon.domain.chapter.interactor.GetChaptersToDownload
import mihon.domain.extensionrepo.interactor.CreateExtensionRepo
import mihon.domain.extensionrepo.interactor.DeleteExtensionRepo
import mihon.domain.extensionrepo.interactor.GetExtensionRepo
Expand Down Expand Up @@ -153,7 +153,7 @@ class DomainModule : InjektModule {
addFactory { ShouldUpdateDbChapter() }
addFactory { SyncChaptersWithSource(get(), get(), get(), get(), get(), get(), get(), get()) }
addFactory { GetAvailableScanlators(get()) }
addFactory { GetReadChapterCountByMangaIdAndChapterNumber(get()) }
addFactory { GetChaptersToDownload(get(), get(), get()) }

addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
addFactory { GetHistory(get()) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.UpdateStrategy
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
import eu.kanade.tachiyomi.util.system.isConnectedToWifi
Expand All @@ -39,17 +38,14 @@ import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import logcat.LogPriority
import mihon.core.chapters.utils.filterChaptersToDownload
import mihon.domain.chapter.interactor.GetReadChapterCountByMangaIdAndChapterNumber
import mihon.domain.chapter.interactor.GetChaptersToDownload
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.preference.getAndSet
import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.category.model.Category
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.chapter.model.NoChaptersException
import tachiyomi.domain.download.service.DownloadPreferences
import tachiyomi.domain.library.model.LibraryManga
import tachiyomi.domain.library.service.LibraryPreferences
import tachiyomi.domain.library.service.LibraryPreferences.Companion.DEVICE_CHARGING
Expand Down Expand Up @@ -80,17 +76,15 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
CoroutineWorker(context, workerParams) {

private val sourceManager: SourceManager = Injekt.get()
private val downloadPreferences: DownloadPreferences = Injekt.get()
private val libraryPreferences: LibraryPreferences = Injekt.get()
private val downloadManager: DownloadManager = Injekt.get()
private val coverCache: CoverCache = Injekt.get()
private val getLibraryManga: GetLibraryManga = Injekt.get()
private val getManga: GetManga = Injekt.get()
private val updateManga: UpdateManga = Injekt.get()
private val getCategories: GetCategories = Injekt.get()
private val syncChaptersWithSource: SyncChaptersWithSource = Injekt.get()
private val fetchInterval: FetchInterval = Injekt.get()
private val getReadChapterCount: GetReadChapterCountByMangaIdAndChapterNumber = Injekt.get()
private val getChaptersToDownload: GetChaptersToDownload = Injekt.get()

private val notifier = LibraryUpdateNotifier(context)

Expand Down Expand Up @@ -330,16 +324,11 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
newUpdates: CopyOnWriteArrayList<Pair<Manga, Array<Chapter>>>,
hasDownloads: AtomicBoolean
) {
val categoryIds = getCategories.await(manga.id).map { it.id }
val chaptersToDownload = getChaptersToDownload.await(manga, newChapters)

if (manga.shouldDownloadNewChapters(categoryIds, downloadPreferences)) {
val chaptersToDownload = newChapters
.filterChaptersToDownload(manga, getReadChapterCount, downloadPreferences)

if (chaptersToDownload.isNotEmpty()) {
downloadChapters(manga, chaptersToDownload)
hasDownloads.set(true)
}
if (chaptersToDownload.isNotEmpty()) {
downloadChapters(manga, chaptersToDownload)
hasDownloads.set(true)
}

libraryPreferences.newUpdatesCount().getAndSet { it + newChapters.size }
Expand Down
21 changes: 6 additions & 15 deletions app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.util.chapter.getNextUnread
import eu.kanade.tachiyomi.util.removeCovers
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.async
Expand All @@ -48,8 +47,7 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import logcat.LogPriority
import mihon.core.chapters.utils.filterChaptersToDownload
import mihon.domain.chapter.interactor.GetReadChapterCountByMangaIdAndChapterNumber
import mihon.domain.chapter.interactor.GetChaptersToDownload
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.preference.CheckboxState
import tachiyomi.core.common.preference.TriState
Expand All @@ -69,7 +67,6 @@ import tachiyomi.domain.chapter.model.ChapterUpdate
import tachiyomi.domain.chapter.model.NoChaptersException
import tachiyomi.domain.chapter.service.calculateChapterGap
import tachiyomi.domain.chapter.service.getChapterSort
import tachiyomi.domain.download.service.DownloadPreferences
import tachiyomi.domain.library.service.LibraryPreferences
import tachiyomi.domain.manga.interactor.GetDuplicateLibraryManga
import tachiyomi.domain.manga.interactor.GetMangaWithChapters
Expand All @@ -89,7 +86,6 @@ class MangaScreenModel(
val context: Context,
val mangaId: Long,
private val isFromSource: Boolean,
private val downloadPreferences: DownloadPreferences = Injekt.get(),
private val libraryPreferences: LibraryPreferences = Injekt.get(),
readerPreferences: ReaderPreferences = Injekt.get(),
private val trackerManager: TrackerManager = Injekt.get(),
Expand All @@ -111,7 +107,7 @@ class MangaScreenModel(
private val addTracks: AddTracks = Injekt.get(),
private val setMangaCategories: SetMangaCategories = Injekt.get(),
private val mangaRepository: MangaRepository = Injekt.get(),
private val getReadChapterCount: GetReadChapterCountByMangaIdAndChapterNumber = Injekt.get(),
private val getChaptersToDownload: GetChaptersToDownload = Injekt.get(),
val snackbarHostState: SnackbarHostState = SnackbarHostState(),
) : StateScreenModel<MangaScreenModel.State>(State.Loading) {

Expand Down Expand Up @@ -774,16 +770,11 @@ class MangaScreenModel(
private fun downloadNewChapters(chapters: List<Chapter>) {
screenModelScope.launchNonCancellable {
val manga = successState?.manga ?: return@launchNonCancellable
val categories = getCategories.await(manga.id).map { it.id }
if (
chapters.isEmpty() ||
!manga.shouldDownloadNewChapters(categories, downloadPreferences)
) {
return@launchNonCancellable
}
val chaptersToDownload = getChaptersToDownload.await(manga, chapters)

val chaptersToDownload = chapters.filterChaptersToDownload(manga, getReadChapterCount, downloadPreferences)
downloadChapters(chaptersToDownload)
if (chaptersToDownload.isNotEmpty()) {
downloadChapters(chaptersToDownload)
}
}
}

Expand Down
26 changes: 0 additions & 26 deletions app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import eu.kanade.domain.manga.model.hasCustomCover
import eu.kanade.domain.manga.model.toSManga
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.source.model.SManga
import tachiyomi.domain.download.service.DownloadPreferences
import tachiyomi.domain.manga.model.Manga
import tachiyomi.source.local.image.LocalCoverManager
import tachiyomi.source.local.isLocal
Expand Down Expand Up @@ -50,31 +49,6 @@ fun Manga.removeCovers(coverCache: CoverCache = Injekt.get()): Manga {
}
}

fun Manga.shouldDownloadNewChapters(dbCategories: List<Long>, preferences: DownloadPreferences): Boolean {
if (!favorite) return false

val categories = dbCategories.ifEmpty { listOf(0L) }

// Boolean to determine if user wants to automatically download new chapters.
val downloadNewChapters = preferences.downloadNewChapters().get()
if (!downloadNewChapters) return false

val includedCategories = preferences.downloadNewChapterCategories().get().map { it.toLong() }
val excludedCategories = preferences.downloadNewChapterCategoriesExclude().get().map { it.toLong() }

// Default: Download from all categories
if (includedCategories.isEmpty() && excludedCategories.isEmpty()) return true

// In excluded category
if (categories.any { it in excludedCategories }) return false

// Included category not selected
if (includedCategories.isEmpty()) return true

// In included category
return categories.any { it in includedCategories }
}

suspend fun Manga.editCover(
coverManager: LocalCoverManager,
stream: InputStream,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package mihon.domain.chapter.interactor

import android.database.sqlite.SQLiteException
import logcat.LogPriority
import tachiyomi.core.common.util.system.logcat
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.chapter.repository.ChapterRepository
import tachiyomi.domain.download.service.DownloadPreferences
import tachiyomi.domain.manga.model.Manga

/**
* Interactor responsible for determining which chapters of a manga should be downloaded.
*
* @property chapterRepository The repository for accessing chapter data.
* @property downloadPreferences User preferences related to chapter downloads.
* @property getCategories Interactor for retrieving categories associated with a manga.
*/
class GetChaptersToDownload(
private val chapterRepository: ChapterRepository,
private val downloadPreferences: DownloadPreferences,
private val getCategories: GetCategories,
) {

/**
* Determines chapters that should be downloaded based on user preferences.
*
* @param manga The manga for which chapters may be downloaded.
* @param newChapters The list of new chapters available for the manga.
* @return A list of chapters that should be downloaded.
*/
suspend fun await(manga: Manga, newChapters: List<Chapter>): List<Chapter> {
if (!shouldDownloadNewChapters(manga)) {
return emptyList()
}

val downloadUnreadChapters = downloadPreferences.downloadUnreadChaptersOnly().get()
return if (downloadUnreadChapters) {
newChapters.filter { isUnreadChapter(manga.id, it.chapterNumber) }
} else {
newChapters
}
}

/**
* Checks if a chapter is unread based on its manga ID and chapter number.
*
* @param mangaId The ID of the manga to which the chapter belongs.
* @param chapterNumber The number of the chapter.
* @return `true` if the chapter is unread; otherwise `false`.
*/
private suspend fun isUnreadChapter(mangaId: Long, chapterNumber: Double): Boolean {
return try {
chapterRepository.getReadChapterCountByMangaIdAndChapterNumber(mangaId, chapterNumber) == 0L
} catch (e: SQLiteException) {
logcat(LogPriority.ERROR, e)
true
}
}

/**
* Determines whether new chapters should be downloaded for the manga based on user preferences and the
* categories to which the manga belongs.
*
* @param manga The manga to check for download eligibility.
* @return `true` if new chapters should be downloaded; otherwise `false`.
*/
private suspend fun shouldDownloadNewChapters(manga: Manga): Boolean {
if (!manga.favorite) return false

// Boolean to determine if user wants to automatically download new chapters.
val downloadNewChapters = downloadPreferences.downloadNewChapters().get()
if (!downloadNewChapters) return false

val categories = getCategories.await(manga.id).map { it.id }.ifEmpty { listOf(DEFAULT_CATEGORY_ID) }
val includedCategories = downloadPreferences.downloadNewChapterCategories().get().map { it.toLong() }
val excludedCategories = downloadPreferences.downloadNewChapterCategoriesExclude().get().map { it.toLong() }

return when {
includedCategories.isEmpty() && excludedCategories.isEmpty() -> true // Default: Download from all categories
categories.any { it in excludedCategories } -> false // In excluded category
includedCategories.isEmpty() -> true // Included category not selected
else -> categories.any { it in includedCategories } // In included category
}
}

companion object {
private const val DEFAULT_CATEGORY_ID = 0L
}
}

This file was deleted.

0 comments on commit 35bede5

Please sign in to comment.