mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	Convert clear database queries to SQLDelight
This commit is contained in:
		@@ -8,12 +8,12 @@ import eu.kanade.tachiyomi.util.system.logcat
 | 
			
		||||
import logcat.LogPriority
 | 
			
		||||
 | 
			
		||||
class ChapterRepositoryImpl(
 | 
			
		||||
    private val databaseHandler: DatabaseHandler,
 | 
			
		||||
    private val handler: DatabaseHandler,
 | 
			
		||||
) : ChapterRepository {
 | 
			
		||||
 | 
			
		||||
    override suspend fun update(chapterUpdate: ChapterUpdate) {
 | 
			
		||||
        try {
 | 
			
		||||
            databaseHandler.await {
 | 
			
		||||
            handler.await {
 | 
			
		||||
                chaptersQueries.update(
 | 
			
		||||
                    chapterUpdate.mangaId,
 | 
			
		||||
                    chapterUpdate.url,
 | 
			
		||||
 
 | 
			
		||||
@@ -8,16 +8,16 @@ import kotlinx.coroutines.flow.Flow
 | 
			
		||||
import logcat.LogPriority
 | 
			
		||||
 | 
			
		||||
class MangaRepositoryImpl(
 | 
			
		||||
    private val databaseHandler: DatabaseHandler,
 | 
			
		||||
    private val handler: DatabaseHandler,
 | 
			
		||||
) : MangaRepository {
 | 
			
		||||
 | 
			
		||||
    override fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>> {
 | 
			
		||||
        return databaseHandler.subscribeToList { mangasQueries.getFavoriteBySourceId(sourceId, mangaMapper) }
 | 
			
		||||
        return handler.subscribeToList { mangasQueries.getFavoriteBySourceId(sourceId, mangaMapper) }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun resetViewerFlags(): Boolean {
 | 
			
		||||
        return try {
 | 
			
		||||
            databaseHandler.await { mangasQueries.resetViewerFlags() }
 | 
			
		||||
            handler.await { mangasQueries.resetViewerFlags() }
 | 
			
		||||
            true
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            logcat(LogPriority.ERROR, e)
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.source.LocalSource
 | 
			
		||||
import eu.kanade.tachiyomi.source.SourceManager
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
import kotlinx.coroutines.flow.map
 | 
			
		||||
import eu.kanade.tachiyomi.source.Source as LoadedSource
 | 
			
		||||
 | 
			
		||||
class SourceRepositoryImpl(
 | 
			
		||||
    private val sourceManager: SourceManager,
 | 
			
		||||
@@ -29,13 +30,23 @@ class SourceRepositoryImpl(
 | 
			
		||||
        val sourceIdWithFavoriteCount = handler.subscribeToList { mangasQueries.getSourceIdWithFavoriteCount() }
 | 
			
		||||
        return sourceIdWithFavoriteCount.map { sourceIdsWithCount ->
 | 
			
		||||
            sourceIdsWithCount
 | 
			
		||||
                .filterNot { it.source == LocalSource.ID }
 | 
			
		||||
                .map { (sourceId, count) ->
 | 
			
		||||
                    val source = sourceManager.getOrStub(sourceId).run {
 | 
			
		||||
                        sourceMapper(this)
 | 
			
		||||
                    }
 | 
			
		||||
                    source to count
 | 
			
		||||
                }
 | 
			
		||||
                .filterNot { it.first.id == LocalSource.ID }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun getSourcesWithNonLibraryManga(): Flow<List<Pair<LoadedSource, Long>>> {
 | 
			
		||||
        val sourceIdWithNonLibraryManga = handler.subscribeToList { mangasQueries.getSourceIdsWithNonLibraryManga() }
 | 
			
		||||
        return sourceIdWithNonLibraryManga.map { sourceId ->
 | 
			
		||||
            sourceId.map { (sourceId, count) ->
 | 
			
		||||
                val source = sourceManager.getOrStub(sourceId)
 | 
			
		||||
                source to count
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ import eu.kanade.domain.manga.repository.MangaRepository
 | 
			
		||||
import eu.kanade.domain.source.interactor.GetEnabledSources
 | 
			
		||||
import eu.kanade.domain.source.interactor.GetLanguagesWithSources
 | 
			
		||||
import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount
 | 
			
		||||
import eu.kanade.domain.source.interactor.GetSourcesWithNonLibraryManga
 | 
			
		||||
import eu.kanade.domain.source.interactor.SetMigrateSorting
 | 
			
		||||
import eu.kanade.domain.source.interactor.ToggleLanguage
 | 
			
		||||
import eu.kanade.domain.source.interactor.ToggleSource
 | 
			
		||||
@@ -58,12 +59,13 @@ class DomainModule : InjektModule {
 | 
			
		||||
        addFactory { GetExtensionLanguages(get(), get()) }
 | 
			
		||||
 | 
			
		||||
        addSingletonFactory<SourceRepository> { SourceRepositoryImpl(get(), get()) }
 | 
			
		||||
        addFactory { GetLanguagesWithSources(get(), get()) }
 | 
			
		||||
        addFactory { GetEnabledSources(get(), get()) }
 | 
			
		||||
        addFactory { ToggleSource(get()) }
 | 
			
		||||
        addFactory { ToggleSourcePin(get()) }
 | 
			
		||||
        addFactory { GetLanguagesWithSources(get(), get()) }
 | 
			
		||||
        addFactory { GetSourcesWithFavoriteCount(get(), get()) }
 | 
			
		||||
        addFactory { GetSourcesWithNonLibraryManga(get()) }
 | 
			
		||||
        addFactory { SetMigrateSorting(get()) }
 | 
			
		||||
        addFactory { ToggleLanguage(get()) }
 | 
			
		||||
        addFactory { ToggleSource(get()) }
 | 
			
		||||
        addFactory { ToggleSourcePin(get()) }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,14 @@
 | 
			
		||||
package eu.kanade.domain.source.interactor
 | 
			
		||||
 | 
			
		||||
import eu.kanade.domain.source.repository.SourceRepository
 | 
			
		||||
import eu.kanade.tachiyomi.source.Source
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
 | 
			
		||||
class GetSourcesWithNonLibraryManga(
 | 
			
		||||
    private val repository: SourceRepository,
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    fun subscribe(): Flow<List<Pair<Source, Long>>> {
 | 
			
		||||
        return repository.getSourcesWithNonLibraryManga()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -2,6 +2,7 @@ package eu.kanade.domain.source.repository
 | 
			
		||||
 | 
			
		||||
import eu.kanade.domain.source.model.Source
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
import eu.kanade.tachiyomi.source.Source as LoadedSource
 | 
			
		||||
 | 
			
		||||
interface SourceRepository {
 | 
			
		||||
 | 
			
		||||
@@ -10,4 +11,6 @@ interface SourceRepository {
 | 
			
		||||
    fun getOnlineSources(): Flow<List<Source>>
 | 
			
		||||
 | 
			
		||||
    fun getSourcesWithFavoriteCount(): Flow<List<Pair<Source, Long>>>
 | 
			
		||||
 | 
			
		||||
    fun getSourcesWithNonLibraryManga(): Flow<List<Pair<LoadedSource, Long>>>
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +0,0 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.database.models
 | 
			
		||||
 | 
			
		||||
data class SourceIdMangaCount(val source: Long, val count: Int)
 | 
			
		||||
@@ -1,20 +1,16 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.database.queries
 | 
			
		||||
 | 
			
		||||
import com.pushtorefresh.storio.Queries
 | 
			
		||||
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects
 | 
			
		||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
 | 
			
		||||
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.LibraryManga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.SourceIdMangaCount
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.resolvers.LibraryMangaGetResolver
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaCoverLastModifiedPutResolver
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaFavoritePutResolver
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaFlagsPutResolver
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaLastUpdatedPutResolver
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.resolvers.SourceIdMangaCountGetResolver
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable
 | 
			
		||||
@@ -86,17 +82,6 @@ interface MangaQueries : DbProvider {
 | 
			
		||||
        )
 | 
			
		||||
        .prepare()
 | 
			
		||||
 | 
			
		||||
    fun getSourceIdsWithNonLibraryManga() = db.get()
 | 
			
		||||
        .listOfObjects(SourceIdMangaCount::class.java)
 | 
			
		||||
        .withQuery(
 | 
			
		||||
            RawQuery.builder()
 | 
			
		||||
                .query(getSourceIdsWithNonLibraryMangaQuery())
 | 
			
		||||
                .observesTables(MangaTable.TABLE)
 | 
			
		||||
                .build(),
 | 
			
		||||
        )
 | 
			
		||||
        .withGetResolver(SourceIdMangaCountGetResolver.INSTANCE)
 | 
			
		||||
        .prepare()
 | 
			
		||||
 | 
			
		||||
    fun insertManga(manga: Manga) = db.put().`object`(manga).prepare()
 | 
			
		||||
 | 
			
		||||
    fun insertMangas(mangas: List<Manga>) = db.put().objects(mangas).prepare()
 | 
			
		||||
@@ -131,16 +116,6 @@ interface MangaQueries : DbProvider {
 | 
			
		||||
        .withPutResolver(MangaCoverLastModifiedPutResolver())
 | 
			
		||||
        .prepare()
 | 
			
		||||
 | 
			
		||||
    fun deleteMangasNotInLibraryBySourceIds(sourceIds: List<Long>) = db.delete()
 | 
			
		||||
        .byQuery(
 | 
			
		||||
            DeleteQuery.builder()
 | 
			
		||||
                .table(MangaTable.TABLE)
 | 
			
		||||
                .where("${MangaTable.COL_FAVORITE} = ? AND ${MangaTable.COL_SOURCE} IN (${Queries.placeholders(sourceIds.size)})")
 | 
			
		||||
                .whereArgs(0, *sourceIds.toTypedArray())
 | 
			
		||||
                .build(),
 | 
			
		||||
        )
 | 
			
		||||
        .prepare()
 | 
			
		||||
 | 
			
		||||
    fun getLastReadManga() = db.get()
 | 
			
		||||
        .listOfObjects(Manga::class.java)
 | 
			
		||||
        .withQuery(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.database.queries
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.resolvers.SourceIdMangaCountGetResolver
 | 
			
		||||
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.HistoryTable as History
 | 
			
		||||
@@ -113,14 +112,3 @@ fun getCategoriesForMangaQuery() =
 | 
			
		||||
    ${MangaCategory.TABLE}.${MangaCategory.COL_CATEGORY_ID}
 | 
			
		||||
    WHERE ${MangaCategory.COL_MANGA_ID} = ?
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
/** Query to get the list of sources in the database that have
 | 
			
		||||
 * non-library manga, and how many
 | 
			
		||||
 */
 | 
			
		||||
fun getSourceIdsWithNonLibraryMangaQuery() =
 | 
			
		||||
    """
 | 
			
		||||
    SELECT ${Manga.COL_SOURCE}, COUNT(*) as ${SourceIdMangaCountGetResolver.COL_COUNT}
 | 
			
		||||
    FROM ${Manga.TABLE}
 | 
			
		||||
    WHERE ${Manga.COL_FAVORITE} = 0
 | 
			
		||||
    GROUP BY ${Manga.COL_SOURCE}
 | 
			
		||||
    """
 | 
			
		||||
 
 | 
			
		||||
@@ -1,23 +0,0 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.database.resolvers
 | 
			
		||||
 | 
			
		||||
import android.annotation.SuppressLint
 | 
			
		||||
import android.database.Cursor
 | 
			
		||||
import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.SourceIdMangaCount
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable
 | 
			
		||||
 | 
			
		||||
class SourceIdMangaCountGetResolver : DefaultGetResolver<SourceIdMangaCount>() {
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        val INSTANCE = SourceIdMangaCountGetResolver()
 | 
			
		||||
        const val COL_COUNT = "manga_count"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SuppressLint("Range")
 | 
			
		||||
    override fun mapFromCursor(cursor: Cursor): SourceIdMangaCount {
 | 
			
		||||
        val sourceID = cursor.getLong(cursor.getColumnIndexOrThrow(MangaTable.COL_SOURCE))
 | 
			
		||||
        val count = cursor.getInt(cursor.getColumnIndexOrThrow(COL_COUNT))
 | 
			
		||||
 | 
			
		||||
        return SourceIdMangaCount(sourceID, count)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,43 +1,37 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.setting.database
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import eu.kanade.domain.source.interactor.GetSourcesWithNonLibraryManga
 | 
			
		||||
import eu.kanade.tachiyomi.Database
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
 | 
			
		||||
import eu.kanade.tachiyomi.source.SourceManager
 | 
			
		||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
 | 
			
		||||
import rx.Observable
 | 
			
		||||
import rx.android.schedulers.AndroidSchedulers
 | 
			
		||||
import rx.schedulers.Schedulers
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.launchIO
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.withUIContext
 | 
			
		||||
import kotlinx.coroutines.flow.collectLatest
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
class ClearDatabasePresenter : BasePresenter<ClearDatabaseController>() {
 | 
			
		||||
 | 
			
		||||
    private val db = Injekt.get<DatabaseHelper>()
 | 
			
		||||
    private val database = Injekt.get<Database>()
 | 
			
		||||
 | 
			
		||||
    private val sourceManager = Injekt.get<SourceManager>()
 | 
			
		||||
class ClearDatabasePresenter(
 | 
			
		||||
    private val database: Database = Injekt.get(),
 | 
			
		||||
    private val getSourcesWithNonLibraryManga: GetSourcesWithNonLibraryManga = Injekt.get(),
 | 
			
		||||
) : BasePresenter<ClearDatabaseController>() {
 | 
			
		||||
 | 
			
		||||
    override fun onCreate(savedState: Bundle?) {
 | 
			
		||||
        super.onCreate(savedState)
 | 
			
		||||
        getDatabaseSourcesObservable()
 | 
			
		||||
            .subscribeOn(Schedulers.io())
 | 
			
		||||
            .observeOn(AndroidSchedulers.mainThread())
 | 
			
		||||
            .subscribeLatestCache(ClearDatabaseController::setItems)
 | 
			
		||||
 | 
			
		||||
        presenterScope.launchIO {
 | 
			
		||||
            getSourcesWithNonLibraryManga.subscribe()
 | 
			
		||||
                .collectLatest { list ->
 | 
			
		||||
                    val items = list
 | 
			
		||||
                        .map { (source, count) -> ClearDatabaseSourceItem(source, count) }
 | 
			
		||||
                        .sortedBy { it.source.name }
 | 
			
		||||
 | 
			
		||||
                    withUIContext { view?.setItems(items) }
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun clearDatabaseForSourceIds(sources: List<Long>) {
 | 
			
		||||
        db.deleteMangasNotInLibraryBySourceIds(sources).executeAsBlocking()
 | 
			
		||||
        database.mangasQueries.deleteMangasNotInLibraryBySourceIds(sources)
 | 
			
		||||
        database.historyQueries.removeResettedHistory()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getDatabaseSourcesObservable(): Observable<List<ClearDatabaseSourceItem>> {
 | 
			
		||||
        return db.getSourceIdsWithNonLibraryManga().asRxObservable()
 | 
			
		||||
            .map { sourceCounts ->
 | 
			
		||||
                sourceCounts.map {
 | 
			
		||||
                    val sourceObj = sourceManager.getOrStub(it.source)
 | 
			
		||||
                    ClearDatabaseSourceItem(sourceObj, it.count)
 | 
			
		||||
                }.sortedBy { it.source.name }
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ import eu.kanade.tachiyomi.source.Source
 | 
			
		||||
import eu.kanade.tachiyomi.source.SourceManager
 | 
			
		||||
import eu.kanade.tachiyomi.source.icon
 | 
			
		||||
 | 
			
		||||
data class ClearDatabaseSourceItem(val source: Source, private val mangaCount: Int) : AbstractFlexibleItem<ClearDatabaseSourceItem.Holder>() {
 | 
			
		||||
data class ClearDatabaseSourceItem(val source: Source, private val mangaCount: Long) : AbstractFlexibleItem<ClearDatabaseSourceItem.Holder>() {
 | 
			
		||||
 | 
			
		||||
    override fun getLayoutRes(): Int {
 | 
			
		||||
        return R.layout.clear_database_source_item
 | 
			
		||||
@@ -31,7 +31,7 @@ data class ClearDatabaseSourceItem(val source: Source, private val mangaCount: I
 | 
			
		||||
 | 
			
		||||
        private val binding = ClearDatabaseSourceItemBinding.bind(view)
 | 
			
		||||
 | 
			
		||||
        fun bind(source: Source, count: Int) {
 | 
			
		||||
        fun bind(source: Source, count: Long) {
 | 
			
		||||
            binding.title.text = source.toString()
 | 
			
		||||
            binding.description.text = itemView.context.getString(R.string.clear_database_source_item_count, count)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user