Use SQLDelight for more SY specific things
This commit is contained in:
parent
e71c9e2775
commit
d88c769d3b
@ -91,5 +91,9 @@ class AndroidDatabaseHandler(
|
|||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
fun getLibraryQuery() = LibraryQuery(driver)
|
fun getLibraryQuery() = LibraryQuery(driver)
|
||||||
|
|
||||||
|
fun rawQuery(query: (SqlDriver) -> Unit) {
|
||||||
|
return query(driver)
|
||||||
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package eu.kanade.data.manga
|
||||||
|
|
||||||
|
import eu.kanade.data.DatabaseHandler
|
||||||
|
import eu.kanade.data.exh.favoriteEntryMapper
|
||||||
|
import eu.kanade.domain.manga.repository.FavoritesEntryRepository
|
||||||
|
import exh.favorites.sql.models.FavoriteEntry
|
||||||
|
|
||||||
|
class FavoritesEntryRepositoryImpl(
|
||||||
|
private val handler: DatabaseHandler,
|
||||||
|
) : FavoritesEntryRepository {
|
||||||
|
override suspend fun deleteAll() {
|
||||||
|
handler.await { eh_favoritesQueries.deleteAll() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun insertAll(favoriteEntries: List<FavoriteEntry>) {
|
||||||
|
handler.await(true) {
|
||||||
|
favoriteEntries.forEach {
|
||||||
|
eh_favoritesQueries.insertEhFavorites(it.id, it.title, it.gid, it.token, it.category.toLong())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun selectAll(): List<FavoriteEntry> {
|
||||||
|
return handler.awaitList { eh_favoritesQueries.selectAll(favoriteEntryMapper) }
|
||||||
|
}
|
||||||
|
}
|
@ -2,10 +2,14 @@ package eu.kanade.data.manga
|
|||||||
|
|
||||||
import eu.kanade.data.DatabaseHandler
|
import eu.kanade.data.DatabaseHandler
|
||||||
import eu.kanade.data.exh.mergedMangaReferenceMapper
|
import eu.kanade.data.exh.mergedMangaReferenceMapper
|
||||||
|
import eu.kanade.data.toLong
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
|
import eu.kanade.domain.manga.model.MergeMangaSettingsUpdate
|
||||||
import eu.kanade.domain.manga.repository.MangaMergeRepository
|
import eu.kanade.domain.manga.repository.MangaMergeRepository
|
||||||
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
import exh.merged.sql.models.MergedMangaReference
|
import exh.merged.sql.models.MergedMangaReference
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import logcat.LogPriority
|
||||||
|
|
||||||
class MangaMergeRepositoryImpl(
|
class MangaMergeRepositoryImpl(
|
||||||
private val handler: DatabaseHandler,
|
private val handler: DatabaseHandler,
|
||||||
@ -34,4 +38,38 @@ class MangaMergeRepositoryImpl(
|
|||||||
override suspend fun subscribeReferencesById(id: Long): Flow<List<MergedMangaReference>> {
|
override suspend fun subscribeReferencesById(id: Long): Flow<List<MergedMangaReference>> {
|
||||||
return handler.subscribeToList { mergedQueries.selectByMergeId(id, mergedMangaReferenceMapper) }
|
return handler.subscribeToList { mergedQueries.selectByMergeId(id, mergedMangaReferenceMapper) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun updateSettings(update: MergeMangaSettingsUpdate): Boolean {
|
||||||
|
return try {
|
||||||
|
partialUpdate(update)
|
||||||
|
true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun updateAllSettings(values: List<MergeMangaSettingsUpdate>): Boolean {
|
||||||
|
return try {
|
||||||
|
partialUpdate(*values.toTypedArray())
|
||||||
|
true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun partialUpdate(vararg values: MergeMangaSettingsUpdate) {
|
||||||
|
handler.await(inTransaction = true) {
|
||||||
|
values.forEach { value ->
|
||||||
|
mergedQueries.updateSettingsById(
|
||||||
|
id = value.id,
|
||||||
|
getChapterUpdates = value.getChapterUpdates?.toLong(),
|
||||||
|
downloadChapters = value.downloadChapters?.toLong(),
|
||||||
|
infoManga = value.isInfoManga?.toLong(),
|
||||||
|
chapterPriority = value.chapterPriority?.toLong(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,14 @@ import eu.kanade.data.DatabaseHandler
|
|||||||
import eu.kanade.data.exh.searchMetadataMapper
|
import eu.kanade.data.exh.searchMetadataMapper
|
||||||
import eu.kanade.data.exh.searchTagMapper
|
import eu.kanade.data.exh.searchTagMapper
|
||||||
import eu.kanade.data.exh.searchTitleMapper
|
import eu.kanade.data.exh.searchTitleMapper
|
||||||
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.domain.manga.repository.MangaMetadataRepository
|
import eu.kanade.domain.manga.repository.MangaMetadataRepository
|
||||||
|
import exh.metadata.metadata.base.FlatMetadata
|
||||||
import exh.metadata.sql.models.SearchMetadata
|
import exh.metadata.sql.models.SearchMetadata
|
||||||
import exh.metadata.sql.models.SearchTag
|
import exh.metadata.sql.models.SearchTag
|
||||||
import exh.metadata.sql.models.SearchTitle
|
import exh.metadata.sql.models.SearchTitle
|
||||||
|
import exh.source.EH_SOURCE_ID
|
||||||
|
import exh.source.EXH_SOURCE_ID
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
class MangaMetadataRepositoryImpl(
|
class MangaMetadataRepositoryImpl(
|
||||||
@ -37,4 +41,34 @@ class MangaMetadataRepositoryImpl(
|
|||||||
override suspend fun subscribeTitlesById(id: Long): Flow<List<SearchTitle>> {
|
override suspend fun subscribeTitlesById(id: Long): Flow<List<SearchTitle>> {
|
||||||
return handler.subscribeToList { search_titlesQueries.selectByMangaId(id, searchTitleMapper) }
|
return handler.subscribeToList { search_titlesQueries.selectByMangaId(id, searchTitleMapper) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun insertFlatMetadata(flatMetadata: FlatMetadata) {
|
||||||
|
require(flatMetadata.metadata.mangaId != -1L)
|
||||||
|
|
||||||
|
handler.await(true) {
|
||||||
|
flatMetadata.metadata.run {
|
||||||
|
search_metadataQueries.upsert(mangaId, uploader, extra, indexedExtra, extraVersion)
|
||||||
|
}
|
||||||
|
search_tagsQueries.deleteByManga(flatMetadata.metadata.mangaId)
|
||||||
|
flatMetadata.tags.forEach {
|
||||||
|
search_tagsQueries.insert(it.mangaId, it.namespace, it.name, it.type)
|
||||||
|
}
|
||||||
|
search_titlesQueries.deleteByManga(flatMetadata.metadata.mangaId)
|
||||||
|
flatMetadata.titles.forEach {
|
||||||
|
search_titlesQueries.insert(it.mangaId, it.title, it.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getExhFavoriteMangaWithMetadata(): List<Manga> {
|
||||||
|
return handler.awaitList { mangasQueries.getEhMangaWithMetadata(EH_SOURCE_ID, EXH_SOURCE_ID, mangaMapper) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getIdsOfFavoriteMangaWithMetadata(): List<Long> {
|
||||||
|
return handler.awaitList { mangasQueries.getIdsOfFavoriteMangaWithMetadata() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getSearchMetadata(): List<SearchMetadata> {
|
||||||
|
return handler.awaitList { search_metadataQueries.selectAll(searchMetadataMapper) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,4 +114,12 @@ class MangaRepositoryImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getMangaBySource(sourceId: Long): List<Manga> {
|
||||||
|
return handler.awaitList { mangasQueries.getBySource(sourceId, mangaMapper) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getAll(): List<Manga> {
|
||||||
|
return handler.awaitList { mangasQueries.getAll(mangaMapper) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ import eu.kanade.domain.history.interactor.UpsertHistory
|
|||||||
import eu.kanade.domain.history.repository.HistoryRepository
|
import eu.kanade.domain.history.repository.HistoryRepository
|
||||||
import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
|
import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
|
||||||
import eu.kanade.domain.manga.interactor.GetFavorites
|
import eu.kanade.domain.manga.interactor.GetFavorites
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaWithChapters
|
import eu.kanade.domain.manga.interactor.GetMangaWithChapters
|
||||||
import eu.kanade.domain.manga.interactor.ResetViewerFlags
|
import eu.kanade.domain.manga.interactor.ResetViewerFlags
|
||||||
import eu.kanade.domain.manga.interactor.SetMangaChapterFlags
|
import eu.kanade.domain.manga.interactor.SetMangaChapterFlags
|
||||||
@ -72,7 +72,7 @@ class DomainModule : InjektModule {
|
|||||||
addFactory { GetDuplicateLibraryManga(get()) }
|
addFactory { GetDuplicateLibraryManga(get()) }
|
||||||
addFactory { GetFavorites(get()) }
|
addFactory { GetFavorites(get()) }
|
||||||
addFactory { GetMangaWithChapters(get(), get()) }
|
addFactory { GetMangaWithChapters(get(), get()) }
|
||||||
addFactory { GetMangaById(get()) }
|
addFactory { GetManga(get()) }
|
||||||
addFactory { GetNextChapter(get()) }
|
addFactory { GetNextChapter(get()) }
|
||||||
addFactory { ResetViewerFlags(get()) }
|
addFactory { ResetViewerFlags(get()) }
|
||||||
addFactory { SetMangaChapterFlags(get()) }
|
addFactory { SetMangaChapterFlags(get()) }
|
||||||
|
@ -1,14 +1,25 @@
|
|||||||
package eu.kanade.domain
|
package eu.kanade.domain
|
||||||
|
|
||||||
|
import eu.kanade.data.manga.FavoritesEntryRepositoryImpl
|
||||||
import eu.kanade.data.manga.MangaMergeRepositoryImpl
|
import eu.kanade.data.manga.MangaMergeRepositoryImpl
|
||||||
import eu.kanade.data.manga.MangaMetadataRepositoryImpl
|
import eu.kanade.data.manga.MangaMetadataRepositoryImpl
|
||||||
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
|
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
|
||||||
|
import eu.kanade.domain.manga.interactor.DeleteFavoriteEntries
|
||||||
|
import eu.kanade.domain.manga.interactor.GetAllManga
|
||||||
|
import eu.kanade.domain.manga.interactor.GetExhFavoriteMangaWithMetadata
|
||||||
|
import eu.kanade.domain.manga.interactor.GetFavoriteEntries
|
||||||
import eu.kanade.domain.manga.interactor.GetFlatMetadataById
|
import eu.kanade.domain.manga.interactor.GetFlatMetadataById
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaByUrlAndSource
|
import eu.kanade.domain.manga.interactor.GetIdsOfFavoriteMangaWithMetadata
|
||||||
|
import eu.kanade.domain.manga.interactor.GetMangaBySource
|
||||||
import eu.kanade.domain.manga.interactor.GetMergedManga
|
import eu.kanade.domain.manga.interactor.GetMergedManga
|
||||||
import eu.kanade.domain.manga.interactor.GetMergedMangaById
|
import eu.kanade.domain.manga.interactor.GetMergedMangaById
|
||||||
import eu.kanade.domain.manga.interactor.GetMergedReferencesById
|
import eu.kanade.domain.manga.interactor.GetMergedReferencesById
|
||||||
|
import eu.kanade.domain.manga.interactor.GetSearchTags
|
||||||
|
import eu.kanade.domain.manga.interactor.GetSearchTitles
|
||||||
|
import eu.kanade.domain.manga.interactor.InsertFavoriteEntries
|
||||||
|
import eu.kanade.domain.manga.interactor.InsertFlatMetadata
|
||||||
import eu.kanade.domain.manga.interactor.SetMangaFilteredScanlators
|
import eu.kanade.domain.manga.interactor.SetMangaFilteredScanlators
|
||||||
|
import eu.kanade.domain.manga.repository.FavoritesEntryRepository
|
||||||
import eu.kanade.domain.manga.repository.MangaMergeRepository
|
import eu.kanade.domain.manga.repository.MangaMergeRepository
|
||||||
import eu.kanade.domain.manga.repository.MangaMetadataRepository
|
import eu.kanade.domain.manga.repository.MangaMetadataRepository
|
||||||
import eu.kanade.domain.source.interactor.GetShowLatest
|
import eu.kanade.domain.source.interactor.GetShowLatest
|
||||||
@ -31,15 +42,26 @@ class SYDomainModule : InjektModule {
|
|||||||
addFactory { SetSourceCategories(get()) }
|
addFactory { SetSourceCategories(get()) }
|
||||||
addFactory { ToggleSources(get()) }
|
addFactory { ToggleSources(get()) }
|
||||||
addFactory { SetMangaFilteredScanlators(get()) }
|
addFactory { SetMangaFilteredScanlators(get()) }
|
||||||
addFactory { GetMangaByUrlAndSource(get()) }
|
addFactory { GetAllManga(get()) }
|
||||||
|
addFactory { GetMangaBySource(get()) }
|
||||||
|
|
||||||
addSingletonFactory<MangaMetadataRepository> { MangaMetadataRepositoryImpl(get()) }
|
addSingletonFactory<MangaMetadataRepository> { MangaMetadataRepositoryImpl(get()) }
|
||||||
addFactory { GetFlatMetadataById(get()) }
|
addFactory { GetFlatMetadataById(get()) }
|
||||||
|
addFactory { InsertFlatMetadata(get()) }
|
||||||
|
addFactory { GetExhFavoriteMangaWithMetadata(get()) }
|
||||||
|
addFactory { GetSearchTags(get()) }
|
||||||
|
addFactory { GetSearchTitles(get()) }
|
||||||
|
addFactory { GetIdsOfFavoriteMangaWithMetadata(get()) }
|
||||||
|
|
||||||
addSingletonFactory<MangaMergeRepository> { MangaMergeRepositoryImpl(get()) }
|
addSingletonFactory<MangaMergeRepository> { MangaMergeRepositoryImpl(get()) }
|
||||||
addFactory { GetMergedManga(get()) }
|
addFactory { GetMergedManga(get()) }
|
||||||
addFactory { GetMergedMangaById(get()) }
|
addFactory { GetMergedMangaById(get()) }
|
||||||
addFactory { GetMergedReferencesById(get()) }
|
addFactory { GetMergedReferencesById(get()) }
|
||||||
addFactory { GetMergedChapterByMangaId(get()) }
|
addFactory { GetMergedChapterByMangaId(get()) }
|
||||||
|
|
||||||
|
addSingletonFactory<FavoritesEntryRepository> { FavoritesEntryRepositoryImpl(get()) }
|
||||||
|
addFactory { GetFavoriteEntries(get()) }
|
||||||
|
addFactory { InsertFavoriteEntries(get()) }
|
||||||
|
addFactory { DeleteFavoriteEntries(get()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package eu.kanade.domain.manga.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.manga.repository.FavoritesEntryRepository
|
||||||
|
|
||||||
|
class DeleteFavoriteEntries(
|
||||||
|
private val favoriteEntryRepository: FavoritesEntryRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await() {
|
||||||
|
return favoriteEntryRepository.deleteAll()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package eu.kanade.domain.manga.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.manga.model.Manga
|
||||||
|
import eu.kanade.domain.manga.repository.MangaRepository
|
||||||
|
|
||||||
|
class GetAllManga(
|
||||||
|
private val mangaRepository: MangaRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(): List<Manga> {
|
||||||
|
return mangaRepository.getAll()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package eu.kanade.domain.manga.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.manga.model.Manga
|
||||||
|
import eu.kanade.domain.manga.repository.MangaMetadataRepository
|
||||||
|
|
||||||
|
class GetExhFavoriteMangaWithMetadata(
|
||||||
|
private val mangaMetadataRepository: MangaMetadataRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(): List<Manga> {
|
||||||
|
return mangaMetadataRepository.getExhFavoriteMangaWithMetadata()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package eu.kanade.domain.manga.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.manga.repository.FavoritesEntryRepository
|
||||||
|
import exh.favorites.sql.models.FavoriteEntry
|
||||||
|
|
||||||
|
class GetFavoriteEntries(
|
||||||
|
private val favoriteEntryRepository: FavoritesEntryRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(): List<FavoriteEntry> {
|
||||||
|
return favoriteEntryRepository.selectAll()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package eu.kanade.domain.manga.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.manga.repository.MangaMetadataRepository
|
||||||
|
|
||||||
|
class GetIdsOfFavoriteMangaWithMetadata(
|
||||||
|
private val mangaMetadataRepository: MangaMetadataRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(): List<Long> {
|
||||||
|
return mangaMetadataRepository.getIdsOfFavoriteMangaWithMetadata()
|
||||||
|
}
|
||||||
|
}
|
@ -6,10 +6,23 @@ import eu.kanade.tachiyomi.util.system.logcat
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
|
|
||||||
class GetMangaByUrlAndSource(
|
class GetManga(
|
||||||
private val mangaRepository: MangaRepository,
|
private val mangaRepository: MangaRepository,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
suspend fun await(id: Long): Manga? {
|
||||||
|
return try {
|
||||||
|
mangaRepository.getMangaById(id)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun subscribe(id: Long): Flow<Manga> {
|
||||||
|
return mangaRepository.subscribeMangaById(id)
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun await(url: String, sourceId: Long): Manga? {
|
suspend fun await(url: String, sourceId: Long): Manga? {
|
||||||
return try {
|
return try {
|
||||||
mangaRepository.getMangaByUrlAndSource(url, sourceId)
|
mangaRepository.getMangaByUrlAndSource(url, sourceId)
|
@ -1,25 +0,0 @@
|
|||||||
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 GetMangaById(
|
|
||||||
private val mangaRepository: MangaRepository,
|
|
||||||
) {
|
|
||||||
|
|
||||||
suspend fun await(id: Long): Manga? {
|
|
||||||
return try {
|
|
||||||
mangaRepository.getMangaById(id)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logcat(LogPriority.ERROR, e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun subscribe(id: Long): Flow<Manga> {
|
|
||||||
return mangaRepository.subscribeMangaById(id)
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,13 @@
|
|||||||
|
package eu.kanade.domain.manga.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.manga.model.Manga
|
||||||
|
import eu.kanade.domain.manga.repository.MangaRepository
|
||||||
|
|
||||||
|
class GetMangaBySource(
|
||||||
|
private val mangaRepository: MangaRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(sourceId: Long): List<Manga> {
|
||||||
|
return mangaRepository.getMangaBySource(sourceId)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package eu.kanade.domain.manga.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.manga.repository.MangaMetadataRepository
|
||||||
|
import exh.metadata.sql.models.SearchMetadata
|
||||||
|
|
||||||
|
class GetSearchMetadata(
|
||||||
|
private val mangaMetadataRepository: MangaMetadataRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(mangaId: Long): SearchMetadata? {
|
||||||
|
return mangaMetadataRepository.getMetadataById(mangaId)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun await(): List<SearchMetadata> {
|
||||||
|
return mangaMetadataRepository.getSearchMetadata()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package eu.kanade.domain.manga.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.manga.repository.MangaMetadataRepository
|
||||||
|
import exh.metadata.sql.models.SearchTag
|
||||||
|
|
||||||
|
class GetSearchTags(
|
||||||
|
private val mangaMetadataRepository: MangaMetadataRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(mangaId: Long): List<SearchTag> {
|
||||||
|
return mangaMetadataRepository.getTagsById(mangaId)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package eu.kanade.domain.manga.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.manga.repository.MangaMetadataRepository
|
||||||
|
import exh.metadata.sql.models.SearchTitle
|
||||||
|
|
||||||
|
class GetSearchTitles(
|
||||||
|
private val mangaMetadataRepository: MangaMetadataRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(mangaId: Long): List<SearchTitle> {
|
||||||
|
return mangaMetadataRepository.getTitlesById(mangaId)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package eu.kanade.domain.manga.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.manga.repository.FavoritesEntryRepository
|
||||||
|
import exh.favorites.sql.models.FavoriteEntry
|
||||||
|
|
||||||
|
class InsertFavoriteEntries(
|
||||||
|
private val favoriteEntryRepository: FavoritesEntryRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(entries: List<FavoriteEntry>) {
|
||||||
|
return favoriteEntryRepository.insertAll(entries)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package eu.kanade.domain.manga.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.manga.repository.MangaMetadataRepository
|
||||||
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
|
import exh.metadata.metadata.base.FlatMetadata
|
||||||
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
|
import logcat.LogPriority
|
||||||
|
|
||||||
|
class InsertFlatMetadata(
|
||||||
|
private val mangaMetadataRepository: MangaMetadataRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(flatMetadata: FlatMetadata) {
|
||||||
|
try {
|
||||||
|
mangaMetadataRepository.insertFlatMetadata(flatMetadata)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun await(metadata: RaisedSearchMetadata) {
|
||||||
|
try {
|
||||||
|
mangaMetadataRepository.insertMetadata(metadata)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package eu.kanade.domain.manga.model
|
||||||
|
|
||||||
|
data class MergeMangaSettingsUpdate(
|
||||||
|
val id: Long,
|
||||||
|
var isInfoManga: Boolean?,
|
||||||
|
var getChapterUpdates: Boolean?,
|
||||||
|
var chapterPriority: Int?,
|
||||||
|
var downloadChapters: Boolean?,
|
||||||
|
)
|
@ -0,0 +1,11 @@
|
|||||||
|
package eu.kanade.domain.manga.repository
|
||||||
|
|
||||||
|
import exh.favorites.sql.models.FavoriteEntry
|
||||||
|
|
||||||
|
interface FavoritesEntryRepository {
|
||||||
|
suspend fun deleteAll()
|
||||||
|
|
||||||
|
suspend fun insertAll(favoriteEntries: List<FavoriteEntry>)
|
||||||
|
|
||||||
|
suspend fun selectAll(): List<FavoriteEntry>
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package eu.kanade.domain.manga.repository
|
package eu.kanade.domain.manga.repository
|
||||||
|
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
|
import eu.kanade.domain.manga.model.MergeMangaSettingsUpdate
|
||||||
import exh.merged.sql.models.MergedMangaReference
|
import exh.merged.sql.models.MergedMangaReference
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@ -16,4 +17,8 @@ interface MangaMergeRepository {
|
|||||||
suspend fun getReferencesById(id: Long): List<MergedMangaReference>
|
suspend fun getReferencesById(id: Long): List<MergedMangaReference>
|
||||||
|
|
||||||
suspend fun subscribeReferencesById(id: Long): Flow<List<MergedMangaReference>>
|
suspend fun subscribeReferencesById(id: Long): Flow<List<MergedMangaReference>>
|
||||||
|
|
||||||
|
suspend fun updateSettings(update: MergeMangaSettingsUpdate): Boolean
|
||||||
|
|
||||||
|
suspend fun updateAllSettings(values: List<MergeMangaSettingsUpdate>): Boolean
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package eu.kanade.domain.manga.repository
|
package eu.kanade.domain.manga.repository
|
||||||
|
|
||||||
|
import eu.kanade.domain.manga.model.Manga
|
||||||
|
import exh.metadata.metadata.base.FlatMetadata
|
||||||
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import exh.metadata.sql.models.SearchMetadata
|
import exh.metadata.sql.models.SearchMetadata
|
||||||
import exh.metadata.sql.models.SearchTag
|
import exh.metadata.sql.models.SearchTag
|
||||||
import exh.metadata.sql.models.SearchTitle
|
import exh.metadata.sql.models.SearchTitle
|
||||||
@ -17,4 +20,14 @@ interface MangaMetadataRepository {
|
|||||||
suspend fun getTitlesById(id: Long): List<SearchTitle>
|
suspend fun getTitlesById(id: Long): List<SearchTitle>
|
||||||
|
|
||||||
suspend fun subscribeTitlesById(id: Long): Flow<List<SearchTitle>>
|
suspend fun subscribeTitlesById(id: Long): Flow<List<SearchTitle>>
|
||||||
|
|
||||||
|
suspend fun insertFlatMetadata(flatMetadata: FlatMetadata)
|
||||||
|
|
||||||
|
suspend fun insertMetadata(metadata: RaisedSearchMetadata) = insertFlatMetadata(metadata.flatten())
|
||||||
|
|
||||||
|
suspend fun getExhFavoriteMangaWithMetadata(): List<Manga>
|
||||||
|
|
||||||
|
suspend fun getIdsOfFavoriteMangaWithMetadata(): List<Long>
|
||||||
|
|
||||||
|
suspend fun getSearchMetadata(): List<SearchMetadata>
|
||||||
}
|
}
|
||||||
|
@ -29,4 +29,8 @@ interface MangaRepository {
|
|||||||
suspend fun update(update: MangaUpdate): Boolean
|
suspend fun update(update: MangaUpdate): Boolean
|
||||||
|
|
||||||
suspend fun updateAll(values: List<MangaUpdate>): Boolean
|
suspend fun updateAll(values: List<MangaUpdate>): Boolean
|
||||||
|
|
||||||
|
suspend fun getMangaBySource(sourceId: Long): List<Manga>
|
||||||
|
|
||||||
|
suspend fun getAll(): List<Manga>
|
||||||
}
|
}
|
||||||
|
@ -14,31 +14,11 @@ import eu.kanade.tachiyomi.data.database.models.History
|
|||||||
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.queries.CategoryQueries
|
|
||||||
import eu.kanade.tachiyomi.data.database.queries.ChapterQueries
|
import eu.kanade.tachiyomi.data.database.queries.ChapterQueries
|
||||||
import eu.kanade.tachiyomi.data.database.queries.HistoryQueries
|
|
||||||
import eu.kanade.tachiyomi.data.database.queries.MangaCategoryQueries
|
|
||||||
import eu.kanade.tachiyomi.data.database.queries.MangaQueries
|
import eu.kanade.tachiyomi.data.database.queries.MangaQueries
|
||||||
import eu.kanade.tachiyomi.data.database.queries.TrackQueries
|
|
||||||
import exh.favorites.sql.mappers.FavoriteEntryTypeMapping
|
|
||||||
import exh.favorites.sql.models.FavoriteEntry
|
|
||||||
import exh.favorites.sql.queries.FavoriteEntryQueries
|
|
||||||
import exh.merged.sql.mappers.MergedMangaTypeMapping
|
import exh.merged.sql.mappers.MergedMangaTypeMapping
|
||||||
import exh.merged.sql.models.MergedMangaReference
|
import exh.merged.sql.models.MergedMangaReference
|
||||||
import exh.merged.sql.queries.MergedQueries
|
import exh.merged.sql.queries.MergedQueries
|
||||||
import exh.metadata.sql.mappers.SearchMetadataTypeMapping
|
|
||||||
import exh.metadata.sql.mappers.SearchTagTypeMapping
|
|
||||||
import exh.metadata.sql.mappers.SearchTitleTypeMapping
|
|
||||||
import exh.metadata.sql.models.SearchMetadata
|
|
||||||
import exh.metadata.sql.models.SearchTag
|
|
||||||
import exh.metadata.sql.models.SearchTitle
|
|
||||||
import exh.metadata.sql.queries.SearchMetadataQueries
|
|
||||||
import exh.metadata.sql.queries.SearchTagQueries
|
|
||||||
import exh.metadata.sql.queries.SearchTitleQueries
|
|
||||||
import exh.savedsearches.mappers.FeedSavedSearchTypeMapping
|
|
||||||
import exh.savedsearches.mappers.SavedSearchTypeMapping
|
|
||||||
import exh.savedsearches.models.FeedSavedSearch
|
|
||||||
import exh.savedsearches.models.SavedSearch
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides operations to manage the database through its interfaces.
|
* This class provides operations to manage the database through its interfaces.
|
||||||
@ -48,16 +28,8 @@ class DatabaseHelper(
|
|||||||
) :
|
) :
|
||||||
MangaQueries,
|
MangaQueries,
|
||||||
ChapterQueries,
|
ChapterQueries,
|
||||||
TrackQueries,
|
|
||||||
CategoryQueries,
|
|
||||||
MangaCategoryQueries,
|
|
||||||
HistoryQueries,
|
|
||||||
/* SY --> */
|
/* SY --> */
|
||||||
SearchMetadataQueries,
|
MergedQueries
|
||||||
SearchTagQueries,
|
|
||||||
SearchTitleQueries,
|
|
||||||
MergedQueries,
|
|
||||||
FavoriteEntryQueries
|
|
||||||
/* SY <-- */ {
|
/* SY <-- */ {
|
||||||
|
|
||||||
override val db = DefaultStorIOSQLite.builder()
|
override val db = DefaultStorIOSQLite.builder()
|
||||||
@ -69,13 +41,7 @@ class DatabaseHelper(
|
|||||||
.addTypeMapping(MangaCategory::class.java, MangaCategoryTypeMapping())
|
.addTypeMapping(MangaCategory::class.java, MangaCategoryTypeMapping())
|
||||||
.addTypeMapping(History::class.java, HistoryTypeMapping())
|
.addTypeMapping(History::class.java, HistoryTypeMapping())
|
||||||
// SY -->
|
// SY -->
|
||||||
.addTypeMapping(SearchMetadata::class.java, SearchMetadataTypeMapping())
|
|
||||||
.addTypeMapping(SearchTag::class.java, SearchTagTypeMapping())
|
|
||||||
.addTypeMapping(SearchTitle::class.java, SearchTitleTypeMapping())
|
|
||||||
.addTypeMapping(MergedMangaReference::class.java, MergedMangaTypeMapping())
|
.addTypeMapping(MergedMangaReference::class.java, MergedMangaTypeMapping())
|
||||||
.addTypeMapping(FavoriteEntry::class.java, FavoriteEntryTypeMapping())
|
|
||||||
.addTypeMapping(SavedSearch::class.java, SavedSearchTypeMapping())
|
|
||||||
.addTypeMapping(FeedSavedSearch::class.java, FeedSavedSearchTypeMapping())
|
|
||||||
// SY <--
|
// SY <--
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.data.database.queries
|
|
||||||
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.RawQuery
|
|
||||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Category
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
|
||||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable
|
|
||||||
|
|
||||||
interface CategoryQueries : DbProvider {
|
|
||||||
|
|
||||||
fun getCategories() = db.get()
|
|
||||||
.listOfObjects(Category::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(CategoryTable.TABLE)
|
|
||||||
.orderBy(CategoryTable.COL_ORDER)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun getCategoriesForManga(manga: Manga) = db.get()
|
|
||||||
.listOfObjects(Category::class.java)
|
|
||||||
.withQuery(
|
|
||||||
RawQuery.builder()
|
|
||||||
.query(getCategoriesForMangaQuery())
|
|
||||||
.args(manga.id)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun insertCategories(categories: List<Category>) = db.put().objects(categories).prepare()
|
|
||||||
}
|
|
@ -23,54 +23,6 @@ interface ChapterQueries : DbProvider {
|
|||||||
.prepare()
|
.prepare()
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
fun getChapter(id: Long) = db.get()
|
|
||||||
.`object`(Chapter::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(ChapterTable.TABLE)
|
|
||||||
.where("${ChapterTable.COL_ID} = ?")
|
|
||||||
.whereArgs(id)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun getChapter(url: String, mangaId: Long) = db.get()
|
|
||||||
.`object`(Chapter::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(ChapterTable.TABLE)
|
|
||||||
.where("${ChapterTable.COL_URL} = ? AND ${ChapterTable.COL_MANGA_ID} = ?")
|
|
||||||
.whereArgs(url, mangaId)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
// SY -->
|
|
||||||
fun getChapters(url: String) = db.get()
|
|
||||||
.listOfObjects(Chapter::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(ChapterTable.TABLE)
|
|
||||||
.where("${ChapterTable.COL_URL} = ?")
|
|
||||||
.whereArgs(url)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun getChaptersReadByUrls(urls: List<String>) = db.get()
|
|
||||||
.listOfObjects(Chapter::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(ChapterTable.TABLE)
|
|
||||||
.where("${ChapterTable.COL_URL} IN (?) AND (${ChapterTable.COL_READ} = 1 OR ${ChapterTable.COL_LAST_PAGE_READ} != 0)")
|
|
||||||
.whereArgs(urls.joinToString { "\"$it\"" })
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
// SY <--
|
|
||||||
|
|
||||||
fun insertChapters(chapters: List<Chapter>) = db.put().objects(chapters).prepare()
|
|
||||||
|
|
||||||
fun deleteChapters(chapters: List<Chapter>) = db.delete().objects(chapters).prepare()
|
fun deleteChapters(chapters: List<Chapter>) = db.delete().objects(chapters).prepare()
|
||||||
|
|
||||||
fun updateChapterProgress(chapter: Chapter) = db.put()
|
fun updateChapterProgress(chapter: Chapter) = db.put()
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.data.database.queries
|
|
||||||
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.RawQuery
|
|
||||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.History
|
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.HistoryChapterIdPutResolver
|
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.HistoryUpsertResolver
|
|
||||||
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
|
|
||||||
|
|
||||||
interface HistoryQueries : DbProvider {
|
|
||||||
|
|
||||||
fun getHistoryByMangaId(mangaId: Long) = db.get()
|
|
||||||
.listOfObjects(History::class.java)
|
|
||||||
.withQuery(
|
|
||||||
RawQuery.builder()
|
|
||||||
.query(getHistoryByMangaId())
|
|
||||||
.args(mangaId)
|
|
||||||
.observesTables(HistoryTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the history last read.
|
|
||||||
* Inserts history object if not yet in database
|
|
||||||
* @param historyList history object list
|
|
||||||
*/
|
|
||||||
fun upsertHistoryLastRead(historyList: List<History>) = db.put()
|
|
||||||
.objects(historyList)
|
|
||||||
.withPutResolver(HistoryUpsertResolver())
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
// SY -->
|
|
||||||
fun updateHistoryChapterIds(history: List<History>) = db.put()
|
|
||||||
.objects(history)
|
|
||||||
.withPutResolver(HistoryChapterIdPutResolver())
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun deleteHistoryIds(ids: List<Long>) = db.delete()
|
|
||||||
.byQuery(
|
|
||||||
DeleteQuery.builder()
|
|
||||||
.table(HistoryTable.TABLE)
|
|
||||||
.where("${HistoryTable.COL_ID} IN (?)")
|
|
||||||
.whereArgs(ids.joinToString())
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
// SY <--
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.data.database.queries
|
|
||||||
|
|
||||||
import com.pushtorefresh.storio.Queries
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
|
||||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
|
||||||
import eu.kanade.tachiyomi.data.database.inTransaction
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaCategory
|
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable
|
|
||||||
|
|
||||||
interface MangaCategoryQueries : DbProvider {
|
|
||||||
|
|
||||||
fun insertMangasCategories(mangasCategories: List<MangaCategory>) = db.put().objects(mangasCategories).prepare()
|
|
||||||
|
|
||||||
fun deleteOldMangasCategories(mangas: List<Manga>) = db.delete()
|
|
||||||
.byQuery(
|
|
||||||
DeleteQuery.builder()
|
|
||||||
.table(MangaCategoryTable.TABLE)
|
|
||||||
.where("${MangaCategoryTable.COL_MANGA_ID} IN (${Queries.placeholders(mangas.size)})")
|
|
||||||
.whereArgs(*mangas.map { it.id }.toTypedArray())
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun setMangaCategories(mangasCategories: List<MangaCategory>, mangas: List<Manga>) {
|
|
||||||
db.inTransaction {
|
|
||||||
// SY -->
|
|
||||||
mangas.chunked(100) { chunk ->
|
|
||||||
deleteOldMangasCategories(chunk).executeAsBlocking()
|
|
||||||
}
|
|
||||||
mangasCategories.chunked(100) { chunk ->
|
|
||||||
insertMangasCategories(chunk).executeAsBlocking()
|
|
||||||
}
|
|
||||||
// SY <--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,17 +6,11 @@ import eu.kanade.tachiyomi.data.database.DbProvider
|
|||||||
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
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.resolvers.LibraryMangaGetResolver
|
import eu.kanade.tachiyomi.data.database.resolvers.LibraryMangaGetResolver
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaFavoritePutResolver
|
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaFilteredScanlatorsPutResolver
|
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaFlagsPutResolver
|
import eu.kanade.tachiyomi.data.database.resolvers.MangaFlagsPutResolver
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaInfoPutResolver
|
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaMigrationPutResolver
|
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaThumbnailPutResolver
|
|
||||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable
|
import eu.kanade.tachiyomi.data.database.tables.CategoryTable
|
||||||
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
|
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable
|
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
||||||
import exh.metadata.sql.tables.SearchMetadataTable
|
|
||||||
|
|
||||||
interface MangaQueries : DbProvider {
|
interface MangaQueries : DbProvider {
|
||||||
|
|
||||||
@ -64,50 +58,8 @@ interface MangaQueries : DbProvider {
|
|||||||
)
|
)
|
||||||
.prepare()
|
.prepare()
|
||||||
|
|
||||||
// SY -->
|
|
||||||
fun getMangas() = db.get()
|
|
||||||
.listOfObjects(Manga::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(MangaTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun getReadNotInLibraryMangas() = db.get()
|
|
||||||
.listOfObjects(Manga::class.java)
|
|
||||||
.withQuery(
|
|
||||||
RawQuery.builder()
|
|
||||||
.query(getReadMangaNotInLibraryQuery())
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun updateMangaInfo(manga: Manga) = db.put()
|
|
||||||
.`object`(manga)
|
|
||||||
.withPutResolver(MangaInfoPutResolver())
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun resetMangaInfo(manga: Manga) = db.put()
|
|
||||||
.`object`(manga)
|
|
||||||
.withPutResolver(MangaInfoPutResolver(true))
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun updateMangaMigrate(manga: Manga) = db.put()
|
|
||||||
.`object`(manga)
|
|
||||||
.withPutResolver(MangaMigrationPutResolver())
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun updateMangaThumbnail(manga: Manga) = db.put()
|
|
||||||
.`object`(manga)
|
|
||||||
.withPutResolver(MangaThumbnailPutResolver())
|
|
||||||
.prepare()
|
|
||||||
// SY <--
|
|
||||||
|
|
||||||
fun insertManga(manga: Manga) = db.put().`object`(manga).prepare()
|
fun insertManga(manga: Manga) = db.put().`object`(manga).prepare()
|
||||||
|
|
||||||
fun insertMangas(mangas: List<Manga>) = db.put().objects(mangas).prepare()
|
|
||||||
|
|
||||||
fun updateChapterFlags(manga: Manga) = db.put()
|
fun updateChapterFlags(manga: Manga) = db.put()
|
||||||
.`object`(manga)
|
.`object`(manga)
|
||||||
.withPutResolver(MangaFlagsPutResolver(MangaTable.COL_CHAPTER_FLAGS, Manga::chapter_flags))
|
.withPutResolver(MangaFlagsPutResolver(MangaTable.COL_CHAPTER_FLAGS, Manga::chapter_flags))
|
||||||
@ -123,69 +75,5 @@ interface MangaQueries : DbProvider {
|
|||||||
.withPutResolver(MangaFlagsPutResolver(MangaTable.COL_VIEWER, Manga::viewer_flags))
|
.withPutResolver(MangaFlagsPutResolver(MangaTable.COL_VIEWER, Manga::viewer_flags))
|
||||||
.prepare()
|
.prepare()
|
||||||
|
|
||||||
fun updateMangaFavorite(manga: Manga) = db.put()
|
|
||||||
.`object`(manga)
|
|
||||||
.withPutResolver(MangaFavoritePutResolver())
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
// SY -->
|
|
||||||
fun updateMangaFilteredScanlators(manga: Manga) = db.put()
|
|
||||||
.`object`(manga)
|
|
||||||
.withPutResolver(MangaFilteredScanlatorsPutResolver())
|
|
||||||
.prepare()
|
|
||||||
// SY <--
|
|
||||||
|
|
||||||
fun deleteManga(manga: Manga) = db.delete().`object`(manga).prepare()
|
fun deleteManga(manga: Manga) = db.delete().`object`(manga).prepare()
|
||||||
|
|
||||||
// SY -->
|
|
||||||
fun getMangaWithMetadata() = db.get()
|
|
||||||
.listOfObjects(Manga::class.java)
|
|
||||||
.withQuery(
|
|
||||||
RawQuery.builder()
|
|
||||||
.query(
|
|
||||||
"""
|
|
||||||
SELECT ${MangaTable.TABLE}.* FROM ${MangaTable.TABLE}
|
|
||||||
INNER JOIN ${SearchMetadataTable.TABLE}
|
|
||||||
ON ${MangaTable.TABLE}.${MangaTable.COL_ID} = ${SearchMetadataTable.TABLE}.${SearchMetadataTable.COL_MANGA_ID}
|
|
||||||
ORDER BY ${MangaTable.TABLE}.${MangaTable.COL_ID}
|
|
||||||
""".trimIndent(),
|
|
||||||
)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun getFavoriteMangaWithMetadata() = db.get()
|
|
||||||
.listOfObjects(Manga::class.java)
|
|
||||||
.withQuery(
|
|
||||||
RawQuery.builder()
|
|
||||||
.query(
|
|
||||||
"""
|
|
||||||
SELECT ${MangaTable.TABLE}.* FROM ${MangaTable.TABLE}
|
|
||||||
INNER JOIN ${SearchMetadataTable.TABLE}
|
|
||||||
ON ${MangaTable.TABLE}.${MangaTable.COL_ID} = ${SearchMetadataTable.TABLE}.${SearchMetadataTable.COL_MANGA_ID}
|
|
||||||
WHERE ${MangaTable.TABLE}.${MangaTable.COL_FAVORITE} = 1
|
|
||||||
ORDER BY ${MangaTable.TABLE}.${MangaTable.COL_ID}
|
|
||||||
""".trimIndent(),
|
|
||||||
)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun getIdsOfFavoriteMangaWithMetadata() = db.get()
|
|
||||||
.cursor()
|
|
||||||
.withQuery(
|
|
||||||
RawQuery.builder()
|
|
||||||
.query(
|
|
||||||
"""
|
|
||||||
SELECT ${MangaTable.TABLE}.${MangaTable.COL_ID} FROM ${MangaTable.TABLE}
|
|
||||||
INNER JOIN ${SearchMetadataTable.TABLE}
|
|
||||||
ON ${MangaTable.TABLE}.${MangaTable.COL_ID} = ${SearchMetadataTable.TABLE}.${SearchMetadataTable.COL_MANGA_ID}
|
|
||||||
WHERE ${MangaTable.TABLE}.${MangaTable.COL_FAVORITE} = 1
|
|
||||||
ORDER BY ${MangaTable.TABLE}.${MangaTable.COL_ID}
|
|
||||||
""".trimIndent(),
|
|
||||||
)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
// SY <--
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package eu.kanade.tachiyomi.data.database.queries
|
package eu.kanade.tachiyomi.data.database.queries
|
||||||
|
|
||||||
import exh.source.MERGED_SOURCE_ID
|
import exh.source.MERGED_SOURCE_ID
|
||||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable as Category
|
|
||||||
import eu.kanade.tachiyomi.data.database.tables.ChapterTable as Chapter
|
import eu.kanade.tachiyomi.data.database.tables.ChapterTable as Chapter
|
||||||
import eu.kanade.tachiyomi.data.database.tables.HistoryTable as History
|
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable as MangaCategory
|
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable as MangaCategory
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable as Manga
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable as Manga
|
||||||
import exh.merged.sql.tables.MergedTable as Merged
|
import exh.merged.sql.tables.MergedTable as Merged
|
||||||
@ -74,18 +72,6 @@ fun getMergedChaptersQuery() =
|
|||||||
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = M.${Merged.COL_MANGA_ID}
|
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = M.${Merged.COL_MANGA_ID}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
/**
|
|
||||||
* Query to get manga that are not in library, but have read chapters
|
|
||||||
*/
|
|
||||||
fun getReadMangaNotInLibraryQuery() =
|
|
||||||
"""
|
|
||||||
SELECT ${Manga.TABLE}.*
|
|
||||||
FROM ${Manga.TABLE}
|
|
||||||
WHERE ${Manga.COL_FAVORITE} = 0 AND ${Manga.COL_ID} IN(
|
|
||||||
SELECT ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} FROM ${Chapter.TABLE} WHERE ${Chapter.COL_READ} = 1 OR ${Chapter.COL_LAST_PAGE_READ} != 0
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query to get the manga from the library, with their categories, read and unread count.
|
* Query to get the manga from the library, with their categories, read and unread count.
|
||||||
*/
|
*/
|
||||||
@ -142,24 +128,4 @@ val libraryQuery =
|
|||||||
ON MC.${MangaCategory.COL_MANGA_ID} = M.${Manga.COL_ID};
|
ON MC.${MangaCategory.COL_MANGA_ID} = M.${Manga.COL_ID};
|
||||||
"""
|
"""
|
||||||
|
|
||||||
fun getHistoryByMangaId() =
|
|
||||||
"""
|
|
||||||
SELECT ${History.TABLE}.*
|
|
||||||
FROM ${History.TABLE}
|
|
||||||
JOIN ${Chapter.TABLE}
|
|
||||||
ON ${History.TABLE}.${History.COL_CHAPTER_ID} = ${Chapter.TABLE}.${Chapter.COL_ID}
|
|
||||||
WHERE ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = ? AND ${History.TABLE}.${History.COL_CHAPTER_ID} = ${Chapter.TABLE}.${Chapter.COL_ID}
|
|
||||||
"""
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Query to get the categories for a manga.
|
|
||||||
*/
|
|
||||||
fun getCategoriesForMangaQuery() =
|
|
||||||
"""
|
|
||||||
SELECT ${Category.TABLE}.* FROM ${Category.TABLE}
|
|
||||||
JOIN ${MangaCategory.TABLE} ON ${Category.TABLE}.${Category.COL_ID} =
|
|
||||||
${MangaCategory.TABLE}.${MangaCategory.COL_CATEGORY_ID}
|
|
||||||
WHERE ${MangaCategory.COL_MANGA_ID} = ?
|
|
||||||
"""
|
|
||||||
|
|
||||||
// SY <--
|
// SY <--
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.data.database.queries
|
|
||||||
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
|
||||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Track
|
|
||||||
import eu.kanade.tachiyomi.data.database.tables.TrackTable
|
|
||||||
|
|
||||||
interface TrackQueries : DbProvider {
|
|
||||||
|
|
||||||
fun getTracks() = db.get()
|
|
||||||
.listOfObjects(Track::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(TrackTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun getTracks(mangaId: Long?) = db.get()
|
|
||||||
.listOfObjects(Track::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(TrackTable.TABLE)
|
|
||||||
.where("${TrackTable.COL_MANGA_ID} = ?")
|
|
||||||
.whereArgs(mangaId)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun insertTrack(track: Track) = db.put().`object`(track).prepare()
|
|
||||||
|
|
||||||
fun insertTracks(tracks: List<Track>) = db.put().objects(tracks).prepare()
|
|
||||||
}
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
|||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import eu.kanade.domain.chapter.interactor.GetChapter
|
import eu.kanade.domain.chapter.interactor.GetChapter
|
||||||
import eu.kanade.domain.chapter.model.toDbChapter
|
import eu.kanade.domain.chapter.model.toDbChapter
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.model.toDbManga
|
import eu.kanade.domain.manga.model.toDbManga
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.download.model.Download
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
@ -34,7 +34,7 @@ class DownloadStore(
|
|||||||
|
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
private val getMangaById: GetMangaById by injectLazy()
|
private val getManga: GetManga by injectLazy()
|
||||||
private val getChapter: GetChapter by injectLazy()
|
private val getChapter: GetChapter by injectLazy()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,7 +96,7 @@ class DownloadStore(
|
|||||||
val cachedManga = mutableMapOf<Long, Manga?>()
|
val cachedManga = mutableMapOf<Long, Manga?>()
|
||||||
for ((mangaId, chapterId) in objs) {
|
for ((mangaId, chapterId) in objs) {
|
||||||
val manga = cachedManga.getOrPut(mangaId) {
|
val manga = cachedManga.getOrPut(mangaId) {
|
||||||
runBlocking { getMangaById.await(mangaId)?.toDbManga() }
|
runBlocking { getManga.await(mangaId)?.toDbManga() }
|
||||||
} ?: continue
|
} ?: continue
|
||||||
val source = sourceManager.get(manga.source) as? HttpSource ?: continue
|
val source = sourceManager.get(manga.source) as? HttpSource ?: continue
|
||||||
val chapter = runBlocking { getChapter.await(chapterId) }?.toDbChapter() ?: continue
|
val chapter = runBlocking { getChapter.await(chapterId) }?.toDbChapter() ?: continue
|
||||||
|
@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.data.download.model
|
|||||||
|
|
||||||
import eu.kanade.domain.chapter.interactor.GetChapter
|
import eu.kanade.domain.chapter.interactor.GetChapter
|
||||||
import eu.kanade.domain.chapter.model.toDbChapter
|
import eu.kanade.domain.chapter.model.toDbChapter
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.model.toDbManga
|
import eu.kanade.domain.manga.model.toDbManga
|
||||||
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
|
||||||
@ -69,11 +69,11 @@ data class Download(
|
|||||||
suspend fun fromChapterId(
|
suspend fun fromChapterId(
|
||||||
chapterId: Long,
|
chapterId: Long,
|
||||||
getChapter: GetChapter = Injekt.get(),
|
getChapter: GetChapter = Injekt.get(),
|
||||||
getMangaById: GetMangaById = Injekt.get(),
|
getManga: GetManga = Injekt.get(),
|
||||||
sourceManager: SourceManager = Injekt.get(),
|
sourceManager: SourceManager = Injekt.get(),
|
||||||
): Download? {
|
): Download? {
|
||||||
val chapter = getChapter.await(chapterId) ?: return null
|
val chapter = getChapter.await(chapterId) ?: return null
|
||||||
val manga = getMangaById.await(chapter.mangaId) ?: return null
|
val manga = getManga.await(chapter.mangaId) ?: return null
|
||||||
val source = sourceManager.get(manga.source) as? HttpSource ?: return null
|
val source = sourceManager.get(manga.source) as? HttpSource ?: return null
|
||||||
|
|
||||||
return Download(source, manga.toDbManga(), chapter.toDbChapter())
|
return Download(source, manga.toDbManga(), chapter.toDbChapter())
|
||||||
|
@ -13,7 +13,9 @@ import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
|
|||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
|
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
|
||||||
import eu.kanade.domain.chapter.model.toDbChapter
|
import eu.kanade.domain.chapter.model.toDbChapter
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetFavorites
|
||||||
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
|
import eu.kanade.domain.manga.interactor.InsertFlatMetadata
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.manga.model.toDbManga
|
import eu.kanade.domain.manga.model.toDbManga
|
||||||
import eu.kanade.domain.manga.model.toMangaInfo
|
import eu.kanade.domain.manga.model.toMangaInfo
|
||||||
@ -61,7 +63,6 @@ import eu.kanade.tachiyomi.util.system.logcat
|
|||||||
import exh.log.xLogE
|
import exh.log.xLogE
|
||||||
import exh.md.utils.FollowStatus
|
import exh.md.utils.FollowStatus
|
||||||
import exh.md.utils.MdUtil
|
import exh.md.utils.MdUtil
|
||||||
import exh.metadata.metadata.base.insertFlatMetadataAsync
|
|
||||||
import exh.source.LIBRARY_UPDATE_EXCLUDED_SOURCES
|
import exh.source.LIBRARY_UPDATE_EXCLUDED_SOURCES
|
||||||
import exh.source.MERGED_SOURCE_ID
|
import exh.source.MERGED_SOURCE_ID
|
||||||
import exh.source.isMdBasedSource
|
import exh.source.isMdBasedSource
|
||||||
@ -77,6 +78,7 @@ import kotlinx.coroutines.async
|
|||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.supervisorScope
|
import kotlinx.coroutines.supervisorScope
|
||||||
import kotlinx.coroutines.sync.Semaphore
|
import kotlinx.coroutines.sync.Semaphore
|
||||||
import kotlinx.coroutines.sync.withPermit
|
import kotlinx.coroutines.sync.withPermit
|
||||||
@ -106,7 +108,7 @@ class LibraryUpdateService(
|
|||||||
val downloadManager: DownloadManager = Injekt.get(),
|
val downloadManager: DownloadManager = Injekt.get(),
|
||||||
val trackManager: TrackManager = Injekt.get(),
|
val trackManager: TrackManager = Injekt.get(),
|
||||||
val coverCache: CoverCache = Injekt.get(),
|
val coverCache: CoverCache = Injekt.get(),
|
||||||
private val getMangaById: GetMangaById = Injekt.get(),
|
private val getManga: GetManga = Injekt.get(),
|
||||||
private val updateManga: UpdateManga = Injekt.get(),
|
private val updateManga: UpdateManga = Injekt.get(),
|
||||||
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
|
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
|
||||||
private val getCategories: GetCategories = Injekt.get(),
|
private val getCategories: GetCategories = Injekt.get(),
|
||||||
@ -114,6 +116,10 @@ class LibraryUpdateService(
|
|||||||
private val getTracks: GetTracks = Injekt.get(),
|
private val getTracks: GetTracks = Injekt.get(),
|
||||||
private val insertTrack: InsertTrack = Injekt.get(),
|
private val insertTrack: InsertTrack = Injekt.get(),
|
||||||
private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay = Injekt.get(),
|
private val syncChaptersWithTrackServiceTwoWay: SyncChaptersWithTrackServiceTwoWay = Injekt.get(),
|
||||||
|
// SY -->
|
||||||
|
private val getFavorites: GetFavorites = Injekt.get(),
|
||||||
|
private val insertFlatMetadata: InsertFlatMetadata = Injekt.get(),
|
||||||
|
// SY <--
|
||||||
) : Service() {
|
) : Service() {
|
||||||
|
|
||||||
private lateinit var wakeLock: PowerManager.WakeLock
|
private lateinit var wakeLock: PowerManager.WakeLock
|
||||||
@ -327,11 +333,11 @@ class LibraryUpdateService(
|
|||||||
when (group) {
|
when (group) {
|
||||||
LibraryGroup.BY_TRACK_STATUS -> {
|
LibraryGroup.BY_TRACK_STATUS -> {
|
||||||
val trackingExtra = groupExtra?.toIntOrNull() ?: -1
|
val trackingExtra = groupExtra?.toIntOrNull() ?: -1
|
||||||
val tracks = db.getTracks().executeAsBlocking().groupBy { it.manga_id }
|
val tracks = runBlocking { getTracks.await() }.groupBy { it.mangaId }
|
||||||
|
|
||||||
libraryManga.filter { manga ->
|
libraryManga.filter { manga ->
|
||||||
val status = tracks[manga.id]?.firstNotNullOfOrNull { track ->
|
val status = tracks[manga.id]?.firstNotNullOfOrNull { track ->
|
||||||
TrackStatus.parseTrackerStatus(track.sync_id.toLong(), track.status)
|
TrackStatus.parseTrackerStatus(track.syncId, track.status)
|
||||||
} ?: TrackStatus.OTHER
|
} ?: TrackStatus.OTHER
|
||||||
status.int == trackingExtra
|
status.int == trackingExtra
|
||||||
}
|
}
|
||||||
@ -404,7 +410,7 @@ class LibraryUpdateService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Don't continue to update if manga not in library
|
// Don't continue to update if manga not in library
|
||||||
manga.id?.let { getMangaById.await(it) } ?: return@forEach
|
manga.id?.let { getManga.await(it) } ?: return@forEach
|
||||||
|
|
||||||
withUpdateNotification(
|
withUpdateNotification(
|
||||||
currentlyUpdatingManga,
|
currentlyUpdatingManga,
|
||||||
@ -536,7 +542,7 @@ class LibraryUpdateService(
|
|||||||
val tracks = getTracks.await(manga.id)
|
val tracks = getTracks.await(manga.id)
|
||||||
if (tracks.isEmpty() || tracks.none { it.syncId == TrackManager.MDLIST }) {
|
if (tracks.isEmpty() || tracks.none { it.syncId == TrackManager.MDLIST }) {
|
||||||
val track = trackManager.mdList.createInitialTracker(manga.toDbManga())
|
val track = trackManager.mdList.createInitialTracker(manga.toDbManga())
|
||||||
db.insertTrack(trackManager.mdList.refresh(track)).executeAsBlocking()
|
insertTrack.await(trackManager.mdList.refresh(track).toDomainTrack(false)!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -550,7 +556,7 @@ class LibraryUpdateService(
|
|||||||
.map { it.toSChapter() }
|
.map { it.toSChapter() }
|
||||||
|
|
||||||
// Get manga from database to account for if it was removed during the update
|
// Get manga from database to account for if it was removed during the update
|
||||||
val dbManga = getMangaById.await(manga.id)
|
val dbManga = getManga.await(manga.id)
|
||||||
?: return Pair(emptyList(), emptyList())
|
?: return Pair(emptyList(), emptyList())
|
||||||
|
|
||||||
// [dbmanga] was used so that manga data doesn't get overwritten
|
// [dbmanga] was used so that manga data doesn't get overwritten
|
||||||
@ -724,7 +730,7 @@ class LibraryUpdateService(
|
|||||||
val id = db.insertManga(dbManga).executeOnIO().insertedId()
|
val id = db.insertManga(dbManga).executeOnIO().insertedId()
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
metadata.mangaId = id
|
metadata.mangaId = id
|
||||||
db.insertFlatMetadataAsync(metadata.flatten()).await()
|
insertFlatMetadata.await(metadata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -736,7 +742,7 @@ class LibraryUpdateService(
|
|||||||
*/
|
*/
|
||||||
private suspend fun pushFavorites() {
|
private suspend fun pushFavorites() {
|
||||||
var count = 0
|
var count = 0
|
||||||
val listManga = db.getFavoriteMangas().executeAsBlocking().filter { it.source in mangaDexSourceIds }
|
val listManga = getFavorites.await().filter { it.source in mangaDexSourceIds }
|
||||||
|
|
||||||
// filter all follows from Mangadex and only add reading or rereading manga to library
|
// filter all follows from Mangadex and only add reading or rereading manga to library
|
||||||
if (trackManager.mdList.isLogged) {
|
if (trackManager.mdList.isLogged) {
|
||||||
@ -746,18 +752,18 @@ class LibraryUpdateService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
count++
|
count++
|
||||||
notifier.showProgressNotification(listOf(manga), count, listManga.size)
|
notifier.showProgressNotification(listOf(manga.toDbManga()), count, listManga.size)
|
||||||
|
|
||||||
// Get this manga's trackers from the database
|
// Get this manga's trackers from the database
|
||||||
val dbTracks = getTracks.await(manga.id!!)
|
val dbTracks = getTracks.await(manga.id)
|
||||||
|
|
||||||
// find the mdlist entry if its unfollowed the follow it
|
// find the mdlist entry if its unfollowed the follow it
|
||||||
val tracker = TrackItem(dbTracks.firstOrNull { it.syncId == TrackManager.MDLIST }?.toDbTrack() ?: trackManager.mdList.createInitialTracker(manga), trackManager.mdList)
|
val tracker = TrackItem(dbTracks.firstOrNull { it.syncId == TrackManager.MDLIST }?.toDbTrack() ?: trackManager.mdList.createInitialTracker(manga.toDbManga()), trackManager.mdList)
|
||||||
|
|
||||||
if (tracker.track?.status == FollowStatus.UNFOLLOWED.int) {
|
if (tracker.track?.status == FollowStatus.UNFOLLOWED.int) {
|
||||||
tracker.track.status = FollowStatus.READING.int
|
tracker.track.status = FollowStatus.READING.int
|
||||||
val updatedTrack = tracker.service.update(tracker.track)
|
val updatedTrack = tracker.service.update(tracker.track)
|
||||||
db.insertTrack(updatedTrack).executeOnIO()
|
insertTrack.await(updatedTrack.toDomainTrack(false)!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import eu.kanade.domain.chapter.interactor.GetChapter
|
|||||||
import eu.kanade.domain.chapter.interactor.UpdateChapter
|
import eu.kanade.domain.chapter.interactor.UpdateChapter
|
||||||
import eu.kanade.domain.chapter.model.toChapterUpdate
|
import eu.kanade.domain.chapter.model.toChapterUpdate
|
||||||
import eu.kanade.domain.chapter.model.toDbChapter
|
import eu.kanade.domain.chapter.model.toDbChapter
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.model.toDbManga
|
import eu.kanade.domain.manga.model.toDbManga
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
|
import eu.kanade.tachiyomi.data.backup.BackupRestoreService
|
||||||
@ -46,7 +46,7 @@ import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
|
|||||||
*/
|
*/
|
||||||
class NotificationReceiver : BroadcastReceiver() {
|
class NotificationReceiver : BroadcastReceiver() {
|
||||||
|
|
||||||
private val getMangaById: GetMangaById by injectLazy()
|
private val getManga: GetManga by injectLazy()
|
||||||
private val getChapter: GetChapter by injectLazy()
|
private val getChapter: GetChapter by injectLazy()
|
||||||
private val updateChapter: UpdateChapter by injectLazy()
|
private val updateChapter: UpdateChapter by injectLazy()
|
||||||
private val downloadManager: DownloadManager by injectLazy()
|
private val downloadManager: DownloadManager by injectLazy()
|
||||||
@ -178,7 +178,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
* @param chapterId id of chapter
|
* @param chapterId id of chapter
|
||||||
*/
|
*/
|
||||||
private fun openChapter(context: Context, mangaId: Long, chapterId: Long) {
|
private fun openChapter(context: Context, mangaId: Long, chapterId: Long) {
|
||||||
val manga = runBlocking { getMangaById.await(mangaId) }
|
val manga = runBlocking { getManga.await(mangaId) }
|
||||||
val chapter = runBlocking { getChapter.await(chapterId) }
|
val chapter = runBlocking { getChapter.await(chapterId) }
|
||||||
if (manga != null && chapter != null) {
|
if (manga != null && chapter != null) {
|
||||||
val intent = ReaderActivity.newIntent(context, manga.id, chapter.id).apply {
|
val intent = ReaderActivity.newIntent(context, manga.id, chapter.id).apply {
|
||||||
@ -248,7 +248,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
.map {
|
.map {
|
||||||
val chapter = it.copy(read = true)
|
val chapter = it.copy(read = true)
|
||||||
if (preferences.removeAfterMarkedAsRead()) {
|
if (preferences.removeAfterMarkedAsRead()) {
|
||||||
val manga = getMangaById.await(mangaId)
|
val manga = getManga.await(mangaId)
|
||||||
if (manga != null) {
|
if (manga != null) {
|
||||||
val source = sourceManager.get(manga.source)
|
val source = sourceManager.get(manga.source)
|
||||||
if (source != null) {
|
if (source != null) {
|
||||||
@ -270,7 +270,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
*/
|
*/
|
||||||
private fun downloadChapters(chapterUrls: Array<String>, mangaId: Long) {
|
private fun downloadChapters(chapterUrls: Array<String>, mangaId: Long) {
|
||||||
launchIO {
|
launchIO {
|
||||||
val manga = getMangaById.await(mangaId)?.toDbManga()
|
val manga = getManga.await(mangaId)?.toDbManga()
|
||||||
val chapters = chapterUrls.mapNotNull { getChapter.await(it, mangaId)?.toDbChapter() }
|
val chapters = chapterUrls.mapNotNull { getChapter.await(it, mangaId)?.toDbChapter() }
|
||||||
if (manga != null && chapters.isNotEmpty()) {
|
if (manga != null && chapters.isNotEmpty()) {
|
||||||
downloadManager.downloadChapters(manga, chapters)
|
downloadManager.downloadChapters(manga, chapters)
|
||||||
|
@ -21,7 +21,8 @@ enum class TrackStatus(val int: Int, @StringRes val res: Int) {
|
|||||||
OTHER(7, R.string.not_tracked);
|
OTHER(7, R.string.not_tracked);
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun parseTrackerStatus(tracker: Long, status: Int): TrackStatus? {
|
fun parseTrackerStatus(tracker: Long, statusLong: Long): TrackStatus? {
|
||||||
|
val status = statusLong.toInt()
|
||||||
return when (tracker) {
|
return when (tracker) {
|
||||||
TrackManager.MDLIST -> {
|
TrackManager.MDLIST -> {
|
||||||
when (FollowStatus.fromInt(status)) {
|
when (FollowStatus.fromInt(status)) {
|
||||||
|
@ -9,7 +9,7 @@ import androidx.work.NetworkType
|
|||||||
import androidx.work.OneTimeWorkRequestBuilder
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.track.interactor.GetTracks
|
import eu.kanade.domain.track.interactor.GetTracks
|
||||||
import eu.kanade.domain.track.interactor.InsertTrack
|
import eu.kanade.domain.track.interactor.InsertTrack
|
||||||
import eu.kanade.domain.track.model.toDbTrack
|
import eu.kanade.domain.track.model.toDbTrack
|
||||||
@ -26,7 +26,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters)
|
|||||||
CoroutineWorker(context, workerParams) {
|
CoroutineWorker(context, workerParams) {
|
||||||
|
|
||||||
override suspend fun doWork(): Result {
|
override suspend fun doWork(): Result {
|
||||||
val getMangaById = Injekt.get<GetMangaById>()
|
val getManga = Injekt.get<GetManga>()
|
||||||
val getTracks = Injekt.get<GetTracks>()
|
val getTracks = Injekt.get<GetTracks>()
|
||||||
val insertTrack = Injekt.get<InsertTrack>()
|
val insertTrack = Injekt.get<InsertTrack>()
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters)
|
|||||||
|
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val tracks = delayedTrackingStore.getItems().mapNotNull {
|
val tracks = delayedTrackingStore.getItems().mapNotNull {
|
||||||
val manga = getMangaById.await(it.mangaId) ?: return@withContext
|
val manga = getManga.await(it.mangaId) ?: return@withContext
|
||||||
getTracks.await(manga.id)
|
getTracks.await(manga.id)
|
||||||
.find { track -> track.id == it.trackId }
|
.find { track -> track.id == it.trackId }
|
||||||
?.copy(lastChapterRead = it.lastChapterRead.toDouble())
|
?.copy(lastChapterRead = it.lastChapterRead.toDouble())
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package eu.kanade.tachiyomi.source.online
|
package eu.kanade.tachiyomi.source.online
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import eu.kanade.data.DatabaseHandler
|
import eu.kanade.domain.manga.interactor.GetFlatMetadataById
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaByUrlAndSource
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.domain.manga.interactor.InsertFlatMetadata
|
||||||
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.source.CatalogueSource
|
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
@ -14,8 +14,6 @@ import eu.kanade.tachiyomi.ui.manga.MangaScreenState
|
|||||||
import eu.kanade.tachiyomi.util.lang.awaitSingle
|
import eu.kanade.tachiyomi.util.lang.awaitSingle
|
||||||
import eu.kanade.tachiyomi.util.lang.runAsObservable
|
import eu.kanade.tachiyomi.util.lang.runAsObservable
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import exh.metadata.metadata.base.awaitFlatMetadataForManga
|
|
||||||
import exh.metadata.metadata.base.awaitInsertFlatMetadata
|
|
||||||
import rx.Completable
|
import rx.Completable
|
||||||
import rx.Single
|
import rx.Single
|
||||||
import tachiyomi.source.model.MangaInfo
|
import tachiyomi.source.model.MangaInfo
|
||||||
@ -27,9 +25,9 @@ import kotlin.reflect.KClass
|
|||||||
* LEWD!
|
* LEWD!
|
||||||
*/
|
*/
|
||||||
interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
|
interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
|
||||||
val db: DatabaseHelper get() = Injekt.get()
|
val getManga: GetManga get() = Injekt.get()
|
||||||
val handler: DatabaseHandler get() = Injekt.get()
|
val insertFlatMetadata: InsertFlatMetadata get() = Injekt.get()
|
||||||
val getMangaByUrlAndSource: GetMangaByUrlAndSource get() = Injekt.get()
|
val getFlatMetadataById: GetFlatMetadataById get() = Injekt.get()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The class of the metadata used by this source
|
* The class of the metadata used by this source
|
||||||
@ -63,14 +61,14 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
|
|||||||
suspend fun parseToManga(manga: MangaInfo, input: I): MangaInfo {
|
suspend fun parseToManga(manga: MangaInfo, input: I): MangaInfo {
|
||||||
val mangaId = manga.id()
|
val mangaId = manga.id()
|
||||||
val metadata = if (mangaId != null) {
|
val metadata = if (mangaId != null) {
|
||||||
val flatMetadata = handler.awaitFlatMetadataForManga(mangaId)
|
val flatMetadata = getFlatMetadataById.await(mangaId)
|
||||||
flatMetadata?.raise(metaClass) ?: newMetaInstance()
|
flatMetadata?.raise(metaClass) ?: newMetaInstance()
|
||||||
} else newMetaInstance()
|
} else newMetaInstance()
|
||||||
|
|
||||||
parseIntoMetadata(metadata, input)
|
parseIntoMetadata(metadata, input)
|
||||||
if (mangaId != null) {
|
if (mangaId != null) {
|
||||||
metadata.mangaId = mangaId
|
metadata.mangaId = mangaId
|
||||||
handler.awaitInsertFlatMetadata(metadata.flatten())
|
insertFlatMetadata.await(metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
return metadata.createMangaInfo(manga)
|
return metadata.createMangaInfo(manga)
|
||||||
@ -99,7 +97,7 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
|
|||||||
*/
|
*/
|
||||||
suspend fun fetchOrLoadMetadata(mangaId: Long?, inputProducer: suspend () -> I): M {
|
suspend fun fetchOrLoadMetadata(mangaId: Long?, inputProducer: suspend () -> I): M {
|
||||||
val meta = if (mangaId != null) {
|
val meta = if (mangaId != null) {
|
||||||
val flatMetadata = handler.awaitFlatMetadataForManga(mangaId)
|
val flatMetadata = getFlatMetadataById.await(mangaId)
|
||||||
flatMetadata?.raise(metaClass)
|
flatMetadata?.raise(metaClass)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
@ -110,7 +108,7 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
|
|||||||
parseIntoMetadata(newMeta, input)
|
parseIntoMetadata(newMeta, input)
|
||||||
if (mangaId != null) {
|
if (mangaId != null) {
|
||||||
newMeta.mangaId = mangaId
|
newMeta.mangaId = mangaId
|
||||||
handler.awaitInsertFlatMetadata(newMeta.flatten())
|
insertFlatMetadata.await(newMeta)
|
||||||
}
|
}
|
||||||
newMeta
|
newMeta
|
||||||
}
|
}
|
||||||
@ -119,7 +117,7 @@ interface MetadataSource<M : RaisedSearchMetadata, I> : CatalogueSource {
|
|||||||
@Composable
|
@Composable
|
||||||
fun DescriptionComposable(state: MangaScreenState.Success, openMetadataViewer: () -> Unit, search: (String) -> Unit)
|
fun DescriptionComposable(state: MangaScreenState.Success, openMetadataViewer: () -> Unit, search: (String) -> Unit)
|
||||||
|
|
||||||
suspend fun MangaInfo.id() = getMangaByUrlAndSource.await(key, id)?.id
|
suspend fun MangaInfo.id() = getManga.await(key, id)?.id
|
||||||
val SManga.id get() = (this as? Manga)?.id
|
val SManga.id get() = (this as? Manga)?.id
|
||||||
val SChapter.mangaId get() = (this as? Chapter)?.manga_id
|
val SChapter.mangaId get() = (this as? Chapter)?.manga_id
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package eu.kanade.tachiyomi.ui.browse.migration.advanced.process
|
package eu.kanade.tachiyomi.ui.browse.migration.advanced.process
|
||||||
|
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
@ -11,7 +11,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
class MigratingManga(
|
class MigratingManga(
|
||||||
private val getMangaById: GetMangaById,
|
private val getManga: GetManga,
|
||||||
private val sourceManager: SourceManager,
|
private val sourceManager: SourceManager,
|
||||||
val mangaId: Long,
|
val mangaId: Long,
|
||||||
parentContext: CoroutineContext,
|
parentContext: CoroutineContext,
|
||||||
@ -28,7 +28,7 @@ class MigratingManga(
|
|||||||
@Volatile
|
@Volatile
|
||||||
private var manga: Manga? = null
|
private var manga: Manga? = null
|
||||||
suspend fun manga(): Manga? {
|
suspend fun manga(): Manga? {
|
||||||
if (manga == null) manga = getMangaById.await(mangaId)
|
if (manga == null) manga = getManga.await(mangaId)
|
||||||
return manga
|
return manga
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
|
|||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.manga.model.toDbManga
|
import eu.kanade.domain.manga.model.toDbManga
|
||||||
import eu.kanade.domain.manga.model.toMangaInfo
|
import eu.kanade.domain.manga.model.toMangaInfo
|
||||||
@ -75,7 +75,7 @@ class MigrationListController(bundle: Bundle? = null) :
|
|||||||
|
|
||||||
private val smartSearchEngine = SmartSearchEngine(config?.extraSearchParams)
|
private val smartSearchEngine = SmartSearchEngine(config?.extraSearchParams)
|
||||||
private val syncChaptersWithSource: SyncChaptersWithSource by injectLazy()
|
private val syncChaptersWithSource: SyncChaptersWithSource by injectLazy()
|
||||||
private val getMangaById: GetMangaById by injectLazy()
|
private val getManga: GetManga by injectLazy()
|
||||||
private val updateManga: UpdateManga by injectLazy()
|
private val updateManga: UpdateManga by injectLazy()
|
||||||
|
|
||||||
private val migrationScope = CoroutineScope(Job() + Dispatchers.IO)
|
private val migrationScope = CoroutineScope(Job() + Dispatchers.IO)
|
||||||
@ -109,7 +109,7 @@ class MigrationListController(bundle: Bundle? = null) :
|
|||||||
|
|
||||||
val newMigratingManga = migratingManga ?: run {
|
val newMigratingManga = migratingManga ?: run {
|
||||||
val new = config.mangaIds.map {
|
val new = config.mangaIds.map {
|
||||||
MigratingManga(getMangaById, sourceManager, it, migrationScope.coroutineContext)
|
MigratingManga(getManga, sourceManager, it, migrationScope.coroutineContext)
|
||||||
}
|
}
|
||||||
migratingManga = new.toMutableList()
|
migratingManga = new.toMutableList()
|
||||||
new
|
new
|
||||||
@ -409,7 +409,7 @@ class MigrationListController(bundle: Bundle? = null) :
|
|||||||
val hasDetails = router.backstack.any { it.controller is MangaController }
|
val hasDetails = router.backstack.any { it.controller is MangaController }
|
||||||
if (hasDetails) {
|
if (hasDetails) {
|
||||||
val manga = migratingManga?.firstOrNull()?.searchResult?.get()?.let {
|
val manga = migratingManga?.firstOrNull()?.searchResult?.get()?.let {
|
||||||
getMangaById.await(it)
|
getManga.await(it)
|
||||||
}
|
}
|
||||||
if (manga != null) {
|
if (manga != null) {
|
||||||
val newStack = router.backstack.filter {
|
val newStack = router.backstack.filter {
|
||||||
|
@ -12,7 +12,7 @@ import eu.kanade.domain.chapter.model.Chapter
|
|||||||
import eu.kanade.domain.chapter.model.ChapterUpdate
|
import eu.kanade.domain.chapter.model.ChapterUpdate
|
||||||
import eu.kanade.domain.history.interactor.UpsertHistory
|
import eu.kanade.domain.history.interactor.UpsertHistory
|
||||||
import eu.kanade.domain.history.model.HistoryUpdate
|
import eu.kanade.domain.history.model.HistoryUpdate
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.domain.manga.model.MangaUpdate
|
import eu.kanade.domain.manga.model.MangaUpdate
|
||||||
@ -35,7 +35,7 @@ class MigrationProcessAdapter(
|
|||||||
private val handler: DatabaseHandler by injectLazy()
|
private val handler: DatabaseHandler by injectLazy()
|
||||||
private val preferences: PreferencesHelper by injectLazy()
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
private val coverCache: CoverCache by injectLazy()
|
private val coverCache: CoverCache by injectLazy()
|
||||||
private val getMangaById: GetMangaById by injectLazy()
|
private val getManga: GetManga by injectLazy()
|
||||||
private val updateManga: UpdateManga by injectLazy()
|
private val updateManga: UpdateManga by injectLazy()
|
||||||
private val updateChapter: UpdateChapter by injectLazy()
|
private val updateChapter: UpdateChapter by injectLazy()
|
||||||
private val getChapterByMangaId: GetChapterByMangaId by injectLazy()
|
private val getChapterByMangaId: GetChapterByMangaId by injectLazy()
|
||||||
@ -81,7 +81,7 @@ class MigrationProcessAdapter(
|
|||||||
currentItems.forEach { migratingManga ->
|
currentItems.forEach { migratingManga ->
|
||||||
val manga = migratingManga.manga
|
val manga = migratingManga.manga
|
||||||
if (manga.searchResult.initialized) {
|
if (manga.searchResult.initialized) {
|
||||||
val toMangaObj = getMangaById.await(manga.searchResult.get() ?: return@forEach)
|
val toMangaObj = getManga.await(manga.searchResult.get() ?: return@forEach)
|
||||||
?: return@forEach
|
?: return@forEach
|
||||||
migrateMangaInternal(
|
migrateMangaInternal(
|
||||||
manga.manga() ?: return@forEach,
|
manga.manga() ?: return@forEach,
|
||||||
@ -97,7 +97,7 @@ class MigrationProcessAdapter(
|
|||||||
launchUI {
|
launchUI {
|
||||||
val manga = getItem(position)?.manga ?: return@launchUI
|
val manga = getItem(position)?.manga ?: return@launchUI
|
||||||
|
|
||||||
val toMangaObj = getMangaById.await(manga.searchResult.get() ?: return@launchUI)
|
val toMangaObj = getManga.await(manga.searchResult.get() ?: return@launchUI)
|
||||||
?: return@launchUI
|
?: return@launchUI
|
||||||
migrateMangaInternal(
|
migrateMangaInternal(
|
||||||
manga.manga() ?: return@launchUI,
|
manga.manga() ?: return@launchUI,
|
||||||
|
@ -7,7 +7,7 @@ import androidx.core.view.isVisible
|
|||||||
import coil.dispose
|
import coil.dispose
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
|
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.interactor.GetMergedReferencesById
|
import eu.kanade.domain.manga.interactor.GetMergedReferencesById
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
@ -32,7 +32,7 @@ class MigrationProcessHolder(
|
|||||||
private val adapter: MigrationProcessAdapter,
|
private val adapter: MigrationProcessAdapter,
|
||||||
) : FlexibleViewHolder(view, adapter) {
|
) : FlexibleViewHolder(view, adapter) {
|
||||||
private val sourceManager: SourceManager by injectLazy()
|
private val sourceManager: SourceManager by injectLazy()
|
||||||
private val getMangaById: GetMangaById by injectLazy()
|
private val getManga: GetManga by injectLazy()
|
||||||
private val getChapterByMangaId: GetChapterByMangaId by injectLazy()
|
private val getChapterByMangaId: GetChapterByMangaId by injectLazy()
|
||||||
private val getMergedReferencesById: GetMergedReferencesById by injectLazy()
|
private val getMergedReferencesById: GetMergedReferencesById by injectLazy()
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ class MigrationProcessHolder(
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
val searchResult = item.manga.searchResult.get()?.let {
|
val searchResult = item.manga.searchResult.get()?.let {
|
||||||
getMangaById.await(it)
|
getManga.await(it)
|
||||||
}
|
}
|
||||||
val resultSource = searchResult?.source?.let {
|
val resultSource = searchResult?.source?.let {
|
||||||
sourceManager.get(it)
|
sourceManager.get(it)
|
||||||
|
@ -5,9 +5,9 @@ import android.view.MenuInflater
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||||
|
import eu.kanade.domain.manga.interactor.GetFavorites
|
||||||
import eu.kanade.presentation.browse.MigrateSourceScreen
|
import eu.kanade.presentation.browse.MigrateSourceScreen
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
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.ui.base.controller.ComposeController
|
import eu.kanade.tachiyomi.ui.base.controller.ComposeController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||||
@ -54,10 +54,9 @@ class MigrationSourcesController : ComposeController<MigrationSourcesPresenter>(
|
|||||||
onClickAll = { source ->
|
onClickAll = { source ->
|
||||||
// TODO: Jay wtf, need to clean this up sometime
|
// TODO: Jay wtf, need to clean this up sometime
|
||||||
launchIO {
|
launchIO {
|
||||||
val manga = Injekt.get<DatabaseHelper>().getFavoriteMangas().executeAsBlocking()
|
val manga = Injekt.get<GetFavorites>().await()
|
||||||
val sourceMangas =
|
val sourceMangas =
|
||||||
manga.asSequence().filter { it.source == source.id }.mapNotNull { it.id }
|
manga.asSequence().filter { it.source == source.id }.map { it.id }.toList()
|
||||||
.toList()
|
|
||||||
withUIContext {
|
withUIContext {
|
||||||
PreMigrationController.navigateToMigration(
|
PreMigrationController.navigateToMigration(
|
||||||
Injekt.get<PreferencesHelper>().skipPreMigration().get(),
|
Injekt.get<PreferencesHelper>().skipPreMigration().get(),
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package eu.kanade.tachiyomi.ui.library
|
package eu.kanade.tachiyomi.ui.library
|
||||||
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
|
import eu.kanade.domain.manga.interactor.GetIdsOfFavoriteMangaWithMetadata
|
||||||
|
import eu.kanade.domain.manga.interactor.GetSearchTags
|
||||||
|
import eu.kanade.domain.manga.interactor.GetSearchTitles
|
||||||
import eu.kanade.domain.track.interactor.GetTracks
|
import eu.kanade.domain.track.interactor.GetTracks
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
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.tables.MangaTable
|
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
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
|
||||||
@ -21,7 +22,6 @@ import exh.search.SearchEngine
|
|||||||
import exh.search.Text
|
import exh.search.Text
|
||||||
import exh.source.isMetadataSource
|
import exh.source.isMetadataSource
|
||||||
import exh.util.cancellable
|
import exh.util.cancellable
|
||||||
import exh.util.executeOnIO
|
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -41,7 +41,6 @@ import uy.kohesive.injekt.injectLazy
|
|||||||
class LibraryCategoryAdapter(view: LibraryCategoryView, val controller: LibraryController) :
|
class LibraryCategoryAdapter(view: LibraryCategoryView, val controller: LibraryController) :
|
||||||
FlexibleAdapter<LibraryItem>(null, view, true) {
|
FlexibleAdapter<LibraryItem>(null, view, true) {
|
||||||
// EXH -->
|
// EXH -->
|
||||||
private val db: DatabaseHelper by injectLazy()
|
|
||||||
private val searchEngine = SearchEngine()
|
private val searchEngine = SearchEngine()
|
||||||
private var lastFilterJob: Job? = null
|
private var lastFilterJob: Job? = null
|
||||||
private val sourceManager: SourceManager by injectLazy()
|
private val sourceManager: SourceManager by injectLazy()
|
||||||
@ -50,8 +49,13 @@ class LibraryCategoryAdapter(view: LibraryCategoryView, val controller: LibraryC
|
|||||||
private val hasLoggedServices by lazy {
|
private val hasLoggedServices by lazy {
|
||||||
trackManager.hasLoggedServices()
|
trackManager.hasLoggedServices()
|
||||||
}
|
}
|
||||||
private val services = trackManager.services.map { service -> service.id to controller.activity!!.getString(service.nameRes()) }.toMap()
|
private val services = trackManager.services.associate { service ->
|
||||||
|
service.id to controller.activity!!.getString(service.nameRes())
|
||||||
|
}
|
||||||
|
private val getIdsOfFavoriteMangaWithMetadata: GetIdsOfFavoriteMangaWithMetadata by injectLazy()
|
||||||
private val getTracks: GetTracks by injectLazy()
|
private val getTracks: GetTracks by injectLazy()
|
||||||
|
private val getSearchTags: GetSearchTags by injectLazy()
|
||||||
|
private val getSearchTitles: GetSearchTitles by injectLazy()
|
||||||
|
|
||||||
// Keep compatibility as searchText field was replaced when we upgraded FlexibleAdapter
|
// Keep compatibility as searchText field was replaced when we upgraded FlexibleAdapter
|
||||||
var searchText
|
var searchText
|
||||||
@ -116,19 +120,7 @@ class LibraryCategoryAdapter(view: LibraryCategoryView, val controller: LibraryC
|
|||||||
val newManga = try {
|
val newManga = try {
|
||||||
// Prepare filter object
|
// Prepare filter object
|
||||||
val parsedQuery = searchEngine.parseQuery(savedSearchText)
|
val parsedQuery = searchEngine.parseQuery(savedSearchText)
|
||||||
|
val mangaWithMetaIds = getIdsOfFavoriteMangaWithMetadata.await()
|
||||||
val mangaWithMetaIdsQuery = db.getIdsOfFavoriteMangaWithMetadata().executeOnIO()
|
|
||||||
val mangaWithMetaIds = LongArray(mangaWithMetaIdsQuery.count)
|
|
||||||
if (mangaWithMetaIds.isNotEmpty()) {
|
|
||||||
val mangaIdCol = mangaWithMetaIdsQuery.getColumnIndex(MangaTable.COL_ID)
|
|
||||||
mangaWithMetaIdsQuery.moveToFirst()
|
|
||||||
while (!mangaWithMetaIdsQuery.isAfterLast) {
|
|
||||||
ensureActive() // Fail early when cancelled
|
|
||||||
|
|
||||||
mangaWithMetaIds[mangaWithMetaIdsQuery.position] = mangaWithMetaIdsQuery.getLong(mangaIdCol)
|
|
||||||
mangaWithMetaIdsQuery.moveToNext()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ensureActive() // Fail early when cancelled
|
ensureActive() // Fail early when cancelled
|
||||||
|
|
||||||
@ -140,8 +132,8 @@ class LibraryCategoryAdapter(view: LibraryCategoryView, val controller: LibraryC
|
|||||||
// No meta? Filter using title
|
// No meta? Filter using title
|
||||||
filterManga(parsedQuery, item.manga)
|
filterManga(parsedQuery, item.manga)
|
||||||
} else {
|
} else {
|
||||||
val tags = db.getSearchTagsForManga(mangaId).executeAsBlocking()
|
val tags = getSearchTags.await(mangaId)
|
||||||
val titles = db.getSearchTitlesForManga(mangaId).executeAsBlocking()
|
val titles = getSearchTitles.await(mangaId)
|
||||||
filterManga(parsedQuery, item.manga, false, tags, titles)
|
filterManga(parsedQuery, item.manga, false, tags, titles)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -934,7 +934,7 @@ class LibraryPresenter(
|
|||||||
val tracks = runBlocking { getTracks.await() }.groupBy { it.mangaId }
|
val tracks = runBlocking { getTracks.await() }.groupBy { it.mangaId }
|
||||||
libraryManga.forEach { libraryItem ->
|
libraryManga.forEach { libraryItem ->
|
||||||
val status = tracks[libraryItem.manga.id]?.firstNotNullOfOrNull { track ->
|
val status = tracks[libraryItem.manga.id]?.firstNotNullOfOrNull { track ->
|
||||||
TrackStatus.parseTrackerStatus(track.syncId, track.status.toInt())
|
TrackStatus.parseTrackerStatus(track.syncId, track.status)
|
||||||
} ?: TrackStatus.OTHER
|
} ?: TrackStatus.OTHER
|
||||||
|
|
||||||
map.getOrPut(status.int.toLong()) { mutableListOf() } += libraryItem
|
map.getOrPut(status.int.toLong()) { mutableListOf() } += libraryItem
|
||||||
|
@ -13,7 +13,7 @@ import coil.transform.RoundedCornersTransformation
|
|||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.chip.Chip
|
||||||
import com.google.android.material.chip.ChipGroup
|
import com.google.android.material.chip.ChipGroup
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.databinding.EditMangaDialogBinding
|
import eu.kanade.tachiyomi.databinding.EditMangaDialogBinding
|
||||||
@ -52,7 +52,7 @@ class EditMangaDialog : DialogController {
|
|||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
constructor(bundle: Bundle) : super(bundle) {
|
constructor(bundle: Bundle) : super(bundle) {
|
||||||
manga = runBlocking { Injekt.get<GetMangaById>().await(bundle.getLong(KEY_MANGA))!! }
|
manga = runBlocking { Injekt.get<GetManga>().await(bundle.getLong(KEY_MANGA))!! }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||||
|
@ -14,8 +14,7 @@ import eu.kanade.domain.chapter.model.ChapterUpdate
|
|||||||
import eu.kanade.domain.chapter.model.toDbChapter
|
import eu.kanade.domain.chapter.model.toDbChapter
|
||||||
import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
|
import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
|
||||||
import eu.kanade.domain.manga.interactor.GetFlatMetadataById
|
import eu.kanade.domain.manga.interactor.GetFlatMetadataById
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaByUrlAndSource
|
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaWithChapters
|
import eu.kanade.domain.manga.interactor.GetMangaWithChapters
|
||||||
import eu.kanade.domain.manga.interactor.GetMergedMangaById
|
import eu.kanade.domain.manga.interactor.GetMergedMangaById
|
||||||
import eu.kanade.domain.manga.interactor.GetMergedReferencesById
|
import eu.kanade.domain.manga.interactor.GetMergedReferencesById
|
||||||
@ -123,8 +122,7 @@ class MangaPresenter(
|
|||||||
// SY <--
|
// SY <--
|
||||||
private val getMangaAndChapters: GetMangaWithChapters = Injekt.get(),
|
private val getMangaAndChapters: GetMangaWithChapters = Injekt.get(),
|
||||||
// SY -->
|
// SY -->
|
||||||
private val getMangaById: GetMangaById = Injekt.get(),
|
private val getManga: GetManga = Injekt.get(),
|
||||||
private val getMangaByUrlAndSource: GetMangaByUrlAndSource = Injekt.get(),
|
|
||||||
private val setMangaFilteredScanlators: SetMangaFilteredScanlators = Injekt.get(),
|
private val setMangaFilteredScanlators: SetMangaFilteredScanlators = Injekt.get(),
|
||||||
private val getMergedChapterByMangaId: GetMergedChapterByMangaId = Injekt.get(),
|
private val getMergedChapterByMangaId: GetMergedChapterByMangaId = Injekt.get(),
|
||||||
private val getMergedMangaById: GetMergedMangaById = Injekt.get(),
|
private val getMergedMangaById: GetMergedMangaById = Injekt.get(),
|
||||||
@ -435,7 +433,7 @@ class MangaPresenter(
|
|||||||
suspend fun smartSearchMerge(context: Context, manga: DomainManga, originalMangaId: Long): DomainManga {
|
suspend fun smartSearchMerge(context: Context, manga: DomainManga, originalMangaId: Long): DomainManga {
|
||||||
val db = Injekt.get<DatabaseHelper>()
|
val db = Injekt.get<DatabaseHelper>()
|
||||||
|
|
||||||
val originalManga = getMangaById.await(originalMangaId)
|
val originalManga = getManga.await(originalMangaId)
|
||||||
?: throw IllegalArgumentException(context.getString(R.string.merge_unknown_manga, originalMangaId))
|
?: throw IllegalArgumentException(context.getString(R.string.merge_unknown_manga, originalMangaId))
|
||||||
if (originalManga.source == MERGED_SOURCE_ID) {
|
if (originalManga.source == MERGED_SOURCE_ID) {
|
||||||
val children = getMergedReferencesById.await(originalMangaId)
|
val children = getMergedReferencesById.await(originalMangaId)
|
||||||
@ -490,7 +488,7 @@ class MangaPresenter(
|
|||||||
date_added = System.currentTimeMillis()
|
date_added = System.currentTimeMillis()
|
||||||
}
|
}
|
||||||
|
|
||||||
var existingManga = getMangaByUrlAndSource.await(mergedManga.url, mergedManga.source)
|
var existingManga = getManga.await(mergedManga.url, mergedManga.source)
|
||||||
while (existingManga != null) {
|
while (existingManga != null) {
|
||||||
if (existingManga.favorite) {
|
if (existingManga.favorite) {
|
||||||
throw IllegalArgumentException(context.getString(R.string.merge_duplicate))
|
throw IllegalArgumentException(context.getString(R.string.merge_duplicate))
|
||||||
@ -500,7 +498,7 @@ class MangaPresenter(
|
|||||||
db.deleteMangaForMergedManga(existingManga!!.id).executeAsBlocking()
|
db.deleteMangaForMergedManga(existingManga!!.id).executeAsBlocking()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
existingManga = getMangaByUrlAndSource.await(mergedManga.url, mergedManga.source)
|
existingManga = getManga.await(mergedManga.url, mergedManga.source)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reload chapters immediately
|
// Reload chapters immediately
|
||||||
@ -744,7 +742,7 @@ class MangaPresenter(
|
|||||||
tracks
|
tracks
|
||||||
.filter { it.syncId in loggedServicesId }
|
.filter { it.syncId in loggedServicesId }
|
||||||
// SY -->
|
// SY -->
|
||||||
.filterNot { it.syncId == TrackManager.MDLIST.toLong() && it.status == FollowStatus.UNFOLLOWED.int.toLong() }
|
.filterNot { it.syncId == TrackManager.MDLIST && it.status == FollowStatus.UNFOLLOWED.int.toLong() }
|
||||||
// SY <--
|
// SY <--
|
||||||
.size
|
.size
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ import androidx.core.os.bundleOf
|
|||||||
import coil.imageLoader
|
import coil.imageLoader
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
import coil.size.Size
|
import coil.size.Size
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.domain.manga.model.hasCustomCover
|
import eu.kanade.domain.manga.model.hasCustomCover
|
||||||
@ -161,7 +161,7 @@ class MangaFullCoverDialog : FullComposeController<MangaFullCoverDialog.MangaFul
|
|||||||
|
|
||||||
inner class MangaFullCoverPresenter(
|
inner class MangaFullCoverPresenter(
|
||||||
private val mangaId: Long,
|
private val mangaId: Long,
|
||||||
private val getMangaById: GetMangaById = Injekt.get(),
|
private val getManga: GetManga = Injekt.get(),
|
||||||
) : Presenter<MangaFullCoverDialog>() {
|
) : Presenter<MangaFullCoverDialog>() {
|
||||||
|
|
||||||
private var presenterScope: CoroutineScope = MainScope()
|
private var presenterScope: CoroutineScope = MainScope()
|
||||||
@ -176,7 +176,7 @@ class MangaFullCoverDialog : FullComposeController<MangaFullCoverDialog.MangaFul
|
|||||||
override fun onCreate(savedState: Bundle?) {
|
override fun onCreate(savedState: Bundle?) {
|
||||||
super.onCreate(savedState)
|
super.onCreate(savedState)
|
||||||
presenterScope.launchIO {
|
presenterScope.launchIO {
|
||||||
getMangaById.subscribe(mangaId)
|
getManga.subscribe(mangaId)
|
||||||
.collect { _mangaFlow.value = it }
|
.collect { _mangaFlow.value = it }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import eu.kanade.domain.chapter.model.toDbChapter
|
|||||||
import eu.kanade.domain.history.interactor.UpsertHistory
|
import eu.kanade.domain.history.interactor.UpsertHistory
|
||||||
import eu.kanade.domain.history.model.HistoryUpdate
|
import eu.kanade.domain.history.model.HistoryUpdate
|
||||||
import eu.kanade.domain.manga.interactor.GetFlatMetadataById
|
import eu.kanade.domain.manga.interactor.GetFlatMetadataById
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.model.isLocal
|
import eu.kanade.domain.manga.model.isLocal
|
||||||
import eu.kanade.domain.manga.model.toDbManga
|
import eu.kanade.domain.manga.model.toDbManga
|
||||||
import eu.kanade.domain.track.interactor.GetTracks
|
import eu.kanade.domain.track.interactor.GetTracks
|
||||||
@ -91,7 +91,7 @@ class ReaderPresenter(
|
|||||||
private val downloadManager: DownloadManager = Injekt.get(),
|
private val downloadManager: DownloadManager = Injekt.get(),
|
||||||
private val preferences: PreferencesHelper = Injekt.get(),
|
private val preferences: PreferencesHelper = Injekt.get(),
|
||||||
private val delayedTrackingStore: DelayedTrackingStore = Injekt.get(),
|
private val delayedTrackingStore: DelayedTrackingStore = Injekt.get(),
|
||||||
private val getMangaById: GetMangaById = Injekt.get(),
|
private val getManga: GetManga = Injekt.get(),
|
||||||
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
|
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
|
||||||
private val getTracks: GetTracks = Injekt.get(),
|
private val getTracks: GetTracks = Injekt.get(),
|
||||||
private val insertTrack: InsertTrack = Injekt.get(),
|
private val insertTrack: InsertTrack = Injekt.get(),
|
||||||
@ -282,7 +282,7 @@ class ReaderPresenter(
|
|||||||
launchIO {
|
launchIO {
|
||||||
try {
|
try {
|
||||||
// SY -->
|
// SY -->
|
||||||
val manga = getMangaById.await(mangaId) ?: return@launchIO
|
val manga = getManga.await(mangaId) ?: return@launchIO
|
||||||
val source = sourceManager.get(manga.source)?.getMainSource<MetadataSource<*, *>>()
|
val source = sourceManager.get(manga.source)?.getMainSource<MetadataSource<*, *>>()
|
||||||
val metadata = if (source != null) {
|
val metadata = if (source != null) {
|
||||||
getFlatMetadataById.await(mangaId)?.raise(source.metaClass)
|
getFlatMetadataById.await(mangaId)?.raise(source.metaClass)
|
||||||
|
@ -14,10 +14,13 @@ import androidx.core.net.toUri
|
|||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
|
||||||
|
import eu.kanade.domain.chapter.model.toDbChapter
|
||||||
|
import eu.kanade.domain.manga.interactor.GetAllManga
|
||||||
|
import eu.kanade.domain.manga.model.toDbManga
|
||||||
import eu.kanade.domain.manga.repository.MangaRepository
|
import eu.kanade.domain.manga.repository.MangaRepository
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Target
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Target
|
||||||
@ -82,7 +85,8 @@ class SettingsAdvancedController(
|
|||||||
private val network: NetworkHelper by injectLazy()
|
private val network: NetworkHelper by injectLazy()
|
||||||
private val chapterCache: ChapterCache by injectLazy()
|
private val chapterCache: ChapterCache by injectLazy()
|
||||||
private val trackManager: TrackManager by injectLazy()
|
private val trackManager: TrackManager by injectLazy()
|
||||||
private val db: DatabaseHelper by injectLazy()
|
private val getAllManga: GetAllManga by injectLazy()
|
||||||
|
private val getChapterByMangaId: GetChapterByMangaId by injectLazy()
|
||||||
|
|
||||||
@SuppressLint("BatteryLife")
|
@SuppressLint("BatteryLife")
|
||||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
|
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
|
||||||
@ -475,7 +479,7 @@ class SettingsAdvancedController(
|
|||||||
if (job?.isActive == true) return
|
if (job?.isActive == true) return
|
||||||
activity?.toast(R.string.starting_cleanup)
|
activity?.toast(R.string.starting_cleanup)
|
||||||
job = launchIO {
|
job = launchIO {
|
||||||
val mangaList = db.getMangas().executeAsBlocking()
|
val mangaList = getAllManga.await()
|
||||||
val downloadManager: DownloadManager = Injekt.get()
|
val downloadManager: DownloadManager = Injekt.get()
|
||||||
var foldersCleared = 0
|
var foldersCleared = 0
|
||||||
Injekt.get<SourceManager>().getOnlineSources().forEach { source ->
|
Injekt.get<SourceManager>().getOnlineSources().forEach { source ->
|
||||||
@ -483,7 +487,7 @@ class SettingsAdvancedController(
|
|||||||
val sourceManga = mangaList
|
val sourceManga = mangaList
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.filter { it.source == source.id }
|
.filter { it.source == source.id }
|
||||||
.map { it to DiskUtil.buildValidFilename(it.originalTitle) }
|
.map { it to DiskUtil.buildValidFilename(it.ogTitle) }
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
mangaFolders.forEach mangaFolder@{ mangaFolder ->
|
mangaFolders.forEach mangaFolder@{ mangaFolder ->
|
||||||
@ -493,8 +497,8 @@ class SettingsAdvancedController(
|
|||||||
foldersCleared += 1 + (mangaFolder.listFiles().orEmpty().size)
|
foldersCleared += 1 + (mangaFolder.listFiles().orEmpty().size)
|
||||||
mangaFolder.delete()
|
mangaFolder.delete()
|
||||||
} else {
|
} else {
|
||||||
val chapterList = db.getChapters(manga).executeAsBlocking()
|
val chapterList = getChapterByMangaId.await(manga.id)
|
||||||
foldersCleared += downloadManager.cleanupChapters(chapterList, manga, source, removeRead, removeNonFavorite)
|
foldersCleared += downloadManager.cleanupChapters(chapterList.map { it.toDbChapter() }, manga.toDbManga(), source, removeRead, removeNonFavorite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,15 +14,19 @@ import androidx.core.widget.doAfterTextChanged
|
|||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import com.fredporciuncula.flow.preferences.Preference
|
import com.fredporciuncula.flow.preferences.Preference
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import eu.kanade.data.DatabaseHandler
|
||||||
|
import eu.kanade.data.manga.mangaMapper
|
||||||
|
import eu.kanade.domain.manga.interactor.DeleteFavoriteEntries
|
||||||
|
import eu.kanade.domain.manga.interactor.GetFlatMetadataById
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
|
||||||
import eu.kanade.tachiyomi.data.preference.DEVICE_CHARGING
|
import eu.kanade.tachiyomi.data.preference.DEVICE_CHARGING
|
||||||
import eu.kanade.tachiyomi.data.preference.DEVICE_ONLY_ON_WIFI
|
import eu.kanade.tachiyomi.data.preference.DEVICE_ONLY_ON_WIFI
|
||||||
import eu.kanade.tachiyomi.databinding.DialogStubTextinputBinding
|
import eu.kanade.tachiyomi.databinding.DialogStubTextinputBinding
|
||||||
import eu.kanade.tachiyomi.ui.setting.eh.FrontPageCategoriesDialog
|
import eu.kanade.tachiyomi.ui.setting.eh.FrontPageCategoriesDialog
|
||||||
import eu.kanade.tachiyomi.ui.setting.eh.LanguagesDialog
|
import eu.kanade.tachiyomi.ui.setting.eh.LanguagesDialog
|
||||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||||
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
|
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||||
import eu.kanade.tachiyomi.util.preference.bindTo
|
import eu.kanade.tachiyomi.util.preference.bindTo
|
||||||
import eu.kanade.tachiyomi.util.preference.entriesRes
|
import eu.kanade.tachiyomi.util.preference.entriesRes
|
||||||
import eu.kanade.tachiyomi.util.preference.intListPreference
|
import eu.kanade.tachiyomi.util.preference.intListPreference
|
||||||
@ -42,11 +46,10 @@ import exh.eh.EHentaiUpdaterStats
|
|||||||
import exh.favorites.FavoritesIntroDialog
|
import exh.favorites.FavoritesIntroDialog
|
||||||
import exh.log.xLogD
|
import exh.log.xLogD
|
||||||
import exh.metadata.metadata.EHentaiSearchMetadata
|
import exh.metadata.metadata.EHentaiSearchMetadata
|
||||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
import exh.source.EH_SOURCE_ID
|
||||||
import exh.source.isEhBasedManga
|
import exh.source.EXH_SOURCE_ID
|
||||||
import exh.uconfig.WarnConfigureDialogController
|
import exh.uconfig.WarnConfigureDialogController
|
||||||
import exh.ui.login.EhLoginActivity
|
import exh.ui.login.EhLoginActivity
|
||||||
import exh.util.executeOnIO
|
|
||||||
import exh.util.nullIfBlank
|
import exh.util.nullIfBlank
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
@ -69,7 +72,9 @@ import kotlin.time.Duration.Companion.seconds
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class SettingsEhController : SettingsController() {
|
class SettingsEhController : SettingsController() {
|
||||||
private val db: DatabaseHelper by injectLazy()
|
private val handler: DatabaseHandler by injectLazy()
|
||||||
|
private val getFlatMetadataById: GetFlatMetadataById by injectLazy()
|
||||||
|
private val deleteFavoriteEntries: DeleteFavoriteEntries by injectLazy()
|
||||||
|
|
||||||
fun Preference<*>.reconfigure(): Boolean {
|
fun Preference<*>.reconfigure(): Boolean {
|
||||||
// Listen for change commit
|
// Listen for change commit
|
||||||
@ -360,10 +365,12 @@ class SettingsEhController : SettingsController() {
|
|||||||
.setTitle(R.string.favorites_sync_reset)
|
.setTitle(R.string.favorites_sync_reset)
|
||||||
.setMessage(R.string.favorites_sync_reset_message)
|
.setMessage(R.string.favorites_sync_reset_message)
|
||||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
db.inTransaction {
|
launchIO {
|
||||||
db.deleteAllFavoriteEntries().executeAsBlocking()
|
deleteFavoriteEntries.await()
|
||||||
|
withUIContext {
|
||||||
|
activity.toast(context.getString(R.string.sync_state_reset), Toast.LENGTH_LONG)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
activity.toast(context.getString(R.string.sync_state_reset), Toast.LENGTH_LONG)
|
|
||||||
}
|
}
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
@ -468,12 +475,12 @@ class SettingsEhController : SettingsController() {
|
|||||||
context.getString(R.string.gallery_updater_stats_text, getRelativeTimeString(getRelativeTimeFromNow(stats.startTime.milliseconds), context), stats.updateCount, stats.possibleUpdates)
|
context.getString(R.string.gallery_updater_stats_text, getRelativeTimeString(getRelativeTimeFromNow(stats.startTime.milliseconds), context), stats.updateCount, stats.possibleUpdates)
|
||||||
} else context.getString(R.string.gallery_updater_not_ran_yet)
|
} else context.getString(R.string.gallery_updater_not_ran_yet)
|
||||||
|
|
||||||
val allMeta = db.getFavoriteMangaWithMetadata().executeOnIO()
|
val allMeta = handler
|
||||||
.filter(Manga::isEhBasedManga)
|
.awaitList { mangasQueries.getEhMangaWithMetadata(EH_SOURCE_ID, EXH_SOURCE_ID, mangaMapper) }
|
||||||
.mapNotNull {
|
.mapNotNull {
|
||||||
db.getFlatMetadataForManga(it.id!!).executeOnIO()
|
getFlatMetadataById.await(it.id)
|
||||||
?.raise<EHentaiSearchMetadata>()
|
?.raise<EHentaiSearchMetadata>()
|
||||||
}.toList()
|
}
|
||||||
|
|
||||||
fun metaInRelativeDuration(duration: Duration): Int {
|
fun metaInRelativeDuration(duration: Duration): Int {
|
||||||
val durationMs = duration.inWholeMilliseconds
|
val durationMs = duration.inWholeMilliseconds
|
||||||
|
@ -5,19 +5,18 @@ package exh
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
import com.pushtorefresh.storio.sqlite.queries.Query
|
||||||
import com.pushtorefresh.storio.sqlite.queries.RawQuery
|
|
||||||
import eu.kanade.data.DatabaseHandler
|
import eu.kanade.data.DatabaseHandler
|
||||||
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
|
import eu.kanade.domain.manga.interactor.GetMangaBySource
|
||||||
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
|
import eu.kanade.domain.manga.model.MangaUpdate
|
||||||
import eu.kanade.tachiyomi.BuildConfig
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
|
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
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.resolvers.MangaUrlPutResolver
|
|
||||||
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
|
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
|
||||||
import eu.kanade.tachiyomi.data.database.tables.TrackTable
|
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
import eu.kanade.tachiyomi.data.preference.MANGA_NON_COMPLETED
|
import eu.kanade.tachiyomi.data.preference.MANGA_NON_COMPLETED
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
|
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
|
||||||
@ -29,7 +28,6 @@ import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
|
|||||||
import eu.kanade.tachiyomi.network.PREF_DOH_CLOUDFLARE
|
import eu.kanade.tachiyomi.network.PREF_DOH_CLOUDFLARE
|
||||||
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.SManga
|
|
||||||
import eu.kanade.tachiyomi.source.online.all.Hitomi
|
import eu.kanade.tachiyomi.source.online.all.Hitomi
|
||||||
import eu.kanade.tachiyomi.source.online.all.NHentai
|
import eu.kanade.tachiyomi.source.online.all.NHentai
|
||||||
import eu.kanade.tachiyomi.ui.library.LibrarySort
|
import eu.kanade.tachiyomi.ui.library.LibrarySort
|
||||||
@ -68,11 +66,15 @@ import uy.kohesive.injekt.injectLazy
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.net.URISyntaxException
|
import java.net.URISyntaxException
|
||||||
|
import eu.kanade.domain.manga.model.Manga as DomainManga
|
||||||
|
|
||||||
object EXHMigrations {
|
object EXHMigrations {
|
||||||
private val db: DatabaseHelper by injectLazy()
|
private val db: DatabaseHelper by injectLazy()
|
||||||
private val database: DatabaseHandler by injectLazy()
|
private val handler: DatabaseHandler by injectLazy()
|
||||||
private val sourceManager: SourceManager by injectLazy()
|
private val sourceManager: SourceManager by injectLazy()
|
||||||
|
private val getManga: GetManga by injectLazy()
|
||||||
|
private val getMangaBySource: GetMangaBySource by injectLazy()
|
||||||
|
private val updateManga: UpdateManga by injectLazy()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a migration when the application is updated.
|
* Performs a migration when the application is updated.
|
||||||
@ -102,68 +104,41 @@ object EXHMigrations {
|
|||||||
|
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
if (oldVersion under 4) {
|
if (oldVersion under 4) {
|
||||||
db.inTransaction {
|
updateSourceId(HBROWSE_SOURCE_ID, 6912)
|
||||||
updateSourceId(HBROWSE_SOURCE_ID, 6912)
|
// Migrate BHrowse URLs
|
||||||
// Migrate BHrowse URLs
|
val hBrowseManga = runBlocking { getMangaBySource.await(HBROWSE_SOURCE_ID) }
|
||||||
val hBrowseManga = db.db.get()
|
val mangaUpdates = hBrowseManga.map {
|
||||||
.listOfObjects(Manga::class.java)
|
MangaUpdate(it.id, url = it.url + "/c00001/")
|
||||||
.withQuery(
|
}
|
||||||
Query.builder()
|
|
||||||
.table(MangaTable.TABLE)
|
|
||||||
.where("${MangaTable.COL_SOURCE} = $HBROWSE_SOURCE_ID")
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
.executeAsBlocking()
|
|
||||||
hBrowseManga.forEach {
|
|
||||||
it.url = it.url + "/c00001/"
|
|
||||||
}
|
|
||||||
|
|
||||||
db.db.put()
|
runBlocking {
|
||||||
.objects(hBrowseManga)
|
updateManga.awaitAll(mangaUpdates)
|
||||||
// Extremely slow without the resolver :/
|
|
||||||
.withPutResolver(MangaUrlPutResolver())
|
|
||||||
.prepare()
|
|
||||||
.executeAsBlocking()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (oldVersion under 5) {
|
if (oldVersion under 5) {
|
||||||
db.inTransaction {
|
// Migrate Hitomi source IDs
|
||||||
// Migrate Hitomi source IDs
|
updateSourceId(Hitomi.otherId, 6910)
|
||||||
updateSourceId(Hitomi.otherId, 6910)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (oldVersion under 6) {
|
if (oldVersion under 6) {
|
||||||
db.inTransaction {
|
updateSourceId(PERV_EDEN_EN_SOURCE_ID, 6905)
|
||||||
updateSourceId(PERV_EDEN_EN_SOURCE_ID, 6905)
|
updateSourceId(PERV_EDEN_IT_SOURCE_ID, 6906)
|
||||||
updateSourceId(PERV_EDEN_IT_SOURCE_ID, 6906)
|
updateSourceId(NHentai.otherId, 6907)
|
||||||
updateSourceId(NHentai.otherId, 6907)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (oldVersion under 7) {
|
if (oldVersion under 7) {
|
||||||
db.inTransaction {
|
db.inTransaction {
|
||||||
val mergedMangas = db.db.get()
|
val mergedMangas = runBlocking { getMangaBySource.await(MERGED_SOURCE_ID) }
|
||||||
.listOfObjects(Manga::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(MangaTable.TABLE)
|
|
||||||
.where("${MangaTable.COL_SOURCE} = $MERGED_SOURCE_ID")
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
.executeAsBlocking()
|
|
||||||
|
|
||||||
if (mergedMangas.isNotEmpty()) {
|
if (mergedMangas.isNotEmpty()) {
|
||||||
val mangaConfigs = mergedMangas.mapNotNull { mergedManga -> readMangaConfig(mergedManga)?.let { mergedManga to it } }
|
val mangaConfigs = mergedMangas.mapNotNull { mergedManga -> readMangaConfig(mergedManga)?.let { mergedManga to it } }
|
||||||
if (mangaConfigs.isNotEmpty()) {
|
if (mangaConfigs.isNotEmpty()) {
|
||||||
val mangaToUpdate = mutableListOf<Manga>()
|
val mangaToUpdate = mutableListOf<MangaUpdate>()
|
||||||
val mergedMangaReferences = mutableListOf<MergedMangaReference>()
|
val mergedMangaReferences = mutableListOf<MergedMangaReference>()
|
||||||
mangaConfigs.onEach { mergedManga ->
|
mangaConfigs.onEach { mergedManga ->
|
||||||
mergedManga.second.children.firstOrNull()?.url?.let {
|
val newFirst = mergedManga.second.children.firstOrNull()?.url?.let {
|
||||||
if (db.getManga(it, MERGED_SOURCE_ID).executeAsBlocking() != null) return@onEach
|
if (runBlocking { getManga.await(it, MERGED_SOURCE_ID) } != null) return@onEach
|
||||||
mergedManga.first.url = it
|
mangaToUpdate += MangaUpdate(id = mergedManga.first.id, url = it)
|
||||||
}
|
mergedManga.first.copy(url = it)
|
||||||
mangaToUpdate += mergedManga.first
|
} ?: mergedManga.first
|
||||||
mergedMangaReferences += MergedMangaReference(
|
mergedMangaReferences += MergedMangaReference(
|
||||||
id = null,
|
id = null,
|
||||||
isInfoManga = false,
|
isInfoManga = false,
|
||||||
@ -171,9 +146,9 @@ object EXHMigrations {
|
|||||||
chapterSortMode = 0,
|
chapterSortMode = 0,
|
||||||
chapterPriority = 0,
|
chapterPriority = 0,
|
||||||
downloadChapters = false,
|
downloadChapters = false,
|
||||||
mergeId = mergedManga.first.id!!,
|
mergeId = mergedManga.first.id,
|
||||||
mergeUrl = mergedManga.first.url,
|
mergeUrl = mergedManga.first.url,
|
||||||
mangaId = mergedManga.first.id!!,
|
mangaId = mergedManga.first.id,
|
||||||
mangaUrl = mergedManga.first.url,
|
mangaUrl = mergedManga.first.url,
|
||||||
mangaSourceId = MERGED_SOURCE_ID,
|
mangaSourceId = MERGED_SOURCE_ID,
|
||||||
)
|
)
|
||||||
@ -186,7 +161,7 @@ object EXHMigrations {
|
|||||||
chapterSortMode = 0,
|
chapterSortMode = 0,
|
||||||
chapterPriority = 0,
|
chapterPriority = 0,
|
||||||
downloadChapters = true,
|
downloadChapters = true,
|
||||||
mergeId = mergedManga.first.id!!,
|
mergeId = mergedManga.first.id,
|
||||||
mergeUrl = mergedManga.first.url,
|
mergeUrl = mergedManga.first.url,
|
||||||
mangaId = load.manga.id!!,
|
mangaId = load.manga.id!!,
|
||||||
mangaUrl = load.manga.url,
|
mangaUrl = load.manga.url,
|
||||||
@ -194,12 +169,9 @@ object EXHMigrations {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
db.db.put()
|
runBlocking {
|
||||||
.objects(mangaToUpdate)
|
updateManga.awaitAll(mangaToUpdate)
|
||||||
// Extremely slow without the resolver :/
|
}
|
||||||
.withPutResolver(MangaUrlPutResolver())
|
|
||||||
.prepare()
|
|
||||||
.executeAsBlocking()
|
|
||||||
db.insertMergedMangas(mergedMangaReferences).executeAsBlocking()
|
db.insertMergedMangas(mergedMangaReferences).executeAsBlocking()
|
||||||
|
|
||||||
val loadedMangaList = mangaConfigs.map { it.second.children }.flatten().mapNotNull { it.load(db, sourceManager) }.distinct()
|
val loadedMangaList = mangaConfigs.map { it.second.children }.flatten().mapNotNull { it.load(db, sourceManager) }.distinct()
|
||||||
@ -208,7 +180,7 @@ object EXHMigrations {
|
|||||||
.withQuery(
|
.withQuery(
|
||||||
Query.builder()
|
Query.builder()
|
||||||
.table(ChapterTable.TABLE)
|
.table(ChapterTable.TABLE)
|
||||||
.where("${ChapterTable.COL_MANGA_ID} IN (${mergedMangas.filter { it.id != null }.joinToString { it.id.toString() }})")
|
.where("${ChapterTable.COL_MANGA_ID} IN (${mergedMangas.joinToString { it.id.toString() }})")
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
.prepare()
|
.prepare()
|
||||||
@ -289,13 +261,9 @@ object EXHMigrations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Delete old mangadex trackers
|
// Delete old mangadex trackers
|
||||||
db.db.lowLevel().delete(
|
runBlocking {
|
||||||
DeleteQuery.builder()
|
handler.await { ehQueries.deleteBySyncId(6) }
|
||||||
.table(TrackTable.TABLE)
|
}
|
||||||
.where("${TrackTable.COL_SYNC_ID} = ?")
|
|
||||||
.whereArgs(6)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (oldVersion under 18) {
|
if (oldVersion under 18) {
|
||||||
val readerTheme = preferences.readerTheme().get()
|
val readerTheme = preferences.readerTheme().get()
|
||||||
@ -407,7 +375,7 @@ object EXHMigrations {
|
|||||||
}
|
}
|
||||||
if (oldVersion under 31) {
|
if (oldVersion under 31) {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
database.await(true) {
|
handler.await(true) {
|
||||||
prefs.getStringSet("eh_saved_searches", emptySet())?.forEach {
|
prefs.getStringSet("eh_saved_searches", emptySet())?.forEach {
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
val content = Json.decodeFromString<JsonObject>(it.substringAfter(':'))
|
val content = Json.decodeFromString<JsonObject>(it.substringAfter(':'))
|
||||||
@ -421,7 +389,7 @@ object EXHMigrations {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
database.await(true) {
|
handler.await(true) {
|
||||||
prefs.getStringSet("latest_tab_sources", emptySet())?.forEach {
|
prefs.getStringSet("latest_tab_sources", emptySet())?.forEach {
|
||||||
feed_saved_searchQueries.insertFeedSavedSearch(
|
feed_saved_searchQueries.insertFeedSavedSearch(
|
||||||
_id = null,
|
_id = null,
|
||||||
@ -557,7 +525,7 @@ object EXHMigrations {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readMangaConfig(manga: SManga): MangaConfig? {
|
private fun readMangaConfig(manga: DomainManga): MangaConfig? {
|
||||||
return MangaConfig.readFromUrl(manga.url)
|
return MangaConfig.readFromUrl(manga.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,17 +554,8 @@ object EXHMigrations {
|
|||||||
private data class LoadedMangaSource(val source: Source, val manga: Manga)
|
private data class LoadedMangaSource(val source: Source, val manga: Manga)
|
||||||
|
|
||||||
private fun updateSourceId(newId: Long, oldId: Long) {
|
private fun updateSourceId(newId: Long, oldId: Long) {
|
||||||
db.lowLevel().executeSQL(
|
runBlocking {
|
||||||
RawQuery.builder()
|
handler.await { ehQueries.migrateSource(newId, oldId) }
|
||||||
.query(
|
}
|
||||||
"""
|
|
||||||
UPDATE ${MangaTable.TABLE}
|
|
||||||
SET ${MangaTable.COL_SOURCE} = $newId
|
|
||||||
WHERE ${MangaTable.COL_SOURCE} = $oldId
|
|
||||||
""".trimIndent(),
|
|
||||||
)
|
|
||||||
.affectsTables(MangaTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,7 @@ import eu.kanade.data.chapter.chapterMapper
|
|||||||
import eu.kanade.data.manga.mangaMapper
|
import eu.kanade.data.manga.mangaMapper
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
||||||
import eu.kanade.domain.chapter.model.Chapter
|
import eu.kanade.domain.chapter.model.Chapter
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaByUrlAndSource
|
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.domain.manga.model.toMangaInfo
|
import eu.kanade.domain.manga.model.toMangaInfo
|
||||||
@ -25,8 +24,7 @@ import uy.kohesive.injekt.api.get
|
|||||||
|
|
||||||
class GalleryAdder(
|
class GalleryAdder(
|
||||||
private val handler: DatabaseHandler = Injekt.get(),
|
private val handler: DatabaseHandler = Injekt.get(),
|
||||||
private val getMangaByUrlAndSource: GetMangaByUrlAndSource = Injekt.get(),
|
private val getManga: GetManga = Injekt.get(),
|
||||||
private val getMangaById: GetMangaById = Injekt.get(),
|
|
||||||
private val updateManga: UpdateManga = Injekt.get(),
|
private val updateManga: UpdateManga = Injekt.get(),
|
||||||
private val syncChaptersWithSource: SyncChaptersWithSource = Injekt.get(),
|
private val syncChaptersWithSource: SyncChaptersWithSource = Injekt.get(),
|
||||||
private val sourceManager: SourceManager = Injekt.get(),
|
private val sourceManager: SourceManager = Injekt.get(),
|
||||||
@ -120,7 +118,7 @@ class GalleryAdder(
|
|||||||
} ?: return GalleryAddEvent.Fail.UnknownType(url, context)
|
} ?: return GalleryAddEvent.Fail.UnknownType(url, context)
|
||||||
|
|
||||||
// Use manga in DB if possible, otherwise, make a new manga
|
// Use manga in DB if possible, otherwise, make a new manga
|
||||||
var manga = getMangaByUrlAndSource.await(cleanedMangaUrl, source.id)
|
var manga = getManga.await(cleanedMangaUrl, source.id)
|
||||||
?: handler.awaitOne(true) {
|
?: handler.awaitOne(true) {
|
||||||
// Insert created manga if not in DB before fetching details
|
// Insert created manga if not in DB before fetching details
|
||||||
// This allows us to keep the metadata when fetching details
|
// This allows us to keep the metadata when fetching details
|
||||||
@ -135,7 +133,7 @@ class GalleryAdder(
|
|||||||
// Fetch and copy details
|
// Fetch and copy details
|
||||||
val newManga = source.getMangaDetails(manga.toMangaInfo())
|
val newManga = source.getMangaDetails(manga.toMangaInfo())
|
||||||
updateManga.awaitUpdateFromSource(manga, newManga, false, Injekt.get())
|
updateManga.awaitUpdateFromSource(manga, newManga, false, Injekt.get())
|
||||||
manga = getMangaById.await(manga.id)!!
|
manga = getManga.await(manga.id)!!
|
||||||
|
|
||||||
if (fav) {
|
if (fav) {
|
||||||
updateManga.awaitUpdateFavorite(manga.id, true)
|
updateManga.awaitUpdateFavorite(manga.id, true)
|
||||||
|
@ -2,13 +2,16 @@ package exh.debug
|
|||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.pushtorefresh.storio.sqlite.queries.RawQuery
|
import eu.kanade.data.AndroidDatabaseHandler
|
||||||
import eu.kanade.data.DatabaseHandler
|
import eu.kanade.data.DatabaseHandler
|
||||||
import eu.kanade.data.manga.mangaMapper
|
import eu.kanade.domain.manga.interactor.GetAllManga
|
||||||
|
import eu.kanade.domain.manga.interactor.GetExhFavoriteMangaWithMetadata
|
||||||
import eu.kanade.domain.manga.interactor.GetFavorites
|
import eu.kanade.domain.manga.interactor.GetFavorites
|
||||||
|
import eu.kanade.domain.manga.interactor.GetFlatMetadataById
|
||||||
|
import eu.kanade.domain.manga.interactor.GetSearchMetadata
|
||||||
|
import eu.kanade.domain.manga.interactor.InsertFlatMetadata
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.manga.model.toMangaInfo
|
import eu.kanade.domain.manga.model.toMangaInfo
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
@ -17,18 +20,10 @@ import exh.EXHMigrations
|
|||||||
import exh.eh.EHentaiThrottleManager
|
import exh.eh.EHentaiThrottleManager
|
||||||
import exh.eh.EHentaiUpdateWorker
|
import exh.eh.EHentaiUpdateWorker
|
||||||
import exh.metadata.metadata.EHentaiSearchMetadata
|
import exh.metadata.metadata.EHentaiSearchMetadata
|
||||||
import exh.metadata.metadata.base.awaitFlatMetadataForManga
|
|
||||||
import exh.metadata.metadata.base.awaitInsertFlatMetadata
|
|
||||||
import exh.source.EH_SOURCE_ID
|
import exh.source.EH_SOURCE_ID
|
||||||
import exh.source.EXH_SOURCE_ID
|
import exh.source.EXH_SOURCE_ID
|
||||||
import exh.source.isEhBasedManga
|
|
||||||
import exh.source.nHentaiSourceIds
|
import exh.source.nHentaiSourceIds
|
||||||
import exh.util.cancellable
|
|
||||||
import exh.util.executeOnIO
|
|
||||||
import exh.util.jobScheduler
|
import exh.util.jobScheduler
|
||||||
import kotlinx.coroutines.flow.asFlow
|
|
||||||
import kotlinx.coroutines.flow.mapNotNull
|
|
||||||
import kotlinx.coroutines.flow.toList
|
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
@ -36,12 +31,16 @@ import java.util.UUID
|
|||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object DebugFunctions {
|
object DebugFunctions {
|
||||||
val app: Application by injectLazy()
|
val app: Application by injectLazy()
|
||||||
val db: DatabaseHelper by injectLazy()
|
|
||||||
val handler: DatabaseHandler by injectLazy()
|
val handler: DatabaseHandler by injectLazy()
|
||||||
val prefs: PreferencesHelper by injectLazy()
|
val prefs: PreferencesHelper by injectLazy()
|
||||||
val sourceManager: SourceManager by injectLazy()
|
val sourceManager: SourceManager by injectLazy()
|
||||||
val updateManga: UpdateManga by injectLazy()
|
val updateManga: UpdateManga by injectLazy()
|
||||||
val getFavorites: GetFavorites by injectLazy()
|
val getFavorites: GetFavorites by injectLazy()
|
||||||
|
val getFlatMetadataById: GetFlatMetadataById by injectLazy()
|
||||||
|
val insertFlatMetadata: InsertFlatMetadata by injectLazy()
|
||||||
|
val getExhFavoriteMangaWithMetadata: GetExhFavoriteMangaWithMetadata by injectLazy()
|
||||||
|
val getSearchMetadata: GetSearchMetadata by injectLazy()
|
||||||
|
val getAllManga: GetAllManga by injectLazy()
|
||||||
|
|
||||||
fun forceUpgradeMigration() {
|
fun forceUpgradeMigration() {
|
||||||
prefs.ehLastVersionCode().set(1)
|
prefs.ehLastVersionCode().set(1)
|
||||||
@ -55,18 +54,11 @@ object DebugFunctions {
|
|||||||
|
|
||||||
fun resetAgedFlagInEXHManga() {
|
fun resetAgedFlagInEXHManga() {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
val metadataManga = db.getFavoriteMangaWithMetadata().executeOnIO()
|
getExhFavoriteMangaWithMetadata.await().forEach { manga ->
|
||||||
|
val meta = getFlatMetadataById.await(manga.id)?.raise<EHentaiSearchMetadata>() ?: return@forEach
|
||||||
val allManga = metadataManga.asFlow().cancellable().mapNotNull { manga ->
|
|
||||||
if (manga.isEhBasedManga()) manga
|
|
||||||
else null
|
|
||||||
}.toList()
|
|
||||||
|
|
||||||
allManga.forEach { manga ->
|
|
||||||
val meta = handler.awaitFlatMetadataForManga(manga.id!!)?.raise<EHentaiSearchMetadata>() ?: return@forEach
|
|
||||||
// remove age flag
|
// remove age flag
|
||||||
meta.aged = false
|
meta.aged = false
|
||||||
handler.awaitInsertFlatMetadata(meta.flatten())
|
insertFlatMetadata.await(meta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,8 +69,7 @@ object DebugFunctions {
|
|||||||
fun resetEHGalleriesForUpdater() {
|
fun resetEHGalleriesForUpdater() {
|
||||||
throttleManager.resetThrottle()
|
throttleManager.resetThrottle()
|
||||||
runBlocking {
|
runBlocking {
|
||||||
val allManga = handler
|
val allManga = getExhFavoriteMangaWithMetadata.await()
|
||||||
.awaitList { mangasQueries.getEhMangaWithMetadata(EH_SOURCE_ID, EXH_SOURCE_ID, mangaMapper) }
|
|
||||||
|
|
||||||
val eh = sourceManager.get(EH_SOURCE_ID)
|
val eh = sourceManager.get(EH_SOURCE_ID)
|
||||||
val ex = sourceManager.get(EXH_SOURCE_ID)
|
val ex = sourceManager.get(EXH_SOURCE_ID)
|
||||||
@ -99,11 +90,8 @@ object DebugFunctions {
|
|||||||
|
|
||||||
fun getEHMangaListWithAgedFlagInfo(): String {
|
fun getEHMangaListWithAgedFlagInfo(): String {
|
||||||
return runBlocking {
|
return runBlocking {
|
||||||
val allManga = handler
|
getExhFavoriteMangaWithMetadata.await().map { manga ->
|
||||||
.awaitList { mangasQueries.getEhMangaWithMetadata(EH_SOURCE_ID, EXH_SOURCE_ID, mangaMapper) }
|
val meta = getFlatMetadataById.await(manga.id)?.raise<EHentaiSearchMetadata>() ?: return@map
|
||||||
|
|
||||||
allManga.map { manga ->
|
|
||||||
val meta = handler.awaitFlatMetadataForManga(manga.id)?.raise<EHentaiSearchMetadata>() ?: return@map
|
|
||||||
"Aged: ${meta.aged}\t Title: ${manga.title}"
|
"Aged: ${meta.aged}\t Title: ${manga.title}"
|
||||||
}
|
}
|
||||||
}.joinToString(",\n")
|
}.joinToString(",\n")
|
||||||
@ -111,10 +99,9 @@ object DebugFunctions {
|
|||||||
|
|
||||||
fun countAgedFlagInEXHManga(): Int {
|
fun countAgedFlagInEXHManga(): Int {
|
||||||
return runBlocking {
|
return runBlocking {
|
||||||
handler
|
getExhFavoriteMangaWithMetadata.await()
|
||||||
.awaitList { mangasQueries.getEhMangaWithMetadata(EH_SOURCE_ID, EXH_SOURCE_ID, mangaMapper) }
|
|
||||||
.count { manga ->
|
.count { manga ->
|
||||||
val meta = handler.awaitFlatMetadataForManga(manga.id)
|
val meta = getFlatMetadataById.await(manga.id)
|
||||||
?.raise<EHentaiSearchMetadata>()
|
?.raise<EHentaiSearchMetadata>()
|
||||||
?: return@count false
|
?: return@count false
|
||||||
meta.aged
|
meta.aged
|
||||||
@ -123,31 +110,30 @@ object DebugFunctions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun addAllMangaInDatabaseToLibrary() {
|
fun addAllMangaInDatabaseToLibrary() {
|
||||||
db.inTransaction {
|
(handler as AndroidDatabaseHandler).rawQuery {
|
||||||
db.lowLevel().executeSQL(
|
it.execute(
|
||||||
RawQuery.builder()
|
null,
|
||||||
.query(
|
"""
|
||||||
"""
|
UPDATE ${MangaTable.TABLE}
|
||||||
UPDATE ${MangaTable.TABLE}
|
SET ${MangaTable.COL_FAVORITE} = 1
|
||||||
SET ${MangaTable.COL_FAVORITE} = 1
|
""".trimIndent(),
|
||||||
""".trimIndent(),
|
0,
|
||||||
)
|
|
||||||
.affectsTables(MangaTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun countMangaInDatabaseInLibrary() = runBlocking { getFavorites.await().size }
|
fun countMangaInDatabaseInLibrary() = runBlocking { getFavorites.await().size }
|
||||||
|
|
||||||
fun countMangaInDatabaseNotInLibrary() = db.getMangas().executeAsBlocking().count { !it.favorite }
|
fun countMangaInDatabaseNotInLibrary() = runBlocking { getAllManga.await() }.count { !it.favorite }
|
||||||
|
|
||||||
fun countMangaInDatabase() = db.getMangas().executeAsBlocking().size
|
fun countMangaInDatabase() = runBlocking { getAllManga.await() }.size
|
||||||
|
|
||||||
fun countMetadataInDatabase() = db.getSearchMetadata().executeAsBlocking().size
|
fun countMetadataInDatabase() = runBlocking { getSearchMetadata.await().size }
|
||||||
|
|
||||||
fun countMangaInLibraryWithMissingMetadata() = db.getMangas().executeAsBlocking().count {
|
fun countMangaInLibraryWithMissingMetadata() = runBlocking {
|
||||||
it.favorite && db.getSearchMetadataForManga(it.id!!).executeAsBlocking() == null
|
runBlocking { getAllManga.await() }.count {
|
||||||
|
it.favorite && getSearchMetadata.await(it.id) == null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearSavedSearches() = runBlocking { handler.await { saved_searchQueries.deleteAll() } }
|
fun clearSavedSearches() = runBlocking { handler.await { saved_searchQueries.deleteAll() } }
|
||||||
@ -214,18 +200,17 @@ object DebugFunctions {
|
|||||||
fun cancelAllScheduledJobs() = app.jobScheduler.cancelAll()
|
fun cancelAllScheduledJobs() = app.jobScheduler.cancelAll()
|
||||||
|
|
||||||
private fun convertSources(from: Long, to: Long) {
|
private fun convertSources(from: Long, to: Long) {
|
||||||
db.lowLevel().executeSQL(
|
(handler as AndroidDatabaseHandler).rawQuery {
|
||||||
RawQuery.builder()
|
it.execute(
|
||||||
.query(
|
null,
|
||||||
"""
|
"""
|
||||||
UPDATE ${MangaTable.TABLE}
|
UPDATE ${MangaTable.TABLE}
|
||||||
SET ${MangaTable.COL_SOURCE} = $to
|
SET ${MangaTable.COL_SOURCE} = $to
|
||||||
WHERE ${MangaTable.COL_SOURCE} = $from
|
WHERE ${MangaTable.COL_SOURCE} = $from
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
)
|
0,
|
||||||
.affectsTables(MangaTable.TABLE)
|
)
|
||||||
.build(),
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*fun copyEHentaiSavedSearchesToExhentai() {
|
/*fun copyEHentaiSavedSearchesToExhentai() {
|
||||||
@ -307,34 +292,28 @@ object DebugFunctions {
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
fun fixReaderViewerBackupBug() {
|
fun fixReaderViewerBackupBug() {
|
||||||
db.inTransaction {
|
(handler as AndroidDatabaseHandler).rawQuery {
|
||||||
db.lowLevel().executeSQL(
|
it.execute(
|
||||||
RawQuery.builder()
|
null,
|
||||||
.query(
|
"""
|
||||||
"""
|
UPDATE ${MangaTable.TABLE}
|
||||||
UPDATE ${MangaTable.TABLE}
|
SET ${MangaTable.COL_VIEWER} = 0
|
||||||
SET ${MangaTable.COL_VIEWER} = 0
|
WHERE ${MangaTable.COL_VIEWER} = -1
|
||||||
WHERE ${MangaTable.COL_VIEWER} = -1
|
""".trimIndent(),
|
||||||
""".trimIndent(),
|
0,
|
||||||
)
|
|
||||||
.affectsTables(MangaTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resetReaderViewerForAllManga() {
|
fun resetReaderViewerForAllManga() {
|
||||||
db.inTransaction {
|
(handler as AndroidDatabaseHandler).rawQuery {
|
||||||
db.lowLevel().executeSQL(
|
it.execute(
|
||||||
RawQuery.builder()
|
null,
|
||||||
.query(
|
"""
|
||||||
"""
|
UPDATE ${MangaTable.TABLE}
|
||||||
UPDATE ${MangaTable.TABLE}
|
SET ${MangaTable.COL_VIEWER} = 0
|
||||||
SET ${MangaTable.COL_VIEWER} = 0
|
""".trimIndent(),
|
||||||
""".trimIndent(),
|
0,
|
||||||
)
|
|
||||||
.affectsTables(MangaTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -344,34 +323,28 @@ object DebugFunctions {
|
|||||||
.also { it.remove(NHentai.otherId) }
|
.also { it.remove(NHentai.otherId) }
|
||||||
.joinToString(separator = ",")
|
.joinToString(separator = ",")
|
||||||
|
|
||||||
db.inTransaction {
|
(handler as AndroidDatabaseHandler).rawQuery {
|
||||||
db.lowLevel().executeSQL(
|
it.execute(
|
||||||
RawQuery.builder()
|
null,
|
||||||
.query(
|
"""
|
||||||
"""
|
UPDATE ${MangaTable.TABLE}
|
||||||
UPDATE ${MangaTable.TABLE}
|
SET ${MangaTable.COL_SOURCE} = ${NHentai.otherId}
|
||||||
SET ${MangaTable.COL_SOURCE} = ${NHentai.otherId}
|
WHERE ${MangaTable.COL_FAVORITE} = 1 AND ${MangaTable.COL_SOURCE} in ($sources)
|
||||||
WHERE ${MangaTable.COL_FAVORITE} = 1 AND ${MangaTable.COL_SOURCE} in ($sources)
|
""".trimIndent(),
|
||||||
""".trimIndent(),
|
0,
|
||||||
)
|
|
||||||
.affectsTables(MangaTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resetFilteredScanlatorsForAllManga() {
|
fun resetFilteredScanlatorsForAllManga() {
|
||||||
db.inTransaction {
|
(handler as AndroidDatabaseHandler).rawQuery {
|
||||||
db.lowLevel().executeSQL(
|
it.execute(
|
||||||
RawQuery.builder()
|
null,
|
||||||
.query(
|
"""
|
||||||
"""
|
UPDATE ${MangaTable.TABLE}
|
||||||
UPDATE ${MangaTable.TABLE}
|
SET ${MangaTable.COL_FILTERED_SCANLATORS} = NULL
|
||||||
SET ${MangaTable.COL_FILTERED_SCANLATORS} = NULL
|
""".trimIndent(),
|
||||||
""".trimIndent(),
|
0,
|
||||||
)
|
|
||||||
.affectsTables(MangaTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import eu.kanade.domain.history.interactor.RemoveHistoryById
|
|||||||
import eu.kanade.domain.history.interactor.UpsertHistory
|
import eu.kanade.domain.history.interactor.UpsertHistory
|
||||||
import eu.kanade.domain.history.model.History
|
import eu.kanade.domain.history.model.History
|
||||||
import eu.kanade.domain.history.model.HistoryUpdate
|
import eu.kanade.domain.history.model.HistoryUpdate
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.domain.manga.model.MangaUpdate
|
import eu.kanade.domain.manga.model.MangaUpdate
|
||||||
@ -37,7 +37,7 @@ class EHentaiUpdateHelper(context: Context) {
|
|||||||
)
|
)
|
||||||
private val handler: DatabaseHandler by injectLazy()
|
private val handler: DatabaseHandler by injectLazy()
|
||||||
private val getChapterByMangaId: GetChapterByMangaId by injectLazy()
|
private val getChapterByMangaId: GetChapterByMangaId by injectLazy()
|
||||||
private val getMangaById: GetMangaById by injectLazy()
|
private val getManga: GetManga by injectLazy()
|
||||||
private val updateManga: UpdateManga by injectLazy()
|
private val updateManga: UpdateManga by injectLazy()
|
||||||
private val setMangaCategories: SetMangaCategories by injectLazy()
|
private val setMangaCategories: SetMangaCategories by injectLazy()
|
||||||
private val getCategories: GetCategories by injectLazy()
|
private val getCategories: GetCategories by injectLazy()
|
||||||
@ -64,7 +64,7 @@ class EHentaiUpdateHelper(context: Context) {
|
|||||||
.mapNotNull { mangaId ->
|
.mapNotNull { mangaId ->
|
||||||
coroutineScope {
|
coroutineScope {
|
||||||
val manga = async(Dispatchers.IO) {
|
val manga = async(Dispatchers.IO) {
|
||||||
getMangaById.await(mangaId)
|
getManga.await(mangaId)
|
||||||
}
|
}
|
||||||
val chapterList = async(Dispatchers.IO) {
|
val chapterList = async(Dispatchers.IO) {
|
||||||
getChapterByMangaId.await(mangaId)
|
getChapterByMangaId.await(mangaId)
|
||||||
|
@ -21,7 +21,6 @@ import eu.kanade.domain.manga.interactor.UpdateManga
|
|||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.domain.manga.model.toDbManga
|
import eu.kanade.domain.manga.model.toDbManga
|
||||||
import eu.kanade.domain.manga.model.toMangaInfo
|
import eu.kanade.domain.manga.model.toMangaInfo
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateNotifier
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateNotifier
|
||||||
import eu.kanade.tachiyomi.data.preference.DEVICE_CHARGING
|
import eu.kanade.tachiyomi.data.preference.DEVICE_CHARGING
|
||||||
import eu.kanade.tachiyomi.data.preference.DEVICE_ONLY_ON_WIFI
|
import eu.kanade.tachiyomi.data.preference.DEVICE_ONLY_ON_WIFI
|
||||||
@ -35,7 +34,7 @@ import exh.eh.EHentaiUpdateWorkerConstants.UPDATES_PER_ITERATION
|
|||||||
import exh.log.xLog
|
import exh.log.xLog
|
||||||
import exh.metadata.metadata.EHentaiSearchMetadata
|
import exh.metadata.metadata.EHentaiSearchMetadata
|
||||||
import exh.metadata.metadata.base.awaitFlatMetadataForManga
|
import exh.metadata.metadata.base.awaitFlatMetadataForManga
|
||||||
import exh.metadata.metadata.base.insertFlatMetadataAsync
|
import exh.metadata.metadata.base.awaitInsertFlatMetadata
|
||||||
import exh.source.EH_SOURCE_ID
|
import exh.source.EH_SOURCE_ID
|
||||||
import exh.source.EXH_SOURCE_ID
|
import exh.source.EXH_SOURCE_ID
|
||||||
import exh.source.isEhBasedManga
|
import exh.source.isEhBasedManga
|
||||||
@ -54,7 +53,6 @@ import kotlin.time.Duration.Companion.days
|
|||||||
|
|
||||||
class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerParameters) :
|
class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerParameters) :
|
||||||
CoroutineWorker(context, workerParams) {
|
CoroutineWorker(context, workerParams) {
|
||||||
private val db: DatabaseHelper by injectLazy()
|
|
||||||
private val handler: DatabaseHandler by injectLazy()
|
private val handler: DatabaseHandler by injectLazy()
|
||||||
private val prefs: PreferencesHelper by injectLazy()
|
private val prefs: PreferencesHelper by injectLazy()
|
||||||
private val sourceManager: SourceManager by injectLazy()
|
private val sourceManager: SourceManager by injectLazy()
|
||||||
@ -228,7 +226,7 @@ class EHentaiUpdateWorker(private val context: Context, workerParams: WorkerPara
|
|||||||
// Age dead galleries
|
// Age dead galleries
|
||||||
logger.d("Aged %s - notfound", manga.id)
|
logger.d("Aged %s - notfound", manga.id)
|
||||||
meta.aged = true
|
meta.aged = true
|
||||||
db.insertFlatMetadataAsync(meta.flatten()).await()
|
handler.awaitInsertFlatMetadata(meta.flatten())
|
||||||
}
|
}
|
||||||
throw GalleryNotUpdatedException(false, t)
|
throw GalleryNotUpdatedException(false, t)
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import eu.kanade.data.DatabaseHandler
|
|||||||
import eu.kanade.domain.category.interactor.GetCategories
|
import eu.kanade.domain.category.interactor.GetCategories
|
||||||
import eu.kanade.domain.category.interactor.SetMangaCategories
|
import eu.kanade.domain.category.interactor.SetMangaCategories
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaByUrlAndSource
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
@ -50,7 +50,7 @@ import kotlin.time.Duration.Companion.seconds
|
|||||||
class FavoritesSyncHelper(val context: Context) {
|
class FavoritesSyncHelper(val context: Context) {
|
||||||
private val handler: DatabaseHandler by injectLazy()
|
private val handler: DatabaseHandler by injectLazy()
|
||||||
private val getCategories: GetCategories by injectLazy()
|
private val getCategories: GetCategories by injectLazy()
|
||||||
private val getMangaByUrlAndSource: GetMangaByUrlAndSource by injectLazy()
|
private val getManga: GetManga by injectLazy()
|
||||||
private val updateManga: UpdateManga by injectLazy()
|
private val updateManga: UpdateManga by injectLazy()
|
||||||
private val setMangaCategories: SetMangaCategories by injectLazy()
|
private val setMangaCategories: SetMangaCategories by injectLazy()
|
||||||
|
|
||||||
@ -332,7 +332,7 @@ class FavoritesSyncHelper(val context: Context) {
|
|||||||
EXH_SOURCE_ID,
|
EXH_SOURCE_ID,
|
||||||
EH_SOURCE_ID,
|
EH_SOURCE_ID,
|
||||||
).forEach {
|
).forEach {
|
||||||
val manga = getMangaByUrlAndSource.await(url, it)
|
val manga = getManga.await(url, it)
|
||||||
|
|
||||||
if (manga?.favorite == true) {
|
if (manga?.favorite == true) {
|
||||||
updateManga.awaitUpdateFavorite(manga.id, false)
|
updateManga.awaitUpdateFavorite(manga.id, false)
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package exh.favorites
|
package exh.favorites
|
||||||
|
|
||||||
import eu.kanade.data.DatabaseHandler
|
|
||||||
import eu.kanade.data.exh.favoriteEntryMapper
|
|
||||||
import eu.kanade.domain.category.interactor.GetCategories
|
import eu.kanade.domain.category.interactor.GetCategories
|
||||||
|
import eu.kanade.domain.manga.interactor.DeleteFavoriteEntries
|
||||||
|
import eu.kanade.domain.manga.interactor.GetFavoriteEntries
|
||||||
import eu.kanade.domain.manga.interactor.GetFavorites
|
import eu.kanade.domain.manga.interactor.GetFavorites
|
||||||
|
import eu.kanade.domain.manga.interactor.InsertFavoriteEntries
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.models.toDomainManga
|
import eu.kanade.tachiyomi.data.database.models.toDomainManga
|
||||||
import eu.kanade.tachiyomi.source.online.all.EHentai
|
import eu.kanade.tachiyomi.source.online.all.EHentai
|
||||||
@ -19,9 +20,11 @@ import kotlinx.coroutines.flow.toList
|
|||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
class LocalFavoritesStorage {
|
class LocalFavoritesStorage {
|
||||||
private val handler: DatabaseHandler by injectLazy()
|
|
||||||
private val getFavorites: GetFavorites by injectLazy()
|
private val getFavorites: GetFavorites by injectLazy()
|
||||||
private val getCategories: GetCategories by injectLazy()
|
private val getCategories: GetCategories by injectLazy()
|
||||||
|
private val deleteFavoriteEntries: DeleteFavoriteEntries by injectLazy()
|
||||||
|
private val getFavoriteEntries: GetFavoriteEntries by injectLazy()
|
||||||
|
private val insertFavoriteEntries: InsertFavoriteEntries by injectLazy()
|
||||||
|
|
||||||
suspend fun getChangedDbEntries() = getFavorites.await()
|
suspend fun getChangedDbEntries() = getFavorites.await()
|
||||||
.asFlow()
|
.asFlow()
|
||||||
@ -48,30 +51,20 @@ class LocalFavoritesStorage {
|
|||||||
.parseToFavoriteEntries()
|
.parseToFavoriteEntries()
|
||||||
|
|
||||||
// Delete old snapshot
|
// Delete old snapshot
|
||||||
handler.await { eh_favoritesQueries.deleteAll() }
|
deleteFavoriteEntries.await()
|
||||||
|
|
||||||
// Insert new snapshots
|
// Insert new snapshots
|
||||||
handler.await(true) {
|
insertFavoriteEntries.await(dbMangas.toList())
|
||||||
dbMangas.toList().forEach {
|
|
||||||
eh_favoritesQueries.insertEhFavorites(
|
|
||||||
it.id,
|
|
||||||
it.title,
|
|
||||||
it.gid,
|
|
||||||
it.token,
|
|
||||||
it.category.toLong(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun clearSnapshots() {
|
suspend fun clearSnapshots() {
|
||||||
handler.await { eh_favoritesQueries.deleteAll() }
|
deleteFavoriteEntries.await()
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun Flow<FavoriteEntry>.getChangedEntries(): ChangeSet {
|
private suspend fun Flow<FavoriteEntry>.getChangedEntries(): ChangeSet {
|
||||||
val terminated = toList()
|
val terminated = toList()
|
||||||
|
|
||||||
val databaseEntries = handler.awaitList { eh_favoritesQueries.selectAll(favoriteEntryMapper) }
|
val databaseEntries = getFavoriteEntries.await()
|
||||||
|
|
||||||
val added = terminated.filter {
|
val added = terminated.filter {
|
||||||
queryListForEntry(databaseEntries, it) == null
|
queryListForEntry(databaseEntries, it) == null
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
package exh.favorites.sql.mappers
|
|
||||||
|
|
||||||
import android.database.Cursor
|
|
||||||
import androidx.core.content.contentValuesOf
|
|
||||||
import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping
|
|
||||||
import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver
|
|
||||||
import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
|
|
||||||
import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.InsertQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
|
|
||||||
import exh.favorites.sql.models.FavoriteEntry
|
|
||||||
import exh.favorites.sql.tables.FavoriteEntryTable.COL_CATEGORY
|
|
||||||
import exh.favorites.sql.tables.FavoriteEntryTable.COL_GID
|
|
||||||
import exh.favorites.sql.tables.FavoriteEntryTable.COL_ID
|
|
||||||
import exh.favorites.sql.tables.FavoriteEntryTable.COL_TITLE
|
|
||||||
import exh.favorites.sql.tables.FavoriteEntryTable.COL_TOKEN
|
|
||||||
import exh.favorites.sql.tables.FavoriteEntryTable.TABLE
|
|
||||||
|
|
||||||
class FavoriteEntryTypeMapping : SQLiteTypeMapping<FavoriteEntry>(
|
|
||||||
FavoriteEntryPutResolver(),
|
|
||||||
FavoriteEntryGetResolver(),
|
|
||||||
FavoriteEntryDeleteResolver(),
|
|
||||||
)
|
|
||||||
|
|
||||||
class FavoriteEntryPutResolver : DefaultPutResolver<FavoriteEntry>() {
|
|
||||||
|
|
||||||
override fun mapToInsertQuery(obj: FavoriteEntry) = InsertQuery.builder()
|
|
||||||
.table(TABLE)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
override fun mapToUpdateQuery(obj: FavoriteEntry) = UpdateQuery.builder()
|
|
||||||
.table(TABLE)
|
|
||||||
.where("$COL_ID = ?")
|
|
||||||
.whereArgs(obj.id)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
override fun mapToContentValues(obj: FavoriteEntry) = contentValuesOf(
|
|
||||||
COL_ID to obj.id,
|
|
||||||
COL_TITLE to obj.title,
|
|
||||||
COL_GID to obj.gid,
|
|
||||||
COL_TOKEN to obj.token,
|
|
||||||
COL_CATEGORY to obj.category,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
class FavoriteEntryGetResolver : DefaultGetResolver<FavoriteEntry>() {
|
|
||||||
|
|
||||||
override fun mapFromCursor(cursor: Cursor): FavoriteEntry = FavoriteEntry(
|
|
||||||
id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID)),
|
|
||||||
title = cursor.getString(cursor.getColumnIndexOrThrow(COL_TITLE)),
|
|
||||||
gid = cursor.getString(cursor.getColumnIndexOrThrow(COL_GID)),
|
|
||||||
token = cursor.getString(cursor.getColumnIndexOrThrow(COL_TOKEN)),
|
|
||||||
category = cursor.getInt(cursor.getColumnIndexOrThrow(COL_CATEGORY)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
class FavoriteEntryDeleteResolver : DefaultDeleteResolver<FavoriteEntry>() {
|
|
||||||
|
|
||||||
override fun mapToDeleteQuery(obj: FavoriteEntry) = DeleteQuery.builder()
|
|
||||||
.table(TABLE)
|
|
||||||
.where("$COL_ID = ?")
|
|
||||||
.whereArgs(obj.id)
|
|
||||||
.build()
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
package exh.favorites.sql.queries
|
|
||||||
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
|
||||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
|
||||||
import exh.favorites.sql.models.FavoriteEntry
|
|
||||||
import exh.favorites.sql.tables.FavoriteEntryTable
|
|
||||||
|
|
||||||
interface FavoriteEntryQueries : DbProvider {
|
|
||||||
fun getFavoriteEntries() = db.get()
|
|
||||||
.listOfObjects(FavoriteEntry::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(FavoriteEntryTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun insertFavoriteEntries(favoriteEntries: List<FavoriteEntry>) = db.put()
|
|
||||||
.objects(favoriteEntries)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun deleteAllFavoriteEntries() = db.delete()
|
|
||||||
.byQuery(
|
|
||||||
DeleteQuery.builder()
|
|
||||||
.table(FavoriteEntryTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package exh.favorites.sql.tables
|
|
||||||
|
|
||||||
object FavoriteEntryTable {
|
|
||||||
|
|
||||||
const val TABLE = "eh_favorites"
|
|
||||||
|
|
||||||
const val COL_ID = "_id"
|
|
||||||
|
|
||||||
const val COL_TITLE = "title"
|
|
||||||
|
|
||||||
const val COL_GID = "gid"
|
|
||||||
|
|
||||||
const val COL_TOKEN = "token"
|
|
||||||
|
|
||||||
const val COL_CATEGORY = "category"
|
|
||||||
}
|
|
@ -1,7 +1,8 @@
|
|||||||
package exh.md.handlers
|
package exh.md.handlers
|
||||||
|
|
||||||
import eu.kanade.data.DatabaseHandler
|
import eu.kanade.domain.manga.interactor.GetFlatMetadataById
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaByUrlAndSource
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
|
import eu.kanade.domain.manga.interactor.InsertFlatMetadata
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import exh.log.xLogE
|
import exh.log.xLogE
|
||||||
import exh.md.dto.ChapterDataDto
|
import exh.md.dto.ChapterDataDto
|
||||||
@ -13,8 +14,6 @@ import exh.md.utils.MdUtil
|
|||||||
import exh.md.utils.asMdMap
|
import exh.md.utils.asMdMap
|
||||||
import exh.metadata.metadata.MangaDexSearchMetadata
|
import exh.metadata.metadata.MangaDexSearchMetadata
|
||||||
import exh.metadata.metadata.base.RaisedTag
|
import exh.metadata.metadata.base.RaisedTag
|
||||||
import exh.metadata.metadata.base.awaitFlatMetadataForManga
|
|
||||||
import exh.metadata.metadata.base.awaitInsertFlatMetadata
|
|
||||||
import exh.util.capitalize
|
import exh.util.capitalize
|
||||||
import exh.util.floor
|
import exh.util.floor
|
||||||
import exh.util.nullIfEmpty
|
import exh.util.nullIfEmpty
|
||||||
@ -26,8 +25,9 @@ import java.util.Locale
|
|||||||
class ApiMangaParser(
|
class ApiMangaParser(
|
||||||
private val lang: String,
|
private val lang: String,
|
||||||
) {
|
) {
|
||||||
private val handler: DatabaseHandler by injectLazy()
|
private val getManga: GetManga by injectLazy()
|
||||||
private val getMangaByUrlAndSource: GetMangaByUrlAndSource by injectLazy()
|
private val insertFlatMetadata: InsertFlatMetadata by injectLazy()
|
||||||
|
private val getFlatMetadataById: GetFlatMetadataById by injectLazy()
|
||||||
|
|
||||||
val metaClass = MangaDexSearchMetadata::class
|
val metaClass = MangaDexSearchMetadata::class
|
||||||
|
|
||||||
@ -46,16 +46,16 @@ class ApiMangaParser(
|
|||||||
simpleChapters: List<String>,
|
simpleChapters: List<String>,
|
||||||
statistics: StatisticsMangaDto?,
|
statistics: StatisticsMangaDto?,
|
||||||
): MangaInfo {
|
): MangaInfo {
|
||||||
val mangaId = getMangaByUrlAndSource.await(manga.key, sourceId)?.id
|
val mangaId = getManga.await(manga.key, sourceId)?.id
|
||||||
val metadata = if (mangaId != null) {
|
val metadata = if (mangaId != null) {
|
||||||
val flatMetadata = handler.awaitFlatMetadataForManga(mangaId)
|
val flatMetadata = getFlatMetadataById.await(mangaId)
|
||||||
flatMetadata?.raise(metaClass) ?: newMetaInstance()
|
flatMetadata?.raise(metaClass) ?: newMetaInstance()
|
||||||
} else newMetaInstance()
|
} else newMetaInstance()
|
||||||
|
|
||||||
parseIntoMetadata(metadata, input, simpleChapters, statistics)
|
parseIntoMetadata(metadata, input, simpleChapters, statistics)
|
||||||
if (mangaId != null) {
|
if (mangaId != null) {
|
||||||
metadata.mangaId = mangaId
|
metadata.mangaId = mangaId
|
||||||
handler.awaitInsertFlatMetadata(metadata.flatten())
|
insertFlatMetadata.await(metadata.flatten())
|
||||||
}
|
}
|
||||||
|
|
||||||
return metadata.createMangaInfo(manga)
|
return metadata.createMangaInfo(manga)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package exh.md.similar
|
package exh.md.similar
|
||||||
|
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.online.all.MangaDex
|
import eu.kanade.tachiyomi.source.online.all.MangaDex
|
||||||
@ -17,14 +17,14 @@ import uy.kohesive.injekt.api.get
|
|||||||
class MangaDexSimilarPresenter(
|
class MangaDexSimilarPresenter(
|
||||||
val mangaId: Long,
|
val mangaId: Long,
|
||||||
sourceId: Long,
|
sourceId: Long,
|
||||||
private val getMangaById: GetMangaById = Injekt.get(),
|
private val getManga: GetManga = Injekt.get(),
|
||||||
) : BrowseSourcePresenter(sourceId) {
|
) : BrowseSourcePresenter(sourceId) {
|
||||||
|
|
||||||
var manga: Manga? = null
|
var manga: Manga? = null
|
||||||
|
|
||||||
override fun createPager(query: String, filters: FilterList): Pager {
|
override fun createPager(query: String, filters: FilterList): Pager {
|
||||||
val sourceAsMangaDex = source.getMainSource() as MangaDex
|
val sourceAsMangaDex = source.getMainSource() as MangaDex
|
||||||
this.manga = runBlocking { getMangaById.await(mangaId) }
|
this.manga = runBlocking { getManga.await(mangaId) }
|
||||||
return MangaDexSimilarPager(manga!!, sourceAsMangaDex)
|
return MangaDexSimilarPager(manga!!, sourceAsMangaDex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,9 @@ import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
|||||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
import com.pushtorefresh.storio.sqlite.queries.Query
|
||||||
import com.pushtorefresh.storio.sqlite.queries.RawQuery
|
import com.pushtorefresh.storio.sqlite.queries.RawQuery
|
||||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
import eu.kanade.tachiyomi.data.database.DbProvider
|
||||||
import eu.kanade.tachiyomi.data.database.inTransaction
|
|
||||||
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.queries.getAllMergedMangaQuery
|
|
||||||
import eu.kanade.tachiyomi.data.database.queries.getMergedChaptersQuery
|
|
||||||
import eu.kanade.tachiyomi.data.database.queries.getMergedMangaForDownloadingQuery
|
import eu.kanade.tachiyomi.data.database.queries.getMergedMangaForDownloadingQuery
|
||||||
import eu.kanade.tachiyomi.data.database.queries.getMergedMangaFromUrlQuery
|
|
||||||
import eu.kanade.tachiyomi.data.database.queries.getMergedMangaQuery
|
import eu.kanade.tachiyomi.data.database.queries.getMergedMangaQuery
|
||||||
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
|
|
||||||
import exh.merged.sql.models.MergedMangaReference
|
import exh.merged.sql.models.MergedMangaReference
|
||||||
import exh.merged.sql.resolvers.MergeMangaSettingsPutResolver
|
import exh.merged.sql.resolvers.MergeMangaSettingsPutResolver
|
||||||
import exh.merged.sql.resolvers.MergedMangaIdPutResolver
|
import exh.merged.sql.resolvers.MergedMangaIdPutResolver
|
||||||
@ -31,17 +25,6 @@ interface MergedQueries : DbProvider {
|
|||||||
)
|
)
|
||||||
.prepare()
|
.prepare()
|
||||||
|
|
||||||
fun getMergedMangaReferences(mergedMangaUrl: String) = db.get()
|
|
||||||
.listOfObjects(MergedMangaReference::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(MergedTable.TABLE)
|
|
||||||
.where("${MergedTable.COL_MERGE_URL} = ?")
|
|
||||||
.whereArgs(mergedMangaUrl)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun deleteMangaForMergedManga(mergedMangaId: Long) = db.delete()
|
fun deleteMangaForMergedManga(mergedMangaId: Long) = db.delete()
|
||||||
.byQuery(
|
.byQuery(
|
||||||
DeleteQuery.builder()
|
DeleteQuery.builder()
|
||||||
@ -72,56 +55,6 @@ interface MergedQueries : DbProvider {
|
|||||||
)
|
)
|
||||||
.prepare()
|
.prepare()
|
||||||
|
|
||||||
fun getMergedMangas(mergedMangaUrl: String) = db.get()
|
|
||||||
.listOfObjects(Manga::class.java)
|
|
||||||
.withQuery(
|
|
||||||
RawQuery.builder()
|
|
||||||
.query(getMergedMangaFromUrlQuery())
|
|
||||||
.args(mergedMangaUrl)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun getMergedMangas() = db.get()
|
|
||||||
.listOfObjects(Manga::class.java)
|
|
||||||
.withQuery(
|
|
||||||
RawQuery.builder()
|
|
||||||
.query(getAllMergedMangaQuery())
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun deleteMangaForMergedManga(mergedMangaUrl: String) = db.delete()
|
|
||||||
.byQuery(
|
|
||||||
DeleteQuery.builder()
|
|
||||||
.table(MergedTable.TABLE)
|
|
||||||
.where("${MergedTable.COL_MERGE_URL} = ?")
|
|
||||||
.whereArgs(mergedMangaUrl)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun getMergedMangaReferences() = db.get()
|
|
||||||
.listOfObjects(MergedMangaReference::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(MergedTable.TABLE)
|
|
||||||
.orderBy(MergedTable.COL_ID)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun getChaptersByMergedMangaId(mergedMangaId: Long) = db.get()
|
|
||||||
.listOfObjects(Chapter::class.java)
|
|
||||||
.withQuery(
|
|
||||||
RawQuery.builder()
|
|
||||||
.query(getMergedChaptersQuery())
|
|
||||||
.args(mergedMangaId)
|
|
||||||
.observesTables(ChapterTable.TABLE, MergedTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun insertMergedManga(mergedManga: MergedMangaReference) = db.put().`object`(mergedManga).prepare()
|
fun insertMergedManga(mergedManga: MergedMangaReference) = db.put().`object`(mergedManga).prepare()
|
||||||
|
|
||||||
fun insertNewMergedMangaId(mergedManga: MergedMangaReference) = db.put().`object`(mergedManga).withPutResolver(MergedMangaIdPutResolver()).prepare()
|
fun insertNewMergedMangaId(mergedManga: MergedMangaReference) = db.put().`object`(mergedManga).withPutResolver(MergedMangaIdPutResolver()).prepare()
|
||||||
@ -133,20 +66,4 @@ interface MergedQueries : DbProvider {
|
|||||||
fun updateMergeMangaSettings(mergeManga: MergedMangaReference) = db.put().`object`(mergeManga).withPutResolver(MergeMangaSettingsPutResolver()).prepare()
|
fun updateMergeMangaSettings(mergeManga: MergedMangaReference) = db.put().`object`(mergeManga).withPutResolver(MergeMangaSettingsPutResolver()).prepare()
|
||||||
|
|
||||||
fun deleteMergedManga(mergedManga: MergedMangaReference) = db.delete().`object`(mergedManga).prepare()
|
fun deleteMergedManga(mergedManga: MergedMangaReference) = db.delete().`object`(mergedManga).prepare()
|
||||||
|
|
||||||
fun deleteAllMergedManga() = db.delete().byQuery(
|
|
||||||
DeleteQuery.builder()
|
|
||||||
.table(MergedTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun setMangasForMergedManga(mergedMangaId: Long, mergedMangas: List<MergedMangaReference>) {
|
|
||||||
db.inTransaction {
|
|
||||||
deleteMangaForMergedManga(mergedMangaId).executeAsBlocking()
|
|
||||||
mergedMangas.chunked(100) { chunk ->
|
|
||||||
insertMergedMangas(chunk).executeAsBlocking()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,15 @@
|
|||||||
package exh.metadata.metadata.base
|
package exh.metadata.metadata.base
|
||||||
|
|
||||||
import com.pushtorefresh.storio.operations.PreparedOperation
|
|
||||||
import eu.kanade.data.AndroidDatabaseHandler
|
|
||||||
import eu.kanade.data.DatabaseHandler
|
import eu.kanade.data.DatabaseHandler
|
||||||
import eu.kanade.data.exh.searchMetadataMapper
|
import eu.kanade.data.exh.searchMetadataMapper
|
||||||
import eu.kanade.data.exh.searchTagMapper
|
import eu.kanade.data.exh.searchTagMapper
|
||||||
import eu.kanade.data.exh.searchTitleMapper
|
import eu.kanade.data.exh.searchTitleMapper
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|
||||||
import exh.metadata.sql.models.SearchMetadata
|
import exh.metadata.sql.models.SearchMetadata
|
||||||
import exh.metadata.sql.models.SearchTag
|
import exh.metadata.sql.models.SearchTag
|
||||||
import exh.metadata.sql.models.SearchTitle
|
import exh.metadata.sql.models.SearchTitle
|
||||||
import kotlinx.coroutines.Deferred
|
|
||||||
import kotlinx.coroutines.async
|
|
||||||
import kotlinx.coroutines.coroutineScope
|
|
||||||
import kotlinx.serialization.InternalSerializationApi
|
import kotlinx.serialization.InternalSerializationApi
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.serializer
|
import kotlinx.serialization.serializer
|
||||||
import rx.Completable
|
|
||||||
import rx.Single
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -36,17 +28,7 @@ data class FlatMetadata(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun DatabaseHandler.getFlatMetadataForManga(mangaId: Long): FlatMetadata? {
|
@Deprecated("Replace with GetFlatMetadataById")
|
||||||
this as AndroidDatabaseHandler
|
|
||||||
val meta = db.search_metadataQueries.selectByMangaId(mangaId, searchMetadataMapper).executeAsOneOrNull()
|
|
||||||
return if (meta != null) {
|
|
||||||
val tags = db.search_tagsQueries.selectByMangaId(mangaId, searchTagMapper).executeAsList()
|
|
||||||
val titles = db.search_titlesQueries.selectByMangaId(mangaId, searchTitleMapper).executeAsList()
|
|
||||||
|
|
||||||
FlatMetadata(meta, tags, titles)
|
|
||||||
} else null
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun DatabaseHandler.awaitFlatMetadataForManga(mangaId: Long): FlatMetadata? {
|
suspend fun DatabaseHandler.awaitFlatMetadataForManga(mangaId: Long): FlatMetadata? {
|
||||||
return await {
|
return await {
|
||||||
val meta = search_metadataQueries.selectByMangaId(mangaId, searchMetadataMapper).executeAsOneOrNull()
|
val meta = search_metadataQueries.selectByMangaId(mangaId, searchMetadataMapper).executeAsOneOrNull()
|
||||||
@ -59,86 +41,7 @@ suspend fun DatabaseHandler.awaitFlatMetadataForManga(mangaId: Long): FlatMetada
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun DatabaseHelper.getFlatMetadataForManga(mangaId: Long): PreparedOperation<FlatMetadata?> {
|
@Deprecated("Replace with InsertFlatMetadata")
|
||||||
// We have to use fromCallable because StorIO messes up the thread scheduling if we use their rx functions
|
|
||||||
val single = Single.fromCallable {
|
|
||||||
val meta = getSearchMetadataForManga(mangaId).executeAsBlocking()
|
|
||||||
if (meta != null) {
|
|
||||||
val tags = getSearchTagsForManga(mangaId).executeAsBlocking()
|
|
||||||
val titles = getSearchTitlesForManga(mangaId).executeAsBlocking()
|
|
||||||
|
|
||||||
FlatMetadata(meta, tags, titles)
|
|
||||||
} else null
|
|
||||||
}
|
|
||||||
|
|
||||||
return preparedOperationFromSingle(single)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <T> preparedOperationFromSingle(single: Single<T>): PreparedOperation<T> {
|
|
||||||
return object : PreparedOperation<T> {
|
|
||||||
/**
|
|
||||||
* Creates [rx.Observable] that emits result of Operation.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Observable may be "Hot" or "Cold", please read documentation of the concrete implementation.
|
|
||||||
*
|
|
||||||
* @return observable result of operation with only one [rx.Observer.onNext] call.
|
|
||||||
*/
|
|
||||||
override fun createObservable() = single.toObservable()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes operation synchronously in current thread.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Notice: Blocking I/O operation should not be executed on the Main Thread,
|
|
||||||
* it can cause ANR (Activity Not Responding dialog), block the UI and drop animations frames.
|
|
||||||
* So please, execute blocking I/O operation only from background thread.
|
|
||||||
* See [androidx.annotation.WorkerThread].
|
|
||||||
*
|
|
||||||
* @return nullable result of operation.
|
|
||||||
*/
|
|
||||||
override fun executeAsBlocking() = single.toBlocking().value()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates [rx.Observable] that emits result of Operation.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Observable may be "Hot" (usually "Warm") or "Cold", please read documentation of the concrete implementation.
|
|
||||||
*
|
|
||||||
* @return observable result of operation with only one [rx.Observer.onNext] call.
|
|
||||||
*/
|
|
||||||
override fun asRxObservable() = single.toObservable()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates [rx.Single] that emits result of Operation lazily when somebody subscribes to it.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return single result of operation.
|
|
||||||
*/
|
|
||||||
override fun asRxSingle() = single
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun DatabaseHandler.insertFlatMetadata(flatMetadata: FlatMetadata) {
|
|
||||||
require(flatMetadata.metadata.mangaId != -1L)
|
|
||||||
|
|
||||||
this as AndroidDatabaseHandler // todo remove when legacy backup is dead
|
|
||||||
db.transaction {
|
|
||||||
flatMetadata.metadata.let {
|
|
||||||
db.search_metadataQueries.upsert(it.mangaId, it.uploader, it.extra, it.indexedExtra, it.extraVersion)
|
|
||||||
}
|
|
||||||
db.search_tagsQueries.deleteByManga(flatMetadata.metadata.mangaId)
|
|
||||||
flatMetadata.tags.forEach {
|
|
||||||
db.search_tagsQueries.insert(it.mangaId, it.namespace, it.name, it.type)
|
|
||||||
}
|
|
||||||
db.search_titlesQueries.deleteByManga(flatMetadata.metadata.mangaId)
|
|
||||||
flatMetadata.titles.forEach {
|
|
||||||
db.search_titlesQueries.insert(it.mangaId, it.title, it.type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun DatabaseHandler.awaitInsertFlatMetadata(flatMetadata: FlatMetadata) {
|
suspend fun DatabaseHandler.awaitInsertFlatMetadata(flatMetadata: FlatMetadata) {
|
||||||
require(flatMetadata.metadata.mangaId != -1L)
|
require(flatMetadata.metadata.mangaId != -1L)
|
||||||
|
|
||||||
@ -156,29 +59,3 @@ suspend fun DatabaseHandler.awaitInsertFlatMetadata(flatMetadata: FlatMetadata)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun DatabaseHelper.insertFlatMetadata(flatMetadata: FlatMetadata) {
|
|
||||||
require(flatMetadata.metadata.mangaId != -1L)
|
|
||||||
|
|
||||||
inTransaction {
|
|
||||||
insertSearchMetadata(flatMetadata.metadata).executeAsBlocking()
|
|
||||||
setSearchTagsForManga(flatMetadata.metadata.mangaId, flatMetadata.tags)
|
|
||||||
setSearchTitlesForManga(flatMetadata.metadata.mangaId, flatMetadata.titles)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun DatabaseHelper.insertFlatMetadataCompletable(flatMetadata: FlatMetadata): Completable = Completable.fromCallable {
|
|
||||||
insertFlatMetadata(flatMetadata)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun DatabaseHelper.insertFlatMetadataAsync(flatMetadata: FlatMetadata): Deferred<Unit> = coroutineScope {
|
|
||||||
async {
|
|
||||||
require(flatMetadata.metadata.mangaId != -1L)
|
|
||||||
|
|
||||||
inTransaction {
|
|
||||||
insertSearchMetadata(flatMetadata.metadata).executeAsBlocking()
|
|
||||||
setSearchTagsForManga(flatMetadata.metadata.mangaId, flatMetadata.tags)
|
|
||||||
setSearchTitlesForManga(flatMetadata.metadata.mangaId, flatMetadata.titles)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
package exh.metadata.sql.mappers
|
|
||||||
|
|
||||||
import android.database.Cursor
|
|
||||||
import androidx.core.content.contentValuesOf
|
|
||||||
import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping
|
|
||||||
import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver
|
|
||||||
import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
|
|
||||||
import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.InsertQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
|
|
||||||
import exh.metadata.sql.models.SearchMetadata
|
|
||||||
import exh.metadata.sql.tables.SearchMetadataTable.COL_EXTRA
|
|
||||||
import exh.metadata.sql.tables.SearchMetadataTable.COL_EXTRA_VERSION
|
|
||||||
import exh.metadata.sql.tables.SearchMetadataTable.COL_INDEXED_EXTRA
|
|
||||||
import exh.metadata.sql.tables.SearchMetadataTable.COL_MANGA_ID
|
|
||||||
import exh.metadata.sql.tables.SearchMetadataTable.COL_UPLOADER
|
|
||||||
import exh.metadata.sql.tables.SearchMetadataTable.TABLE
|
|
||||||
|
|
||||||
class SearchMetadataTypeMapping : SQLiteTypeMapping<SearchMetadata>(
|
|
||||||
SearchMetadataPutResolver(),
|
|
||||||
SearchMetadataGetResolver(),
|
|
||||||
SearchMetadataDeleteResolver(),
|
|
||||||
)
|
|
||||||
|
|
||||||
class SearchMetadataPutResolver : DefaultPutResolver<SearchMetadata>() {
|
|
||||||
|
|
||||||
override fun mapToInsertQuery(obj: SearchMetadata) = InsertQuery.builder()
|
|
||||||
.table(TABLE)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
override fun mapToUpdateQuery(obj: SearchMetadata) = UpdateQuery.builder()
|
|
||||||
.table(TABLE)
|
|
||||||
.where("$COL_MANGA_ID = ?")
|
|
||||||
.whereArgs(obj.mangaId)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
override fun mapToContentValues(obj: SearchMetadata) = contentValuesOf(
|
|
||||||
COL_MANGA_ID to obj.mangaId,
|
|
||||||
COL_UPLOADER to obj.uploader,
|
|
||||||
COL_EXTRA to obj.extra,
|
|
||||||
COL_INDEXED_EXTRA to obj.indexedExtra,
|
|
||||||
COL_EXTRA_VERSION to obj.extraVersion,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
class SearchMetadataGetResolver : DefaultGetResolver<SearchMetadata>() {
|
|
||||||
|
|
||||||
override fun mapFromCursor(cursor: Cursor): SearchMetadata =
|
|
||||||
SearchMetadata(
|
|
||||||
mangaId = cursor.getLong(cursor.getColumnIndexOrThrow(COL_MANGA_ID)),
|
|
||||||
uploader = cursor.getString(cursor.getColumnIndexOrThrow(COL_UPLOADER)),
|
|
||||||
extra = cursor.getString(cursor.getColumnIndexOrThrow(COL_EXTRA)),
|
|
||||||
indexedExtra = cursor.getString(cursor.getColumnIndexOrThrow(COL_INDEXED_EXTRA)),
|
|
||||||
extraVersion = cursor.getInt(cursor.getColumnIndexOrThrow(COL_EXTRA_VERSION)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
class SearchMetadataDeleteResolver : DefaultDeleteResolver<SearchMetadata>() {
|
|
||||||
|
|
||||||
override fun mapToDeleteQuery(obj: SearchMetadata) = DeleteQuery.builder()
|
|
||||||
.table(TABLE)
|
|
||||||
.where("$COL_MANGA_ID = ?")
|
|
||||||
.whereArgs(obj.mangaId)
|
|
||||||
.build()
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
package exh.metadata.sql.mappers
|
|
||||||
|
|
||||||
import android.database.Cursor
|
|
||||||
import androidx.core.content.contentValuesOf
|
|
||||||
import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping
|
|
||||||
import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver
|
|
||||||
import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
|
|
||||||
import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.InsertQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
|
|
||||||
import exh.metadata.sql.models.SearchTag
|
|
||||||
import exh.metadata.sql.tables.SearchTagTable.COL_ID
|
|
||||||
import exh.metadata.sql.tables.SearchTagTable.COL_MANGA_ID
|
|
||||||
import exh.metadata.sql.tables.SearchTagTable.COL_NAME
|
|
||||||
import exh.metadata.sql.tables.SearchTagTable.COL_NAMESPACE
|
|
||||||
import exh.metadata.sql.tables.SearchTagTable.COL_TYPE
|
|
||||||
import exh.metadata.sql.tables.SearchTagTable.TABLE
|
|
||||||
|
|
||||||
class SearchTagTypeMapping : SQLiteTypeMapping<SearchTag>(
|
|
||||||
SearchTagPutResolver(),
|
|
||||||
SearchTagGetResolver(),
|
|
||||||
SearchTagDeleteResolver(),
|
|
||||||
)
|
|
||||||
|
|
||||||
class SearchTagPutResolver : DefaultPutResolver<SearchTag>() {
|
|
||||||
|
|
||||||
override fun mapToInsertQuery(obj: SearchTag) = InsertQuery.builder()
|
|
||||||
.table(TABLE)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
override fun mapToUpdateQuery(obj: SearchTag) = UpdateQuery.builder()
|
|
||||||
.table(TABLE)
|
|
||||||
.where("$COL_ID = ?")
|
|
||||||
.whereArgs(obj.id)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
override fun mapToContentValues(obj: SearchTag) = contentValuesOf(
|
|
||||||
COL_ID to obj.id,
|
|
||||||
COL_MANGA_ID to obj.mangaId,
|
|
||||||
COL_NAMESPACE to obj.namespace,
|
|
||||||
COL_NAME to obj.name,
|
|
||||||
COL_TYPE to obj.type,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
class SearchTagGetResolver : DefaultGetResolver<SearchTag>() {
|
|
||||||
|
|
||||||
override fun mapFromCursor(cursor: Cursor): SearchTag = SearchTag(
|
|
||||||
id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID)),
|
|
||||||
mangaId = cursor.getLong(cursor.getColumnIndexOrThrow(COL_MANGA_ID)),
|
|
||||||
namespace = cursor.getString(cursor.getColumnIndexOrThrow(COL_NAMESPACE)),
|
|
||||||
name = cursor.getString(cursor.getColumnIndexOrThrow(COL_NAME)),
|
|
||||||
type = cursor.getInt(cursor.getColumnIndexOrThrow(COL_TYPE)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
class SearchTagDeleteResolver : DefaultDeleteResolver<SearchTag>() {
|
|
||||||
|
|
||||||
override fun mapToDeleteQuery(obj: SearchTag) = DeleteQuery.builder()
|
|
||||||
.table(TABLE)
|
|
||||||
.where("$COL_ID = ?")
|
|
||||||
.whereArgs(obj.id)
|
|
||||||
.build()
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
package exh.metadata.sql.mappers
|
|
||||||
|
|
||||||
import android.database.Cursor
|
|
||||||
import androidx.core.content.contentValuesOf
|
|
||||||
import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping
|
|
||||||
import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver
|
|
||||||
import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
|
|
||||||
import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.InsertQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
|
|
||||||
import exh.metadata.sql.models.SearchTitle
|
|
||||||
import exh.metadata.sql.tables.SearchTitleTable.COL_ID
|
|
||||||
import exh.metadata.sql.tables.SearchTitleTable.COL_MANGA_ID
|
|
||||||
import exh.metadata.sql.tables.SearchTitleTable.COL_TITLE
|
|
||||||
import exh.metadata.sql.tables.SearchTitleTable.COL_TYPE
|
|
||||||
import exh.metadata.sql.tables.SearchTitleTable.TABLE
|
|
||||||
|
|
||||||
class SearchTitleTypeMapping : SQLiteTypeMapping<SearchTitle>(
|
|
||||||
SearchTitlePutResolver(),
|
|
||||||
SearchTitleGetResolver(),
|
|
||||||
SearchTitleDeleteResolver(),
|
|
||||||
)
|
|
||||||
|
|
||||||
class SearchTitlePutResolver : DefaultPutResolver<SearchTitle>() {
|
|
||||||
|
|
||||||
override fun mapToInsertQuery(obj: SearchTitle) = InsertQuery.builder()
|
|
||||||
.table(TABLE)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
override fun mapToUpdateQuery(obj: SearchTitle) = UpdateQuery.builder()
|
|
||||||
.table(TABLE)
|
|
||||||
.where("$COL_ID = ?")
|
|
||||||
.whereArgs(obj.id)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
override fun mapToContentValues(obj: SearchTitle) = contentValuesOf(
|
|
||||||
COL_ID to obj.id,
|
|
||||||
COL_MANGA_ID to obj.mangaId,
|
|
||||||
COL_TITLE to obj.title,
|
|
||||||
COL_TYPE to obj.type,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
class SearchTitleGetResolver : DefaultGetResolver<SearchTitle>() {
|
|
||||||
|
|
||||||
override fun mapFromCursor(cursor: Cursor): SearchTitle = SearchTitle(
|
|
||||||
id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID)),
|
|
||||||
mangaId = cursor.getLong(cursor.getColumnIndexOrThrow(COL_MANGA_ID)),
|
|
||||||
title = cursor.getString(cursor.getColumnIndexOrThrow(COL_TITLE)),
|
|
||||||
type = cursor.getInt(cursor.getColumnIndexOrThrow(COL_TYPE)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
class SearchTitleDeleteResolver : DefaultDeleteResolver<SearchTitle>() {
|
|
||||||
|
|
||||||
override fun mapToDeleteQuery(obj: SearchTitle) = DeleteQuery.builder()
|
|
||||||
.table(TABLE)
|
|
||||||
.where("$COL_ID = ?")
|
|
||||||
.whereArgs(obj.id)
|
|
||||||
.build()
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
package exh.metadata.sql.queries
|
|
||||||
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
|
||||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
|
||||||
import exh.metadata.sql.models.SearchMetadata
|
|
||||||
import exh.metadata.sql.tables.SearchMetadataTable
|
|
||||||
|
|
||||||
interface SearchMetadataQueries : DbProvider {
|
|
||||||
|
|
||||||
fun getSearchMetadataForManga(mangaId: Long) = db.get()
|
|
||||||
.`object`(SearchMetadata::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(SearchMetadataTable.TABLE)
|
|
||||||
.where("${SearchMetadataTable.COL_MANGA_ID} = ?")
|
|
||||||
.whereArgs(mangaId)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun getSearchMetadata() = db.get()
|
|
||||||
.listOfObjects(SearchMetadata::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(SearchMetadataTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun getSearchMetadataByIndexedExtra(extra: String) = db.get()
|
|
||||||
.listOfObjects(SearchMetadata::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(SearchMetadataTable.TABLE)
|
|
||||||
.where("${SearchMetadataTable.COL_INDEXED_EXTRA} = ?")
|
|
||||||
.whereArgs(extra)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun insertSearchMetadata(metadata: SearchMetadata) = db.put().`object`(metadata).prepare()
|
|
||||||
|
|
||||||
fun deleteSearchMetadata(metadata: SearchMetadata) = db.delete().`object`(metadata).prepare()
|
|
||||||
|
|
||||||
fun deleteAllSearchMetadata() = db.delete().byQuery(
|
|
||||||
DeleteQuery.builder()
|
|
||||||
.table(SearchMetadataTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
package exh.metadata.sql.queries
|
|
||||||
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
|
||||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
|
||||||
import eu.kanade.tachiyomi.data.database.inTransaction
|
|
||||||
import exh.metadata.sql.models.SearchTag
|
|
||||||
import exh.metadata.sql.tables.SearchTagTable
|
|
||||||
|
|
||||||
interface SearchTagQueries : DbProvider {
|
|
||||||
fun getSearchTagsForManga(mangaId: Long) = db.get()
|
|
||||||
.listOfObjects(SearchTag::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(SearchTagTable.TABLE)
|
|
||||||
.where("${SearchTagTable.COL_MANGA_ID} = ?")
|
|
||||||
.whereArgs(mangaId)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun deleteSearchTagsForManga(mangaId: Long) = db.delete()
|
|
||||||
.byQuery(
|
|
||||||
DeleteQuery.builder()
|
|
||||||
.table(SearchTagTable.TABLE)
|
|
||||||
.where("${SearchTagTable.COL_MANGA_ID} = ?")
|
|
||||||
.whereArgs(mangaId)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun insertSearchTag(searchTag: SearchTag) = db.put().`object`(searchTag).prepare()
|
|
||||||
|
|
||||||
fun insertSearchTags(searchTags: List<SearchTag>) = db.put().objects(searchTags).prepare()
|
|
||||||
|
|
||||||
fun deleteSearchTag(searchTag: SearchTag) = db.delete().`object`(searchTag).prepare()
|
|
||||||
|
|
||||||
fun deleteAllSearchTags() = db.delete().byQuery(
|
|
||||||
DeleteQuery.builder()
|
|
||||||
.table(SearchTagTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun setSearchTagsForManga(mangaId: Long, tags: List<SearchTag>) {
|
|
||||||
db.inTransaction {
|
|
||||||
deleteSearchTagsForManga(mangaId).executeAsBlocking()
|
|
||||||
tags.chunked(100) { chunk ->
|
|
||||||
insertSearchTags(chunk).executeAsBlocking()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
package exh.metadata.sql.queries
|
|
||||||
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
|
||||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
|
||||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
|
||||||
import eu.kanade.tachiyomi.data.database.inTransaction
|
|
||||||
import exh.metadata.sql.models.SearchTitle
|
|
||||||
import exh.metadata.sql.tables.SearchTitleTable
|
|
||||||
|
|
||||||
interface SearchTitleQueries : DbProvider {
|
|
||||||
fun getSearchTitlesForManga(mangaId: Long) = db.get()
|
|
||||||
.listOfObjects(SearchTitle::class.java)
|
|
||||||
.withQuery(
|
|
||||||
Query.builder()
|
|
||||||
.table(SearchTitleTable.TABLE)
|
|
||||||
.where("${SearchTitleTable.COL_MANGA_ID} = ?")
|
|
||||||
.whereArgs(mangaId)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun deleteSearchTitlesForManga(mangaId: Long) = db.delete()
|
|
||||||
.byQuery(
|
|
||||||
DeleteQuery.builder()
|
|
||||||
.table(SearchTitleTable.TABLE)
|
|
||||||
.where("${SearchTitleTable.COL_MANGA_ID} = ?")
|
|
||||||
.whereArgs(mangaId)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun insertSearchTitle(searchTitle: SearchTitle) = db.put().`object`(searchTitle).prepare()
|
|
||||||
|
|
||||||
fun insertSearchTitles(searchTitles: List<SearchTitle>) = db.put().objects(searchTitles).prepare()
|
|
||||||
|
|
||||||
fun deleteSearchTitle(searchTitle: SearchTitle) = db.delete().`object`(searchTitle).prepare()
|
|
||||||
|
|
||||||
fun deleteAllSearchTitle() = db.delete().byQuery(
|
|
||||||
DeleteQuery.builder()
|
|
||||||
.table(SearchTitleTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
fun setSearchTitlesForManga(mangaId: Long, titles: List<SearchTitle>) {
|
|
||||||
db.inTransaction {
|
|
||||||
deleteSearchTitlesForManga(mangaId).executeAsBlocking()
|
|
||||||
titles.chunked(100) { chunk ->
|
|
||||||
insertSearchTitles(chunk).executeAsBlocking()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package exh.metadata.sql.tables
|
|
||||||
|
|
||||||
object SearchMetadataTable {
|
|
||||||
const val TABLE = "search_metadata"
|
|
||||||
|
|
||||||
const val COL_MANGA_ID = "manga_id"
|
|
||||||
|
|
||||||
const val COL_UPLOADER = "uploader"
|
|
||||||
|
|
||||||
const val COL_EXTRA = "extra"
|
|
||||||
|
|
||||||
const val COL_INDEXED_EXTRA = "indexed_extra"
|
|
||||||
|
|
||||||
const val COL_EXTRA_VERSION = "extra_version"
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package exh.metadata.sql.tables
|
|
||||||
|
|
||||||
object SearchTagTable {
|
|
||||||
const val TABLE = "search_tags"
|
|
||||||
|
|
||||||
const val COL_ID = "_id"
|
|
||||||
|
|
||||||
const val COL_MANGA_ID = "manga_id"
|
|
||||||
|
|
||||||
const val COL_NAMESPACE = "namespace"
|
|
||||||
|
|
||||||
const val COL_NAME = "name"
|
|
||||||
|
|
||||||
const val COL_TYPE = "type"
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package exh.metadata.sql.tables
|
|
||||||
|
|
||||||
object SearchTitleTable {
|
|
||||||
const val TABLE = "search_titles"
|
|
||||||
|
|
||||||
const val COL_ID = "_id"
|
|
||||||
|
|
||||||
const val COL_MANGA_ID = "manga_id"
|
|
||||||
|
|
||||||
const val COL_TITLE = "title"
|
|
||||||
|
|
||||||
const val COL_TYPE = "type"
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
package exh.recs
|
package exh.recs
|
||||||
|
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
|
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter
|
||||||
@ -15,13 +15,13 @@ import uy.kohesive.injekt.api.get
|
|||||||
class RecommendsPresenter(
|
class RecommendsPresenter(
|
||||||
val mangaId: Long,
|
val mangaId: Long,
|
||||||
sourceId: Long,
|
sourceId: Long,
|
||||||
private val getMangaById: GetMangaById = Injekt.get(),
|
private val getManga: GetManga = Injekt.get(),
|
||||||
) : BrowseSourcePresenter(sourceId) {
|
) : BrowseSourcePresenter(sourceId) {
|
||||||
|
|
||||||
var manga: Manga? = null
|
var manga: Manga? = null
|
||||||
|
|
||||||
override fun createPager(query: String, filters: FilterList): Pager {
|
override fun createPager(query: String, filters: FilterList): Pager {
|
||||||
this.manga = runBlocking { getMangaById.await(mangaId) }
|
this.manga = runBlocking { getManga.await(mangaId) }
|
||||||
return RecommendsPager(manga!!)
|
return RecommendsPager(manga!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
package exh.search
|
package exh.search
|
||||||
|
|
||||||
import exh.metadata.sql.tables.SearchMetadataTable
|
|
||||||
import exh.metadata.sql.tables.SearchTagTable
|
|
||||||
import exh.metadata.sql.tables.SearchTitleTable
|
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class SearchEngine {
|
class SearchEngine {
|
||||||
@ -23,16 +20,16 @@ class SearchEngine {
|
|||||||
val params = mutableListOf<String>()
|
val params = mutableListOf<String>()
|
||||||
it.joinToString(separator = " OR ", prefix = "(", postfix = ")") { q ->
|
it.joinToString(separator = " OR ", prefix = "(", postfix = ")") { q ->
|
||||||
params += q
|
params += q
|
||||||
"${SearchTagTable.TABLE}.${SearchTagTable.COL_NAME} LIKE ?"
|
"search_tags.name LIKE ?"
|
||||||
} to params
|
} to params
|
||||||
}
|
}
|
||||||
return when {
|
return when {
|
||||||
namespace != null -> {
|
namespace != null -> {
|
||||||
var query =
|
var query =
|
||||||
"""
|
"""
|
||||||
(SELECT ${SearchTagTable.COL_MANGA_ID} AS $COL_MANGA_ID FROM ${SearchTagTable.TABLE}
|
(SELECT ${"manga_id"} AS $COL_MANGA_ID FROM ${"search_tags"}
|
||||||
WHERE ${SearchTagTable.COL_NAMESPACE} IS NOT NULL
|
WHERE ${"namespace"} IS NOT NULL
|
||||||
AND ${SearchTagTable.COL_NAMESPACE} LIKE ?
|
AND ${"namespace"} LIKE ?
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val params = mutableListOf(escapeLike(namespace))
|
val params = mutableListOf(escapeLike(namespace))
|
||||||
if (componentTagQuery != null) {
|
if (componentTagQuery != null) {
|
||||||
@ -46,14 +43,14 @@ class SearchEngine {
|
|||||||
// Match title + tags
|
// Match title + tags
|
||||||
val tagQuery =
|
val tagQuery =
|
||||||
"""
|
"""
|
||||||
SELECT ${SearchTagTable.COL_MANGA_ID} AS $COL_MANGA_ID FROM ${SearchTagTable.TABLE}
|
SELECT ${"manga_id"} AS $COL_MANGA_ID FROM ${"search_tags"}
|
||||||
WHERE ${componentTagQuery!!.first}
|
WHERE ${componentTagQuery!!.first}
|
||||||
""".trimIndent() to componentTagQuery.second
|
""".trimIndent() to componentTagQuery.second
|
||||||
|
|
||||||
val titleQuery =
|
val titleQuery =
|
||||||
"""
|
"""
|
||||||
SELECT ${SearchTitleTable.COL_MANGA_ID} AS $COL_MANGA_ID FROM ${SearchTitleTable.TABLE}
|
SELECT ${"manga_id"} AS $COL_MANGA_ID FROM ${"search_titles"}
|
||||||
WHERE ${SearchTitleTable.COL_TITLE} LIKE ?
|
WHERE ${"title"} LIKE ?
|
||||||
""".trimIndent() to listOf(component.asLenientTitleQuery())
|
""".trimIndent() to listOf(component.asLenientTitleQuery())
|
||||||
|
|
||||||
"(${tagQuery.first} UNION ${titleQuery.first})".trimIndent() to
|
"(${tagQuery.first} UNION ${titleQuery.first})".trimIndent() to
|
||||||
@ -75,7 +72,7 @@ class SearchEngine {
|
|||||||
textToSubQueries(null, component)
|
textToSubQueries(null, component)
|
||||||
} else if (component is Namespace) {
|
} else if (component is Namespace) {
|
||||||
if (component.namespace == "uploader") {
|
if (component.namespace == "uploader") {
|
||||||
wheres += "meta.${SearchMetadataTable.COL_UPLOADER} LIKE ?"
|
wheres += "meta.uploader LIKE ?"
|
||||||
whereParams += component.tag!!.rawTextEscapedForLike()
|
whereParams += component.tag!!.rawTextEscapedForLike()
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
@ -97,15 +94,15 @@ class SearchEngine {
|
|||||||
val completeParams = mutableListOf<String>()
|
val completeParams = mutableListOf<String>()
|
||||||
var baseQuery =
|
var baseQuery =
|
||||||
"""
|
"""
|
||||||
SELECT ${SearchMetadataTable.COL_MANGA_ID}
|
SELECT ${"manga_id"}
|
||||||
FROM ${SearchMetadataTable.TABLE} meta
|
FROM ${"search_metadata"} meta
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
include.forEachIndexed { index, pair ->
|
include.forEachIndexed { index, pair ->
|
||||||
baseQuery += "\n" + (
|
baseQuery += "\n" + (
|
||||||
"""
|
"""
|
||||||
INNER JOIN ${pair.first} i$index
|
INNER JOIN ${pair.first} i$index
|
||||||
ON i$index.$COL_MANGA_ID = meta.${SearchMetadataTable.COL_MANGA_ID}
|
ON i$index.$COL_MANGA_ID = meta.${"manga_id"}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
completeParams += pair.second
|
completeParams += pair.second
|
||||||
@ -113,7 +110,7 @@ class SearchEngine {
|
|||||||
|
|
||||||
exclude.forEach {
|
exclude.forEach {
|
||||||
wheres += """
|
wheres += """
|
||||||
(meta.${SearchMetadataTable.COL_MANGA_ID} NOT IN ${it.first})
|
(meta.${"manga_id"} NOT IN ${it.first})
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
whereParams += it.second
|
whereParams += it.second
|
||||||
}
|
}
|
||||||
@ -122,7 +119,7 @@ class SearchEngine {
|
|||||||
baseQuery += "\nWHERE\n"
|
baseQuery += "\nWHERE\n"
|
||||||
baseQuery += wheres.joinToString("\nAND\n")
|
baseQuery += wheres.joinToString("\nAND\n")
|
||||||
}
|
}
|
||||||
baseQuery += "\nORDER BY ${SearchMetadataTable.COL_MANGA_ID}"
|
baseQuery += "\nORDER BY manga_id"
|
||||||
|
|
||||||
return baseQuery to completeParams
|
return baseQuery to completeParams
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package exh.smartsearch
|
package exh.smartsearch
|
||||||
|
|
||||||
|
import eu.kanade.data.DatabaseHandler
|
||||||
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.source.CatalogueSource
|
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
@ -18,6 +19,7 @@ class SmartSearchEngine(
|
|||||||
private val extraSearchParams: String? = null,
|
private val extraSearchParams: String? = null,
|
||||||
) {
|
) {
|
||||||
private val db: DatabaseHelper by injectLazy()
|
private val db: DatabaseHelper by injectLazy()
|
||||||
|
private val handler: DatabaseHandler by injectLazy()
|
||||||
|
|
||||||
private val normalizedLevenshtein = NormalizedLevenshtein()
|
private val normalizedLevenshtein = NormalizedLevenshtein()
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import android.view.View
|
|||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.kanade.domain.manga.interactor.GetMangaById
|
import eu.kanade.domain.manga.interactor.GetManga
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.tachiyomi.databinding.MetadataViewControllerBinding
|
import eu.kanade.tachiyomi.databinding.MetadataViewControllerBinding
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
@ -29,7 +29,7 @@ class MetadataViewController : NucleusController<MetadataViewControllerBinding,
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(mangaId: Long) : this(
|
constructor(mangaId: Long) : this(
|
||||||
runBlocking { Injekt.get<GetMangaById>().await(mangaId)!! },
|
runBlocking { Injekt.get<GetManga>().await(mangaId)!! },
|
||||||
)
|
)
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
|
7
app/src/main/sqldelight/data/eh.sq
Normal file
7
app/src/main/sqldelight/data/eh.sq
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
deleteBySyncId:
|
||||||
|
DELETE FROM manga_sync WHERE sync_id = :syncId;
|
||||||
|
|
||||||
|
migrateSource:
|
||||||
|
UPDATE mangas
|
||||||
|
SET source = :newId
|
||||||
|
WHERE source = :oldId;
|
@ -196,6 +196,18 @@ INNER JOIN search_metadata
|
|||||||
ON mangas._id = search_metadata.manga_id
|
ON mangas._id = search_metadata.manga_id
|
||||||
WHERE mangas.favorite = 1 AND (mangas.source = :eh OR mangas.source = :exh);
|
WHERE mangas.favorite = 1 AND (mangas.source = :eh OR mangas.source = :exh);
|
||||||
|
|
||||||
|
getIdsOfFavoriteMangaWithMetadata:
|
||||||
|
SELECT mangas._id FROM mangas
|
||||||
|
INNER JOIN search_metadata
|
||||||
|
ON mangas._id = search_metadata.manga_id
|
||||||
|
WHERE mangas.favorite = 1;
|
||||||
|
|
||||||
|
getBySource:
|
||||||
|
SELECT * FROM mangas WHERE source = :sourceId;
|
||||||
|
|
||||||
|
getAll:
|
||||||
|
SELECT * FROM mangas;
|
||||||
|
|
||||||
selectLastInsertRow:
|
selectLastInsertRow:
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM mangas
|
FROM mangas
|
||||||
|
@ -80,11 +80,11 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
|||||||
updateSettingsById:
|
updateSettingsById:
|
||||||
UPDATE merged
|
UPDATE merged
|
||||||
SET
|
SET
|
||||||
get_chapter_updates = ?,
|
get_chapter_updates = coalesce(:getChapterUpdates, get_chapter_updates),
|
||||||
download_chapters = ?,
|
download_chapters = coalesce(:downloadChapters, download_chapters),
|
||||||
info_manga = ?,
|
info_manga = coalesce(:infoManga, info_manga),
|
||||||
chapter_priority = ?
|
chapter_priority = coalesce(:chapterPriority, chapter_priority)
|
||||||
WHERE _id = ?;
|
WHERE _id = :id;
|
||||||
|
|
||||||
deleteById:
|
deleteById:
|
||||||
DELETE FROM merged WHERE _id = ?;
|
DELETE FROM merged WHERE _id = ?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user