Add support to update strategy on global update (#7902)

* Add support to update strategy.

* Add JavaDoc and bump the LIB_VERSION_MAX constant.

* Fix a word typo.

* Store update strategy enum as integer in the DB.

(cherry picked from commit ba533f30ce70bdcfbfaaae3e7758dbe38fe6fb1b)

# Conflicts:
#	app/src/main/java/eu/kanade/data/DatabaseAdapter.kt
#	app/src/main/java/eu/kanade/data/manga/MangaMapper.kt
#	app/src/main/java/eu/kanade/data/manga/MangaRepositoryImpl.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/data/backup/models/BackupManga.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/database/models/MangaImpl.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt
#	app/src/main/sqldelight/data/mangas.sq
#	app/src/main/sqldelight/migrations/20.sqm
This commit is contained in:
Alessandro Jean 2022-09-25 11:12:36 -03:00 committed by Jobobby04
parent 3da5a2a20d
commit 2d2ee54c99
20 changed files with 103 additions and 15 deletions

View File

@ -1,6 +1,7 @@
package eu.kanade.data package eu.kanade.data
import com.squareup.sqldelight.ColumnAdapter import com.squareup.sqldelight.ColumnAdapter
import eu.kanade.tachiyomi.source.model.UpdateStrategy
import java.util.Date import java.util.Date
val dateAdapter = object : ColumnAdapter<Date, Long> { val dateAdapter = object : ColumnAdapter<Date, Long> {
@ -19,6 +20,15 @@ val listOfStringsAdapter = object : ColumnAdapter<List<String>, String> {
override fun encode(value: List<String>) = value.joinToString(separator = 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 --> // SY -->
private const val listOfStringsAndSeparator = " & " private const val listOfStringsAndSeparator = " & "
val listOfStringsAndAdapter = object : ColumnAdapter<List<String>, String> { val listOfStringsAndAdapter = object : ColumnAdapter<List<String>, String> {

View File

@ -4,6 +4,7 @@ import com.squareup.sqldelight.Query
import com.squareup.sqldelight.db.SqlCursor import com.squareup.sqldelight.db.SqlCursor
import com.squareup.sqldelight.db.SqlDriver import com.squareup.sqldelight.db.SqlDriver
import com.squareup.sqldelight.internal.copyOnWriteList import com.squareup.sqldelight.internal.copyOnWriteList
import eu.kanade.data.updateStrategyAdapter
import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.data.database.models.LibraryManga
import exh.source.MERGED_SOURCE_ID import exh.source.MERGED_SOURCE_ID
@ -27,9 +28,10 @@ private val mapper = { cursor: SqlCursor ->
cover_last_modified = cursor.getLong(16)!! cover_last_modified = cursor.getLong(16)!!
date_added = cursor.getLong(17)!! date_added = cursor.getLong(17)!!
filtered_scanlators = cursor.getString(18) filtered_scanlators = cursor.getString(18)
unreadCount = cursor.getLong(19)!!.toInt() update_strategy = updateStrategyAdapter.decode(cursor.getLong(19)!!)
readCount = cursor.getLong(20)!!.toInt() unreadCount = cursor.getLong(20)!!.toInt()
category = cursor.getLong(21)!!.toInt() readCount = cursor.getLong(21)!!.toInt()
category = cursor.getLong(22)!!.toInt()
} }
} }

View File

@ -4,9 +4,10 @@ import eu.kanade.data.listOfStringsAndAdapter
import eu.kanade.domain.chapter.model.Chapter import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.Manga
import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.source.model.UpdateStrategy
val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, List<String>?) -> Manga = 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, viewer, chapterFlags, coverLastModified, dateAdded, filteredScanlators -> { id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, _, initialized, viewer, chapterFlags, coverLastModified, dateAdded, filteredScanlators, updateStrategy ->
Manga( Manga(
id = id, id = id,
source = source, source = source,
@ -26,6 +27,7 @@ val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?,
ogStatus = status, ogStatus = status,
// SY <-- // SY <--
thumbnailUrl = thumbnailUrl, thumbnailUrl = thumbnailUrl,
updateStrategy = updateStrategy,
initialized = initialized, initialized = initialized,
// SY --> // SY -->
filteredScanlators = filteredScanlators, filteredScanlators = filteredScanlators,
@ -33,8 +35,8 @@ val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?,
) )
} }
val mangaChapterMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, List<String>?, Long, Long, String, String, String?, Boolean, Boolean, Long, Float, Long, Long, Long) -> Pair<Manga, Chapter> = val mangaChapterMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, List<String>?, Long, Long, String, String, String?, Boolean, Boolean, Long, Float, Long, Long, Long) -> Pair<Manga, Chapter> =
{ _id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, next_update, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, filteredScanlators, chapterId, mangaId, chapterUrl, name, scanlator, read, bookmark, lastPageRead, chapterNumber, sourceOrder, dateFetch, dateUpload -> { _id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, next_update, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, updateStrategy, filteredScanlators, chapterId, mangaId, chapterUrl, name, scanlator, read, bookmark, lastPageRead, chapterNumber, sourceOrder, dateFetch, dateUpload ->
Manga( Manga(
id = _id, id = _id,
source = source, source = source,
@ -54,6 +56,7 @@ val mangaChapterMapper: (Long, Long, String, String?, String?, String?, List<Str
ogStatus = status, ogStatus = status,
// SY <-- // SY <--
thumbnailUrl = thumbnailUrl, thumbnailUrl = thumbnailUrl,
updateStrategy = updateStrategy,
initialized = initialized, initialized = initialized,
// SY --> // SY -->
filteredScanlators = filteredScanlators, filteredScanlators = filteredScanlators,
@ -74,8 +77,8 @@ val mangaChapterMapper: (Long, Long, String, String?, String?, String?, List<Str
) )
} }
val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, List<String>?, Long, Long, Long) -> LibraryManga = val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, List<String>?, Long, Long, Long) -> LibraryManga =
{ _id, source, url, artist, author, description, genre, title, status, thumbnail_url, favorite, last_update, next_update, initialized, viewer, chapter_flags, cover_last_modified, date_added, filtered_scanlators, unread_count, read_count, category -> { _id, source, url, artist, author, description, genre, title, status, thumbnail_url, favorite, last_update, next_update, initialized, viewer, chapter_flags, cover_last_modified, date_added, update_strategy, filtered_scanlators, unread_count, read_count, category ->
LibraryManga().apply { LibraryManga().apply {
this.id = _id this.id = _id
this.source = source this.source = source
@ -89,6 +92,7 @@ val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?,
this.thumbnail_url = thumbnail_url this.thumbnail_url = thumbnail_url
this.favorite = favorite this.favorite = favorite
this.last_update = last_update ?: 0 this.last_update = last_update ?: 0
this.update_strategy = update_strategy
this.initialized = initialized this.initialized = initialized
this.viewer_flags = viewer.toInt() this.viewer_flags = viewer.toInt()
this.chapter_flags = chapter_flags.toInt() this.chapter_flags = chapter_flags.toInt()

View File

@ -4,6 +4,7 @@ import eu.kanade.data.AndroidDatabaseHandler
import eu.kanade.data.DatabaseHandler import eu.kanade.data.DatabaseHandler
import eu.kanade.data.listOfStringsAdapter import eu.kanade.data.listOfStringsAdapter
import eu.kanade.data.listOfStringsAndAdapter import eu.kanade.data.listOfStringsAndAdapter
import eu.kanade.data.updateStrategyAdapter
import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.Manga
import eu.kanade.domain.manga.model.MangaUpdate import eu.kanade.domain.manga.model.MangaUpdate
import eu.kanade.domain.manga.repository.MangaRepository import eu.kanade.domain.manga.repository.MangaRepository
@ -96,6 +97,10 @@ class MangaRepositoryImpl(
chapterFlags = manga.chapterFlags, chapterFlags = manga.chapterFlags,
coverLastModified = manga.coverLastModified, coverLastModified = manga.coverLastModified,
dateAdded = manga.dateAdded, dateAdded = manga.dateAdded,
// SY -->
filteredScanlators = manga.filteredScanlators,
// SY <--
updateStrategy = manga.updateStrategy,
) )
mangasQueries.selectLastInsertedRowId() mangasQueries.selectLastInsertedRowId()
} }
@ -141,8 +146,11 @@ class MangaRepositoryImpl(
chapterFlags = value.chapterFlags, chapterFlags = value.chapterFlags,
coverLastModified = value.coverLastModified, coverLastModified = value.coverLastModified,
dateAdded = value.dateAdded, dateAdded = value.dateAdded,
// SY -->
filteredScanlators = value.filteredScanlators?.let(listOfStringsAndAdapter::encode), filteredScanlators = value.filteredScanlators?.let(listOfStringsAndAdapter::encode),
// SY <--
mangaId = value.id, mangaId = value.id,
updateStrategy = value.updateStrategy?.let(updateStrategyAdapter::encode),
) )
} }
} }

View File

@ -78,6 +78,7 @@ class UpdateManga(
genre = remoteManga.getGenres(), genre = remoteManga.getGenres(),
thumbnailUrl = thumbnailUrl, thumbnailUrl = thumbnailUrl,
status = remoteManga.status.toLong(), status = remoteManga.status.toLong(),
updateStrategy = remoteManga.update_strategy,
initialized = true, initialized = true,
), ),
) )

View File

@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.library.CustomMangaManager import eu.kanade.tachiyomi.data.library.CustomMangaManager
import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.UpdateStrategy
import eu.kanade.tachiyomi.widget.ExtendedNavigationView import eu.kanade.tachiyomi.widget.ExtendedNavigationView
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -34,6 +35,7 @@ data class Manga(
val ogStatus: Long, val ogStatus: Long,
// SY <-- // SY <--
val thumbnailUrl: String?, val thumbnailUrl: String?,
val updateStrategy: UpdateStrategy,
val initialized: Boolean, val initialized: Boolean,
// SY --> // SY -->
val filteredScanlators: List<String>?, val filteredScanlators: List<String>?,
@ -183,6 +185,7 @@ data class Manga(
ogStatus = 0L, ogStatus = 0L,
// SY <-- // SY <--
thumbnailUrl = null, thumbnailUrl = null,
updateStrategy = UpdateStrategy.ALWAYS_UPDATE,
initialized = false, initialized = false,
// SY --> // SY -->
filteredScanlators = null, filteredScanlators = null,
@ -229,6 +232,7 @@ fun Manga.toDbManga(): DbManga = MangaImpl().also {
it.status = ogStatus.toInt() it.status = ogStatus.toInt()
// SY <-- // SY <--
it.thumbnail_url = thumbnailUrl it.thumbnail_url = thumbnailUrl
it.update_strategy = updateStrategy
it.initialized = initialized it.initialized = initialized
// SY --> // SY -->
it.filtered_scanlators = filteredScanlators?.let(listOfStringsAndAdapter::encode) it.filtered_scanlators = filteredScanlators?.let(listOfStringsAndAdapter::encode)
@ -255,6 +259,7 @@ fun Manga.toMangaUpdate(): MangaUpdate {
status = ogStatus, status = ogStatus,
// SY <-- // SY <--
thumbnailUrl = thumbnailUrl, thumbnailUrl = thumbnailUrl,
updateStrategy = updateStrategy,
initialized = initialized, initialized = initialized,
// SY --> // SY -->
filteredScanlators = filteredScanlators, filteredScanlators = filteredScanlators,

View File

@ -1,5 +1,7 @@
package eu.kanade.domain.manga.model package eu.kanade.domain.manga.model
import eu.kanade.tachiyomi.source.model.UpdateStrategy
data class MangaUpdate( data class MangaUpdate(
val id: Long, val id: Long,
val source: Long? = null, val source: Long? = null,
@ -17,6 +19,7 @@ data class MangaUpdate(
val genre: List<String>? = null, val genre: List<String>? = null,
val status: Long? = null, val status: Long? = null,
val thumbnailUrl: String? = null, val thumbnailUrl: String? = null,
val updateStrategy: UpdateStrategy? = null,
val initialized: Boolean? = null, val initialized: Boolean? = null,
// SY --> // SY -->
val filteredScanlators: List<String>? = null, val filteredScanlators: List<String>? = null,

View File

@ -16,6 +16,7 @@ import eu.kanade.data.dateAdapter
import eu.kanade.data.listOfLongsAdapter import eu.kanade.data.listOfLongsAdapter
import eu.kanade.data.listOfStringsAdapter import eu.kanade.data.listOfStringsAdapter
import eu.kanade.data.listOfStringsAndAdapter import eu.kanade.data.listOfStringsAndAdapter
import eu.kanade.data.updateStrategyAdapter
import eu.kanade.domain.UnsortedPreferences import eu.kanade.domain.UnsortedPreferences
import eu.kanade.domain.backup.service.BackupPreferences import eu.kanade.domain.backup.service.BackupPreferences
import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.base.BasePreferences
@ -95,6 +96,7 @@ class AppModule(val app: Application) : InjektModule {
), ),
mangasAdapter = Mangas.Adapter( mangasAdapter = Mangas.Adapter(
genreAdapter = listOfStringsAdapter, genreAdapter = listOfStringsAdapter,
update_strategyAdapter = updateStrategyAdapter,
// SY --> // SY -->
filtered_scanlatorsAdapter = listOfStringsAndAdapter, filtered_scanlatorsAdapter = listOfStringsAndAdapter,
// SY <-- // SY <--

View File

@ -8,7 +8,9 @@ import data.Manga_sync
import data.Mangas import data.Mangas
import eu.kanade.data.DatabaseHandler import eu.kanade.data.DatabaseHandler
import eu.kanade.data.exh.mergedMangaReferenceMapper import eu.kanade.data.exh.mergedMangaReferenceMapper
import eu.kanade.data.listOfStringsAndAdapter
import eu.kanade.data.manga.mangaMapper import eu.kanade.data.manga.mangaMapper
import eu.kanade.data.updateStrategyAdapter
import eu.kanade.domain.backup.service.BackupPreferences import eu.kanade.domain.backup.service.BackupPreferences
import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.domain.category.interactor.GetCategories
import eu.kanade.domain.category.model.Category import eu.kanade.domain.category.model.Category
@ -564,6 +566,10 @@ class BackupManager(
chapterFlags = manga.chapter_flags.toLong(), chapterFlags = manga.chapter_flags.toLong(),
coverLastModified = manga.cover_last_modified, coverLastModified = manga.cover_last_modified,
dateAdded = manga.date_added, dateAdded = manga.date_added,
// SY -->
filteredScanlators = manga.filtered_scanlators?.nullIfBlank()?.let(listOfStringsAndAdapter::decode),
// SY <--
updateStrategy = manga.update_strategy,
) )
mangasQueries.selectLastInsertedRowId() mangasQueries.selectLastInsertedRowId()
} }
@ -588,10 +594,11 @@ class BackupManager(
chapterFlags = manga.chapter_flags.toLong(), chapterFlags = manga.chapter_flags.toLong(),
coverLastModified = manga.cover_last_modified, coverLastModified = manga.cover_last_modified,
dateAdded = manga.date_added, dateAdded = manga.date_added,
mangaId = manga.id!!,
// SY --> // SY -->
filteredScanlators = manga.filtered_scanlators, filteredScanlators = manga.filtered_scanlators,
// SY <-- // SY <--
mangaId = manga.id!!,
updateStrategy = manga.update_strategy.let(updateStrategyAdapter::encode),
) )
} }
return manga.id!! return manga.id!!

View File

@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.data.database.models.ChapterImpl
import eu.kanade.tachiyomi.data.database.models.MangaImpl import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.database.models.TrackImpl import eu.kanade.tachiyomi.data.database.models.TrackImpl
import eu.kanade.tachiyomi.data.library.CustomMangaManager import eu.kanade.tachiyomi.data.library.CustomMangaManager
import eu.kanade.tachiyomi.source.model.UpdateStrategy
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
@ -40,6 +41,7 @@ data class BackupManga(
@ProtoNumber(102) var brokenHistory: List<BrokenBackupHistory> = emptyList(), @ProtoNumber(102) var brokenHistory: List<BrokenBackupHistory> = emptyList(),
@ProtoNumber(103) var viewer_flags: Int? = null, @ProtoNumber(103) var viewer_flags: Int? = null,
@ProtoNumber(104) var history: List<BackupHistory> = emptyList(), @ProtoNumber(104) var history: List<BackupHistory> = emptyList(),
@ProtoNumber(105) var updateStrategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE,
// SY specific values // SY specific values
@ProtoNumber(600) var mergedMangaReferences: List<BackupMergedMangaReference> = emptyList(), @ProtoNumber(600) var mergedMangaReferences: List<BackupMergedMangaReference> = emptyList(),
@ -72,6 +74,7 @@ data class BackupManga(
date_added = this@BackupManga.dateAdded date_added = this@BackupManga.dateAdded
viewer_flags = this@BackupManga.viewer_flags ?: this@BackupManga.viewer viewer_flags = this@BackupManga.viewer_flags ?: this@BackupManga.viewer
chapter_flags = this@BackupManga.chapterFlags chapter_flags = this@BackupManga.chapterFlags
update_strategy = this@BackupManga.updateStrategy
filtered_scanlators = this@BackupManga.filtered_scanlators filtered_scanlators = this@BackupManga.filtered_scanlators
} }
} }
@ -130,6 +133,7 @@ data class BackupManga(
viewer = (manga.viewerFlags.toInt() and ReadingModeType.MASK), viewer = (manga.viewerFlags.toInt() and ReadingModeType.MASK),
viewer_flags = manga.viewerFlags.toInt(), viewer_flags = manga.viewerFlags.toInt(),
chapterFlags = manga.chapterFlags.toInt(), chapterFlags = manga.chapterFlags.toInt(),
updateStrategy = manga.updateStrategy,
// SY --> // SY -->
filtered_scanlators = manga.filteredScanlators?.let(listOfStringsAndAdapter::encode), filtered_scanlators = manga.filteredScanlators?.let(listOfStringsAndAdapter::encode),
).also { backupManga -> ).also { backupManga ->

View File

@ -105,6 +105,7 @@ fun Manga.toDomainManga(): DomainManga? {
ogStatus = originalStatus.toLong(), ogStatus = originalStatus.toLong(),
// SY <-- // SY <--
thumbnailUrl = thumbnail_url, thumbnailUrl = thumbnail_url,
updateStrategy = update_strategy,
initialized = initialized, initialized = initialized,
// SY --> // SY -->
filteredScanlators = filtered_scanlators?.let(listOfStringsAndAdapter::decode)?.nullIfEmpty(), filteredScanlators = filtered_scanlators?.let(listOfStringsAndAdapter::decode)?.nullIfEmpty(),

View File

@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.database.models
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.library.CustomMangaManager import eu.kanade.tachiyomi.data.library.CustomMangaManager
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.UpdateStrategy
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -58,6 +59,8 @@ open class MangaImpl : Manga {
override var date_added: Long = 0 override var date_added: Long = 0
override var update_strategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE
override var initialized: Boolean = false override var initialized: Boolean = false
override var viewer_flags: Int = 0 override var viewer_flags: Int = 0

View File

@ -52,6 +52,7 @@ import eu.kanade.tachiyomi.data.track.TrackStatus
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.UnmeteredSource import eu.kanade.tachiyomi.source.UnmeteredSource
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.UpdateStrategy
import eu.kanade.tachiyomi.source.online.all.MergedSource import eu.kanade.tachiyomi.source.online.all.MergedSource
import eu.kanade.tachiyomi.ui.manga.track.TrackItem import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.lang.withIOContext
@ -435,6 +436,9 @@ class LibraryUpdateService(
MANGA_NON_READ in restrictions && mangaWithNotif.totalChapters > 0 && !mangaWithNotif.hasStarted -> MANGA_NON_READ in restrictions && mangaWithNotif.totalChapters > 0 && !mangaWithNotif.hasStarted ->
skippedUpdates.add(mangaWithNotif to getString(R.string.skipped_reason_not_started)) skippedUpdates.add(mangaWithNotif to getString(R.string.skipped_reason_not_started))
mangaWithNotif.update_strategy != UpdateStrategy.ALWAYS_UPDATE ->
skippedUpdates.add(mangaWithNotif to getString(R.string.skipped_reason_not_always_update))
else -> { else -> {
// Convert to the manga that contains new chapters // Convert to the manga that contains new chapters
mangaWithNotif.toDomainManga()?.let { domainManga -> mangaWithNotif.toDomainManga()?.let { domainManga ->

View File

@ -38,7 +38,7 @@ internal object ExtensionLoader {
private const val METADATA_HAS_README = "tachiyomi.extension.hasReadme" private const val METADATA_HAS_README = "tachiyomi.extension.hasReadme"
private const val METADATA_HAS_CHANGELOG = "tachiyomi.extension.hasChangelog" private const val METADATA_HAS_CHANGELOG = "tachiyomi.extension.hasChangelog"
const val LIB_VERSION_MIN = 1.2 const val LIB_VERSION_MIN = 1.2
const val LIB_VERSION_MAX = 1.3 const val LIB_VERSION_MAX = 1.4
private const val PACKAGE_FLAGS = PackageManager.GET_CONFIGURATIONS or PackageManager.GET_SIGNATURES private const val PACKAGE_FLAGS = PackageManager.GET_CONFIGURATIONS or PackageManager.GET_SIGNATURES

View File

@ -1,3 +1,4 @@
import eu.kanade.tachiyomi.source.model.UpdateStrategy;
import java.lang.String; import java.lang.String;
import kotlin.collections.List; import kotlin.collections.List;
@ -20,7 +21,8 @@ CREATE TABLE mangas(
chapter_flags INTEGER NOT NULL, chapter_flags INTEGER NOT NULL,
cover_last_modified INTEGER AS Long NOT NULL, cover_last_modified INTEGER AS Long NOT NULL,
date_added INTEGER AS Long NOT NULL, date_added INTEGER AS Long NOT NULL,
filtered_scanlators TEXT AS List<String> filtered_scanlators TEXT AS List<String>,
update_strategy INTEGER AS UpdateStrategy NOT NULL DEFAULT 0
); );
CREATE INDEX library_favorite_index ON mangas(favorite) WHERE favorite = 1; CREATE INDEX library_favorite_index ON mangas(favorite) WHERE favorite = 1;
@ -151,8 +153,8 @@ WHERE favorite = 0 AND source IN :sourceIdsAND AND _id NOT IN (
); );
insert: insert:
INSERT INTO mangas(source,url,artist,author,description,genre,title,status,thumbnail_url,favorite,last_update,next_update,initialized,viewer,chapter_flags,cover_last_modified,date_added) INSERT INTO mangas(source,url,artist,author,description,genre,title,status,thumbnail_url,favorite,last_update,next_update,initialized,viewer,chapter_flags,cover_last_modified,date_added,filtered_scanlators,update_strategy)
VALUES (:source,:url,:artist,:author,:description,:genre,:title,:status,:thumbnailUrl,:favorite,:lastUpdate,:nextUpdate,:initialized,:viewerFlags,:chapterFlags,:coverLastModified,:dateAdded); VALUES (:source,:url,:artist,:author,:description,:genre,:title,:status,:thumbnailUrl,:favorite,:lastUpdate,:nextUpdate,:initialized,:viewerFlags,:chapterFlags,:coverLastModified,:dateAdded,:filteredScanlators,:updateStrategy);
update: update:
UPDATE mangas SET UPDATE mangas SET
@ -172,7 +174,8 @@ UPDATE mangas SET
chapter_flags = coalesce(:chapterFlags, chapter_flags), chapter_flags = coalesce(:chapterFlags, chapter_flags),
cover_last_modified = coalesce(:coverLastModified, cover_last_modified), cover_last_modified = coalesce(:coverLastModified, cover_last_modified),
date_added = coalesce(:dateAdded, date_added), date_added = coalesce(:dateAdded, date_added),
filtered_scanlators = coalesce(:filteredScanlators, filtered_scanlators) filtered_scanlators = coalesce(:filteredScanlators, filtered_scanlators),
update_strategy = coalesce(:updateStrategy, update_strategy)
WHERE _id = :mangaId; WHERE _id = :mangaId;
selectLastInsertedRowId: selectLastInsertedRowId:

View File

@ -0,0 +1 @@
ALTER TABLE mangas ADD COLUMN update_strategy INTEGER NOT NULL DEFAULT 0;

View File

@ -801,6 +801,7 @@
<string name="skipped_reason_completed">Skipped because series is complete</string> <string name="skipped_reason_completed">Skipped because series is complete</string>
<string name="skipped_reason_not_caught_up">Skipped because there are unread chapters</string> <string name="skipped_reason_not_caught_up">Skipped because there are unread chapters</string>
<string name="skipped_reason_not_started">Skipped because no chapters are read</string> <string name="skipped_reason_not_started">Skipped because no chapters are read</string>
<string name="skipped_reason_not_always_update">Skipped because series does not require updates</string>
<!-- File Picker Titles --> <!-- File Picker Titles -->
<string name="file_select_cover">Select cover image</string> <string name="file_select_cover">Select cover image</string>

View File

@ -20,6 +20,8 @@ interface SManga : Serializable {
var thumbnail_url: String? var thumbnail_url: String?
var update_strategy: UpdateStrategy
var initialized: Boolean var initialized: Boolean
fun getGenres(): List<String>? { fun getGenres(): List<String>? {
@ -65,6 +67,8 @@ interface SManga : Serializable {
status = other.status status = other.status
update_strategy = other.update_strategy
if (!initialized) { if (!initialized) {
initialized = other.initialized initialized = other.initialized
} }
@ -81,6 +85,7 @@ interface SManga : Serializable {
it.status = originalStatus it.status = originalStatus
// SY <-- // SY <--
it.thumbnail_url = thumbnail_url it.thumbnail_url = thumbnail_url
it.update_strategy = update_strategy
it.initialized = initialized it.initialized = initialized
} }

View File

@ -20,6 +20,8 @@ class SMangaImpl : SManga {
override var thumbnail_url: String? = null override var thumbnail_url: String? = null
override var update_strategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE
override var initialized: Boolean = false override var initialized: Boolean = false
// SY --> // SY -->

View File

@ -0,0 +1,22 @@
package eu.kanade.tachiyomi.source.model
/**
* Define the update strategy for a single [SManga].
* The strategy used will only take effect on the library update.
*
* @since extensions-lib 1.4
*/
enum class UpdateStrategy {
/**
* Series marked as always update will be included in the library
* update if they aren't excluded by additional restrictions.
*/
ALWAYS_UPDATE,
/**
* Series marked as only fetch once will be automatically skipped
* during library updates. Useful for cases where the series is previously
* known to be finished and have only a single chapter, for example.
*/
ONLY_FETCH_ONCE
}