Rebuilding Downloader
This commit is contained in:
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@@ -2,6 +2,5 @@
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/gh-pages" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user