feat: Add support for backing up and storing source's feeds along with saved searches
This commit is contained in:
parent
9d36c1ae15
commit
7c63f84f5f
7 changed files with 66 additions and 26 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package eu.kanade.tachiyomi.data.backup.create.creators
|
||||
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
||||
import eu.kanade.tachiyomi.data.backup.models.backupFeedMapper
|
||||
import eu.kanade.tachiyomi.data.backup.models.backupSavedSearchMapper
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
import uy.kohesive.injekt.Injekt
|
||||
|
|
@ -11,6 +12,23 @@ class SavedSearchBackupCreator(
|
|||
) {
|
||||
|
||||
suspend fun backupSavedSearches(): List<BackupSavedSearch> {
|
||||
return handler.awaitList { saved_searchQueries.selectAll(backupSavedSearchMapper) }
|
||||
// KMK -->
|
||||
// return handler.awaitList { saved_searchQueries.selectAll(backupSavedSearchMapper) }
|
||||
val savedSearches = handler.awaitList { saved_searchQueries.selectAll() }
|
||||
val feedSavedSearches =
|
||||
handler.awaitList { feed_saved_searchQueries.selectAllFeedHasSavedSearch() }
|
||||
|
||||
return savedSearches.map { savedSearch ->
|
||||
val feeds = feedSavedSearches.filter { it.saved_search == savedSearch._id }
|
||||
backupSavedSearchMapper(
|
||||
savedSearch._id,
|
||||
savedSearch.source,
|
||||
savedSearch.name,
|
||||
savedSearch.query,
|
||||
savedSearch.filters_json,
|
||||
feeds.map { it.backupFeedMapper() },
|
||||
)
|
||||
}
|
||||
// KMK <--
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.data.backup.models
|
|||
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.protobuf.ProtoNumber
|
||||
import tachiyomi.data.SelectAllFeedHasSavedSearch
|
||||
|
||||
@Serializable
|
||||
data class BackupFeed(
|
||||
|
|
@ -16,3 +17,5 @@ val backupFeedMapper =
|
|||
global = global,
|
||||
)
|
||||
}
|
||||
|
||||
fun SelectAllFeedHasSavedSearch.backupFeedMapper() = backupFeedMapper(_id, source, saved_search, global)
|
||||
|
|
|
|||
|
|
@ -12,14 +12,20 @@ data class BackupSavedSearch(
|
|||
@ProtoNumber(2) val query: String = "",
|
||||
@ProtoNumber(3) val filterList: String = "",
|
||||
@ProtoNumber(4) val source: Long = 0,
|
||||
// KMK -->
|
||||
@ProtoNumber(9) var backupFeeds: List<BackupFeed> = emptyList(),
|
||||
// KMK <--
|
||||
)
|
||||
|
||||
val backupSavedSearchMapper =
|
||||
{ _: Long, source: Long, name: String, query: String?, filtersJson: String? ->
|
||||
{ _: Long, source: Long, name: String, query: String?, filtersJson: String?, backupFeeds: List<BackupFeed> ->
|
||||
BackupSavedSearch(
|
||||
source = source,
|
||||
name = name,
|
||||
query = query.orEmpty(),
|
||||
filterList = filtersJson ?: "[]",
|
||||
// KMK -->
|
||||
backupFeeds = backupFeeds,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,18 +8,14 @@ import uy.kohesive.injekt.api.get
|
|||
class FeedRestorer(
|
||||
private val handler: DatabaseHandler = Injekt.get(),
|
||||
) {
|
||||
|
||||
/**
|
||||
* Restore global Popular/Latest feeds
|
||||
*/
|
||||
suspend fun restoreFeeds(backupFeeds: List<BackupFeed>) {
|
||||
suspend fun restoreFeeds(backupFeeds: List<BackupFeed>, savedSearchId: Long? = null) {
|
||||
if (backupFeeds.isEmpty()) return
|
||||
|
||||
val currentFeeds = handler.awaitList {
|
||||
feed_saved_searchQueries.selectAllGlobalNonSavedSearch()
|
||||
}
|
||||
handler.await(true) {
|
||||
val currentFeeds = handler.awaitList {
|
||||
feed_saved_searchQueries.selectAllGlobalNonSavedSearch()
|
||||
}
|
||||
|
||||
handler.await {
|
||||
backupFeeds.filter { backupFeed ->
|
||||
// Filter if source's global Popular/Latest feed already existed
|
||||
currentFeeds.none {
|
||||
|
|
@ -28,7 +24,7 @@ class FeedRestorer(
|
|||
}.forEach {
|
||||
feed_saved_searchQueries.insert(
|
||||
sourceId = it.source,
|
||||
savedSearch = null,
|
||||
savedSearch = savedSearchId,
|
||||
global = it.global,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,25 +8,39 @@ import uy.kohesive.injekt.api.get
|
|||
|
||||
class SavedSearchRestorer(
|
||||
private val handler: DatabaseHandler = Injekt.get(),
|
||||
// KMK -->
|
||||
private val feedRestorer: FeedRestorer = FeedRestorer(),
|
||||
// KMK <--
|
||||
) {
|
||||
suspend fun restoreSavedSearches(backupSavedSearches: List<BackupSavedSearch>) {
|
||||
if (backupSavedSearches.isEmpty()) return
|
||||
|
||||
val currentSavedSearches = handler.awaitList {
|
||||
saved_searchQueries.selectNamesAndSources()
|
||||
}
|
||||
// KMK -->
|
||||
handler.await(true) {
|
||||
// KMK <--
|
||||
val currentSavedSearches = handler.awaitList {
|
||||
saved_searchQueries.selectNamesAndSources()
|
||||
}
|
||||
|
||||
handler.await {
|
||||
backupSavedSearches.filter { backupSavedSearch ->
|
||||
currentSavedSearches.none { it.source == backupSavedSearch.source && it.name == backupSavedSearch.name }
|
||||
}.forEach {
|
||||
saved_searchQueries.insert(
|
||||
source = it.source,
|
||||
name = it.name,
|
||||
query = it.query.nullIfBlank(),
|
||||
filtersJson = it.filterList.nullIfBlank()
|
||||
?.takeUnless { it == "[]" },
|
||||
)
|
||||
}.forEach { backupSavedSearch ->
|
||||
// KMK -->
|
||||
val savedSearchId = handler.awaitOneExecutable(true) {
|
||||
// KMK <--
|
||||
saved_searchQueries.insert(
|
||||
source = backupSavedSearch.source,
|
||||
name = backupSavedSearch.name,
|
||||
query = backupSavedSearch.query.nullIfBlank(),
|
||||
filtersJson = backupSavedSearch.filterList.nullIfBlank()
|
||||
?.takeUnless { it == "[]" },
|
||||
)
|
||||
// KMK -->
|
||||
saved_searchQueries.selectLastInsertedRowId()
|
||||
}
|
||||
|
||||
feedRestorer.restoreFeeds(backupSavedSearch.backupFeeds, savedSearchId)
|
||||
// KMK <--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,4 +57,7 @@ selectLastInsertedRowId:
|
|||
SELECT last_insert_rowid();
|
||||
|
||||
selectAllGlobalNonSavedSearch:
|
||||
SELECT * FROM feed_saved_search WHERE global = 1 AND saved_search IS NULL;
|
||||
SELECT * FROM feed_saved_search WHERE global = 1 AND saved_search IS NULL;
|
||||
|
||||
selectAllFeedHasSavedSearch:
|
||||
SELECT * FROM feed_saved_search WHERE saved_search IS NOT NULL;
|
||||
|
|
@ -10,6 +10,6 @@ data class FeedSavedSearch(
|
|||
// If null then get latest/popular, if set get the saved search
|
||||
val savedSearch: Long?,
|
||||
|
||||
// If the feed is a global or source specific feed
|
||||
// If the feed is a global (FeedScreen) or source specific feed (SourceFeedScreen)
|
||||
val global: Boolean,
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue