Use SQLDelight on Updates screen (#7423)

This commit is contained in:
Andreas 2022-07-01 04:18:12 +02:00 committed by GitHub
parent b9e108eb4d
commit 1f10b79ee8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 156 additions and 125 deletions

View File

@ -1,5 +1,6 @@
package eu.kanade.data.manga package eu.kanade.data.manga
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.Manga
val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long) -> Manga = val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long) -> Manga =
@ -24,3 +25,39 @@ val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?,
initialized = initialized, initialized = initialized,
) )
} }
val mangaChapterMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, Long, Long, String, String, String?, Boolean, Boolean, Long, Float, Long, Long, Long) -> Pair<Manga, Chapter> =
{ _id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, next_update, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, chapterId, mangaId, chapterUrl, name, scanlator, read, bookmark, lastPageRead, chapterNumber, sourceOrder, dateFetch, dateUpload ->
Manga(
id = _id,
source = source,
favorite = favorite,
lastUpdate = lastUpdate ?: 0,
dateAdded = dateAdded,
viewerFlags = viewerFlags,
chapterFlags = chapterFlags,
coverLastModified = coverLastModified,
url = url,
title = title,
artist = artist,
author = author,
description = description,
genre = genre,
status = status,
thumbnailUrl = thumbnailUrl,
initialized = initialized,
) to Chapter(
id = chapterId,
mangaId = mangaId,
read = read,
bookmark = bookmark,
lastPageRead = lastPageRead,
dateFetch = dateFetch,
sourceOrder = sourceOrder,
url = chapterUrl,
name = name,
dateUpload = dateUpload,
chapterNumber = chapterNumber,
scanlator = scanlator,
)
}

View File

@ -1,15 +1,11 @@
package eu.kanade.tachiyomi.data.database.queries package eu.kanade.tachiyomi.data.database.queries
import com.pushtorefresh.storio.sqlite.queries.Query import com.pushtorefresh.storio.sqlite.queries.Query
import com.pushtorefresh.storio.sqlite.queries.RawQuery
import eu.kanade.tachiyomi.data.database.DbProvider import eu.kanade.tachiyomi.data.database.DbProvider
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaChapter
import eu.kanade.tachiyomi.data.database.resolvers.ChapterProgressPutResolver import eu.kanade.tachiyomi.data.database.resolvers.ChapterProgressPutResolver
import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterGetResolver
import eu.kanade.tachiyomi.data.database.tables.ChapterTable import eu.kanade.tachiyomi.data.database.tables.ChapterTable
import java.util.Date
interface ChapterQueries : DbProvider { interface ChapterQueries : DbProvider {
@ -24,18 +20,6 @@ interface ChapterQueries : DbProvider {
) )
.prepare() .prepare()
fun getRecentChapters(date: Date) = db.get()
.listOfObjects(MangaChapter::class.java)
.withQuery(
RawQuery.builder()
.query(getRecentsQuery())
.args(date.time)
.observesTables(ChapterTable.TABLE)
.build(),
)
.withGetResolver(MangaChapterGetResolver.INSTANCE)
.prepare()
fun getChapter(id: Long) = db.get() fun getChapter(id: Long) = db.get()
.`object`(Chapter::class.java) .`object`(Chapter::class.java)
.withQuery( .withQuery(

View File

@ -38,19 +38,6 @@ val libraryQuery =
ON MC.${MangaCategory.COL_MANGA_ID} = M.${Manga.COL_ID} ON MC.${MangaCategory.COL_MANGA_ID} = M.${Manga.COL_ID}
""" """
/**
* Query to get the recent chapters of manga from the library up to a date.
*/
fun getRecentsQuery() =
"""
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, * FROM ${Manga.TABLE} JOIN ${Chapter.TABLE}
ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}
WHERE ${Manga.COL_FAVORITE} = 1
AND ${Chapter.COL_DATE_UPLOAD} > ?
AND ${Chapter.COL_DATE_FETCH} > ${Manga.COL_DATE_ADDED}
ORDER BY ${Chapter.COL_DATE_UPLOAD} DESC
"""
fun getLastReadMangaQuery() = fun getLastReadMangaQuery() =
""" """
SELECT ${Manga.TABLE}.*, MAX(${History.TABLE}.${History.COL_LAST_READ}) AS max SELECT ${Manga.TABLE}.*, MAX(${History.TABLE}.${History.COL_LAST_READ}) AS max

View File

@ -2,16 +2,14 @@ package eu.kanade.tachiyomi.ui.manga.chapter.base
import eu.davidea.flexibleadapter.items.AbstractHeaderItem import eu.davidea.flexibleadapter.items.AbstractHeaderItem
import eu.davidea.flexibleadapter.items.AbstractSectionableItem import eu.davidea.flexibleadapter.items.AbstractSectionableItem
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
abstract class BaseChapterItem<T : BaseChapterHolder, H : AbstractHeaderItem<*>>( abstract class BaseChapterItem<T : BaseChapterHolder, H : AbstractHeaderItem<*>>(
val chapter: Chapter, val chapter: Chapter,
header: H? = null, header: H? = null,
) : ) : AbstractSectionableItem<T, H?>(header) {
AbstractSectionableItem<T, H?>(header),
Chapter by chapter {
private var _status: Download.State = Download.State.NOT_DOWNLOADED private var _status: Download.State = Download.State.NOT_DOWNLOADED
@ -36,12 +34,14 @@ abstract class BaseChapterItem<T : BaseChapterHolder, H : AbstractHeaderItem<*>>
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other is BaseChapterItem<*, *>) { if (other is BaseChapterItem<*, *>) {
return chapter.id!! == other.chapter.id!! return chapter.id == other.chapter.id && chapter.read == other.chapter.read
} }
return false return false
} }
override fun hashCode(): Int { override fun hashCode(): Int {
return chapter.id!!.hashCode() var result = chapter.id.hashCode()
result = 31 * result + chapter.read.hashCode()
return result
} }
} }

View File

@ -11,7 +11,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
import dev.chrisbanes.insetter.applyInsetter import dev.chrisbanes.insetter.applyInsetter
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.SelectableAdapter import eu.davidea.flexibleadapter.SelectableAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.DownloadService import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
@ -30,8 +29,10 @@ import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.onAnimationsFinished import eu.kanade.tachiyomi.util.view.onAnimationsFinished
import eu.kanade.tachiyomi.widget.ActionModeWithToolbar import eu.kanade.tachiyomi.widget.ActionModeWithToolbar
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import logcat.LogPriority import logcat.LogPriority
import reactivecircus.flowbinding.recyclerview.scrollStateChanges import reactivecircus.flowbinding.recyclerview.scrollStateChanges
import reactivecircus.flowbinding.swiperefreshlayout.refreshes import reactivecircus.flowbinding.swiperefreshlayout.refreshes
@ -107,6 +108,24 @@ class UpdatesController :
binding.swipeRefresh.isRefreshing = false binding.swipeRefresh.isRefreshing = false
} }
.launchIn(viewScope) .launchIn(viewScope)
viewScope.launch {
presenter.updates.collectLatest { updatesItems ->
destroyActionModeIfNeeded()
if (adapter == null) {
adapter = UpdatesAdapter(this@UpdatesController, binding.recycler.context, updatesItems)
binding.recycler.adapter = adapter
adapter!!.fastScroller = binding.fastScroller
} else {
adapter?.updateDataSet(updatesItems)
}
binding.swipeRefresh.isRefreshing = false
binding.fastScroller.isVisible = true
binding.recycler.onAnimationsFinished {
(activity as? MainActivity)?.ready = true
}
}
}
} }
override fun onDestroyView(view: View) { override fun onDestroyView(view: View) {
@ -191,7 +210,7 @@ class UpdatesController :
*/ */
private fun openChapter(item: UpdatesItem) { private fun openChapter(item: UpdatesItem) {
val activity = activity ?: return val activity = activity ?: return
val intent = ReaderActivity.newIntent(activity, item.manga, item.chapter) val intent = ReaderActivity.newIntent(activity, item.manga.id, item.chapter.id)
startActivity(intent) startActivity(intent)
} }
@ -204,26 +223,6 @@ class UpdatesController :
destroyActionModeIfNeeded() destroyActionModeIfNeeded()
} }
/**
* Populate adapter with chapters
* @param chapters list of [Any]
*/
fun onNextRecentChapters(chapters: List<IFlexible<*>>) {
destroyActionModeIfNeeded()
if (adapter == null) {
adapter = UpdatesAdapter(this@UpdatesController, binding.recycler.context, chapters)
binding.recycler.adapter = adapter
adapter!!.fastScroller = binding.fastScroller
} else {
adapter?.updateDataSet(chapters)
}
binding.swipeRefresh.isRefreshing = false
binding.fastScroller.isVisible = true
binding.recycler.onAnimationsFinished {
(activity as? MainActivity)?.ready = true
}
}
override fun onUpdateEmptyView(size: Int) { override fun onUpdateEmptyView(size: Int) {
if (size > 0) { if (size > 0) {
binding.emptyView.hide() binding.emptyView.hide()
@ -317,8 +316,8 @@ class UpdatesController :
} }
override fun startDownloadNow(position: Int) { override fun startDownloadNow(position: Int) {
val chapter = adapter?.getItem(position) as? UpdatesItem ?: return val item = adapter?.getItem(position) as? UpdatesItem ?: return
presenter.startDownloadingNow(chapter) presenter.startDownloadingNow(item.chapter)
} }
private fun bookmarkChapters(chapters: List<UpdatesItem>, bookmarked: Boolean) { private fun bookmarkChapters(chapters: List<UpdatesItem>, bookmarked: Boolean) {
@ -357,8 +356,8 @@ class UpdatesController :
if (chapters.isEmpty()) return if (chapters.isEmpty()) return
toolbar.findToolbarItem(R.id.action_download)?.isVisible = chapters.any { !it.isDownloaded } toolbar.findToolbarItem(R.id.action_download)?.isVisible = chapters.any { !it.isDownloaded }
toolbar.findToolbarItem(R.id.action_delete)?.isVisible = chapters.any { it.isDownloaded } toolbar.findToolbarItem(R.id.action_delete)?.isVisible = chapters.any { it.isDownloaded }
toolbar.findToolbarItem(R.id.action_bookmark)?.isVisible = chapters.any { !it.bookmark } toolbar.findToolbarItem(R.id.action_bookmark)?.isVisible = chapters.any { !it.chapter.bookmark }
toolbar.findToolbarItem(R.id.action_remove_bookmark)?.isVisible = chapters.all { it.bookmark } toolbar.findToolbarItem(R.id.action_remove_bookmark)?.isVisible = chapters.all { it.chapter.bookmark }
toolbar.findToolbarItem(R.id.action_mark_as_read)?.isVisible = chapters.any { !it.chapter.read } toolbar.findToolbarItem(R.id.action_mark_as_read)?.isVisible = chapters.any { !it.chapter.read }
toolbar.findToolbarItem(R.id.action_mark_as_unread)?.isVisible = chapters.all { it.chapter.read } toolbar.findToolbarItem(R.id.action_mark_as_unread)?.isVisible = chapters.all { it.chapter.read }
} }

View File

@ -44,12 +44,12 @@ class UpdatesHolder(private val view: View, private val adapter: UpdatesAdapter)
} else { } else {
binding.mangaTitle.setTextColor(adapter.unreadColor) binding.mangaTitle.setTextColor(adapter.unreadColor)
binding.chapterTitle.setTextColor( binding.chapterTitle.setTextColor(
if (item.bookmark) adapter.bookmarkedColor else adapter.unreadColorSecondary, if (item.chapter.bookmark) adapter.bookmarkedColor else adapter.unreadColorSecondary,
) )
} }
// Set bookmark status // Set bookmark status
binding.bookmarkIcon.isVisible = item.bookmark binding.bookmarkIcon.isVisible = item.chapter.bookmark
// Set chapter status // Set chapter status
binding.download.isVisible = item.manga.source != LocalSource.ID binding.download.isVisible = item.manga.source != LocalSource.ID

View File

@ -4,9 +4,9 @@ import android.view.View
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.manga.model.Manga
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChapterItem import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChapterItem
import eu.kanade.tachiyomi.ui.recent.DateSectionItem import eu.kanade.tachiyomi.ui.recent.DateSectionItem

View File

@ -1,17 +1,28 @@
package eu.kanade.tachiyomi.ui.recent.updates package eu.kanade.tachiyomi.ui.recent.updates
import android.os.Bundle import android.os.Bundle
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.data.DatabaseHandler
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.data.manga.mangaChapterMapper
import eu.kanade.tachiyomi.data.database.models.MangaChapter import eu.kanade.domain.chapter.interactor.UpdateChapter
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.chapter.model.ChapterUpdate
import eu.kanade.domain.chapter.model.toDbChapter
import eu.kanade.domain.manga.model.Manga
import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.recent.DateSectionItem import eu.kanade.tachiyomi.ui.recent.DateSectionItem
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.toDateKey import eu.kanade.tachiyomi.util.lang.toDateKey
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.map
import logcat.LogPriority import logcat.LogPriority
import rx.Observable import rx.Observable
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
@ -25,24 +36,22 @@ import java.util.TreeMap
class UpdatesPresenter : BasePresenter<UpdatesController>() { class UpdatesPresenter : BasePresenter<UpdatesController>() {
val preferences: PreferencesHelper by injectLazy() val preferences: PreferencesHelper by injectLazy()
private val db: DatabaseHelper by injectLazy()
private val downloadManager: DownloadManager by injectLazy() private val downloadManager: DownloadManager by injectLazy()
private val sourceManager: SourceManager by injectLazy() private val sourceManager: SourceManager by injectLazy()
private val handler: DatabaseHandler by injectLazy()
private val updateChapter: UpdateChapter by injectLazy()
private val relativeTime: Int = preferences.relativeTime().get() private val relativeTime: Int = preferences.relativeTime().get()
private val dateFormat: DateFormat = preferences.dateFormat() private val dateFormat: DateFormat = preferences.dateFormat()
/** private val _updates: MutableStateFlow<List<UpdatesItem>> = MutableStateFlow(listOf())
* List containing chapter and manga information val updates: StateFlow<List<UpdatesItem>> = _updates.asStateFlow()
*/
private var chapters: List<UpdatesItem> = emptyList()
override fun onCreate(savedState: Bundle?) { override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState) super.onCreate(savedState)
getUpdatesObservable() getUpdatesObservable()
.observeOn(AndroidSchedulers.mainThread())
.subscribeLatestCache(UpdatesController::onNextRecentChapters)
downloadManager.queue.getStatusObservable() downloadManager.queue.getStatusObservable()
.observeOn(Schedulers.io()) .observeOn(Schedulers.io())
@ -72,43 +81,47 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
* *
* @return observable containing recent chapters and date * @return observable containing recent chapters and date
*/ */
private fun getUpdatesObservable(): Observable<List<UpdatesItem>> { private fun getUpdatesObservable() {
// Set date limit for recent chapters // Set date limit for recent chapters
val cal = Calendar.getInstance().apply { presenterScope.launchIO {
time = Date() val cal = Calendar.getInstance().apply {
add(Calendar.MONTH, -3) time = Date()
} add(Calendar.MONTH, -3)
return db.getRecentChapters(cal.time).asRxObservable()
// Convert to a list of recent chapters.
.map { mangaChapters ->
val map = TreeMap<Date, MutableList<MangaChapter>> { d1, d2 -> d2.compareTo(d1) }
val byDay = mangaChapters
.groupByTo(map) { it.chapter.date_fetch.toDateKey() }
byDay.flatMap { entry ->
val dateItem = DateSectionItem(entry.key, relativeTime, dateFormat)
entry.value
.sortedWith(compareBy({ it.chapter.date_fetch }, { it.chapter.chapter_number })).asReversed()
.map { UpdatesItem(it.chapter, it.manga, dateItem) }
}
} }
.doOnNext { list ->
list.forEach { item ->
// Find an active download for this chapter.
val download = downloadManager.queue.find { it.chapter.id == item.chapter.id }
// If there's an active download, assign it, otherwise ask the manager if handler
// the chapter is downloaded and assign it to the status. .subscribeToList {
if (download != null) { mangasQueries.getRecentlyUpdated(after = cal.timeInMillis, mangaChapterMapper)
item.download = download }
.map { mangaChapter ->
val map = TreeMap<Date, MutableList<Pair<Manga, Chapter>>> { d1, d2 -> d2.compareTo(d1) }
val byDate = mangaChapter.groupByTo(map) { it.second.dateFetch.toDateKey() }
byDate.flatMap { entry ->
val dateItem = DateSectionItem(entry.key, relativeTime, dateFormat)
entry.value
.sortedWith(compareBy({ it.second.dateFetch }, { it.second.chapterNumber })).asReversed()
.map { UpdatesItem(it.second, it.first, dateItem) }
} }
} }
setDownloadedChapters(list) .collectLatest { list ->
chapters = list list.forEach { item ->
// Find an active download for this chapter.
val download = downloadManager.queue.find { it.chapter.id == item.chapter.id }
// Set unread chapter count for bottom bar badge // If there's an active download, assign it, otherwise ask the manager if
preferences.unreadUpdatesCount().set(list.count { !it.read }) // the chapter is downloaded and assign it to the status.
} if (download != null) {
item.download = download
}
}
setDownloadedChapters(list)
_updates.value = list
// Set unread chapter count for bottom bar badge
preferences.unreadUpdatesCount().set(list.count { !it.chapter.read })
}
}
} }
/** /**
@ -135,6 +148,7 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
private fun onDownloadStatusChange(download: Download) { private fun onDownloadStatusChange(download: Download) {
// Assign the download to the model object. // Assign the download to the model object.
if (download.status == Download.State.QUEUE) { if (download.status == Download.State.QUEUE) {
val chapters = (view?.adapter?.currentItems ?: emptyList()).filterIsInstance<UpdatesItem>()
val chapter = chapters.find { it.chapter.id == download.chapter.id } val chapter = chapters.find { it.chapter.id == download.chapter.id }
if (chapter != null && chapter.download == null) { if (chapter != null && chapter.download == null) {
chapter.download = download chapter.download = download
@ -153,17 +167,16 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
* @param read read status * @param read read status
*/ */
fun markChapterRead(items: List<UpdatesItem>, read: Boolean) { fun markChapterRead(items: List<UpdatesItem>, read: Boolean) {
val chapters = items.map { it.chapter } presenterScope.launchIO {
chapters.forEach { val toUpdate = items.map {
it.read = read ChapterUpdate(
if (!read) { read = read,
it.last_page_read = 0 lastPageRead = if (!read) 0 else null,
id = it.chapter.id,
)
} }
updateChapter.awaitAll(toUpdate)
} }
Observable.fromCallable { db.updateChaptersProgress(chapters).executeAsBlocking() }
.subscribeOn(Schedulers.io())
.subscribe()
} }
/** /**
@ -190,14 +203,15 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
* @param bookmarked bookmark status * @param bookmarked bookmark status
*/ */
fun bookmarkChapters(items: List<UpdatesItem>, bookmarked: Boolean) { fun bookmarkChapters(items: List<UpdatesItem>, bookmarked: Boolean) {
val chapters = items.map { it.chapter } presenterScope.launchIO {
chapters.forEach { val toUpdate = items.map {
it.bookmark = bookmarked ChapterUpdate(
bookmark = bookmarked,
id = it.chapter.id,
)
}
updateChapter.awaitAll(toUpdate)
} }
Observable.fromCallable { db.updateChaptersProgress(chapters).executeAsBlocking() }
.subscribeOn(Schedulers.io())
.subscribe()
} }
/** /**
@ -205,7 +219,7 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
* @param items list of recent chapters seleted. * @param items list of recent chapters seleted.
*/ */
fun downloadChapters(items: List<UpdatesItem>) { fun downloadChapters(items: List<UpdatesItem>) {
items.forEach { downloadManager.downloadChapters(it.manga, listOf(it.chapter)) } items.forEach { downloadManager.downloadChapters(it.manga.toDbManga(), listOf(it.chapter.toDbChapter())) }
} }
/** /**
@ -216,9 +230,9 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
private fun deleteChaptersInternal(chapterItems: List<UpdatesItem>) { private fun deleteChaptersInternal(chapterItems: List<UpdatesItem>) {
val itemsByManga = chapterItems.groupBy { it.manga.id } val itemsByManga = chapterItems.groupBy { it.manga.id }
for ((_, items) in itemsByManga) { for ((_, items) in itemsByManga) {
val manga = items.first().manga val manga = items.first().manga.toDbManga()
val source = sourceManager.get(manga.source) ?: continue val source = sourceManager.get(manga.source) ?: continue
val chapters = items.map { it.chapter } val chapters = items.map { it.chapter.toDbChapter() }
downloadManager.deleteChapters(chapters, manga, source) downloadManager.deleteChapters(chapters, manga, source)
items.forEach { items.forEach {

View File

@ -76,6 +76,16 @@ FROM mangas
WHERE favorite = 0 WHERE favorite = 0
GROUP BY source; GROUP BY source;
getRecentlyUpdated:
SELECT *
FROM mangas M
JOIN chapters C
ON M._id = C.manga_id
WHERE M.favorite = 1
AND C.date_upload > :after
AND C.date_fetch > M.date_added
ORDER BY C.date_upload DESC;
deleteMangasNotInLibraryBySourceIds: deleteMangasNotInLibraryBySourceIds:
DELETE FROM mangas DELETE FROM mangas
WHERE favorite = 0 AND source IN :sourceIds; WHERE favorite = 0 AND source IN :sourceIds;