From 10712e6e625e1ee94a454ba980504a2108a9edb1 Mon Sep 17 00:00:00 2001 From: Pupil Date: Tue, 28 Jan 2020 10:48:31 +0900 Subject: [PATCH] Rebuilding Downloader --- .idea/vcs.xml | 1 - .../pupil/adapters/GalleryBlockAdapter.kt | 3 + .../xyz/quaver/pupil/util/download/Cache.kt | 91 ++++++++++--------- .../pupil/util/download/DownloadWorker.kt | 53 +++++++---- .../quaver/pupil/util/download/Metadata.kt | 19 +++- 5 files changed, 103 insertions(+), 64 deletions(-) diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 56883e31..35eb1ddf 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,6 +2,5 @@ - \ No newline at end of file diff --git a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt index eccc0556..f0022d54 100644 --- a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt +++ b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt @@ -19,6 +19,7 @@ package xyz.quaver.pupil.adapters import android.graphics.drawable.Drawable +import android.util.Log import android.util.SparseBooleanArray import android.view.LayoutInflater import android.view.View @@ -129,6 +130,8 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri with(view.galleryblock_progressbar) { progress = imageCache.invoke().list()?.size ?: 0 + Log.i("PUPILD", progress.toString()) + if (!readerCache.invoke().exists()) { visibility = View.GONE max = 0 diff --git a/app/src/main/java/xyz/quaver/pupil/util/download/Cache.kt b/app/src/main/java/xyz/quaver/pupil/util/download/Cache.kt index 6950c037..5a78d329 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/download/Cache.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/download/Cache.kt @@ -21,6 +21,8 @@ package xyz.quaver.pupil.util.download import android.content.Context import android.content.ContextWrapper import androidx.core.content.ContextCompat +import androidx.preference.PreferenceManager +import kotlinx.coroutines.* import kotlinx.serialization.ImplicitReflectionSerializer import kotlinx.serialization.json.Json import kotlinx.serialization.parse @@ -31,6 +33,8 @@ import java.io.File class Cache(context: Context) : ContextWrapper(context) { + private val preference = PreferenceManager.getDefaultSharedPreferences(this) + // Search in this order // Download -> Cache fun getCachedGallery(galleryID: Int) : File? { @@ -81,62 +85,63 @@ class Cache(context: Context) : ContextWrapper(context) { } } - fun getGalleryBlock(galleryID: Int): GalleryBlock { - var meta = Cache(this).getCachedMetadata(galleryID) + suspend fun getGalleryBlock(galleryID: Int): GalleryBlock? { + val metadata = Cache(this).getCachedMetadata(galleryID) - if (meta == null) { - meta = Metadata(galleryBlock = xyz.quaver.hitomi.getGalleryBlock(galleryID)) + val galleryBlock = if (metadata?.galleryBlock == null) + withContext(Dispatchers.IO) { + try { + xyz.quaver.hitomi.getGalleryBlock(galleryID) + } catch (e: Exception) { + null + } + } + else + metadata.galleryBlock - Cache(this).setCachedMetadata( - galleryID, - meta - ) - } else if (meta.galleryBlock == null) - Cache(this).setCachedMetadata( - galleryID, - meta.apply { - galleryBlock = xyz.quaver.hitomi.getGalleryBlock(galleryID) - } - ) + setCachedMetadata( + galleryID, + Metadata(metadata, galleryBlock = galleryBlock) + ) - return meta.galleryBlock!! + return galleryBlock } - fun getReaders(galleryID: Int): List { - var meta = getCachedMetadata(galleryID) + suspend fun getReader(galleryID: Int): Reader? { + val metadata = getCachedMetadata(galleryID) - if (meta == null) { - meta = Metadata(reader = mutableListOf(xyz.quaver.hitomi.getReader(galleryID))) - - setCachedMetadata( - galleryID, - meta - ) - } else if (meta.reader == null) - setCachedMetadata( - galleryID, - meta.apply { - reader = mutableListOf(xyz.quaver.hitomi.getReader(galleryID)) + val readers = if (metadata?.readers == null) { + listOf( + { xyz.quaver.hitomi.getReader(galleryID) }, + { xyz.quaver.hiyobi.getReader(galleryID) } + ).map { + CoroutineScope(Dispatchers.IO).async { + try { + it.invoke() + } catch (e: Exception) { + null + } } - ) - else if (!meta.reader!!.any { it.code == Reader.Code.HITOMI }) + }.awaitAll().filterNotNull() + } else { + metadata.readers + } + + if (readers.isNotEmpty()) setCachedMetadata( galleryID, - meta.apply { - reader!!.add(xyz.quaver.hitomi.getReader(galleryID)) - } + Metadata(metadata, readers = readers) ) - return meta.reader!! + val mirrors = preference.getString("mirrors", "")!!.split('>') + + return readers.firstOrNull { + mirrors.contains(it.code.name) + } } - fun getImage(galleryID: Int, index: Int): File { - val cache = getCachedGallery(galleryID) - - if (cache == null) - ;//TODO: initiate image download - - return File(cache, "%04d".format(index)) + suspend fun getImage(galleryID: Int): File? { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } } \ No newline at end of file diff --git a/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt b/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt index 38d41a94..c0b3b9f6 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt @@ -20,24 +20,26 @@ package xyz.quaver.pupil.util.download import android.content.Context import android.content.ContextWrapper -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.asCoroutineDispatcher +import androidx.preference.PreferenceManager +import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.launch import okhttp3.OkHttpClient import okhttp3.ResponseBody import okio.* import java.util.concurrent.Executors +@UseExperimental(ExperimentalCoroutinesApi::class) class DownloadWorker(context: Context) : ContextWrapper(context) { + val preferences = PreferenceManager.getDefaultSharedPreferences(context) + + //region ProgressListener interface ProgressListener { - fun update(bytesRead : Long, contentLength: Long, done: Boolean) + fun update(tag: Any?, bytesRead : Long, contentLength: Long, done: Boolean) } - //region ProgressResponseBody class ProgressResponseBody( + val tag: Any?, val responseBody: ResponseBody, val progressListener : ProgressListener ) : ResponseBody() { @@ -61,7 +63,7 @@ class DownloadWorker(context: Context) : ContextWrapper(context) { val bytesRead = super.read(sink, byteCount) totalBytesRead += if (bytesRead == -1L) 0L else bytesRead - progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1L) + progressListener.update(tag, totalBytesRead, responseBody.contentLength(), bytesRead == -1L) return bytesRead } @@ -71,28 +73,47 @@ class DownloadWorker(context: Context) : ContextWrapper(context) { //endregion val queue = Channel() - val worker = Executors.newFixedThreadPool(4).asCoroutineDispatcher() + val progress = mutableMapOf() + val worker = Executors.newCachedThreadPool().asCoroutineDispatcher() val progressListener = object: ProgressListener { - override fun update(bytesRead: Long, contentLength: Long, done: Boolean) { + override fun update(tag: Any?, bytesRead: Long, contentLength: Long, done: Boolean) { } } val client = OkHttpClient.Builder() .addNetworkInterceptor { chain -> - chain.proceed(chain.request()).let { originalResponse -> - originalResponse.newBuilder() - .body(ProgressResponseBody(originalResponse.body!!, progressListener)) - .build() + val request = chain.request() + var response = chain.proceed(request) + + var retry = preferences.getInt("retry", 3) + while (!response.isSuccessful && retry > 0) { + response = chain.proceed(request) + retry-- } + + response.newBuilder() + .body(ProgressResponseBody(request.tag(), response.body!!, progressListener)) + .build() }.build() init { - CoroutineScope(Dispatchers.IO).launch { - while (true) { + val maxThread = preferences.getInt("max_thread", 4) + + CoroutineScope(Dispatchers.Unconfined).launch { + while (!(queue.isEmpty && queue.isClosedForReceive)) { + val lowQuality = preferences.getBoolean("low_quality", false) val galleryID = queue.receive() - val reader = Cache(context).getReaders(galleryID) + launch(Dispatchers.IO) { + val reader = Cache(context).getReader(galleryID) ?: return@launch + + reader.galleryInfo.forEachIndexed { index, galleryInfo -> + when(reader.code) { + + } + } + } } } } diff --git a/app/src/main/java/xyz/quaver/pupil/util/download/Metadata.kt b/app/src/main/java/xyz/quaver/pupil/util/download/Metadata.kt index bf5249e2..0ea2a129 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/download/Metadata.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/download/Metadata.kt @@ -24,7 +24,18 @@ import xyz.quaver.hitomi.Reader @Serializable data class Metadata( - var thumbnail: String? = null, - var galleryBlock: GalleryBlock? = null, - var reader: MutableList? = null -) \ No newline at end of file + val thumbnail: String? = null, + val galleryBlock: GalleryBlock? = null, + val readers: List? = null +) { + constructor( + metadata: Metadata?, + thumbnail: String? = null, + galleryBlock: GalleryBlock? = null, + readers: List? = null + ) : this( + thumbnail ?: metadata?.thumbnail, + galleryBlock ?: metadata?.galleryBlock, + readers ?: metadata?.readers + ) +} \ No newline at end of file