Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03444f070f | ||
|
|
2f1a63eb64 | ||
|
|
9d0898b26c | ||
|
|
994aa99797 | ||
|
|
8204a15276 |
@@ -19,8 +19,8 @@ android {
|
|||||||
applicationId "xyz.quaver.pupil"
|
applicationId "xyz.quaver.pupil"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 42
|
versionCode 43
|
||||||
versionName "4.6"
|
versionName "4.7-beta1"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":42,"versionName":"4.6","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
|
[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":43,"versionName":"4.7-beta1","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
|
||||||
@@ -119,8 +119,9 @@ class ReaderAdapter(private val context: Context,
|
|||||||
holder.view.reader_index.text = (position+1).toString()
|
holder.view.reader_index.text = (position+1).toString()
|
||||||
|
|
||||||
val images = Cache(context).getImage(galleryID, position)
|
val images = Cache(context).getImage(galleryID, position)
|
||||||
|
val progress = DownloadWorker.getInstance(context).progress[galleryID]?.get(position)
|
||||||
|
|
||||||
if (images != null) {
|
if (progress?.isInfinite() == true && images != null) {
|
||||||
glide
|
glide
|
||||||
.load(images)
|
.load(images)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
@@ -132,8 +133,6 @@ class ReaderAdapter(private val context: Context,
|
|||||||
}
|
}
|
||||||
.into(holder.view.image)
|
.into(holder.view.image)
|
||||||
} else {
|
} else {
|
||||||
val progress = DownloadWorker.getInstance(context).progress[galleryID]?.get(position)
|
|
||||||
|
|
||||||
if (progress?.isNaN() == true) {
|
if (progress?.isNaN() == true) {
|
||||||
if (Fabric.isInitialized())
|
if (Fabric.isInitialized())
|
||||||
Crashlytics.logException(DownloadWorker.getInstance(context).exception[galleryID]?.get(position))
|
Crashlytics.logException(DownloadWorker.getInstance(context).exception[galleryID]?.get(position))
|
||||||
|
|||||||
@@ -27,13 +27,16 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.io.InputStream
|
||||||
import xyz.quaver.Code
|
import xyz.quaver.Code
|
||||||
import xyz.quaver.hitomi.GalleryBlock
|
import xyz.quaver.hitomi.GalleryBlock
|
||||||
import xyz.quaver.hitomi.Reader
|
import xyz.quaver.hitomi.Reader
|
||||||
|
import xyz.quaver.proxy
|
||||||
import xyz.quaver.pupil.util.getCachedGallery
|
import xyz.quaver.pupil.util.getCachedGallery
|
||||||
import xyz.quaver.pupil.util.getDownloadDirectory
|
import xyz.quaver.pupil.util.getDownloadDirectory
|
||||||
import xyz.quaver.pupil.util.json
|
import xyz.quaver.pupil.util.json
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
class Cache(context: Context) : ContextWrapper(context) {
|
class Cache(context: Context) : ContextWrapper(context) {
|
||||||
@@ -78,7 +81,9 @@ class Cache(context: Context) : ContextWrapper(context) {
|
|||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val thumbnails = getGalleryBlock(galleryID)?.thumbnails
|
val thumbnails = getGalleryBlock(galleryID)?.thumbnails
|
||||||
try {
|
try {
|
||||||
Base64.encodeToString(URL(thumbnails?.firstOrNull()).readBytes(), Base64.DEFAULT)
|
Base64.encodeToString(URL(thumbnails?.firstOrNull()).openConnection(proxy).getInputStream().use {
|
||||||
|
it.readBytes()
|
||||||
|
}, Base64.DEFAULT)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@@ -212,16 +217,13 @@ class Cache(context: Context) : ContextWrapper(context) {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putImage(galleryID: Int, name: String, data: ByteArray) {
|
fun putImage(galleryID: Int, index: Int, ext: String, data: InputStream) {
|
||||||
val cache = File(getCachedGallery(galleryID), name).also {
|
val cache = File(getCachedGallery(galleryID), "%05d.$ext".format(index)).also {
|
||||||
if (!it.exists())
|
if (!it.exists())
|
||||||
it.createNewFile()
|
it.createNewFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Regex("""^[0-9]+.+$""").matches(name))
|
data.copyTo(FileOutputStream(cache))
|
||||||
throw IllegalArgumentException("File name is not a number")
|
|
||||||
|
|
||||||
cache.writeBytes(data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun moveToDownload(galleryID: Int) {
|
fun moveToDownload(galleryID: Int) {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.content.Context
|
|||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
import android.util.Log
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
@@ -46,6 +47,7 @@ import xyz.quaver.pupil.ui.ReaderActivity
|
|||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import java.util.concurrent.LinkedBlockingQueue
|
import java.util.concurrent.LinkedBlockingQueue
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@UseExperimental(ExperimentalCoroutinesApi::class)
|
@UseExperimental(ExperimentalCoroutinesApi::class)
|
||||||
class DownloadWorker private constructor(context: Context) : ContextWrapper(context) {
|
class DownloadWorker private constructor(context: Context) : ContextWrapper(context) {
|
||||||
@@ -153,12 +155,14 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
|||||||
val response = chain.proceed(request)
|
val response = chain.proceed(request)
|
||||||
|
|
||||||
response.newBuilder()
|
response.newBuilder()
|
||||||
.body(ProgressResponseBody(request.tag(), response.body(), progressListener))
|
.body(ProgressResponseBody(request.tag(), response.body(), progressListener))
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
fun buildClient() =
|
fun buildClient() =
|
||||||
OkHttpClient.Builder()
|
OkHttpClient.Builder()
|
||||||
.addInterceptor(interceptor)
|
.addInterceptor(interceptor)
|
||||||
|
.connectTimeout(0, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(0, TimeUnit.SECONDS)
|
||||||
.dispatcher(Dispatcher(Executors.newFixedThreadPool(4)))
|
.dispatcher(Dispatcher(Executors.newFixedThreadPool(4)))
|
||||||
.proxy(proxy)
|
.proxy(proxy)
|
||||||
.build()
|
.build()
|
||||||
@@ -279,6 +283,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
|||||||
for (i in reader.galleryInfo.files.indices) {
|
for (i in reader.galleryInfo.files.indices) {
|
||||||
val callback = object : Callback {
|
val callback = object : Callback {
|
||||||
override fun onFailure(call: Call, e: IOException) {
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
|
Log.i("PUPILD", "FAIL ${call.request().tag()} (${e.message})")
|
||||||
if (Fabric.isInitialized() && e.message != "Canceled")
|
if (Fabric.isInitialized() && e.message != "Canceled")
|
||||||
Crashlytics.logException(e)
|
Crashlytics.logException(e)
|
||||||
|
|
||||||
@@ -287,43 +292,57 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
|||||||
|
|
||||||
notify(galleryID)
|
notify(galleryID)
|
||||||
|
|
||||||
if (isCompleted(galleryID)) {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
with(Cache(this@DownloadWorker)) {
|
if (isCompleted(galleryID) && clients.indexOfKey(galleryID) >= 0) {
|
||||||
if (isDownloading(galleryID)) {
|
clients.remove(galleryID)
|
||||||
moveToDownload(galleryID)
|
with(Cache(this@DownloadWorker)) {
|
||||||
setDownloading(galleryID, false)
|
if (isDownloading(galleryID)) {
|
||||||
|
moveToDownload(galleryID)
|
||||||
|
setDownloading(galleryID, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clients.remove(galleryID)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResponse(call: Call, response: Response) {
|
override fun onResponse(call: Call, response: Response) {
|
||||||
response.body().use {
|
Log.i("PUPILD", "OK ${call.request().tag()}")
|
||||||
val res = it.bytes()
|
|
||||||
val ext =
|
|
||||||
call.request().url().encodedPath().split('.').last()
|
|
||||||
|
|
||||||
Cache(this@DownloadWorker).putImage(galleryID, "%05d.%s".format(i, ext), res)
|
try {
|
||||||
|
val ext = call.request().url().encodedPath().split('.').last()
|
||||||
|
|
||||||
|
response.body().use {
|
||||||
|
Cache(this@DownloadWorker).putImage(galleryID, i, ext, it.byteStream())
|
||||||
|
}
|
||||||
progress[galleryID]?.set(i, Float.POSITIVE_INFINITY)
|
progress[galleryID]?.set(i, Float.POSITIVE_INFINITY)
|
||||||
}
|
|
||||||
|
|
||||||
notify(galleryID)
|
notify(galleryID)
|
||||||
|
|
||||||
if (isCompleted(galleryID)) {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
with(Cache(this@DownloadWorker)) {
|
if (isCompleted(galleryID) && clients.indexOfKey(galleryID) >= 0) {
|
||||||
if (isDownloading(galleryID)) {
|
clients.remove(galleryID)
|
||||||
moveToDownload(galleryID)
|
with(Cache(this@DownloadWorker)) {
|
||||||
setDownloading(galleryID, false)
|
if (isDownloading(galleryID)) {
|
||||||
|
moveToDownload(galleryID)
|
||||||
|
setDownloading(galleryID, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clients.remove(galleryID)
|
|
||||||
|
Log.i("PUPILD", "SUCCESS ${call.request().tag()}")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.i("PUPILD", "FAIL ON OK ${call.request().tag()} (${e.message})")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress[galleryID]?.get(i)?.isFinite() == true)
|
if (progress[galleryID]?.get(i)?.isFinite() == true) {
|
||||||
queueDownload(galleryID, reader, i, callback)
|
queueDownload(galleryID, reader, i, callback)
|
||||||
|
Log.i("PUPILD", "$galleryID QUEUED $i")
|
||||||
|
} else {
|
||||||
|
Log.i("PUPILD", "$galleryID SKIPPED $i (${progress[galleryID]?.get(i)})")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,7 +373,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
|||||||
}
|
}
|
||||||
val pendingIntent = TaskStackBuilder.create(this).run {
|
val pendingIntent = TaskStackBuilder.create(this).run {
|
||||||
addNextIntentWithParentStack(intent)
|
addNextIntentWithParentStack(intent)
|
||||||
getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
|
getPendingIntent(galleryID, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.put(galleryID, NotificationCompat.Builder(this, "download").apply {
|
notification.put(galleryID, NotificationCompat.Builder(this, "download").apply {
|
||||||
@@ -369,7 +388,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
|||||||
|
|
||||||
private fun loop() = CoroutineScope(Dispatchers.Default).launch {
|
private fun loop() = CoroutineScope(Dispatchers.Default).launch {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (queue.isEmpty() || clients.size() > preferences.getInt("max_download", 4))
|
if (queue.isEmpty() || clients.size() >= preferences.getInt("max_download", 4))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
val galleryID = queue.poll() ?: continue
|
val galleryID = queue.poll() ?: continue
|
||||||
|
|||||||
5555
dependencies.txt
Normal file
5555
dependencies.txt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user