diff --git a/app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt b/app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt index 2c58b0e605..b91525a6d8 100644 --- a/app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt @@ -74,6 +74,7 @@ private fun ColumnScope.FilterPage( ) { val filterDownloaded by screenModel.libraryPreferences.filterDownloaded().collectAsState() val downloadedOnly by screenModel.preferences.downloadedOnly().collectAsState() + HeadingItem(R.string.status) TriStateItem( label = stringResource(R.string.label_downloaded), state = if (downloadedOnly) { @@ -102,12 +103,37 @@ private fun ColumnScope.FilterPage( state = filterBookmarked, onClick = { screenModel.toggleFilter(LibraryPreferences::filterBookmarked) }, ) + val filterIntervalLate by screenModel.libraryPreferences.filterIntervalLate().collectAsState() + TriStateItem( + label = stringResource(R.string.action_filter_interval_late), + state = filterIntervalLate, + onClick = { screenModel.toggleFilter(LibraryPreferences::filterIntervalLate) }, + ) + val filterIntervalDropped by screenModel.libraryPreferences.filterIntervalDropped().collectAsState() + TriStateItem( + label = stringResource(R.string.action_filter_interval_dropped), + state = filterIntervalDropped, + onClick = { screenModel.toggleFilter(LibraryPreferences::filterIntervalDropped) }, + ) val filterCompleted by screenModel.libraryPreferences.filterCompleted().collectAsState() TriStateItem( label = stringResource(R.string.completed), state = filterCompleted, onClick = { screenModel.toggleFilter(LibraryPreferences::filterCompleted) }, ) + HeadingItem(R.string.intervals_header) + val filterIntervalCustom by screenModel.libraryPreferences.filterIntervalCustom().collectAsState() + TriStateItem( + label = stringResource(R.string.action_filter_interval_custom), + state = filterIntervalCustom, + onClick = { screenModel.toggleFilter(LibraryPreferences::filterIntervalCustom) }, + ) + val filterIntervalLong by screenModel.libraryPreferences.filterIntervalLong().collectAsState() + TriStateItem( + label = stringResource(R.string.action_filter_interval_long), + state = filterIntervalLong, + onClick = { screenModel.toggleFilter(LibraryPreferences::filterIntervalLong) }, + ) val trackers = remember { screenModel.trackers } when (trackers.size) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt index 72fa1cc6ca..1c664c7717 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt @@ -70,6 +70,8 @@ import tachiyomi.source.local.isLocal import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.util.Collections +import java.util.Date +import kotlin.math.absoluteValue /** * Typealias for the library manga, using the category as keys, and list of manga as values. @@ -181,6 +183,10 @@ class LibraryScreenModel( val filterUnread = prefs.filterUnread val filterStarted = prefs.filterStarted val filterBookmarked = prefs.filterBookmarked + val filterIntervalLong = prefs.filterIntervalLong + val filterIntervalLate = prefs.filterIntervalLate + val filterIntervalDropped = prefs.filterIntervalDropped + val filterIntervalCustom = prefs.filterIntervalCustom val filterCompleted = prefs.filterCompleted val isNotLoggedInAnyTrack = loggedInTrackers.isEmpty() @@ -189,6 +195,43 @@ class LibraryScreenModel( val includedTracks = loggedInTrackers.mapNotNull { if (it.value == TriState.ENABLED_IS) it.key else null } val trackFiltersIsIgnored = includedTracks.isEmpty() && excludedTracks.isEmpty() + val filterFnIntervalCustom: (LibraryItem) -> Boolean = { + applyFilter(filterIntervalCustom) { it.libraryManga.manga.fetchInterval < 0 } + } + + val filterFnIntervalLong: (LibraryItem) -> Boolean = { + applyFilter(filterIntervalLong) { + it.libraryManga.manga.fetchInterval.absoluteValue >= 28 + } + } + + val now = lazy { Date().time } + val filterFnIntervalLate: (LibraryItem) -> Boolean = { + applyFilter(filterIntervalLate) { + if (it.libraryManga.manga.fetchInterval == 0) { true } else { + // get last chapter upload or last fetch if source has no upload time + val maxUpload = if (it.libraryManga.latestUpload != 0L) it.libraryManga.latestUpload else it.libraryManga.chapterFetchedAt + val lapse = (now.value - maxUpload) + val interval = (it.libraryManga.manga.fetchInterval.absoluteValue) * 86400000L + // Missed 10 to 20 checks + lapse > interval * 5 + } + } + } + val late2month = lazy { now.value - 56 * 86400000L } + val filterFnIntervalDropped: (LibraryItem) -> Boolean = { + applyFilter(filterIntervalDropped) { + if (it.libraryManga.manga.fetchInterval == 0) { true } else { + val maxUpload = if (it.libraryManga.latestUpload != 0L) it.libraryManga.latestUpload else it.libraryManga.chapterFetchedAt + val lapse = now.value - maxUpload + val interval = (it.libraryManga.manga.fetchInterval.absoluteValue) * 86400000L + // Missed 20+ check and late 2 months + lapse > interval * 10 && late2month.value >= maxUpload + } + } + // get last chapter upload or last fetch if source has no upload time + } + val filterFnDownloaded: (LibraryItem) -> Boolean = { applyFilter(filterDownloaded) { it.libraryManga.manga.isLocal() || @@ -231,6 +274,10 @@ class LibraryScreenModel( filterFnUnread(it) && filterFnStarted(it) && filterFnBookmarked(it) && + filterFnIntervalCustom(it) && + filterFnIntervalLong(it) && + filterFnIntervalLate(it) && + filterFnIntervalDropped(it) && filterFnCompleted(it) && filterFnTracking(it) } @@ -325,6 +372,10 @@ class LibraryScreenModel( libraryPreferences.filterStarted().changes(), libraryPreferences.filterBookmarked().changes(), libraryPreferences.filterCompleted().changes(), + libraryPreferences.filterIntervalLate().changes(), + libraryPreferences.filterIntervalDropped().changes(), + libraryPreferences.filterIntervalCustom().changes(), + libraryPreferences.filterIntervalLong().changes(), transform = { ItemPreferences( downloadBadge = it[0] as Boolean, @@ -336,6 +387,10 @@ class LibraryScreenModel( filterStarted = it[6] as TriState, filterBookmarked = it[7] as TriState, filterCompleted = it[8] as TriState, + filterIntervalLate = it[9] as TriState, + filterIntervalDropped = it[10] as TriState, + filterIntervalCustom = it[11] as TriState, + filterIntervalLong = it[12] as TriState, ) }, ) @@ -699,6 +754,11 @@ class LibraryScreenModel( val filterStarted: TriState, val filterBookmarked: TriState, val filterCompleted: TriState, + val filterIntervalLate: TriState, + val filterIntervalDropped: TriState, + val filterIntervalCustom: TriState, + val filterIntervalLong: TriState, + ) @Immutable diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index 47b7a9efa2..2728963cb1 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -52,8 +52,8 @@ Unread Customized fetch interval Fetch monthly (28 days) - Late 10+ check - Dropped? Late 20+ and 2 months + Late 5+ check + Dropped? Late 10+ and 2 months Passed check period Remove filter