|
|
|
@ -17,31 +17,30 @@ import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
|
|
|
|
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.withUIContext
|
|
|
|
|
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.catch
|
|
|
|
|
import kotlinx.coroutines.flow.collectLatest
|
|
|
|
|
import kotlinx.coroutines.flow.map
|
|
|
|
|
import logcat.LogPriority
|
|
|
|
|
import rx.Observable
|
|
|
|
|
import rx.android.schedulers.AndroidSchedulers
|
|
|
|
|
import rx.schedulers.Schedulers
|
|
|
|
|
import uy.kohesive.injekt.injectLazy
|
|
|
|
|
import uy.kohesive.injekt.Injekt
|
|
|
|
|
import uy.kohesive.injekt.api.get
|
|
|
|
|
import java.text.DateFormat
|
|
|
|
|
import java.util.Calendar
|
|
|
|
|
import java.util.Date
|
|
|
|
|
import java.util.TreeMap
|
|
|
|
|
|
|
|
|
|
class UpdatesPresenter : BasePresenter<UpdatesController>() {
|
|
|
|
|
|
|
|
|
|
val preferences: PreferencesHelper by injectLazy()
|
|
|
|
|
private val downloadManager: DownloadManager by injectLazy()
|
|
|
|
|
private val sourceManager: SourceManager by injectLazy()
|
|
|
|
|
|
|
|
|
|
private val handler: DatabaseHandler by injectLazy()
|
|
|
|
|
private val updateChapter: UpdateChapter by injectLazy()
|
|
|
|
|
private val setReadStatus: SetReadStatus by injectLazy()
|
|
|
|
|
class UpdatesPresenter(
|
|
|
|
|
private val preferences: PreferencesHelper = Injekt.get(),
|
|
|
|
|
private val downloadManager: DownloadManager = Injekt.get(),
|
|
|
|
|
private val sourceManager: SourceManager = Injekt.get(),
|
|
|
|
|
private val handler: DatabaseHandler = Injekt.get(),
|
|
|
|
|
private val updateChapter: UpdateChapter = Injekt.get(),
|
|
|
|
|
private val setReadStatus: SetReadStatus = Injekt.get(),
|
|
|
|
|
) : BasePresenter<UpdatesController>() {
|
|
|
|
|
|
|
|
|
|
private val relativeTime: Int = preferences.relativeTime().get()
|
|
|
|
|
private val dateFormat: DateFormat = preferences.dateFormat()
|
|
|
|
@ -52,77 +51,70 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
|
|
|
|
|
override fun onCreate(savedState: Bundle?) {
|
|
|
|
|
super.onCreate(savedState)
|
|
|
|
|
|
|
|
|
|
getUpdatesObservable()
|
|
|
|
|
|
|
|
|
|
downloadManager.queue.getStatusObservable()
|
|
|
|
|
.observeOn(Schedulers.io())
|
|
|
|
|
.onBackpressureBuffer()
|
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
|
|
|
.subscribeLatestCache(
|
|
|
|
|
{ view, it ->
|
|
|
|
|
onDownloadStatusChange(it)
|
|
|
|
|
view.onChapterDownloadUpdate(it)
|
|
|
|
|
},
|
|
|
|
|
{ _, error ->
|
|
|
|
|
logcat(LogPriority.ERROR, error)
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
presenterScope.launchIO {
|
|
|
|
|
subscribeToUpdates()
|
|
|
|
|
|
|
|
|
|
downloadManager.queue.getStatusAsFlow()
|
|
|
|
|
.catch { error -> logcat(LogPriority.ERROR, error) }
|
|
|
|
|
.collectLatest {
|
|
|
|
|
withUIContext {
|
|
|
|
|
onDownloadStatusChange(it)
|
|
|
|
|
view?.onChapterDownloadUpdate(it)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
downloadManager.queue.getProgressObservable()
|
|
|
|
|
.observeOn(Schedulers.io())
|
|
|
|
|
.onBackpressureBuffer()
|
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
|
|
|
.subscribeLatestCache(UpdatesController::onChapterDownloadUpdate) { _, error ->
|
|
|
|
|
logcat(LogPriority.ERROR, error)
|
|
|
|
|
}
|
|
|
|
|
downloadManager.queue.getProgressAsFlow()
|
|
|
|
|
.catch { error -> logcat(LogPriority.ERROR, error) }
|
|
|
|
|
.collectLatest {
|
|
|
|
|
withUIContext {
|
|
|
|
|
view?.onChapterDownloadUpdate(it)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get observable containing recent chapters and date
|
|
|
|
|
*
|
|
|
|
|
* @return observable containing recent chapters and date
|
|
|
|
|
*/
|
|
|
|
|
private fun getUpdatesObservable() {
|
|
|
|
|
private suspend fun subscribeToUpdates() {
|
|
|
|
|
// Set date limit for recent chapters
|
|
|
|
|
presenterScope.launchIO {
|
|
|
|
|
val cal = Calendar.getInstance().apply {
|
|
|
|
|
time = Date()
|
|
|
|
|
add(Calendar.MONTH, -3)
|
|
|
|
|
}
|
|
|
|
|
val cal = Calendar.getInstance().apply {
|
|
|
|
|
time = Date()
|
|
|
|
|
add(Calendar.MONTH, -3)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handler
|
|
|
|
|
.subscribeToList {
|
|
|
|
|
mangasQueries.getRecentlyUpdated(after = cal.timeInMillis, mangaChapterMapper)
|
|
|
|
|
handler
|
|
|
|
|
.subscribeToList {
|
|
|
|
|
mangasQueries.getRecentlyUpdated(after = cal.timeInMillis, mangaChapterMapper)
|
|
|
|
|
}
|
|
|
|
|
.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) }
|
|
|
|
|
}
|
|
|
|
|
.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) }
|
|
|
|
|
}
|
|
|
|
|
.collectLatest { 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
|
|
|
|
|
// the chapter is downloaded and assign it to the status.
|
|
|
|
|
if (download != null) {
|
|
|
|
|
item.download = download
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.collectLatest { 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
|
|
|
|
|
// the chapter is downloaded and assign it to the status.
|
|
|
|
|
if (download != null) {
|
|
|
|
|
item.download = download
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
setDownloadedChapters(list)
|
|
|
|
|
setDownloadedChapters(list)
|
|
|
|
|
|
|
|
|
|
_updates.value = list
|
|
|
|
|
_updates.value = list
|
|
|
|
|
|
|
|
|
|
// Set unread chapter count for bottom bar badge
|
|
|
|
|
preferences.unreadUpdatesCount().set(list.count { !it.chapter.read })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Set unread chapter count for bottom bar badge
|
|
|
|
|
preferences.unreadUpdatesCount().set(list.count { !it.chapter.read })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -184,16 +176,14 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
|
|
|
|
|
* @param chapters list of chapters
|
|
|
|
|
*/
|
|
|
|
|
fun deleteChapters(chapters: List<UpdatesItem>) {
|
|
|
|
|
Observable.just(chapters)
|
|
|
|
|
.doOnNext { deleteChaptersInternal(it) }
|
|
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
|
|
|
.subscribeFirst(
|
|
|
|
|
{ view, _ ->
|
|
|
|
|
view.onChaptersDeleted()
|
|
|
|
|
},
|
|
|
|
|
UpdatesController::onChaptersDeletedError,
|
|
|
|
|
)
|
|
|
|
|
launchIO {
|
|
|
|
|
try {
|
|
|
|
|
deleteChaptersInternal(chapters)
|
|
|
|
|
withUIContext { view?.onChaptersDeleted() }
|
|
|
|
|
} catch (e: Throwable) {
|
|
|
|
|
withUIContext { view?.onChaptersDeletedError(e) }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|