Move SQLDelight to data module (#8954)
And use tachiyomi instead of eu.kanade.tachiyomi for package names in the module (cherry picked from commit 823749fc1ed16dbf52d43839888a70de089d65b1) # Conflicts: # app/build.gradle.kts # app/src/main/java/eu/kanade/data/history/HistoryRepositoryImpl.kt # app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.kt # app/src/main/java/eu/kanade/data/updates/UpdatesRepositoryImpl.kt # app/src/main/java/eu/kanade/tachiyomi/App.kt # app/src/main/java/eu/kanade/tachiyomi/AppModule.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt # app/src/main/java/eu/kanade/tachiyomi/source/model/SMangaExtensions.kt # data/src/main/java/tachiyomi/data/AndroidDatabaseHandler.kt # data/src/main/sqldelight/tachiyomi/data/eh.sq # data/src/main/sqldelight/tachiyomi/data/eh_favorites.sq # data/src/main/sqldelight/tachiyomi/data/feed_saved_search.sq # data/src/main/sqldelight/tachiyomi/data/merged.sq # data/src/main/sqldelight/tachiyomi/data/saved_search.sq # data/src/main/sqldelight/tachiyomi/data/search_metadata.sq # data/src/main/sqldelight/tachiyomi/data/search_tags.sq # data/src/main/sqldelight/tachiyomi/data/search_titles.sq # data/src/main/sqldelight/tachiyomi/migrations/16.sqm # data/src/main/sqldelight/tachiyomi/migrations/24.sqm
This commit is contained in:
@@ -1,98 +0,0 @@
|
||||
package eu.kanade.data
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import com.squareup.sqldelight.Query
|
||||
import com.squareup.sqldelight.db.SqlDriver
|
||||
import com.squareup.sqldelight.runtime.coroutines.asFlow
|
||||
import com.squareup.sqldelight.runtime.coroutines.mapToList
|
||||
import com.squareup.sqldelight.runtime.coroutines.mapToOne
|
||||
import com.squareup.sqldelight.runtime.coroutines.mapToOneOrNull
|
||||
import eu.kanade.data.manga.LibraryQuery
|
||||
import eu.kanade.data.updates.UpdatesQuery
|
||||
import eu.kanade.tachiyomi.Database
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class AndroidDatabaseHandler(
|
||||
val db: Database,
|
||||
private val driver: SqlDriver,
|
||||
val queryDispatcher: CoroutineDispatcher = Dispatchers.IO,
|
||||
val transactionDispatcher: CoroutineDispatcher = queryDispatcher,
|
||||
) : DatabaseHandler {
|
||||
|
||||
val suspendingTransactionId = ThreadLocal<Int>()
|
||||
|
||||
override suspend fun <T> await(inTransaction: Boolean, block: suspend Database.() -> T): T {
|
||||
return dispatch(inTransaction, block)
|
||||
}
|
||||
|
||||
override suspend fun <T : Any> awaitList(
|
||||
inTransaction: Boolean,
|
||||
block: suspend Database.() -> Query<T>,
|
||||
): List<T> {
|
||||
return dispatch(inTransaction) { block(db).executeAsList() }
|
||||
}
|
||||
|
||||
override suspend fun <T : Any> awaitOne(
|
||||
inTransaction: Boolean,
|
||||
block: suspend Database.() -> Query<T>,
|
||||
): T {
|
||||
return dispatch(inTransaction) { block(db).executeAsOne() }
|
||||
}
|
||||
|
||||
override suspend fun <T : Any> awaitOneOrNull(
|
||||
inTransaction: Boolean,
|
||||
block: suspend Database.() -> Query<T>,
|
||||
): T? {
|
||||
return dispatch(inTransaction) { block(db).executeAsOneOrNull() }
|
||||
}
|
||||
|
||||
override fun <T : Any> subscribeToList(block: Database.() -> Query<T>): Flow<List<T>> {
|
||||
return block(db).asFlow().mapToList(queryDispatcher)
|
||||
}
|
||||
|
||||
override fun <T : Any> subscribeToOne(block: Database.() -> Query<T>): Flow<T> {
|
||||
return block(db).asFlow().mapToOne(queryDispatcher)
|
||||
}
|
||||
|
||||
override fun <T : Any> subscribeToOneOrNull(block: Database.() -> Query<T>): Flow<T?> {
|
||||
return block(db).asFlow().mapToOneOrNull(queryDispatcher)
|
||||
}
|
||||
|
||||
override fun <T : Any> subscribeToPagingSource(
|
||||
countQuery: Database.() -> Query<Long>,
|
||||
queryProvider: Database.(Long, Long) -> Query<T>,
|
||||
): PagingSource<Long, T> {
|
||||
return QueryPagingSource(
|
||||
handler = this,
|
||||
countQuery = countQuery,
|
||||
queryProvider = { limit, offset ->
|
||||
queryProvider.invoke(db, limit, offset)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun <T> dispatch(inTransaction: Boolean, block: suspend Database.() -> T): T {
|
||||
// Create a transaction if needed and run the calling block inside it.
|
||||
if (inTransaction) {
|
||||
return withTransaction { block(db) }
|
||||
}
|
||||
|
||||
// If we're currently in the transaction thread, there's no need to dispatch our query.
|
||||
if (driver.currentTransaction() != null) {
|
||||
return block(db)
|
||||
}
|
||||
|
||||
// Get the current database context and run the calling block.
|
||||
val context = getCurrentDatabaseContext()
|
||||
return withContext(context) { block(db) }
|
||||
}
|
||||
|
||||
// SY -->
|
||||
fun getLibraryQuery() = LibraryQuery(driver)
|
||||
|
||||
fun getUpdatesQuery(after: Long) = UpdatesQuery(driver, after)
|
||||
// SY <--
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package eu.kanade.data
|
||||
|
||||
import com.squareup.sqldelight.ColumnAdapter
|
||||
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||
import java.util.Date
|
||||
|
||||
val dateAdapter = object : ColumnAdapter<Date, Long> {
|
||||
override fun decode(databaseValue: Long): Date = Date(databaseValue)
|
||||
override fun encode(value: Date): Long = value.time
|
||||
}
|
||||
|
||||
private const val listOfStringsSeparator = ", "
|
||||
val listOfStringsAdapter = object : ColumnAdapter<List<String>, String> {
|
||||
override fun decode(databaseValue: String) =
|
||||
if (databaseValue.isEmpty()) {
|
||||
emptyList()
|
||||
} else {
|
||||
databaseValue.split(listOfStringsSeparator)
|
||||
}
|
||||
override fun encode(value: List<String>) = value.joinToString(separator = listOfStringsSeparator)
|
||||
}
|
||||
|
||||
val updateStrategyAdapter = object : ColumnAdapter<UpdateStrategy, Long> {
|
||||
private val enumValues by lazy { UpdateStrategy.values() }
|
||||
|
||||
override fun decode(databaseValue: Long): UpdateStrategy =
|
||||
enumValues.getOrElse(databaseValue.toInt()) { UpdateStrategy.ALWAYS_UPDATE }
|
||||
|
||||
override fun encode(value: UpdateStrategy): Long = value.ordinal.toLong()
|
||||
}
|
||||
|
||||
// SY -->
|
||||
private const val listOfStringsAndSeparator = " & "
|
||||
val listOfStringsAndAdapter = object : ColumnAdapter<List<String>, String> {
|
||||
override fun decode(databaseValue: String) =
|
||||
if (databaseValue.isEmpty()) {
|
||||
emptyList()
|
||||
} else {
|
||||
databaseValue.split(listOfStringsAndSeparator)
|
||||
}
|
||||
override fun encode(value: List<String>) = value.joinToString(separator = listOfStringsAndSeparator)
|
||||
}
|
||||
|
||||
private const val listOfLongsSeparator = "/"
|
||||
val listOfLongsAdapter = object : ColumnAdapter<List<Long>, String> {
|
||||
override fun decode(databaseValue: String) =
|
||||
if (databaseValue.isEmpty()) {
|
||||
emptyList()
|
||||
} else {
|
||||
databaseValue.split(listOfLongsSeparator).mapNotNull { it.toLongOrNull() }
|
||||
}
|
||||
override fun encode(value: List<Long>) = value.joinToString(separator = listOfLongsSeparator)
|
||||
}
|
||||
// SY <--
|
||||
@@ -1,37 +0,0 @@
|
||||
package eu.kanade.data
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import com.squareup.sqldelight.Query
|
||||
import eu.kanade.tachiyomi.Database
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface DatabaseHandler {
|
||||
|
||||
suspend fun <T> await(inTransaction: Boolean = false, block: suspend Database.() -> T): T
|
||||
|
||||
suspend fun <T : Any> awaitList(
|
||||
inTransaction: Boolean = false,
|
||||
block: suspend Database.() -> Query<T>,
|
||||
): List<T>
|
||||
|
||||
suspend fun <T : Any> awaitOne(
|
||||
inTransaction: Boolean = false,
|
||||
block: suspend Database.() -> Query<T>,
|
||||
): T
|
||||
|
||||
suspend fun <T : Any> awaitOneOrNull(
|
||||
inTransaction: Boolean = false,
|
||||
block: suspend Database.() -> Query<T>,
|
||||
): T?
|
||||
|
||||
fun <T : Any> subscribeToList(block: Database.() -> Query<T>): Flow<List<T>>
|
||||
|
||||
fun <T : Any> subscribeToOne(block: Database.() -> Query<T>): Flow<T>
|
||||
|
||||
fun <T : Any> subscribeToOneOrNull(block: Database.() -> Query<T>): Flow<T?>
|
||||
|
||||
fun <T : Any> subscribeToPagingSource(
|
||||
countQuery: Database.() -> Query<Long>,
|
||||
queryProvider: Database.(Long, Long) -> Query<T>,
|
||||
): PagingSource<Long, T>
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package eu.kanade.data
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.squareup.sqldelight.Query
|
||||
import eu.kanade.tachiyomi.Database
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
class QueryPagingSource<RowType : Any>(
|
||||
val handler: DatabaseHandler,
|
||||
val countQuery: Database.() -> Query<Long>,
|
||||
val queryProvider: Database.(Long, Long) -> Query<RowType>,
|
||||
) : PagingSource<Long, RowType>(), Query.Listener {
|
||||
|
||||
override val jumpingSupported: Boolean = true
|
||||
|
||||
private var currentQuery: Query<RowType>? by Delegates.observable(null) { _, old, new ->
|
||||
old?.removeListener(this)
|
||||
new?.addListener(this)
|
||||
}
|
||||
|
||||
init {
|
||||
registerInvalidatedCallback {
|
||||
currentQuery?.removeListener(this)
|
||||
currentQuery = null
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(params: LoadParams<Long>): LoadResult<Long, RowType> {
|
||||
try {
|
||||
val key = params.key ?: 0L
|
||||
val loadSize = params.loadSize
|
||||
val count = handler.awaitOne { countQuery() }
|
||||
|
||||
val (offset, limit) = when (params) {
|
||||
is LoadParams.Prepend -> key - loadSize to loadSize.toLong()
|
||||
else -> key to loadSize.toLong()
|
||||
}
|
||||
|
||||
val data = handler.awaitList {
|
||||
queryProvider(limit, offset)
|
||||
.also { currentQuery = it }
|
||||
}
|
||||
|
||||
val (prevKey, nextKey) = when (params) {
|
||||
is LoadParams.Append -> { offset - loadSize to offset + loadSize }
|
||||
else -> { offset to offset + loadSize }
|
||||
}
|
||||
|
||||
return LoadResult.Page(
|
||||
data = data,
|
||||
prevKey = if (offset <= 0L || prevKey < 0L) null else prevKey,
|
||||
nextKey = if (offset + loadSize >= count) null else nextKey,
|
||||
itemsBefore = maxOf(0L, offset).toInt(),
|
||||
itemsAfter = maxOf(0L, count - (offset + loadSize)).toInt(),
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
return LoadResult.Error(throwable = e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Long, RowType>): Long? {
|
||||
return state.anchorPosition?.let { anchorPosition ->
|
||||
val anchorPage = state.closestPageToPosition(anchorPosition)
|
||||
anchorPage?.prevKey ?: anchorPage?.nextKey
|
||||
}
|
||||
}
|
||||
|
||||
override fun queryResultsChanged() {
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
package eu.kanade.data
|
||||
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.asContextElement
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.concurrent.RejectedExecutionException
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.coroutines.ContinuationInterceptor
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.coroutines.coroutineContext
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
/**
|
||||
* Returns the transaction dispatcher if we are on a transaction, or the database dispatchers.
|
||||
*/
|
||||
internal suspend fun AndroidDatabaseHandler.getCurrentDatabaseContext(): CoroutineContext {
|
||||
return coroutineContext[TransactionElement]?.transactionDispatcher ?: queryDispatcher
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the specified suspending [block] in a database transaction. The transaction will be
|
||||
* marked as successful unless an exception is thrown in the suspending [block] or the coroutine
|
||||
* is cancelled.
|
||||
*
|
||||
* SQLDelight will only perform at most one transaction at a time, additional transactions are queued
|
||||
* and executed on a first come, first serve order.
|
||||
*
|
||||
* Performing blocking database operations is not permitted in a coroutine scope other than the
|
||||
* one received by the suspending block. It is recommended that all [Dao] function invoked within
|
||||
* the [block] be suspending functions.
|
||||
*
|
||||
* The dispatcher used to execute the given [block] will utilize threads from SQLDelight's query executor.
|
||||
*/
|
||||
internal suspend fun <T> AndroidDatabaseHandler.withTransaction(block: suspend () -> T): T {
|
||||
// Use inherited transaction context if available, this allows nested suspending transactions.
|
||||
val transactionContext =
|
||||
coroutineContext[TransactionElement]?.transactionDispatcher ?: createTransactionContext()
|
||||
return withContext(transactionContext) {
|
||||
val transactionElement = coroutineContext[TransactionElement]!!
|
||||
transactionElement.acquire()
|
||||
try {
|
||||
db.transactionWithResult {
|
||||
runBlocking(transactionContext) {
|
||||
block()
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
transactionElement.release()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a [CoroutineContext] for performing database operations within a coroutine transaction.
|
||||
*
|
||||
* The context is a combination of a dispatcher, a [TransactionElement] and a thread local element.
|
||||
*
|
||||
* * The dispatcher will dispatch coroutines to a single thread that is taken over from the SQLDelight
|
||||
* query executor. If the coroutine context is switched, suspending DAO functions will be able to
|
||||
* dispatch to the transaction thread.
|
||||
*
|
||||
* * The [TransactionElement] serves as an indicator for inherited context, meaning, if there is a
|
||||
* switch of context, suspending DAO methods will be able to use the indicator to dispatch the
|
||||
* database operation to the transaction thread.
|
||||
*
|
||||
* * The thread local element serves as a second indicator and marks threads that are used to
|
||||
* execute coroutines within the coroutine transaction, more specifically it allows us to identify
|
||||
* if a blocking DAO method is invoked within the transaction coroutine. Never assign meaning to
|
||||
* this value, for now all we care is if its present or not.
|
||||
*/
|
||||
private suspend fun AndroidDatabaseHandler.createTransactionContext(): CoroutineContext {
|
||||
val controlJob = Job()
|
||||
// make sure to tie the control job to this context to avoid blocking the transaction if
|
||||
// context get cancelled before we can even start using this job. Otherwise, the acquired
|
||||
// transaction thread will forever wait for the controlJob to be cancelled.
|
||||
// see b/148181325
|
||||
coroutineContext[Job]?.invokeOnCompletion {
|
||||
controlJob.cancel()
|
||||
}
|
||||
|
||||
val dispatcher = transactionDispatcher.acquireTransactionThread(controlJob)
|
||||
val transactionElement = TransactionElement(controlJob, dispatcher)
|
||||
val threadLocalElement =
|
||||
suspendingTransactionId.asContextElement(System.identityHashCode(controlJob))
|
||||
return dispatcher + transactionElement + threadLocalElement
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires a thread from the executor and returns a [ContinuationInterceptor] to dispatch
|
||||
* coroutines to the acquired thread. The [controlJob] is used to control the release of the
|
||||
* thread by cancelling the job.
|
||||
*/
|
||||
private suspend fun CoroutineDispatcher.acquireTransactionThread(
|
||||
controlJob: Job,
|
||||
): ContinuationInterceptor {
|
||||
return suspendCancellableCoroutine { continuation ->
|
||||
continuation.invokeOnCancellation {
|
||||
// We got cancelled while waiting to acquire a thread, we can't stop our attempt to
|
||||
// acquire a thread, but we can cancel the controlling job so once it gets acquired it
|
||||
// is quickly released.
|
||||
controlJob.cancel()
|
||||
}
|
||||
try {
|
||||
dispatch(EmptyCoroutineContext) {
|
||||
runBlocking {
|
||||
// Thread acquired, resume coroutine
|
||||
continuation.resume(coroutineContext[ContinuationInterceptor]!!)
|
||||
controlJob.join()
|
||||
}
|
||||
}
|
||||
} catch (ex: RejectedExecutionException) {
|
||||
// Couldn't acquire a thread, cancel coroutine
|
||||
continuation.cancel(
|
||||
IllegalStateException(
|
||||
"Unable to acquire a thread to perform the database transaction",
|
||||
ex,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A [CoroutineContext.Element] that indicates there is an on-going database transaction.
|
||||
*/
|
||||
private class TransactionElement(
|
||||
private val transactionThreadControlJob: Job,
|
||||
val transactionDispatcher: ContinuationInterceptor,
|
||||
) : CoroutineContext.Element {
|
||||
|
||||
companion object Key : CoroutineContext.Key<TransactionElement>
|
||||
|
||||
override val key: CoroutineContext.Key<TransactionElement>
|
||||
get() = TransactionElement
|
||||
|
||||
/**
|
||||
* Number of transactions (including nested ones) started with this element.
|
||||
* Call [acquire] to increase the count and [release] to decrease it. If the count reaches zero
|
||||
* when [release] is invoked then the transaction job is cancelled and the transaction thread
|
||||
* is released.
|
||||
*/
|
||||
private val referenceCount = AtomicInteger(0)
|
||||
|
||||
fun acquire() {
|
||||
referenceCount.incrementAndGet()
|
||||
}
|
||||
|
||||
fun release() {
|
||||
val count = referenceCount.decrementAndGet()
|
||||
if (count < 0) {
|
||||
throw IllegalStateException("Transaction was never started or was already released")
|
||||
} else if (count == 0) {
|
||||
// Cancel the job that controls the transaction thread, causing it to be released.
|
||||
transactionThreadControlJob.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package eu.kanade.data.category
|
||||
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.domain.category.model.Category
|
||||
import eu.kanade.domain.category.model.CategoryUpdate
|
||||
import eu.kanade.domain.category.repository.CategoryRepository
|
||||
import eu.kanade.tachiyomi.Database
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import tachiyomi.data.Database
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class CategoryRepositoryImpl(
|
||||
private val handler: DatabaseHandler,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package eu.kanade.data.chapter
|
||||
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.domain.chapter.model.Chapter
|
||||
import eu.kanade.domain.chapter.model.ChapterUpdate
|
||||
import eu.kanade.domain.chapter.repository.ChapterRepository
|
||||
@@ -8,6 +7,7 @@ import eu.kanade.tachiyomi.util.system.logcat
|
||||
import eu.kanade.tachiyomi.util.system.toLong
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class ChapterRepositoryImpl(
|
||||
private val handler: DatabaseHandler,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package eu.kanade.data.history
|
||||
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.domain.history.model.History
|
||||
import eu.kanade.domain.history.model.HistoryUpdate
|
||||
import eu.kanade.domain.history.model.HistoryWithRelations
|
||||
@@ -8,6 +7,7 @@ import eu.kanade.domain.history.repository.HistoryRepository
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class HistoryRepositoryImpl(
|
||||
private val handler: DatabaseHandler,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package eu.kanade.data.manga
|
||||
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.data.exh.favoriteEntryMapper
|
||||
import eu.kanade.domain.manga.repository.FavoritesEntryRepository
|
||||
import exh.favorites.sql.models.FavoriteEntry
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class FavoritesEntryRepositoryImpl(
|
||||
private val handler: DatabaseHandler,
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
package eu.kanade.data.manga
|
||||
|
||||
import com.squareup.sqldelight.Query
|
||||
import com.squareup.sqldelight.db.SqlCursor
|
||||
import com.squareup.sqldelight.db.SqlDriver
|
||||
import com.squareup.sqldelight.internal.copyOnWriteList
|
||||
import eu.kanade.data.listOfStringsAdapter
|
||||
import eu.kanade.data.listOfStringsAndAdapter
|
||||
import eu.kanade.data.updateStrategyAdapter
|
||||
import eu.kanade.domain.library.model.LibraryManga
|
||||
import exh.source.MERGED_SOURCE_ID
|
||||
|
||||
private val mapper = { cursor: SqlCursor ->
|
||||
LibraryManga(
|
||||
manga = mangaMapper(
|
||||
cursor.getLong(0)!!,
|
||||
cursor.getLong(1)!!,
|
||||
cursor.getString(2)!!,
|
||||
cursor.getString(3),
|
||||
cursor.getString(4),
|
||||
cursor.getString(5),
|
||||
cursor.getString(6)?.let(listOfStringsAdapter::decode),
|
||||
cursor.getString(7)!!,
|
||||
cursor.getLong(8)!!,
|
||||
cursor.getString(9),
|
||||
cursor.getLong(10)!! == 1L,
|
||||
cursor.getLong(11) ?: 0,
|
||||
null,
|
||||
cursor.getLong(13)!! == 1L,
|
||||
cursor.getLong(14)!!,
|
||||
cursor.getLong(15)!!,
|
||||
cursor.getLong(16)!!,
|
||||
cursor.getLong(17)!!,
|
||||
cursor.getString(18)?.let(listOfStringsAndAdapter::decode),
|
||||
updateStrategyAdapter.decode(cursor.getLong(19)!!),
|
||||
),
|
||||
totalChapters = cursor.getLong(20)!!,
|
||||
readCount = cursor.getLong(21)!!,
|
||||
latestUpload = cursor.getLong(22)!!,
|
||||
chapterFetchedAt = cursor.getLong(23)!!,
|
||||
lastRead = cursor.getLong(24)!!,
|
||||
bookmarkCount = cursor.getLong(25)!!,
|
||||
category = cursor.getLong(26)!!,
|
||||
)
|
||||
}
|
||||
|
||||
class LibraryQuery(val driver: SqlDriver) : Query<LibraryManga>(copyOnWriteList(), mapper) {
|
||||
override fun execute(): SqlCursor {
|
||||
return driver.executeQuery(
|
||||
null,
|
||||
"""
|
||||
SELECT
|
||||
M.*,
|
||||
coalesce(C.total, 0) AS totalCount,
|
||||
coalesce(C.readCount, 0) AS readCount,
|
||||
coalesce(C.latestUpload, 0) AS latestUpload,
|
||||
coalesce(C.fetchedAt, 0) AS chapterFetchedAt,
|
||||
coalesce(C.lastRead, 0) AS lastRead,
|
||||
coalesce(C.bookmarkCount, 0) AS bookmarkCount,
|
||||
coalesce(MC.category_id, 0) AS category
|
||||
FROM mangas M
|
||||
LEFT JOIN(
|
||||
SELECT
|
||||
chapters.manga_id,
|
||||
count(*) AS total,
|
||||
sum(read) AS readCount,
|
||||
coalesce(max(chapters.date_upload), 0) AS latestUpload,
|
||||
coalesce(max(history.last_read), 0) AS lastRead,
|
||||
coalesce(max(chapters.date_fetch), 0) AS fetchedAt,
|
||||
sum(chapters.bookmark) AS bookmarkCount
|
||||
FROM chapters
|
||||
LEFT JOIN history
|
||||
ON chapters._id = history.chapter_id
|
||||
GROUP BY chapters.manga_id
|
||||
) AS C
|
||||
ON M._id = C.manga_id
|
||||
LEFT JOIN mangas_categories AS MC
|
||||
ON MC.manga_id = M._id
|
||||
WHERE M.favorite = 1 AND M.source <> $MERGED_SOURCE_ID
|
||||
UNION
|
||||
SELECT
|
||||
M.*,
|
||||
coalesce(C.total, 0) AS totalCount,
|
||||
coalesce(C.readCount, 0) AS readCount,
|
||||
coalesce(C.latestUpload, 0) AS latestUpload,
|
||||
coalesce(C.fetchedAt, 0) AS chapterFetchedAt,
|
||||
coalesce(C.lastRead, 0) AS lastRead,
|
||||
coalesce(C.bookmarkCount, 0) AS bookmarkCount,
|
||||
coalesce(MC.category_id, 0) AS category
|
||||
FROM mangas M
|
||||
LEFT JOIN (
|
||||
SELECT merged.manga_id,merged.merge_id
|
||||
FROM merged
|
||||
GROUP BY merged.merge_id
|
||||
) as ME
|
||||
ON ME.merge_id = M._id
|
||||
LEFT JOIN(
|
||||
SELECT
|
||||
ME.merge_id,
|
||||
count(*) AS total,
|
||||
sum(read) AS readCount,
|
||||
coalesce(max(chapters.date_upload), 0) AS latestUpload,
|
||||
coalesce(max(history.last_read), 0) AS lastRead,
|
||||
coalesce(max(chapters.date_fetch), 0) AS fetchedAt,
|
||||
sum(chapters.bookmark) AS bookmarkCount
|
||||
FROM chapters
|
||||
LEFT JOIN history
|
||||
ON chapters._id = history.chapter_id
|
||||
LEFT JOIN merged as ME
|
||||
ON ME.manga_id = chapters.manga_id
|
||||
GROUP BY ME.merge_id
|
||||
) AS C
|
||||
ON ME.merge_id = C.merge_id
|
||||
LEFT JOIN mangas_categories AS MC
|
||||
ON MC.manga_id = M._id
|
||||
WHERE M.favorite = 1 AND M.source = $MERGED_SOURCE_ID;
|
||||
""".trimIndent(),
|
||||
1,
|
||||
)
|
||||
}
|
||||
|
||||
override fun toString(): String = "LibraryQuery.sq:get"
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package eu.kanade.data.manga
|
||||
import eu.kanade.domain.library.model.LibraryManga
|
||||
import eu.kanade.domain.manga.model.Manga
|
||||
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||
import tachiyomi.view.LibraryView
|
||||
|
||||
val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, List<String>?, UpdateStrategy) -> Manga =
|
||||
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, _, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, filteredScanlators, updateStrategy ->
|
||||
@@ -69,3 +70,36 @@ val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?,
|
||||
lastRead = lastRead,
|
||||
)
|
||||
}
|
||||
|
||||
val libraryViewMapper: (LibraryView) -> LibraryManga = {
|
||||
LibraryManga(
|
||||
Manga(
|
||||
id = it._id,
|
||||
source = it.source,
|
||||
favorite = it.favorite,
|
||||
lastUpdate = it.last_update ?: 0,
|
||||
dateAdded = it.date_added,
|
||||
viewerFlags = it.viewer,
|
||||
chapterFlags = it.chapter_flags,
|
||||
coverLastModified = it.cover_last_modified,
|
||||
url = it.url,
|
||||
ogTitle = it.title,
|
||||
ogArtist = it.artist,
|
||||
ogAuthor = it.author,
|
||||
ogDescription = it.description,
|
||||
ogGenre = it.genre,
|
||||
ogStatus = it.status,
|
||||
thumbnailUrl = it.thumbnail_url,
|
||||
updateStrategy = it.update_strategy,
|
||||
initialized = it.initialized,
|
||||
filteredScanlators = it.filtered_scanlators,
|
||||
),
|
||||
it.category,
|
||||
it.totalCount,
|
||||
it.readCount,
|
||||
it.bookmarkCount,
|
||||
it.latestUpload,
|
||||
it.chapterFetchedAt,
|
||||
it.lastRead,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package eu.kanade.data.manga
|
||||
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.data.exh.mergedMangaReferenceMapper
|
||||
import eu.kanade.domain.manga.model.Manga
|
||||
import eu.kanade.domain.manga.model.MergeMangaSettingsUpdate
|
||||
@@ -10,6 +9,7 @@ import eu.kanade.tachiyomi.util.system.toLong
|
||||
import exh.merged.sql.models.MergedMangaReference
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class MangaMergeRepositoryImpl(
|
||||
private val handler: DatabaseHandler,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package eu.kanade.data.manga
|
||||
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.data.exh.searchMetadataMapper
|
||||
import eu.kanade.data.exh.searchTagMapper
|
||||
import eu.kanade.data.exh.searchTitleMapper
|
||||
@@ -13,6 +12,7 @@ import exh.metadata.sql.models.SearchTitle
|
||||
import exh.source.EH_SOURCE_ID
|
||||
import exh.source.EXH_SOURCE_ID
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class MangaMetadataRepositoryImpl(
|
||||
private val handler: DatabaseHandler,
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
package eu.kanade.data.manga
|
||||
|
||||
import eu.kanade.data.AndroidDatabaseHandler
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.data.listOfStringsAdapter
|
||||
import eu.kanade.data.listOfStringsAndAdapter
|
||||
import eu.kanade.data.updateStrategyAdapter
|
||||
import eu.kanade.domain.library.model.LibraryManga
|
||||
import eu.kanade.domain.manga.model.Manga
|
||||
import eu.kanade.domain.manga.model.MangaUpdate
|
||||
@@ -14,6 +9,11 @@ import eu.kanade.tachiyomi.util.system.toLong
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.data.AndroidDatabaseHandler
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
import tachiyomi.data.listOfStringsAdapter
|
||||
import tachiyomi.data.listOfStringsAndAdapter
|
||||
import tachiyomi.data.updateStrategyAdapter
|
||||
|
||||
class MangaRepositoryImpl(
|
||||
private val handler: DatabaseHandler,
|
||||
@@ -40,7 +40,7 @@ class MangaRepositoryImpl(
|
||||
}
|
||||
|
||||
override suspend fun getLibraryManga(): List<LibraryManga> {
|
||||
return handler.awaitList { (handler as AndroidDatabaseHandler).getLibraryQuery() }
|
||||
return handler.awaitList { (handler as AndroidDatabaseHandler).getLibraryQuery() }.map(libraryViewMapper)
|
||||
// return handler.awaitList { libraryViewQueries.library(libraryManga) }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package eu.kanade.data.source
|
||||
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.data.exh.feedSavedSearchMapper
|
||||
import eu.kanade.data.exh.savedSearchMapper
|
||||
import eu.kanade.domain.source.repository.FeedSavedSearchRepository
|
||||
import exh.savedsearches.models.FeedSavedSearch
|
||||
import exh.savedsearches.models.SavedSearch
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class FeedSavedSearchRepositoryImpl(
|
||||
private val handler: DatabaseHandler,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package eu.kanade.data.source
|
||||
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.data.exh.savedSearchMapper
|
||||
import eu.kanade.domain.source.repository.SavedSearchRepository
|
||||
import exh.savedsearches.models.SavedSearch
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class SavedSearchRepositoryImpl(
|
||||
private val handler: DatabaseHandler,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package eu.kanade.data.source
|
||||
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.domain.source.model.SourceData
|
||||
import eu.kanade.domain.source.repository.SourceDataRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class SourceDataRepositoryImpl(
|
||||
private val handler: DatabaseHandler,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package eu.kanade.data.source
|
||||
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.domain.source.model.Source
|
||||
import eu.kanade.domain.source.model.SourcePagingSourceType
|
||||
import eu.kanade.domain.source.model.SourceWithCount
|
||||
@@ -13,6 +12,7 @@ import eu.kanade.tachiyomi.source.online.all.EHentai
|
||||
import exh.source.MERGED_SOURCE_ID
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class SourceRepositoryImpl(
|
||||
private val sourceManager: SourceManager,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package eu.kanade.data.track
|
||||
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.domain.track.model.Track
|
||||
import eu.kanade.domain.track.repository.TrackRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class TrackRepositoryImpl(
|
||||
private val handler: DatabaseHandler,
|
||||
|
||||
@@ -2,6 +2,7 @@ package eu.kanade.data.updates
|
||||
|
||||
import eu.kanade.domain.manga.model.MangaCover
|
||||
import eu.kanade.domain.updates.model.UpdatesWithRelations
|
||||
import tachiyomi.view.UpdatesView
|
||||
|
||||
val updateWithRelationMapper: (Long, String, Long, String, String?, Boolean, Boolean, Long, Long, Boolean, String?, Long, Long, Long) -> UpdatesWithRelations = {
|
||||
mangaId, mangaTitle, chapterId, chapterName, scanlator, read, bookmark, lastPageRead, sourceId, favorite, thumbnailUrl, coverLastModified, _, dateFetch ->
|
||||
@@ -27,3 +28,25 @@ val updateWithRelationMapper: (Long, String, Long, String, String?, Boolean, Boo
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val updatesViewMapper: (UpdatesView) -> UpdatesWithRelations = {
|
||||
UpdatesWithRelations(
|
||||
mangaId = it.mangaId,
|
||||
ogMangaTitle = it.mangaTitle,
|
||||
chapterId = it.chapterId,
|
||||
chapterName = it.chapterName,
|
||||
scanlator = it.scanlator,
|
||||
read = it.read,
|
||||
bookmark = it.bookmark,
|
||||
lastPageRead = it.last_page_read,
|
||||
sourceId = it.source,
|
||||
dateFetch = it.datefetch,
|
||||
coverData = MangaCover(
|
||||
mangaId = it.mangaId,
|
||||
sourceId = it.source,
|
||||
isMangaFavorite = it.favorite,
|
||||
url = it.thumbnailUrl,
|
||||
lastModified = it.coverLastModified,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
package eu.kanade.data.updates
|
||||
|
||||
import com.squareup.sqldelight.Query
|
||||
import com.squareup.sqldelight.db.SqlCursor
|
||||
import com.squareup.sqldelight.db.SqlDriver
|
||||
import com.squareup.sqldelight.internal.copyOnWriteList
|
||||
import eu.kanade.domain.updates.model.UpdatesWithRelations
|
||||
import exh.source.MERGED_SOURCE_ID
|
||||
|
||||
private val mapper = { cursor: SqlCursor ->
|
||||
updateWithRelationMapper(
|
||||
cursor.getLong(0)!!,
|
||||
cursor.getString(1)!!,
|
||||
cursor.getLong(2)!!,
|
||||
cursor.getString(3)!!,
|
||||
cursor.getString(4),
|
||||
cursor.getLong(5)!! == 1L,
|
||||
cursor.getLong(6)!! == 1L,
|
||||
cursor.getLong(7)!!,
|
||||
cursor.getLong(8)!!,
|
||||
cursor.getLong(9)!! == 1L,
|
||||
cursor.getString(10),
|
||||
cursor.getLong(11)!!,
|
||||
cursor.getLong(12)!!,
|
||||
cursor.getLong(13)!!,
|
||||
)
|
||||
}
|
||||
|
||||
class UpdatesQuery(val driver: SqlDriver, val after: Long) : Query<UpdatesWithRelations>(copyOnWriteList(), mapper) {
|
||||
override fun execute(): SqlCursor {
|
||||
return driver.executeQuery(
|
||||
null,
|
||||
"""
|
||||
SELECT
|
||||
mangas._id AS mangaId,
|
||||
mangas.title AS mangaTitle,
|
||||
chapters._id AS chapterId,
|
||||
chapters.name AS chapterName,
|
||||
chapters.scanlator,
|
||||
chapters.read,
|
||||
chapters.bookmark,
|
||||
chapters.last_page_read,
|
||||
mangas.source,
|
||||
mangas.favorite,
|
||||
mangas.thumbnail_url AS thumbnailUrl,
|
||||
mangas.cover_last_modified AS coverLastModified,
|
||||
chapters.date_upload AS dateUpload,
|
||||
chapters.date_fetch AS datefetch
|
||||
FROM mangas JOIN chapters
|
||||
ON mangas._id = chapters.manga_id
|
||||
WHERE favorite = 1 AND source <> $MERGED_SOURCE_ID
|
||||
AND date_fetch > date_added
|
||||
AND dateUpload > :after
|
||||
UNION
|
||||
SELECT
|
||||
mangas._id AS mangaId,
|
||||
mangas.title AS mangaTitle,
|
||||
chapters._id AS chapterId,
|
||||
chapters.name AS chapterName,
|
||||
chapters.scanlator,
|
||||
chapters.read,
|
||||
chapters.bookmark,
|
||||
chapters.last_page_read,
|
||||
mangas.source,
|
||||
mangas.favorite,
|
||||
mangas.thumbnail_url AS thumbnailUrl,
|
||||
mangas.cover_last_modified AS coverLastModified,
|
||||
chapters.date_upload AS dateUpload,
|
||||
chapters.date_fetch AS datefetch
|
||||
FROM mangas
|
||||
LEFT JOIN (
|
||||
SELECT merged.manga_id,merged.merge_id
|
||||
FROM merged
|
||||
GROUP BY merged.merge_id
|
||||
) as ME
|
||||
ON ME.merge_id = mangas._id
|
||||
JOIN chapters
|
||||
ON ME.manga_id = chapters.manga_id
|
||||
WHERE favorite = 1 AND source = $MERGED_SOURCE_ID
|
||||
AND date_fetch > date_added
|
||||
AND dateUpload > :after
|
||||
ORDER BY datefetch DESC;
|
||||
""".trimIndent(),
|
||||
1,
|
||||
binders = {
|
||||
bindLong(1, after)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override fun toString(): String = "LibraryQuery.sq:get"
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package eu.kanade.data.updates
|
||||
|
||||
import eu.kanade.data.AndroidDatabaseHandler
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.domain.updates.model.UpdatesWithRelations
|
||||
import eu.kanade.domain.updates.repository.UpdatesRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import tachiyomi.data.AndroidDatabaseHandler
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
class UpdatesRepositoryImpl(
|
||||
val databaseHandler: DatabaseHandler,
|
||||
@@ -16,6 +16,7 @@ class UpdatesRepositoryImpl(
|
||||
updatesViewQueries.updates(after, updateWithRelationMapper)
|
||||
}.map {
|
||||
databaseHandler.awaitList { (databaseHandler as AndroidDatabaseHandler).getUpdatesQuery(after) }
|
||||
.map(updatesViewMapper)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -50,7 +50,6 @@ import eu.kanade.presentation.components.FastScrollLazyColumn
|
||||
import eu.kanade.presentation.components.LoadingScreen
|
||||
import eu.kanade.presentation.components.Scaffold
|
||||
import eu.kanade.presentation.util.selectedBackground
|
||||
import eu.kanade.tachiyomi.Database
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||
@@ -58,6 +57,7 @@ import eu.kanade.tachiyomi.util.lang.withNonCancellableContext
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.update
|
||||
import tachiyomi.data.Database
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
|
||||
-4
@@ -74,10 +74,6 @@ import eu.kanade.tachiyomi.util.CrashLogUtil
|
||||
import eu.kanade.tachiyomi.util.lang.launchNonCancellable
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.isPackageInstalled
|
||||
import eu.kanade.tachiyomi.util.system.isPreviewBuildType
|
||||
import eu.kanade.tachiyomi.util.system.isReleaseBuildType
|
||||
import eu.kanade.tachiyomi.util.system.isShizukuInstalled
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import eu.kanade.tachiyomi.util.system.powerManager
|
||||
|
||||
@@ -35,7 +35,6 @@ import com.elvishew.xlog.printer.file.clean.FileLastModifiedCleanStrategy
|
||||
import com.elvishew.xlog.printer.file.naming.DateFileNameGenerator
|
||||
import com.google.firebase.analytics.ktx.analytics
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.domain.DomainModule
|
||||
import eu.kanade.domain.SYDomainModule
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
@@ -74,6 +73,7 @@ import kotlinx.coroutines.flow.onEach
|
||||
import logcat.LogPriority
|
||||
import logcat.LogcatLogger
|
||||
import org.conscrypt.Conscrypt
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
@@ -7,16 +7,6 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
|
||||
import com.squareup.sqldelight.android.AndroidSqliteDriver
|
||||
import com.squareup.sqldelight.db.SqlDriver
|
||||
import data.Categories
|
||||
import data.History
|
||||
import data.Mangas
|
||||
import eu.kanade.data.AndroidDatabaseHandler
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.data.dateAdapter
|
||||
import eu.kanade.data.listOfLongsAdapter
|
||||
import eu.kanade.data.listOfStringsAdapter
|
||||
import eu.kanade.data.listOfStringsAndAdapter
|
||||
import eu.kanade.data.updateStrategyAdapter
|
||||
import eu.kanade.domain.UnsortedPreferences
|
||||
import eu.kanade.domain.backup.service.BackupPreferences
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
@@ -55,6 +45,17 @@ import nl.adaptivity.xmlutil.XmlDeclMode
|
||||
import nl.adaptivity.xmlutil.core.XmlVersion
|
||||
import nl.adaptivity.xmlutil.serialization.UnknownChildHandler
|
||||
import nl.adaptivity.xmlutil.serialization.XML
|
||||
import tachiyomi.data.AndroidDatabaseHandler
|
||||
import tachiyomi.data.Categories
|
||||
import tachiyomi.data.Database
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
import tachiyomi.data.History
|
||||
import tachiyomi.data.Mangas
|
||||
import tachiyomi.data.dateAdapter
|
||||
import tachiyomi.data.listOfLongsAdapter
|
||||
import tachiyomi.data.listOfStringsAdapter
|
||||
import tachiyomi.data.listOfStringsAndAdapter
|
||||
import tachiyomi.data.updateStrategyAdapter
|
||||
import uy.kohesive.injekt.api.InjektModule
|
||||
import uy.kohesive.injekt.api.InjektRegistrar
|
||||
import uy.kohesive.injekt.api.addSingleton
|
||||
|
||||
@@ -4,13 +4,8 @@ import android.Manifest
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.hippo.unifile.UniFile
|
||||
import data.Manga_sync
|
||||
import data.Mangas
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.data.exh.mergedMangaReferenceMapper
|
||||
import eu.kanade.data.listOfStringsAndAdapter
|
||||
import eu.kanade.data.manga.mangaMapper
|
||||
import eu.kanade.data.updateStrategyAdapter
|
||||
import eu.kanade.domain.backup.service.BackupPreferences
|
||||
import eu.kanade.domain.category.interactor.GetCategories
|
||||
import eu.kanade.domain.category.model.Category
|
||||
@@ -65,6 +60,11 @@ import logcat.LogPriority
|
||||
import okio.buffer
|
||||
import okio.gzip
|
||||
import okio.sink
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
import tachiyomi.data.Manga_sync
|
||||
import tachiyomi.data.Mangas
|
||||
import tachiyomi.data.listOfStringsAndAdapter
|
||||
import tachiyomi.data.updateStrategyAdapter
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.FileOutputStream
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package eu.kanade.tachiyomi.data.backup.models
|
||||
|
||||
import eu.kanade.data.listOfStringsAndAdapter
|
||||
import eu.kanade.domain.manga.model.Manga
|
||||
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
|
||||
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||
@@ -10,6 +9,7 @@ import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.protobuf.ProtoNumber
|
||||
import tachiyomi.data.listOfStringsAndAdapter
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Serializable
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package eu.kanade.tachiyomi.data.database.models
|
||||
|
||||
import eu.kanade.data.listOfStringsAndAdapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
|
||||
import exh.util.nullIfEmpty
|
||||
import tachiyomi.data.listOfStringsAndAdapter
|
||||
import eu.kanade.domain.manga.model.Manga as DomainManga
|
||||
|
||||
interface Manga : SManga {
|
||||
|
||||
@@ -43,7 +43,6 @@ import coil.request.ImageRequest
|
||||
import coil.size.Precision
|
||||
import coil.size.Scale
|
||||
import coil.transform.RoundedCornersTransformation
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.domain.manga.model.MangaCover
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.core.security.SecurityPreferences
|
||||
@@ -52,10 +51,11 @@ import eu.kanade.tachiyomi.util.Constants
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import kotlinx.coroutines.MainScope
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
import tachiyomi.view.UpdatesView
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import view.UpdatesView
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.kanade.tachiyomi.source.model
|
||||
|
||||
import data.Chapters
|
||||
import tachiyomi.data.Chapters
|
||||
|
||||
fun SChapter.copyFrom(other: Chapters) {
|
||||
name = other.name
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package eu.kanade.tachiyomi.source.model
|
||||
|
||||
import data.Mangas
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import tachiyomi.data.Mangas
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@@ -31,7 +31,7 @@ fun SManga.copyFrom(other: Mangas) {
|
||||
}
|
||||
|
||||
if (other.genre != null) {
|
||||
genre = other.genre.joinToString(separator = ", ")
|
||||
genre = other.genre!!.joinToString(separator = ", ")
|
||||
}
|
||||
|
||||
if (other.thumbnail_url != null) {
|
||||
|
||||
Reference in New Issue
Block a user