Эх сурвалжийг харах

Added option to bookmark single chapter (#496)

* Added option to bookmark single chapter

* Fixes
Bram van de Kerkhof 8 жил өмнө
parent
commit
125f1ae34c

+ 4 - 1
app/src/main/java/eu/kanade/tachiyomi/data/database/DbOpenHelper.kt

@@ -17,7 +17,7 @@ class DbOpenHelper(context: Context)
         /**
          * Version of the database.
          */
-        const val DATABASE_VERSION = 3
+        const val DATABASE_VERSION = 4
     }
 
     override fun onCreate(db: SQLiteDatabase) = with(db) {
@@ -48,6 +48,9 @@ class DbOpenHelper(context: Context)
             db.execSQL(HistoryTable.createTableQuery)
             db.execSQL(HistoryTable.createChapterIdIndexQuery)
         }
+        if (oldVersion < 4) {
+            db.execSQL(ChapterTable.bookmarkUpdateQuery)
+        }
     }
 
     override fun onConfigure(db: SQLiteDatabase) {

+ 4 - 1
app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/ChapterTypeMapping.kt

@@ -11,6 +11,7 @@ import com.pushtorefresh.storio.sqlite.queries.InsertQuery
 import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
 import eu.kanade.tachiyomi.data.database.models.Chapter
 import eu.kanade.tachiyomi.data.database.models.ChapterImpl
+import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_BOOKMARKED
 import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_CHAPTER_NUMBER
 import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_DATE_FETCH
 import eu.kanade.tachiyomi.data.database.tables.ChapterTable.COL_DATE_UPLOAD
@@ -41,12 +42,13 @@ class ChapterPutResolver : DefaultPutResolver<Chapter>() {
             .whereArgs(obj.id)
             .build()
 
-    override fun mapToContentValues(obj: Chapter) = ContentValues(10).apply {
+    override fun mapToContentValues(obj: Chapter) = ContentValues(11).apply {
         put(COL_ID, obj.id)
         put(COL_MANGA_ID, obj.manga_id)
         put(COL_URL, obj.url)
         put(COL_NAME, obj.name)
         put(COL_READ, obj.read)
+        put(COL_BOOKMARKED, obj.bookmark)
         put(COL_DATE_FETCH, obj.date_fetch)
         put(COL_DATE_UPLOAD, obj.date_upload)
         put(COL_LAST_PAGE_READ, obj.last_page_read)
@@ -63,6 +65,7 @@ class ChapterGetResolver : DefaultGetResolver<Chapter>() {
         url = cursor.getString(cursor.getColumnIndex(COL_URL))
         name = cursor.getString(cursor.getColumnIndex(COL_NAME))
         read = cursor.getInt(cursor.getColumnIndex(COL_READ)) == 1
+        bookmark = cursor.getInt(cursor.getColumnIndex(COL_BOOKMARKED)) == 1
         date_fetch = cursor.getLong(cursor.getColumnIndex(COL_DATE_FETCH))
         date_upload = cursor.getLong(cursor.getColumnIndex(COL_DATE_UPLOAD))
         last_page_read = cursor.getInt(cursor.getColumnIndex(COL_LAST_PAGE_READ))

+ 2 - 0
app/src/main/java/eu/kanade/tachiyomi/data/database/models/Chapter.kt

@@ -14,6 +14,8 @@ interface Chapter : Serializable {
 
     var read: Boolean
 
+    var bookmark: Boolean
+
     var last_page_read: Int
 
     var date_fetch: Long

+ 2 - 0
app/src/main/java/eu/kanade/tachiyomi/data/database/models/ChapterImpl.kt

@@ -12,6 +12,8 @@ class ChapterImpl : Chapter {
 
     override var read: Boolean = false
 
+    override var bookmark: Boolean = false
+
     override var last_page_read: Int = 0
 
     override var date_fetch: Long = 0

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

@@ -84,6 +84,10 @@ interface Manga : Serializable {
         get() = chapter_flags and DOWNLOADED_MASK
         set(filter) = setFlags(filter, DOWNLOADED_MASK)
 
+    var bookmarkedFilter: Int
+        get() = chapter_flags and BOOKMARKED_MASK
+        set(filter) = setFlags(filter, BOOKMARKED_MASK)
+
     var sorting: Int
         get() = chapter_flags and SORTING_MASK
         set(sort) = setFlags(sort, SORTING_MASK)
@@ -110,6 +114,10 @@ interface Manga : Serializable {
         const val SHOW_NOT_DOWNLOADED = 0x00000010
         const val DOWNLOADED_MASK = 0x00000018
 
+        const val SHOW_BOOKMARKED = 0x00000020
+        const val SHOW_NOT_BOOKMARKED = 0x00000040
+        const val BOOKMARKED_MASK = 0x00000060
+
         const val SORTING_SOURCE = 0x00000000
         const val SORTING_NUMBER = 0x00000100
         const val SORTING_MASK = 0x00000100

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

@@ -25,8 +25,9 @@ class ChapterProgressPutResolver : PutResolver<Chapter>() {
             .whereArgs(chapter.id)
             .build()
 
-    fun mapToContentValues(chapter: Chapter) = ContentValues(2).apply {
+    fun mapToContentValues(chapter: Chapter) = ContentValues(3).apply {
         put(ChapterTable.COL_READ, chapter.read)
+        put(ChapterTable.COL_BOOKMARKED, chapter.bookmark)
         put(ChapterTable.COL_LAST_PAGE_READ, chapter.last_page_read)
     }
 

+ 6 - 0
app/src/main/java/eu/kanade/tachiyomi/data/database/tables/ChapterTable.kt

@@ -14,6 +14,8 @@ object ChapterTable {
 
     const val COL_READ = "read"
 
+    const val COL_BOOKMARKED = "bookmark"
+
     const val COL_DATE_FETCH = "date_fetch"
 
     const val COL_DATE_UPLOAD = "date_upload"
@@ -31,6 +33,7 @@ object ChapterTable {
             $COL_URL TEXT NOT NULL,
             $COL_NAME TEXT NOT NULL,
             $COL_READ BOOLEAN NOT NULL,
+            $COL_BOOKMARKED BOOLEAN NOT NULL,
             $COL_LAST_PAGE_READ INT NOT NULL,
             $COL_CHAPTER_NUMBER FLOAT NOT NULL,
             $COL_SOURCE_ORDER INTEGER NOT NULL,
@@ -46,4 +49,7 @@ object ChapterTable {
     val sourceOrderUpdateQuery: String
         get() = "ALTER TABLE $TABLE ADD COLUMN $COL_SOURCE_ORDER INTEGER DEFAULT 0"
 
+    val bookmarkUpdateQuery: String
+        get() = "ALTER TABLE $TABLE ADD COLUMN $COL_BOOKMARKED BOOLEAN DEFAULT FALSE"
+
 }

+ 11 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.kt

@@ -121,11 +121,13 @@ class ChaptersFragment : BaseRxFragment<ChaptersPresenter>(), ActionMode.Callbac
         val menuFilterRead = menu.findItem(R.id.action_filter_read)
         val menuFilterUnread = menu.findItem(R.id.action_filter_unread)
         val menuFilterDownloaded = menu.findItem(R.id.action_filter_downloaded)
+        val menuFilterBookmarked = menu.findItem(R.id.action_filter_bookmarked)
 
         // Set correct checkbox values.
         menuFilterRead.isChecked = presenter.onlyRead()
         menuFilterUnread.isChecked = presenter.onlyUnread()
         menuFilterDownloaded.isChecked = presenter.onlyDownloaded()
+        menuFilterBookmarked.isChecked = presenter.onlyBookmarked()
 
         if (presenter.onlyRead())
             //Disable unread filter option if read filter is enabled.
@@ -154,6 +156,10 @@ class ChaptersFragment : BaseRxFragment<ChaptersPresenter>(), ActionMode.Callbac
                 item.isChecked = !item.isChecked
                 presenter.setDownloadedFilter(item.isChecked)
             }
+            R.id.action_filter_bookmarked -> {
+                item.isChecked = !item.isChecked
+                presenter.setBookmarkedFilter(item.isChecked)
+            }
             R.id.action_filter_empty -> {
                 presenter.removeFilters()
                 activity.supportInvalidateOptionsMenu()
@@ -362,6 +368,11 @@ class ChaptersFragment : BaseRxFragment<ChaptersPresenter>(), ActionMode.Callbac
         presenter.downloadChapters(chapters)
     }
 
+    fun bookmarkChapters(chapters: List<ChapterModel>, bookmarked: Boolean) {
+        destroyActionModeIfNeeded()
+        presenter.bookmarkChapters(chapters,bookmarked)
+    }
+
     fun deleteChapters(chapters: List<ChapterModel>) {
         destroyActionModeIfNeeded()
         DeletingChaptersDialog().show(childFragmentManager, DeletingChaptersDialog.TAG)

+ 10 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersHolder.kt

@@ -21,6 +21,7 @@ class ChaptersHolder(
 
     private val readColor = view.context.theme.getResourceColor(android.R.attr.textColorHint)
     private val unreadColor = view.context.theme.getResourceColor(android.R.attr.textColorPrimary)
+    private val bookmarkedColor = view.context.theme.getResourceColor(android.R.attr.colorAccent)
     private val decimalFormat = DecimalFormat("#.###", DecimalFormatSymbols().apply { decimalSeparator = '.' })
     private val df = DateFormat.getDateInstance(DateFormat.SHORT)
 
@@ -43,7 +44,10 @@ class ChaptersHolder(
             }
             else -> chapter.name
         }
+
+        // Set correct text color
         chapter_title.setTextColor(if (chapter.read) readColor else unreadColor)
+        if (chapter.bookmark) chapter_title.setTextColor(bookmarkedColor)
 
         if (chapter.date_upload > 0) {
             chapter_date.text = df.format(Date(chapter.date_upload))
@@ -84,6 +88,10 @@ class ChaptersHolder(
             popup.menu.findItem(R.id.action_delete).isVisible = true
         }
 
+        // Hide bookmark if bookmark
+        popup.menu.findItem(R.id.action_bookmark).isVisible = !chapter.bookmark
+        popup.menu.findItem(R.id.action_remove_bookmark).isVisible = chapter.bookmark
+
         // Hide mark as unread when the chapter is unread
         if (!chapter.read && chapter.last_page_read == 0) {
             popup.menu.findItem(R.id.action_mark_as_unread).isVisible = false
@@ -101,6 +109,8 @@ class ChaptersHolder(
             with(adapter.fragment) {
                 when (menuItem.itemId) {
                     R.id.action_download -> downloadChapters(chapterList)
+                    R.id.action_bookmark -> bookmarkChapters(chapterList, true)
+                    R.id.action_remove_bookmark -> bookmarkChapters(chapterList, false)
                     R.id.action_delete -> deleteChapters(chapterList)
                     R.id.action_mark_as_read -> markAsRead(chapterList)
                     R.id.action_mark_as_unread -> markAsUnread(chapterList)

+ 36 - 12
app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.kt

@@ -200,7 +200,6 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
 
     /**
      * Applies the view filters to the list of chapters obtained from the database.
-     *
      * @param chapters the list of chapters from the database
      * @return an observable of the list of chapters filtered and sorted.
      */
@@ -215,6 +214,9 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
         if (onlyDownloaded()) {
             observable = observable.filter { it.isDownloaded }
         }
+        if (onlyBookmarked()) {
+            observable = observable.filter { it.bookmark }
+        }
         val sortFunction: (Chapter, Chapter) -> Int = when (manga.sorting) {
             Manga.SORTING_SOURCE -> when (sortDescending()) {
                 true  -> { c1, c2 -> c1.source_order.compareTo(c2.source_order) }
@@ -231,7 +233,6 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
 
     /**
      * Called when a download for the active manga changes status.
-     *
      * @param download the download whose status changed.
      */
     fun onDownloadStatusChange(download: Download) {
@@ -258,7 +259,6 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
 
     /**
      * Mark the selected chapter list as read/unread.
-     *
      * @param selectedChapters the list of selected chapters.
      * @param read whether to mark chapters as read or unread.
      */
@@ -278,7 +278,6 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
 
     /**
      * Mark the previous chapters to the selected one as read.
-     *
      * @param chapter the selected chapter.
      */
     fun markPreviousChaptersAsRead(chapter: ChapterModel) {
@@ -292,7 +291,6 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
 
     /**
      * Downloads the given list of chapters with the manager.
-     *
      * @param chapters the list of chapters to download.
      */
     fun downloadChapters(chapters: List<ChapterModel>) {
@@ -300,9 +298,23 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
         downloadManager.downloadChapters(manga, chapters)
     }
 
+    /**
+     * Bookmarks the given list of chapters.
+     * @param selectedChapters the list of chapters to bookmark.
+     */
+    fun bookmarkChapters(selectedChapters: List<ChapterModel>, bookmarked: Boolean) {
+        Observable.from(selectedChapters)
+                .doOnNext { chapter ->
+                    chapter.bookmark = bookmarked
+                }
+                .toList()
+                .flatMap { db.updateChaptersProgress(it).asRxObservable() }
+                .subscribeOn(Schedulers.io())
+                .subscribe()
+    }
+
     /**
      * Deletes the given list of chapter.
-     *
      * @param chapters the list of chapters to delete.
      */
     fun deleteChapters(chapters: List<ChapterModel>) {
@@ -328,7 +340,6 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
 
     /**
      * Deletes a chapter from disk. This method is called in a background thread.
-     *
      * @param chapter the chapter to delete.
      */
     private fun deleteChapter(chapter: ChapterModel) {
@@ -349,7 +360,6 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
 
     /**
      * Sets the read filter and requests an UI update.
-     *
      * @param onlyUnread whether to display only unread chapters or all chapters.
      */
     fun setUnreadFilter(onlyUnread: Boolean) {
@@ -360,7 +370,6 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
 
     /**
      * Sets the read filter and requests an UI update.
-     *
      * @param onlyRead whether to display only read chapters or all chapters.
      */
     fun setReadFilter(onlyRead: Boolean) {
@@ -371,7 +380,6 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
 
     /**
      * Sets the download filter and requests an UI update.
-     *
      * @param onlyDownloaded whether to display only downloaded chapters or all chapters.
      */
     fun setDownloadedFilter(onlyDownloaded: Boolean) {
@@ -380,19 +388,29 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
         refreshChapters()
     }
 
+    /**
+     * Sets the bookmark filter and requests an UI update.
+     * @param onlyBookmarked whether to display only bookmarked chapters or all chapters.
+     */
+    fun setBookmarkedFilter(onlyBookmarked: Boolean) {
+        manga.bookmarkedFilter = if (onlyBookmarked) Manga.SHOW_BOOKMARKED else Manga.SHOW_ALL
+        db.updateFlags(manga).executeAsBlocking()
+        refreshChapters()
+    }
+
     /**
      * Removes all filters and requests an UI update.
      */
     fun removeFilters() {
         manga.readFilter = Manga.SHOW_ALL
         manga.downloadedFilter = Manga.SHOW_ALL
+        manga.bookmarkedFilter = Manga.SHOW_ALL
         db.updateFlags(manga).executeAsBlocking()
         refreshChapters()
     }
 
     /**
      * Sets the active display mode.
-     *
      * @param mode the mode to set.
      */
     fun setDisplayMode(mode: Int) {
@@ -402,7 +420,6 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
 
     /**
      * Sets the sorting method and requests an UI update.
-     *
      * @param sort the sorting mode.
      */
     fun setSorting(sort: Int) {
@@ -418,6 +435,13 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
         return manga.downloadedFilter == Manga.SHOW_DOWNLOADED
     }
 
+    /**
+     * Whether the display only downloaded filter is enabled.
+     */
+    fun onlyBookmarked(): Boolean {
+        return manga.bookmarkedFilter == Manga.SHOW_BOOKMARKED
+    }
+
     /**
      * Whether the display only unread filter is enabled.
      */

+ 0 - 2
app/src/main/res/layout/item_chapter.xml

@@ -5,8 +5,6 @@
                 android:layout_width="fill_parent"
                 android:layout_height="?android:attr/listPreferredItemHeight"
                 android:background="?attr/selectable_list_drawable">
-
-
     <RelativeLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"

+ 8 - 0
app/src/main/res/menu/chapter_single.xml

@@ -6,6 +6,14 @@
           android:title="@string/action_download"
           android:visible="true" />
 
+    <item android:id="@+id/action_bookmark"
+          android:title="@string/action_bookmark"
+          android:visible="true" />
+
+    <item android:id="@+id/action_remove_bookmark"
+          android:title="@string/action_remove_bookmark"
+          android:visible="true" />
+
     <item android:id="@+id/action_delete"
           android:title="@string/action_delete"
           android:visible="false" />

+ 4 - 0
app/src/main/res/menu/chapters.xml

@@ -20,6 +20,10 @@
                 android:id="@+id/action_filter_downloaded"
                 android:checkable="true"
                 android:title="@string/action_filter_downloaded"/>
+            <item
+                android:id="@+id/action_filter_bookmarked"
+                android:checkable="true"
+                android:title="@string/action_filter_bookmarked"/>
             <item
                 android:id="@+id/action_filter_empty"
                 android:title="@string/action_filter_empty"/>

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

@@ -19,6 +19,7 @@
     <string name="action_settings">Settings</string>
     <string name="action_filter">Filter</string>
     <string name="action_filter_downloaded">Downloaded</string>
+    <string name="action_filter_bookmarked">Bookmarked</string>
     <string name="action_filter_unread">Unread</string>
     <string name="action_filter_read">Read</string>
     <string name="action_filter_empty">Remove filter</string>
@@ -28,6 +29,8 @@
     <string name="action_mark_as_unread">Mark as unread</string>
     <string name="action_mark_previous_as_read">Mark previous as read</string>
     <string name="action_download">Download</string>
+    <string name="action_bookmark">Bookmark</string>
+    <string name="action_remove_bookmark">Remove bookmark</string>
     <string name="action_delete">Delete</string>
     <string name="action_update">Update</string>
     <string name="action_update_library">Update library</string>