Add dynamic category library update upgrades

This commit is contained in:
Jobobby04 2020-08-18 18:55:00 -04:00
parent 20aa5b9aa1
commit 9e0e2db25d
9 changed files with 160 additions and 37 deletions

View File

@ -17,10 +17,12 @@ import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.library.LibraryUpdateRanker.rankingScheme
import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Companion.start
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.preference.PreferenceValues
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.library.LibraryGroup
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.prepUpdateCover
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
@ -28,6 +30,7 @@ import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.acquireWakeLock
import eu.kanade.tachiyomi.util.system.isServiceRunning
import exh.LIBRARY_UPDATE_EXCLUDED_SOURCES
import exh.util.nullIfBlank
import java.io.File
import java.util.concurrent.atomic.AtomicInteger
import rx.Observable
@ -87,6 +90,14 @@ class LibraryUpdateService(
*/
const val KEY_TARGET = "target"
// SY -->
/**
* Key for group to update.
*/
const val KEY_GROUP = "group"
const val KEY_GROUP_EXTRA = "group_extra"
// SY <--
/**
* Returns the status of the service.
*
@ -106,11 +117,15 @@ class LibraryUpdateService(
* @param target defines what should be updated.
* @return true if service newly started, false otherwise
*/
fun start(context: Context, category: Category? = null, target: Target = Target.CHAPTERS): Boolean {
fun start(context: Context, category: Category? = null, target: Target = Target.CHAPTERS /* SY --> */, group: Int = LibraryGroup.BY_DEFAULT, groupExtra: String? = null /* SY <-- */): Boolean {
if (!isRunning(context)) {
val intent = Intent(context, LibraryUpdateService::class.java).apply {
putExtra(KEY_TARGET, target)
category?.let { putExtra(KEY_CATEGORY, it.id) }
// SY -->
putExtra(KEY_GROUP, group)
groupExtra?.let { putExtra(KEY_GROUP_EXTRA, it) }
// SY <--
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
context.startService(intent)
@ -221,10 +236,15 @@ class LibraryUpdateService(
*/
fun getMangaToUpdate(intent: Intent, target: Target): List<LibraryManga> {
val categoryId = intent.getIntExtra(KEY_CATEGORY, -1)
// SY -->
val group = intent.getIntExtra(KEY_GROUP, LibraryGroup.BY_DEFAULT)
val groupLibraryUpdateType = preferences.groupLibraryUpdateType().get()
// SY <--
var listToUpdate = if (categoryId != -1) {
db.getLibraryMangas().executeAsBlocking().filter { it.category == categoryId }
} else {
// SY -->
} else if (group == LibraryGroup.BY_DEFAULT || groupLibraryUpdateType == PreferenceValues.GroupLibraryMode.GLOBAL || (groupLibraryUpdateType == PreferenceValues.GroupLibraryMode.ALL_BUT_UNGROUPED && group == LibraryGroup.UNGROUPED)) {
val categoriesToUpdate = preferences.libraryUpdateCategories().get().map(String::toInt)
if (categoriesToUpdate.isNotEmpty()) {
db.getLibraryMangas().executeAsBlocking()
@ -233,6 +253,43 @@ class LibraryUpdateService(
} else {
db.getLibraryMangas().executeAsBlocking().distinctBy { it.id }
}
} else {
val libraryManga = db.getLibraryMangas().executeAsBlocking().distinctBy { it.id }
when (group) {
LibraryGroup.BY_TRACK_STATUS -> {
val trackingExtra = intent.getStringExtra(KEY_GROUP_EXTRA)?.toIntOrNull() ?: -1
libraryManga.filter {
val loggedServices = trackManager.services.filter { it.isLogged }
val status: String = {
val tracks = db.getTracks(it).executeAsBlocking()
val track = tracks.find { track ->
loggedServices.any { it.id == track?.sync_id }
}
val service = loggedServices.find { it.id == track?.sync_id }
if (track != null && service != null) {
service.getStatus(track.status)
} else {
"not tracked"
}
}()
trackManager.mapTrackingOrder(status, applicationContext) == trackingExtra
}
}
LibraryGroup.BY_SOURCE -> {
val sourceExtra = intent.getStringExtra(KEY_GROUP_EXTRA).nullIfBlank()
val source = sourceManager.getCatalogueSources().find { it.name == sourceExtra }
if (source != null) libraryManga.filter { it.source == source.id } else emptyList()
}
LibraryGroup.BY_STATUS -> {
val statusExtra = intent.getStringExtra(KEY_GROUP_EXTRA)?.toIntOrNull() ?: -1
libraryManga.filter {
it.status == statusExtra
}
}
LibraryGroup.UNGROUPED -> libraryManga
else -> libraryManga
}
// SY <--
}
if (target == Target.CHAPTERS && preferences.updateOnlyNonCompleted()) {
listToUpdate = listToUpdate.filter { it.status != SManga.COMPLETED }

View File

@ -282,4 +282,6 @@ object PreferenceKeys {
const val groupLibraryBy = "group_library_by"
const val continuousVerticalTappingByPage = "continuous_vertical_tapping_by_page"
const val groupLibraryUpdateType = "group_library_update_type"
}

View File

@ -46,4 +46,12 @@ object PreferenceValues {
PARTIAL,
BLOCKED
}
// SY -->
enum class GroupLibraryMode {
GLOBAL,
ALL_BUT_UNGROUPED,
ALL
}
// SY <--
}

View File

@ -387,4 +387,6 @@ class PreferencesHelper(val context: Context) {
fun groupLibraryBy() = flowPrefs.getInt(Keys.groupLibraryBy, 0)
fun continuousVerticalTappingByPage() = flowPrefs.getBoolean(Keys.continuousVerticalTappingByPage, false)
fun groupLibraryUpdateType() = flowPrefs.getEnum(Keys.groupLibraryUpdateType, Values.GroupLibraryMode.GLOBAL)
}

View File

@ -15,6 +15,16 @@ class TrackManager(context: Context) {
const val KITSU = 3
const val SHIKIMORI = 4
const val BANGUMI = 5
// SY -->
const val READING = 1
const val REREADING = 2
const val PLANTOREAD = 3
const val PAUSED = 4
const val COMPLETED = 5
const val DROPPED = 6
const val OTHER = 7
// SY <--
}
val myAnimeList = MyAnimeList(context, MYANIMELIST)
@ -32,4 +42,20 @@ class TrackManager(context: Context) {
fun getService(id: Int) = services.find { it.id == id }
fun hasLoggedServices() = services.any { it.isLogged }
// SY -->
fun mapTrackingOrder(status: String, context: Context): Int {
with(context) {
return when (status) {
getString(eu.kanade.tachiyomi.R.string.reading), getString(eu.kanade.tachiyomi.R.string.currently_reading) -> READING
getString(eu.kanade.tachiyomi.R.string.repeating) -> REREADING
getString(eu.kanade.tachiyomi.R.string.plan_to_read), getString(eu.kanade.tachiyomi.R.string.want_to_read) -> PLANTOREAD
getString(eu.kanade.tachiyomi.R.string.on_hold), getString(eu.kanade.tachiyomi.R.string.paused) -> PAUSED
getString(eu.kanade.tachiyomi.R.string.completed) -> COMPLETED
getString(eu.kanade.tachiyomi.R.string.dropped) -> DROPPED
else -> OTHER
}
}
}
// SY <--
}

View File

@ -13,6 +13,7 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.preference.PreferenceValues
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.category.CategoryAdapter
@ -128,9 +129,33 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
swipe_refresh.setDistanceToTriggerSync((2 * 64 * resources.displayMetrics.density).toInt())
swipe_refresh.refreshes()
.onEach {
if (LibraryUpdateService.start(context, if (preferences.groupLibraryBy().get() == LibraryGroup.BY_DEFAULT) category else null)) {
context.toast(R.string.updating_category)
// SY -->
if (LibraryUpdateService.start(
context,
if (controller.presenter.groupType == LibraryGroup.BY_DEFAULT) category else null,
group = controller.presenter.groupType,
groupExtra = when (controller.presenter.groupType) {
LibraryGroup.BY_DEFAULT -> null
LibraryGroup.BY_SOURCE -> category.name
LibraryGroup.BY_STATUS, LibraryGroup.BY_TRACK_STATUS -> category.id.toString()
else -> null
}
)
) {
context.toast(
when {
controller.presenter.groupType == LibraryGroup.BY_DEFAULT ||
(preferences.groupLibraryUpdateType().get() == PreferenceValues.GroupLibraryMode.ALL) -> R.string.updating_category
(
controller.presenter.groupType == LibraryGroup.UNGROUPED &&
preferences.groupLibraryUpdateType().get() == PreferenceValues.GroupLibraryMode.ALL_BUT_UNGROUPED
) ||
preferences.groupLibraryUpdateType().get() == PreferenceValues.GroupLibraryMode.GLOBAL -> R.string.updating_library
else -> R.string.updating_category
}
)
}
// SY <--
// It can be a very long operation, so we disable swipe refresh and show a toast.
swipe_refresh.isRefreshing = false

View File

@ -59,7 +59,8 @@ class LibraryPresenter(
private val sourceManager: SourceManager = Injekt.get(),
private val downloadManager: DownloadManager = Injekt.get(),
// SY -->
private val customMangaManager: CustomMangaManager = Injekt.get()
private val customMangaManager: CustomMangaManager = Injekt.get(),
private val trackManager: TrackManager = Injekt.get()
// SY <--
) : BasePresenter<LibraryController>() {
@ -94,12 +95,12 @@ class LibraryPresenter(
// SY -->
val favoritesSync = FavoritesSyncHelper(context)
private var groupType = preferences.groupLibraryBy().get()
var groupType = preferences.groupLibraryBy().get()
private val libraryIsGrouped
get() = groupType != LibraryGroup.UNGROUPED
private val loggedServices by lazy { Injekt.get<TrackManager>().services.filter { it.isLogged } }
private val loggedServices by lazy { trackManager.services.filter { it.isLogged } }
/**
* Relay used to apply the UI update to the last emission of the library.
@ -571,8 +572,11 @@ class LibraryPresenter(
private fun getGroupedMangaItems(libraryManga: List<LibraryItem>): Pair<LibraryMap, List<Category>> {
val grouping: MutableList<Triple<String, Int, String>> = mutableListOf()
when (groupType) {
LibraryGroup.BY_STATUS -> libraryManga.distinctBy { it.manga.status }.map { it.manga.status }.forEachIndexed { index, status ->
grouping += Triple(status.toString(), index, mapStatus(status))
LibraryGroup.BY_STATUS -> {
grouping += Triple(SManga.ONGOING.toString(), SManga.ONGOING, context.getString(R.string.ongoing))
grouping += Triple(SManga.LICENSED.toString(), SManga.LICENSED, context.getString(R.string.licensed))
grouping += Triple(SManga.COMPLETED.toString(), SManga.COMPLETED, context.getString(R.string.completed))
grouping += Triple(SManga.UNKNOWN.toString(), SManga.UNKNOWN, context.getString(R.string.unknown))
}
LibraryGroup.BY_SOURCE -> libraryManga.distinctBy { it.manga.source }.map { it.manga.source }.forEachIndexed { index, sourceLong ->
grouping += Triple(sourceLong.toString(), index, sourceManager.getOrStub(sourceLong).name)
@ -604,7 +608,7 @@ class LibraryPresenter(
"not tracked"
}
}()
val group = grouping.find { it.first == mapTrackingOrder(status) }
val group = grouping.find { it.first == trackManager.mapTrackingOrder(status, context).toString() }
if (group != null) {
map[group.second]?.plusAssign(libraryItem) ?: map.put(group.second, mutableListOf(libraryItem))
} else {
@ -621,7 +625,7 @@ class LibraryPresenter(
}
}
else -> {
val group = grouping.find { it.first == libraryItem.manga.status.toString() }
val group = grouping.find { it.second == libraryItem.manga.status }
if (group != null) {
map[group.second]?.plusAssign(libraryItem) ?: map.put(group.second, mutableListOf(libraryItem))
} else {
@ -635,7 +639,7 @@ class LibraryPresenter(
val categories = (
when (groupType) {
LibraryGroup.BY_SOURCE -> grouping.sortedBy { it.third.toLowerCase() }
LibraryGroup.BY_TRACK_STATUS -> grouping.filter { it.second in map.keys }
LibraryGroup.BY_TRACK_STATUS, LibraryGroup.BY_STATUS -> grouping.filter { it.second in map.keys }
else -> grouping
}
).map {
@ -646,30 +650,5 @@ class LibraryPresenter(
return map to categories
}
private fun mapTrackingOrder(status: String): String {
with(context) {
return when (status) {
getString(R.string.reading), getString(R.string.currently_reading) -> "1"
getString(R.string.repeating) -> "2"
getString(R.string.plan_to_read), getString(R.string.want_to_read) -> "3"
getString(R.string.on_hold), getString(R.string.paused) -> "4"
getString(R.string.completed) -> "5"
getString(R.string.dropped) -> "6"
else -> "7"
}
}
}
private fun mapStatus(status: Int): String {
return context.getString(
when (status) {
SManga.LICENSED -> R.string.licensed
SManga.ONGOING -> R.string.ongoing
SManga.COMPLETED -> R.string.completed
else -> R.string.unknown
}
)
}
// SY <--
}

View File

@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.PreferenceValues
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.ui.base.controller.DialogController
@ -21,6 +22,7 @@ import eu.kanade.tachiyomi.ui.library.LibrarySettingsSheet
import eu.kanade.tachiyomi.util.preference.defaultValue
import eu.kanade.tachiyomi.util.preference.entriesRes
import eu.kanade.tachiyomi.util.preference.intListPreference
import eu.kanade.tachiyomi.util.preference.listPreference
import eu.kanade.tachiyomi.util.preference.multiSelectListPreference
import eu.kanade.tachiyomi.util.preference.onChange
import eu.kanade.tachiyomi.util.preference.onClick
@ -194,6 +196,24 @@ class SettingsLibraryController : SettingsController() {
}
.launchIn(scope)
}
// SY -->
listPreference {
key = Keys.groupLibraryUpdateType
titleRes = R.string.library_group_updates
entriesRes = arrayOf(
R.string.library_group_updates_global,
R.string.library_group_updates_all_but_ungrouped,
R.string.library_group_updates_all
)
entryValues = arrayOf(
PreferenceValues.GroupLibraryMode.GLOBAL.name,
PreferenceValues.GroupLibraryMode.ALL_BUT_UNGROUPED.name,
PreferenceValues.GroupLibraryMode.ALL.name
)
defaultValue = PreferenceValues.GroupLibraryMode.GLOBAL.name
summary = "%s"
}
// SY <--
intListPreference {
key = Keys.libraryUpdatePrioritization
titleRes = R.string.pref_library_update_prioritization

View File

@ -152,6 +152,10 @@
<string name="pref_skip_pre_migration_summary">Use last saved pre-migration preferences and sources to mass migrate</string>
<string name="library_settings_sheet">Library settings sheet</string>
<string name="library_settings_sheet_summary">More library display settings</string>
<string name="library_group_updates">Library dynamic category updates</string>
<string name="library_group_updates_global">Always launch global updates</string>
<string name="library_group_updates_all_but_ungrouped">Launch global updates only for ungrouped, category updates for others</string>
<string name="library_group_updates_all">Launch category updates all the time</string>
<!-- Reader Settings -->
<string name="download_threads">Download threads</string>