Browse Source

Add "Started" library filter and library update restriction (#6382)

* Add chapter read count to library manga

Co-Authored-By: Jays2Kings <[email protected]>

* Add "Started" library filter and library update restriction

* Update Filter when its changed

* Add back accidentally removed stuff.

* Update..

* Change variable names

* Change Variable name where I missed

Co-authored-by: Jays2Kings <[email protected]>
FourTOne5 3 years ago
parent
commit
f18d161eaf

+ 8 - 1
app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt

@@ -2,7 +2,14 @@ package eu.kanade.tachiyomi.data.database.models
 
 class LibraryManga : MangaImpl() {
 
-    var unread: Int = 0
+    var unreadCount: Int = 0
+    var readCount: Int = 0
+
+    val totalChapters
+        get() = readCount + unreadCount
+
+    val hasStarted
+        get() = readCount > 0
 
     var category: Int = 0
 }

+ 10 - 3
app/src/main/java/eu/kanade/tachiyomi/data/database/queries/RawQueries.kt

@@ -8,21 +8,28 @@ import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable as MangaCateg
 import eu.kanade.tachiyomi.data.database.tables.MangaTable as Manga
 
 /**
- * Query to get the manga from the library, with their categories and unread count.
+ * Query to get the manga from the library, with their categories, read and unread count.
  */
 val libraryQuery =
     """
     SELECT M.*, COALESCE(MC.${MangaCategory.COL_CATEGORY_ID}, 0) AS ${Manga.COL_CATEGORY}
     FROM (
-        SELECT ${Manga.TABLE}.*, COALESCE(C.unread, 0) AS ${Manga.COL_UNREAD}
+        SELECT ${Manga.TABLE}.*, COALESCE(C.unreadCount, 0) AS ${Manga.COMPUTED_COL_UNREAD_COUNT}, COALESCE(R.readCount, 0) AS ${Manga.COMPUTED_COL_READ_COUNT}
         FROM ${Manga.TABLE}
         LEFT JOIN (
-            SELECT ${Chapter.COL_MANGA_ID}, COUNT(*) AS unread
+            SELECT ${Chapter.COL_MANGA_ID}, COUNT(*) AS unreadCount
             FROM ${Chapter.TABLE}
             WHERE ${Chapter.COL_READ} = 0
             GROUP BY ${Chapter.COL_MANGA_ID}
         ) AS C
         ON ${Manga.COL_ID} = C.${Chapter.COL_MANGA_ID}
+        LEFT JOIN (
+            SELECT ${Chapter.COL_MANGA_ID}, COUNT(*) AS readCount
+            FROM ${Chapter.TABLE}
+            WHERE ${Chapter.COL_READ} = 1
+            GROUP BY ${Chapter.COL_MANGA_ID}
+        ) AS R
+        ON ${Manga.COL_ID} = R.${Chapter.COL_MANGA_ID}
         WHERE ${Manga.COL_FAVORITE} = 1
         GROUP BY ${Manga.COL_ID}
         ORDER BY ${Manga.COL_TITLE}

+ 2 - 1
app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/LibraryMangaGetResolver.kt

@@ -16,8 +16,9 @@ class LibraryMangaGetResolver : DefaultGetResolver<LibraryManga>(), BaseMangaGet
         val manga = LibraryManga()
 
         mapBaseFromCursor(manga, cursor)
-        manga.unread = cursor.getInt(cursor.getColumnIndexOrThrow(MangaTable.COL_UNREAD))
+        manga.unreadCount = cursor.getInt(cursor.getColumnIndexOrThrow(MangaTable.COMPUTED_COL_UNREAD_COUNT))
         manga.category = cursor.getInt(cursor.getColumnIndexOrThrow(MangaTable.COL_CATEGORY))
+        manga.readCount = cursor.getInt(cursor.getColumnIndexOrThrow(MangaTable.COMPUTED_COL_READ_COUNT))
 
         return manga
     }

+ 5 - 2
app/src/main/java/eu/kanade/tachiyomi/data/database/tables/MangaTable.kt

@@ -39,12 +39,15 @@ object MangaTable {
 
     const val COL_CHAPTER_FLAGS = "chapter_flags"
 
-    const val COL_UNREAD = "unread"
-
     const val COL_CATEGORY = "category"
 
     const val COL_COVER_LAST_MODIFIED = "cover_last_modified"
 
+    // Not an actual value but computed when created
+    const val COMPUTED_COL_UNREAD_COUNT = "unread_count"
+
+    const val COMPUTED_COL_READ_COUNT = "read_count"
+
     val createTableQuery: String
         get() =
             """CREATE TABLE $TABLE(

+ 9 - 1
app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt

@@ -21,6 +21,7 @@ import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Companion.start
 import eu.kanade.tachiyomi.data.notification.Notifications
 import eu.kanade.tachiyomi.data.preference.MANGA_FULLY_READ
 import eu.kanade.tachiyomi.data.preference.MANGA_ONGOING
+import eu.kanade.tachiyomi.data.preference.MANGA_STARTED
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.track.EnhancedTrackService
 import eu.kanade.tachiyomi.data.track.TrackManager
@@ -266,7 +267,14 @@ class LibraryUpdateService(
                 listToUpdate = listToUpdate.filterNot { it.status == SManga.COMPLETED }
             }
             if (MANGA_FULLY_READ in restrictions) {
-                listToUpdate = listToUpdate.filter { it.unread == 0 }
+                listToUpdate = listToUpdate.filter { it.unreadCount == 0 }
+            }
+            if (MANGA_STARTED in restrictions) {
+                listToUpdate = listToUpdate.filter { manga ->
+                    // If the manga has 0 chapters you can't actually start reading it
+                    if (manga.totalChapters == 0) true
+                    else manga.hasStarted
+                }
             }
         }
 

+ 2 - 0
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt

@@ -31,6 +31,8 @@ object PreferenceKeys {
 
     const val filterUnread = "pref_filter_library_unread"
 
+    const val filterStarted = "pref_filter_library_started"
+
     const val filterCompleted = "pref_filter_library_completed"
 
     const val filterTracked = "pref_filter_library_tracked"

+ 1 - 0
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceValues.kt

@@ -7,6 +7,7 @@ const val DEVICE_CHARGING = "ac"
 
 const val MANGA_ONGOING = "manga_ongoing"
 const val MANGA_FULLY_READ = "manga_fully_read"
+const val MANGA_STARTED = "manga_started"
 
 /**
  * This class stores the values for the preferences in the application.

+ 3 - 1
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt

@@ -224,7 +224,7 @@ class PreferencesHelper(val context: Context) {
     fun libraryUpdateInterval() = flowPrefs.getInt("pref_library_update_interval_key", 24)
 
     fun libraryUpdateDeviceRestriction() = flowPrefs.getStringSet("library_update_restriction", setOf(DEVICE_ONLY_ON_WIFI))
-    fun libraryUpdateMangaRestriction() = flowPrefs.getStringSet("library_update_manga_restriction", setOf(MANGA_FULLY_READ, MANGA_ONGOING))
+    fun libraryUpdateMangaRestriction() = flowPrefs.getStringSet("library_update_manga_restriction", setOf(MANGA_FULLY_READ, MANGA_ONGOING, MANGA_STARTED))
 
     fun showUpdatesNavBadge() = flowPrefs.getBoolean("library_update_show_tab_badge", false)
     fun unreadUpdatesCount() = flowPrefs.getInt("library_unread_updates_count", 0)
@@ -252,6 +252,8 @@ class PreferencesHelper(val context: Context) {
 
     fun filterUnread() = flowPrefs.getInt(Keys.filterUnread, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value)
 
+    fun filterStarted() = flowPrefs.getInt(Keys.filterStarted, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value)
+
     fun filterCompleted() = flowPrefs.getInt(Keys.filterCompleted, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value)
 
     fun filterTracking(name: Int) = flowPrefs.getInt("${Keys.filterTracked}_$name", ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value)

+ 34 - 30
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt

@@ -120,6 +120,7 @@ class LibraryPresenter(
         val downloadedOnly = preferences.downloadedOnly().get()
         val filterDownloaded = preferences.filterDownloaded().get()
         val filterUnread = preferences.filterUnread().get()
+        val filterStarted = preferences.filterStarted().get()
         val filterCompleted = preferences.filterCompleted().get()
         val loggedInServices = trackManager.services.filter { trackService -> trackService.isLogged }
             .associate { trackService ->
@@ -127,14 +128,34 @@ class LibraryPresenter(
             }
         val isNotAnyLoggedIn = !loggedInServices.values.any()
 
+        val filterFnDownloaded: (LibraryItem) -> Boolean = downloaded@{ item ->
+            if (!downloadedOnly && filterDownloaded == State.IGNORE.value) return@downloaded true
+            val isDownloaded = when {
+                item.manga.isLocal() -> true
+                item.downloadCount != -1 -> item.downloadCount > 0
+                else -> downloadManager.getDownloadCount(item.manga) > 0
+            }
+
+            return@downloaded if (downloadedOnly || filterDownloaded == State.INCLUDE.value) isDownloaded
+            else !isDownloaded
+        }
+
         val filterFnUnread: (LibraryItem) -> Boolean = unread@{ item ->
             if (filterUnread == State.IGNORE.value) return@unread true
-            val isUnread = item.manga.unread != 0
+            val isUnread = item.manga.unreadCount != 0
 
             return@unread if (filterUnread == State.INCLUDE.value) isUnread
             else !isUnread
         }
 
+        val filterFnStarted: (LibraryItem) -> Boolean = started@{ item ->
+            if (filterStarted == State.IGNORE.value) return@started true
+            val hasStarted = item.manga.hasStarted
+
+            return@started if (filterStarted == State.INCLUDE.value) hasStarted
+            else !hasStarted
+        }
+
         val filterFnCompleted: (LibraryItem) -> Boolean = completed@{ item ->
             if (filterCompleted == State.IGNORE.value) return@completed true
             val isCompleted = item.manga.status == SManga.COMPLETED
@@ -143,18 +164,6 @@ class LibraryPresenter(
             else !isCompleted
         }
 
-        val filterFnDownloaded: (LibraryItem) -> Boolean = downloaded@{ item ->
-            if (!downloadedOnly && filterDownloaded == State.IGNORE.value) return@downloaded true
-            val isDownloaded = when {
-                item.manga.isLocal() -> true
-                item.downloadCount != -1 -> item.downloadCount > 0
-                else -> downloadManager.getDownloadCount(item.manga) > 0
-            }
-
-            return@downloaded if (downloadedOnly || filterDownloaded == State.INCLUDE.value) isDownloaded
-            else !isDownloaded
-        }
-
         val filterFnTracking: (LibraryItem) -> Boolean = tracking@{ item ->
             if (isNotAnyLoggedIn) return@tracking true
 
@@ -181,9 +190,10 @@ class LibraryPresenter(
 
         val filterFn: (LibraryItem) -> Boolean = filter@{ item ->
             return@filter !(
-                !filterFnUnread(item) ||
+                !filterFnDownloaded(item) ||
+                    !filterFnUnread(item) ||
+                    !filterFnStarted(item) ||
                     !filterFnCompleted(item) ||
-                    !filterFnDownloaded(item) ||
                     !filterFnTracking(item)
                 )
         }
@@ -212,7 +222,7 @@ class LibraryPresenter(
                 }
 
                 item.unreadCount = if (showUnreadBadges) {
-                    item.manga.unread
+                    item.manga.unreadCount
                 } else {
                     // Unset unread count if not enabled
                     -1
@@ -245,10 +255,6 @@ class LibraryPresenter(
             var counter = 0
             db.getLastReadManga().executeAsBlocking().associate { it.id!! to counter++ }
         }
-        val totalChapterManga by lazy {
-            var counter = 0
-            db.getTotalChapterManga().executeAsBlocking().associate { it.id!! to counter++ }
-        }
         val latestChapterManga by lazy {
             var counter = 0
             db.getLatestChapterManga().executeAsBlocking().associate { it.id!! to counter++ }
@@ -262,7 +268,7 @@ class LibraryPresenter(
             (category.id ?: 0) to SortModeSetting.get(preferences, category)
         }
 
-        val sortAscending = categories.associate { category ->
+        val sortDirections = categories.associate { category ->
             (category.id ?: 0) to SortDirectionSetting.get(preferences, category)
         }
 
@@ -272,7 +278,7 @@ class LibraryPresenter(
         }
         val sortFn: (LibraryItem, LibraryItem) -> Int = { i1, i2 ->
             val sortingMode = sortingModes[i1.manga.category]!!
-            val sortAscending = sortAscending[i1.manga.category]!! == SortDirectionSetting.ASCENDING
+            val sortAscending = sortDirections[i1.manga.category]!! == SortDirectionSetting.ASCENDING
             when (sortingMode) {
                 SortModeSetting.ALPHABETICAL -> {
                     collator.compare(i1.manga.title.lowercase(locale), i2.manga.title.lowercase(locale))
@@ -286,15 +292,13 @@ class LibraryPresenter(
                 SortModeSetting.LAST_CHECKED -> i2.manga.last_update.compareTo(i1.manga.last_update)
                 SortModeSetting.UNREAD -> when {
                     // Ensure unread content comes first
-                    i1.manga.unread == i2.manga.unread -> 0
-                    i1.manga.unread == 0 -> if (sortAscending) 1 else -1
-                    i2.manga.unread == 0 -> if (sortAscending) -1 else 1
-                    else -> i1.manga.unread.compareTo(i2.manga.unread)
+                    i1.manga.unreadCount == i2.manga.unreadCount -> 0
+                    i1.manga.unreadCount == 0 -> if (sortAscending) 1 else -1
+                    i2.manga.unreadCount == 0 -> if (sortAscending) -1 else 1
+                    else -> i1.manga.unreadCount.compareTo(i2.manga.unreadCount)
                 }
                 SortModeSetting.TOTAL_CHAPTERS -> {
-                    val manga1TotalChapter = totalChapterManga[i1.manga.id!!] ?: 0
-                    val mange2TotalChapter = totalChapterManga[i2.manga.id!!] ?: 0
-                    manga1TotalChapter.compareTo(mange2TotalChapter)
+                    i1.manga.totalChapters.compareTo(i2.manga.totalChapters)
                 }
                 SortModeSetting.LATEST_CHAPTER -> {
                     val manga1latestChapter = latestChapterManga[i1.manga.id!!]
@@ -315,7 +319,7 @@ class LibraryPresenter(
         }
 
         return map.mapValues { entry ->
-            val sortAscending = sortAscending[entry.key]!! == SortDirectionSetting.ASCENDING
+            val sortAscending = sortDirections[entry.key]!! == SortDirectionSetting.ASCENDING
 
             val comparator = if (sortAscending) {
                 Comparator(sortFn)

+ 4 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt

@@ -89,6 +89,7 @@ class LibrarySettingsSheet(
 
             private val downloaded = Item.TriStateGroup(R.string.action_filter_downloaded, this)
             private val unread = Item.TriStateGroup(R.string.action_filter_unread, this)
+            private val started = Item.TriStateGroup(R.string.action_filter_started, this)
             private val completed = Item.TriStateGroup(R.string.completed, this)
             private val trackFilters: Map<Int, Item.TriStateGroup>
 
@@ -103,7 +104,7 @@ class LibrarySettingsSheet(
                         trackFilters = services.associate { service ->
                             Pair(service.id, Item.TriStateGroup(getServiceResId(service, size), this))
                         }
-                        val list: MutableList<Item> = mutableListOf(downloaded, unread, completed)
+                        val list: MutableList<Item> = mutableListOf(downloaded, unread, started, completed)
                         if (size > 1) list.add(Item.Header(R.string.action_filter_tracked))
                         list.addAll(trackFilters.values)
                         items = list
@@ -122,6 +123,7 @@ class LibrarySettingsSheet(
                     downloaded.state = preferences.filterDownloaded().get()
                 }
                 unread.state = preferences.filterUnread().get()
+                started.state = preferences.filterStarted().get()
                 completed.state = preferences.filterCompleted().get()
 
                 trackFilters.forEach { trackFilter ->
@@ -141,6 +143,7 @@ class LibrarySettingsSheet(
                 when (item) {
                     downloaded -> preferences.filterDownloaded().set(newState)
                     unread -> preferences.filterUnread().set(newState)
+                    started -> preferences.filterStarted().set(newState)
                     completed -> preferences.filterCompleted().set(newState)
                     else -> {
                         trackFilters.forEach { trackFilter ->

+ 5 - 4
app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt

@@ -15,6 +15,7 @@ import eu.kanade.tachiyomi.data.preference.DEVICE_CHARGING
 import eu.kanade.tachiyomi.data.preference.DEVICE_ONLY_ON_WIFI
 import eu.kanade.tachiyomi.data.preference.MANGA_FULLY_READ
 import eu.kanade.tachiyomi.data.preference.MANGA_ONGOING
+import eu.kanade.tachiyomi.data.preference.MANGA_STARTED
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.track.TrackManager
 import eu.kanade.tachiyomi.databinding.PrefLibraryColumnsBinding
@@ -195,16 +196,16 @@ class SettingsLibraryController : SettingsController() {
             multiSelectListPreference {
                 bindTo(preferences.libraryUpdateMangaRestriction())
                 titleRes = R.string.pref_library_update_manga_restriction
-                entriesRes = arrayOf(R.string.pref_update_only_completely_read, R.string.pref_update_only_non_completed)
-                entryValues = arrayOf(MANGA_FULLY_READ, MANGA_ONGOING)
+                entriesRes = arrayOf(R.string.pref_update_only_completely_read, R.string.pref_update_only_non_completed, R.string.pref_update_only_started)
+                entryValues = arrayOf(MANGA_FULLY_READ, MANGA_ONGOING, MANGA_STARTED)
 
                 fun updateSummary() {
-                    val restrictions = preferences.libraryUpdateMangaRestriction().get()
-                        .sorted()
+                    val restrictions = preferences.libraryUpdateMangaRestriction().get().sorted()
                         .map {
                             when (it) {
                                 MANGA_ONGOING -> context.getString(R.string.pref_update_only_non_completed)
                                 MANGA_FULLY_READ -> context.getString(R.string.pref_update_only_completely_read)
+                                MANGA_STARTED -> context.getString(R.string.pref_update_only_started)
                                 else -> it
                             }
                         }

+ 3 - 0
app/src/main/res/values/strings.xml

@@ -38,6 +38,7 @@
     <string name="action_filter_bookmarked">Bookmarked</string>
     <string name="action_filter_tracked">Tracked</string>
     <string name="action_filter_unread">Unread</string>
+    <string name="action_filter_started">Started</string>
     <string name="action_filter_empty">Remove filter</string>
     <string name="action_sort_alpha">Alphabetically</string>
     <string name="action_sort_count">Total manga</string>
@@ -222,10 +223,12 @@
     <string name="connected_to_wifi">Only on Wi-Fi</string>
     <string name="charging">Charging</string>
     <string name="restrictions">Restrictions: %s</string>
+
     <string name="pref_library_update_manga_restriction">Library update restrictions</string>
     <string name="only_update_restrictions">Only update: %s</string>
     <string name="pref_update_only_completely_read">Completely read series</string>
     <string name="pref_update_only_non_completed">Ongoing series</string>
+    <string name="pref_update_only_started">Started series</string>
     <string name="pref_library_update_show_tab_badge">Show unread count on Updates icon</string>
     <string name="pref_library_update_refresh_metadata">Automatically refresh metadata</string>
     <string name="pref_library_update_refresh_metadata_summary">Check for new cover and details when updating library</string>