Compare commits

..

20 Commits
4.18 ... 4.18.4

Author SHA1 Message Date
Pupil
9ddb19530b Merge pull request #101 from tom5079/dev
Version 4.18.3
2020-07-12 20:09:12 +09:00
tom5079
431e56a9f1 Version 4.18.3 2020-07-12 20:07:59 +09:00
Pupil
71093aac4c Update README.md 2020-07-12 19:53:28 +09:00
tom5079
47c9e8127e Remove logic for resetting low quality setting 2020-07-07 10:21:30 +09:00
tom5079
24b801b346 resolves #52 2020-07-05 19:45:55 +09:00
tom5079
70608c3ed9 resolves #52 2020-07-05 19:40:14 +09:00
tom5079
f185196e85 Version Update 2020-07-05 19:33:56 +09:00
tom5079
a8766a8bbe Drawer logo fixed 2020-06-23 20:37:20 +09:00
Pupil
27a8c93cfe Merge pull request #97 from tom5079/Pupil-95
Pupil 95
2020-06-23 18:49:57 +09:00
tom5079
a3cd29fda9 Merge remote-tracking branch 'origin/Pupil-95' into Pupil-95 2020-06-23 18:48:24 +09:00
tom5079
adda8ab640 Pupil-95 Search tag icon not visible in light theme 2020-06-23 18:48:13 +09:00
tom5079
1538ea5fc8 Merge remote-tracking branch 'origin/dev' into dev 2020-06-23 18:47:58 +09:00
tom5079
2367a97a54 App built 2020-06-23 18:47:48 +09:00
tom5079
090ec0e4af Auto-Retry
Bug fix
2020-06-23 18:47:48 +09:00
tom5079
de7f552e5c Pupil-95 Search tag icon not visible in light theme 2020-06-23 18:40:43 +09:00
tom5079
d763f5dca0 App built 2020-06-22 09:52:25 +09:00
tom5079
9f41116241 Auto-Retry
Bug fix
2020-06-22 09:48:04 +09:00
Pupil
57faada201 Merge pull request #93 from tom5079/dev
Version 4.18.1
2020-06-21 23:03:59 +09:00
tom5079
1edb95f0c5 Prevent OOM when cache is disabled 2020-06-21 23:03:10 +09:00
tom5079
9f363d8900 idk wtf i'm doin' 2020-06-21 22:43:47 +09:00
27 changed files with 179 additions and 201 deletions

View File

@@ -4,7 +4,6 @@
*Pupil, Hitomi.la viewer for Android* *Pupil, Hitomi.la viewer for Android*
[![](https://discordapp.com/api/guilds/610452916612104194/embed.png?style=banner2)](https://discord.gg/Stj4b5v) [![](https://discordapp.com/api/guilds/610452916612104194/embed.png?style=banner2)](https://discord.gg/Stj4b5v)
I can speak English, Japanese and Korean. If you have any questions, head over to my discord server or DM me!
# Screenshot # Screenshot
![Main Screen](https://github.com/tom5079/Pupil/blob/gh-pages/assets/images/main-screenshot.png?raw=true) ![Main Screen](https://github.com/tom5079/Pupil/blob/gh-pages/assets/images/main-screenshot.png?raw=true)

View File

@@ -19,8 +19,8 @@ android {
applicationId "xyz.quaver.pupil" applicationId "xyz.quaver.pupil"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 29 targetSdkVersion 29
versionCode 53 versionCode 56
versionName "4.18" versionName "4.18.3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
@@ -65,9 +65,9 @@ dependencies {
implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.multidex:multidex:2.0.1'
implementation "com.daimajia.swipelayout:library:1.2.0@aar" implementation "com.daimajia.swipelayout:library:1.2.0@aar"
implementation 'com.google.android.material:material:1.3.0-alpha01' implementation 'com.google.android.material:material:1.3.0-alpha01'
implementation 'com.google.firebase:firebase-core:17.4.3' implementation 'com.google.firebase:firebase-core:17.4.4'
implementation 'com.google.firebase:firebase-analytics:17.4.3' implementation 'com.google.firebase:firebase-analytics:17.4.4'
implementation 'com.google.firebase:firebase-crashlytics:17.1.0' implementation 'com.google.firebase:firebase-crashlytics:17.1.1'
implementation 'com.google.firebase:firebase-perf:19.0.7' implementation 'com.google.firebase:firebase-perf:19.0.7'
implementation 'com.github.arimorty:floatingsearchview:2.1.1' implementation 'com.github.arimorty:floatingsearchview:2.1.1'
implementation 'com.github.clans:fab:1.6.4' implementation 'com.github.clans:fab:1.6.4'

View File

@@ -32,4 +32,7 @@
} }
-keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder$InternalRewinder { -keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder$InternalRewinder {
*** rewind(); *** rewind();
} }
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep class com.bumptech.glide.GeneratedAppGlideModuleImpl

View File

@@ -11,8 +11,8 @@
"type": "SINGLE", "type": "SINGLE",
"filters": [], "filters": [],
"properties": [], "properties": [],
"versionCode": 53, "versionCode": 56,
"versionName": "53", "versionName": "56",
"enabled": true, "enabled": true,
"outputFile": "app-release.apk" "outputFile": "app-release.apk"
} }

View File

@@ -99,7 +99,7 @@ class ExampleInstrumentedTest {
while(worker.progress.indexOfKey(galleryID) < 0 || worker.progress[galleryID] != null) { while(worker.progress.indexOfKey(galleryID) < 0 || worker.progress[galleryID] != null) {
Log.i("PUPILD", worker.progress[galleryID]?.joinToString(" ") ?: "null") Log.i("PUPILD", worker.progress[galleryID]?.joinToString(" ") ?: "null")
if (worker.progress[galleryID]?.all { !it.isFinite() } == true) if (worker.progress[galleryID]?.all { it.isInfinite() } == true)
break break
} }

View File

@@ -71,13 +71,6 @@ class Pupil : MultiDexApplication() {
preference.edit().remove("dl_location").apply() preference.edit().remove("dl_location").apply()
} }
if (!preference.getBoolean("low_quality_reset", false)) {
preference.edit()
.putBoolean("low_quality", true)
.putBoolean("low_quality_reset", true)
.apply()
}
histories = Histories(File(ContextCompat.getDataDir(this), "histories.json")) histories = Histories(File(ContextCompat.getDataDir(this), "histories.json"))
favorites = Histories(File(ContextCompat.getDataDir(this), "favorites.json")) favorites = Histories(File(ContextCompat.getDataDir(this), "favorites.json"))

View File

@@ -18,29 +18,38 @@
package xyz.quaver.pupil.adapters package xyz.quaver.pupil.adapters
import android.app.Activity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.RequestManager import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.google.android.material.snackbar.Snackbar import com.bumptech.glide.load.model.GlideUrl
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.bumptech.glide.load.model.LazyHeaders
import kotlinx.android.synthetic.main.activity_reader.view.*
import kotlinx.android.synthetic.main.item_reader.view.* import kotlinx.android.synthetic.main.item_reader.view.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import xyz.quaver.Code
import xyz.quaver.hitomi.Reader 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.R
import xyz.quaver.pupil.util.download.Cache
import xyz.quaver.pupil.util.download.DownloadWorker import xyz.quaver.pupil.util.download.DownloadWorker
import java.util.* import java.util.*
import kotlin.concurrent.schedule import kotlin.concurrent.schedule
import kotlin.math.roundToInt import kotlin.math.roundToInt
class ReaderAdapter(private val glide: RequestManager, class ReaderAdapter(private val glide: RequestManager,
private val galleryID: Int) : RecyclerView.Adapter<ReaderAdapter.ViewHolder>() { private val galleryID: Int,
private val activity: Activity) : RecyclerView.Adapter<ReaderAdapter.ViewHolder>() {
var reader: Reader? = null var reader: Reader? = null
val timer = Timer() val timer = Timer()
@@ -88,46 +97,57 @@ class ReaderAdapter(private val glide: RequestManager,
holder.view.reader_index.text = (position+1).toString() holder.view.reader_index.text = (position+1).toString()
val image = downloadWorker!!.results[galleryID]?.get(position) val preferences = PreferenceManager.getDefaultSharedPreferences(holder.view.context)
val progress = downloadWorker!!.progress[galleryID]?.get(position) if (preferences.getBoolean("cache_disable", false)) {
val lowQuality = preferences.getBoolean("low_quality", false)
if (progress?.isInfinite() == true && image != null) {
holder.view.reader_item_progressbar.visibility = View.INVISIBLE
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 { holder.view.image.post {
glide glide
.load(image) .load(url!!)
.diskCacheStrategy(DiskCacheStrategy.NONE) .diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true) .skipMemoryCache(false)
.fitCenter() .fitCenter()
.error(R.drawable.image_broken_variant) .error(R.drawable.image_broken_variant)
.into(holder.view.image) .into(holder.view.image)
} }
} else { } 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) { holder.view.image.post {
FirebaseCrashlytics.getInstance().recordException( glide
DownloadWorker.getInstance(holder.view.context).exception[galleryID]?.get(position)!! .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 { } else {
holder.view.reader_item_progressbar.visibility = View.VISIBLE
glide.clear(holder.view.image)
holder.view.reader_item_progressbar.progress = holder.view.reader_item_progressbar.progress =
if (progress?.isInfinite() == true) if (progress?.isInfinite() == true)
100 100
@@ -135,11 +155,11 @@ class ReaderAdapter(private val glide: RequestManager,
progress?.roundToInt() ?: 0 progress?.roundToInt() ?: 0
holder.view.image.setImageDrawable(null) holder.view.image.setImageDrawable(null)
}
timer.schedule(1000) { timer.schedule(1000) {
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
notifyItemChanged(position) notifyItemChanged(position)
}
} }
} }
} }

View File

@@ -26,6 +26,7 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.text.* import android.text.*
import android.text.style.AlignmentSpan import android.text.style.AlignmentSpan
import android.util.TypedValue
import android.view.KeyEvent import android.view.KeyEvent
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
@@ -144,30 +145,6 @@ class MainActivity : AppCompatActivity() {
preference.edit().putBoolean("https_block_alert", true).apply() 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) { with(application as Pupil) {
@@ -464,8 +441,10 @@ class MainActivity : AppCompatActivity() {
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean("cache_disable", false)) if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean("cache_disable", false))
Toast.makeText(context, R.string.settings_download_when_cache_disable_warning, Toast.LENGTH_SHORT).show() Toast.makeText(context, R.string.settings_download_when_cache_disable_warning, Toast.LENGTH_SHORT).show()
else { else {
if (Cache(context).isDownloading(galleryID)) //download in progress if (worker.progress.indexOfKey(galleryID) >= 0 && Cache(context).isDownloading(galleryID)) { //download in progress
Cache(context).setDownloading(galleryID, false)
worker.cancel(galleryID) worker.cancel(galleryID)
}
else { else {
Cache(context).setDownloading(galleryID, true) Cache(context).setDownloading(galleryID, true)
@@ -867,6 +846,9 @@ class MainActivity : AppCompatActivity() {
val tag = "${item.n}:${item.s.replace(Regex("\\s"), "_")}" val tag = "${item.n}:${item.s.replace(Regex("\\s"), "_")}"
val color = TypedValue()
theme.resolveAttribute(R.attr.colorControlNormal, color, true)
leftIcon.setImageDrawable( leftIcon.setImageDrawable(
ResourcesCompat.getDrawable( ResourcesCompat.getDrawable(
resources, resources,
@@ -880,7 +862,7 @@ class MainActivity : AppCompatActivity() {
"artist" -> R.drawable.brush "artist" -> R.drawable.brush
else -> R.drawable.tag else -> R.drawable.tag
}, },
null) context.theme)
) )
with(suggestionView.findViewById<ImageView>(R.id.right_icon)) { with(suggestionView.findViewById<ImageView>(R.id.right_icon)) {

View File

@@ -39,6 +39,9 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics
import kotlinx.android.synthetic.main.activity_reader.* import kotlinx.android.synthetic.main.activity_reader.*
import kotlinx.android.synthetic.main.activity_reader.view.* import kotlinx.android.synthetic.main.activity_reader.view.*
import kotlinx.android.synthetic.main.dialog_numberpicker.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.Code
import xyz.quaver.pupil.Pupil import xyz.quaver.pupil.Pupil
import xyz.quaver.pupil.R import xyz.quaver.pupil.R
@@ -99,7 +102,36 @@ class ReaderActivity : AppCompatActivity() {
} }
initView() 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) { override fun onNewIntent(intent: Intent) {
@@ -232,6 +264,7 @@ class ReaderActivity : AppCompatActivity() {
private fun initDownloader() { private fun initDownloader() {
val worker = DownloadWorker.getInstance(this).apply { val worker = DownloadWorker.getInstance(this).apply {
cancel(galleryID)
queue.add(galleryID) queue.add(galleryID)
} }
@@ -248,7 +281,7 @@ class ReaderActivity : AppCompatActivity() {
runOnUiThread { runOnUiThread {
reader_download_progressbar.max = reader_recyclerview.adapter?.itemCount ?: 0 reader_download_progressbar.max = reader_recyclerview.adapter?.itemCount ?: 0
reader_download_progressbar.progress = worker.progress[galleryID]?.count { !it.isFinite() } ?: 0 reader_download_progressbar.progress = worker.progress[galleryID]?.count { it.isInfinite() } ?: 0
reader_progressbar.max = reader_recyclerview.adapter?.itemCount ?: 0 reader_progressbar.max = reader_recyclerview.adapter?.itemCount ?: 0
if (title == getString(R.string.reader_loading)) { if (title == getString(R.string.reader_loading)) {
@@ -273,7 +306,7 @@ class ReaderActivity : AppCompatActivity() {
} }
} }
if (worker.progress[galleryID]?.all { !it.isFinite() } == true) { //Download finished if (worker.progress[galleryID]?.all { it.isInfinite() } == true) { //Download finished
reader_download_progressbar.visibility = View.GONE reader_download_progressbar.visibility = View.GONE
animateDownloadFAB(false) animateDownloadFAB(false)
@@ -284,7 +317,7 @@ class ReaderActivity : AppCompatActivity() {
private fun initView() { private fun initView() {
with(reader_recyclerview) { with(reader_recyclerview) {
adapter = ReaderAdapter(Glide.with(this@ReaderActivity), galleryID).apply { adapter = ReaderAdapter(Glide.with(this@ReaderActivity), galleryID, this@ReaderActivity).apply {
onItemClickListener = { onItemClickListener = {
if (isScroll) { if (isScroll) {
isScroll = false isScroll = false
@@ -396,7 +429,7 @@ class ReaderActivity : AppCompatActivity() {
icon?.registerAnimationCallback(object : Animatable2Compat.AnimationCallback() { icon?.registerAnimationCallback(object : Animatable2Compat.AnimationCallback() {
override fun onAnimationEnd(drawable: Drawable?) { override fun onAnimationEnd(drawable: Drawable?) {
val worker = DownloadWorker.getInstance(context) val worker = DownloadWorker.getInstance(context)
if (worker.progress[galleryID]?.all { !it.isFinite() } == true) // If download is finished, stop animating if (worker.progress[galleryID]?.all { it.isInfinite() } == true) // If download is finished, stop animating
post { post {
setImageResource(R.drawable.ic_download) setImageResource(R.drawable.ic_download)
labelText = getString(R.string.reader_fab_download_cancel) labelText = getString(R.string.reader_fab_download_cancel)

View File

@@ -21,7 +21,6 @@ package xyz.quaver.pupil.util.download
import android.content.Context import android.content.Context
import android.content.ContextWrapper import android.content.ContextWrapper
import android.util.Base64 import android.util.Base64
import android.util.Log
import android.util.SparseArray import android.util.SparseArray
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.crashlytics.FirebaseCrashlytics
@@ -34,8 +33,10 @@ import xyz.quaver.pupil.util.getCachedGallery
import xyz.quaver.pupil.util.getDownloadDirectory import xyz.quaver.pupil.util.getDownloadDirectory
import xyz.quaver.pupil.util.isParentOf import xyz.quaver.pupil.util.isParentOf
import xyz.quaver.pupil.util.json import xyz.quaver.pupil.util.json
import java.io.BufferedInputStream
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.io.InputStream
import java.net.URL import java.net.URL
import java.util.* import java.util.*
import java.util.concurrent.locks.Lock import java.util.concurrent.locks.Lock
@@ -67,7 +68,7 @@ class Cache(context: Context) : ContextWrapper(context) {
// Search in this order // Search in this order
// Download -> Cache // Download -> Cache
fun getCachedGallery(galleryID: Int) = getCachedGallery(this, galleryID).also { fun getCachedGallery(galleryID: Int) = getCachedGallery(this, galleryID).also {
if (!it.exists() && !preference.getBoolean("cache_disable", false)) if (!it.exists())
it.mkdirs() it.mkdirs()
} }
@@ -250,7 +251,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)) if (preference.getBoolean("cache_disable", false))
return return
@@ -260,8 +261,10 @@ class Cache(context: Context) : ContextWrapper(context) {
} }
try { try {
FileOutputStream(cache).use { BufferedInputStream(data).use { inputStream ->
it.write(data) FileOutputStream(cache).use { outputStream ->
inputStream.copyTo(outputStream)
}
} }
} catch (e: Exception) { } catch (e: Exception) {
cache.delete() cache.delete()
@@ -285,17 +288,17 @@ class Cache(context: Context) : ContextWrapper(context) {
if (download.isParentOf(cache)) if (download.isParentOf(cache))
return@launch return@launch
Log.i("PUPILD", "MOVING ${cache.canonicalPath} --> ${download.canonicalPath}") FirebaseCrashlytics.getInstance().log("MOVING ${cache.canonicalPath} --> ${download.canonicalPath}")
cache.copyRecursively(download, true) { file, err -> cache.copyRecursively(download, true) { file, err ->
Log.i("PUPILD", "MOVING ERROR ${file.canonicalPath} ${err.message}") FirebaseCrashlytics.getInstance().log("MOVING ERROR ${file.canonicalPath} ${err.message}")
OnErrorAction.SKIP OnErrorAction.SKIP
} }
Log.i("PUPILD", "MOVED ${cache.canonicalPath}") FirebaseCrashlytics.getInstance().log("MOVED ${cache.canonicalPath}")
Log.i("PUPILD", "DELETING ${cache.canonicalPath}") FirebaseCrashlytics.getInstance().log("DELETING ${cache.canonicalPath}")
cache.deleteRecursively() cache.deleteRecursively()
Log.i("PUPILD", "DELETED ${cache.canonicalPath}") FirebaseCrashlytics.getInstance().log("DELETED ${cache.canonicalPath}")
} }
} }

View File

@@ -128,22 +128,8 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
* SECONDARY VALUE * SECONDARY VALUE
* 0 <= value < 100 -> Download in progress * 0 <= value < 100 -> Download in progress
* Float.POSITIVE_INFINITY -> Download completed * Float.POSITIVE_INFINITY -> Download completed
* Float.NaN -> Exception
*/ */
val progress = SparseArray<MutableList<Float>?>() val progress = SparseArray<MutableList<Float>?>()
/*
* KEY
* primary galleryID
* secondary index
* PRIMARY VALUE
* MutableList -> Download in progress / Loading
* null -> Gallery doesn't exist
* SECONDARY VALUE
* Throwable -> Exception
* null -> Download in progress / Loading
*/
val exception = SparseArray<MutableList<Throwable?>?>()
val results = SparseArray<MutableList<ByteArray?>?>()
val notification = SparseArray<NotificationCompat.Builder>() val notification = SparseArray<NotificationCompat.Builder>()
private val loop = loop() private val loop = loop()
@@ -195,8 +181,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
} }
progress.clear() progress.clear()
exception.clear()
results.clear()
notification.clear() notification.clear()
notificationManager.cancelAll() notificationManager.cancelAll()
} }
@@ -212,16 +196,11 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
} }
progress.remove(galleryID) progress.remove(galleryID)
exception.remove(galleryID)
results.remove(galleryID)
notification.remove(galleryID) notification.remove(galleryID)
notificationManager.cancel(galleryID) notificationManager.cancel(galleryID)
if (progress.indexOfKey(galleryID) >= 0)
Cache(this@DownloadWorker).setDownloading(galleryID, false)
} }
fun isCompleted(galleryID: Int) = progress[galleryID]?.all { !it.isFinite() } == true fun isCompleted(galleryID: Int) = progress[galleryID]?.all { it.isInfinite() } == true
private fun queueDownload(galleryID: Int, reader: Reader, index: Int, callback: Callback) { private fun queueDownload(galleryID: Int, reader: Reader, index: Int, callback: Callback) {
val lowQuality = preferences.getBoolean("low_quality", false) val lowQuality = preferences.getBoolean("low_quality", false)
@@ -251,8 +230,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
}.build() }.build()
client.newCall(request).enqueue(callback) client.newCall(request).enqueue(callback)
Log.i("PUPILD", "DOWNLOADING ($galleryID, $index) from ${request.url()}")
} }
private fun download(galleryID: Int) = CoroutineScope(Dispatchers.IO).launch { private fun download(galleryID: Int) = CoroutineScope(Dispatchers.IO).launch {
@@ -261,8 +238,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
//gallery doesn't exist //gallery doesn't exist
if (reader == null) { if (reader == null) {
progress.put(galleryID, null) progress.put(galleryID, null)
exception.put(galleryID, null)
results.put(galleryID, null)
Cache(this@DownloadWorker).setDownloading(galleryID, false) Cache(this@DownloadWorker).setDownloading(galleryID, false)
return@launch return@launch
@@ -276,10 +251,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
else else
0F 0F
}.toMutableList()) }.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) if (notification[galleryID] == null)
initNotification(galleryID) initNotification(galleryID)
@@ -301,47 +272,32 @@ 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) {
if (e.message?.contains("cancel", true) != false)
return
Log.i("PUPILD", "FAIL ${call.request().tag()} (${e.message})") Log.i("PUPILD", "FAIL ${call.request().tag()} (${e.message})")
if (e.message?.contains("cancel", true) != true) FirebaseCrashlytics.getInstance().apply {
FirebaseCrashlytics.getInstance().recordException(e) log("FAIL ${call.request().tag()} (${e.message})")
setCustomKey("POS", "FAIL")
progress[galleryID]?.set(i, Float.NaN) recordException(e)
exception[galleryID]?.set(i, e)
notify(galleryID)
CoroutineScope(Dispatchers.IO).launch {
if (isCompleted(galleryID)) {
with(Cache(this@DownloadWorker)) {
if (isDownloading(galleryID)) {
moveToDownload(galleryID)
setDownloading(galleryID, false)
}
}
}
} }
cancel(galleryID)
queue.add(galleryID)
} }
override fun onResponse(call: Call, response: Response) { override fun onResponse(call: Call, response: Response) {
Log.i("PUPILD", "OK ${call.request().tag()}")
val ext = call.request().url().encodedPath().split('.').last() val ext = call.request().url().encodedPath().split('.').last()
try { try {
response.body().use { response.body().use {
it!! Cache(this@DownloadWorker).putImage(galleryID, i, ext, it!!.byteStream())
results[galleryID]?.set(i, it.source().readByteArray())
} }
progress[galleryID]?.set(i, Float.POSITIVE_INFINITY) progress[galleryID]?.set(i, Float.POSITIVE_INFINITY)
notify(galleryID) notify(galleryID)
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
results[galleryID]?.get(i)?.also {
Cache(this@DownloadWorker).putImage(galleryID, i, ext, it)
}
if (isCompleted(galleryID)) { if (isCompleted(galleryID)) {
with(Cache(this@DownloadWorker)) { with(Cache(this@DownloadWorker)) {
if (isDownloading(galleryID)) { if (isDownloading(galleryID)) {
@@ -351,47 +307,29 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
} }
} }
} }
Log.i("PUPILD", "SUCCESS ${call.request().tag()}")
} catch (e: Exception) { } catch (e: Exception) {
FirebaseCrashlytics.getInstance().apply {
progress[galleryID]?.set(i, Float.NaN) log("FAIL ON OK ${call.request().tag()} (${e.message})")
exception[galleryID]?.set(i, e) setCustomKey("POS", "FAIL ON OK")
recordException(e)
notify(galleryID)
CoroutineScope(Dispatchers.IO).launch {
if (isCompleted(galleryID)) {
with(Cache(this@DownloadWorker)) {
if (isDownloading(galleryID)) {
moveToDownload(galleryID)
setDownloading(galleryID, false)
}
}
}
} }
File(Cache(this@DownloadWorker).getCachedGallery(galleryID), "%05d.$ext".format(i)).delete() File(Cache(this@DownloadWorker).getCachedGallery(galleryID), "%05d.$ext".format(i)).delete()
Log.i("PUPILD", "FAIL ON OK ${call.request().tag()} (${e.message})") cancel(galleryID)
queue.add(galleryID)
} }
} }
} }
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)})")
}
} }
} }
private fun notify(galleryID: Int) { private fun notify(galleryID: Int) {
val max = progress[galleryID]?.size ?: 0 val max = progress[galleryID]?.size ?: 0
val progress = progress[galleryID]?.count { !it.isFinite() } ?: 0 val progress = progress[galleryID]?.count { it.isInfinite() } ?: 0
Log.i("PUPILD", "NOTIFY $galleryID ${isCompleted(galleryID)} $progress/$max")
if (isCompleted(galleryID)) { if (isCompleted(galleryID)) {
notification[galleryID] notification[galleryID]
@@ -447,8 +385,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
if (Cache(this@DownloadWorker).isDownloading(galleryID)) if (Cache(this@DownloadWorker).isDownloading(galleryID))
notificationManager.notify(galleryID, notification[galleryID].build()) notificationManager.notify(galleryID, notification[galleryID].build())
Log.i("PUPILD", "QUEUED $galleryID")
worker.put(galleryID, download(galleryID)) worker.put(galleryID, download(galleryID))
queue.poll() queue.poll()
} }

View File

@@ -41,7 +41,7 @@ class Histories(private val file: File) : ArrayList<Int>() {
fun load() : Histories { fun load() : Histories {
return apply { return apply {
super.clear() super.clear()
addAll( super.addAll(
json.parse( json.parse(
serializer, serializer,
file.bufferedReader().use { it.readText() } file.bufferedReader().use { it.readText() }
@@ -67,6 +67,20 @@ class Histories(private val file: File) : ArrayList<Int>() {
return true return true
} }
override fun addAll(elements: Collection<Int>): Boolean {
load()
for (e in elements) {
if (contains(e))
super.remove(e)
super.add(0, e)
}
save()
return true
}
override fun remove(element: Int): Boolean { override fun remove(element: Int): Boolean {
load() load()
val retval = super.remove(element) val retval = super.remove(element)

View File

@@ -319,7 +319,7 @@ fun importOldGalleries(context: Context, folder: File) = CoroutineScope(Dispatch
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
val index = it.nameWithoutExtension.toIntOrNull() ?: return@forEach 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())
} }
} }

View File

@@ -4,5 +4,5 @@
android:width="24dp" android:width="24dp"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path android:fillColor="#fff" android:pathData="M12,5.5A3.5,3.5 0 0,1 15.5,9A3.5,3.5 0 0,1 12,12.5A3.5,3.5 0 0,1 8.5,9A3.5,3.5 0 0,1 12,5.5M5,8C5.56,8 6.08,8.15 6.53,8.42C6.38,9.85 6.8,11.27 7.66,12.38C7.16,13.34 6.16,14 5,14A3,3 0 0,1 2,11A3,3 0 0,1 5,8M19,8A3,3 0 0,1 22,11A3,3 0 0,1 19,14C17.84,14 16.84,13.34 16.34,12.38C17.2,11.27 17.62,9.85 17.47,8.42C17.92,8.15 18.44,8 19,8M5.5,18.25C5.5,16.18 8.41,14.5 12,14.5C15.59,14.5 18.5,16.18 18.5,18.25V20H5.5V18.25M0,20V18.5C0,17.11 1.89,15.94 4.45,15.6C3.86,16.28 3.5,17.22 3.5,18.25V20H0M24,20H20.5V18.25C20.5,17.22 20.14,16.28 19.55,15.6C22.11,15.94 24,17.11 24,18.5V20Z" /> <path android:fillColor="?attr/colorControlNormal" android:pathData="M12,5.5A3.5,3.5 0 0,1 15.5,9A3.5,3.5 0 0,1 12,12.5A3.5,3.5 0 0,1 8.5,9A3.5,3.5 0 0,1 12,5.5M5,8C5.56,8 6.08,8.15 6.53,8.42C6.38,9.85 6.8,11.27 7.66,12.38C7.16,13.34 6.16,14 5,14A3,3 0 0,1 2,11A3,3 0 0,1 5,8M19,8A3,3 0 0,1 22,11A3,3 0 0,1 19,14C17.84,14 16.84,13.34 16.34,12.38C17.2,11.27 17.62,9.85 17.47,8.42C17.92,8.15 18.44,8 19,8M5.5,18.25C5.5,16.18 8.41,14.5 12,14.5C15.59,14.5 18.5,16.18 18.5,18.25V20H5.5V18.25M0,20V18.5C0,17.11 1.89,15.94 4.45,15.6C3.86,16.28 3.5,17.22 3.5,18.25V20H0M24,20H20.5V18.25C20.5,17.22 20.14,16.28 19.55,15.6C22.11,15.94 24,17.11 24,18.5V20Z" />
</vector> </vector>

View File

@@ -4,5 +4,5 @@
android:width="24dp" android:width="24dp"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path android:fillColor="#fff" android:pathData="M15,14C12.33,14 7,15.33 7,18V20H23V18C23,15.33 17.67,14 15,14M15,12A4,4 0 0,0 19,8A4,4 0 0,0 15,4A4,4 0 0,0 11,8A4,4 0 0,0 15,12M5,13.28L7.45,14.77L6.8,11.96L9,10.08L6.11,9.83L5,7.19L3.87,9.83L1,10.08L3.18,11.96L2.5,14.77L5,13.28Z" /> <path android:fillColor="?attr/colorControlNormal" android:pathData="M15,14C12.33,14 7,15.33 7,18V20H23V18C23,15.33 17.67,14 15,14M15,12A4,4 0 0,0 19,8A4,4 0 0,0 15,4A4,4 0 0,0 11,8A4,4 0 0,0 15,12M5,13.28L7.45,14.77L6.8,11.96L9,10.08L6.11,9.83L5,7.19L3.87,9.83L1,10.08L3.18,11.96L2.5,14.77L5,13.28Z" />
</vector> </vector>

View File

@@ -4,5 +4,5 @@
android:width="24dp" android:width="24dp"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path android:fillColor="#fff" android:pathData="M13,12H20V13.5H13M13,9.5H20V11H13M13,14.5H20V16H13M21,4H3A2,2 0 0,0 1,6V19A2,2 0 0,0 3,21H21A2,2 0 0,0 23,19V6A2,2 0 0,0 21,4M21,19H12V6H21" /> <path android:fillColor="?attr/colorControlNormal" android:pathData="M13,12H20V13.5H13M13,9.5H20V11H13M13,14.5H20V16H13M21,4H3A2,2 0 0,0 1,6V19A2,2 0 0,0 3,21H21A2,2 0 0,0 23,19V6A2,2 0 0,0 21,4M21,19H12V6H21" />
</vector> </vector>

View File

@@ -4,5 +4,5 @@
android:width="24dp" android:width="24dp"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path android:fillColor="#fff" android:pathData="M20.71,4.63L19.37,3.29C19,2.9 18.35,2.9 17.96,3.29L9,12.25L11.75,15L20.71,6.04C21.1,5.65 21.1,5 20.71,4.63M7,14A3,3 0 0,0 4,17C4,18.31 2.84,19 2,19C2.92,20.22 4.5,21 6,21A4,4 0 0,0 10,17A3,3 0 0,0 7,14Z" /> <path android:fillColor="?attr/colorControlNormal" android:pathData="M20.71,4.63L19.37,3.29C19,2.9 18.35,2.9 17.96,3.29L9,12.25L11.75,15L20.71,6.04C21.1,5.65 21.1,5 20.71,4.63M7,14A3,3 0 0,0 4,17C4,18.31 2.84,19 2,19C2.92,20.22 4.5,21 6,21A4,4 0 0,0 10,17A3,3 0 0,0 7,14Z" />
</vector> </vector>

View File

@@ -4,5 +4,5 @@
android:width="24dp" android:width="24dp"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path android:fillColor="#fff" android:pathData="M12,4A6,6 0 0,1 18,10C18,12.97 15.84,15.44 13,15.92V18H15V20H13V22H11V20H9V18H11V15.92C8.16,15.44 6,12.97 6,10A6,6 0 0,1 12,4M12,6A4,4 0 0,0 8,10A4,4 0 0,0 12,14A4,4 0 0,0 16,10A4,4 0 0,0 12,6Z" /> <path android:fillColor="?attr/colorControlNormal" android:pathData="M12,4A6,6 0 0,1 18,10C18,12.97 15.84,15.44 13,15.92V18H15V20H13V22H11V20H9V18H11V15.92C8.16,15.44 6,12.97 6,10A6,6 0 0,1 12,4M12,6A4,4 0 0,0 8,10A4,4 0 0,0 12,14A4,4 0 0,0 16,10A4,4 0 0,0 12,6Z" />
</vector> </vector>

View File

@@ -4,5 +4,5 @@
android:width="24dp" android:width="24dp"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path android:fillColor="#fff" android:pathData="M9,9C10.29,9 11.5,9.41 12.47,10.11L17.58,5H13V3H21V11H19V6.41L13.89,11.5C14.59,12.5 15,13.7 15,15A6,6 0 0,1 9,21A6,6 0 0,1 3,15A6,6 0 0,1 9,9M9,11A4,4 0 0,0 5,15A4,4 0 0,0 9,19A4,4 0 0,0 13,15A4,4 0 0,0 9,11Z" /> <path android:fillColor="?attr/colorControlNormal" android:pathData="M9,9C10.29,9 11.5,9.41 12.47,10.11L17.58,5H13V3H21V11H19V6.41L13.89,11.5C14.59,12.5 15,13.7 15,15A6,6 0 0,1 9,21A6,6 0 0,1 3,15A6,6 0 0,1 9,9M9,11A4,4 0 0,0 5,15A4,4 0 0,0 9,19A4,4 0 0,0 13,15A4,4 0 0,0 9,11Z" />
</vector> </vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 67 KiB

View File

@@ -4,5 +4,5 @@
android:width="24dp" android:width="24dp"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path android:fillColor="#fff" android:pathData="M5.5,7A1.5,1.5 0 0,1 4,5.5A1.5,1.5 0 0,1 5.5,4A1.5,1.5 0 0,1 7,5.5A1.5,1.5 0 0,1 5.5,7M21.41,11.58L12.41,2.58C12.05,2.22 11.55,2 11,2H4C2.89,2 2,2.89 2,4V11C2,11.55 2.22,12.05 2.59,12.41L11.58,21.41C11.95,21.77 12.45,22 13,22C13.55,22 14.05,21.77 14.41,21.41L21.41,14.41C21.78,14.05 22,13.55 22,13C22,12.44 21.77,11.94 21.41,11.58Z" /> <path android:fillColor="?attr/colorControlNormal" android:pathData="M5.5,7A1.5,1.5 0 0,1 4,5.5A1.5,1.5 0 0,1 5.5,4A1.5,1.5 0 0,1 7,5.5A1.5,1.5 0 0,1 5.5,7M21.41,11.58L12.41,2.58C12.05,2.22 11.55,2 11,2H4C2.89,2 2,2.89 2,4V11C2,11.55 2.22,12.05 2.59,12.41L11.58,21.41C11.95,21.77 12.45,22 13,22C13.55,22 14.05,21.77 14.41,21.41L21.41,14.41C21.78,14.05 22,13.55 22,13C22,12.44 21.77,11.94 21.41,11.58Z" />
</vector> </vector>

View File

@@ -4,5 +4,5 @@
android:width="24dp" android:width="24dp"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path android:fillColor="#fff" android:pathData="M12.87,15.07L10.33,12.56L10.36,12.53C12.1,10.59 13.34,8.36 14.07,6H17V4H10V2H8V4H1V6H12.17C11.5,7.92 10.44,9.75 9,11.35C8.07,10.32 7.3,9.19 6.69,8H4.69C5.42,9.63 6.42,11.17 7.67,12.56L2.58,17.58L4,19L9,14L12.11,17.11L12.87,15.07M18.5,10H16.5L12,22H14L15.12,19H19.87L21,22H23L18.5,10M15.88,17L17.5,12.67L19.12,17H15.88Z" /> <path android:fillColor="?attr/colorControlNormal" android:pathData="M12.87,15.07L10.33,12.56L10.36,12.53C12.1,10.59 13.34,8.36 14.07,6H17V4H10V2H8V4H1V6H12.17C11.5,7.92 10.44,9.75 9,11.35C8.07,10.32 7.3,9.19 6.69,8H4.69C5.42,9.63 6.42,11.17 7.67,12.56L2.58,17.58L4,19L9,14L12.11,17.11L12.87,15.07M18.5,10H16.5L12,22H14L15.12,19H19.87L21,22H23L18.5,10M15.88,17L17.5,12.67L19.12,17H15.88Z" />
</vector> </vector>

View File

@@ -19,11 +19,14 @@
<ImageView <ImageView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height" android:layout_height="wrap_content"
android:background="@drawable/side_nav_bar" android:src="@drawable/side_nav_bar"
android:adjustViewBounds="true"
android:paddingBottom="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin" android:paddingTop="@dimen/activity_vertical_margin"
android:gravity="bottom"/> android:gravity="bottom"
tools:ignore="ContentDescription" />

View File

@@ -146,8 +146,6 @@
<string name="default_query_dialog_filter_loli">登場人物を全て18歳以上にする</string> <string name="default_query_dialog_filter_loli">登場人物を全て18歳以上にする</string>
<string name="settings_cache_disable">キャッシュを使用しない</string> <string name="settings_cache_disable">キャッシュを使用しない</string>
<string name="settings_download_when_cache_disable_warning">キャッシュを使用しないため、ダウンロードできません</string> <string name="settings_download_when_cache_disable_warning">キャッシュを使用しないため、ダウンロードできません</string>
<string name="apcjsa_option_title">(Korean only)</string>
<string name="apcjsa_option_message">(Korean only)</string>
<string name="settings_user_id">ユーザーID</string> <string name="settings_user_id">ユーザーID</string>
<string name="settings_user_id_toast">ユーザーIDをクリップボードにコピーしました</string> <string name="settings_user_id_toast">ユーザーIDをクリップボードにコピーしました</string>
<string name="reader_error_retry">ダウンロードエラーが発生しました。リトライしますか?</string> <string name="reader_error_retry">ダウンロードエラーが発生しました。リトライしますか?</string>

View File

@@ -146,10 +146,8 @@
<string name="default_query_dialog_filter_loli">판사님 저는 페도가 아닙니다</string> <string name="default_query_dialog_filter_loli">판사님 저는 페도가 아닙니다</string>
<string name="settings_cache_disable">캐시 비활성화</string> <string name="settings_cache_disable">캐시 비활성화</string>
<string name="settings_download_when_cache_disable_warning">캐시를 활성화 해야 다운로드를 진행할 수 있습니다</string> <string name="settings_download_when_cache_disable_warning">캐시를 활성화 해야 다운로드를 진행할 수 있습니다</string>
<string name="apcjsa_option_title">아청법 대응 옵션 추가</string>
<string name="apcjsa_option_message">경찰서 정모 확률을 줄여보고자 캐시 비활성화/태그 필터를 추가하였습니다. 적용하시겠습니까?</string>
<string name="settings_user_id">유저 ID</string> <string name="settings_user_id">유저 ID</string>
<string name="settings_user_id_toast">유저 ID를 클립보드에 복사했습니다</string> <string name="settings_user_id_toast">유저 ID를 클립보드에 복사했습니다</string>
<string name="reader_error_retry">다운로드 에러가 발생했습니. 재시도 하시겠습니까?</string> <string name="reader_error_retry">다운로드 에러가 발생했습니. 재시도 하시겠습니까?</string>
<string name="reader_fab_retry">재시도</string> <string name="reader_fab_retry">재시도</string>
</resources> </resources>

View File

@@ -27,9 +27,6 @@
<string name="https_block_alert_title">(Korean only)</string> <string name="https_block_alert_title">(Korean only)</string>
<string name="https_block_alert">(Korean only)</string> <string name="https_block_alert">(Korean only)</string>
<string name="apcjsa_option_title">(Korean only)</string>
<string name="apcjsa_option_message">(Korean only)</string>
<string name="update_failed">Update failed</string> <string name="update_failed">Update failed</string>
<string name="update_failed_message">Please install manually by visiting github release page :{ (or try again!)</string> <string name="update_failed_message">Please install manually by visiting github release page :{ (or try again!)</string>
<string name="update_no_permission">Cannot auto update because permission is denied. Please download manually from the webpage.</string> <string name="update_no_permission">Cannot auto update because permission is denied. Please download manually from the webpage.</string>
@@ -124,7 +121,7 @@
<string name="reader_notification_complete">Download complete</string> <string name="reader_notification_complete">Download complete</string>
<string name="reader_notification_error">Download error</string> <string name="reader_notification_error">Download error</string>
<string name="reader_error_retry">Download Error occurred. Retry?</string> <string name="reader_error_retry">Download Error. Retry?</string>
<string name="reader_help">Help</string> <string name="reader_help">Help</string>

View File

@@ -19,6 +19,5 @@ package xyz.quaver
enum class Code { enum class Code {
HITOMI, HITOMI,
HIYOBI, HIYOBI
SORALA
} }