diff --git a/app/build.gradle b/app/build.gradle index 415b38c7..5d545827 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -19,8 +19,8 @@ android { applicationId "xyz.quaver.pupil" minSdkVersion 16 targetSdkVersion 29 - versionCode 53 - versionName "4.18" + versionCode 54 + versionName "4.18.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled true vectorDrawables.useSupportLibrary = true diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index efbc5792..92f0fd7a 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -32,4 +32,7 @@ } -keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder$InternalRewinder { *** rewind(); -} \ No newline at end of file +} + +-keep public class * extends com.bumptech.glide.module.AppGlideModule +-keep class com.bumptech.glide.GeneratedAppGlideModuleImpl \ No newline at end of file diff --git a/app/release/output.json b/app/release/output.json index 246862e8..967b8923 100644 --- a/app/release/output.json +++ b/app/release/output.json @@ -11,8 +11,8 @@ "type": "SINGLE", "filters": [], "properties": [], - "versionCode": 53, - "versionName": "53", + "versionCode": 54, + "versionName": "54", "enabled": true, "outputFile": "app-release.apk" } diff --git a/app/src/main/java/xyz/quaver/pupil/adapters/ReaderAdapter.kt b/app/src/main/java/xyz/quaver/pupil/adapters/ReaderAdapter.kt index d008e837..a6505838 100644 --- a/app/src/main/java/xyz/quaver/pupil/adapters/ReaderAdapter.kt +++ b/app/src/main/java/xyz/quaver/pupil/adapters/ReaderAdapter.kt @@ -22,9 +22,12 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.constraintlayout.widget.ConstraintLayout +import androidx.preference.PreferenceManager import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.RequestManager import com.bumptech.glide.load.engine.DiskCacheStrategy +import com.bumptech.glide.load.model.GlideUrl +import com.bumptech.glide.load.model.LazyHeaders import com.google.android.material.snackbar.Snackbar import com.google.firebase.crashlytics.FirebaseCrashlytics import kotlinx.android.synthetic.main.activity_reader.view.* @@ -32,8 +35,15 @@ import kotlinx.android.synthetic.main.item_reader.view.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import xyz.quaver.Code import xyz.quaver.hitomi.Reader +import xyz.quaver.hitomi.getReferer +import xyz.quaver.hitomi.imageUrlFromImage +import xyz.quaver.hiyobi.cookie +import xyz.quaver.hiyobi.createImgList +import xyz.quaver.hiyobi.user_agent import xyz.quaver.pupil.R +import xyz.quaver.pupil.util.download.Cache import xyz.quaver.pupil.util.download.DownloadWorker import java.util.* import kotlin.concurrent.schedule @@ -88,58 +98,89 @@ class ReaderAdapter(private val glide: RequestManager, holder.view.reader_index.text = (position+1).toString() - val image = downloadWorker!!.results[galleryID]?.get(position) - val progress = downloadWorker!!.progress[galleryID]?.get(position) - - if (progress?.isInfinite() == true && image != null) { - holder.view.reader_item_progressbar.visibility = View.INVISIBLE + val preferences = PreferenceManager.getDefaultSharedPreferences(holder.view.context) + if (preferences.getBoolean("cache_disable", false)) { + val lowQuality = preferences.getBoolean("low_quality", false) + val url = when (reader!!.code) { + Code.HITOMI -> + GlideUrl( + imageUrlFromImage( + galleryID, + reader!!.galleryInfo.files[position], + !lowQuality + ) + , LazyHeaders.Builder().addHeader("Referer", getReferer(galleryID)).build()) + Code.HIYOBI -> + GlideUrl(createImgList(galleryID, reader!!, lowQuality)[position].path, LazyHeaders.Builder() + .addHeader("User-Agent", user_agent) + .addHeader("Cookie", cookie) + .build()) + else -> null + } holder.view.image.post { glide - .load(image) + .load(url!!) .diskCacheStrategy(DiskCacheStrategy.NONE) - .skipMemoryCache(true) + .skipMemoryCache(false) .fitCenter() .error(R.drawable.image_broken_variant) .into(holder.view.image) } - } else { - holder.view.reader_item_progressbar.visibility = View.VISIBLE + val image = Cache(holder.view.context).getImage(galleryID, position) + val progress = downloadWorker!!.progress[galleryID]?.get(position) - glide.clear(holder.view.image) + if (progress?.isInfinite() == true && image != null) { + holder.view.reader_item_progressbar.visibility = View.INVISIBLE - if (progress?.isNaN() == true) { - FirebaseCrashlytics.getInstance().recordException( - DownloadWorker.getInstance(holder.view.context).exception[galleryID]?.get(position)!! - ) + holder.view.image.post { + glide + .load(image) + .diskCacheStrategy(DiskCacheStrategy.NONE) + .skipMemoryCache(true) + .fitCenter() + .error(R.drawable.image_broken_variant) + .into(holder.view.image) + } - glide - .load(R.drawable.image_broken_variant) - .into(holder.view.image) - - Snackbar.make(holder.view.reader_layout, R.string.reader_error_retry, Snackbar.LENGTH_SHORT).apply { - setAction(android.R.string.no) { } - setAction(android.R.string.yes) { - downloadWorker!!.cancel(galleryID) - downloadWorker!!.queue.add(galleryID) - } - }.show() - - return } else { - holder.view.reader_item_progressbar.progress = - if (progress?.isInfinite() == true) - 100 - else - progress?.roundToInt() ?: 0 + holder.view.reader_item_progressbar.visibility = View.VISIBLE - holder.view.image.setImageDrawable(null) - } + glide.clear(holder.view.image) - timer.schedule(1000) { - CoroutineScope(Dispatchers.Main).launch { - notifyItemChanged(position) + if (progress?.isNaN() == true) { + FirebaseCrashlytics.getInstance().recordException( + DownloadWorker.getInstance(holder.view.context).exception[galleryID]?.get(position)!! + ) + + glide + .load(R.drawable.image_broken_variant) + .into(holder.view.image) + + Snackbar.make(holder.view.reader_layout, R.string.reader_error_retry, Snackbar.LENGTH_SHORT).apply { + setAction(android.R.string.no) { } + setAction(android.R.string.yes) { + downloadWorker!!.cancel(galleryID) + downloadWorker!!.queue.add(galleryID) + } + }.show() + + return + } else { + holder.view.reader_item_progressbar.progress = + if (progress?.isInfinite() == true) + 100 + else + progress?.roundToInt() ?: 0 + + holder.view.image.setImageDrawable(null) + } + + timer.schedule(1000) { + CoroutineScope(Dispatchers.Main).launch { + notifyItemChanged(position) + } } } } diff --git a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt index 65f37e9e..2a1aa3b0 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt @@ -144,30 +144,6 @@ class MainActivity : AppCompatActivity() { preference.edit().putBoolean("https_block_alert", true).apply() } - - if (!preference.getBoolean("apcjsa_option", false)) { - android.app.AlertDialog.Builder(this).apply { - setTitle(R.string.apcjsa_option_title) - setMessage(R.string.apcjsa_option_message) - setPositiveButton(android.R.string.yes) { _, _ -> - val tags = Tags.parse( - preference.getString("default_query", "") ?: "" - ) - - tags.add("-female:loli") - tags.add("-male:shota") - - preference.edit() - .putString("default_query", tags.toString()) - .putBoolean("cache_disable", true) - .putBoolean("apcjsa_option", true) - .apply() - } - setNegativeButton(android.R.string.no) { _, _ -> } - }.show() - - preference.edit().putBoolean("apcjsa_option", true).apply() - } } with(application as Pupil) { diff --git a/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt index 7681698f..c4ce1917 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt @@ -39,6 +39,9 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics import kotlinx.android.synthetic.main.activity_reader.* import kotlinx.android.synthetic.main.activity_reader.view.* import kotlinx.android.synthetic.main.dialog_numberpicker.view.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import xyz.quaver.Code import xyz.quaver.pupil.Pupil import xyz.quaver.pupil.R @@ -99,7 +102,36 @@ class ReaderActivity : AppCompatActivity() { } initView() - initDownloader() + if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("cache_disable", false)) { + reader_download_progressbar.visibility = View.GONE + CoroutineScope(Dispatchers.IO).launch { + val reader = Cache(this@ReaderActivity).getReader(galleryID) + + launch(Dispatchers.Main) initDownloader@{ + if (reader == null) { + Snackbar + .make(reader_layout, R.string.reader_failed_to_find_gallery, Snackbar.LENGTH_INDEFINITE) + .show() + return@initDownloader + } + + (reader_recyclerview.adapter as ReaderAdapter).apply { + this.reader = reader + notifyDataSetChanged() + } + title = reader.galleryInfo.title ?: "" + menu?.findItem(R.id.reader_menu_page_indicator)?.title = "$currentPage/${reader.galleryInfo.files.size}" + + menu?.findItem(R.id.reader_type)?.icon = ContextCompat.getDrawable(this@ReaderActivity, + when (reader.code) { + Code.HITOMI -> R.drawable.hitomi + Code.HIYOBI -> R.drawable.ic_hiyobi + else -> android.R.color.transparent + }) + } + } + } else + initDownloader() } override fun onNewIntent(intent: Intent) { 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 deb4c25c..51389012 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 @@ -34,8 +34,10 @@ import xyz.quaver.pupil.util.getCachedGallery import xyz.quaver.pupil.util.getDownloadDirectory import xyz.quaver.pupil.util.isParentOf import xyz.quaver.pupil.util.json +import java.io.BufferedInputStream import java.io.File import java.io.FileOutputStream +import java.io.InputStream import java.net.URL import java.util.* import java.util.concurrent.locks.Lock @@ -250,7 +252,7 @@ class Cache(context: Context) : ContextWrapper(context) { } - fun putImage(galleryID: Int, index: Int, ext: String, data: ByteArray) { + fun putImage(galleryID: Int, index: Int, ext: String, data: InputStream) { if (preference.getBoolean("cache_disable", false)) return @@ -260,8 +262,10 @@ class Cache(context: Context) : ContextWrapper(context) { } try { - FileOutputStream(cache).use { - it.write(data) + BufferedInputStream(data).use { inputStream -> + FileOutputStream(cache).use { outputStream -> + inputStream.copyTo(outputStream) + } } } catch (e: Exception) { cache.delete() 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 587a51c8..4ff09b62 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 @@ -143,7 +143,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont * null -> Download in progress / Loading */ val exception = SparseArray?>() - val results = SparseArray?>() val notification = SparseArray() private val loop = loop() @@ -196,7 +195,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont progress.clear() exception.clear() - results.clear() notification.clear() notificationManager.cancelAll() } @@ -213,7 +211,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont progress.remove(galleryID) exception.remove(galleryID) - results.remove(galleryID) notification.remove(galleryID) notificationManager.cancel(galleryID) @@ -262,7 +259,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont if (reader == null) { progress.put(galleryID, null) exception.put(galleryID, null) - results.put(galleryID, null) Cache(this@DownloadWorker).setDownloading(galleryID, false) return@launch @@ -277,9 +273,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont 0F }.toMutableList()) exception.put(galleryID, reader.galleryInfo.files.map { null }.toMutableList()) - results.put(galleryID, reader.galleryInfo.files.indices.map { index -> - cache?.firstOrNull { it?.nameWithoutExtension?.toIntOrNull() == index }?.readBytes() - }.toMutableList()) if (notification[galleryID] == null) initNotification(galleryID) @@ -329,19 +322,13 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont try { response.body().use { - it!! - - results[galleryID]?.set(i, it.source().readByteArray()) + Cache(this@DownloadWorker).putImage(galleryID, i, ext, it!!.byteStream()) } progress[galleryID]?.set(i, Float.POSITIVE_INFINITY) notify(galleryID) CoroutineScope(Dispatchers.IO).launch { - results[galleryID]?.get(i)?.also { - Cache(this@DownloadWorker).putImage(galleryID, i, ext, it) - } - if (isCompleted(galleryID)) { with(Cache(this@DownloadWorker)) { if (isDownloading(galleryID)) { diff --git a/app/src/main/java/xyz/quaver/pupil/util/update.kt b/app/src/main/java/xyz/quaver/pupil/util/update.kt index 406837cd..758357c9 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/update.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/update.kt @@ -319,7 +319,7 @@ fun importOldGalleries(context: Context, folder: File) = CoroutineScope(Dispatch @Suppress("NAME_SHADOWING") val index = it.nameWithoutExtension.toIntOrNull() ?: return@forEach - Cache(context).putImage(galleryID, index, it.extension, it.readBytes()) + Cache(context).putImage(galleryID, index, it.extension, it.inputStream()) } } diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 34dd3810..9a0f825e 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -146,8 +146,6 @@ 登場人物を全て18歳以上にする キャッシュを使用しない キャッシュを使用しないため、ダウンロードできません - (Korean only) - (Korean only) ユーザーID ユーザーIDをクリップボードにコピーしました ダウンロードエラーが発生しました。リトライしますか? diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index e4321f2c..fb18e2a7 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -146,8 +146,6 @@ 판사님 저는 페도가 아닙니다 캐시 비활성화 캐시를 활성화 해야 다운로드를 진행할 수 있습니다 - 아청법 대응 옵션 추가 - 경찰서 정모 확률을 줄여보고자 캐시 비활성화/태그 필터를 추가하였습니다. 적용하시겠습니까? 유저 ID 유저 ID를 클립보드에 복사했습니다 다운로드 에러가 발생했습니다. 재시도 하시겠습니까? diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3028ed1a..531e9997 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -27,9 +27,6 @@ (Korean only) (Korean only) - (Korean only) - (Korean only) - Update failed Please install manually by visiting github release page :{ (or try again!) Cannot auto update because permission is denied. Please download manually from the webpage. diff --git a/libpupil/src/main/java/xyz/quaver/Code.kt b/libpupil/src/main/java/xyz/quaver/Code.kt index 5f9364f2..0251d817 100644 --- a/libpupil/src/main/java/xyz/quaver/Code.kt +++ b/libpupil/src/main/java/xyz/quaver/Code.kt @@ -19,6 +19,5 @@ package xyz.quaver enum class Code { HITOMI, - HIYOBI, - SORALA + HIYOBI } \ No newline at end of file