Added Download feature

This commit is contained in:
Pupil
2020-02-01 12:50:26 +09:00
parent 07643e4b4c
commit 874606bff9
5 changed files with 63 additions and 25 deletions

View File

@@ -406,6 +406,7 @@ class MainActivity : AppCompatActivity() {
worker.cancel(galleryID) worker.cancel(galleryID)
else { else {
Cache(context).moveToDownload(galleryID) Cache(context).moveToDownload(galleryID)
Cache(context).setDownloading(galleryID, true)
if (!worker.queue.contains(galleryID)) if (!worker.queue.contains(galleryID))
worker.queue.add(galleryID) worker.queue.add(galleryID)

View File

@@ -38,6 +38,9 @@ import io.fabric.sdk.android.Fabric
import kotlinx.android.synthetic.main.activity_reader.* import kotlinx.android.synthetic.main.activity_reader.*
import kotlinx.android.synthetic.main.activity_reader.view.* import kotlinx.android.synthetic.main.activity_reader.view.*
import kotlinx.android.synthetic.main.dialog_numberpicker.view.* import kotlinx.android.synthetic.main.dialog_numberpicker.view.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.serialization.ImplicitReflectionSerializer import kotlinx.serialization.ImplicitReflectionSerializer
import xyz.quaver.hitomi.Reader import xyz.quaver.hitomi.Reader
import xyz.quaver.pupil.Pupil import xyz.quaver.pupil.Pupil
@@ -46,8 +49,6 @@ import xyz.quaver.pupil.adapters.ReaderAdapter
import xyz.quaver.pupil.util.Histories import xyz.quaver.pupil.util.Histories
import xyz.quaver.pupil.util.download.Cache import xyz.quaver.pupil.util.download.Cache
import xyz.quaver.pupil.util.download.DownloadWorker import xyz.quaver.pupil.util.download.DownloadWorker
import xyz.quaver.pupil.util.getDownloadDirectory
import xyz.quaver.pupil.util.isParentOf
import java.util.* import java.util.*
import kotlin.concurrent.schedule import kotlin.concurrent.schedule
@@ -199,8 +200,8 @@ class ReaderActivity : AppCompatActivity() {
timer.cancel() timer.cancel()
if (!getDownloadDirectory(this).isParentOf(Cache(this).getCachedGallery(galleryID))) if (!Cache(this).isDownloading(galleryID))
DownloadWorker.getInstance(this).cancel(galleryID) DownloadWorker.getInstance(this@ReaderActivity).cancel(galleryID)
} }
override fun onBackPressed() { override fun onBackPressed() {
@@ -253,7 +254,7 @@ class ReaderActivity : AppCompatActivity() {
runOnUiThread { runOnUiThread {
reader_download_progressbar.max = reader_recyclerview.adapter?.itemCount ?: 0 reader_download_progressbar.max = reader_recyclerview.adapter?.itemCount ?: 0
reader_download_progressbar.progress = worker.progress[galleryID]!!.count { !it.isFinite() } reader_download_progressbar.progress = worker.progress[galleryID]?.count { !it.isFinite() } ?: 0
reader_progressbar.max = reader_recyclerview.adapter?.itemCount ?: 0 reader_progressbar.max = reader_recyclerview.adapter?.itemCount ?: 0
if (title == getString(R.string.reader_loading)) { if (title == getString(R.string.reader_loading)) {
@@ -272,7 +273,7 @@ class ReaderActivity : AppCompatActivity() {
} }
} }
if (worker.progress[galleryID]!!.all { !it.isFinite() }) { //Download finished if (worker.progress[galleryID]?.all { !it.isFinite() } == true) { //Download finished
reader_download_progressbar.visibility = View.GONE reader_download_progressbar.visibility = View.GONE
animateDownloadFAB(false) animateDownloadFAB(false)
@@ -318,12 +319,21 @@ class ReaderActivity : AppCompatActivity() {
} }
with(reader_fab_download) { with(reader_fab_download) {
animateDownloadFAB(getDownloadDirectory(context).isParentOf(Cache(context).getCachedGallery(galleryID))) //If download in progress, animate button animateDownloadFAB(Cache(context).isDownloading(galleryID)) //If download in progress, animate button
setOnClickListener { setOnClickListener {
Cache(context).moveToDownload(galleryID) if (Cache(context).isDownloading(galleryID)) {
Cache(context).setDownloading(galleryID, false)
animateDownloadFAB(true) animateDownloadFAB(false)
} else {
CoroutineScope(Dispatchers.IO).launch {
Cache(context).moveToDownload(galleryID)
}
Cache(context).setDownloading(galleryID, true)
animateDownloadFAB(true)
}
} }
} }
@@ -379,7 +389,7 @@ class ReaderActivity : AppCompatActivity() {
setImageResource(R.drawable.ic_download) setImageResource(R.drawable.ic_download)
labelText = getString(R.string.reader_fab_download) labelText = getString(R.string.reader_fab_download)
} }
else // Or continue animating else // Or continue animate
post { post {
icon.start() icon.start()
labelText = getString(R.string.reader_fab_download_cancel) labelText = getString(R.string.reader_fab_download_cancel)
@@ -389,8 +399,10 @@ class ReaderActivity : AppCompatActivity() {
setImageDrawable(icon) setImageDrawable(icon)
icon?.start() icon?.start()
} else } else {
setImageResource(R.drawable.ic_download) setImageResource(R.drawable.ic_download)
labelText = getString(R.string.reader_fab_download)
}
} }
} }
} }

View File

@@ -21,6 +21,7 @@ package xyz.quaver.pupil.util.download
import android.content.Context import android.content.Context
import android.content.ContextWrapper import android.content.ContextWrapper
import android.util.Base64 import android.util.Base64
import android.util.Log
import android.util.SparseArray import android.util.SparseArray
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
@@ -218,4 +219,11 @@ class Cache(context: Context) : ContextWrapper(context) {
File(getDownloadDirectory(this), galleryID.toString()).mkdirs() File(getDownloadDirectory(this), galleryID.toString()).mkdirs()
} }
fun isDownloading(galleryID: Int) = getCachedMetadata(galleryID)?.isDownloading == true
fun setDownloading(galleryID: Int, isDownloading: Boolean) {
Log.i("PUPILD", "$galleryID $isDownloading")
setCachedMetadata(galleryID, Metadata(getCachedMetadata(galleryID), isDownloading = isDownloading))
}
} }

View File

@@ -70,7 +70,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
override fun source(): BufferedSource { override fun source(): BufferedSource {
if (bufferedSource == null) if (bufferedSource == null)
bufferedSource = source(responseBody.source()).buffer() bufferedSource = Okio.buffer(source(responseBody.source()))
return bufferedSource!! return bufferedSource!!
} }
@@ -143,13 +143,12 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
var retry = preferences.getInt("retry", 3) var retry = preferences.getInt("retry", 3)
while (!response.isSuccessful && retry > 0) { while (!response.isSuccessful && retry > 0) {
response.close()
response = chain.proceed(request) response = chain.proceed(request)
retry-- retry--
} }
response.newBuilder() response.newBuilder()
.body(ProgressResponseBody(request.tag(), response.body!!, progressListener)) .body(ProgressResponseBody(request.tag(), response.body(), progressListener))
.build() .build()
} }
.dispatcher(Dispatcher(Executors.newSingleThreadExecutor())) .dispatcher(Dispatcher(Executors.newSingleThreadExecutor()))
@@ -159,21 +158,31 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
queue.clear() queue.clear()
loop.cancel() loop.cancel()
for (i in 0..worker.size()) for (i in 0..worker.size()) {
worker[worker.keyAt(i)]?.cancel() val galleryID = worker.keyAt(i)
client.dispatcher.cancelAll() Cache(this@DownloadWorker).setDownloading(galleryID, false)
worker[galleryID]?.cancel()
}
client.dispatcher().cancelAll()
progress.clear() progress.clear()
exception.clear() exception.clear()
nRunners = 0
} }
fun cancel(galleryID: Int) { fun cancel(galleryID: Int) {
queue.remove(galleryID) queue.remove(galleryID)
worker[galleryID]?.cancel() worker[galleryID]?.cancel()
client.dispatcher.queuedCalls() client.dispatcher().queuedCalls()
.filter { it.request().tag(Pair::class.java)?.first == galleryID } .filter {
@Suppress("UNCHECKED_CAST")
(it.request().tag() as? Pair<Int, Int>)?.first == galleryID
}
.forEach { .forEach {
it.cancel() it.cancel()
} }
@@ -182,6 +191,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
progress.remove(galleryID) progress.remove(galleryID)
exception.remove(galleryID) exception.remove(galleryID)
Cache(this@DownloadWorker).setDownloading(galleryID, false)
nRunners-- nRunners--
} }
} }
@@ -231,6 +241,8 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
if (reader == null) { if (reader == null) {
progress.put(galleryID, null) progress.put(galleryID, null)
exception.put(galleryID, null) exception.put(galleryID, null)
Cache(this@DownloadWorker).setDownloading(galleryID, false)
nRunners-- nRunners--
return@launch return@launch
} }
@@ -251,15 +263,16 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
progress.remove(galleryID) progress.remove(galleryID)
exception.remove(galleryID) exception.remove(galleryID)
Cache(this@DownloadWorker).setDownloading(galleryID, false)
nRunners-- nRunners--
} }
} }
override fun onResponse(call: Call, response: Response) { override fun onResponse(call: Call, response: Response) {
response.use { response.body().use {
val res = it.body!!.bytes() val res = it.bytes()
val ext = val ext =
call.request().url.encodedPath.split('.').last() call.request().url().encodedPath().split('.').last()
Cache(this@DownloadWorker).putImage(galleryID, "$i.$ext", res) Cache(this@DownloadWorker).putImage(galleryID, "$i.$ext", res)
progress[galleryID]?.set(i, Float.POSITIVE_INFINITY) progress[galleryID]?.set(i, Float.POSITIVE_INFINITY)
@@ -269,6 +282,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
progress.remove(galleryID) progress.remove(galleryID)
exception.remove(galleryID) exception.remove(galleryID)
Cache(this@DownloadWorker).setDownloading(galleryID, false)
nRunners-- nRunners--
} }
} }

View File

@@ -26,16 +26,19 @@ import xyz.quaver.hitomi.Reader
data class Metadata( data class Metadata(
val thumbnail: String? = null, val thumbnail: String? = null,
val galleryBlock: GalleryBlock? = null, val galleryBlock: GalleryBlock? = null,
val readers: List<Reader>? = null val readers: List<Reader>? = null,
val isDownloading: Boolean? = null
) { ) {
constructor( constructor(
metadata: Metadata?, metadata: Metadata?,
thumbnail: String? = null, thumbnail: String? = null,
galleryBlock: GalleryBlock? = null, galleryBlock: GalleryBlock? = null,
readers: List<Reader>? = null readers: List<Reader>? = null,
isDownloading: Boolean? = null
) : this( ) : this(
thumbnail ?: metadata?.thumbnail, thumbnail ?: metadata?.thumbnail,
galleryBlock ?: metadata?.galleryBlock, galleryBlock ?: metadata?.galleryBlock,
readers ?: metadata?.readers readers ?: metadata?.readers,
isDownloading ?: metadata?.isDownloading
) )
} }