From 125f1ae34ca020017daea74ed1b06d2f22d0f8f6 Mon Sep 17 00:00:00 2001 From: Bram van de Kerkhof Date: Sun, 6 Nov 2016 13:33:00 +0100 Subject: [PATCH] Added option to bookmark single chapter (#496) * Added option to bookmark single chapter * Fixes --- .../tachiyomi/data/database/DbOpenHelper.kt | 5 +- .../database/mappers/ChapterTypeMapping.kt | 5 +- .../tachiyomi/data/database/models/Chapter.kt | 2 + .../data/database/models/ChapterImpl.kt | 2 + .../tachiyomi/data/database/models/Manga.kt | 8 ++++ .../resolvers/ChapterProgressPutResolver.kt | 3 +- .../data/database/tables/ChapterTable.kt | 6 +++ .../ui/manga/chapter/ChaptersFragment.kt | 11 +++++ .../ui/manga/chapter/ChaptersHolder.kt | 10 ++++ .../ui/manga/chapter/ChaptersPresenter.kt | 48 ++++++++++++++----- app/src/main/res/layout/item_chapter.xml | 2 - app/src/main/res/menu/chapter_single.xml | 8 ++++ app/src/main/res/menu/chapters.xml | 4 ++ app/src/main/res/values/strings.xml | 3 ++ 14 files changed, 100 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/DbOpenHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/DbOpenHelper.kt index 5790260de..4687a0e38 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/DbOpenHelper.kt +++ b/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) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/ChapterTypeMapping.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/ChapterTypeMapping.kt index 82914045f..656f42e6e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/mappers/ChapterTypeMapping.kt +++ b/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() { .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() { 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)) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Chapter.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Chapter.kt index f0294c275..af2346fc8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Chapter.kt +++ b/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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/ChapterImpl.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/ChapterImpl.kt index 7120e583b..f7f1d0662 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/ChapterImpl.kt +++ b/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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Manga.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Manga.kt index 45709b256..320560aa9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Manga.kt +++ b/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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/ChapterProgressPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/ChapterProgressPutResolver.kt index a272597b5..f994ddcec 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/ChapterProgressPutResolver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/ChapterProgressPutResolver.kt @@ -25,8 +25,9 @@ class ChapterProgressPutResolver : PutResolver() { .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) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/ChapterTable.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/ChapterTable.kt index d3795a15a..6405f45f9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/tables/ChapterTable.kt +++ b/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" + } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.kt index fdf5a0747..39458dba7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.kt @@ -121,11 +121,13 @@ class ChaptersFragment : BaseRxFragment(), 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(), 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(), ActionMode.Callbac presenter.downloadChapters(chapters) } + fun bookmarkChapters(chapters: List, bookmarked: Boolean) { + destroyActionModeIfNeeded() + presenter.bookmarkChapters(chapters,bookmarked) + } + fun deleteChapters(chapters: List) { destroyActionModeIfNeeded() DeletingChaptersDialog().show(childFragmentManager, DeletingChaptersDialog.TAG) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersHolder.kt index e2cbe0a1e..373a37d0b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersHolder.kt +++ b/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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.kt index df212d13f..1a669426e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersPresenter.kt @@ -200,7 +200,6 @@ class ChaptersPresenter : BasePresenter() { /** * 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() { 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() { /** * 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() { /** * 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() { /** * 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() { /** * Downloads the given list of chapters with the manager. - * * @param chapters the list of chapters to download. */ fun downloadChapters(chapters: List) { @@ -300,9 +298,23 @@ class ChaptersPresenter : BasePresenter() { downloadManager.downloadChapters(manga, chapters) } + /** + * Bookmarks the given list of chapters. + * @param selectedChapters the list of chapters to bookmark. + */ + fun bookmarkChapters(selectedChapters: List, 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) { @@ -328,7 +340,6 @@ class ChaptersPresenter : BasePresenter() { /** * 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() { /** * 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() { /** * 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() { /** * 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() { 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() { /** * 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() { 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. */ diff --git a/app/src/main/res/layout/item_chapter.xml b/app/src/main/res/layout/item_chapter.xml index 8235a97eb..3aab2d412 100644 --- a/app/src/main/res/layout/item_chapter.xml +++ b/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"> - - + + + + diff --git a/app/src/main/res/menu/chapters.xml b/app/src/main/res/menu/chapters.xml index 4512d8637..c911d1fbf 100644 --- a/app/src/main/res/menu/chapters.xml +++ b/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"/> + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 89900da3c..b6e9bdb3a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -19,6 +19,7 @@ Settings Filter Downloaded + Bookmarked Unread Read Remove filter @@ -28,6 +29,8 @@ Mark as unread Mark previous as read Download + Bookmark + Remove bookmark Delete Update Update library