Rebuilding Downloader

This commit is contained in:
Pupil
2020-01-28 10:48:31 +09:00
parent d73dc19d3d
commit 10712e6e62
5 changed files with 103 additions and 64 deletions

1
.idea/vcs.xml generated
View File

@@ -2,6 +2,5 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/gh-pages" vcs="Git" />
</component>
</project>

View File

@@ -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

View File

@@ -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<Reader> {
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.
}
}

View File

@@ -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<Int>()
val worker = Executors.newFixedThreadPool(4).asCoroutineDispatcher()
val progress = mutableMapOf<String, Double>()
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) {
}
}
}
}
}
}

View File

@@ -24,7 +24,18 @@ import xyz.quaver.hitomi.Reader
@Serializable
data class Metadata(
var thumbnail: String? = null,
var galleryBlock: GalleryBlock? = null,
var reader: MutableList<Reader>? = null
)
val thumbnail: String? = null,
val galleryBlock: GalleryBlock? = null,
val readers: List<Reader>? = null
) {
constructor(
metadata: Metadata?,
thumbnail: String? = null,
galleryBlock: GalleryBlock? = null,
readers: List<Reader>? = null
) : this(
thumbnail ?: metadata?.thumbnail,
galleryBlock ?: metadata?.galleryBlock,
readers ?: metadata?.readers
)
}