Skip to content

Commit

Permalink
Apply code review
Browse files Browse the repository at this point in the history
  • Loading branch information
shabnix committed Aug 21, 2024
1 parent 776c7b7 commit 839ad09
Show file tree
Hide file tree
Showing 10 changed files with 46 additions and 79 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.GetChaptersToDownload
import mihon.domain.chapter.interactor.FilterChaptersForDownload
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 { GetChaptersToDownload(get(), get(), get()) }
addFactory { FilterChaptersForDownload(get(), get(), get()) }

addSingletonFactory<HistoryRepository> { HistoryRepositoryImpl(get()) }
addFactory { GetHistory(get()) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ object SettingsDownloadScreen : SearchableSettings {
allCategories: List<Category>,
): Preference.PreferenceGroup {
val downloadNewChaptersPref = downloadPreferences.downloadNewChapters()
val downloadUnreadChaptersOnlyPref = downloadPreferences.downloadUnreadChaptersOnly()
val downloadNewUnreadChaptersOnlyPref = downloadPreferences.downloadNewUnreadChaptersOnly()
val downloadNewChapterCategoriesPref = downloadPreferences.downloadNewChapterCategories()
val downloadNewChapterCategoriesExcludePref = downloadPreferences.downloadNewChapterCategoriesExclude()

Expand Down Expand Up @@ -154,8 +154,8 @@ object SettingsDownloadScreen : SearchableSettings {
title = stringResource(MR.strings.pref_download_new),
),
Preference.PreferenceItem.SwitchPreference(
pref = downloadUnreadChaptersOnlyPref,
title = stringResource(MR.strings.pref_download_unready_chapters_only),
pref = downloadNewUnreadChaptersOnlyPref,
title = stringResource(MR.strings.pref_download_new_unread_chapters_only),
enabled = downloadNewChapters,
),
Preference.PreferenceItem.TextPreference(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import logcat.LogPriority
import mihon.domain.chapter.interactor.GetChaptersToDownload
import mihon.domain.chapter.interactor.FilterChaptersForDownload
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.preference.getAndSet
import tachiyomi.core.common.util.lang.withIOContext
Expand Down Expand Up @@ -84,7 +84,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
private val updateManga: UpdateManga = Injekt.get()
private val syncChaptersWithSource: SyncChaptersWithSource = Injekt.get()
private val fetchInterval: FetchInterval = Injekt.get()
private val getChaptersToDownload: GetChaptersToDownload = Injekt.get()
private val filterChaptersForDownload: FilterChaptersForDownload = Injekt.get()

private val notifier = LibraryUpdateNotifier(context)

Expand Down Expand Up @@ -267,7 +267,17 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
.sortedByDescending { it.sourceOrder }

if (newChapters.isNotEmpty()) {
handleNewChapters(manga, newChapters, newUpdates, hasDownloads)
val chaptersToDownload = filterChaptersForDownload.await(manga, newChapters)

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

libraryPreferences.newUpdatesCount().getAndSet { it + newChapters.size }

// Convert to the manga that contains new chapters
newUpdates.add(manga to newChapters.toTypedArray())
}
} catch (e: Throwable) {
val errorMessage = when (e) {
Expand Down Expand Up @@ -308,32 +318,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
}
}

/**
* Handles new chapters for a specific manga by determining which chapters should be downloaded based on
* user preferences. Updates relevant lists and flags to reflect the processed chapters.
*
* @param manga The manga for which new chapters are being handled.
* @param newChapters A list of new chapters for the manga.
* @param newUpdates A thread-safe list that stores pairs of manga and their respective new chapters.
* @param hasDownloads A flag indicating whether there are any chapters to download.
*/
private suspend fun handleNewChapters(
manga: Manga,
newChapters: List<Chapter>,
newUpdates: CopyOnWriteArrayList<Pair<Manga, Array<Chapter>>>,
hasDownloads: AtomicBoolean
) {
val chaptersToDownload = getChaptersToDownload.await(manga, newChapters)

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

libraryPreferences.newUpdatesCount().getAndSet { it + newChapters.size }
newUpdates.add(manga to newChapters.toTypedArray())
}

private fun downloadChapters(manga: Manga, chapters: List<Chapter>) {
// We don't want to start downloading while the library is updating, because websites
// may don't like it and they could ban the user.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import logcat.LogPriority
import mihon.domain.chapter.interactor.GetChaptersToDownload
import mihon.domain.chapter.interactor.FilterChaptersForDownload
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.preference.CheckboxState
import tachiyomi.core.common.preference.TriState
Expand Down Expand Up @@ -107,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 getChaptersToDownload: GetChaptersToDownload = Injekt.get(),
private val filterChaptersForDownload: FilterChaptersForDownload = Injekt.get(),
val snackbarHostState: SnackbarHostState = SnackbarHostState(),
) : StateScreenModel<MangaScreenModel.State>(State.Loading) {

Expand Down Expand Up @@ -770,7 +770,7 @@ class MangaScreenModel(
private fun downloadNewChapters(chapters: List<Chapter>) {
screenModelScope.launchNonCancellable {
val manga = successState?.manga ?: return@launchNonCancellable
val chaptersToDownload = getChaptersToDownload.await(manga, chapters)
val chaptersToDownload = filterChaptersForDownload.await(manga, chapters)

if (chaptersToDownload.isNotEmpty()) {
downloadChapters(chaptersToDownload)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,6 @@ class ChapterRepositoryImpl(
}
}

override suspend fun getReadChapterCountByMangaIdAndChapterNumber(mangaId: Long, chapterNumber: Double): Long {
return handler.awaitOne {
chaptersQueries.getReadChapterCountByMangaIdAndChapterNumber(mangaId, chapterNumber)
}
}

private fun mapChapter(
id: Long,
mangaId: Long,
Expand Down
9 changes: 1 addition & 8 deletions data/src/main/sqldelight/tachiyomi/data/chapters.sq
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,4 @@ SET manga_id = coalesce(:mangaId, manga_id),
WHERE _id = :chapterId;

selectLastInsertedRowId:
SELECT last_insert_rowid();

getReadChapterCountByMangaIdAndChapterNumber:
SELECT COUNT(*)
FROM chapters
WHERE manga_id = :mangaId
AND chapter_number =:chapterNumber
AND read = 1;
SELECT last_insert_rowid();
Original file line number Diff line number Diff line change
@@ -1,61 +1,59 @@
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.interactor.GetChaptersByMangaId
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 getChaptersByMangaId Interactor for retrieving chapters by manga ID.
* @property downloadPreferences User preferences related to chapter downloads.
* @property getCategories Interactor for retrieving categories associated with a manga.
*/
class GetChaptersToDownload(
private val chapterRepository: ChapterRepository,
class FilterChaptersForDownload(
private val getChaptersByMangaId: GetChaptersByMangaId,
private val downloadPreferences: DownloadPreferences,
private val getCategories: GetCategories,
) {

/**
* Determines chapters that should be downloaded based on user preferences.
* Determines which chapters of a manga 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.
* @return A list of chapters that should be downloaded. If new chapters should not be downloaded,
* returns an empty list.
*/
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) }
val downloadNewUnreadChaptersOnly = downloadPreferences.downloadNewUnreadChaptersOnly().get()
return if (downloadNewUnreadChaptersOnly) {
getUnreadChapters(manga, newChapters)
} else {
newChapters
}
}

/**
* Checks if a chapter is unread based on its manga ID and chapter number.
* Filters out chapters that have already been read.
*
* @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`.
* @param manga The manga whose chapters are being checked.
* @param newChapters The list of new chapters to filter.
* @return A list of unread chapters that are present in `newChapters`.
*/
private suspend fun isUnreadChapter(mangaId: Long, chapterNumber: Double): Boolean {
return try {
chapterRepository.getReadChapterCountByMangaIdAndChapterNumber(mangaId, chapterNumber) == 0L
} catch (e: SQLiteException) {
logcat(LogPriority.ERROR, e)
true
}
private suspend fun getUnreadChapters(manga: Manga, newChapters: List<Chapter>): List<Chapter> {
val dbChapters = getChaptersByMangaId.await(manga.id)
val unreadChapters = dbChapters
.groupBy { it.chapterNumber }
.filterValues { chapters -> chapters.none { it.read } }

return newChapters.filter { it.chapterNumber in unreadChapters }
}

/**
Expand All @@ -77,7 +75,7 @@ class GetChaptersToDownload(
val excludedCategories = downloadPreferences.downloadNewChapterCategoriesExclude().get().map { it.toLong() }

return when {
includedCategories.isEmpty() && excludedCategories.isEmpty() -> true // Default: Download from all categories
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,4 @@ interface ChapterRepository {
suspend fun getChapterByMangaIdAsFlow(mangaId: Long, applyScanlatorFilter: Boolean = false): Flow<List<Chapter>>

suspend fun getChapterByUrlAndMangaId(url: String, mangaId: Long): Chapter?

suspend fun getReadChapterCountByMangaIdAndChapterNumber(mangaId: Long, chapterNumber: Double): Long
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ class DownloadPreferences(
emptySet(),
)

fun downloadUnreadChaptersOnly() = preferenceStore.getBoolean("download_unread_only", true)
fun downloadNewUnreadChaptersOnly() = preferenceStore.getBoolean("download_new_unread_chapters_only", false)
}
2 changes: 1 addition & 1 deletion i18n/src/commonMain/moko-resources/base/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@
<string name="fifth_to_last">Fifth to last read chapter</string>
<string name="pref_category_auto_download">Auto-download</string>
<string name="pref_download_new">Download new chapters</string>
<string name="pref_download_unready_chapters_only">Prevent downloading read chapters</string>
<string name="pref_download_new_unread_chapters_only">Skip downloading read chapters</string>
<string name="pref_download_new_categories_details">Entries in excluded categories will not be downloaded even if they are also in included categories.</string>
<string name="download_ahead">Download ahead</string>
<string name="auto_download_while_reading">Auto download while reading</string>
Expand Down

0 comments on commit 839ad09

Please sign in to comment.