refactor(db): Fully migrated from StorIO to SQLDelight

This commit is contained in:
Ahmad Ansori Palembani 2024-11-30 08:03:11 +07:00
parent a832e4d6dc
commit 07c1e7e67f
Signed by: null2264
GPG key ID: BA64F8B60AF3EFB6
67 changed files with 156 additions and 1755 deletions

View file

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.backup.restore.restorers
import eu.kanade.tachiyomi.data.backup.models.BackupCategory import eu.kanade.tachiyomi.data.backup.models.BackupCategory
import eu.kanade.tachiyomi.data.backup.models.BackupHistory import eu.kanade.tachiyomi.data.backup.models.BackupHistory
import eu.kanade.tachiyomi.data.backup.models.BackupManga import eu.kanade.tachiyomi.data.backup.models.BackupManga
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.History import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.models.MangaCategory import eu.kanade.tachiyomi.data.database.models.MangaCategory
@ -31,9 +30,9 @@ import yokai.domain.manga.interactor.GetManga
import yokai.domain.manga.interactor.InsertManga import yokai.domain.manga.interactor.InsertManga
import yokai.domain.manga.interactor.UpdateManga import yokai.domain.manga.interactor.UpdateManga
import yokai.domain.track.interactor.GetTrack import yokai.domain.track.interactor.GetTrack
import yokai.domain.track.interactor.InsertTrack
class MangaBackupRestorer( class MangaBackupRestorer(
private val db: DatabaseHelper = Injekt.get(),
private val customMangaManager: CustomMangaManager = Injekt.get(), private val customMangaManager: CustomMangaManager = Injekt.get(),
private val handler: DatabaseHandler = Injekt.get(), private val handler: DatabaseHandler = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(), private val getCategories: GetCategories = Injekt.get(),
@ -47,6 +46,7 @@ class MangaBackupRestorer(
private val getHistory: GetHistory = Injekt.get(), private val getHistory: GetHistory = Injekt.get(),
private val upsertHistory: UpsertHistory = Injekt.get(), private val upsertHistory: UpsertHistory = Injekt.get(),
private val getTrack: GetTrack = Injekt.get(), private val getTrack: GetTrack = Injekt.get(),
private val insertTrack: InsertTrack = Injekt.get(),
) { ) {
suspend fun restoreManga( suspend fun restoreManga(
backupManga: BackupManga, backupManga: BackupManga,
@ -272,7 +272,7 @@ class MangaBackupRestorer(
} }
// Update database // Update database
if (trackToUpdate.isNotEmpty()) { if (trackToUpdate.isNotEmpty()) {
db.insertTracks(trackToUpdate).executeAsBlocking() insertTrack.awaitBulk(trackToUpdate)
} }
} }

View file

@ -1,57 +0,0 @@
package eu.kanade.tachiyomi.data.database
import android.content.Context
import androidx.sqlite.db.SupportSQLiteOpenHelper
import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite
import eu.kanade.tachiyomi.data.database.mappers.CategoryTypeMapping
import eu.kanade.tachiyomi.data.database.mappers.ChapterTypeMapping
import eu.kanade.tachiyomi.data.database.mappers.HistoryTypeMapping
import eu.kanade.tachiyomi.data.database.mappers.MangaCategoryTypeMapping
import eu.kanade.tachiyomi.data.database.mappers.MangaTypeMapping
import eu.kanade.tachiyomi.data.database.mappers.SearchMetadataTypeMapping
import eu.kanade.tachiyomi.data.database.mappers.TrackTypeMapping
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.models.MangaCategory
import eu.kanade.tachiyomi.data.database.models.SearchMetadata
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.HistoryQueries
import eu.kanade.tachiyomi.data.database.queries.MangaCategoryQueries
import eu.kanade.tachiyomi.data.database.queries.MangaQueries
import eu.kanade.tachiyomi.data.database.queries.TrackQueries
import eu.kanade.tachiyomi.domain.manga.models.Manga
/**
* This class provides operations to manage the database through its interfaces.
*/
open class DatabaseHelper(
context: Context,
openHelper: SupportSQLiteOpenHelper,
) :
MangaQueries,
ChapterQueries,
TrackQueries,
CategoryQueries,
MangaCategoryQueries,
HistoryQueries {
override val db = DefaultStorIOSQLite.builder()
.sqliteOpenHelper(openHelper)
.addTypeMapping(Manga::class.java, MangaTypeMapping())
.addTypeMapping(Chapter::class.java, ChapterTypeMapping())
.addTypeMapping(Track::class.java, TrackTypeMapping())
.addTypeMapping(Category::class.java, CategoryTypeMapping())
.addTypeMapping(MangaCategory::class.java, MangaCategoryTypeMapping())
.addTypeMapping(SearchMetadata::class.java, SearchMetadataTypeMapping())
.addTypeMapping(History::class.java, HistoryTypeMapping())
.build()
inline fun inTransaction(block: () -> Unit) = db.inTransaction(block)
inline fun <T> inTransactionReturn(block: () -> T): T = db.inTransactionReturn(block)
fun lowLevel() = db.lowLevel()
}

View file

@ -1,27 +1,5 @@
package eu.kanade.tachiyomi.data.database package eu.kanade.tachiyomi.data.database
import android.database.Cursor import android.database.Cursor
import com.pushtorefresh.storio.sqlite.StorIOSQLite
inline fun StorIOSQLite.inTransaction(block: () -> Unit) {
lowLevel().beginTransaction()
try {
block()
lowLevel().setTransactionSuccessful()
} finally {
lowLevel().endTransaction()
}
}
inline fun <T> StorIOSQLite.inTransactionReturn(block: () -> T): T {
lowLevel().beginTransaction()
try {
val result = block()
lowLevel().setTransactionSuccessful()
return result
} finally {
lowLevel().endTransaction()
}
}
fun Cursor.getBoolean(index: Int) = getLong(index) > 0 fun Cursor.getBoolean(index: Int) = getLong(index) > 0

View file

@ -1,75 +0,0 @@
package eu.kanade.tachiyomi.data.database.mappers
import android.content.ContentValues
import android.database.Cursor
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 eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.CategoryImpl
import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_FLAGS
import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_ID
import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_MANGA_ORDER
import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_NAME
import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_ORDER
import eu.kanade.tachiyomi.data.database.tables.CategoryTable.TABLE
class CategoryTypeMapping : SQLiteTypeMapping<Category>(
CategoryPutResolver(),
CategoryGetResolver(),
CategoryDeleteResolver(),
)
class CategoryPutResolver : DefaultPutResolver<Category>() {
override fun mapToInsertQuery(obj: Category) = InsertQuery.builder()
.table(TABLE)
.build()
override fun mapToUpdateQuery(obj: Category) = UpdateQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
override fun mapToContentValues(obj: Category) = ContentValues(4).apply {
put(COL_ID, obj.id)
put(COL_NAME, obj.name)
put(COL_ORDER, obj.order)
put(COL_FLAGS, obj.flags)
if (obj.mangaSort != null) {
put(COL_MANGA_ORDER, obj.mangaSort.toString())
} else {
val orderString = obj.mangaOrder.joinToString("/")
put(COL_MANGA_ORDER, orderString)
}
}
}
class CategoryGetResolver : DefaultGetResolver<Category>() {
override fun mapFromCursor(cursor: Cursor): Category = CategoryImpl().also {
it.id = cursor.getInt(cursor.getColumnIndex(COL_ID))
it.name = cursor.getString(cursor.getColumnIndex(COL_NAME))
it.order = cursor.getInt(cursor.getColumnIndex(COL_ORDER))
it.flags = cursor.getInt(cursor.getColumnIndex(COL_FLAGS))
val orderString = cursor.getString(cursor.getColumnIndex(COL_MANGA_ORDER))
val (sort, order) = Category.mangaOrderFromString(orderString)
if (sort != null) it.mangaSort = sort
it.mangaOrder = order
}
}
class CategoryDeleteResolver : DefaultDeleteResolver<Category>() {
override fun mapToDeleteQuery(obj: Category) = DeleteQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
}

View file

@ -1,90 +0,0 @@
package eu.kanade.tachiyomi.data.database.mappers
import android.content.ContentValues
import android.database.Cursor
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 eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_BOOKMARK
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_CHAPTER_NUMBER
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_DATE_FETCH
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_DATE_UPLOAD
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_ID
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_LAST_PAGE_READ
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_MANGA_ID
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_NAME
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_PAGES_LEFT
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_READ
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_SCANLATOR
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_SOURCE_ORDER
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_URL
import eu.kanade.tachiyomi.data.database.tables.ChapterTable.TABLE
class ChapterTypeMapping : SQLiteTypeMapping<Chapter>(
ChapterPutResolver(),
ChapterGetResolver(),
ChapterDeleteResolver(),
)
class ChapterPutResolver : DefaultPutResolver<Chapter>() {
override fun mapToInsertQuery(obj: Chapter) = InsertQuery.builder()
.table(TABLE)
.build()
override fun mapToUpdateQuery(obj: Chapter) = UpdateQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
override fun mapToContentValues(obj: Chapter) = ContentValues(11).apply {
put(COL_ID, obj.id)
put(COL_MANGA_ID, obj.manga_id)
put(COL_URL, obj.url)
put(COL_NAME, obj.name)
put(COL_READ, obj.read)
put(COL_SCANLATOR, obj.scanlator)
put(COL_BOOKMARK, obj.bookmark)
put(COL_DATE_FETCH, obj.date_fetch)
put(COL_DATE_UPLOAD, obj.date_upload)
put(COL_LAST_PAGE_READ, obj.last_page_read)
put(COL_PAGES_LEFT, obj.pages_left)
put(COL_CHAPTER_NUMBER, obj.chapter_number)
put(COL_SOURCE_ORDER, obj.source_order)
}
}
class ChapterGetResolver : DefaultGetResolver<Chapter>() {
override fun mapFromCursor(cursor: Cursor): Chapter = ChapterImpl().apply {
id = cursor.getLong(cursor.getColumnIndex(COL_ID))
manga_id = cursor.getLong(cursor.getColumnIndex(COL_MANGA_ID))
url = cursor.getString(cursor.getColumnIndex(COL_URL))
name = cursor.getString(cursor.getColumnIndex(COL_NAME))
scanlator = cursor.getString(cursor.getColumnIndex(COL_SCANLATOR))
read = cursor.getInt(cursor.getColumnIndex(COL_READ)) == 1
bookmark = cursor.getInt(cursor.getColumnIndex(COL_BOOKMARK)) == 1
date_fetch = cursor.getLong(cursor.getColumnIndex(COL_DATE_FETCH))
date_upload = cursor.getLong(cursor.getColumnIndex(COL_DATE_UPLOAD))
last_page_read = cursor.getInt(cursor.getColumnIndex(COL_LAST_PAGE_READ))
pages_left = cursor.getInt(cursor.getColumnIndex(COL_PAGES_LEFT))
chapter_number = cursor.getFloat(cursor.getColumnIndex(COL_CHAPTER_NUMBER))
source_order = cursor.getInt(cursor.getColumnIndex(COL_SOURCE_ORDER))
}
}
class ChapterDeleteResolver : DefaultDeleteResolver<Chapter>() {
override fun mapToDeleteQuery(obj: Chapter) = DeleteQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
}

View file

@ -1,62 +0,0 @@
package eu.kanade.tachiyomi.data.database.mappers
import android.content.ContentValues
import android.database.Cursor
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 eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.tables.HistoryTable.COL_CHAPTER_ID
import eu.kanade.tachiyomi.data.database.tables.HistoryTable.COL_ID
import eu.kanade.tachiyomi.data.database.tables.HistoryTable.COL_LAST_READ
import eu.kanade.tachiyomi.data.database.tables.HistoryTable.COL_TIME_READ
import eu.kanade.tachiyomi.data.database.tables.HistoryTable.TABLE
class HistoryTypeMapping : SQLiteTypeMapping<History>(
HistoryPutResolver(),
HistoryGetResolver(),
HistoryDeleteResolver(),
)
open class HistoryPutResolver : DefaultPutResolver<History>() {
override fun mapToInsertQuery(obj: History) = InsertQuery.builder()
.table(TABLE)
.build()
override fun mapToUpdateQuery(obj: History) = UpdateQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
override fun mapToContentValues(obj: History) = ContentValues(4).apply {
put(COL_ID, obj.id)
put(COL_CHAPTER_ID, obj.chapter_id)
put(COL_LAST_READ, obj.last_read)
put(COL_TIME_READ, obj.time_read)
}
}
class HistoryGetResolver : DefaultGetResolver<History>() {
override fun mapFromCursor(cursor: Cursor): History = History.mapper(
id = cursor.getLong(cursor.getColumnIndex(COL_ID)),
chapterId = cursor.getLong(cursor.getColumnIndex(COL_CHAPTER_ID)),
lastRead = cursor.getLong(cursor.getColumnIndex(COL_LAST_READ)),
timeRead = cursor.getLong(cursor.getColumnIndex(COL_TIME_READ)),
)
}
class HistoryDeleteResolver : DefaultDeleteResolver<History>() {
override fun mapToDeleteQuery(obj: History) = DeleteQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
}

View file

@ -1,59 +0,0 @@
package eu.kanade.tachiyomi.data.database.mappers
import android.content.ContentValues
import android.database.Cursor
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 eu.kanade.tachiyomi.data.database.models.MangaCategory
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable.COL_CATEGORY_ID
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable.COL_ID
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable.COL_MANGA_ID
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable.TABLE
class MangaCategoryTypeMapping : SQLiteTypeMapping<MangaCategory>(
MangaCategoryPutResolver(),
MangaCategoryGetResolver(),
MangaCategoryDeleteResolver(),
)
class MangaCategoryPutResolver : DefaultPutResolver<MangaCategory>() {
override fun mapToInsertQuery(obj: MangaCategory) = InsertQuery.builder()
.table(TABLE)
.build()
override fun mapToUpdateQuery(obj: MangaCategory) = UpdateQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
override fun mapToContentValues(obj: MangaCategory) = ContentValues(3).apply {
put(COL_ID, obj.id)
put(COL_MANGA_ID, obj.manga_id)
put(COL_CATEGORY_ID, obj.category_id)
}
}
class MangaCategoryGetResolver : DefaultGetResolver<MangaCategory>() {
override fun mapFromCursor(cursor: Cursor): MangaCategory = MangaCategory().apply {
id = cursor.getLong(cursor.getColumnIndex(COL_ID))
manga_id = cursor.getLong(cursor.getColumnIndex(COL_MANGA_ID))
category_id = cursor.getInt(cursor.getColumnIndex(COL_CATEGORY_ID))
}
}
class MangaCategoryDeleteResolver : DefaultDeleteResolver<MangaCategory>() {
override fun mapToDeleteQuery(obj: MangaCategory) = DeleteQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
}

View file

@ -1,121 +0,0 @@
package eu.kanade.tachiyomi.data.database.mappers
import android.annotation.SuppressLint
import android.content.ContentValues
import android.database.Cursor
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 eu.kanade.tachiyomi.data.database.getBoolean
import eu.kanade.tachiyomi.data.database.models.mapper
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_ARTIST
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_AUTHOR
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_CHAPTER_FLAGS
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_COVER_LAST_MODIFIED
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_DATE_ADDED
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_DESCRIPTION
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_FAVORITE
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_FILTERED_SCANLATORS
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_GENRE
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_HIDE_TITLE
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_ID
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_INITIALIZED
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_LAST_UPDATE
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_SOURCE
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_STATUS
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_THUMBNAIL_URL
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_TITLE
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_UPDATE_STRATEGY
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_URL
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_VIEWER
import eu.kanade.tachiyomi.data.database.tables.MangaTable.TABLE
import eu.kanade.tachiyomi.domain.manga.models.Manga
import yokai.data.updateStrategyAdapter
class MangaTypeMapping : SQLiteTypeMapping<Manga>(
MangaPutResolver(),
MangaGetResolver(),
MangaDeleteResolver(),
)
class MangaPutResolver : DefaultPutResolver<Manga>() {
override fun mapToInsertQuery(obj: Manga) = InsertQuery.builder()
.table(TABLE)
.build()
override fun mapToUpdateQuery(obj: Manga) = UpdateQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
override fun mapToContentValues(obj: Manga) = ContentValues(15).apply {
put(COL_ID, obj.id)
put(COL_SOURCE, obj.source)
put(COL_URL, obj.url)
put(COL_ARTIST, obj.originalArtist)
put(COL_AUTHOR, obj.originalAuthor)
put(COL_DESCRIPTION, obj.originalDescription)
put(COL_GENRE, obj.originalGenre)
put(COL_TITLE, obj.ogTitle)
put(COL_STATUS, obj.ogStatus)
put(COL_THUMBNAIL_URL, obj.thumbnail_url)
put(COL_FAVORITE, obj.favorite)
put(COL_LAST_UPDATE, obj.last_update)
put(COL_INITIALIZED, obj.initialized)
put(COL_VIEWER, obj.viewer_flags)
put(COL_HIDE_TITLE, obj.hide_title)
put(COL_CHAPTER_FLAGS, obj.chapter_flags)
put(COL_DATE_ADDED, obj.date_added)
put(COL_FILTERED_SCANLATORS, obj.filtered_scanlators)
put(COL_UPDATE_STRATEGY, obj.update_strategy.let(updateStrategyAdapter::encode))
put(COL_COVER_LAST_MODIFIED, obj.cover_last_modified)
}
}
interface BaseMangaGetResolver {
@SuppressLint("Range")
fun mapBaseFromCursor(cursor: Cursor) = Manga.mapper(
id = cursor.getLong(cursor.getColumnIndex(COL_ID)),
source = cursor.getLong(cursor.getColumnIndex(COL_SOURCE)),
url = cursor.getString(cursor.getColumnIndex(COL_URL)),
artist = cursor.getString(cursor.getColumnIndex(COL_ARTIST)),
author = cursor.getString(cursor.getColumnIndex(COL_AUTHOR)),
description = cursor.getString(cursor.getColumnIndex(COL_DESCRIPTION)),
genre = cursor.getString(cursor.getColumnIndex(COL_GENRE)),
title = cursor.getString(cursor.getColumnIndex(COL_TITLE)),
status = cursor.getLong(cursor.getColumnIndex(COL_STATUS)),
thumbnailUrl = cursor.getString(cursor.getColumnIndex(COL_THUMBNAIL_URL)),
favorite = cursor.getBoolean(cursor.getColumnIndex(COL_FAVORITE)),
lastUpdate = cursor.getLong(cursor.getColumnIndex(COL_LAST_UPDATE)),
initialized = cursor.getBoolean(cursor.getColumnIndex(COL_INITIALIZED)),
viewerFlags = cursor.getLong(cursor.getColumnIndex(COL_VIEWER)),
chapterFlags = cursor.getLong(cursor.getColumnIndex(COL_CHAPTER_FLAGS)),
hideTitle = cursor.getBoolean(cursor.getColumnIndex(COL_HIDE_TITLE)),
dateAdded = cursor.getLong(cursor.getColumnIndex(COL_DATE_ADDED)),
filteredScanlators = cursor.getString(cursor.getColumnIndex(COL_FILTERED_SCANLATORS)),
updateStrategy = cursor.getLong(cursor.getColumnIndex(COL_UPDATE_STRATEGY)),
coverLastModified = cursor.getLong(cursor.getColumnIndex(COL_COVER_LAST_MODIFIED)),
)
}
open class MangaGetResolver : DefaultGetResolver<Manga>(), BaseMangaGetResolver {
override fun mapFromCursor(cursor: Cursor): Manga {
return mapBaseFromCursor(cursor)
}
}
class MangaDeleteResolver : DefaultDeleteResolver<Manga>() {
override fun mapToDeleteQuery(obj: Manga) = DeleteQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
}

View file

@ -1,65 +0,0 @@
package eu.kanade.tachiyomi.data.database.mappers
import android.content.ContentValues
import android.database.Cursor
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 eu.kanade.tachiyomi.data.database.models.SearchMetadata
import eu.kanade.tachiyomi.data.database.tables.SearchMetadataTable.COL_EXTRA
import eu.kanade.tachiyomi.data.database.tables.SearchMetadataTable.COL_EXTRA_VERSION
import eu.kanade.tachiyomi.data.database.tables.SearchMetadataTable.COL_INDEXED_EXTRA
import eu.kanade.tachiyomi.data.database.tables.SearchMetadataTable.COL_MANGA_ID
import eu.kanade.tachiyomi.data.database.tables.SearchMetadataTable.COL_UPLOADER
import eu.kanade.tachiyomi.data.database.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) = ContentValues(5).apply {
put(COL_MANGA_ID, obj.mangaId)
put(COL_UPLOADER, obj.uploader)
put(COL_EXTRA, obj.extra)
put(COL_INDEXED_EXTRA, obj.indexedExtra)
put(COL_EXTRA_VERSION, obj.extraVersion)
}
}
class SearchMetadataGetResolver : DefaultGetResolver<SearchMetadata>() {
override fun mapFromCursor(cursor: Cursor): SearchMetadata = SearchMetadata(
mangaId = cursor.getLong(cursor.getColumnIndex(COL_MANGA_ID)),
uploader = cursor.getString(cursor.getColumnIndex(COL_UPLOADER)),
extra = cursor.getString(cursor.getColumnIndex(COL_EXTRA)),
indexedExtra = cursor.getString(cursor.getColumnIndex(COL_INDEXED_EXTRA)),
extraVersion = cursor.getInt(cursor.getColumnIndex(COL_EXTRA_VERSION)),
)
}
class SearchMetadataDeleteResolver : DefaultDeleteResolver<SearchMetadata>() {
override fun mapToDeleteQuery(obj: SearchMetadata) = DeleteQuery.builder()
.table(TABLE)
.where("$COL_MANGA_ID = ?")
.whereArgs(obj.mangaId)
.build()
}

View file

@ -1,90 +0,0 @@
package eu.kanade.tachiyomi.data.database.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 eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.database.models.TrackImpl
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_FINISH_DATE
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_ID
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_LAST_CHAPTER_READ
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_LIBRARY_ID
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_MANGA_ID
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_MEDIA_ID
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_SCORE
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_START_DATE
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_STATUS
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_SYNC_ID
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_TITLE
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_TOTAL_CHAPTERS
import eu.kanade.tachiyomi.data.database.tables.TrackTable.COL_TRACKING_URL
import eu.kanade.tachiyomi.data.database.tables.TrackTable.TABLE
class TrackTypeMapping : SQLiteTypeMapping<Track>(
TrackPutResolver(),
TrackGetResolver(),
TrackDeleteResolver(),
)
class TrackPutResolver : DefaultPutResolver<Track>() {
override fun mapToInsertQuery(obj: Track) = InsertQuery.builder()
.table(TABLE)
.build()
override fun mapToUpdateQuery(obj: Track) = UpdateQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
override fun mapToContentValues(obj: Track) = contentValuesOf(
COL_ID to obj.id,
COL_MANGA_ID to obj.manga_id,
COL_SYNC_ID to obj.sync_id,
COL_MEDIA_ID to obj.media_id,
COL_LIBRARY_ID to obj.library_id,
COL_TITLE to obj.title,
COL_LAST_CHAPTER_READ to obj.last_chapter_read,
COL_TOTAL_CHAPTERS to obj.total_chapters,
COL_STATUS to obj.status,
COL_TRACKING_URL to obj.tracking_url,
COL_SCORE to obj.score,
COL_START_DATE to obj.started_reading_date,
COL_FINISH_DATE to obj.finished_reading_date,
)
}
class TrackGetResolver : DefaultGetResolver<Track>() {
override fun mapFromCursor(cursor: Cursor): Track = TrackImpl().apply {
id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID))
manga_id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_MANGA_ID))
sync_id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_SYNC_ID))
media_id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_MEDIA_ID))
library_id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_LIBRARY_ID))
title = cursor.getString(cursor.getColumnIndexOrThrow(COL_TITLE))
last_chapter_read = cursor.getFloat(cursor.getColumnIndexOrThrow(COL_LAST_CHAPTER_READ))
total_chapters = cursor.getLong(cursor.getColumnIndexOrThrow(COL_TOTAL_CHAPTERS))
status = cursor.getInt(cursor.getColumnIndexOrThrow(COL_STATUS))
score = cursor.getFloat(cursor.getColumnIndexOrThrow(COL_SCORE))
tracking_url = cursor.getString(cursor.getColumnIndexOrThrow(COL_TRACKING_URL))
started_reading_date = cursor.getLong(cursor.getColumnIndexOrThrow(COL_START_DATE))
finished_reading_date = cursor.getLong(cursor.getColumnIndexOrThrow(COL_FINISH_DATE))
}
}
class TrackDeleteResolver : DefaultDeleteResolver<Track>() {
override fun mapToDeleteQuery(obj: Track) = DeleteQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
}

View file

@ -1,21 +0,0 @@
package eu.kanade.tachiyomi.data.database.queries
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.domain.manga.models.Manga
interface CategoryQueries : DbProvider {
// FIXME: Migrate to SQLDelight, on halt: in StorIO transaction
fun getCategoriesForManga(manga: Manga) = db.get()
.listOfObjects(Category::class.java)
.withQuery(
RawQuery.builder()
.query(getCategoriesForMangaQuery())
.args(manga.id)
.build(),
)
.prepare()
}

View file

@ -1,25 +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.Chapter
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
import eu.kanade.tachiyomi.domain.manga.models.Manga
interface ChapterQueries : DbProvider {
// FIXME: Migrate to SQLDelight, on halt: in StorIO transaction
fun getChapters(manga: Manga) = db.get()
.listOfObjects(Chapter::class.java)
.withQuery(
Query.builder()
.table(ChapterTable.TABLE)
.where("${ChapterTable.COL_MANGA_ID} = ?")
.whereArgs(manga.id)
.build(),
)
.prepare()
// FIXME: Migrate to SQLDelight, on halt: in StorIO transaction
fun insertChapters(chapters: List<Chapter>) = db.put().objects(chapters).prepare()
}

View file

@ -1,37 +0,0 @@
package eu.kanade.tachiyomi.data.database.queries
import com.pushtorefresh.storio.sqlite.queries.RawQuery
import eu.kanade.tachiyomi.data.database.DbProvider
import eu.kanade.tachiyomi.data.database.inTransactionReturn
import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.resolvers.HistoryUpsertResolver
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
interface HistoryQueries : DbProvider {
// FIXME: Migrate to SQLDelight, on halt: in StorIO transaction
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
*/
// FIXME: Migrate to SQLDelight, on halt: in StorIO transaction
fun upsertHistoryLastRead(historyList: List<History>) = db.inTransactionReturn {
db.put()
.objects(historyList)
.withPutResolver(HistoryUpsertResolver())
.prepare()
}
}

View file

@ -1,32 +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.MangaCategory
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable
import eu.kanade.tachiyomi.domain.manga.models.Manga
interface MangaCategoryQueries : DbProvider {
private fun insertMangasCategories(mangasCategories: List<MangaCategory>) = db.put().objects(mangasCategories).prepare()
private 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()
// FIXME: Migrate to SQLDelight, on halt: in StorIO transaction
fun setMangaCategories(mangasCategories: List<MangaCategory>, mangas: List<Manga>) {
db.inTransaction {
deleteOldMangasCategories(mangas).executeAsBlocking()
insertMangasCategories(mangasCategories).executeAsBlocking()
}
}
}

View file

@ -1,43 +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.resolvers.MangaDateAddedPutResolver
import eu.kanade.tachiyomi.data.database.resolvers.MangaFavoritePutResolver
import eu.kanade.tachiyomi.data.database.resolvers.MangaTitlePutResolver
import eu.kanade.tachiyomi.data.database.tables.MangaTable
import eu.kanade.tachiyomi.domain.manga.models.Manga
interface MangaQueries : DbProvider {
// FIXME: Migrate to SQLDelight, on halt: in StorIO transaction
fun getManga(id: Long) = db.get()
.`object`(Manga::class.java)
.withQuery(
Query.builder()
.table(MangaTable.TABLE)
.where("${MangaTable.COL_ID} = ?")
.whereArgs(id)
.build(),
)
.prepare()
// FIXME: Migrate to SQLDelight, on halt: used by StorIO's inTransaction
fun updateMangaFavorite(manga: Manga) = db.put()
.`object`(manga)
.withPutResolver(MangaFavoritePutResolver())
.prepare()
// FIXME: Migrate to SQLDelight, on halt: used by StorIO's inTransaction
fun updateMangaAdded(manga: Manga) = db.put()
.`object`(manga)
.withPutResolver(MangaDateAddedPutResolver())
.prepare()
// FIXME: Migrate to SQLDelight, on halt: used by StorIO's inTransaction
fun updateMangaTitle(manga: Manga) = db.put()
.`object`(manga)
.withPutResolver(MangaTitlePutResolver())
.prepare()
}

View file

@ -1,294 +0,0 @@
package eu.kanade.tachiyomi.data.database.queries
import eu.kanade.tachiyomi.ui.recents.RecentsPresenter
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
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable as MangaCategory
import eu.kanade.tachiyomi.data.database.tables.MangaTable as Manga
// TODO: Migrate to SQLDelight
/**
* Query to get the recent chapters of manga from the library up to a date.
*/
fun getRecentsQuery(search: String, offset: Int, isResuming: Boolean) =
"""
SELECT
M.url AS mangaUrl,
M.*,
C.*
FROM mangas AS M
JOIN chapters AS C
ON M._id = C.manga_id
LEFT JOIN scanlators_view AS S
ON C.manga_id = S.manga_id
AND ifnull(C.scanlator, 'N/A') = ifnull(S.name, '/<INVALID>/')
WHERE M.favorite = 1
AND C.date_fetch > M.date_added
AND lower(M.title) LIKE '%$search%'
AND S.name IS NULL
ORDER BY C.date_fetch DESC
${limitAndOffset(true, isResuming, offset)}
"""
fun limitAndOffset(endless: Boolean, isResuming: Boolean, offset: Int): String {
return when {
isResuming && endless && offset > 0 -> "LIMIT $offset"
endless -> "LIMIT ${RecentsPresenter.ENDLESS_LIMIT}\nOFFSET $offset"
else -> "LIMIT ${RecentsPresenter.SHORT_LIMIT}"
}
}
// TODO: Migrate to SQLDelight
/**
* Query to get the recently read chapters of manga from the library up to a date.
* The max_last_read table contains the most recent chapters grouped by manga
* The select statement returns all information of chapters that have the same id as the chapter in max_last_read
* and are read after the given time period
*/
fun getRecentHistoryUngrouped(
search: String = "",
offset: Int = 0,
isResuming: Boolean,
) =
"""
SELECT
M.url AS mangaUrl,
M.*,
C.*,
H.*
FROM mangas AS M
JOIN chapters AS C
ON M._id = C.manga_id
JOIN history AS H
ON C._id = H.history_chapter_id
AND H.history_last_read > 0
LEFT JOIN scanlators_view AS S
ON C.manga_id = S.manga_id
AND ifnull(C.scanlator, 'N/A') = ifnull(S.name, '/<INVALID>/')
WHERE lower(M.title) LIKE '%$search%'
AND S.name IS NULL
ORDER BY H.history_last_read DESC
${limitAndOffset(true, isResuming, offset)}
"""
// TODO: Migrate to SQLDelight
/**
* Query to get the recently read chapters of manga from the library up to a date.
* The max_last_read table contains the most recent chapters grouped by manga
* The select statement returns all information of chapters that have the same id as the chapter in max_last_read
* and are read after the given time period
*/
fun getRecentMangasLimitQuery(
search: String = "",
offset: Int = 0,
isResuming: Boolean,
) =
"""
SELECT
M.url AS mangaUrl,
M.*,
C.*,
H.*
FROM mangas AS M
JOIN chapters AS C
ON M._id = C.manga_id
JOIN history AS H
ON C._id = H.history_chapter_id
JOIN (
SELECT
C2.manga_id AS manga_id,
C2._id AS history_chapter_id,
MAX(H2.history_last_read) AS history_last_read
FROM chapters AS C2 JOIN history AS H2
ON C2._id = H2.history_chapter_id
GROUP BY C2.manga_id
) AS max_last_read
ON C.manga_id = max_last_read.manga_id
AND max_last_read.history_chapter_id = H.history_chapter_id
AND max_last_read.history_last_read > 0
LEFT JOIN scanlators_view AS S
ON C.manga_id = S.manga_id
AND ifnull(C.scanlator, 'N/A') = ifnull(S.name, '/<INVALID>/')
WHERE lower(M.title) LIKE '%$search%'
AND S.name IS NULL
ORDER BY max_last_read.history_last_read DESC
${limitAndOffset(true, isResuming, offset)}
"""
/**
* Query to get the read chapters of manga from the library during the period.
* The max_last_read table contains the most recent chapters grouped by manga
* The select statement returns all information of chapters that have the same id as the chapter in max_last_read
* and are read after the given time period
*/
fun getHistoryPerPeriodQuery(startDate: Long, endDate: Long) =
"""
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.*, ${History.TABLE}.*
FROM ${Manga.TABLE}
JOIN ${Chapter.TABLE}
ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}
JOIN ${History.TABLE}
ON ${Chapter.TABLE}.${Chapter.COL_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
AND ${History.TABLE}.${History.COL_LAST_READ} >= $startDate
AND ${History.TABLE}.${History.COL_LAST_READ} <= $endDate
ORDER BY ${History.TABLE}.${History.COL_LAST_READ} DESC
"""
/**
* Query to get the recently read manga that has more chapters to read
* The first from checks that there's an unread chapter
* The max_last_read table contains the most recent chapters grouped by manga
* The select statement returns all information of chapters that have the same id as the chapter in max_last_read
* and are read after the given time period
* The Second Union/Select gets recents chapters
* Final Union gets newly added manga
*/
fun getAllRecentsType(
search: String = "",
includeRead: Boolean,
endless: Boolean,
offset: Int = 0,
isResuming: Boolean,
) = """
SELECT * FROM
(SELECT mangas.url as mangaUrl, mangas.*, chapters.*, history.*
FROM (
SELECT mangas.*
FROM mangas
LEFT JOIN (
SELECT manga_id, COUNT(*) AS unread
FROM chapters
WHERE read = 0
GROUP BY manga_id
) AS C
ON _id = C.manga_id
${if (includeRead) "" else "WHERE C.unread > 0"}
GROUP BY _id
ORDER BY title
) AS mangas
JOIN chapters
ON mangas._id = chapters.manga_id
JOIN history
ON chapters._id = history.history_chapter_id
JOIN (
SELECT ${Chapter.TABLE}.${Chapter.COL_MANGA_ID},${Chapter.TABLE}.${Chapter.COL_ID} as ${History.COL_CHAPTER_ID}, MAX(${History.TABLE}.${History.COL_LAST_READ}) as ${History.COL_LAST_READ}
FROM ${Chapter.TABLE} JOIN ${History.TABLE}
ON ${Chapter.TABLE}.${Chapter.COL_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
GROUP BY ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}) AS max_last_read
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = max_last_read.${Chapter.COL_MANGA_ID}
AND max_last_read.${History.COL_CHAPTER_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
AND max_last_read.${History.COL_LAST_READ} > 0
AND lower(${Manga.COL_TITLE}) LIKE '%$search%')
UNION
SELECT * FROM
(SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.*,
Null as history_id,
Null as history_chapter_id,
chapters.date_fetch as history_last_read,
Null as history_time_read
FROM ${Manga.TABLE}
JOIN ${Chapter.TABLE}
ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}
JOIN (
SELECT ${Chapter.TABLE}.${Chapter.COL_MANGA_ID},${Chapter.TABLE}.${Chapter.COL_ID} as ${History.COL_CHAPTER_ID},MAX(${Chapter.TABLE}.${Chapter.COL_DATE_UPLOAD})
FROM ${Chapter.TABLE} JOIN ${Manga.TABLE}
ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}
WHERE ${Chapter.COL_READ} = 0
GROUP BY ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}) AS newest_chapter
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = newest_chapter.${Chapter.COL_MANGA_ID}
WHERE ${Manga.COL_FAVORITE} = 1
AND newest_chapter.${History.COL_CHAPTER_ID} = ${Chapter.TABLE}.${Chapter.COL_ID}
AND ${Chapter.COL_DATE_FETCH} > ${Manga.COL_DATE_ADDED}
AND lower(${Manga.COL_TITLE}) LIKE '%$search%')
UNION
SELECT * FROM
(SELECT mangas.url as mangaUrl,
mangas.*,
Null as _id,
Null as manga_id,
Null as url,
Null as name,
Null as read,
Null as scanlator,
Null as bookmark,
Null as date_fetch,
Null as date_upload,
Null as last_page_read,
Null as pages_left,
Null as chapter_number,
Null as source_order,
Null as history_id,
Null as history_chapter_id,
${Manga.TABLE}.${Manga.COL_DATE_ADDED} as history_last_read,
Null as history_time_read
FROM mangas
WHERE ${Manga.COL_FAVORITE} = 1
AND lower(${Manga.COL_TITLE}) LIKE '%$search%')
ORDER BY history_last_read DESC
${limitAndOffset(endless, isResuming, offset)}
"""
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}
"""
fun getHistoryByChapterUrl() =
"""
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_URL} = ? AND ${History.TABLE}.${History.COL_CHAPTER_ID} = ${Chapter.TABLE}.${Chapter.COL_ID}
"""
fun getLastReadMangaQuery() =
"""
SELECT ${Manga.TABLE}.*, MAX(${History.TABLE}.${History.COL_LAST_READ}) AS max
FROM ${Manga.TABLE}
JOIN ${Chapter.TABLE}
ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}
JOIN ${History.TABLE}
ON ${Chapter.TABLE}.${Chapter.COL_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
WHERE ${Manga.TABLE}.${Manga.COL_FAVORITE} = 1
GROUP BY ${Manga.TABLE}.${Manga.COL_ID}
ORDER BY max DESC
"""
fun getLastFetchedMangaQuery() =
"""
SELECT ${Manga.TABLE}.*, MAX(${Chapter.TABLE}.${Chapter.COL_DATE_FETCH}) AS max
FROM ${Manga.TABLE}
JOIN ${Chapter.TABLE}
ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}
WHERE ${Manga.TABLE}.${Manga.COL_FAVORITE} = 1
GROUP BY ${Manga.TABLE}.${Manga.COL_ID}
ORDER BY max DESC
"""
fun getTotalChapterMangaQuery() =
"""
SELECT ${Manga.TABLE}.*
FROM ${Manga.TABLE}
JOIN ${Chapter.TABLE}
ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}
GROUP BY ${Manga.TABLE}.${Manga.COL_ID}
ORDER by COUNT(*)
"""
/**
* 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} = ?
"""

View file

@ -1,26 +1,7 @@
package eu.kanade.tachiyomi.data.database.queries 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.DbProvider
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.database.tables.TrackTable
import eu.kanade.tachiyomi.domain.manga.models.Manga
interface TrackQueries : DbProvider { interface TrackQueries : DbProvider {
// FIXME: Migrate to SQLDelight, on halt: in StorIO transaction
fun getTracks(manga: Manga) = db.get()
.listOfObjects(Track::class.java)
.withQuery(
Query.builder()
.table(TrackTable.TABLE)
.where("${TrackTable.COL_MANGA_ID} = ?")
.whereArgs(manga.id)
.build(),
)
.prepare()
// FIXME: Migrate to SQLDelight, on halt: in StorIO transaction
fun insertTracks(tracks: List<Track>) = db.put().objects(tracks).prepare()
} }

View file

@ -1,33 +0,0 @@
package eu.kanade.tachiyomi.data.database.resolvers
import android.content.ContentValues
import com.pushtorefresh.storio.sqlite.StorIOSQLite
import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.inTransactionReturn
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
class ChapterBackupPutResolver : PutResolver<Chapter>() {
override fun performPut(db: StorIOSQLite, chapter: Chapter) = db.inTransactionReturn {
val updateQuery = mapToUpdateQuery(chapter)
val contentValues = mapToContentValues(chapter)
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
}
fun mapToUpdateQuery(chapter: Chapter) = UpdateQuery.builder()
.table(ChapterTable.TABLE)
.where("${ChapterTable.COL_URL} = ?")
.whereArgs(chapter.url)
.build()
fun mapToContentValues(chapter: Chapter) = ContentValues(3).apply {
put(ChapterTable.COL_READ, chapter.read)
put(ChapterTable.COL_BOOKMARK, chapter.bookmark)
put(ChapterTable.COL_LAST_PAGE_READ, chapter.last_page_read)
}
}

View file

@ -1,34 +0,0 @@
package eu.kanade.tachiyomi.data.database.resolvers
import androidx.core.content.contentValuesOf
import com.pushtorefresh.storio.sqlite.StorIOSQLite
import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.inTransactionReturn
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
class ChapterKnownBackupPutResolver : PutResolver<Chapter>() {
override fun performPut(db: StorIOSQLite, chapter: Chapter) = db.inTransactionReturn {
val updateQuery = mapToUpdateQuery(chapter)
val contentValues = mapToContentValues(chapter)
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
}
fun mapToUpdateQuery(chapter: Chapter) = UpdateQuery.builder()
.table(ChapterTable.TABLE)
.where("${ChapterTable.COL_ID} = ?")
.whereArgs(chapter.id)
.build()
fun mapToContentValues(chapter: Chapter) =
contentValuesOf(
ChapterTable.COL_READ to chapter.read,
ChapterTable.COL_BOOKMARK to chapter.bookmark,
ChapterTable.COL_LAST_PAGE_READ to chapter.last_page_read,
)
}

View file

@ -1,31 +0,0 @@
package eu.kanade.tachiyomi.data.database.resolvers
import android.content.ContentValues
import com.pushtorefresh.storio.sqlite.StorIOSQLite
import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.inTransactionReturn
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
class ChapterSourceOrderPutResolver : PutResolver<Chapter>() {
override fun performPut(db: StorIOSQLite, chapter: Chapter) = db.inTransactionReturn {
val updateQuery = mapToUpdateQuery(chapter)
val contentValues = mapToContentValues(chapter)
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
}
fun mapToUpdateQuery(chapter: Chapter) = UpdateQuery.builder()
.table(ChapterTable.TABLE)
.where("${ChapterTable.COL_URL} = ? AND ${ChapterTable.COL_MANGA_ID} = ?")
.whereArgs(chapter.url, chapter.manga_id)
.build()
fun mapToContentValues(chapter: Chapter) = ContentValues(1).apply {
put(ChapterTable.COL_SOURCE_ORDER, chapter.source_order)
}
}

View file

@ -1,51 +0,0 @@
package eu.kanade.tachiyomi.data.database.resolvers
import androidx.core.content.contentValuesOf
import com.pushtorefresh.storio.sqlite.StorIOSQLite
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
import com.pushtorefresh.storio.sqlite.queries.Query
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.mappers.HistoryPutResolver
import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
class HistoryUpsertResolver : HistoryPutResolver() {
/**
* Updates last_read time of chapter
*/
override fun performPut(db: StorIOSQLite, history: History): PutResult {
val updateQuery = mapToUpdateQuery(history)
val cursor = db.lowLevel().query(
Query.builder()
.table(updateQuery.table())
.where(updateQuery.where())
.whereArgs(updateQuery.whereArgs())
.build(),
)
return cursor.use { putCursor ->
if (putCursor.count == 0) {
val insertQuery = mapToInsertQuery(history)
val insertedId = db.lowLevel().insert(insertQuery, mapToContentValues(history))
PutResult.newInsertResult(insertedId, insertQuery.table())
} else {
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, mapToUpdateContentValues(history))
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
}
}
}
override fun mapToUpdateQuery(obj: History) = UpdateQuery.builder()
.table(HistoryTable.TABLE)
.where("${HistoryTable.COL_CHAPTER_ID} = ?")
.whereArgs(obj.chapter_id)
.build()
private fun mapToUpdateContentValues(history: History) =
contentValuesOf(
HistoryTable.COL_LAST_READ to history.last_read,
HistoryTable.COL_TIME_READ to history.time_read,
)
}

View file

@ -1,27 +0,0 @@
package eu.kanade.tachiyomi.data.database.resolvers
import android.database.Cursor
import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
import eu.kanade.tachiyomi.data.database.mappers.ChapterGetResolver
import eu.kanade.tachiyomi.data.database.mappers.MangaGetResolver
import eu.kanade.tachiyomi.data.database.models.MangaChapter
class MangaChapterGetResolver : DefaultGetResolver<MangaChapter>() {
companion object {
val INSTANCE = MangaChapterGetResolver()
}
private val mangaGetResolver = MangaGetResolver()
private val chapterGetResolver = ChapterGetResolver()
override fun mapFromCursor(cursor: Cursor): MangaChapter {
val manga = mangaGetResolver.mapFromCursor(cursor)
val chapter = chapterGetResolver.mapFromCursor(cursor)
manga.id = chapter.manga_id
manga.url = cursor.getString(cursor.getColumnIndex("mangaUrl"))
return MangaChapter(manga, chapter)
}
}

View file

@ -1,73 +0,0 @@
package eu.kanade.tachiyomi.data.database.resolvers
import android.database.Cursor
import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
import eu.kanade.tachiyomi.data.database.mappers.ChapterGetResolver
import eu.kanade.tachiyomi.data.database.mappers.HistoryGetResolver
import eu.kanade.tachiyomi.data.database.mappers.MangaGetResolver
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
import eu.kanade.tachiyomi.data.database.models.HistoryImpl
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
class MangaChapterHistoryGetResolver : DefaultGetResolver<MangaChapterHistory>() {
companion object {
val INSTANCE = MangaChapterHistoryGetResolver()
}
/**
* Manga get resolver
*/
private val mangaGetResolver = MangaGetResolver()
/**
* Chapter get resolver
*/
private val chapterResolver = ChapterGetResolver()
/**
* History get resolver
*/
private val historyGetResolver = HistoryGetResolver()
/**
* Map correct objects from cursor result
*/
override fun mapFromCursor(cursor: Cursor): MangaChapterHistory {
// Get manga object
val manga = mangaGetResolver.mapFromCursor(cursor)
// Get chapter object
val chapter =
if (!cursor.isNull(cursor.getColumnIndex(ChapterTable.COL_MANGA_ID))) {
chapterResolver.mapFromCursor(cursor)
} else {
ChapterImpl()
}
// Get history object
val history =
if (!cursor.isNull(cursor.getColumnIndex(HistoryTable.COL_ID))) {
historyGetResolver.mapFromCursor(cursor)
} else {
HistoryImpl().apply {
last_read = try {
cursor.getLong(cursor.getColumnIndex(HistoryTable.COL_LAST_READ))
} catch (e: Exception) {
0L
}
}
}
// Make certain column conflicts are dealt with
if (chapter.id != null) {
manga.id = chapter.manga_id
manga.url = cursor.getString(cursor.getColumnIndex("mangaUrl"))
}
if (history.id != null) chapter.id = history.chapter_id
// Return result
return MangaChapterHistory(manga, chapter, history)
}
}

View file

@ -1,31 +0,0 @@
package eu.kanade.tachiyomi.data.database.resolvers
import android.content.ContentValues
import com.pushtorefresh.storio.sqlite.StorIOSQLite
import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.inTransactionReturn
import eu.kanade.tachiyomi.data.database.tables.MangaTable
import eu.kanade.tachiyomi.domain.manga.models.Manga
class MangaDateAddedPutResolver : PutResolver<Manga>() {
override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn {
val updateQuery = mapToUpdateQuery(manga)
val contentValues = mapToContentValues(manga)
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
}
fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder()
.table(MangaTable.TABLE)
.where("${MangaTable.COL_ID} = ?")
.whereArgs(manga.id)
.build()
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
put(MangaTable.COL_DATE_ADDED, manga.date_added)
}
}

View file

@ -1,31 +0,0 @@
package eu.kanade.tachiyomi.data.database.resolvers
import android.content.ContentValues
import com.pushtorefresh.storio.sqlite.StorIOSQLite
import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.inTransactionReturn
import eu.kanade.tachiyomi.data.database.tables.MangaTable
import eu.kanade.tachiyomi.domain.manga.models.Manga
class MangaFavoritePutResolver : PutResolver<Manga>() {
override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn {
val updateQuery = mapToUpdateQuery(manga)
val contentValues = mapToContentValues(manga)
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
}
fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder()
.table(MangaTable.TABLE)
.where("${MangaTable.COL_ID} = ?")
.whereArgs(manga.id)
.build()
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
put(MangaTable.COL_FAVORITE, manga.favorite)
}
}

View file

@ -1,31 +0,0 @@
package eu.kanade.tachiyomi.data.database.resolvers
import androidx.core.content.contentValuesOf
import com.pushtorefresh.storio.sqlite.StorIOSQLite
import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.inTransactionReturn
import eu.kanade.tachiyomi.data.database.tables.MangaTable
import eu.kanade.tachiyomi.domain.manga.models.Manga
class MangaFilteredScanlatorsPutResolver : PutResolver<Manga>() {
override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn {
val updateQuery = mapToUpdateQuery(manga)
val contentValues = mapToContentValues(manga)
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
}
fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder()
.table(MangaTable.TABLE)
.where("${MangaTable.COL_ID} = ?")
.whereArgs(manga.id)
.build()
fun mapToContentValues(manga: Manga) = contentValuesOf(
MangaTable.COL_FILTERED_SCANLATORS to manga.filtered_scanlators,
)
}

View file

@ -1,43 +0,0 @@
package eu.kanade.tachiyomi.data.database.resolvers
import androidx.core.content.contentValuesOf
import com.pushtorefresh.storio.sqlite.StorIOSQLite
import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.inTransactionReturn
import eu.kanade.tachiyomi.data.database.tables.MangaTable
import eu.kanade.tachiyomi.domain.manga.models.Manga
import kotlin.reflect.KProperty1
class MangaFlagsPutResolver(private val colName: String, private val fieldGetter: KProperty1<Manga, Int>, private val updateAll: Boolean = false) : PutResolver<Manga>() {
override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn {
val updateQuery = mapToUpdateQuery(manga)
val contentValues = mapToContentValues(manga)
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
}
fun mapToUpdateQuery(manga: Manga): UpdateQuery {
val builder = UpdateQuery.builder()
return if (updateAll) {
builder
.table(MangaTable.TABLE)
.build()
} else {
builder
.table(MangaTable.TABLE)
.where("${MangaTable.COL_ID} = ?")
.whereArgs(manga.id)
.build()
}
}
fun mapToContentValues(manga: Manga) =
contentValuesOf(
colName to fieldGetter.get(manga),
)
}

View file

@ -1,36 +0,0 @@
package eu.kanade.tachiyomi.data.database.resolvers
import android.content.ContentValues
import com.pushtorefresh.storio.sqlite.StorIOSQLite
import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.inTransactionReturn
import eu.kanade.tachiyomi.data.database.tables.MangaTable
import eu.kanade.tachiyomi.domain.manga.models.Manga
class MangaInfoPutResolver() : PutResolver<Manga>() {
override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn {
val updateQuery = mapToUpdateQuery(manga)
val contentValues = mapToContentValues(manga)
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
}
fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder()
.table(MangaTable.TABLE)
.where("${MangaTable.COL_ID} = ?")
.whereArgs(manga.id)
.build()
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
put(MangaTable.COL_TITLE, manga.originalTitle)
put(MangaTable.COL_GENRE, manga.originalGenre)
put(MangaTable.COL_AUTHOR, manga.originalAuthor)
put(MangaTable.COL_ARTIST, manga.originalArtist)
put(MangaTable.COL_DESCRIPTION, manga.originalDescription)
put(MangaTable.COL_STATUS, manga.originalStatus)
}
}

View file

@ -1,31 +0,0 @@
package eu.kanade.tachiyomi.data.database.resolvers
import android.content.ContentValues
import com.pushtorefresh.storio.sqlite.StorIOSQLite
import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.inTransactionReturn
import eu.kanade.tachiyomi.data.database.tables.MangaTable
import eu.kanade.tachiyomi.domain.manga.models.Manga
class MangaLastUpdatedPutResolver : PutResolver<Manga>() {
override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn {
val updateQuery = mapToUpdateQuery(manga)
val contentValues = mapToContentValues(manga)
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
}
fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder()
.table(MangaTable.TABLE)
.where("${MangaTable.COL_ID} = ?")
.whereArgs(manga.id)
.build()
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
put(MangaTable.COL_LAST_UPDATE, manga.last_update)
}
}

View file

@ -1,31 +0,0 @@
package eu.kanade.tachiyomi.data.database.resolvers
import android.content.ContentValues
import com.pushtorefresh.storio.sqlite.StorIOSQLite
import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.inTransactionReturn
import eu.kanade.tachiyomi.data.database.tables.MangaTable
import eu.kanade.tachiyomi.domain.manga.models.Manga
class MangaTitlePutResolver : PutResolver<Manga>() {
override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn {
val updateQuery = mapToUpdateQuery(manga)
val contentValues = mapToContentValues(manga)
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
}
fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder()
.table(MangaTable.TABLE)
.where("${MangaTable.COL_ID} = ?")
.whereArgs(manga.id)
.build()
fun mapToContentValues(manga: Manga) = ContentValues(1).apply {
put(MangaTable.COL_TITLE, manga.title)
}
}

View file

@ -119,7 +119,6 @@ class DownloadProvider(private val context: Context) {
*/ */
/* /*
fun renameChapters() { fun renameChapters() {
val db by injectLazy<DatabaseHelper>()
val sourceManager by injectLazy<SourceManager>() val sourceManager by injectLazy<SourceManager>()
val mangas = db.getFavoriteMangas().executeAsBlocking() val mangas = db.getFavoriteMangas().executeAsBlocking()
mangas.forEach sfor@{ manga -> mangas.forEach sfor@{ manga ->

View file

@ -7,7 +7,6 @@ import co.touchlab.kermit.Logger
import com.hippo.unifile.UniFile import com.hippo.unifile.UniFile
import com.jakewharton.rxrelay.PublishRelay import com.jakewharton.rxrelay.PublishRelay
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.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.download.model.DownloadQueue import eu.kanade.tachiyomi.data.download.model.DownloadQueue
@ -83,7 +82,6 @@ class Downloader(
private val downloadPreferences: DownloadPreferences by injectLazy() private val downloadPreferences: DownloadPreferences by injectLazy()
private val chapterCache: ChapterCache by injectLazy() private val chapterCache: ChapterCache by injectLazy()
private val xml: XML by injectLazy() private val xml: XML by injectLazy()
private val db: DatabaseHelper by injectLazy()
private val getCategories: GetCategories by injectLazy() private val getCategories: GetCategories by injectLazy()
/** /**

View file

@ -21,7 +21,6 @@ import coil3.imageLoader
import coil3.request.CachePolicy import coil3.request.CachePolicy
import coil3.request.ImageRequest import coil3.request.ImageRequest
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.data.database.models.LibraryManga
@ -95,8 +94,6 @@ import yokai.util.lang.getString
class LibraryUpdateJob(private val context: Context, workerParams: WorkerParameters) : class LibraryUpdateJob(private val context: Context, workerParams: WorkerParameters) :
CoroutineWorker(context, workerParams) { CoroutineWorker(context, workerParams) {
private val db: DatabaseHelper = Injekt.get()
private val getCategories: GetCategories = Injekt.get() private val getCategories: GetCategories = Injekt.get()
private val getChapter: GetChapter = Injekt.get() private val getChapter: GetChapter = Injekt.get()

View file

@ -228,7 +228,7 @@ class NotificationReceiver : BroadcastReceiver() {
} }
val newLastChapter = chapters.maxByOrNull { it.chapter_number.toInt() } val newLastChapter = chapters.maxByOrNull { it.chapter_number.toInt() }
LibraryUpdateJob.updateMutableFlow.tryEmit(manga.id) LibraryUpdateJob.updateMutableFlow.tryEmit(manga.id)
updateTrackChapterMarkedAsRead(Injekt.get(), preferences, newLastChapter, mangaId, 0) updateTrackChapterMarkedAsRead(preferences, newLastChapter, mangaId, 0)
} }
} }

View file

@ -10,7 +10,6 @@ import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -31,7 +30,6 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters)
override suspend fun doWork(): Result { override suspend fun doWork(): Result {
val preferences = Injekt.get<PreferencesHelper>() val preferences = Injekt.get<PreferencesHelper>()
val db = Injekt.get<DatabaseHelper>()
val trackManager = Injekt.get<TrackManager>() val trackManager = Injekt.get<TrackManager>()
val trackings = preferences.trackingsToAddOnline().get().toMutableSet().mapNotNull { val trackings = preferences.trackingsToAddOnline().get().toMutableSet().mapNotNull {
val items = it.split(":") val items = it.split(":")

View file

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.track
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.database.models.isOneShotOrCompleted import eu.kanade.tachiyomi.data.database.models.isOneShotOrCompleted
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
@ -19,7 +18,6 @@ abstract class TrackService(val id: Long) {
val trackPreferences: TrackPreferences by injectLazy() val trackPreferences: TrackPreferences by injectLazy()
val networkService: NetworkHelper by injectLazy() val networkService: NetworkHelper by injectLazy()
val db: DatabaseHelper by injectLazy()
val getChapter: GetChapter by injectLazy() val getChapter: GetChapter by injectLazy()
val getManga: GetManga by injectLazy() val getManga: GetManga by injectLazy()
val getHistory: GetHistory by injectLazy() val getHistory: GetHistory by injectLazy()

View file

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.source.online package eu.kanade.tachiyomi.source.online
import android.net.Uri import android.net.Uri
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.MangaImpl import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.database.models.create import eu.kanade.tachiyomi.data.database.models.create
@ -17,7 +16,6 @@ abstract class DelegatedHttpSource {
var delegate: HttpSource? = null var delegate: HttpSource? = null
abstract val domainName: String abstract val domainName: String
protected val db: DatabaseHelper by injectLazy()
protected val getChapter: GetChapter by injectLazy() protected val getChapter: GetChapter by injectLazy()
protected val getManga: GetManga by injectLazy() protected val getManga: GetManga by injectLazy()

View file

@ -13,7 +13,6 @@ import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.mikepenz.fastadapter.FastAdapter import com.mikepenz.fastadapter.FastAdapter
import com.mikepenz.fastadapter.adapters.ItemAdapter import com.mikepenz.fastadapter.adapters.ItemAdapter
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.MangaCategory import eu.kanade.tachiyomi.data.database.models.MangaCategory
import eu.kanade.tachiyomi.data.database.models.seriesType import eu.kanade.tachiyomi.data.database.models.seriesType
@ -74,7 +73,6 @@ class SetCategoriesSheet(
private val fastAdapter: FastAdapter<AddCategoryItem> private val fastAdapter: FastAdapter<AddCategoryItem>
private val itemAdapter = ItemAdapter<AddCategoryItem>() private val itemAdapter = ItemAdapter<AddCategoryItem>()
private val db: DatabaseHelper by injectLazy()
private val getCategories: GetCategories by injectLazy() private val getCategories: GetCategories by injectLazy()
private val setMangaCategories: SetMangaCategories by injectLazy() private val setMangaCategories: SetMangaCategories by injectLazy()
private val updateManga: UpdateManga by injectLazy() private val updateManga: UpdateManga by injectLazy()

View file

@ -5,7 +5,6 @@ import android.view.HapticFeedbackConstants
import android.view.View import android.view.View
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.flexibleadapter.items.IFlexible
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.domain.manga.models.Manga import eu.kanade.tachiyomi.domain.manga.models.Manga
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager

View file

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.library
import eu.kanade.tachiyomi.core.preference.minusAssign import eu.kanade.tachiyomi.core.preference.minusAssign
import eu.kanade.tachiyomi.core.preference.plusAssign import eu.kanade.tachiyomi.core.preference.plusAssign
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Chapter.Companion.copy import eu.kanade.tachiyomi.data.database.models.Chapter.Companion.copy
@ -84,7 +83,6 @@ import yokai.util.lang.getString
* Presenter of [LibraryController]. * Presenter of [LibraryController].
*/ */
class LibraryPresenter( class LibraryPresenter(
val db: DatabaseHelper = Injekt.get(),
private val preferences: PreferencesHelper = Injekt.get(), private val preferences: PreferencesHelper = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(), private val coverCache: CoverCache = Injekt.get(),
val sourceManager: SourceManager = Injekt.get(), val sourceManager: SourceManager = Injekt.get(),

View file

@ -67,7 +67,6 @@ import com.google.android.material.snackbar.Snackbar
import com.google.android.material.transition.platform.MaterialContainerTransformSharedElementCallback import com.google.android.material.transition.platform.MaterialContainerTransformSharedElementCallback
import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.download.DownloadJob import eu.kanade.tachiyomi.data.download.DownloadJob
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
@ -171,7 +170,6 @@ open class MainActivity : BaseActivity<MainActivityBinding>() {
private val mangaShortcutManager: MangaShortcutManager by injectLazy() private val mangaShortcutManager: MangaShortcutManager by injectLazy()
private val extensionManager: ExtensionManager by injectLazy() private val extensionManager: ExtensionManager by injectLazy()
private val db: DatabaseHelper by injectLazy()
private val getRecents: GetRecents by injectLazy() private val getRecents: GetRecents by injectLazy()
private val hideBottomNav private val hideBottomNav

View file

@ -1002,7 +1002,6 @@ class MangaDetailsController :
fun toggleReadChapter(position: Int) { fun toggleReadChapter(position: Int) {
val preferences = presenter.preferences val preferences = presenter.preferences
val db = presenter.db
val item = adapter?.getItem(position) as? ChapterItem ?: return val item = adapter?.getItem(position) as? ChapterItem ?: return
val chapter = item.chapter val chapter = item.chapter
val lastRead = chapter.last_page_read val lastRead = chapter.last_page_read
@ -1031,7 +1030,7 @@ class MangaDetailsController :
if (preferences.removeAfterMarkedAsRead().get()) { if (preferences.removeAfterMarkedAsRead().get()) {
presenter.deleteChapters(listOf(item)) presenter.deleteChapters(listOf(item))
} }
updateTrackChapterMarkedAsRead(db, preferences, chapter, manga?.id) { updateTrackChapterMarkedAsRead(preferences, chapter, manga?.id) {
presenter.fetchTracks() presenter.fetchTracks()
} }
} }
@ -1647,7 +1646,6 @@ class MangaDetailsController :
val activity = activity ?: return val activity = activity ?: return
snack?.dismiss() snack?.dismiss()
snack = presenter.manga.addOrRemoveToFavorites( snack = presenter.manga.addOrRemoveToFavorites(
presenter.db,
presenter.preferences, presenter.preferences,
view, view,
activity, activity,

View file

@ -12,7 +12,6 @@ import coil3.request.SuccessResult
import com.hippo.unifile.UniFile import com.hippo.unifile.UniFile
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.History import eu.kanade.tachiyomi.data.database.models.History
@ -106,7 +105,6 @@ class MangaDetailsPresenter(
val sourceManager: SourceManager = Injekt.get(), val sourceManager: SourceManager = Injekt.get(),
val preferences: PreferencesHelper = Injekt.get(), val preferences: PreferencesHelper = Injekt.get(),
val coverCache: CoverCache = Injekt.get(), val coverCache: CoverCache = Injekt.get(),
val db: DatabaseHelper = Injekt.get(),
private val downloadManager: DownloadManager = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(),
private val chapterFilter: ChapterFilter = Injekt.get(), private val chapterFilter: ChapterFilter = Injekt.get(),
private val storageManager: StorageManager = Injekt.get(), private val storageManager: StorageManager = Injekt.get(),
@ -614,7 +612,7 @@ class MangaDetailsPresenter(
withContext(Dispatchers.Main) { view?.updateChapters(chapters) } withContext(Dispatchers.Main) { view?.updateChapters(chapters) }
if (read && deleteNow) { if (read && deleteNow) {
val latestReadChapter = selectedChapters.maxByOrNull { it.chapter_number.toInt() }?.chapter val latestReadChapter = selectedChapters.maxByOrNull { it.chapter_number.toInt() }?.chapter
updateTrackChapterMarkedAsRead(db, preferences, latestReadChapter, manga.id) { updateTrackChapterMarkedAsRead(preferences, latestReadChapter, manga.id) {
fetchTracks() fetchTracks()
} }
} }

View file

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.ui.migration package eu.kanade.tachiyomi.ui.migration
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.preference.PreferenceValues import eu.kanade.tachiyomi.data.preference.PreferenceValues
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.domain.manga.models.Manga import eu.kanade.tachiyomi.domain.manga.models.Manga
@ -21,7 +20,6 @@ import yokai.domain.ui.UiPreferences
abstract class BaseMigrationPresenter<T : BaseMigrationInterface>( abstract class BaseMigrationPresenter<T : BaseMigrationInterface>(
protected val sourceManager: SourceManager = Injekt.get(), protected val sourceManager: SourceManager = Injekt.get(),
protected val db: DatabaseHelper = Injekt.get(),
val uiPreferences: UiPreferences = Injekt.get(), val uiPreferences: UiPreferences = Injekt.get(),
val preferences: PreferencesHelper = Injekt.get(), val preferences: PreferencesHelper = Injekt.get(),
) : BaseCoroutinePresenter<T>() { ) : BaseCoroutinePresenter<T>() {

View file

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.migration
import android.content.Context import android.content.Context
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.library.CustomMangaManager import eu.kanade.tachiyomi.data.library.CustomMangaManager
import eu.kanade.tachiyomi.domain.manga.models.Manga import eu.kanade.tachiyomi.domain.manga.models.Manga
import eu.kanade.tachiyomi.util.system.toInt import eu.kanade.tachiyomi.util.system.toInt
@ -21,7 +20,6 @@ object MigrationFlags {
private const val CUSTOM_MANGA_INFO = 0b1000 private const val CUSTOM_MANGA_INFO = 0b1000
private val coverCache: CoverCache by injectLazy() private val coverCache: CoverCache by injectLazy()
private val db: DatabaseHelper by injectLazy()
private val customMangaManager: CustomMangaManager by injectLazy() private val customMangaManager: CustomMangaManager by injectLazy()
private val getTrack: GetTrack by injectLazy() private val getTrack: GetTrack by injectLazy()

View file

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.ui.migration.manga.process package eu.kanade.tachiyomi.ui.migration.manga.process
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.domain.manga.models.Manga import eu.kanade.tachiyomi.domain.manga.models.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
@ -13,7 +12,6 @@ import uy.kohesive.injekt.injectLazy
import yokai.domain.manga.interactor.GetManga import yokai.domain.manga.interactor.GetManga
class MigratingManga( class MigratingManga(
private val db: DatabaseHelper,
private val sourceManager: SourceManager, private val sourceManager: SourceManager,
val mangaId: Long, val mangaId: Long,
parentContext: CoroutineContext, parentContext: CoroutineContext,

View file

@ -19,7 +19,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
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.databinding.MigrationListControllerBinding import eu.kanade.tachiyomi.databinding.MigrationListControllerBinding
import eu.kanade.tachiyomi.domain.manga.models.Manga import eu.kanade.tachiyomi.domain.manga.models.Manga
@ -87,7 +86,6 @@ class MigrationListController(bundle: Bundle? = null) :
val config = args.getParcelableCompat(CONFIG_EXTRA, MigrationProcedureConfig::class.java) val config = args.getParcelableCompat(CONFIG_EXTRA, MigrationProcedureConfig::class.java)
private val db: DatabaseHelper by injectLazy()
private val getManga: GetManga by injectLazy() private val getManga: GetManga by injectLazy()
private val updateManga: UpdateManga by injectLazy() private val updateManga: UpdateManga by injectLazy()
@ -117,7 +115,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(db, sourceManager, it, coroutineContext) MigratingManga(sourceManager, it, coroutineContext)
} }
migratingManga = new.toMutableList() migratingManga = new.toMutableList()
new new

View file

@ -3,9 +3,7 @@ package eu.kanade.tachiyomi.ui.migration.manga.process
import android.view.MenuItem import android.view.MenuItem
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.History import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.models.MangaCategory
import eu.kanade.tachiyomi.data.database.models.updateCoverLastModified import eu.kanade.tachiyomi.data.database.models.updateCoverLastModified
import eu.kanade.tachiyomi.data.library.CustomMangaManager import eu.kanade.tachiyomi.data.library.CustomMangaManager
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -15,7 +13,6 @@ import eu.kanade.tachiyomi.domain.manga.models.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
import eu.kanade.tachiyomi.ui.migration.MigrationFlags import eu.kanade.tachiyomi.ui.migration.MigrationFlags
import eu.kanade.tachiyomi.util.system.launchNow
import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.system.launchUI
import java.util.Date import java.util.Date
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -24,14 +21,28 @@ import kotlinx.coroutines.withContext
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import yokai.domain.category.interactor.GetCategories
import yokai.domain.category.interactor.SetMangaCategories
import yokai.domain.chapter.interactor.GetChapter
import yokai.domain.chapter.interactor.UpdateChapter
import yokai.domain.chapter.models.ChapterUpdate
import yokai.domain.history.interactor.GetHistory
import yokai.domain.history.interactor.UpsertHistory
import yokai.domain.library.custom.model.CustomMangaInfo.Companion.getMangaInfo import yokai.domain.library.custom.model.CustomMangaInfo.Companion.getMangaInfo
import yokai.domain.manga.interactor.GetManga
import yokai.domain.manga.interactor.UpdateManga
import yokai.domain.manga.models.MangaUpdate
import yokai.domain.track.interactor.GetTrack
import yokai.domain.track.interactor.InsertTrack
import yokai.domain.ui.UiPreferences import yokai.domain.ui.UiPreferences
class MigrationProcessAdapter( class MigrationProcessAdapter(
val controller: MigrationListController, val controller: MigrationListController,
) : FlexibleAdapter<MigrationProcessItem>(null, controller, true) { ) : FlexibleAdapter<MigrationProcessItem>(null, controller, true) {
private val db: DatabaseHelper by injectLazy() private val getCategories: GetCategories by injectLazy()
private val getManga: GetManga by injectLazy()
var items: List<MigrationProcessItem> = emptyList() var items: List<MigrationProcessItem> = emptyList()
val preferences: PreferencesHelper by injectLazy() val preferences: PreferencesHelper by injectLazy()
val uiPreferences: UiPreferences by injectLazy() val uiPreferences: UiPreferences by injectLazy()
@ -75,25 +86,21 @@ class MigrationProcessAdapter(
suspend fun performMigrations(copy: Boolean) { suspend fun performMigrations(copy: Boolean) {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
db.inTransaction { currentItems.forEach { migratingManga ->
currentItems.forEach { migratingManga -> val manga = migratingManga.manga
val manga = migratingManga.manga if (manga.searchResult.initialized) {
if (manga.searchResult.initialized) { val toMangaObj =
val toMangaObj = getManga.awaitById(manga.searchResult.get() ?: return@forEach) ?: return@forEach
db.getManga(manga.searchResult.get() ?: return@forEach) val prevManga = manga.manga() ?: return@forEach
.executeAsBlocking() val source = sourceManager.get(toMangaObj.source) ?: return@forEach
?: return@forEach val prevSource = sourceManager.get(prevManga.source)
val prevManga = manga.manga() ?: return@forEach migrateMangaInternal(
val source = sourceManager.get(toMangaObj.source) ?: return@forEach prevSource,
val prevSource = sourceManager.get(prevManga.source) source,
migrateMangaInternal( prevManga,
prevSource, toMangaObj,
source, !copy,
prevManga, )
toMangaObj,
!copy,
)
}
} }
} }
} }
@ -102,21 +109,17 @@ class MigrationProcessAdapter(
fun migrateManga(position: Int, copy: Boolean) { fun migrateManga(position: Int, copy: Boolean) {
launchUI { launchUI {
val manga = getItem(position)?.manga ?: return@launchUI val manga = getItem(position)?.manga ?: return@launchUI
db.inTransaction { val toMangaObj = getManga.awaitById(manga.searchResult.get() ?: return@launchUI) ?: return@launchUI
val toMangaObj = val prevManga = manga.manga() ?: return@launchUI
db.getManga(manga.searchResult.get() ?: return@launchUI).executeAsBlocking() val source = sourceManager.get(toMangaObj.source) ?: return@launchUI
?: return@launchUI val prevSource = sourceManager.get(prevManga.source)
val prevManga = manga.manga() ?: return@launchUI migrateMangaInternal(
val source = sourceManager.get(toMangaObj.source) ?: return@launchUI prevSource,
val prevSource = sourceManager.get(prevManga.source) source,
migrateMangaInternal( prevManga,
prevSource, toMangaObj,
source, !copy,
prevManga, )
toMangaObj,
!copy,
)
}
removeManga(position) removeManga(position)
} }
} }
@ -131,7 +134,7 @@ class MigrationProcessAdapter(
} }
// FIXME: Migrate to SQLDelight, on halt: in StorIO transaction // FIXME: Migrate to SQLDelight, on halt: in StorIO transaction
private fun migrateMangaInternal( private suspend fun migrateMangaInternal(
prevSource: Source?, prevSource: Source?,
source: Source, source: Source,
prevManga: Manga, prevManga: Manga,
@ -140,15 +143,24 @@ class MigrationProcessAdapter(
) { ) {
if (controller.config == null) return if (controller.config == null) return
val flags = preferences.migrateFlags().get() val flags = preferences.migrateFlags().get()
migrateMangaInternal(flags, db, enhancedServices, coverCache, customMangaManager, prevSource, source, prevManga, manga, replace) migrateMangaInternal(
flags,
enhancedServices,
coverCache,
customMangaManager,
prevSource,
source,
prevManga,
manga,
replace,
)
} }
companion object { companion object {
// FIXME: Migrate to SQLDelight, on halt: in StorIO transaction // FIXME: Migrate to SQLDelight, on halt: in StorIO transaction
fun migrateMangaInternal( suspend fun migrateMangaInternal(
flags: Int, flags: Int,
db: DatabaseHelper,
enhancedServices: List<EnhancedTrackService>, enhancedServices: List<EnhancedTrackService>,
coverCache: CoverCache, coverCache: CoverCache,
customMangaManager: CustomMangaManager, customMangaManager: CustomMangaManager,
@ -160,20 +172,30 @@ class MigrationProcessAdapter(
) { ) {
// Update chapters read // Update chapters read
if (MigrationFlags.hasChapters(flags)) { if (MigrationFlags.hasChapters(flags)) {
val prevMangaChapters = db.getChapters(prevManga).executeAsBlocking() val getChapter: GetChapter = Injekt.get()
val maxChapterRead = val updateChapter: UpdateChapter = Injekt.get()
prevMangaChapters.filter { it.read }.maxOfOrNull { it.chapter_number } ?: 0f val getHistory: GetHistory = Injekt.get()
val dbChapters = db.getChapters(manga).executeAsBlocking() val upsertHistory: UpsertHistory = Injekt.get()
val prevHistoryList = db.getHistoryByMangaId(prevManga.id!!).executeAsBlocking()
val prevMangaChapters = getChapter.awaitAll(prevManga, false)
val maxChapterRead = prevMangaChapters.filter { it.read }.maxOfOrNull { it.chapter_number } ?: 0f
val dbChapters = getChapter.awaitAll(manga, false)
val prevHistoryList = getHistory.awaitAllByMangaId(prevManga.id!!)
val historyList = mutableListOf<History>() val historyList = mutableListOf<History>()
val chapterUpdates = mutableListOf<ChapterUpdate>()
for (chapter in dbChapters) { for (chapter in dbChapters) {
if (chapter.isRecognizedNumber) { if (chapter.isRecognizedNumber) {
var update: ChapterUpdate? = null
val prevChapter = val prevChapter =
prevMangaChapters.find { it.isRecognizedNumber && it.chapter_number == chapter.chapter_number } prevMangaChapters.find { it.isRecognizedNumber && it.chapter_number == chapter.chapter_number }
if (prevChapter != null) { if (prevChapter != null) {
chapter.bookmark = prevChapter.bookmark // copy data from prevChapter -> chapter
chapter.read = prevChapter.read update = ChapterUpdate(
chapter.date_fetch = prevChapter.date_fetch id = chapter.id!!,
bookmark = prevChapter.bookmark,
read = prevChapter.read,
dateFetch = prevChapter.date_fetch,
)
prevHistoryList.find { it.chapter_id == prevChapter.id } prevHistoryList.find { it.chapter_id == prevChapter.id }
?.let { prevHistory -> ?.let { prevHistory ->
val history = History.create(chapter) val history = History.create(chapter)
@ -184,23 +206,26 @@ class MigrationProcessAdapter(
historyList.add(history) historyList.add(history)
} }
} else if (chapter.chapter_number <= maxChapterRead) { } else if (chapter.chapter_number <= maxChapterRead) {
chapter.read = true update = ChapterUpdate(
id = chapter.id!!,
read = true
)
} }
update?.let { chapterUpdates.add(it) }
} }
} }
db.insertChapters(dbChapters).executeAsBlocking() updateChapter.awaitAll(chapterUpdates)
db.upsertHistoryLastRead(historyList).executeAsBlocking() upsertHistory.awaitBulk(historyList)
} }
// Update categories // Update categories
if (MigrationFlags.hasCategories(flags)) { if (MigrationFlags.hasCategories(flags)) {
val categories = db.getCategoriesForManga(prevManga).executeAsBlocking() val categories = Injekt.get<GetCategories>().awaitByMangaId(prevManga.id)
val mangaCategories = categories.map { MangaCategory.create(manga, it) } Injekt.get<SetMangaCategories>().await(prevManga.id, categories.mapNotNull { it.id?.toLong() })
db.setMangaCategories(mangaCategories, listOf(manga))
} }
// Update track // Update track
if (MigrationFlags.hasTracks(flags)) { if (MigrationFlags.hasTracks(flags)) {
val tracksToUpdate = val tracksToUpdate =
db.getTracks(prevManga).executeAsBlocking().mapNotNull { track -> Injekt.get<GetTrack>().awaitAllByMangaId(prevManga.id).mapNotNull { track ->
track.id = null track.id = null
track.manga_id = manga.id!! track.manga_id = manga.id!!
@ -212,13 +237,20 @@ class MigrationProcessAdapter(
track track
} }
} }
db.insertTracks(tracksToUpdate).executeAsBlocking() Injekt.get<InsertTrack>().awaitBulk(tracksToUpdate)
} }
val updateManga: UpdateManga = Injekt.get()
// Update favorite status // Update favorite status
if (replace) { if (replace) {
prevManga.favorite = false prevManga.favorite = false
db.updateMangaFavorite(prevManga).executeAsBlocking() updateManga.await(
MangaUpdate(
id = prevManga.id!!,
favorite = false,
)
)
} }
manga.favorite = true manga.favorite = true
if (replace) { if (replace) {
manga.date_added = prevManga.date_added manga.date_added = prevManga.date_added
@ -230,18 +262,21 @@ class MigrationProcessAdapter(
if (MigrationFlags.hasCustomMangaInfo(flags)) { if (MigrationFlags.hasCustomMangaInfo(flags)) {
if (coverCache.getCustomCoverFile(prevManga).exists()) { if (coverCache.getCustomCoverFile(prevManga).exists()) {
coverCache.setCustomCoverToCache(manga, coverCache.getCustomCoverFile(prevManga).inputStream()) coverCache.setCustomCoverToCache(manga, coverCache.getCustomCoverFile(prevManga).inputStream())
launchNow { manga.updateCoverLastModified() } manga.updateCoverLastModified()
} }
customMangaManager.getManga(prevManga)?.let { customManga -> customMangaManager.getManga(prevManga)?.let { customManga ->
launchNow { customMangaManager.updateMangaInfo(prevManga.id, manga.id, customManga.getMangaInfo())
customMangaManager.updateMangaInfo(prevManga.id, manga.id, customManga.getMangaInfo())
}
} }
} }
db.updateMangaFavorite(manga).executeAsBlocking() updateManga.await(
db.updateMangaAdded(manga).executeAsBlocking() MangaUpdate(
db.updateMangaTitle(manga).executeAsBlocking() id = manga.id!!,
title = manga.title,
favorite = manga.favorite,
dateAdded = manga.date_added,
)
)
} }
} }
} }

View file

@ -7,7 +7,6 @@ import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.coil.useCustomCover import eu.kanade.tachiyomi.data.coil.useCustomCover
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.databinding.MangaGridItemBinding import eu.kanade.tachiyomi.databinding.MangaGridItemBinding
import eu.kanade.tachiyomi.databinding.MigrationProcessItemBinding import eu.kanade.tachiyomi.databinding.MigrationProcessItemBinding
import eu.kanade.tachiyomi.domain.manga.models.Manga import eu.kanade.tachiyomi.domain.manga.models.Manga
@ -25,6 +24,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import yokai.domain.chapter.interactor.GetChapter import yokai.domain.chapter.interactor.GetChapter
import yokai.domain.manga.interactor.GetManga
import yokai.domain.manga.models.cover import yokai.domain.manga.models.cover
import yokai.i18n.MR import yokai.i18n.MR
import yokai.presentation.core.util.coil.loadManga import yokai.presentation.core.util.coil.loadManga
@ -35,8 +35,8 @@ class MigrationProcessHolder(
private val adapter: MigrationProcessAdapter, private val adapter: MigrationProcessAdapter,
) : BaseFlexibleViewHolder(view, adapter) { ) : BaseFlexibleViewHolder(view, adapter) {
private val db: DatabaseHelper by injectLazy()
private val getChapter: GetChapter by injectLazy() private val getChapter: GetChapter by injectLazy()
private val getManga: GetManga by injectLazy()
private val sourceManager: SourceManager by injectLazy() private val sourceManager: SourceManager by injectLazy()
private var item: MigrationProcessItem? = null private var item: MigrationProcessItem? = null
@ -99,12 +99,8 @@ class MigrationProcessHolder(
} }
}*/ }*/
val searchResult = item.manga.searchResult.get()?.let { val searchResult = item.manga.searchResult.get()?.let { getManga.awaitById(it) }
db.getManga(it).executeAsBlocking() val resultSource = searchResult?.source?.let { sourceManager.get(it) }
}
val resultSource = searchResult?.source?.let {
sourceManager.get(it)
}
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
if (item.manga.mangaId != this@MigrationProcessHolder.item?.manga?.mangaId || item.manga.migrationStatus == MigrationStatus.RUNNUNG) { if (item.manga.mangaId != this@MigrationProcessHolder.item?.manga?.mangaId || item.manga.migrationStatus == MigrationStatus.RUNNUNG) {
return@withContext return@withContext

View file

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.ui.more.stats package eu.kanade.tachiyomi.ui.more.stats
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.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
@ -30,7 +29,6 @@ import yokai.util.lang.getString
* Presenter of [StatsController]. * Presenter of [StatsController].
*/ */
class StatsPresenter( class StatsPresenter(
private val db: DatabaseHelper = Injekt.get(),
private val prefs: PreferencesHelper = Injekt.get(), private val prefs: PreferencesHelper = Injekt.get(),
private val trackManager: TrackManager = Injekt.get(), private val trackManager: TrackManager = Injekt.get(),
private val downloadManager: DownloadManager = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(),

View file

@ -4,7 +4,6 @@ import android.graphics.drawable.Drawable
import android.text.format.DateUtils import android.text.format.DateUtils
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.History import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.data.database.models.LibraryManga
@ -48,7 +47,6 @@ import yokai.i18n.MR
import yokai.util.lang.getString import yokai.util.lang.getString
class StatsDetailsPresenter( class StatsDetailsPresenter(
private val db: DatabaseHelper = Injekt.get(),
private val prefs: PreferencesHelper = Injekt.get(), private val prefs: PreferencesHelper = Injekt.get(),
val trackManager: TrackManager = Injekt.get(), val trackManager: TrackManager = Injekt.get(),
private val sourceManager: SourceManager = Injekt.get(), private val sourceManager: SourceManager = Injekt.get(),

View file

@ -10,7 +10,6 @@ import androidx.lifecycle.viewModelScope
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import com.hippo.unifile.UniFile import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
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.History import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.models.defaultReaderType import eu.kanade.tachiyomi.data.database.models.defaultReaderType
@ -98,7 +97,6 @@ import yokai.util.lang.getString
*/ */
class ReaderViewModel( class ReaderViewModel(
private val savedState: SavedStateHandle = SavedStateHandle(), private val savedState: SavedStateHandle = SavedStateHandle(),
private val db: DatabaseHelper = Injekt.get(),
private val sourceManager: SourceManager = Injekt.get(), private val sourceManager: SourceManager = Injekt.get(),
private val downloadManager: DownloadManager = Injekt.get(), private val downloadManager: DownloadManager = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(), private val coverCache: CoverCache = Injekt.get(),

View file

@ -90,12 +90,12 @@ import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.util.view.updateGradiantBGRadius import eu.kanade.tachiyomi.util.view.updateGradiantBGRadius
import eu.kanade.tachiyomi.util.view.withFadeTransaction import eu.kanade.tachiyomi.util.view.withFadeTransaction
import eu.kanade.tachiyomi.widget.LinearLayoutManagerAccurateOffset import eu.kanade.tachiyomi.widget.LinearLayoutManagerAccurateOffset
import java.util.Locale
import kotlin.math.max
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import yokai.i18n.MR import yokai.i18n.MR
import yokai.util.lang.getString import yokai.util.lang.getString
import java.util.*
import kotlin.math.max
import android.R as AR import android.R as AR
/** /**
@ -839,7 +839,6 @@ class RecentsController(bundle: Bundle? = null) :
override fun markAsRead(position: Int) { override fun markAsRead(position: Int) {
val preferences = presenter.preferences val preferences = presenter.preferences
val db = presenter.db
val item = adapter.getItem(position) as? RecentMangaItem ?: return val item = adapter.getItem(position) as? RecentMangaItem ?: return
val holder = binding.recycler.findViewHolderForAdapterPosition(position) val holder = binding.recycler.findViewHolderForAdapterPosition(position)
val holderId = (holder as? RecentMangaHolder)?.chapterId val holderId = (holder as? RecentMangaHolder)?.chapterId
@ -880,7 +879,7 @@ class RecentsController(bundle: Bundle? = null) :
lastChapterId = chapter.id lastChapterId = chapter.id
presenter.deleteChapter(chapter, manga) presenter.deleteChapter(chapter, manga)
} }
updateTrackChapterMarkedAsRead(db, preferences, chapter, manga.id) { updateTrackChapterMarkedAsRead(preferences, chapter, manga.id) {
(router.backstack.lastOrNull()?.controller as? MangaDetailsController)?.presenter?.fetchTracks() (router.backstack.lastOrNull()?.controller as? MangaDetailsController)?.presenter?.fetchTracks()
} }
} }

View file

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.ui.recents package eu.kanade.tachiyomi.ui.recents
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.ChapterHistory import eu.kanade.tachiyomi.data.database.models.ChapterHistory
import eu.kanade.tachiyomi.data.database.models.History import eu.kanade.tachiyomi.data.database.models.History
@ -55,7 +54,6 @@ class RecentsPresenter(
val recentsPreferences: RecentsPreferences = Injekt.get(), val recentsPreferences: RecentsPreferences = Injekt.get(),
val preferences: PreferencesHelper = Injekt.get(), val preferences: PreferencesHelper = Injekt.get(),
val downloadManager: DownloadManager = Injekt.get(), val downloadManager: DownloadManager = Injekt.get(),
val db: DatabaseHelper = Injekt.get(),
private val chapterFilter: ChapterFilter = Injekt.get(), private val chapterFilter: ChapterFilter = Injekt.get(),
) : BaseCoroutinePresenter<RecentsController>(), DownloadQueue.DownloadListener { ) : BaseCoroutinePresenter<RecentsController>(), DownloadQueue.DownloadListener {
private val handler: DatabaseHandler by injectLazy() private val handler: DatabaseHandler by injectLazy()

View file

@ -58,10 +58,10 @@ import eu.kanade.tachiyomi.util.view.withFadeTransaction
import eu.kanade.tachiyomi.widget.AutofitRecyclerView import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import eu.kanade.tachiyomi.widget.EmptyView import eu.kanade.tachiyomi.widget.EmptyView
import eu.kanade.tachiyomi.widget.LinearLayoutManagerAccurateOffset import eu.kanade.tachiyomi.widget.LinearLayoutManagerAccurateOffset
import kotlin.math.roundToInt
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import yokai.i18n.MR import yokai.i18n.MR
import yokai.util.lang.getString import yokai.util.lang.getString
import kotlin.math.roundToInt
/** /**
* Controller to manage the catalogues available in the app. * Controller to manage the catalogues available in the app.
@ -769,7 +769,6 @@ open class BrowseSourceController(bundle: Bundle) :
val activity = activity ?: return val activity = activity ?: return
snack?.dismiss() snack?.dismiss()
snack = manga.addOrRemoveToFavorites( snack = manga.addOrRemoveToFavorites(
presenter.db,
preferences, preferences,
view, view,
activity, activity,

View file

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.source.browse
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.create import eu.kanade.tachiyomi.data.database.models.create
import eu.kanade.tachiyomi.data.database.models.removeCover import eu.kanade.tachiyomi.data.database.models.removeCover
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
@ -54,7 +53,6 @@ open class BrowseSourcePresenter(
searchQuery: String? = null, searchQuery: String? = null,
var useLatest: Boolean = false, var useLatest: Boolean = false,
val sourceManager: SourceManager = Injekt.get(), val sourceManager: SourceManager = Injekt.get(),
val db: DatabaseHelper = Injekt.get(),
val uiPreferences: UiPreferences = Injekt.get(), val uiPreferences: UiPreferences = Injekt.get(),
val preferences: PreferencesHelper = Injekt.get(), val preferences: PreferencesHelper = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(), private val coverCache: CoverCache = Injekt.get(),

View file

@ -116,7 +116,6 @@ open class GlobalSearchController(
val activity = activity ?: return val activity = activity ?: return
snack?.dismiss() snack?.dismiss()
snack = manga.addOrRemoveToFavorites( snack = manga.addOrRemoveToFavorites(
presenter.db,
preferences, preferences,
view, view,
activity, activity,

View file

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.ui.source.globalsearch package eu.kanade.tachiyomi.ui.source.globalsearch
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.create import eu.kanade.tachiyomi.data.database.models.create
import eu.kanade.tachiyomi.data.database.models.removeCover import eu.kanade.tachiyomi.data.database.models.removeCover
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
@ -38,7 +37,6 @@ import yokai.domain.manga.interactor.UpdateManga
* Function calls should be done from here. UI calls should be done from the controller. * Function calls should be done from here. UI calls should be done from the controller.
* *
* @param sourceManager manages the different sources. * @param sourceManager manages the different sources.
* @param db manages the database calls.
* @param preferences manages the preference calls. * @param preferences manages the preference calls.
*/ */
open class GlobalSearchPresenter( open class GlobalSearchPresenter(
@ -46,7 +44,6 @@ open class GlobalSearchPresenter(
private val initialExtensionFilter: String? = null, private val initialExtensionFilter: String? = null,
private val sourcesToUse: List<CatalogueSource>? = null, private val sourcesToUse: List<CatalogueSource>? = null,
val sourceManager: SourceManager = Injekt.get(), val sourceManager: SourceManager = Injekt.get(),
val db: DatabaseHelper = Injekt.get(),
private val preferences: PreferencesHelper = Injekt.get(), private val preferences: PreferencesHelper = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(), private val coverCache: CoverCache = Injekt.get(),
) : BaseCoroutinePresenter<GlobalSearchController>() { ) : BaseCoroutinePresenter<GlobalSearchController>() {

View file

@ -10,7 +10,6 @@ import co.touchlab.kermit.Logger
import com.bluelinelabs.conductor.Controller import com.bluelinelabs.conductor.Controller
import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.seriesType import eu.kanade.tachiyomi.data.database.models.seriesType
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -29,6 +28,7 @@ import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationProcessAdapter
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithTrackServiceTwoWay import eu.kanade.tachiyomi.util.chapter.syncChaptersWithTrackServiceTwoWay
import eu.kanade.tachiyomi.util.lang.asButton import eu.kanade.tachiyomi.util.lang.asButton
import eu.kanade.tachiyomi.util.system.launchIO import eu.kanade.tachiyomi.util.system.launchIO
import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.system.materialAlertDialog import eu.kanade.tachiyomi.util.system.materialAlertDialog
import eu.kanade.tachiyomi.util.system.setCustomTitleAndMessage import eu.kanade.tachiyomi.util.system.setCustomTitleAndMessage
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
@ -147,7 +147,6 @@ fun List<Manga>.moveCategories(
} }
fun Manga.addOrRemoveToFavorites( fun Manga.addOrRemoveToFavorites(
db: DatabaseHelper,
preferences: PreferencesHelper, preferences: PreferencesHelper,
view: View, view: View,
activity: Activity, activity: Activity,
@ -175,12 +174,10 @@ fun Manga.addOrRemoveToFavorites(
this, this,
duplicateManga, duplicateManga,
activity, activity,
db,
sourceManager, sourceManager,
controller, controller,
addManga = { addManga = {
addOrRemoveToFavorites( addOrRemoveToFavorites(
db,
preferences, preferences,
view, view,
activity, activity,
@ -375,7 +372,6 @@ private fun showAddDuplicateDialog(
newManga: Manga, newManga: Manga,
libraryManga: Manga, libraryManga: Manga,
activity: Activity, activity: Activity,
db: DatabaseHelper,
sourceManager: SourceManager, sourceManager: SourceManager,
controller: Controller, controller: Controller,
addManga: () -> Unit, addManga: () -> Unit,
@ -389,18 +385,19 @@ private fun showAddDuplicateDialog(
val enabled = titles.indices.map { listView.isItemChecked(it) }.toTypedArray() val enabled = titles.indices.map { listView.isItemChecked(it) }.toTypedArray()
val flags = MigrationFlags.getFlagsFromPositions(enabled, libraryManga) val flags = MigrationFlags.getFlagsFromPositions(enabled, libraryManga)
val enhancedServices by lazy { Injekt.get<TrackManager>().services.filterIsInstance<EnhancedTrackService>() } val enhancedServices by lazy { Injekt.get<TrackManager>().services.filterIsInstance<EnhancedTrackService>() }
MigrationProcessAdapter.migrateMangaInternal( launchUI {
flags, MigrationProcessAdapter.migrateMangaInternal(
db, flags,
enhancedServices, enhancedServices,
Injekt.get(), Injekt.get(),
Injekt.get(), Injekt.get(),
source, source,
sourceManager.getOrStub(newManga.source), sourceManager.getOrStub(newManga.source),
libraryManga, libraryManga,
newManga, newManga,
replace, replace,
) )
}
migrateManga(libraryManga.source, !replace) migrateManga(libraryManga.source, !replace)
} }

View file

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.util.chapter package eu.kanade.tachiyomi.util.chapter
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
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.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -67,7 +66,6 @@ private var trackingJobs = HashMap<Long, Pair<Job?, Float?>>()
* will run in a background thread and errors are ignored. * will run in a background thread and errors are ignored.
*/ */
fun updateTrackChapterMarkedAsRead( fun updateTrackChapterMarkedAsRead(
db: DatabaseHelper,
preferences: PreferencesHelper, preferences: PreferencesHelper,
newLastChapter: Chapter?, newLastChapter: Chapter?,
mangaId: Long?, mangaId: Long?,

View file

@ -15,7 +15,6 @@ import coil3.size.SizeResolver
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.appwidget.TachiyomiWidgetManager import eu.kanade.tachiyomi.appwidget.TachiyomiWidgetManager
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
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.domain.manga.models.Manga import eu.kanade.tachiyomi.domain.manga.models.Manga
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
@ -35,7 +34,6 @@ import kotlin.math.min
class MangaShortcutManager( class MangaShortcutManager(
val preferences: PreferencesHelper = Injekt.get(), val preferences: PreferencesHelper = Injekt.get(),
val db: DatabaseHelper = Injekt.get(),
val coverCache: CoverCache = Injekt.get(), val coverCache: CoverCache = Injekt.get(),
val sourceManager: SourceManager = Injekt.get(), val sourceManager: SourceManager = Injekt.get(),
) { ) {

View file

@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.core.storage.AndroidStorageFolderProvider import eu.kanade.tachiyomi.core.storage.AndroidStorageFolderProvider
import eu.kanade.tachiyomi.data.cache.ChapterCache import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.DbOpenCallback import eu.kanade.tachiyomi.data.database.DbOpenCallback
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.library.CustomMangaManager import eu.kanade.tachiyomi.data.library.CustomMangaManager
@ -84,10 +83,6 @@ fun appModule(app: Application) = module {
single<DatabaseHandler> { AndroidDatabaseHandler(get(), get()) } single<DatabaseHandler> { AndroidDatabaseHandler(get(), get()) }
single { DatabaseHelper(app, get()) } withOptions {
createdAtStart()
}
single { ChapterCache(app) } single { ChapterCache(app) }
single { CoverCache(app) } single { CoverCache(app) }

View file

@ -28,4 +28,24 @@ class TrackRepositoryImpl(private val handler: DatabaseHandler) : TrackRepositor
finishDate = track.finished_reading_date, finishDate = track.finished_reading_date,
) )
} }
override suspend fun insertBulk(tracks: List<Track>) =
handler.await(inTransaction = true) {
tracks.forEach { track ->
manga_syncQueries.insert(
mangaId = track.manga_id,
syncId = track.sync_id,
remoteId = track.media_id,
libraryId = track.library_id,
title = track.title,
lastChapterRead = track.last_chapter_read.toDouble(),
totalChapters = track.total_chapters,
status = track.status.toLong(),
score = track.score.toDouble(),
remoteUrl = track.tracking_url,
startDate = track.started_reading_date,
finishDate = track.finished_reading_date,
)
}
}
} }

View file

@ -6,6 +6,6 @@ class GetCategories(
private val categoryRepository: CategoryRepository, private val categoryRepository: CategoryRepository,
) { ) {
suspend fun await() = categoryRepository.getAll() suspend fun await() = categoryRepository.getAll()
suspend fun awaitByMangaId(mangaId: Long) = categoryRepository.getAllByMangaId(mangaId) suspend fun awaitByMangaId(mangaId: Long?) = mangaId?.let { categoryRepository.getAllByMangaId(it) }.orEmpty()
fun subscribe() = categoryRepository.getAllAsFlow() fun subscribe() = categoryRepository.getAllAsFlow()
} }

View file

@ -6,7 +6,9 @@ import yokai.domain.manga.MangaRepository
class SetMangaCategories( class SetMangaCategories(
private val mangaRepository: MangaRepository, private val mangaRepository: MangaRepository,
) { ) {
suspend fun await(mangaId: Long, categories: List<Long>) = mangaRepository.setCategories(mangaId, categories) suspend fun await(mangaId: Long?, categories: List<Long>) {
mangaRepository.setCategories(mangaId ?: return, categories)
}
suspend fun awaitAll(mangaIds: List<Long>, mangaCategories: List<MangaCategory>) = suspend fun awaitAll(mangaIds: List<Long>, mangaCategories: List<MangaCategory>) =
mangaRepository.setMultipleMangaCategories(mangaIds, mangaCategories) mangaRepository.setMultipleMangaCategories(mangaIds, mangaCategories)
} }

View file

@ -6,4 +6,5 @@ interface TrackRepository {
suspend fun getAllByMangaId(mangaId: Long): List<Track> suspend fun getAllByMangaId(mangaId: Long): List<Track>
suspend fun deleteForManga(mangaId: Long, syncId: Long) suspend fun deleteForManga(mangaId: Long, syncId: Long)
suspend fun insert(track: Track) suspend fun insert(track: Track)
suspend fun insertBulk(tracks: List<Track>)
} }

View file

@ -7,4 +7,5 @@ class InsertTrack(
private val trackRepository: TrackRepository, private val trackRepository: TrackRepository,
) { ) {
suspend fun await(track: Track) = trackRepository.insert(track) suspend fun await(track: Track) = trackRepository.insert(track)
suspend fun awaitBulk(tracks: List<Track>) = trackRepository.insertBulk(tracks)
} }