Add option to backup non-library read entries (#1324)
Co-authored-by: jobobby04 <jobobby04@gmail.com> Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com> (cherry picked from commit de36357da834bff4110dbb56dd7ce7aad04d3c7d) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreator.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupOptions.kt # data/src/main/sqldelight/tachiyomi/data/mangas.sq
This commit is contained in:
parent
216bc2c57d
commit
943555c0af
@ -45,7 +45,7 @@ import tachiyomi.domain.manga.interactor.GetMergedManga
|
|||||||
import tachiyomi.domain.manga.interactor.GetMergedMangaById
|
import tachiyomi.domain.manga.interactor.GetMergedMangaById
|
||||||
import tachiyomi.domain.manga.interactor.GetMergedMangaForDownloading
|
import tachiyomi.domain.manga.interactor.GetMergedMangaForDownloading
|
||||||
import tachiyomi.domain.manga.interactor.GetMergedReferencesById
|
import tachiyomi.domain.manga.interactor.GetMergedReferencesById
|
||||||
import tachiyomi.domain.manga.interactor.GetReadMangaNotInLibrary
|
import tachiyomi.domain.manga.interactor.GetReadMangaNotInLibraryView
|
||||||
import tachiyomi.domain.manga.interactor.GetSearchMetadata
|
import tachiyomi.domain.manga.interactor.GetSearchMetadata
|
||||||
import tachiyomi.domain.manga.interactor.GetSearchTags
|
import tachiyomi.domain.manga.interactor.GetSearchTags
|
||||||
import tachiyomi.domain.manga.interactor.GetSearchTitles
|
import tachiyomi.domain.manga.interactor.GetSearchTitles
|
||||||
@ -101,7 +101,7 @@ class SYDomainModule : InjektModule {
|
|||||||
addFactory { GetPagePreviews(get(), get()) }
|
addFactory { GetPagePreviews(get(), get()) }
|
||||||
addFactory { SearchEngine() }
|
addFactory { SearchEngine() }
|
||||||
addFactory { IsTrackUnfollowed() }
|
addFactory { IsTrackUnfollowed() }
|
||||||
addFactory { GetReadMangaNotInLibrary(get()) }
|
addFactory { GetReadMangaNotInLibraryView(get()) }
|
||||||
|
|
||||||
// Required for [MetadataSource]
|
// Required for [MetadataSource]
|
||||||
addFactory<MetadataSource.GetMangaId> { GetManga(get()) }
|
addFactory<MetadataSource.GetMangaId> { GetManga(get()) }
|
||||||
|
@ -32,6 +32,7 @@ import tachiyomi.domain.backup.service.BackupPreferences
|
|||||||
import tachiyomi.domain.manga.interactor.GetFavorites
|
import tachiyomi.domain.manga.interactor.GetFavorites
|
||||||
import tachiyomi.domain.manga.interactor.GetMergedManga
|
import tachiyomi.domain.manga.interactor.GetMergedManga
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
|
import tachiyomi.domain.manga.repository.MangaRepository
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
@ -48,6 +49,7 @@ class BackupCreator(
|
|||||||
private val parser: ProtoBuf = Injekt.get(),
|
private val parser: ProtoBuf = Injekt.get(),
|
||||||
private val getFavorites: GetFavorites = Injekt.get(),
|
private val getFavorites: GetFavorites = Injekt.get(),
|
||||||
private val backupPreferences: BackupPreferences = Injekt.get(),
|
private val backupPreferences: BackupPreferences = Injekt.get(),
|
||||||
|
private val mangaRepository: MangaRepository = Injekt.get(),
|
||||||
|
|
||||||
private val categoriesBackupCreator: CategoriesBackupCreator = CategoriesBackupCreator(),
|
private val categoriesBackupCreator: CategoriesBackupCreator = CategoriesBackupCreator(),
|
||||||
private val mangaBackupCreator: MangaBackupCreator = MangaBackupCreator(),
|
private val mangaBackupCreator: MangaBackupCreator = MangaBackupCreator(),
|
||||||
@ -85,15 +87,12 @@ class BackupCreator(
|
|||||||
throw IllegalStateException(context.stringResource(MR.strings.create_backup_file_error))
|
throw IllegalStateException(context.stringResource(MR.strings.create_backup_file_error))
|
||||||
}
|
}
|
||||||
|
|
||||||
val backupManga = backupMangas(
|
val nonFavoriteManga = if (options.readEntries) mangaRepository.getReadMangaNotInLibrary() else emptyList()
|
||||||
getFavorites.await() /* SY --> */ +
|
// SY -->
|
||||||
if (options.readEntries) {
|
val mergedManga = getMergedManga.await()
|
||||||
handler.awaitList { mangasQueries.getReadMangaNotInLibrary(MangaMapper::mapManga) }
|
// SY <--
|
||||||
} else {
|
val backupManga = backupMangas(getFavorites.await() + nonFavoriteManga /* SY --> */ + mergedManga /* SY <-- */, options)
|
||||||
emptyList()
|
|
||||||
} + getMergedManga.await(), // SY <--
|
|
||||||
options,
|
|
||||||
)
|
|
||||||
val backup = Backup(
|
val backup = Backup(
|
||||||
backupManga = backupManga,
|
backupManga = backupManga,
|
||||||
backupCategories = backupCategories(options),
|
backupCategories = backupCategories(options),
|
||||||
|
@ -11,13 +11,13 @@ data class BackupOptions(
|
|||||||
val chapters: Boolean = true,
|
val chapters: Boolean = true,
|
||||||
val tracking: Boolean = true,
|
val tracking: Boolean = true,
|
||||||
val history: Boolean = true,
|
val history: Boolean = true,
|
||||||
|
val readEntries: Boolean = true,
|
||||||
val appSettings: Boolean = true,
|
val appSettings: Boolean = true,
|
||||||
val extensionRepoSettings: Boolean = true,
|
val extensionRepoSettings: Boolean = true,
|
||||||
val sourceSettings: Boolean = true,
|
val sourceSettings: Boolean = true,
|
||||||
val privateSettings: Boolean = false,
|
val privateSettings: Boolean = false,
|
||||||
// SY -->
|
// SY -->
|
||||||
val customInfo: Boolean = true,
|
val customInfo: Boolean = true,
|
||||||
val readEntries: Boolean = true,
|
|
||||||
val savedSearches: Boolean = true,
|
val savedSearches: Boolean = true,
|
||||||
// SY <--
|
// SY <--
|
||||||
) {
|
) {
|
||||||
@ -28,13 +28,13 @@ data class BackupOptions(
|
|||||||
chapters,
|
chapters,
|
||||||
tracking,
|
tracking,
|
||||||
history,
|
history,
|
||||||
|
readEntries,
|
||||||
appSettings,
|
appSettings,
|
||||||
extensionRepoSettings,
|
extensionRepoSettings,
|
||||||
sourceSettings,
|
sourceSettings,
|
||||||
privateSettings,
|
privateSettings,
|
||||||
// SY -->
|
// SY -->
|
||||||
customInfo,
|
customInfo,
|
||||||
readEntries,
|
|
||||||
savedSearches,
|
savedSearches,
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
@ -72,6 +72,12 @@ data class BackupOptions(
|
|||||||
getter = BackupOptions::categories,
|
getter = BackupOptions::categories,
|
||||||
setter = { options, enabled -> options.copy(categories = enabled) },
|
setter = { options, enabled -> options.copy(categories = enabled) },
|
||||||
),
|
),
|
||||||
|
Entry(
|
||||||
|
label = MR.strings.non_library_settings,
|
||||||
|
getter = BackupOptions::readEntries,
|
||||||
|
setter = { options, enabled -> options.copy(readEntries = enabled) },
|
||||||
|
enabled = { it.libraryEntries },
|
||||||
|
),
|
||||||
// SY -->
|
// SY -->
|
||||||
Entry(
|
Entry(
|
||||||
label = SYMR.strings.custom_entry_info,
|
label = SYMR.strings.custom_entry_info,
|
||||||
@ -79,12 +85,6 @@ data class BackupOptions(
|
|||||||
setter = { options, enabled -> options.copy(customInfo = enabled) },
|
setter = { options, enabled -> options.copy(customInfo = enabled) },
|
||||||
enabled = { it.libraryEntries },
|
enabled = { it.libraryEntries },
|
||||||
),
|
),
|
||||||
Entry(
|
|
||||||
label = SYMR.strings.all_read_entries,
|
|
||||||
getter = BackupOptions::readEntries,
|
|
||||||
setter = { options, enabled -> options.copy(readEntries = enabled) },
|
|
||||||
enabled = { it.libraryEntries },
|
|
||||||
),
|
|
||||||
Entry(
|
Entry(
|
||||||
label = SYMR.strings.saved_searches,
|
label = SYMR.strings.saved_searches,
|
||||||
getter = BackupOptions::savedSearches,
|
getter = BackupOptions::savedSearches,
|
||||||
@ -123,13 +123,13 @@ data class BackupOptions(
|
|||||||
chapters = array[2],
|
chapters = array[2],
|
||||||
tracking = array[3],
|
tracking = array[3],
|
||||||
history = array[4],
|
history = array[4],
|
||||||
appSettings = array[5],
|
readEntries = array[5],
|
||||||
extensionRepoSettings = array[6],
|
appSettings = array[6],
|
||||||
sourceSettings = array[7],
|
extensionRepoSettings = array[7],
|
||||||
privateSettings = array[8],
|
sourceSettings = array[8],
|
||||||
|
privateSettings = array[9],
|
||||||
// SY -->
|
// SY -->
|
||||||
customInfo = array[9],
|
customInfo = array[10],
|
||||||
readEntries = array[10],
|
|
||||||
savedSearches = array[11],
|
savedSearches = array[11],
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
|
@ -24,7 +24,7 @@ import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_HAS_U
|
|||||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_COMPLETED
|
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_COMPLETED
|
||||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_READ
|
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_READ
|
||||||
import tachiyomi.domain.manga.interactor.GetLibraryManga
|
import tachiyomi.domain.manga.interactor.GetLibraryManga
|
||||||
import tachiyomi.domain.manga.interactor.GetReadMangaNotInLibrary
|
import tachiyomi.domain.manga.interactor.GetReadMangaNotInLibraryView
|
||||||
import tachiyomi.domain.track.interactor.GetTracks
|
import tachiyomi.domain.track.interactor.GetTracks
|
||||||
import tachiyomi.domain.track.model.Track
|
import tachiyomi.domain.track.model.Track
|
||||||
import tachiyomi.source.local.isLocal
|
import tachiyomi.source.local.isLocal
|
||||||
@ -39,7 +39,7 @@ class StatsScreenModel(
|
|||||||
private val preferences: LibraryPreferences = Injekt.get(),
|
private val preferences: LibraryPreferences = Injekt.get(),
|
||||||
private val trackerManager: TrackerManager = Injekt.get(),
|
private val trackerManager: TrackerManager = Injekt.get(),
|
||||||
// SY -->
|
// SY -->
|
||||||
private val getReadMangaNotInLibrary: GetReadMangaNotInLibrary = Injekt.get(),
|
private val getReadMangaNotInLibraryView: GetReadMangaNotInLibraryView = Injekt.get(),
|
||||||
// SY <--
|
// SY <--
|
||||||
) : StateScreenModel<StatsScreenState>(StatsScreenState.Loading) {
|
) : StateScreenModel<StatsScreenState>(StatsScreenState.Loading) {
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ class StatsScreenModel(
|
|||||||
_allRead.onEach { allRead ->
|
_allRead.onEach { allRead ->
|
||||||
mutableState.update { StatsScreenState.Loading }
|
mutableState.update { StatsScreenState.Loading }
|
||||||
val libraryManga = getLibraryManga.await() + if (allRead) {
|
val libraryManga = getLibraryManga.await() + if (allRead) {
|
||||||
getReadMangaNotInLibrary.await()
|
getReadMangaNotInLibraryView.await()
|
||||||
} else {
|
} else {
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,10 @@ class MangaRepositoryImpl(
|
|||||||
return handler.awaitList { mangasQueries.getFavorites(MangaMapper::mapManga) }
|
return handler.awaitList { mangasQueries.getFavorites(MangaMapper::mapManga) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getReadMangaNotInLibrary(): List<Manga> {
|
||||||
|
return handler.awaitList { mangasQueries.getReadMangaNotInLibrary(MangaMapper::mapManga) }
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun getLibraryManga(): List<LibraryManga> {
|
override suspend fun getLibraryManga(): List<LibraryManga> {
|
||||||
return handler.awaitListExecutable {
|
return handler.awaitListExecutable {
|
||||||
(handler as AndroidDatabaseHandler).getLibraryQuery()
|
(handler as AndroidDatabaseHandler).getLibraryQuery()
|
||||||
@ -198,7 +202,7 @@ class MangaRepositoryImpl(
|
|||||||
handler.await { mangasQueries.deleteById(mangaId) }
|
handler.await { mangasQueries.deleteById(mangaId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getReadMangaNotInLibrary(): List<LibraryManga> {
|
override suspend fun getReadMangaNotInLibraryView(): List<LibraryManga> {
|
||||||
return handler.awaitListExecutable {
|
return handler.awaitListExecutable {
|
||||||
(handler as AndroidDatabaseHandler).getLibraryQuery("M.favorite = 0 AND C.readCount != 0")
|
(handler as AndroidDatabaseHandler).getLibraryQuery("M.favorite = 0 AND C.readCount != 0")
|
||||||
}.map(MangaMapper::mapLibraryView)
|
}.map(MangaMapper::mapLibraryView)
|
||||||
|
@ -80,10 +80,12 @@ FROM mangas
|
|||||||
WHERE favorite = 1;
|
WHERE favorite = 1;
|
||||||
|
|
||||||
getReadMangaNotInLibrary:
|
getReadMangaNotInLibrary:
|
||||||
SELECT mangas.*
|
SELECT *
|
||||||
FROM mangas
|
FROM mangas
|
||||||
WHERE favorite = 0 AND _id IN(
|
WHERE favorite = 0 AND _id IN (
|
||||||
SELECT chapters.manga_id FROM chapters WHERE read = 1 OR last_page_read != 0
|
SELECT DISTINCT chapters.manga_id
|
||||||
|
FROM chapters
|
||||||
|
WHERE read = 1 OR last_page_read != 0
|
||||||
);
|
);
|
||||||
|
|
||||||
getAllManga:
|
getAllManga:
|
||||||
|
@ -3,11 +3,11 @@ package tachiyomi.domain.manga.interactor
|
|||||||
import tachiyomi.domain.library.model.LibraryManga
|
import tachiyomi.domain.library.model.LibraryManga
|
||||||
import tachiyomi.domain.manga.repository.MangaRepository
|
import tachiyomi.domain.manga.repository.MangaRepository
|
||||||
|
|
||||||
class GetReadMangaNotInLibrary(
|
class GetReadMangaNotInLibraryView(
|
||||||
private val mangaRepository: MangaRepository,
|
private val mangaRepository: MangaRepository,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun await(): List<LibraryManga> {
|
suspend fun await(): List<LibraryManga> {
|
||||||
return mangaRepository.getReadMangaNotInLibrary()
|
return mangaRepository.getReadMangaNotInLibraryView()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,6 +17,8 @@ interface MangaRepository {
|
|||||||
|
|
||||||
suspend fun getFavorites(): List<Manga>
|
suspend fun getFavorites(): List<Manga>
|
||||||
|
|
||||||
|
suspend fun getReadMangaNotInLibrary(): List<Manga>
|
||||||
|
|
||||||
suspend fun getLibraryManga(): List<LibraryManga>
|
suspend fun getLibraryManga(): List<LibraryManga>
|
||||||
|
|
||||||
fun getLibraryMangaAsFlow(): Flow<List<LibraryManga>>
|
fun getLibraryMangaAsFlow(): Flow<List<LibraryManga>>
|
||||||
@ -44,6 +46,6 @@ interface MangaRepository {
|
|||||||
|
|
||||||
suspend fun deleteManga(mangaId: Long)
|
suspend fun deleteManga(mangaId: Long)
|
||||||
|
|
||||||
suspend fun getReadMangaNotInLibrary(): List<LibraryManga>
|
suspend fun getReadMangaNotInLibraryView(): List<LibraryManga>
|
||||||
// SY <--
|
// SY <--
|
||||||
}
|
}
|
||||||
|
@ -546,6 +546,7 @@
|
|||||||
<string name="source_settings">Source settings</string>
|
<string name="source_settings">Source settings</string>
|
||||||
<string name="extensionRepo_settings">Extension repos</string>
|
<string name="extensionRepo_settings">Extension repos</string>
|
||||||
<string name="private_settings">Include sensitive settings (e.g., tracker login tokens)</string>
|
<string name="private_settings">Include sensitive settings (e.g., tracker login tokens)</string>
|
||||||
|
<string name="non_library_settings">All read entries</string>
|
||||||
<string name="creating_backup">Creating backup</string>
|
<string name="creating_backup">Creating backup</string>
|
||||||
<string name="creating_backup_error">Backup failed</string>
|
<string name="creating_backup_error">Backup failed</string>
|
||||||
<string name="missing_storage_permission">Storage permissions not granted</string>
|
<string name="missing_storage_permission">Storage permissions not granted</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user