Migrate saved search and feed saved search to SQLDelight
This commit is contained in:
parent
4a115785eb
commit
26b30adf4a
13
app/src/main/java/eu/kanade/data/exh/FeedSavedSearch.kt
Normal file
13
app/src/main/java/eu/kanade/data/exh/FeedSavedSearch.kt
Normal file
@ -0,0 +1,13 @@
|
||||
package eu.kanade.data.exh
|
||||
|
||||
import exh.savedsearches.models.FeedSavedSearch
|
||||
|
||||
val feedSavedSearchMapper: (Long, Long, Long?, Boolean) -> FeedSavedSearch =
|
||||
{ id, source, savedSearch, global ->
|
||||
FeedSavedSearch(
|
||||
id = id,
|
||||
source = source,
|
||||
savedSearch = savedSearch,
|
||||
global = global
|
||||
)
|
||||
}
|
14
app/src/main/java/eu/kanade/data/exh/SavedSearch.kt
Normal file
14
app/src/main/java/eu/kanade/data/exh/SavedSearch.kt
Normal file
@ -0,0 +1,14 @@
|
||||
package eu.kanade.data.exh
|
||||
|
||||
import exh.savedsearches.models.SavedSearch
|
||||
|
||||
val savedSearchMapper: (Long, Long, String, String?, String?) -> SavedSearch =
|
||||
{ id, source, name, query, filtersJson ->
|
||||
SavedSearch(
|
||||
id = id,
|
||||
source = source,
|
||||
name = name,
|
||||
query = query,
|
||||
filtersJson = filtersJson
|
||||
)
|
||||
}
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.data.backup
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
@ -20,6 +21,7 @@ import uy.kohesive.injekt.injectLazy
|
||||
abstract class AbstractBackupManager(protected val context: Context) {
|
||||
|
||||
internal val databaseHelper: DatabaseHelper by injectLazy()
|
||||
internal val databaseHandler: DatabaseHandler by injectLazy()
|
||||
internal val sourceManager: SourceManager by injectLazy()
|
||||
internal val trackManager: TrackManager by injectLazy()
|
||||
protected val preferences: PreferencesHelper by injectLazy()
|
||||
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.backup.full
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.data.exh.savedSearchMapper
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.backup.AbstractBackupManager
|
||||
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY
|
||||
@ -39,11 +40,11 @@ import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||
import exh.metadata.metadata.base.insertFlatMetadataAsync
|
||||
import exh.savedsearches.models.SavedSearch
|
||||
import exh.source.MERGED_SOURCE_ID
|
||||
import exh.source.getMainSource
|
||||
import exh.util.executeOnIO
|
||||
import exh.util.nullIfBlank
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.serialization.protobuf.ProtoBuf
|
||||
import logcat.LogPriority
|
||||
import okio.buffer
|
||||
@ -167,7 +168,8 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
||||
* @return list of [BackupSavedSearch] to be backed up
|
||||
*/
|
||||
private fun backupSavedSearches(): List<BackupSavedSearch> {
|
||||
return databaseHelper.getSavedSearches().executeAsBlocking().map {
|
||||
return runBlocking {
|
||||
databaseHandler.awaitList { saved_searchQueries.selectAll(savedSearchMapper) }.map {
|
||||
BackupSavedSearch(
|
||||
it.name,
|
||||
it.query.orEmpty(),
|
||||
@ -176,6 +178,7 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
// SY <--
|
||||
|
||||
/**
|
||||
@ -431,25 +434,24 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
||||
}
|
||||
|
||||
// SY -->
|
||||
internal fun restoreSavedSearches(backupSavedSearches: List<BackupSavedSearch>) {
|
||||
val currentSavedSearches = databaseHelper.getSavedSearches()
|
||||
.executeAsBlocking()
|
||||
internal suspend fun restoreSavedSearches(backupSavedSearches: List<BackupSavedSearch>) {
|
||||
val currentSavedSearches = databaseHandler.awaitList {
|
||||
saved_searchQueries.selectAll(savedSearchMapper)
|
||||
}
|
||||
|
||||
val newSavedSearches = backupSavedSearches.filter { backupSavedSearch ->
|
||||
databaseHandler.await(true) {
|
||||
backupSavedSearches.filter { backupSavedSearch ->
|
||||
currentSavedSearches.none { it.name == backupSavedSearch.name && it.source == backupSavedSearch.source }
|
||||
}.map {
|
||||
SavedSearch(
|
||||
id = null,
|
||||
it.source,
|
||||
it.name,
|
||||
it.query.nullIfBlank(),
|
||||
filtersJson = it.filterList.nullIfBlank()
|
||||
}.forEach {
|
||||
saved_searchQueries.insertSavedSearch(
|
||||
_id = null,
|
||||
source = it.source,
|
||||
name = it.name,
|
||||
query = it.query.nullIfBlank(),
|
||||
filters_json = it.filterList.nullIfBlank()
|
||||
?.takeUnless { it == "[]" },
|
||||
)
|
||||
}.ifEmpty { null }
|
||||
|
||||
if (newSavedSearches != null) {
|
||||
databaseHelper.insertSavedSearches(newSavedSearches)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier) : AbstractBa
|
||||
}
|
||||
|
||||
// SY -->
|
||||
private fun restoreSavedSearches(backupSavedSearches: List<BackupSavedSearch>) {
|
||||
private suspend fun restoreSavedSearches(backupSavedSearches: List<BackupSavedSearch>) {
|
||||
backupManager.restoreSavedSearches(backupSavedSearches)
|
||||
|
||||
restoreProgress += 1
|
||||
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.data.backup.legacy
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import eu.kanade.data.exh.savedSearchMapper
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.backup.AbstractBackupManager
|
||||
import eu.kanade.tachiyomi.data.backup.legacy.models.Backup.Companion.CURRENT_VERSION
|
||||
@ -289,12 +290,15 @@ class LegacyBackupManager(context: Context, version: Int = CURRENT_VERSION) : Ab
|
||||
}
|
||||
|
||||
// SY -->
|
||||
internal fun restoreSavedSearches(jsonSavedSearches: String) {
|
||||
internal suspend fun restoreSavedSearches(jsonSavedSearches: String) {
|
||||
val backupSavedSearches = jsonSavedSearches.split("***").toSet()
|
||||
|
||||
val currentSavedSearches = databaseHelper.getSavedSearches().executeAsBlocking()
|
||||
val currentSavedSearches = databaseHandler.awaitList {
|
||||
saved_searchQueries.selectAll(savedSearchMapper)
|
||||
}
|
||||
|
||||
val newSavedSearches = backupSavedSearches.mapNotNull {
|
||||
databaseHandler.await(true) {
|
||||
backupSavedSearches.mapNotNull {
|
||||
runCatching {
|
||||
val content = parser.decodeFromString<JsonObject>(it.substringAfter(':'))
|
||||
SavedSearch(
|
||||
@ -307,10 +311,16 @@ class LegacyBackupManager(context: Context, version: Int = CURRENT_VERSION) : Ab
|
||||
}.getOrNull()
|
||||
}.filter { backupSavedSearch ->
|
||||
currentSavedSearches.none { it.name == backupSavedSearch.name && it.source == backupSavedSearch.source }
|
||||
}.ifEmpty { null }
|
||||
|
||||
if (newSavedSearches != null) {
|
||||
databaseHelper.insertSavedSearches(newSavedSearches)
|
||||
}.forEach {
|
||||
saved_searchQueries.insertSavedSearch(
|
||||
_id = null,
|
||||
source = it.source,
|
||||
name = it.name,
|
||||
query = it.query.nullIfBlank(),
|
||||
filters_json = it.filtersJson.nullIfBlank()
|
||||
?.takeUnless { it == "[]" },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract
|
||||
}
|
||||
|
||||
// SY -->
|
||||
private fun restoreSavedSearches(savedSearches: String) {
|
||||
private suspend fun restoreSavedSearches(savedSearches: String) {
|
||||
backupManager.restoreSavedSearches(savedSearches)
|
||||
|
||||
restoreProgress += 1
|
||||
|
@ -1,8 +1,6 @@
|
||||
package eu.kanade.tachiyomi.data.database.queries
|
||||
|
||||
import eu.kanade.tachiyomi.data.database.resolvers.SourceIdMangaCountGetResolver
|
||||
import exh.savedsearches.tables.FeedSavedSearchTable
|
||||
import exh.savedsearches.tables.SavedSearchTable
|
||||
import exh.source.MERGED_SOURCE_ID
|
||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable as Category
|
||||
import eu.kanade.tachiyomi.data.database.tables.ChapterTable as Chapter
|
||||
@ -76,32 +74,6 @@ fun getReadMangaNotInLibraryQuery() =
|
||||
)
|
||||
"""
|
||||
|
||||
/**
|
||||
* Query to get the global feed saved searches
|
||||
*/
|
||||
fun getGlobalFeedSavedSearchQuery() =
|
||||
"""
|
||||
SELECT ${SavedSearchTable.TABLE}.*
|
||||
FROM (
|
||||
SELECT ${FeedSavedSearchTable.COL_SAVED_SEARCH_ID} FROM ${FeedSavedSearchTable.TABLE} WHERE ${FeedSavedSearchTable.COL_GLOBAL} = 1
|
||||
) AS M
|
||||
JOIN ${SavedSearchTable.TABLE}
|
||||
ON ${SavedSearchTable.TABLE}.${SavedSearchTable.COL_ID} = M.${FeedSavedSearchTable.COL_SAVED_SEARCH_ID}
|
||||
"""
|
||||
|
||||
/**
|
||||
* Query to get the source feed saved searches
|
||||
*/
|
||||
fun getSourceFeedSavedSearchQuery() =
|
||||
"""
|
||||
SELECT ${SavedSearchTable.TABLE}.*
|
||||
FROM (
|
||||
SELECT ${FeedSavedSearchTable.COL_SAVED_SEARCH_ID} FROM ${FeedSavedSearchTable.TABLE} WHERE ${FeedSavedSearchTable.COL_GLOBAL} = 0 AND ${FeedSavedSearchTable.COL_SOURCE} = ?
|
||||
) AS M
|
||||
JOIN ${SavedSearchTable.TABLE}
|
||||
ON ${SavedSearchTable.TABLE}.${SavedSearchTable.COL_ID} = M.${FeedSavedSearchTable.COL_SAVED_SEARCH_ID}
|
||||
"""
|
||||
|
||||
/**
|
||||
* Query to get the manga from the library, with their categories, read and unread count.
|
||||
*/
|
||||
|
@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController
|
||||
import eu.kanade.tachiyomi.ui.browse.source.latest.LatestUpdatesController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import exh.savedsearches.models.FeedSavedSearch
|
||||
import exh.savedsearches.models.SavedSearch
|
||||
@ -66,9 +67,10 @@ open class FeedController :
|
||||
}
|
||||
|
||||
private fun addFeed() {
|
||||
viewScope.launchUI {
|
||||
if (presenter.hasTooManyFeeds()) {
|
||||
activity?.toast(R.string.too_many_in_feed)
|
||||
return
|
||||
return@launchUI
|
||||
}
|
||||
val items = presenter.getEnabledSources()
|
||||
val itemsStrings = items.map { it.toString() }
|
||||
@ -85,8 +87,10 @@ open class FeedController :
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun addFeedSearch(source: CatalogueSource) {
|
||||
viewScope.launchUI {
|
||||
val items = presenter.getSourceSavedSearches(source)
|
||||
val itemsStrings = listOf(activity!!.getString(R.string.latest)) + items.map { it.name }
|
||||
var selectedIndex = 0
|
||||
@ -102,6 +106,7 @@ open class FeedController :
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when manga in global search is clicked, opens manga.
|
||||
|
@ -1,6 +1,9 @@
|
||||
package eu.kanade.tachiyomi.ui.browse.feed
|
||||
|
||||
import android.os.Bundle
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.data.exh.feedSavedSearchMapper
|
||||
import eu.kanade.data.exh.savedSearchMapper
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
|
||||
@ -15,9 +18,12 @@ import eu.kanade.tachiyomi.source.model.toSManga
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.runAsObservable
|
||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import exh.savedsearches.models.FeedSavedSearch
|
||||
import exh.savedsearches.models.SavedSearch
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import logcat.LogPriority
|
||||
@ -35,11 +41,12 @@ import xyz.nulldev.ts.api.http.serializer.FilterSerializer
|
||||
* Function calls should be done from here. UI calls should be done from the controller.
|
||||
*
|
||||
* @param sourceManager manages the different sources.
|
||||
* @param db manages the database calls.
|
||||
* @param database manages the database calls.
|
||||
* @param preferences manages the preference calls.
|
||||
*/
|
||||
open class FeedPresenter(
|
||||
val sourceManager: SourceManager = Injekt.get(),
|
||||
val database: DatabaseHandler = Injekt.get(),
|
||||
val db: DatabaseHelper = Injekt.get(),
|
||||
val preferences: PreferencesHelper = Injekt.get(),
|
||||
) : BasePresenter<FeedController>() {
|
||||
@ -62,14 +69,11 @@ open class FeedPresenter(
|
||||
override fun onCreate(savedState: Bundle?) {
|
||||
super.onCreate(savedState)
|
||||
|
||||
db.getGlobalFeedSavedSearches()
|
||||
.asRxObservable()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnEach {
|
||||
database.subscribeToList { feed_saved_searchQueries.selectAllGlobal() }
|
||||
.onEach {
|
||||
getFeed()
|
||||
}
|
||||
.subscribe()
|
||||
.let(::add)
|
||||
.launchIn(presenterScope)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
@ -78,8 +82,10 @@ open class FeedPresenter(
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
fun hasTooManyFeeds(): Boolean {
|
||||
return db.getGlobalFeedSavedSearches().executeAsBlocking().size > 10
|
||||
suspend fun hasTooManyFeeds(): Boolean {
|
||||
return withIOContext {
|
||||
database.awaitList { feed_saved_searchQueries.selectAllGlobal() }.size > 10
|
||||
}
|
||||
}
|
||||
|
||||
fun getEnabledSources(): List<CatalogueSource> {
|
||||
@ -93,33 +99,38 @@ open class FeedPresenter(
|
||||
return list.sortedBy { it.id.toString() !in pinnedSources }
|
||||
}
|
||||
|
||||
fun getSourceSavedSearches(source: CatalogueSource): List<SavedSearch> {
|
||||
return db.getSavedSearches(source.id).executeAsBlocking()
|
||||
suspend fun getSourceSavedSearches(source: CatalogueSource): List<SavedSearch> {
|
||||
return withIOContext {
|
||||
database.awaitList { saved_searchQueries.selectBySource(source.id, savedSearchMapper) }
|
||||
}
|
||||
}
|
||||
|
||||
fun createFeed(source: CatalogueSource, savedSearch: SavedSearch?) {
|
||||
launchIO {
|
||||
db.insertFeedSavedSearch(
|
||||
FeedSavedSearch(
|
||||
id = null,
|
||||
database.await {
|
||||
feed_saved_searchQueries.insertFeedSavedSearch(
|
||||
_id = null,
|
||||
source = source.id,
|
||||
savedSearch = savedSearch?.id,
|
||||
saved_search = savedSearch?.id,
|
||||
global = true,
|
||||
),
|
||||
).executeAsBlocking()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteFeed(feed: FeedSavedSearch) {
|
||||
launchIO {
|
||||
db.deleteFeedSavedSearch(feed).executeAsBlocking()
|
||||
database.await {
|
||||
feed_saved_searchQueries.deleteById(feed.id ?: return@await)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSourcesToGetFeed(): List<Pair<FeedSavedSearch, SavedSearch?>> {
|
||||
val savedSearches = db.getGlobalSavedSearchesFeed().executeAsBlocking()
|
||||
.associateBy { it.id!! }
|
||||
return db.getGlobalFeedSavedSearches().executeAsBlocking()
|
||||
private suspend fun getSourcesToGetFeed(): List<Pair<FeedSavedSearch, SavedSearch?>> {
|
||||
val savedSearches = database.awaitList {
|
||||
feed_saved_searchQueries.selectGlobalFeedSavedSearch(savedSearchMapper)
|
||||
}.associateBy { it.id }
|
||||
return database.awaitList { feed_saved_searchQueries.selectAllGlobal(feedSavedSearchMapper) }
|
||||
.map { it to savedSearches[it.savedSearch] }
|
||||
}
|
||||
|
||||
@ -138,7 +149,7 @@ open class FeedPresenter(
|
||||
/**
|
||||
* Initiates get manga per feed.
|
||||
*/
|
||||
fun getFeed() {
|
||||
suspend fun getFeed() {
|
||||
// Create image fetch subscription
|
||||
initializeFetchImageSubscription()
|
||||
|
||||
|
@ -44,6 +44,7 @@ import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.more.MoreController
|
||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||
import eu.kanade.tachiyomi.util.preference.asImmediateFlow
|
||||
import eu.kanade.tachiyomi.util.system.connectivityManager
|
||||
import eu.kanade.tachiyomi.util.system.openInBrowser
|
||||
@ -201,7 +202,7 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
// SY -->
|
||||
this,
|
||||
presenter.source,
|
||||
presenter.loadSearches(),
|
||||
emptyList(),
|
||||
// SY <--
|
||||
onFilterClicked = {
|
||||
showProgressBar()
|
||||
@ -216,6 +217,7 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
},
|
||||
// EXH -->
|
||||
onSaveClicked = {
|
||||
viewScope.launchUI {
|
||||
filterSheet?.context?.let {
|
||||
val names = presenter.loadSearches().map { it.name }
|
||||
var searchName = ""
|
||||
@ -234,8 +236,10 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
.setNegativeButton(R.string.action_cancel, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
},
|
||||
onSavedSearchClicked = cb@{ idOfSearch ->
|
||||
onSavedSearchClicked = { idOfSearch ->
|
||||
viewScope.launchUI {
|
||||
val search = presenter.loadSearch(idOfSearch)
|
||||
|
||||
if (search == null) {
|
||||
@ -245,12 +249,12 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
.setMessage(R.string.save_search_failed_to_load_message)
|
||||
.show()
|
||||
}
|
||||
return@cb
|
||||
return@launchUI
|
||||
}
|
||||
|
||||
if (search.filterList == null) {
|
||||
activity?.toast(R.string.save_search_invalid)
|
||||
return@cb
|
||||
return@launchUI
|
||||
}
|
||||
|
||||
presenter.sourceFilters = FilterList(search.filterList)
|
||||
@ -262,8 +266,9 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
filterSheet?.dismiss()
|
||||
presenter.restartPager(search.query, if (allDefault) FilterList() else presenter.sourceFilters)
|
||||
activity?.invalidateOptionsMenu()
|
||||
}
|
||||
},
|
||||
onSavedSearchDeleteClicked = cb@{ idToDelete, name ->
|
||||
onSavedSearchDeleteClicked = { idToDelete, name ->
|
||||
filterSheet?.context?.let {
|
||||
MaterialAlertDialogBuilder(it)
|
||||
.setTitle(R.string.save_search_delete)
|
||||
@ -277,6 +282,9 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
},
|
||||
// EXH <--
|
||||
)
|
||||
launchUI {
|
||||
filterSheet?.setSavedSearches(presenter.loadSearches())
|
||||
}
|
||||
filterSheet?.setFilters(presenter.filterItems)
|
||||
|
||||
filterSheet?.setOnShowListener { actionFab?.hide() }
|
||||
|
@ -2,6 +2,8 @@ package eu.kanade.tachiyomi.ui.browse.source.browse
|
||||
|
||||
import android.os.Bundle
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.data.exh.savedSearchMapper
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Category
|
||||
@ -37,6 +39,7 @@ import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateSectionItem
|
||||
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
|
||||
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithTrackServiceTwoWay
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.removeCovers
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
@ -50,8 +53,10 @@ import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
@ -78,6 +83,7 @@ open class BrowseSourcePresenter(
|
||||
// SY <--
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val db: DatabaseHelper = Injekt.get(),
|
||||
private val database: DatabaseHandler = Injekt.get(),
|
||||
private val prefs: PreferencesHelper = Injekt.get(),
|
||||
private val coverCache: CoverCache = Injekt.get(),
|
||||
) : BasePresenter<BrowseSourceController>() {
|
||||
@ -140,7 +146,11 @@ open class BrowseSourcePresenter(
|
||||
val jsonFilters = filters
|
||||
if (savedSearchFilters != null) {
|
||||
runCatching {
|
||||
val savedSearch = db.getSavedSearch(savedSearchFilters).executeAsBlocking() ?: return@runCatching
|
||||
val savedSearch = runBlocking {
|
||||
database.awaitOneOrNull {
|
||||
saved_searchQueries.selectById(savedSearchFilters, savedSearchMapper)
|
||||
}
|
||||
} ?: return@runCatching
|
||||
query = savedSearch.query.orEmpty()
|
||||
val filtersJson = savedSearch.filtersJson
|
||||
?: return@runCatching
|
||||
@ -156,18 +166,14 @@ open class BrowseSourcePresenter(
|
||||
}
|
||||
}
|
||||
|
||||
db.getSavedSearches(source.id)
|
||||
.asRxObservable()
|
||||
.map {
|
||||
loadSearches(it)
|
||||
database.subscribeToList { saved_searchQueries.selectBySource(source.id, savedSearchMapper) }
|
||||
.map { loadSearches(it) }
|
||||
.onEach {
|
||||
withUIContext {
|
||||
view?.setSavedSearches(it)
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeLatestCache(
|
||||
{ controller, savedSearches ->
|
||||
controller.setSavedSearches(savedSearches)
|
||||
},
|
||||
)
|
||||
}
|
||||
.launchIn(presenterScope)
|
||||
// SY <--
|
||||
|
||||
if (savedState != null) {
|
||||
@ -485,28 +491,31 @@ open class BrowseSourcePresenter(
|
||||
fun saveSearch(name: String, query: String, filterList: FilterList) {
|
||||
launchIO {
|
||||
kotlin.runCatching {
|
||||
val savedSearch = SavedSearch(
|
||||
id = null,
|
||||
database.await {
|
||||
saved_searchQueries.insertSavedSearch(
|
||||
_id = null,
|
||||
source = source.id,
|
||||
name = name.trim(),
|
||||
query = query.nullIfBlank(),
|
||||
filtersJson = filterSerializer.serialize(filterList).ifEmpty { null }?.let { Json.encodeToString(it) },
|
||||
filters_json = filterSerializer.serialize(filterList).ifEmpty { null }?.let { Json.encodeToString(it) },
|
||||
)
|
||||
|
||||
db.insertSavedSearch(savedSearch).executeAsBlocking()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteSearch(searchId: Long) {
|
||||
launchIO {
|
||||
db.deleteSavedSearch(searchId).executeAsBlocking()
|
||||
database.await { saved_searchQueries.deleteById(searchId) }
|
||||
}
|
||||
}
|
||||
|
||||
fun loadSearch(searchId: Long): EXHSavedSearch? {
|
||||
val search = db.getSavedSearch(searchId).executeAsBlocking() ?: return null
|
||||
return EXHSavedSearch(
|
||||
suspend fun loadSearch(searchId: Long): EXHSavedSearch? {
|
||||
return withIOContext {
|
||||
val search = database.awaitOneOrNull {
|
||||
saved_searchQueries.selectById(searchId, savedSearchMapper)
|
||||
} ?: return@withIOContext null
|
||||
EXHSavedSearch(
|
||||
id = search.id!!,
|
||||
name = search.name,
|
||||
query = search.query.orEmpty(),
|
||||
@ -522,9 +531,12 @@ open class BrowseSourcePresenter(
|
||||
}.getOrNull(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun loadSearches(searches: List<SavedSearch> = db.getSavedSearches(source.id).executeAsBlocking()): List<EXHSavedSearch> {
|
||||
return searches.map {
|
||||
suspend fun loadSearches(searches: List<SavedSearch>? = null): List<EXHSavedSearch> {
|
||||
return withIOContext {
|
||||
(searches ?: (database.awaitList { saved_searchQueries.selectBySource(source.id, savedSearchMapper) }))
|
||||
.map {
|
||||
val filtersJson = it.filtersJson ?: return@map EXHSavedSearch(
|
||||
id = it.id!!,
|
||||
name = it.name,
|
||||
@ -564,5 +576,6 @@ open class BrowseSourcePresenter(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// EXH <--
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.SourceFilterSheet
|
||||
import eu.kanade.tachiyomi.ui.browse.source.latest.LatestUpdatesController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import exh.savedsearches.models.FeedSavedSearch
|
||||
import exh.savedsearches.models.SavedSearch
|
||||
@ -184,7 +186,7 @@ open class SourceFeedController :
|
||||
// SY -->
|
||||
this,
|
||||
presenter.source,
|
||||
presenter.loadSearches(),
|
||||
emptyList(),
|
||||
// SY <--
|
||||
onFilterClicked = {
|
||||
val allDefault = presenter.sourceFilters == presenter.source.getFilterList()
|
||||
@ -202,7 +204,8 @@ open class SourceFeedController :
|
||||
},
|
||||
onResetClicked = {},
|
||||
onSaveClicked = {},
|
||||
onSavedSearchClicked = cb@{ idOfSearch ->
|
||||
onSavedSearchClicked = { idOfSearch ->
|
||||
viewScope.launchUI {
|
||||
val search = presenter.loadSearch(idOfSearch)
|
||||
|
||||
if (search == null) {
|
||||
@ -212,12 +215,12 @@ open class SourceFeedController :
|
||||
.setMessage(R.string.save_search_failed_to_load_message)
|
||||
.show()
|
||||
}
|
||||
return@cb
|
||||
return@launchUI
|
||||
}
|
||||
|
||||
if (search.filterList == null) {
|
||||
activity?.toast(R.string.save_search_invalid)
|
||||
return@cb
|
||||
return@launchUI
|
||||
}
|
||||
|
||||
presenter.sourceFilters = FilterList(search.filterList)
|
||||
@ -231,12 +234,15 @@ open class SourceFeedController :
|
||||
savedSearch = search.id,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
onSavedSearchDeleteClicked = cb@{ idOfSearch, name ->
|
||||
onSavedSearchDeleteClicked = { idOfSearch, name ->
|
||||
viewScope.launchUI {
|
||||
if (presenter.hasTooManyFeeds()) {
|
||||
activity?.toast(R.string.too_many_in_feed)
|
||||
return@cb
|
||||
return@launchUI
|
||||
}
|
||||
withUIContext {
|
||||
MaterialAlertDialogBuilder(activity!!)
|
||||
.setTitle(R.string.feed)
|
||||
.setMessage(activity!!.getString(R.string.feed_add, name))
|
||||
@ -245,8 +251,13 @@ open class SourceFeedController :
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
launchUI {
|
||||
filterSheet?.setSavedSearches(presenter.loadSearches())
|
||||
}
|
||||
filterSheet?.setFilters(presenter.filterItems)
|
||||
|
||||
// TODO: [ExtendedFloatingActionButton] hide/show methods don't work properly
|
||||
|
@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.ui.browse.source.feed
|
||||
|
||||
import android.os.Bundle
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.data.exh.feedSavedSearchMapper
|
||||
import eu.kanade.data.exh.savedSearchMapper
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
|
||||
@ -16,11 +19,15 @@ import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter.Companion.toItems
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.runAsObservable
|
||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import exh.log.xLogE
|
||||
import exh.savedsearches.EXHSavedSearch
|
||||
import exh.savedsearches.models.FeedSavedSearch
|
||||
import exh.savedsearches.models.SavedSearch
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
@ -46,11 +53,12 @@ sealed class SourceFeed {
|
||||
* Function calls should be done from here. UI calls should be done from the controller.
|
||||
*
|
||||
* @param source the source.
|
||||
* @param db manages the database calls.
|
||||
* @param database manages the database calls.
|
||||
* @param preferences manages the preference calls.
|
||||
*/
|
||||
open class SourceFeedPresenter(
|
||||
val source: CatalogueSource,
|
||||
val database: DatabaseHandler = Injekt.get(),
|
||||
val db: DatabaseHelper = Injekt.get(),
|
||||
val preferences: PreferencesHelper = Injekt.get(),
|
||||
) : BasePresenter<SourceFeedController>() {
|
||||
@ -90,14 +98,11 @@ open class SourceFeedPresenter(
|
||||
|
||||
sourceFilters = source.getFilterList()
|
||||
|
||||
db.getSourceFeedSavedSearches(source.id)
|
||||
.asRxObservable()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnEach {
|
||||
database.subscribeToList { feed_saved_searchQueries.selectSourceFeedSavedSearch(source.id, savedSearchMapper) }
|
||||
.onEach {
|
||||
getFeed()
|
||||
}
|
||||
.subscribe()
|
||||
.let(::add)
|
||||
.launchIn(presenterScope)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
@ -106,35 +111,39 @@ open class SourceFeedPresenter(
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
fun hasTooManyFeeds(): Boolean {
|
||||
return db.getSourceFeedSavedSearches(source.id).executeAsBlocking().size > 10
|
||||
suspend fun hasTooManyFeeds(): Boolean {
|
||||
return withIOContext {
|
||||
database.awaitList {
|
||||
feed_saved_searchQueries.selectSourceFeedSavedSearch(source.id)
|
||||
}.size > 10
|
||||
}
|
||||
}
|
||||
|
||||
fun getSourceSavedSearches(): List<SavedSearch> {
|
||||
return db.getSavedSearches(source.id).executeAsBlocking()
|
||||
suspend fun getSourceSavedSearches(): List<SavedSearch> {
|
||||
return database.awaitList { saved_searchQueries.selectBySource(source.id, savedSearchMapper) }
|
||||
}
|
||||
|
||||
fun createFeed(savedSearchId: Long) {
|
||||
launchIO {
|
||||
db.insertFeedSavedSearch(
|
||||
FeedSavedSearch(
|
||||
id = null,
|
||||
database.await {
|
||||
feed_saved_searchQueries.insertFeedSavedSearch(
|
||||
_id = null,
|
||||
source = source.id,
|
||||
savedSearch = savedSearchId,
|
||||
global = false,
|
||||
),
|
||||
).executeAsBlocking()
|
||||
saved_search = savedSearchId,
|
||||
global = false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteFeed(feed: FeedSavedSearch) {
|
||||
launchIO {
|
||||
db.deleteFeedSavedSearch(feed).executeAsBlocking()
|
||||
database.await { feed_saved_searchQueries.deleteById(feed.id ?: return@await) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSourcesToGetFeed(): List<SourceFeed> {
|
||||
val savedSearches = db.getSourceSavedSearchesFeed(source.id).executeAsBlocking()
|
||||
private suspend fun getSourcesToGetFeed(): List<SourceFeed> {
|
||||
val savedSearches = database.awaitList { feed_saved_searchQueries.selectSourceFeedSavedSearch(source.id, savedSearchMapper) }
|
||||
.associateBy { it.id!! }
|
||||
|
||||
return listOfNotNull(
|
||||
@ -142,7 +151,7 @@ open class SourceFeedPresenter(
|
||||
SourceFeed.Latest
|
||||
} else null,
|
||||
SourceFeed.Browse,
|
||||
) + db.getSourceFeedSavedSearches(source.id).executeAsBlocking()
|
||||
) + database.awaitList { feed_saved_searchQueries.selectBySource(source.id, feedSavedSearchMapper) }
|
||||
.map { SourceFeed.SourceSavedSearch(it, savedSearches[it.savedSearch]!!) }
|
||||
}
|
||||
|
||||
@ -159,7 +168,7 @@ open class SourceFeedPresenter(
|
||||
/**
|
||||
* Initiates get manga per feed.
|
||||
*/
|
||||
fun getFeed() {
|
||||
suspend fun getFeed() {
|
||||
// Create image fetch subscription
|
||||
initializeFetchImageSubscription()
|
||||
|
||||
@ -300,9 +309,12 @@ open class SourceFeedPresenter(
|
||||
return localManga
|
||||
}
|
||||
|
||||
fun loadSearch(searchId: Long): EXHSavedSearch? {
|
||||
val search = db.getSavedSearch(searchId).executeAsBlocking() ?: return null
|
||||
return EXHSavedSearch(
|
||||
suspend fun loadSearch(searchId: Long): EXHSavedSearch? {
|
||||
return withIOContext {
|
||||
val search = database.awaitOneOrNull {
|
||||
saved_searchQueries.selectById(searchId, savedSearchMapper)
|
||||
} ?: return@withIOContext null
|
||||
EXHSavedSearch(
|
||||
id = search.id!!,
|
||||
name = search.name,
|
||||
query = search.query.orEmpty(),
|
||||
@ -318,9 +330,11 @@ open class SourceFeedPresenter(
|
||||
}.getOrNull(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun loadSearches(): List<EXHSavedSearch> {
|
||||
return db.getSavedSearches(source.id).executeAsBlocking().map {
|
||||
suspend fun loadSearches(): List<EXHSavedSearch> {
|
||||
return withIOContext {
|
||||
database.awaitList { saved_searchQueries.selectBySource(source.id, savedSearchMapper) }.map {
|
||||
val filtersJson = it.filtersJson ?: return@map EXHSavedSearch(
|
||||
id = it.id!!,
|
||||
name = it.name,
|
||||
@ -330,6 +344,7 @@ open class SourceFeedPresenter(
|
||||
val filters = try {
|
||||
Json.decodeFromString<JsonArray>(filtersJson)
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
null
|
||||
} ?: return@map EXHSavedSearch(
|
||||
id = it.id!!,
|
||||
@ -359,4 +374,5 @@ open class SourceFeedPresenter(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import androidx.preference.PreferenceManager
|
||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
||||
import com.pushtorefresh.storio.sqlite.queries.RawQuery
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
@ -40,8 +41,6 @@ import exh.eh.EHentaiUpdateWorker
|
||||
import exh.log.xLogE
|
||||
import exh.log.xLogW
|
||||
import exh.merged.sql.models.MergedMangaReference
|
||||
import exh.savedsearches.models.FeedSavedSearch
|
||||
import exh.savedsearches.models.SavedSearch
|
||||
import exh.source.BlacklistedSources
|
||||
import exh.source.EH_SOURCE_ID
|
||||
import exh.source.HBROWSE_SOURCE_ID
|
||||
@ -51,6 +50,7 @@ import exh.source.PERV_EDEN_IT_SOURCE_ID
|
||||
import exh.source.TSUMINO_SOURCE_ID
|
||||
import exh.util.nullIfBlank
|
||||
import exh.util.under
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromString
|
||||
@ -69,6 +69,7 @@ import java.net.URISyntaxException
|
||||
|
||||
object EXHMigrations {
|
||||
private val db: DatabaseHelper by injectLazy()
|
||||
private val database: DatabaseHandler by injectLazy()
|
||||
private val sourceManager: SourceManager by injectLazy()
|
||||
|
||||
/**
|
||||
@ -404,31 +405,31 @@ object EXHMigrations {
|
||||
BackupCreatorJob.setupTask(context)
|
||||
}
|
||||
if (oldVersion under 31) {
|
||||
val savedSearches = prefs.getStringSet("eh_saved_searches", emptySet())?.mapNotNull {
|
||||
runBlocking {
|
||||
database.await(true) {
|
||||
prefs.getStringSet("eh_saved_searches", emptySet())?.forEach {
|
||||
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),
|
||||
saved_searchQueries.insertSavedSearch(
|
||||
_id = null,
|
||||
source = it.substringBefore(':').toLongOrNull() ?: return@forEach,
|
||||
name = content["name"]!!.jsonPrimitive.content,
|
||||
query = content["query"]!!.jsonPrimitive.contentOrNull?.nullIfBlank(),
|
||||
filters_json = Json.encodeToString(content["filters"]!!.jsonArray)
|
||||
)
|
||||
}.getOrNull()
|
||||
}?.ifEmpty { null }
|
||||
if (savedSearches != null) {
|
||||
db.insertSavedSearches(savedSearches).executeAsBlocking()
|
||||
}
|
||||
val feed = prefs.getStringSet("latest_tab_sources", emptySet())?.map {
|
||||
FeedSavedSearch(
|
||||
id = null,
|
||||
}
|
||||
}
|
||||
database.await(true) {
|
||||
prefs.getStringSet("latest_tab_sources", emptySet())?.forEach {
|
||||
feed_saved_searchQueries.insertFeedSavedSearch(
|
||||
_id = null,
|
||||
source = it.toLong(),
|
||||
savedSearch = null,
|
||||
saved_search = null,
|
||||
global = true,
|
||||
)
|
||||
}?.ifEmpty { null }
|
||||
if (feed != null) {
|
||||
db.insertFeedSavedSearches(feed).executeAsBlocking()
|
||||
}
|
||||
}
|
||||
}
|
||||
prefs.edit(commit = true) {
|
||||
remove("eh_saved_searches")
|
||||
|
@ -3,6 +3,7 @@ package exh.debug
|
||||
import android.app.Application
|
||||
import androidx.work.WorkManager
|
||||
import com.pushtorefresh.storio.sqlite.queries.RawQuery
|
||||
import eu.kanade.data.DatabaseHandler
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
|
||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
||||
@ -34,6 +35,7 @@ import java.util.UUID
|
||||
object DebugFunctions {
|
||||
val app: Application by injectLazy()
|
||||
val db: DatabaseHelper by injectLazy()
|
||||
val database: DatabaseHandler by injectLazy()
|
||||
val prefs: PreferencesHelper by injectLazy()
|
||||
val sourceManager: SourceManager by injectLazy()
|
||||
|
||||
@ -164,7 +166,7 @@ object DebugFunctions {
|
||||
it.favorite && db.getSearchMetadataForManga(it.id!!).executeAsBlocking() == null
|
||||
}
|
||||
|
||||
fun clearSavedSearches() = db.deleteAllSavedSearches().executeAsBlocking()
|
||||
fun clearSavedSearches() = runBlocking { database.await { saved_searchQueries.deleteAll() } }
|
||||
|
||||
fun listAllSources() = sourceManager.getCatalogueSources().joinToString("\n") {
|
||||
"${it.id}: ${it.name} (${it.lang.uppercase()})"
|
||||
|
@ -1,86 +1,5 @@
|
||||
package exh.savedsearches.queries
|
||||
|
||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
|
||||
import com.pushtorefresh.storio.sqlite.queries.Query
|
||||
import com.pushtorefresh.storio.sqlite.queries.RawQuery
|
||||
import eu.kanade.tachiyomi.data.database.DbProvider
|
||||
import eu.kanade.tachiyomi.data.database.queries.getGlobalFeedSavedSearchQuery
|
||||
import eu.kanade.tachiyomi.data.database.queries.getSourceFeedSavedSearchQuery
|
||||
import exh.savedsearches.models.FeedSavedSearch
|
||||
import exh.savedsearches.models.SavedSearch
|
||||
import exh.savedsearches.tables.FeedSavedSearchTable
|
||||
|
||||
interface FeedSavedSearchQueries : DbProvider {
|
||||
fun getGlobalFeedSavedSearches() = db.get()
|
||||
.listOfObjects(FeedSavedSearch::class.java)
|
||||
.withQuery(
|
||||
Query.builder()
|
||||
.table(FeedSavedSearchTable.TABLE)
|
||||
.where("${FeedSavedSearchTable.COL_GLOBAL} = 1")
|
||||
.orderBy(FeedSavedSearchTable.COL_ID)
|
||||
.build(),
|
||||
)
|
||||
.prepare()
|
||||
|
||||
fun getSourceFeedSavedSearches(sourceId: Long) = db.get()
|
||||
.listOfObjects(FeedSavedSearch::class.java)
|
||||
.withQuery(
|
||||
Query.builder()
|
||||
.table(FeedSavedSearchTable.TABLE)
|
||||
.where("${FeedSavedSearchTable.COL_SOURCE} = ? AND ${FeedSavedSearchTable.COL_GLOBAL} = 0")
|
||||
.whereArgs(sourceId)
|
||||
.orderBy(FeedSavedSearchTable.COL_ID)
|
||||
.build(),
|
||||
)
|
||||
.prepare()
|
||||
|
||||
fun insertFeedSavedSearch(savedSearch: FeedSavedSearch) = db.put().`object`(savedSearch).prepare()
|
||||
|
||||
fun insertFeedSavedSearches(savedSearches: List<FeedSavedSearch>) = db.put().objects(savedSearches).prepare()
|
||||
|
||||
fun deleteFeedSavedSearch(savedSearch: FeedSavedSearch) = db.delete().`object`(savedSearch).prepare()
|
||||
|
||||
fun deleteFeedSavedSearch(id: Long) = db.delete()
|
||||
.byQuery(
|
||||
DeleteQuery.builder()
|
||||
.table(FeedSavedSearchTable.TABLE)
|
||||
.where("${FeedSavedSearchTable.COL_ID} = ?")
|
||||
.whereArgs(id)
|
||||
.build(),
|
||||
).prepare()
|
||||
|
||||
fun deleteAllFeedSavedSearches() = db.delete().byQuery(
|
||||
DeleteQuery.builder()
|
||||
.table(FeedSavedSearchTable.TABLE)
|
||||
.build(),
|
||||
)
|
||||
.prepare()
|
||||
|
||||
fun getGlobalSavedSearchesFeed() = db.get()
|
||||
.listOfObjects(SavedSearch::class.java)
|
||||
.withQuery(
|
||||
RawQuery.builder()
|
||||
.query(getGlobalFeedSavedSearchQuery())
|
||||
.build(),
|
||||
)
|
||||
.prepare()
|
||||
|
||||
fun getSourceSavedSearchesFeed(sourceId: Long) = db.get()
|
||||
.listOfObjects(SavedSearch::class.java)
|
||||
.withQuery(
|
||||
RawQuery.builder()
|
||||
.query(getSourceFeedSavedSearchQuery())
|
||||
.args(sourceId)
|
||||
.build(),
|
||||
)
|
||||
.prepare()
|
||||
|
||||
/*fun setMangasForMergedManga(mergedMangaId: Long, mergedMangases: List<SavedSearch>) {
|
||||
db.inTransaction {
|
||||
deleteSavedSearches(mergedMangaId).executeAsBlocking()
|
||||
mergedMangases.chunked(100) { chunk ->
|
||||
insertSavedSearches(chunk).executeAsBlocking()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
interface FeedSavedSearchQueries : DbProvider
|
||||
|
@ -1,93 +1,5 @@
|
||||
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 getSavedSearches(ids: List<Long>) = db.get()
|
||||
.listOfObjects(SavedSearch::class.java)
|
||||
.withQuery(
|
||||
Query.builder()
|
||||
.table(SavedSearchTable.TABLE)
|
||||
.where("${SavedSearchTable.COL_ID} IN (?)")
|
||||
.whereArgs(ids.joinToString())
|
||||
.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()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
interface SavedSearchQueries : DbProvider
|
||||
|
Loading…
x
Reference in New Issue
Block a user