Migrate saved searches to the db
This commit is contained in:
@@ -40,6 +40,7 @@ import exh.eh.EHentaiUpdateWorker
|
||||
import exh.log.xLogE
|
||||
import exh.log.xLogW
|
||||
import exh.merged.sql.models.MergedMangaReference
|
||||
import exh.savedsearches.models.SavedSearch
|
||||
import exh.source.BlacklistedSources
|
||||
import exh.source.EH_SOURCE_ID
|
||||
import exh.source.HBROWSE_SOURCE_ID
|
||||
@@ -47,11 +48,17 @@ import exh.source.MERGED_SOURCE_ID
|
||||
import exh.source.PERV_EDEN_EN_SOURCE_ID
|
||||
import exh.source.PERV_EDEN_IT_SOURCE_ID
|
||||
import exh.source.TSUMINO_SOURCE_ID
|
||||
import exh.util.nullIfBlank
|
||||
import exh.util.under
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.contentOrNull
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
@@ -395,6 +402,26 @@ object EXHMigrations {
|
||||
if (oldVersion under 30) {
|
||||
BackupCreatorJob.setupTask(context)
|
||||
}
|
||||
if (oldVersion under 31) {
|
||||
val savedSearches = prefs.getStringSet("eh_saved_searches", emptySet())?.mapNotNull {
|
||||
kotlin.runCatching {
|
||||
val content = Json.decodeFromString<JsonObject>(it.substringAfter(':'))
|
||||
SavedSearch(
|
||||
id = null,
|
||||
source = it.substringBefore(':').toLongOrNull() ?: return@mapNotNull null,
|
||||
content["name"]!!.jsonPrimitive.content,
|
||||
content["query"]!!.jsonPrimitive.contentOrNull?.nullIfBlank(),
|
||||
Json.encodeToString(content["filters"]!!.jsonArray)
|
||||
)
|
||||
}.getOrNull()
|
||||
}?.ifEmpty { null }
|
||||
if (savedSearches != null) {
|
||||
db.insertSavedSearches(savedSearches)
|
||||
}
|
||||
prefs.edit(commit = true) {
|
||||
remove("eh_saved_searches")
|
||||
}
|
||||
}
|
||||
|
||||
// if (oldVersion under 1) { } (1 is current release version)
|
||||
// do stuff here when releasing changed crap
|
||||
|
||||
@@ -7,18 +7,15 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
|
||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.model.toSManga
|
||||
import eu.kanade.tachiyomi.source.online.all.NHentai
|
||||
import exh.EXHMigrations
|
||||
import exh.eh.EHentaiThrottleManager
|
||||
import exh.eh.EHentaiUpdateWorker
|
||||
import exh.log.xLogE
|
||||
import exh.metadata.metadata.EHentaiSearchMetadata
|
||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||
import exh.metadata.metadata.base.insertFlatMetadataAsync
|
||||
import exh.savedsearches.JsonSavedSearch
|
||||
import exh.source.EH_SOURCE_ID
|
||||
import exh.source.EXH_SOURCE_ID
|
||||
import exh.source.isEhBasedManga
|
||||
@@ -30,11 +27,7 @@ import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.lang.RuntimeException
|
||||
import java.util.UUID
|
||||
|
||||
@Suppress("unused")
|
||||
@@ -171,7 +164,7 @@ object DebugFunctions {
|
||||
it.favorite && db.getSearchMetadataForManga(it.id!!).executeAsBlocking() == null
|
||||
}
|
||||
|
||||
fun clearSavedSearches() = prefs.savedSearches().set(emptySet())
|
||||
fun clearSavedSearches() = db.deleteAllSavedSearches().executeAsBlocking()
|
||||
|
||||
fun listAllSources() = sourceManager.getCatalogueSources().joinToString("\n") {
|
||||
"${it.id}: ${it.name} (${it.lang.uppercase()})"
|
||||
@@ -249,7 +242,7 @@ object DebugFunctions {
|
||||
)
|
||||
}
|
||||
|
||||
fun copyEHentaiSavedSearchesToExhentai() {
|
||||
/*fun copyEHentaiSavedSearchesToExhentai() {
|
||||
runBlocking {
|
||||
val source = sourceManager.get(EH_SOURCE_ID) as? CatalogueSource ?: return@runBlocking
|
||||
val newSource = sourceManager.get(EXH_SOURCE_ID) as? CatalogueSource ?: return@runBlocking
|
||||
@@ -325,7 +318,7 @@ object DebugFunctions {
|
||||
}
|
||||
prefs.savedSearches().set((otherSerialized + newSerialized).toSet())
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
fun fixReaderViewerBackupBug() {
|
||||
db.inTransaction {
|
||||
|
||||
@@ -3,6 +3,7 @@ package exh.savedsearches
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
|
||||
data class EXHSavedSearch(
|
||||
val id: Long,
|
||||
val name: String,
|
||||
val query: String,
|
||||
val filterList: FilterList?
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package exh.savedsearches
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
|
||||
@Serializable
|
||||
data class JsonSavedSearch(
|
||||
val name: String,
|
||||
val query: String,
|
||||
val filters: JsonArray
|
||||
)
|
||||
@@ -0,0 +1,66 @@
|
||||
package exh.savedsearches.mappers
|
||||
|
||||
import android.database.Cursor
|
||||
import androidx.core.content.contentValuesOf
|
||||
import androidx.core.database.getStringOrNull
|
||||
import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping
|
||||
import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver
|
||||
import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
|
||||
import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver
|
||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
||||
import com.pushtorefresh.storio.sqlite.queries.InsertQuery
|
||||
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
|
||||
import exh.savedsearches.models.SavedSearch
|
||||
import exh.savedsearches.tables.SavedSearchTable.COL_FILTERS_JSON
|
||||
import exh.savedsearches.tables.SavedSearchTable.COL_ID
|
||||
import exh.savedsearches.tables.SavedSearchTable.COL_NAME
|
||||
import exh.savedsearches.tables.SavedSearchTable.COL_QUERY
|
||||
import exh.savedsearches.tables.SavedSearchTable.COL_SOURCE
|
||||
import exh.savedsearches.tables.SavedSearchTable.TABLE
|
||||
|
||||
class SavedSearchTypeMapping : SQLiteTypeMapping<SavedSearch>(
|
||||
SavedSearchPutResolver(),
|
||||
SavedSearchGetResolver(),
|
||||
SavedSearchDeleteResolver()
|
||||
)
|
||||
|
||||
class SavedSearchPutResolver : DefaultPutResolver<SavedSearch>() {
|
||||
|
||||
override fun mapToInsertQuery(obj: SavedSearch) = InsertQuery.builder()
|
||||
.table(TABLE)
|
||||
.build()
|
||||
|
||||
override fun mapToUpdateQuery(obj: SavedSearch) = UpdateQuery.builder()
|
||||
.table(TABLE)
|
||||
.where("$COL_ID = ?")
|
||||
.whereArgs(obj.id)
|
||||
.build()
|
||||
|
||||
override fun mapToContentValues(obj: SavedSearch) = contentValuesOf(
|
||||
COL_ID to obj.id,
|
||||
COL_SOURCE to obj.source,
|
||||
COL_NAME to obj.name,
|
||||
COL_QUERY to obj.query,
|
||||
COL_FILTERS_JSON to obj.filtersJson
|
||||
)
|
||||
}
|
||||
|
||||
class SavedSearchGetResolver : DefaultGetResolver<SavedSearch>() {
|
||||
|
||||
override fun mapFromCursor(cursor: Cursor): SavedSearch = SavedSearch(
|
||||
id = cursor.getLong(cursor.getColumnIndexOrThrow(COL_ID)),
|
||||
source = cursor.getLong(cursor.getColumnIndexOrThrow(COL_SOURCE)),
|
||||
name = cursor.getString(cursor.getColumnIndexOrThrow(COL_NAME)),
|
||||
query = cursor.getStringOrNull(cursor.getColumnIndexOrThrow(COL_QUERY)),
|
||||
filtersJson = cursor.getStringOrNull(cursor.getColumnIndexOrThrow(COL_FILTERS_JSON))
|
||||
)
|
||||
}
|
||||
|
||||
class SavedSearchDeleteResolver : DefaultDeleteResolver<SavedSearch>() {
|
||||
|
||||
override fun mapToDeleteQuery(obj: SavedSearch) = DeleteQuery.builder()
|
||||
.table(TABLE)
|
||||
.where("$COL_ID = ?")
|
||||
.whereArgs(obj.id)
|
||||
.build()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package exh.savedsearches.models
|
||||
|
||||
data class SavedSearch(
|
||||
// Tag identifier, unique
|
||||
var id: Long?,
|
||||
|
||||
// The source the saved search is for
|
||||
var source: Long,
|
||||
|
||||
// If false the manga will not grab chapter updates
|
||||
var name: String,
|
||||
|
||||
// The query if there is any
|
||||
var query: String?,
|
||||
|
||||
// The filter list
|
||||
var filtersJson: String?,
|
||||
)
|
||||
@@ -0,0 +1,82 @@
|
||||
package exh.savedsearches.queries
|
||||
|
||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
||||
import exh.savedsearches.models.SavedSearch
|
||||
import exh.savedsearches.tables.SavedSearchTable
|
||||
|
||||
interface SavedSearchQueries : DbProvider {
|
||||
fun getSavedSearches(source: Long) = db.get()
|
||||
.listOfObjects(SavedSearch::class.java)
|
||||
.withQuery(
|
||||
Query.builder()
|
||||
.table(SavedSearchTable.TABLE)
|
||||
.where("${SavedSearchTable.COL_SOURCE} = ?")
|
||||
.whereArgs(source)
|
||||
.build()
|
||||
)
|
||||
.prepare()
|
||||
|
||||
fun deleteSavedSearches(source: Long) = db.delete()
|
||||
.byQuery(
|
||||
DeleteQuery.builder()
|
||||
.table(SavedSearchTable.TABLE)
|
||||
.where("${SavedSearchTable.COL_SOURCE} = ?")
|
||||
.whereArgs(source)
|
||||
.build()
|
||||
)
|
||||
.prepare()
|
||||
|
||||
fun getSavedSearches() = db.get()
|
||||
.listOfObjects(SavedSearch::class.java)
|
||||
.withQuery(
|
||||
Query.builder()
|
||||
.table(SavedSearchTable.TABLE)
|
||||
.orderBy(SavedSearchTable.COL_ID)
|
||||
.build()
|
||||
)
|
||||
.prepare()
|
||||
|
||||
fun getSavedSearch(id: Long) = db.get()
|
||||
.`object`(SavedSearch::class.java)
|
||||
.withQuery(
|
||||
Query.builder()
|
||||
.table(SavedSearchTable.TABLE)
|
||||
.where("${SavedSearchTable.COL_ID} = ?")
|
||||
.whereArgs(id)
|
||||
.build()
|
||||
)
|
||||
.prepare()
|
||||
|
||||
fun insertSavedSearch(savedSearch: SavedSearch) = db.put().`object`(savedSearch).prepare()
|
||||
|
||||
fun insertSavedSearches(savedSearches: List<SavedSearch>) = db.put().objects(savedSearches).prepare()
|
||||
|
||||
fun deleteSavedSearch(savedSearch: SavedSearch) = db.delete().`object`(savedSearch).prepare()
|
||||
|
||||
fun deleteSavedSearch(id: Long) = db.delete()
|
||||
.byQuery(
|
||||
DeleteQuery.builder()
|
||||
.table(SavedSearchTable.TABLE)
|
||||
.where("${SavedSearchTable.COL_ID} = ?")
|
||||
.whereArgs(id)
|
||||
.build()
|
||||
).prepare()
|
||||
|
||||
fun deleteAllSavedSearches() = db.delete().byQuery(
|
||||
DeleteQuery.builder()
|
||||
.table(SavedSearchTable.TABLE)
|
||||
.build()
|
||||
)
|
||||
.prepare()
|
||||
|
||||
/*fun setMangasForMergedManga(mergedMangaId: Long, mergedMangases: List<SavedSearch>) {
|
||||
db.inTransaction {
|
||||
deleteSavedSearches(mergedMangaId).executeAsBlocking()
|
||||
mergedMangases.chunked(100) { chunk ->
|
||||
insertSavedSearches(chunk).executeAsBlocking()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package exh.savedsearches.tables
|
||||
|
||||
object SavedSearchTable {
|
||||
|
||||
const val TABLE = "saved_search"
|
||||
|
||||
const val COL_ID = "_id"
|
||||
|
||||
const val COL_SOURCE = "source"
|
||||
|
||||
const val COL_NAME = "name"
|
||||
|
||||
const val COL_QUERY = "query"
|
||||
|
||||
const val COL_FILTERS_JSON = "filters_json"
|
||||
|
||||
val createTableQuery: String
|
||||
get() =
|
||||
"""CREATE TABLE $TABLE(
|
||||
$COL_ID INTEGER NOT NULL PRIMARY KEY,
|
||||
$COL_SOURCE INTEGER NOT NULL,
|
||||
$COL_NAME TEXT NOT NULL,
|
||||
$COL_QUERY TEXT,
|
||||
$COL_FILTERS_JSON TEXT
|
||||
)"""
|
||||
}
|
||||
Reference in New Issue
Block a user