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