Browse Source

Recently read improvements: Open next chapter if read, local date formatting

len 8 years ago
parent
commit
3680eb0bf5

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

@@ -50,4 +50,14 @@ interface HistoryQueries : DbProvider {
             .`object`(history)
             .withPutResolver(HistoryLastReadPutResolver())
             .prepare()
+
+    /**
+     * Updates the history last read.
+     * Inserts history object if not yet in database
+     * @param historyList history object list
+     */
+    fun updateHistoryLastRead(historyList: List<History>) = db.put()
+            .objects(historyList)
+            .withPutResolver(HistoryLastReadPutResolver())
+            .prepare()
 }

+ 24 - 12
app/src/main/java/eu/kanade/tachiyomi/ui/recently_read/RecentlyReadFragment.kt

@@ -14,6 +14,7 @@ import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment
 import eu.kanade.tachiyomi.ui.main.MainActivity
 import eu.kanade.tachiyomi.ui.manga.MangaActivity
 import eu.kanade.tachiyomi.ui.reader.ReaderActivity
+import eu.kanade.tachiyomi.util.toast
 import kotlinx.android.synthetic.main.fragment_recently_read.*
 import nucleus.factory.RequiresPresenter
 
@@ -85,7 +86,6 @@ class RecentlyReadFragment : BaseRxFragment<RecentlyReadPresenter>() {
      */
     fun removeFromHistory(history: History) {
         presenter.removeFromHistory(history)
-        adapter.notifyDataSetChanged()
     }
 
     /**
@@ -94,7 +94,6 @@ class RecentlyReadFragment : BaseRxFragment<RecentlyReadPresenter>() {
      */
     fun removeAllFromHistory(mangaId: Long) {
         presenter.removeAllFromHistory(mangaId)
-        adapter.notifyDataSetChanged()
     }
 
     /**
@@ -103,8 +102,29 @@ class RecentlyReadFragment : BaseRxFragment<RecentlyReadPresenter>() {
      * @param manga manga belonging to chapter
      */
     fun openChapter(chapter: Chapter, manga: Manga) {
-        val intent = ReaderActivity.newIntent(activity, manga, chapter)
-        startActivity(intent)
+        if (!chapter.read) {
+            val intent = ReaderActivity.newIntent(activity, manga, chapter)
+            startActivity(intent)
+        } else {
+            presenter.openNextChapter(chapter, manga)
+        }
+    }
+
+    /**
+     * Called from the presenter when wanting to open the next chapter of the current one.
+     * @param chapter the next chapter or null if it doesn't exist.
+     * @param manga the manga of the chapter.
+     */
+    fun onOpenNextChapter(chapter: Chapter?, manga: Manga) {
+        if (chapter == null) {
+            context.toast(R.string.no_next_chapter)
+        }
+        // Avoid crashes if the fragment isn't resumed, the event will be ignored but it's unlikely
+        // to happen.
+        else if (isResumed) {
+            val intent = ReaderActivity.newIntent(activity, manga, chapter)
+            startActivity(intent)
+        }
     }
 
     /**
@@ -116,12 +136,4 @@ class RecentlyReadFragment : BaseRxFragment<RecentlyReadPresenter>() {
         startActivity(intent)
     }
 
-    /**
-     * Returns the timestamp of last read
-     * @param history history containing time of last read
-     */
-    fun getLastRead(history: History): String? {
-        return presenter.getLastRead(history)
-    }
-
 }

+ 10 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/recently_read/RecentlyReadHolder.kt

@@ -10,8 +10,11 @@ import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
 import eu.kanade.tachiyomi.data.source.SourceManager
 import kotlinx.android.synthetic.main.dialog_remove_recently.view.*
 import kotlinx.android.synthetic.main.item_recently_read.view.*
+import uy.kohesive.injekt.injectLazy
+import java.text.DateFormat
 import java.text.DecimalFormat
 import java.text.DecimalFormatSymbols
+import java.util.*
 
 /**
  * Holder that contains recent manga item
@@ -30,6 +33,10 @@ class RecentlyReadHolder(view: View, private val adapter: RecentlyReadAdapter)
      */
     private val decimalFormat = DecimalFormat("#.###", DecimalFormatSymbols().apply { decimalSeparator = '.' })
 
+    private val sourceManager by injectLazy<SourceManager>()
+
+    private val df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT)
+
     /**
      * Set values of view
      *
@@ -47,10 +54,10 @@ class RecentlyReadHolder(view: View, private val adapter: RecentlyReadAdapter)
         // Set source + chapter title
         val formattedNumber = decimalFormat.format(chapter.chapter_number.toDouble())
         itemView.manga_source.text = itemView.context.getString(R.string.recent_manga_source)
-                .format(SourceManager(adapter.fragment.context).get(manga.source)?.name, formattedNumber)
+                .format(sourceManager.get(manga.source)?.name, formattedNumber)
 
         // Set last read timestamp title
-        itemView.last_read.text = adapter.fragment.getLastRead(history)
+        itemView.last_read.text = df.format(Date(history.last_read))
 
         // Set cover
         if (!manga.thumbnail_url.isNullOrEmpty()) {
@@ -79,7 +86,7 @@ class RecentlyReadHolder(view: View, private val adapter: RecentlyReadAdapter)
                     .onNegative { materialDialog, dialogAction ->
                         materialDialog.dismiss()
                     }
-                    .show();
+                    .show()
         }
 
         // Set continue reading clickListener

+ 59 - 37
app/src/main/java/eu/kanade/tachiyomi/ui/recently_read/RecentlyReadPresenter.kt

@@ -2,15 +2,15 @@ package eu.kanade.tachiyomi.ui.recently_read
 
 import android.os.Bundle
 import eu.kanade.tachiyomi.data.database.DatabaseHelper
+import eu.kanade.tachiyomi.data.database.models.Chapter
 import eu.kanade.tachiyomi.data.database.models.History
+import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
 import rx.Observable
 import rx.android.schedulers.AndroidSchedulers
-import rx.schedulers.Schedulers
 import timber.log.Timber
 import uy.kohesive.injekt.injectLazy
-import java.text.SimpleDateFormat
 import java.util.*
 
 /**
@@ -20,13 +20,6 @@ import java.util.*
  */
 class RecentlyReadPresenter : BasePresenter<RecentlyReadFragment>() {
 
-    companion object {
-        /**
-         * The id of the restartable.
-         */
-        const private val GET_RECENT_MANGA = 1
-    }
-
     /**
      * Used to connect to database
      */
@@ -35,26 +28,18 @@ class RecentlyReadPresenter : BasePresenter<RecentlyReadFragment>() {
     override fun onCreate(savedState: Bundle?) {
         super.onCreate(savedState)
 
-        // Used to get recent manga
-        restartableLatestCache(GET_RECENT_MANGA,
-                { getRecentMangaObservable() },
-                { view, manga ->
-                    // Update adapter to show recent manga's
-                    view.onNextManga(manga)
-                }
-        )
-
-        if (savedState == null) {
-            // Start fetching recent manga
-            start(GET_RECENT_MANGA)
-        }
+        // Used to get a list of recently read manga
+        getRecentMangaObservable()
+                .subscribeLatestCache({ view, historyList ->
+                    view.onNextManga(historyList)
+                })
     }
 
     /**
      * Get recent manga observable
      * @return list of history
      */
-    fun getRecentMangaObservable(): Observable<MutableList<MangaChapterHistory>> {
+    fun getRecentMangaObservable(): Observable<List<MangaChapterHistory>> {
         // Set date for recent manga
         val cal = Calendar.getInstance()
         cal.time = Date()
@@ -71,30 +56,67 @@ class RecentlyReadPresenter : BasePresenter<RecentlyReadFragment>() {
     fun removeFromHistory(history: History) {
         history.last_read = 0L
         db.updateHistoryLastRead(history).asRxObservable()
-                .doOnError { Timber.e(it.message) }.subscribe()
+                .subscribe()
     }
 
     /**
-     * Removes all chapters belonging to manga from library
+     * Removes all chapters belonging to manga from history.
      * @param mangaId id of manga
      */
     fun removeAllFromHistory(mangaId: Long) {
-        db.getHistoryByMangaId(mangaId).asRxObservable()
-                .take(1)
-                .flatMapIterable { it }
-                .doOnError { Timber.e(it.message) }
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribe({ result -> removeFromHistory(result) })
+        db.getHistoryByMangaId(mangaId).asRxSingle()
+                .map { list ->
+                    list.forEach { it.last_read = 0L }
+                    db.updateHistoryLastRead(list).executeAsBlocking()
+                }
+                .subscribe()
     }
 
     /**
-     * Returns the timestamp of last read
-     * @param history history containing time of last read
+     * Open the next chapter instead of the current one.
+     * @param chapter the chapter of the history object.
+     * @param manga the manga of the chapter.
      */
-    fun getLastRead(history: History): String? {
-        return SimpleDateFormat("dd-MM-yyyy HH:mm",
-                Locale.getDefault()).format(Date(history.last_read))
+    fun openNextChapter(chapter: Chapter, manga: Manga) {
+        val sortFunction: (Chapter, Chapter) -> Int = when (manga.sorting) {
+            Manga.SORTING_SOURCE -> { c1, c2 -> c2.source_order.compareTo(c1.source_order) }
+            Manga.SORTING_NUMBER -> { c1, c2 -> c1.chapter_number.compareTo(c2.chapter_number) }
+            else -> throw NotImplementedError("Unknown sorting method")
+        }
+
+        db.getChapters(manga).asRxSingle()
+                .map { it.sortedWith(Comparator<Chapter> { c1, c2 -> sortFunction(c1, c2) }) }
+                .map { chapters ->
+                    val currChapterIndex = chapters.indexOfFirst { chapter.id == it.id }
+                    when (manga.sorting) {
+                        Manga.SORTING_SOURCE -> {
+                            chapters.getOrNull(currChapterIndex + 1)
+                        }
+                        Manga.SORTING_NUMBER -> {
+                            val chapterNumber = chapter.chapter_number
+
+                            var nextChapter: Chapter? = null
+                            for (i in (currChapterIndex + 1) until chapters.size) {
+                                val c = chapters[i]
+                                if (c.chapter_number > chapterNumber &&
+                                        c.chapter_number <= chapterNumber + 1) {
+
+                                    nextChapter = c
+                                    break
+                                }
+                            }
+                            nextChapter
+                        }
+                        else -> throw NotImplementedError("Unknown sorting method")
+                    }
+                }
+                .toObservable()
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribeFirst({ view, chapter ->
+                    view.onOpenNextChapter(chapter, manga)
+                }, { view, error ->
+                    Timber.e(error, error.message)
+                })
     }
 
 }