Refactor download states into enum

This commit is contained in:
arkon 2020-12-27 10:20:14 -05:00
parent 6dd280205b
commit 84ae61f72c
14 changed files with 69 additions and 97 deletions

View File

@ -114,8 +114,8 @@ class Downloader(
initializeSubscriptions() initializeSubscriptions()
} }
val pending = queue.filter { it.status != Download.DOWNLOADED } val pending = queue.filter { it.status != Download.State.DOWNLOADED }
pending.forEach { if (it.status != Download.QUEUE) it.status = Download.QUEUE } pending.forEach { if (it.status != Download.State.QUEUE) it.status = Download.State.QUEUE }
notifier.paused = false notifier.paused = false
@ -129,8 +129,8 @@ class Downloader(
fun stop(reason: String? = null) { fun stop(reason: String? = null) {
destroySubscriptions() destroySubscriptions()
queue queue
.filter { it.status == Download.DOWNLOADING } .filter { it.status == Download.State.DOWNLOADING }
.forEach { it.status = Download.ERROR } .forEach { it.status = Download.State.ERROR }
if (reason != null) { if (reason != null) {
notifier.onWarning(reason) notifier.onWarning(reason)
@ -151,8 +151,8 @@ class Downloader(
fun pause() { fun pause() {
destroySubscriptions() destroySubscriptions()
queue queue
.filter { it.status == Download.DOWNLOADING } .filter { it.status == Download.State.DOWNLOADING }
.forEach { it.status = Download.QUEUE } .forEach { it.status = Download.State.QUEUE }
notifier.paused = true notifier.paused = true
} }
@ -167,8 +167,8 @@ class Downloader(
// Needed to update the chapter view // Needed to update the chapter view
if (isNotification) { if (isNotification) {
queue queue
.filter { it.status == Download.QUEUE } .filter { it.status == Download.State.QUEUE }
.forEach { it.status = Download.NOT_DOWNLOADED } .forEach { it.status = Download.State.NOT_DOWNLOADED }
} }
queue.clear() queue.clear()
notifier.dismissProgress() notifier.dismissProgress()
@ -271,7 +271,7 @@ class Downloader(
val availSpace = DiskUtil.getAvailableStorageSpace(mangaDir) val availSpace = DiskUtil.getAvailableStorageSpace(mangaDir)
if (availSpace != -1L && availSpace < MIN_DISK_SPACE) { if (availSpace != -1L && availSpace < MIN_DISK_SPACE) {
download.status = Download.ERROR download.status = Download.State.ERROR
notifier.onError(context.getString(R.string.download_insufficient_space), download.chapter.name) notifier.onError(context.getString(R.string.download_insufficient_space), download.chapter.name)
return@defer Observable.just(download) return@defer Observable.just(download)
} }
@ -301,7 +301,7 @@ class Downloader(
?.forEach { it.delete() } ?.forEach { it.delete() }
download.downloadedImages = 0 download.downloadedImages = 0
download.status = Download.DOWNLOADING download.status = Download.State.DOWNLOADING
} }
// Get all the URLs to the source images, fetch pages if necessary // Get all the URLs to the source images, fetch pages if necessary
.flatMap { download.source.fetchAllImageUrlsFromPageList(it) } .flatMap { download.source.fetchAllImageUrlsFromPageList(it) }
@ -317,7 +317,7 @@ class Downloader(
.doOnNext { ensureSuccessfulDownload(download, mangaDir, tmpDir, chapterDirname) } .doOnNext { ensureSuccessfulDownload(download, mangaDir, tmpDir, chapterDirname) }
// If the page list threw, it will resume here // If the page list threw, it will resume here
.onErrorReturn { error -> .onErrorReturn { error ->
download.status = Download.ERROR download.status = Download.State.ERROR
notifier.onError(error.message, download.chapter.name) notifier.onError(error.message, download.chapter.name)
download download
} }
@ -457,13 +457,13 @@ class Downloader(
val downloadedImages = tmpDir.listFiles().orEmpty().filterNot { it.name!!.endsWith(".tmp") } val downloadedImages = tmpDir.listFiles().orEmpty().filterNot { it.name!!.endsWith(".tmp") }
download.status = if (downloadedImages.size == download.pages!!.size) { download.status = if (downloadedImages.size == download.pages!!.size) {
Download.DOWNLOADED Download.State.DOWNLOADED
} else { } else {
Download.ERROR Download.State.ERROR
} }
// Only rename the directory if it's downloaded. // Only rename the directory if it's downloaded.
if (download.status == Download.DOWNLOADED) { if (download.status == Download.State.DOWNLOADED) {
tmpDir.renameTo(dirname) tmpDir.renameTo(dirname)
cache.addChapter(dirname, mangaDir, download.manga) cache.addChapter(dirname, mangaDir, download.manga)
@ -476,7 +476,7 @@ class Downloader(
*/ */
private fun completeDownload(download: Download) { private fun completeDownload(download: Download) {
// Delete successful downloads from queue // Delete successful downloads from queue
if (download.status == Download.DOWNLOADED) { if (download.status == Download.State.DOWNLOADED) {
// remove downloaded chapter from queue // remove downloaded chapter from queue
queue.remove(download) queue.remove(download)
} }
@ -489,7 +489,7 @@ class Downloader(
* Returns true if all the queued downloads are in DOWNLOADED or ERROR state. * Returns true if all the queued downloads are in DOWNLOADED or ERROR state.
*/ */
private fun areAllDownloadsFinished(): Boolean { private fun areAllDownloadsFinished(): Boolean {
return queue.none { it.status <= Download.DOWNLOADING } return queue.none { it.status.value <= Download.State.DOWNLOADING.value }
} }
companion object { companion object {

View File

@ -20,7 +20,7 @@ class Download(val source: HttpSource, val manga: Manga, val chapter: Chapter) {
@Volatile @Volatile
@Transient @Transient
var status: Int = 0 var status: State = State.NOT_DOWNLOADED
set(status) { set(status) {
field = status field = status
statusSubject?.onNext(this) statusSubject?.onNext(this)
@ -47,11 +47,11 @@ class Download(val source: HttpSource, val manga: Manga, val chapter: Chapter) {
statusCallback = f statusCallback = f
} }
companion object { enum class State(val value: Int) {
const val NOT_DOWNLOADED = 0 NOT_DOWNLOADED(0),
const val QUEUE = 1 QUEUE(1),
const val DOWNLOADING = 2 DOWNLOADING(2),
const val DOWNLOADED = 3 DOWNLOADED(3),
const val ERROR = 4 ERROR(4),
} }
} }

View File

@ -22,7 +22,7 @@ class DownloadQueue(
downloads.forEach { download -> downloads.forEach { download ->
download.setStatusSubject(statusSubject) download.setStatusSubject(statusSubject)
download.setStatusCallback(::setPagesFor) download.setStatusCallback(::setPagesFor)
download.status = Download.QUEUE download.status = Download.State.QUEUE
} }
queue.addAll(downloads) queue.addAll(downloads)
store.addAll(downloads) store.addAll(downloads)
@ -34,8 +34,8 @@ class DownloadQueue(
store.remove(download) store.remove(download)
download.setStatusSubject(null) download.setStatusSubject(null)
download.setStatusCallback(null) download.setStatusCallback(null)
if (download.status == Download.DOWNLOADING || download.status == Download.QUEUE) { if (download.status == Download.State.DOWNLOADING || download.status == Download.State.QUEUE) {
download.status = Download.NOT_DOWNLOADED download.status = Download.State.NOT_DOWNLOADED
} }
if (removed) { if (removed) {
updatedRelay.call(Unit) updatedRelay.call(Unit)
@ -60,8 +60,8 @@ class DownloadQueue(
queue.forEach { download -> queue.forEach { download ->
download.setStatusSubject(null) download.setStatusSubject(null)
download.setStatusCallback(null) download.setStatusCallback(null)
if (download.status == Download.DOWNLOADING || download.status == Download.QUEUE) { if (download.status == Download.State.DOWNLOADING || download.status == Download.State.QUEUE) {
download.status = Download.NOT_DOWNLOADED download.status = Download.State.NOT_DOWNLOADED
} }
} }
queue.clear() queue.clear()
@ -70,7 +70,7 @@ class DownloadQueue(
} }
fun getActiveDownloads(): Observable<Download> = fun getActiveDownloads(): Observable<Download> =
Observable.from(this).filter { download -> download.status == Download.DOWNLOADING } Observable.from(this).filter { download -> download.status == Download.State.DOWNLOADING }
fun getStatusObservable(): Observable<Download> = statusSubject.onBackpressureBuffer() fun getStatusObservable(): Observable<Download> = statusSubject.onBackpressureBuffer()
@ -79,7 +79,7 @@ class DownloadQueue(
.map { this } .map { this }
private fun setPagesFor(download: Download) { private fun setPagesFor(download: Download) {
if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) { if (download.status == Download.State.DOWNLOADED || download.status == Download.State.ERROR) {
setPagesSubject(download.pages, null) setPagesSubject(download.pages, null)
} }
} }
@ -88,19 +88,19 @@ class DownloadQueue(
return statusSubject.onBackpressureBuffer() return statusSubject.onBackpressureBuffer()
.startWith(getActiveDownloads()) .startWith(getActiveDownloads())
.flatMap { download -> .flatMap { download ->
if (download.status == Download.DOWNLOADING) { if (download.status == Download.State.DOWNLOADING) {
val pageStatusSubject = PublishSubject.create<Int>() val pageStatusSubject = PublishSubject.create<Int>()
setPagesSubject(download.pages, pageStatusSubject) setPagesSubject(download.pages, pageStatusSubject)
return@flatMap pageStatusSubject return@flatMap pageStatusSubject
.onBackpressureBuffer() .onBackpressureBuffer()
.filter { it == Page.READY } .filter { it == Page.READY }
.map { download } .map { download }
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) { } else if (download.status == Download.State.DOWNLOADED || download.status == Download.State.ERROR) {
setPagesSubject(download.pages, null) setPagesSubject(download.pages, null)
} }
Observable.just(download) Observable.just(download)
} }
.filter { it.status == Download.DOWNLOADING } .filter { it.status == Download.State.DOWNLOADING }
} }
private fun setPagesSubject(pages: List<Page>?, subject: PublishSubject<Int>?) { private fun setPagesSubject(pages: List<Page>?, subject: PublishSubject<Int>?) {

View File

@ -172,17 +172,17 @@ class DownloadController :
*/ */
private fun onStatusChange(download: Download) { private fun onStatusChange(download: Download) {
when (download.status) { when (download.status) {
Download.DOWNLOADING -> { Download.State.DOWNLOADING -> {
observeProgress(download) observeProgress(download)
// Initial update of the downloaded pages // Initial update of the downloaded pages
onUpdateDownloadedPages(download) onUpdateDownloadedPages(download)
} }
Download.DOWNLOADED -> { Download.State.DOWNLOADED -> {
unsubscribeProgress(download) unsubscribeProgress(download)
onUpdateProgress(download) onUpdateProgress(download)
onUpdateDownloadedPages(download) onUpdateDownloadedPages(download)
} }
Download.ERROR -> unsubscribeProgress(download) Download.State.ERROR -> unsubscribeProgress(download)
} }
} }

View File

@ -957,7 +957,7 @@ class MangaController :
// OVERFLOW MENU DIALOGS // OVERFLOW MENU DIALOGS
private fun getUnreadChaptersSorted() = presenter.chapters private fun getUnreadChaptersSorted() = presenter.chapters
.filter { !it.read && it.status == Download.NOT_DOWNLOADED } .filter { !it.read && it.status == Download.State.NOT_DOWNLOADED }
.distinctBy { it.name } .distinctBy { it.name }
.sortedByDescending { it.source_order } .sortedByDescending { it.source_order }

View File

@ -328,7 +328,7 @@ class MangaPresenter(
private fun setDownloadedChapters(chapters: List<ChapterItem>) { private fun setDownloadedChapters(chapters: List<ChapterItem>) {
chapters chapters
.filter { downloadManager.isChapterDownloaded(it, manga) } .filter { downloadManager.isChapterDownloaded(it, manga) }
.forEach { it.status = Download.DOWNLOADED } .forEach { it.status = Download.State.DOWNLOADED }
} }
/** /**
@ -416,7 +416,7 @@ class MangaPresenter(
*/ */
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.QUEUE) { if (download.status == Download.State.QUEUE) {
chapters.find { it.id == download.chapter.id }?.let { chapters.find { it.id == download.chapter.id }?.let {
if (it.download == null) { if (it.download == null) {
it.download = download it.download = download
@ -425,7 +425,7 @@ class MangaPresenter(
} }
// Force UI update if downloaded filter active and download finished. // Force UI update if downloaded filter active and download finished.
if (onlyDownloaded() != State.IGNORE && download.status == Download.DOWNLOADED) { if (onlyDownloaded() != State.IGNORE && download.status == Download.State.DOWNLOADED) {
refreshChapters() refreshChapters()
} }
} }
@ -514,7 +514,7 @@ class MangaPresenter(
private fun deleteChaptersInternal(chapters: List<ChapterItem>) { private fun deleteChaptersInternal(chapters: List<ChapterItem>) {
downloadManager.deleteChapters(chapters, manga, source).forEach { downloadManager.deleteChapters(chapters, manga, source).forEach {
if (it is ChapterItem) { if (it is ChapterItem) {
it.status = Download.NOT_DOWNLOADED it.status = Download.State.NOT_DOWNLOADED
it.download = null it.download = null
} }
} }

View File

@ -5,6 +5,7 @@ import android.util.AttributeSet
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.core.view.isVisible import androidx.core.view.isVisible
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.databinding.ChapterDownloadViewBinding import eu.kanade.tachiyomi.databinding.ChapterDownloadViewBinding
class ChapterDownloadView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : class ChapterDownloadView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
@ -17,20 +18,12 @@ class ChapterDownloadView @JvmOverloads constructor(context: Context, attrs: Att
addView(binding.root) addView(binding.root)
} }
fun setState(state: State) { fun setState(state: Download.State) {
binding.downloadIconBorder.isVisible = state == State.DOWNLOAD || state == State.ERROR binding.downloadIconBorder.isVisible = state == Download.State.NOT_DOWNLOADED || state == Download.State.ERROR
binding.downloadIcon.isVisible = state == State.DOWNLOAD || state == State.DOWNLOADING binding.downloadIcon.isVisible = state == Download.State.NOT_DOWNLOADED || state == Download.State.DOWNLOADING
binding.downloadProgress.isVisible = state == State.DOWNLOADING || state == State.QUEUED binding.downloadProgress.isVisible = state == Download.State.DOWNLOADING || state == Download.State.QUEUE
binding.downloadedIcon.isVisible = state == State.DOWNLOADED binding.downloadedIcon.isVisible = state == Download.State.DOWNLOADED
}
enum class State {
DOWNLOAD,
QUEUED,
DOWNLOADING,
ERROR,
DOWNLOADED,
} }
} }

View File

@ -8,7 +8,6 @@ import androidx.core.view.isVisible
import eu.davidea.viewholders.FlexibleViewHolder import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.databinding.ChaptersItemBinding import eu.kanade.tachiyomi.databinding.ChaptersItemBinding
import java.util.Date import java.util.Date
@ -68,16 +67,6 @@ class ChapterHolder(
binding.chapterDescription.text = "" binding.chapterDescription.text = ""
} }
notifyStatus(item.status) binding.download.setState(item.status)
}
private fun notifyStatus(status: Int) = with(binding.download) {
when (status) {
Download.QUEUE -> setState(ChapterDownloadView.State.QUEUED)
Download.DOWNLOADING -> setState(ChapterDownloadView.State.DOWNLOADING)
Download.DOWNLOADED -> setState(ChapterDownloadView.State.DOWNLOADED)
Download.ERROR -> setState(ChapterDownloadView.State.ERROR)
else -> setState(ChapterDownloadView.State.DOWNLOAD)
}
} }
} }

View File

@ -14,9 +14,9 @@ class ChapterItem(val chapter: Chapter, val manga: Manga) :
AbstractFlexibleItem<ChapterHolder>(), AbstractFlexibleItem<ChapterHolder>(),
Chapter by chapter { Chapter by chapter {
private var _status: Int = 0 private var _status: Download.State = Download.State.NOT_DOWNLOADED
var status: Int var status: Download.State
get() = download?.status ?: _status get() = download?.status ?: _status
set(value) { set(value) {
_status = value _status = value
@ -26,7 +26,7 @@ class ChapterItem(val chapter: Chapter, val manga: Manga) :
var download: Download? = null var download: Download? = null
val isDownloaded: Boolean val isDownloaded: Boolean
get() = status == Download.DOWNLOADED get() = status == Download.State.DOWNLOADED
override fun getLayoutRes(): Int { override fun getLayoutRes(): Int {
return R.layout.chapters_item return R.layout.chapters_item

View File

@ -81,18 +81,7 @@ class UpdatesHolder(private val view: View, private val adapter: UpdatesAdapter)
.into(binding.mangaCover) .into(binding.mangaCover)
} }
/** fun notifyStatus(state: Download.State) {
* Updates chapter status in view. binding.download.setState(state)
*
* @param status download status
*/
fun notifyStatus(status: Int) = with(binding.downloadText) {
when (status) {
Download.QUEUE -> setText(R.string.chapter_queued)
Download.DOWNLOADING -> setText(R.string.chapter_downloading)
Download.DOWNLOADED -> setText(R.string.chapter_downloaded)
Download.ERROR -> setText(R.string.chapter_error)
else -> text = ""
}
} }
} }

View File

@ -14,9 +14,9 @@ import eu.kanade.tachiyomi.ui.recent.DateSectionItem
class UpdatesItem(val chapter: Chapter, val manga: Manga, header: DateSectionItem) : class UpdatesItem(val chapter: Chapter, val manga: Manga, header: DateSectionItem) :
AbstractSectionableItem<UpdatesHolder, DateSectionItem>(header) { AbstractSectionableItem<UpdatesHolder, DateSectionItem>(header) {
private var _status: Int = 0 private var _status: Download.State = Download.State.NOT_DOWNLOADED
var status: Int var status: Download.State
get() = download?.status ?: _status get() = download?.status ?: _status
set(value) { set(value) {
_status = value _status = value
@ -26,7 +26,7 @@ class UpdatesItem(val chapter: Chapter, val manga: Manga, header: DateSectionIte
var download: Download? = null var download: Download? = null
val isDownloaded: Boolean val isDownloaded: Boolean
get() = status == Download.DOWNLOADED get() = status == Download.State.DOWNLOADED
override fun getLayoutRes(): Int { override fun getLayoutRes(): Int {
return R.layout.updates_item return R.layout.updates_item

View File

@ -108,7 +108,7 @@ class UpdatesPresenter(
val chapter = item.chapter val chapter = item.chapter
if (downloadManager.isChapterDownloaded(chapter, manga)) { if (downloadManager.isChapterDownloaded(chapter, manga)) {
item.status = Download.DOWNLOADED item.status = Download.State.DOWNLOADED
} }
} }
} }
@ -120,7 +120,7 @@ class UpdatesPresenter(
*/ */
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.QUEUE) { if (download.status == Download.State.QUEUE) {
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
@ -188,7 +188,7 @@ class UpdatesPresenter(
downloadManager.deleteChapters(chapters, manga, source) downloadManager.deleteChapters(chapters, manga, source)
items.forEach { items.forEach {
it.status = Download.NOT_DOWNLOADED it.status = Download.State.NOT_DOWNLOADED
it.download = null it.download = null
} }
} }

View File

@ -31,6 +31,7 @@
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:paddingEnd="8dp"
app:layout_constraintEnd_toStartOf="@+id/download" app:layout_constraintEnd_toStartOf="@+id/download"
app:layout_constraintStart_toEndOf="@+id/bookmark_icon" app:layout_constraintStart_toEndOf="@+id/bookmark_icon"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@ -43,6 +44,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:ellipsize="end" android:ellipsize="end"
android:paddingEnd="8dp"
android:singleLine="true" android:singleLine="true"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/download" app:layout_constraintEnd_toStartOf="@+id/download"

View File

@ -27,9 +27,10 @@
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:paddingEnd="8dp"
android:textAppearance="@style/TextAppearance.Regular.Body1" android:textAppearance="@style/TextAppearance.Regular.Body1"
app:layout_constraintBottom_toTopOf="@+id/chapter_title" app:layout_constraintBottom_toTopOf="@+id/chapter_title"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toStartOf="@+id/download"
app:layout_constraintStart_toEndOf="@+id/manga_cover" app:layout_constraintStart_toEndOf="@+id/manga_cover"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" app:layout_constraintVertical_chainStyle="packed"
@ -43,22 +44,20 @@
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:paddingEnd="8dp"
android:textAppearance="@style/TextAppearance.Regular.Caption" android:textAppearance="@style/TextAppearance.Regular.Caption"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/download_text" app:layout_constraintEnd_toStartOf="@+id/download"
app:layout_constraintStart_toEndOf="@+id/manga_cover" app:layout_constraintStart_toEndOf="@+id/manga_cover"
app:layout_constraintTop_toBottomOf="@+id/manga_title" app:layout_constraintTop_toBottomOf="@+id/manga_title"
tools:text="Chapter title" /> tools:text="Chapter title" />
<TextView <eu.kanade.tachiyomi.ui.manga.chapter.ChapterDownloadView
android:id="@+id/download_text" android:id="@+id/download"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAllCaps="true" app:layout_constraintTop_toTopOf="parent"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintTop_toBottomOf="@+id/manga_title"
tools:text="Downloaded" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>