Starting shift to 1.x sources

This commit is contained in:
Jays2Kings 2021-03-21 13:30:11 -04:00
parent 7963a607b8
commit 73df525939
11 changed files with 137 additions and 102 deletions

View File

@ -24,8 +24,9 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
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.fetchMangaDetailsAsync
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toMangaInfo
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.storage.getUriCompat
@ -92,10 +93,10 @@ class LibraryUpdateService(
// List containing categories that get included in downloads. // List containing categories that get included in downloads.
private val categoriesToDownload = private val categoriesToDownload =
preferences.downloadNewCategories().getOrDefault().map(String::toInt) preferences.downloadNewCategories().get().map(String::toInt)
// Boolean to determine if user wants to automatically download new chapters. // Boolean to determine if user wants to automatically download new chapters.
private val downloadNew: Boolean = preferences.downloadNew().getOrDefault() private val downloadNew: Boolean = preferences.downloadNew().get()
// Boolean to determine if DownloadManager has downloads // Boolean to determine if DownloadManager has downloads
private var hasDownloads = false private var hasDownloads = false
@ -198,7 +199,7 @@ class LibraryUpdateService(
db.getLibraryMangas().executeAsBlocking().filter { it.category == categoryId } db.getLibraryMangas().executeAsBlocking().filter { it.category == categoryId }
} else { } else {
val categoriesToUpdate = val categoriesToUpdate =
preferences.libraryUpdateCategories().getOrDefault().map(String::toInt) preferences.libraryUpdateCategories().get().map(String::toInt)
if (categoriesToUpdate.isNotEmpty()) { if (categoriesToUpdate.isNotEmpty()) {
categoryIds.addAll(categoriesToUpdate) categoryIds.addAll(categoriesToUpdate)
db.getLibraryMangas().executeAsBlocking() db.getLibraryMangas().executeAsBlocking()
@ -451,7 +452,7 @@ class LibraryUpdateService(
) )
val networkManga = try { val networkManga = try {
source.fetchMangaDetailsAsync(manga) source.getMangaDetails(manga.toMangaInfo()).toSManga()
} catch (e: java.lang.Exception) { } catch (e: java.lang.Exception) {
Timber.e(e) Timber.e(e)
null null

View File

@ -174,7 +174,7 @@ class PreferencesHelper(val context: Context) {
fun libraryUpdateRestriction() = prefs.getStringSet(Keys.libraryUpdateRestriction, emptySet()) fun libraryUpdateRestriction() = prefs.getStringSet(Keys.libraryUpdateRestriction, emptySet())
fun libraryUpdateCategories() = rxPrefs.getStringSet(Keys.libraryUpdateCategories, emptySet()) fun libraryUpdateCategories() = flowPrefs.getStringSet(Keys.libraryUpdateCategories, emptySet())
fun libraryUpdatePrioritization() = rxPrefs.getInteger(Keys.libraryUpdatePrioritization, 0) fun libraryUpdatePrioritization() = rxPrefs.getInteger(Keys.libraryUpdatePrioritization, 0)
@ -212,9 +212,9 @@ class PreferencesHelper(val context: Context) {
fun pinnedCatalogues() = rxPrefs.getStringSet("pinned_catalogues", emptySet()) fun pinnedCatalogues() = rxPrefs.getStringSet("pinned_catalogues", emptySet())
fun downloadNew() = rxPrefs.getBoolean(Keys.downloadNew, false) fun downloadNew() = flowPrefs.getBoolean(Keys.downloadNew, false)
fun downloadNewCategories() = rxPrefs.getStringSet(Keys.downloadNewCategories, emptySet()) fun downloadNewCategories() = flowPrefs.getStringSet(Keys.downloadNewCategories, emptySet())
fun lang() = prefs.getString(Keys.lang, "") fun lang() = prefs.getString(Keys.lang, "")

View File

@ -41,6 +41,7 @@ interface Source : tachiyomi.source.Source {
* *
* @param manga the manga to update. * @param manga the manga to update.
*/ */
@Deprecated("Use getMangaDetails instead")
fun fetchMangaDetails(manga: SManga): Observable<SManga> fun fetchMangaDetails(manga: SManga): Observable<SManga>
/** /**
@ -48,6 +49,7 @@ interface Source : tachiyomi.source.Source {
* *
* @param manga the manga to update. * @param manga the manga to update.
*/ */
@Deprecated("Use getChapterList instead")
fun fetchChapterList(manga: SManga): Observable<List<SChapter>> fun fetchChapterList(manga: SManga): Observable<List<SChapter>>
/** /**
@ -55,6 +57,7 @@ interface Source : tachiyomi.source.Source {
* *
* @param chapter the chapter. * @param chapter the chapter.
*/ */
@Deprecated("Use getPageList instead")
fun fetchPageList(chapter: SChapter): Observable<List<Page>> fun fetchPageList(chapter: SChapter): Observable<List<Page>>
/** /**
@ -92,17 +95,5 @@ interface Source : tachiyomi.source.Source {
} }
} }
suspend fun Source.fetchMangaDetailsAsync(manga: SManga): SManga? {
return withContext(Dispatchers.IO) {
fetchMangaDetails(manga).toBlocking().single()
}
}
suspend fun Source.fetchChapterListAsync(manga: SManga): List<SChapter>? {
return withContext(Dispatchers.IO) {
fetchChapterList(manga).toBlocking().single()
}
}
fun Source.icon(): Drawable? = fun Source.icon(): Drawable? =
Injekt.get<ExtensionManager>().getAppIconForSource(this) Injekt.get<ExtensionManager>().getAppIconForSource(this)

View File

@ -5,9 +5,11 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaImpl import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.fetchChapterListAsync
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.source.model.toSManga
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
abstract class DelegatedHttpSource { abstract class DelegatedHttpSource {
@ -24,10 +26,10 @@ abstract class DelegatedHttpSource {
open fun pageNumber(uri: Uri): Int? = uri.pathSegments.lastOrNull()?.toIntOrNull() open fun pageNumber(uri: Uri): Int? = uri.pathSegments.lastOrNull()?.toIntOrNull()
abstract suspend fun fetchMangaFromChapterUrl(uri: Uri): Triple<Chapter, Manga, List<SChapter>>? abstract suspend fun fetchMangaFromChapterUrl(uri: Uri): Triple<Chapter, Manga, List<SChapter>>?
protected open fun getMangaInfo(url: String): Manga? { protected open suspend fun getMangaInfo(url: String): Manga? {
val id = delegate?.id ?: return null val id = delegate?.id ?: return null
val manga = Manga.create(url, "", id) val manga = Manga.create(url, "", id)
val networkManga = delegate?.fetchMangaDetails(manga)?.toBlocking()?.single() ?: return null val networkManga = delegate?.getMangaDetails(manga.toMangaInfo())?.toSManga() ?: return null
val newManga = MangaImpl().apply { val newManga = MangaImpl().apply {
this.url = url this.url = url
title = try { networkManga.title } catch (e: Exception) { "" } title = try { networkManga.title } catch (e: Exception) { "" }
@ -40,6 +42,6 @@ abstract class DelegatedHttpSource {
suspend fun getChapters(url: String): List<SChapter>? { suspend fun getChapters(url: String): List<SChapter>? {
val id = delegate?.id ?: return null val id = delegate?.id ?: return null
val manga = Manga.create(url, "", id) val manga = Manga.create(url, "", id)
return delegate?.fetchChapterListAsync(manga) return delegate?.getChapterList(manga.toMangaInfo())?.map { it.toSChapter() }
} }
} }

View File

@ -6,7 +6,7 @@ import android.view.View
import android.widget.CompoundButton import android.widget.CompoundButton
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView import com.afollestad.materialdialogs.customview.customView
import com.f2prateek.rx.preferences.Preference import com.tfcporciuncula.flow.Preference
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
@ -99,18 +99,18 @@ class ManageCategoryDialog(bundle: Bundle? = null) :
} }
view.title.hint = category.name view.title.hint = category.name
view.title.append(category.name) view.title.append(category.name)
val downloadNew = preferences.downloadNew().getOrDefault() val downloadNew = preferences.downloadNew().get()
setCheckbox( setCheckbox(
view.download_new, view.download_new,
preferences.downloadNewCategories(), preferences.downloadNewCategories(),
true true
) )
if (downloadNew && preferences.downloadNewCategories().getOrDefault().isEmpty()) if (downloadNew && preferences.downloadNewCategories().get().isEmpty())
view.download_new.gone() view.download_new.gone()
else if (!downloadNew) else if (!downloadNew)
view.download_new.visible() view.download_new.visible()
view.download_new.isChecked = view.download_new.isChecked =
preferences.downloadNew().getOrDefault() && view.download_new.isChecked preferences.downloadNew().get() && view.download_new.isChecked
setCheckbox( setCheckbox(
view.include_global, view.include_global,
preferences.libraryUpdateCategories(), preferences.libraryUpdateCategories(),
@ -121,7 +121,7 @@ class ManageCategoryDialog(bundle: Bundle? = null) :
/** Update a pref based on checkbox, and return if the pref is not empty */ /** Update a pref based on checkbox, and return if the pref is not empty */
private fun updatePref(categories: Preference<Set<String>>, box: CompoundButton): Boolean { private fun updatePref(categories: Preference<Set<String>>, box: CompoundButton): Boolean {
val categoryId = category.id ?: return true val categoryId = category.id ?: return true
val updateCategories = categories.getOrDefault().toMutableSet() val updateCategories = categories.get().toMutableSet()
if (box.isChecked) { if (box.isChecked) {
updateCategories.add(categoryId.toString()) updateCategories.add(categoryId.toString())
} else { } else {
@ -136,7 +136,7 @@ class ManageCategoryDialog(bundle: Bundle? = null) :
categories: Preference<Set<String>>, categories: Preference<Set<String>>,
shouldShow: Boolean shouldShow: Boolean
) { ) {
val updateCategories = categories.getOrDefault() val updateCategories = categories.get()
box.visibleIf(updateCategories.isNotEmpty() && shouldShow) box.visibleIf(updateCategories.isNotEmpty() && shouldShow)
if (updateCategories.isNotEmpty() && shouldShow) box.isChecked = if (updateCategories.isNotEmpty() && shouldShow) box.isChecked =
updateCategories.any { category.id == it.toIntOrNull() } updateCategories.any { category.id == it.toIntOrNull() }

View File

@ -13,6 +13,7 @@ import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaCategory import eu.kanade.tachiyomi.data.database.models.MangaCategory
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
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.download.model.Download
import eu.kanade.tachiyomi.data.download.model.DownloadQueue import eu.kanade.tachiyomi.data.download.model.DownloadQueue
@ -25,9 +26,8 @@ import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.fetchChapterListAsync import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.source.fetchMangaDetailsAsync import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
import eu.kanade.tachiyomi.ui.manga.track.TrackItem import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
@ -35,6 +35,7 @@ import eu.kanade.tachiyomi.util.chapter.ChapterFilter
import eu.kanade.tachiyomi.util.chapter.ChapterUtil import eu.kanade.tachiyomi.util.chapter.ChapterUtil
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.lang.trimOrNull import eu.kanade.tachiyomi.util.lang.trimOrNull
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.system.ImageUtil import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.executeOnIO import eu.kanade.tachiyomi.util.system.executeOnIO
@ -316,16 +317,16 @@ class MangaDetailsPresenter(
var chapterError: java.lang.Exception? = null var chapterError: java.lang.Exception? = null
val chapters = async(Dispatchers.IO) { val chapters = async(Dispatchers.IO) {
try { try {
source.fetchChapterListAsync(manga) source.getChapterList(manga.toMangaInfo()).map { it.toSChapter() }
} catch (e: Exception) { } catch (e: Exception) {
chapterError = e chapterError = e
emptyList<SChapter>() emptyList()
} ?: emptyList() }
} }
val thumbnailUrl = manga.thumbnail_url val thumbnailUrl = manga.thumbnail_url
val nManga = async(Dispatchers.IO) { val nManga = async(Dispatchers.IO) {
try { try {
source.fetchMangaDetailsAsync(manga) source.getMangaDetails(manga.toMangaInfo()).toSManga()
} catch (e: java.lang.Exception) { } catch (e: java.lang.Exception) {
mangaError = e mangaError = e
null null
@ -350,18 +351,13 @@ class MangaDetailsPresenter(
if (finChapters.isNotEmpty()) { if (finChapters.isNotEmpty()) {
val newChapters = syncChaptersWithSource(db, finChapters, manga, source) val newChapters = syncChaptersWithSource(db, finChapters, manga, source)
if (newChapters.first.isNotEmpty()) { if (newChapters.first.isNotEmpty()) {
val downloadNew = preferences.downloadNew().getOrDefault() if (manga.shouldDownloadNewChapters(db, preferences)) {
if (downloadNew && !controller.fromCatalogue && mangaWasInitalized) {
val categoriesToDownload = preferences.downloadNewCategories().getOrDefault().map(String::toInt)
val shouldDownload = categoriesToDownload.isEmpty() || getMangaCategoryIds().any { it in categoriesToDownload }
if (shouldDownload) {
downloadChapters( downloadChapters(
newChapters.first.sortedBy { it.chapter_number } newChapters.first.sortedBy { it.chapter_number }
.map { it.toModel() } .map { it.toModel() }
) )
} }
} }
}
if (newChapters.second.isNotEmpty()) { if (newChapters.second.isNotEmpty()) {
val removedChaptersId = newChapters.second.map { it.id } val removedChaptersId = newChapters.second.map { it.id }
val removedChapters = this@MangaDetailsPresenter.chapters.filter { val removedChapters = this@MangaDetailsPresenter.chapters.filter {
@ -403,7 +399,7 @@ class MangaDetailsPresenter(
scope.launch(Dispatchers.IO) { scope.launch(Dispatchers.IO) {
val chapters = try { val chapters = try {
source.fetchChapterListAsync(manga) source.getChapterList(manga.toMangaInfo()).map { it.toSChapter() }
} catch (e: Exception) { } catch (e: Exception) {
withContext(Dispatchers.Main) { controller.showError(trimException(e)) } withContext(Dispatchers.Main) { controller.showError(trimException(e)) }
return@launch return@launch

View File

@ -18,6 +18,7 @@ import com.bluelinelabs.conductor.changehandler.FadeChangeHandler
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.smartsearch.SmartSearchEngine import eu.kanade.tachiyomi.smartsearch.SmartSearchEngine
@ -25,6 +26,8 @@ import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.main.BottomNavBarInterface import eu.kanade.tachiyomi.ui.main.BottomNavBarInterface
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
@ -184,10 +187,7 @@ class MigrationListController(bundle: Bundle? = null) :
source.id source.id
) )
val chapters = val chapters =
source.fetchChapterList(localManga).toSingle() source.getChapterList(localManga.toMangaInfo()).map { it.toSChapter() }
.await(
Schedulers.io()
)
try { try {
syncChaptersWithSource( syncChaptersWithSource(
db, db,
@ -226,8 +226,7 @@ class MigrationListController(bundle: Bundle? = null) :
source.id source.id
) )
val chapters = try { val chapters = try {
source.fetchChapterList(localManga).toSingle() source.getChapterList(localManga.toMangaInfo()).map { it.toSChapter() }
.await(Schedulers.io())
} catch (e: java.lang.Exception) { } catch (e: java.lang.Exception) {
Timber.e(e) Timber.e(e)
emptyList<SChapter>() emptyList<SChapter>()
@ -260,8 +259,7 @@ class MigrationListController(bundle: Bundle? = null) :
if (result != null && result.thumbnail_url == null) { if (result != null && result.thumbnail_url == null) {
try { try {
val newManga = val newManga =
sourceManager.getOrStub(result.source).fetchMangaDetails(result) sourceManager.getOrStub(result.source).getMangaDetails(result.toMangaInfo()).toSManga()
.toSingle().await()
result.copyFrom(newManga) result.copyFrom(newManga)
db.insertManga(result).executeAsBlocking() db.insertManga(result).executeAsBlocking()
@ -366,9 +364,7 @@ class MigrationListController(bundle: Bundle? = null) :
launchUI { launchUI {
val result = CoroutineScope(migratingManga.manga.migrationJob).async { val result = CoroutineScope(migratingManga.manga.migrationJob).async {
val localManga = smartSearchEngine.networkToLocalManga(manga, source.id) val localManga = smartSearchEngine.networkToLocalManga(manga, source.id)
val chapters = source.fetchChapterList(localManga).toSingle().await( val chapters = source.getChapterList(localManga.toMangaInfo()).map { it.toSChapter() }
Schedulers.io()
)
try { try {
syncChaptersWithSource(db, chapters, localManga, source) syncChaptersWithSource(db, chapters, localManga, source)
} catch (e: Exception) { } catch (e: Exception) {
@ -380,8 +376,8 @@ class MigrationListController(bundle: Bundle? = null) :
if (result != null) { if (result != null) {
try { try {
val newManga = val newManga =
sourceManager.getOrStub(result.source).fetchMangaDetails(result).toSingle() sourceManager.getOrStub(result.source).getMangaDetails(result.toMangaInfo())
.await() .toSManga()
result.copyFrom(newManga) result.copyFrom(newManga)
db.insertManga(result).executeAsBlocking() db.insertManga(result).executeAsBlocking()

View File

@ -16,6 +16,7 @@ import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.util.system.getFilePicker import eu.kanade.tachiyomi.util.system.getFilePicker
@ -93,12 +94,10 @@ class SettingsDownloadController : SettingsController() {
entryValues = dbCategories.map { it.id.toString() } entryValues = dbCategories.map { it.id.toString() }
allSelectionRes = R.string.all allSelectionRes = R.string.all
preferences.downloadNew().asObservable() preferences.downloadNew().asImmediateFlow { isVisible = it }
.subscribeUntilDestroy { isVisible = it }
preferences.downloadNewCategories().asObservable() preferences.downloadNewCategories().asImmediateFlow { list ->
.subscribeUntilDestroy { val selectedCategories = list
val selectedCategories = it
.mapNotNull { id -> dbCategories.find { it.id == id.toInt() } } .mapNotNull { id -> dbCategories.find { it.id == id.toInt() } }
.sortedBy { it.order } .sortedBy { it.order }

View File

@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.ui.category.CategoryController import eu.kanade.tachiyomi.ui.category.CategoryController
import eu.kanade.tachiyomi.util.view.withFadeTransaction import eu.kanade.tachiyomi.util.view.withFadeTransaction
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -133,9 +134,9 @@ class SettingsLibraryController : SettingsController() {
entryValues = dbCategories.map { it.id.toString() } entryValues = dbCategories.map { it.id.toString() }
allSelectionRes = R.string.all allSelectionRes = R.string.all
preferences.libraryUpdateCategories().asObservable().subscribeUntilDestroy { preferences.libraryUpdateCategories().asImmediateFlow { list ->
val selectedCategories = val selectedCategories =
it.mapNotNull { id -> dbCategories.find { it.id == id.toInt() } } list.mapNotNull { id -> dbCategories.find { it.id == id.toInt() } }
.sortedBy { it.order } .sortedBy { it.order }
customSummary = customSummary =

View File

@ -0,0 +1,73 @@
package eu.kanade.tachiyomi.util
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.model.SManga
import java.util.Date
fun Manga.isLocal() = source == LocalSource.ID
/*
/**
* Call before updating [Manga.thumbnail_url] to ensure old cover can be cleared from cache
*/
fun Manga.prepUpdateCover(coverCache: CoverCache, remoteManga: SManga, refreshSameUrl: Boolean) {
// Never refresh covers if the new url is null, as the current url has possibly become invalid
val newUrl = remoteManga.thumbnail_url ?: return
// Never refresh covers if the url is empty to avoid "losing" existing covers
if (newUrl.isEmpty()) return
if (!refreshSameUrl && thumbnail_url == newUrl) return
when {
isLocal() -> {
cover_last_modified = Date().time
}
hasCustomCover(coverCache) -> {
coverCache.deleteFromCache(this, false)
}
else -> {
cover_last_modified = Date().time
coverCache.deleteFromCache(this, false)
}
}
}
fun Manga.hasCustomCover(coverCache: CoverCache): Boolean {
return coverCache.getCustomCoverFile(this).exists()
}
fun Manga.removeCovers(coverCache: CoverCache) {
if (isLocal()) return
cover_last_modified = Date().time
coverCache.deleteFromCache(this, true)
}
fun Manga.updateCoverLastModified(db: DatabaseHelper) {
cover_last_modified = Date().time
db.updateMangaCoverLastModified(this).executeAsBlocking()
}*/
fun Manga.shouldDownloadNewChapters(db: DatabaseHelper, prefs: PreferencesHelper): Boolean {
if (!favorite) return false
// Boolean to determine if user wants to automatically download new chapters.
val downloadNew = prefs.downloadNew().get()
if (!downloadNew) return false
val categoriesToDownload = prefs.downloadNewCategories().get().map(String::toInt)
if (categoriesToDownload.isEmpty()) return true
// Get all categories, else default category (0)
val categoriesForManga =
db.getCategoriesForManga(this).executeAsBlocking()
.mapNotNull { it.id }
.takeUnless { it.isEmpty() } ?: listOf(0)
return categoriesForManga.intersect(categoriesToDownload).isNotEmpty()
}

View File

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.data.backup package eu.kanade.tachiyomi.data.backup
import android.app.Application import android.app.Application
import android.app.backup.BackupManager
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
import com.github.salomonbrys.kotson.fromJson import com.github.salomonbrys.kotson.fromJson
@ -8,8 +9,9 @@ import com.google.gson.JsonArray
import com.google.gson.JsonObject import com.google.gson.JsonObject
import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner
import eu.kanade.tachiyomi.data.backup.models.Backup import eu.kanade.tachiyomi.data.backup.legacy.LegacyBackupManager
import eu.kanade.tachiyomi.data.backup.models.DHistory import eu.kanade.tachiyomi.data.backup.legacy.models.Backup
import eu.kanade.tachiyomi.data.backup.legacy.models.DHistory
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
@ -62,7 +64,7 @@ class BackupTest {
lateinit var context: Context lateinit var context: Context
lateinit var source: HttpSource lateinit var source: HttpSource
lateinit var backupManager: BackupManager lateinit var backupManager: LegacyBackupManager
lateinit var db: DatabaseHelper lateinit var db: DatabaseHelper
@ -70,7 +72,7 @@ class BackupTest {
fun setup() { fun setup() {
app = RuntimeEnvironment.application app = RuntimeEnvironment.application
context = app.applicationContext context = app.applicationContext
backupManager = BackupManager(context) backupManager = LegacyBackupManager(context)
db = backupManager.databaseHelper db = backupManager.databaseHelper
// Mock the source manager // Mock the source manager
@ -93,9 +95,6 @@ class BackupTest {
*/ */
@Test @Test
fun testRestoreEmptyCategory() { fun testRestoreEmptyCategory() {
// Initialize json with version 2
initializeJsonTest(2)
// Create backup of empty database // Create backup of empty database
backupManager.backupCategories(categoryEntries) backupManager.backupCategories(categoryEntries)
@ -112,9 +111,6 @@ class BackupTest {
*/ */
@Test @Test
fun testRestoreSingleCategory() { fun testRestoreSingleCategory() {
// Initialize json with version 2
initializeJsonTest(2)
// Create category and add to json // Create category and add to json
val category = addSingleCategory("category") val category = addSingleCategory("category")
@ -132,9 +128,6 @@ class BackupTest {
*/ */
@Test @Test
fun testRestoreMultipleCategories() { fun testRestoreMultipleCategories() {
// Initialize json with version 2
initializeJsonTest(2)
// Create category and add to json // Create category and add to json
val category = addSingleCategory("category") val category = addSingleCategory("category")
val category2 = addSingleCategory("category2") val category2 = addSingleCategory("category2")
@ -163,9 +156,6 @@ class BackupTest {
*/ */
@Test @Test
fun testRestoreManga() { fun testRestoreManga() {
// Initialize json with version 2
initializeJsonTest(2)
// Add manga to database // Add manga to database
val manga = getSingleManga("One Piece") val manga = getSingleManga("One Piece")
manga.viewer = 3 manga.viewer = 3
@ -215,7 +205,7 @@ class BackupTest {
GlobalScope.launch { GlobalScope.launch {
try { try {
backupManager.restoreMangaFetch(source, jsonManga) backupManager.fetchManga(source, jsonManga)
} catch (e: Exception) { } catch (e: Exception) {
fail("Unexpected onError events") fail("Unexpected onError events")
} }
@ -233,9 +223,6 @@ class BackupTest {
*/ */
@Test @Test
fun testRestoreChapters() { fun testRestoreChapters() {
// Initialize json with version 2
initializeJsonTest(2)
// Insert manga // Insert manga
val manga = getSingleManga("One Piece") val manga = getSingleManga("One Piece")
manga.id = backupManager.databaseHelper.insertManga(manga).executeAsBlocking().insertedId() manga.id = backupManager.databaseHelper.insertManga(manga).executeAsBlocking().insertedId()
@ -261,7 +248,7 @@ class BackupTest {
// Call restoreChapterFetchObservable // Call restoreChapterFetchObservable
GlobalScope.launch { GlobalScope.launch {
try { try {
backupManager.restoreChapterFetch(source, manga, restoredChapters) backupManager.restoreChapters(source, manga, restoredChapters)
} catch (e: Exception) { } catch (e: Exception) {
fail("Unexpected onError events") fail("Unexpected onError events")
} }
@ -277,9 +264,6 @@ class BackupTest {
*/ */
@Test @Test
fun restoreHistoryForManga() { fun restoreHistoryForManga() {
// Initialize json with version 2
initializeJsonTest(2)
val manga = getSingleManga("One Piece") val manga = getSingleManga("One Piece")
manga.id = backupManager.databaseHelper.insertManga(manga).executeAsBlocking().insertedId() manga.id = backupManager.databaseHelper.insertManga(manga).executeAsBlocking().insertedId()
@ -311,9 +295,6 @@ class BackupTest {
*/ */
@Test @Test
fun restoreTrackForManga() { fun restoreTrackForManga() {
// Initialize json with version 2
initializeJsonTest(2)
// Create mangas // Create mangas
val manga = getSingleManga("One Piece") val manga = getSingleManga("One Piece")
val manga2 = getSingleManga("Bleach") val manga2 = getSingleManga("Bleach")
@ -377,11 +358,6 @@ class BackupTest {
categoryEntries = JsonArray() categoryEntries = JsonArray()
} }
fun initializeJsonTest(version: Int) {
clearJson()
backupManager.setVersion(version)
}
fun addSingleCategory(name: String): Category { fun addSingleCategory(name: String): Category {
val category = Category.create(name) val category = Category.create(name)
val catJson = backupManager.parser.toJsonTree(category) val catJson = backupManager.parser.toJsonTree(category)