From cd2f26a7c959eba5429ed129fed4d114d3daaec9 Mon Sep 17 00:00:00 2001 From: Andreas Date: Sat, 2 Jul 2022 22:12:06 +0200 Subject: [PATCH] Use SQLDelight for a Category related queries (#7438) (cherry picked from commit 2674570792a275abaee7a6ec1ae947d94f69a634) # Conflicts: # app/src/main/java/eu/kanade/data/category/CategoryRepositoryImpl.kt # app/src/main/java/eu/kanade/domain/category/model/Category.kt # app/src/main/java/eu/kanade/domain/category/repository/CategoryRepository.kt # app/src/main/java/eu/kanade/tachiyomi/data/database/DatabaseHelper.kt # app/src/main/java/eu/kanade/tachiyomi/data/database/queries/CategoryQueries.kt # app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt # app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt # app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt # app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt --- app/build.gradle.kts | 2 +- .../data/category/CategoryRepositoryImpl.kt | 6 +- .../kanade/data/manga/MangaRepositoryImpl.kt | 8 ++ .../java/eu/kanade/domain/SYDomainModule.kt | 2 + .../category/interactor/GetCategories.kt | 12 +-- .../kanade/domain/category/model/Category.kt | 17 +++- .../category/repository/CategoryRepository.kt | 6 +- .../interactor/GetMangaByUrlAndSource.kt | 25 +++++ .../manga/repository/MangaRepository.kt | 4 + .../data/download/DownloadManager.kt | 7 +- .../data/library/LibraryUpdateService.kt | 5 +- .../source/online/all/MergedSource.kt | 5 +- .../source/browse/BrowseSourcePresenter.kt | 6 +- .../tachiyomi/ui/manga/MangaController.kt | 27 +++--- .../tachiyomi/ui/manga/MangaPresenter.kt | 95 ++++++++++++------- .../ui/setting/SettingsDownloadController.kt | 23 ++--- .../ui/setting/SettingsLibraryController.kt | 25 ++--- .../kanade/tachiyomi/util/MangaExtensions.kt | 22 +---- 18 files changed, 188 insertions(+), 109 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index eb049fb9d..270980700 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -19,7 +19,7 @@ if (gradle.startParameter.taskRequests.toString().contains("Standard")) { shortcutHelper.setFilePath("./shortcuts.xml") android { - namespace = "eu.kanade.tachiyomi.sy" + namespace = "eu.kanade.tachiyomi" compileSdk = AndroidConfig.compileSdk ndkVersion = AndroidConfig.ndk diff --git a/app/src/main/java/eu/kanade/data/category/CategoryRepositoryImpl.kt b/app/src/main/java/eu/kanade/data/category/CategoryRepositoryImpl.kt index 9ecff4985..cd0e593d5 100644 --- a/app/src/main/java/eu/kanade/data/category/CategoryRepositoryImpl.kt +++ b/app/src/main/java/eu/kanade/data/category/CategoryRepositoryImpl.kt @@ -12,13 +12,11 @@ class CategoryRepositoryImpl( private val handler: DatabaseHandler, ) : CategoryRepository { - // SY --> - override suspend fun awaitAll(): List { + override suspend fun getAll(): List { return handler.awaitList { categoriesQueries.getCategories(categoryMapper) } } - // SY <-- - override fun getAll(): Flow> { + override fun getAllAsFlow(): Flow> { return handler.subscribeToList { categoriesQueries.getCategories(categoryMapper) } } diff --git a/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt b/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt index 61f2061b9..66b129c4e 100644 --- a/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt +++ b/app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt @@ -27,6 +27,14 @@ class MangaRepositoryImpl( return handler.subscribeToOne { mangasQueries.getMangaById(id, mangaMapper) } } + override suspend fun getMangaByUrlAndSource(url: String, sourceId: Long): Manga? { + return handler.awaitOneOrNull { mangasQueries.getMangaByUrlAndSource(url, sourceId, mangaMapper) } + } + + override suspend fun subscribeMangaByUrlAndSource(url: String, sourceId: Long): Flow { + return handler.subscribeToOneOrNull { mangasQueries.getMangaByUrlAndSource(url, sourceId, mangaMapper) } + } + override suspend fun getFavorites(): List { return handler.awaitList { mangasQueries.getFavorites(mangaMapper) } } diff --git a/app/src/main/java/eu/kanade/domain/SYDomainModule.kt b/app/src/main/java/eu/kanade/domain/SYDomainModule.kt index c371a47ba..202444f47 100644 --- a/app/src/main/java/eu/kanade/domain/SYDomainModule.kt +++ b/app/src/main/java/eu/kanade/domain/SYDomainModule.kt @@ -4,6 +4,7 @@ import eu.kanade.data.manga.MangaMergeRepositoryImpl import eu.kanade.data.manga.MangaMetadataRepositoryImpl import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId import eu.kanade.domain.manga.interactor.GetFlatMetadataById +import eu.kanade.domain.manga.interactor.GetMangaByUrlAndSource import eu.kanade.domain.manga.interactor.GetMergedManga import eu.kanade.domain.manga.interactor.GetMergedMangaById import eu.kanade.domain.manga.interactor.GetMergedReferencesById @@ -30,6 +31,7 @@ class SYDomainModule : InjektModule { addFactory { SetSourceCategories(get()) } addFactory { ToggleSources(get()) } addFactory { SetMangaFilteredScanlators(get()) } + addFactory { GetMangaByUrlAndSource(get()) } addSingletonFactory { MangaMetadataRepositoryImpl(get()) } addFactory { GetFlatMetadataById(get()) } diff --git a/app/src/main/java/eu/kanade/domain/category/interactor/GetCategories.kt b/app/src/main/java/eu/kanade/domain/category/interactor/GetCategories.kt index e3861164b..a13fb7e89 100644 --- a/app/src/main/java/eu/kanade/domain/category/interactor/GetCategories.kt +++ b/app/src/main/java/eu/kanade/domain/category/interactor/GetCategories.kt @@ -8,20 +8,18 @@ class GetCategories( private val categoryRepository: CategoryRepository, ) { - // SY --> - suspend fun await(): List { - return categoryRepository.awaitAll() - } - // SY <-- - fun subscribe(): Flow> { - return categoryRepository.getAll() + return categoryRepository.getAllAsFlow() } fun subscribe(mangaId: Long): Flow> { return categoryRepository.getCategoriesByMangaIdAsFlow(mangaId) } + suspend fun await(): List { + return categoryRepository.getAll() + } + suspend fun await(mangaId: Long): List { return categoryRepository.getCategoriesByMangaId(mangaId) } diff --git a/app/src/main/java/eu/kanade/domain/category/model/Category.kt b/app/src/main/java/eu/kanade/domain/category/model/Category.kt index 6f7b0874b..d3699bbad 100644 --- a/app/src/main/java/eu/kanade/domain/category/model/Category.kt +++ b/app/src/main/java/eu/kanade/domain/category/model/Category.kt @@ -1,5 +1,7 @@ package eu.kanade.domain.category.model +import android.content.Context +import eu.kanade.tachiyomi.R import java.io.Serializable import eu.kanade.tachiyomi.data.database.models.Category as DbCategory @@ -11,7 +13,20 @@ data class Category( // SY --> val mangaOrder: List, // SY <-- -) : Serializable +) : Serializable { + + companion object { + val default = { context: Context -> + Category( + id = 0, + name = context.getString(R.string.default_category), + order = 0, + flags = 0, + mangaOrder = emptyList() + ) + } + } +} fun Category.toDbCategory(): DbCategory = DbCategory.create(name).also { it.id = id.toInt() diff --git a/app/src/main/java/eu/kanade/domain/category/repository/CategoryRepository.kt b/app/src/main/java/eu/kanade/domain/category/repository/CategoryRepository.kt index 5e339a02e..6499243b4 100644 --- a/app/src/main/java/eu/kanade/domain/category/repository/CategoryRepository.kt +++ b/app/src/main/java/eu/kanade/domain/category/repository/CategoryRepository.kt @@ -6,11 +6,9 @@ import kotlinx.coroutines.flow.Flow interface CategoryRepository { - // SY --> - suspend fun awaitAll(): List - // SY <-- + suspend fun getAll(): List - fun getAll(): Flow> + fun getAllAsFlow(): Flow> suspend fun getCategoriesByMangaId(mangaId: Long): List diff --git a/app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaByUrlAndSource.kt b/app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaByUrlAndSource.kt index e69de29bb..f8dc7373b 100644 --- a/app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaByUrlAndSource.kt +++ b/app/src/main/java/eu/kanade/domain/manga/interactor/GetMangaByUrlAndSource.kt @@ -0,0 +1,25 @@ +package eu.kanade.domain.manga.interactor + +import eu.kanade.domain.manga.model.Manga +import eu.kanade.domain.manga.repository.MangaRepository +import eu.kanade.tachiyomi.util.system.logcat +import kotlinx.coroutines.flow.Flow +import logcat.LogPriority + +class GetMangaByUrlAndSource( + private val mangaRepository: MangaRepository, +) { + + suspend fun await(url: String, sourceId: Long): Manga? { + return try { + mangaRepository.getMangaByUrlAndSource(url, sourceId) + } catch (e: Exception) { + logcat(LogPriority.ERROR, e) + null + } + } + + suspend fun subscribe(url: String, sourceId: Long): Flow { + return mangaRepository.subscribeMangaByUrlAndSource(url, sourceId) + } +} diff --git a/app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt b/app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt index 97c35de42..5d16bc333 100644 --- a/app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt +++ b/app/src/main/java/eu/kanade/domain/manga/repository/MangaRepository.kt @@ -12,6 +12,10 @@ interface MangaRepository { suspend fun getMangaByIdAsFlow(id: Long): Flow + suspend fun getMangaByUrlAndSource(url: String, sourceId: Long): Manga? + + suspend fun subscribeMangaByUrlAndSource(url: String, sourceId: Long): Flow + suspend fun getFavorites(): List fun getFavoritesBySourceId(sourceId: Long): Flow> diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt index e3e61cb68..4f9aaad2d 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt @@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.download import android.content.Context import com.hippo.unifile.UniFile import com.jakewharton.rxrelay.BehaviorRelay +import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Chapter @@ -34,6 +35,7 @@ import uy.kohesive.injekt.injectLazy class DownloadManager( private val context: Context, private val db: DatabaseHelper = Injekt.get(), + private val getCategories: GetCategories = Injekt.get(), ) { private val sourceManager: SourceManager by injectLazy() @@ -416,8 +418,9 @@ class DownloadManager( private fun getChaptersToDelete(chapters: List, manga: Manga): List { // Retrieve the categories that are set to exclude from being deleted on read val categoriesToExclude = preferences.removeExcludeCategories().get().map(String::toInt) - val categoriesForManga = db.getCategoriesForManga(manga).executeAsBlocking() - .mapNotNull { it.id } + + val categoriesForManga = runBlocking { getCategories.await(manga.id!!) } + .map { it.id } .takeUnless { it.isEmpty() } ?: listOf(0) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt index 91fd6ca4c..b8a014204 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt @@ -7,6 +7,7 @@ import android.os.IBinder import android.os.PowerManager import androidx.core.content.ContextCompat import eu.kanade.data.chapter.NoChaptersException +import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.domain.chapter.interactor.GetChapterByMangaId import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay @@ -108,6 +109,7 @@ class LibraryUpdateService( private val getMangaById: GetMangaById = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(), private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(), + private val getCategories: GetCategories = Injekt.get(), private val syncChaptersWithSource: SyncChaptersWithSource = Injekt.get(), private val getTracks: GetTracks = Injekt.get(), private val insertTrack: InsertTrack = Injekt.get(), @@ -427,7 +429,8 @@ class LibraryUpdateService( val newDbChapters = newChapters.map { it.toDbChapter() } if (newChapters.isNotEmpty()) { - if (mangaWithNotif.shouldDownloadNewChapters(db, preferences)) { + val categoryIds = getCategories.await(domainManga.id).map { it.id } + if (domainManga.shouldDownloadNewChapters(categoryIds, preferences)) { downloadChapters(mangaWithNotif, newDbChapters) hasDownloads.set(true) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MergedSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MergedSource.kt index 5f37ee0d4..287c85c94 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MergedSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MergedSource.kt @@ -1,9 +1,9 @@ package eu.kanade.tachiyomi.source.online.all +import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource import eu.kanade.domain.chapter.model.toDbChapter -import eu.kanade.domain.manga.model.toDbManga import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga @@ -44,6 +44,7 @@ import eu.kanade.domain.manga.model.Manga as DomainManga class MergedSource : HttpSource() { private val db: DatabaseHelper by injectLazy() private val getMergedChaptersByMangaId: GetMergedChapterByMangaId by injectLazy() + private val getCategories: GetCategories by injectLazy() private val sourceManager: SourceManager by injectLazy() private val downloadManager: DownloadManager by injectLazy() private val preferences: PreferencesHelper by injectLazy() @@ -169,7 +170,7 @@ class MergedSource : HttpSource() { throw IllegalArgumentException("Manga references are empty, chapters unavailable, merge is likely corrupted") } - val ifDownloadNewChapters = downloadChapters && manga.toDbManga().shouldDownloadNewChapters(db, preferences) + val ifDownloadNewChapters = downloadChapters && manga.shouldDownloadNewChapters(getCategories.await(manga.id).map { it.id }, preferences) val semaphore = Semaphore(5) var exception: Exception? = null return supervisorScope { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt index f62f57e68..a66fc0f5f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt @@ -461,9 +461,9 @@ open class BrowseSourcePresenter( * @param manga the manga to get categories from. * @return Array of category ids the manga is in, if none returns default id */ - fun getMangaCategoryIds(manga: Manga): Array { - val categories = db.getCategoriesForManga(manga).executeAsBlocking() - return categories.mapNotNull { it?.id?.toLong() }.toTypedArray() + suspend fun getMangaCategoryIds(manga: Manga): Array { + val categories = getCategories.await(manga.id!!) + return categories.map { it.id }.toTypedArray() } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index 13f568478..967ad4d63 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -66,6 +66,7 @@ import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.recent.history.HistoryController import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController import eu.kanade.tachiyomi.ui.webview.WebViewActivity +import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.toast @@ -361,7 +362,7 @@ class MangaController : router?.popCurrentController() router?.replaceTopController( MangaController( - mergedManga.id!!, + mergedManga.id, true, update = true, ).withFadeTransaction(), @@ -408,18 +409,22 @@ class MangaController : } private fun onCategoriesClick() { - val manga = presenter.manga ?: return - val categories = presenter.getCategories() + viewScope.launchIO { + val manga = presenter.manga ?: return@launchIO + val categories = presenter.getCategories() - val ids = presenter.getMangaCategoryIds(manga) - val preselected = categories.map { - if (it.id in ids) { - QuadStateTextView.State.CHECKED.ordinal - } else { - QuadStateTextView.State.UNCHECKED.ordinal + val ids = presenter.getMangaCategoryIds(manga) + val preselected = categories.map { + if (it.id in ids) { + QuadStateTextView.State.CHECKED.ordinal + } else { + QuadStateTextView.State.UNCHECKED.ordinal + } + }.toTypedArray() + launchUI { + showChangeCategoryDialog(manga.toDbManga(), categories, preselected) } - }.toTypedArray() - showChangeCategoryDialog(manga.toDbManga(), categories, preselected) + } } private fun showChangeCategoryDialog(manga: Manga, categories: List, preselected: Array) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt index 91eb99515..3c9fc1dcf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt @@ -5,6 +5,7 @@ import android.os.Bundle import androidx.compose.runtime.Immutable import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.domain.category.interactor.SetMangaCategories +import eu.kanade.domain.category.model.toDbCategory import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay @@ -13,12 +14,15 @@ import eu.kanade.domain.chapter.model.ChapterUpdate import eu.kanade.domain.chapter.model.toDbChapter import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga import eu.kanade.domain.manga.interactor.GetFlatMetadataById +import eu.kanade.domain.manga.interactor.GetMangaById +import eu.kanade.domain.manga.interactor.GetMangaByUrlAndSource import eu.kanade.domain.manga.interactor.GetMangaWithChapters import eu.kanade.domain.manga.interactor.GetMergedMangaById import eu.kanade.domain.manga.interactor.GetMergedReferencesById import eu.kanade.domain.manga.interactor.SetMangaChapterFlags import eu.kanade.domain.manga.interactor.SetMangaFilteredScanlators import eu.kanade.domain.manga.interactor.UpdateManga +import eu.kanade.domain.manga.model.MangaUpdate import eu.kanade.domain.manga.model.TriStateFilter import eu.kanade.domain.manga.model.isLocal import eu.kanade.domain.manga.model.toDbManga @@ -33,9 +37,9 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga -import eu.kanade.tachiyomi.data.database.models.MangaCategory import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.toDomainChapter +import eu.kanade.tachiyomi.data.database.models.toDomainManga import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.library.CustomMangaManager @@ -113,7 +117,6 @@ class MangaPresenter( val isFromSource: Boolean, val smartSearched: Boolean, private val preferences: PreferencesHelper = Injekt.get(), - private val db: DatabaseHelper = Injekt.get(), private val trackManager: TrackManager = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(), // SY --> @@ -121,6 +124,8 @@ class MangaPresenter( // SY <-- private val getMangaAndChapters: GetMangaWithChapters = Injekt.get(), // SY --> + private val getMangaById: GetMangaById = Injekt.get(), + private val getMangaByUrlAndSource: GetMangaByUrlAndSource = Injekt.get(), private val setMangaFilteredScanlators: SetMangaFilteredScanlators = Injekt.get(), private val getMergedChapterByMangaId: GetMergedChapterByMangaId = Injekt.get(), private val getMergedMangaById: GetMergedMangaById = Injekt.get(), @@ -377,8 +382,12 @@ class MangaPresenter( val state = successState ?: return var manga = state.manga if (state.manga.isLocal()) { + val newTitle = if (title.isNullOrBlank()) manga.url else title.trim() + val newAuthor = author?.trimOrNull() + val newArtist = artist?.trimOrNull() + val newDesc = description?.trimOrNull() manga = manga.copy( - ogTitle = if (title.isNullOrBlank()) manga.url else title.trim(), + ogTitle = newTitle, ogAuthor = author?.trimOrNull(), ogArtist = artist?.trimOrNull(), ogDescription = description?.trimOrNull(), @@ -386,8 +395,19 @@ class MangaPresenter( ogStatus = status ?: 0, ) (sourceManager.get(LocalSource.ID) as LocalSource).updateMangaInfo(manga.toSManga()) - // TODO - db.updateMangaInfo(manga.toDbManga()).executeAsBlocking() + launchIO { + updateManga.await( + MangaUpdate( + manga.id, + title = newTitle, + author = newAuthor, + artist = newArtist, + description = newDesc, + genre = tags, + status = status + ) + ) + } } else { val genre = if (!tags.isNullOrEmpty() && tags != state.manga.ogGenre) { tags @@ -413,11 +433,13 @@ class MangaPresenter( } } - suspend fun smartSearchMerge(context: Context, manga: DomainManga, originalMangaId: Long): Manga { - val originalManga = db.getManga(originalMangaId).executeAsBlocking() + suspend fun smartSearchMerge(context: Context, manga: DomainManga, originalMangaId: Long): DomainManga { + val db = Injekt.get() + + val originalManga = getMangaById.await(originalMangaId) ?: throw IllegalArgumentException(context.getString(R.string.merge_unknown_manga, originalMangaId)) if (originalManga.source == MERGED_SOURCE_ID) { - val children = db.getMergedMangaReferences(originalMangaId).executeAsBlocking() + val children = getMergedReferencesById.await(originalMangaId) if (children.any { it.mangaSourceId == manga.source && it.mangaUrl == manga.url }) { throw IllegalArgumentException(context.getString(R.string.merged_already)) } @@ -430,7 +452,7 @@ class MangaPresenter( chapterSortMode = 0, chapterPriority = 0, downloadChapters = true, - mergeId = originalManga.id!!, + mergeId = originalManga.id, mergeUrl = originalManga.url, mangaId = manga.id, mangaUrl = manga.url, @@ -446,38 +468,40 @@ class MangaPresenter( chapterSortMode = 0, chapterPriority = -1, downloadChapters = false, - mergeId = originalManga.id!!, + mergeId = originalManga.id, mergeUrl = originalManga.url, - mangaId = originalManga.id!!, + mangaId = originalManga.id, mangaUrl = originalManga.url, mangaSourceId = MERGED_SOURCE_ID, ) } + // todo db.insertMergedMangas(mangaReferences).executeAsBlocking() return originalManga } else { val mergedManga = Manga.create(originalManga.url, originalManga.title, MERGED_SOURCE_ID).apply { - copyFrom(originalManga) + copyFrom(originalManga.toSManga()) favorite = true - last_update = originalManga.last_update - viewer_flags = originalManga.viewer_flags - chapter_flags = originalManga.chapter_flags + last_update = originalManga.lastUpdate + viewer_flags = originalManga.viewerFlags.toInt() + chapter_flags = originalManga.chapterFlags.toInt() sorting = Manga.CHAPTER_SORTING_NUMBER date_added = System.currentTimeMillis() } - var existingManga = db.getManga(mergedManga.url, mergedManga.source).executeAsBlocking() + + var existingManga = getMangaByUrlAndSource.await(mergedManga.url, mergedManga.source) while (existingManga != null) { if (existingManga.favorite) { throw IllegalArgumentException(context.getString(R.string.merge_duplicate)) } else if (!existingManga.favorite) { withContext(NonCancellable) { - db.deleteManga(existingManga!!).executeAsBlocking() - db.deleteMangaForMergedManga(existingManga!!.id!!).executeAsBlocking() + db.deleteManga(existingManga!!.toDbManga()).executeAsBlocking() + db.deleteMangaForMergedManga(existingManga!!.id).executeAsBlocking() } } - existingManga = db.getManga(mergedManga.url, mergedManga.source).executeAsBlocking() + existingManga = getMangaByUrlAndSource.await(mergedManga.url, mergedManga.source) } // Reload chapters immediately @@ -486,13 +510,12 @@ class MangaPresenter( val newId = db.insertManga(mergedManga).executeAsBlocking().insertedId() if (newId != null) mergedManga.id = newId - db.getCategoriesForManga(originalManga) - .executeAsBlocking() - .map { MangaCategory.create(mergedManga, it) } + getCategories.await(originalMangaId) .let { - db.insertMangasCategories(it).executeAsBlocking() + setMangaCategories.await(mergedManga.id!!, it.map { it.id }) } + val originalMangaReference = MergedMangaReference( id = null, isInfoManga = true, @@ -502,7 +525,7 @@ class MangaPresenter( downloadChapters = true, mergeId = mergedManga.id!!, mergeUrl = mergedManga.url, - mangaId = originalManga.id!!, + mangaId = originalManga.id, mangaUrl = originalManga.url, mangaSourceId = originalManga.source, ) @@ -537,7 +560,7 @@ class MangaPresenter( db.insertMergedMangas(listOf(originalMangaReference, newMangaReference, mergedMangaReference)).executeAsBlocking() - return mergedManga + return mergedManga.toDomainManga()!! } // Note that if the manga are merged in a different order, this won't trigger, but I don't care lol @@ -545,6 +568,8 @@ class MangaPresenter( fun updateMergeSettings(mergeReference: MergedMangaReference?, mergedMangaReferences: List) { launchIO { + // todo + val db = Injekt.get() mergeReference?.let { db.updateMergeMangaSettings(it).executeAsBlocking() } @@ -665,8 +690,8 @@ class MangaPresenter( * * @return List of categories, not including the default category */ - fun getCategories(): List { - return db.getCategories().executeAsBlocking() + suspend fun getCategories(): List { + return getCategories.await().map { it.toDbCategory() } } /** @@ -976,9 +1001,12 @@ class MangaPresenter( } private fun downloadNewChapters(chapters: List) { - val manga = successState?.manga ?: return - if (chapters.isEmpty() || !manga.shouldDownloadNewChapters(db, preferences) || manga.isEhBasedManga()) return - downloadChapters(chapters.map { it.toDomainChapter()!! }) + presenterScope.launchIO { + val manga = successState?.manga ?: return@launchIO + val categories = getCategories.await(manga.id).map { it.id } + if (chapters.isEmpty() || !manga.shouldDownloadNewChapters(categories, preferences) || manga.isEhBasedManga()) return@launchIO + downloadChapters(chapters.map { it.toDomainChapter()!! }) + } } /** @@ -1110,14 +1138,15 @@ class MangaPresenter( } // SY --> - private fun createMdListTrack(): TrackItem { + private suspend fun createMdListTrack(): TrackItem { val state = successState!! val mdManga = state.manga.takeIf { it.source in mangaDexSourceIds } ?: state.mergedData?.manga?.values?.find { it.source in mangaDexSourceIds } ?: throw IllegalArgumentException("Could not create initial track") val track = trackManager.mdList.createInitialTracker(state.manga.toDbManga(), mdManga.toDbManga()) - track.id = db.insertTrack(track).executeAsBlocking().insertedId() - return TrackItem(track, trackManager.mdList) + .toDomainTrack(false)!! + insertTrack.await(track) + return TrackItem(getTracks.await(mangaId).first { it.syncId == TrackManager.MDLIST }.toDbTrack(), trackManager.mdList) } // SY <-- diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt index eaf43573e..8b550b9b7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt @@ -11,9 +11,9 @@ import androidx.core.text.buildSpannedString import androidx.preference.PreferenceScreen import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.hippo.unifile.UniFile +import eu.kanade.domain.category.interactor.GetCategories +import eu.kanade.domain.category.model.Category import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.DatabaseHelper -import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.util.preference.bindTo @@ -32,6 +32,7 @@ import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView import eu.kanade.tachiyomi.widget.materialdialogs.setQuadStateMultiChoiceItems import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.runBlocking import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy @@ -40,13 +41,13 @@ import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys class SettingsDownloadController : SettingsController() { - private val db: DatabaseHelper by injectLazy() + private val getCategories: GetCategories by injectLazy() override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_downloads - val dbCategories = db.getCategories().executeAsBlocking() - val categories = listOf(Category.createDefault(context)) + dbCategories + val dbCategories = runBlocking { getCategories.await() } + val categories = listOf(Category.default(context)) + dbCategories preference { bindTo(preferences.downloadsDirectory()) @@ -116,7 +117,7 @@ class SettingsDownloadController : SettingsController() { preferences.removeExcludeCategories().asFlow() .onEach { mutable -> val selected = mutable - .mapNotNull { id -> categories.find { it.id == id.toInt() } } + .mapNotNull { id -> categories.find { it.id == id.toLong() } } .sortedBy { it.order } summary = if (selected.isEmpty()) { @@ -146,7 +147,7 @@ class SettingsDownloadController : SettingsController() { fun updateSummary() { val selectedCategories = preferences.downloadNewChapterCategories().get() - .mapNotNull { id -> categories.find { it.id == id.toInt() } } + .mapNotNull { id -> categories.find { it.id == id.toLong() } } .sortedBy { it.order } val includedItemsText = if (selectedCategories.isEmpty()) { context.getString(R.string.all) @@ -155,7 +156,7 @@ class SettingsDownloadController : SettingsController() { } val excludedCategories = preferences.downloadNewChapterCategoriesExclude().get() - .mapNotNull { id -> categories.find { it.id == id.toInt() } } + .mapNotNull { id -> categories.find { it.id == id.toLong() } } .sortedBy { it.order } val excludedItemsText = if (excludedCategories.isEmpty()) { context.getString(R.string.none) @@ -251,11 +252,11 @@ class SettingsDownloadController : SettingsController() { class DownloadCategoriesDialog : DialogController() { private val preferences: PreferencesHelper = Injekt.get() - private val db: DatabaseHelper = Injekt.get() + private val getCategories: GetCategories = Injekt.get() override fun onCreateDialog(savedViewState: Bundle?): Dialog { - val dbCategories = db.getCategories().executeAsBlocking() - val categories = listOf(Category.createDefault(activity!!)) + dbCategories + val dbCategories = runBlocking { getCategories.await() } + val categories = listOf(Category.default(activity!!)) + dbCategories val items = categories.map { it.name } var selected = categories diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt index 398fcdfb7..b61fb1098 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt @@ -7,9 +7,9 @@ import androidx.core.content.ContextCompat import androidx.core.text.buildSpannedString import androidx.preference.PreferenceScreen import com.google.android.material.dialog.MaterialAlertDialogBuilder +import eu.kanade.domain.category.interactor.GetCategories +import eu.kanade.domain.category.model.Category import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.database.DatabaseHelper -import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.preference.DEVICE_BATTERY_NOT_LOW import eu.kanade.tachiyomi.data.preference.DEVICE_CHARGING @@ -45,6 +45,7 @@ import eu.kanade.tachiyomi.widget.materialdialogs.setQuadStateMultiChoiceItems import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.runBlocking import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy @@ -52,7 +53,7 @@ import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys class SettingsLibraryController : SettingsController() { - private val db: DatabaseHelper = Injekt.get() + private val getCategories: GetCategories by injectLazy() private val trackManager: TrackManager by injectLazy() // SY --> @@ -65,8 +66,8 @@ class SettingsLibraryController : SettingsController() { override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { titleRes = R.string.pref_category_library - val dbCategories = db.getCategories().executeAsBlocking() - val categories = listOf(Category.createDefault(context)) + dbCategories + val dbCategories = runBlocking { getCategories.await() } + val categories = listOf(Category.default(context)) + dbCategories preferenceCategory { titleRes = R.string.pref_category_display @@ -136,12 +137,12 @@ class SettingsLibraryController : SettingsController() { entryValues = arrayOf("-1") + categories.map { it.id.toString() }.toTypedArray() defaultValue = "-1" - val selectedCategory = categories.find { it.id == preferences.defaultCategory() } + val selectedCategory = categories.find { it.id == preferences.defaultCategory().toLong() } summary = selectedCategory?.name ?: context.getString(R.string.default_category_summary) onChange { newValue -> summary = categories.find { - it.id == (newValue as String).toInt() + it.id == (newValue as String).toLong() }?.name ?: context.getString(R.string.default_category_summary) true } @@ -254,10 +255,10 @@ class SettingsLibraryController : SettingsController() { fun updateSummary() { val includedCategories = preferences.libraryUpdateCategories().get() - .mapNotNull { id -> categories.find { it.id == id.toInt() } } + .mapNotNull { id -> categories.find { it.id == id.toLong() } } .sortedBy { it.order } val excludedCategories = preferences.libraryUpdateCategoriesExclude().get() - .mapNotNull { id -> categories.find { it.id == id.toInt() } } + .mapNotNull { id -> categories.find { it.id == id.toLong() } } .sortedBy { it.order } val allExcluded = excludedCategories.size == categories.size @@ -399,11 +400,11 @@ class SettingsLibraryController : SettingsController() { class LibraryGlobalUpdateCategoriesDialog : DialogController() { private val preferences: PreferencesHelper = Injekt.get() - private val db: DatabaseHelper = Injekt.get() + private val getCategories: GetCategories = Injekt.get() override fun onCreateDialog(savedViewState: Bundle?): Dialog { - val dbCategories = db.getCategories().executeAsBlocking() - val categories = listOf(Category.createDefault(activity!!)) + dbCategories + val dbCategories = runBlocking { getCategories.await() } + val categories = listOf(Category.default(activity!!)) + dbCategories val items = categories.map { it.name } var selected = categories diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt index 9fdb0dea4..b9d76ebfd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/MangaExtensions.kt @@ -5,9 +5,7 @@ import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.model.isLocal import eu.kanade.domain.manga.model.toDbManga 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.database.models.toDomainManga import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.model.SManga @@ -56,37 +54,27 @@ fun Manga.removeCovers(coverCache: CoverCache = Injekt.get()): Int { return coverCache.deleteFromCache(this, true) } -fun Manga.shouldDownloadNewChapters(db: DatabaseHelper, prefs: PreferencesHelper): Boolean { - return toDomainManga()?.shouldDownloadNewChapters(db, prefs) ?: false -} - -fun DomainManga.shouldDownloadNewChapters(db: DatabaseHelper, prefs: PreferencesHelper): Boolean { +fun DomainManga.shouldDownloadNewChapters(categories: List, prefs: PreferencesHelper): Boolean { if (!favorite) return false // Boolean to determine if user wants to automatically download new chapters. val downloadNewChapter = prefs.downloadNewChapter().get() if (!downloadNewChapter) return false - val includedCategories = prefs.downloadNewChapterCategories().get().map { it.toInt() } - val excludedCategories = prefs.downloadNewChapterCategoriesExclude().get().map { it.toInt() } + val includedCategories = prefs.downloadNewChapterCategories().get().map { it.toLong() } + val excludedCategories = prefs.downloadNewChapterCategoriesExclude().get().map { it.toLong() } // Default: Download from all categories if (includedCategories.isEmpty() && excludedCategories.isEmpty()) return true - // Get all categories, else default category (0) - val categoriesForManga = - db.getCategoriesForManga(toDbManga()).executeAsBlocking() - .mapNotNull { it.id } - .takeUnless { it.isEmpty() } ?: listOf(0) - // In excluded category - if (categoriesForManga.any { it in excludedCategories }) return false + if (categories.any { it in excludedCategories }) return false // Included category not selected if (includedCategories.isEmpty()) return true // In included category - return categoriesForManga.any { it in includedCategories } + return categories.any { it in includedCategories } } suspend fun DomainManga.editCover(