diff --git a/app/build.gradle b/app/build.gradle
index bd3755c2..415b38c7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -7,7 +7,7 @@ apply plugin: 'kotlinx-serialization'
if (file("google-services.json").exists() && file("src/debug/google-services.json").exists()) {
logger.lifecycle("Firebase Enabled")
apply plugin: 'com.google.gms.google-services'
- apply plugin: 'io.fabric'
+ apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'com.google.firebase.firebase-perf'
} else {
logger.lifecycle("Firebase Disabled")
@@ -19,8 +19,8 @@ android {
applicationId "xyz.quaver.pupil"
minSdkVersion 16
targetSdkVersion 29
- versionCode 52
- versionName "4.17"
+ versionCode 53
+ versionName "4.18"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
vectorDrawables.useSupportLibrary = true
@@ -50,12 +50,12 @@ android {
}
dependencies {
- def markwonVersion = "3.0.1"
+ def markwonVersion = '3.1.0'
- implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3'
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7"
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.7"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
@@ -66,8 +66,9 @@ dependencies {
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
implementation 'com.google.android.material:material:1.3.0-alpha01'
implementation 'com.google.firebase:firebase-core:17.4.3'
+ implementation 'com.google.firebase:firebase-analytics:17.4.3'
+ implementation 'com.google.firebase:firebase-crashlytics:17.1.0'
implementation 'com.google.firebase:firebase-perf:19.0.7'
- implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
implementation 'com.github.arimorty:floatingsearchview:2.1.1'
implementation 'com.github.clans:fab:1.6.4'
implementation 'com.github.bumptech.glide:glide:4.11.0'
@@ -79,6 +80,7 @@ dependencies {
implementation 'net.rdrei.android.dirchooser:library:3.2@aar'
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
implementation 'com.andrognito.patternlockview:patternlockview:1.0.0'
+ //implementation 'com.andrognito.pinlockview:pinlockview:2.1.0'
implementation "ru.noties.markwon:core:${markwonVersion}"
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
diff --git a/app/libs/pinlockview-release.aar b/app/libs/pinlockview-release.aar
new file mode 100644
index 00000000..646f97a4
Binary files /dev/null and b/app/libs/pinlockview-release.aar differ
diff --git a/app/release/output.json b/app/release/output.json
index 41aaa36f..246862e8 100644
--- a/app/release/output.json
+++ b/app/release/output.json
@@ -1 +1,20 @@
-[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":52,"versionName":"4.17","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release","dirName":""},"path":"app-release.apk","properties":{}}]
\ No newline at end of file
+{
+ "version": 1,
+ "artifactType": {
+ "type": "APK",
+ "kind": "Directory"
+ },
+ "applicationId": "xyz.quaver.pupil",
+ "variantName": "release",
+ "elements": [
+ {
+ "type": "SINGLE",
+ "filters": [],
+ "properties": [],
+ "versionCode": 53,
+ "versionName": "53",
+ "enabled": true,
+ "outputFile": "app-release.apk"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b61f152c..dab7dfb3 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -53,6 +53,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
@@ -97,21 +196,10 @@
-
-
-
-
-
-
-
-
+ android:scheme="https" />
.
+ */
+
+package com.arlib.floatingsearchview
+
+import android.content.Context
+import android.os.Parcelable
+import android.util.AttributeSet
+
+class FloatingSearchViewDayNight @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null)
+ : FloatingSearchView(context, attrs) {
+
+ // hack to remove color attributes which should not be reused
+ override fun onSaveInstanceState(): Parcelable? {
+ super.onSaveInstanceState()
+ return null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/quaver/pupil/Pupil.kt b/app/src/main/java/xyz/quaver/pupil/Pupil.kt
index 54b1b78c..1a723eec 100644
--- a/app/src/main/java/xyz/quaver/pupil/Pupil.kt
+++ b/app/src/main/java/xyz/quaver/pupil/Pupil.kt
@@ -31,10 +31,12 @@ import com.google.android.gms.common.GooglePlayServicesNotAvailableException
import com.google.android.gms.common.GooglePlayServicesRepairableException
import com.google.android.gms.security.ProviderInstaller
import com.google.firebase.analytics.FirebaseAnalytics
+import com.google.firebase.crashlytics.FirebaseCrashlytics
import xyz.quaver.proxy
import xyz.quaver.pupil.util.Histories
import xyz.quaver.pupil.util.getProxy
import java.io.File
+import java.util.*
class Pupil : MultiDexApplication() {
@@ -48,6 +50,16 @@ class Pupil : MultiDexApplication() {
override fun onCreate() {
val preference = PreferenceManager.getDefaultSharedPreferences(this)
+ val userID =
+ if (preference.getString("user_id", "").isNullOrEmpty()) {
+ UUID.randomUUID().toString().also {
+ preference.edit().putString("user_id", it).apply()
+ }
+ } else
+ preference.getString("user_id", "") ?: ""
+
+ FirebaseCrashlytics.getInstance().setUserId(userID)
+
proxy = getProxy(this)
try {
diff --git a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt
index 618bbe72..c2886904 100644
--- a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt
+++ b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt
@@ -28,6 +28,7 @@ import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.cardview.widget.CardView
import androidx.core.content.ContextCompat
+import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.CircularProgressDrawable
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
@@ -42,7 +43,9 @@ import kotlinx.android.synthetic.main.item_galleryblock.view.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
import xyz.quaver.hitomi.GalleryBlock
+import xyz.quaver.hitomi.getReader
import xyz.quaver.pupil.BuildConfig
import xyz.quaver.pupil.Pupil
import xyz.quaver.pupil.R
@@ -75,7 +78,7 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri
val reader = Cache(context).getReaderOrNull(galleryID)
CoroutineScope(Dispatchers.Main).launch {
- if (reader == null) {
+ if (reader == null || PreferenceManager.getDefaultSharedPreferences(context).getBoolean("cache_disable", false)) {
view.galleryblock_progressbar.visibility = View.GONE
view.galleryblock_progress_complete.visibility = View.GONE
return@launch
@@ -218,12 +221,12 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri
"male" -> {
setChipBackgroundColorResource(R.color.material_blue_700)
setTextColor(ContextCompat.getColor(context, android.R.color.white))
- ContextCompat.getDrawable(context, R.drawable.ic_gender_male_white)
+ ContextCompat.getDrawable(context, R.drawable.gender_male)
}
"female" -> {
setChipBackgroundColorResource(R.color.material_pink_600)
setTextColor(ContextCompat.getColor(context, android.R.color.white))
- ContextCompat.getDrawable(context, R.drawable.ic_gender_female_white)
+ ContextCompat.getDrawable(context, R.drawable.gender_female)
}
else -> null
}
@@ -237,6 +240,15 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri
}
galleryblock_id.text = galleryBlock.id.toString()
+ galleryblock_pagecount.text = "-"
+ CoroutineScope(Dispatchers.IO).launch {
+ val pageCount = kotlin.runCatching {
+ getReader(galleryBlock.id).galleryInfo.files.size
+ }.getOrNull() ?: return@launch
+ withContext(Dispatchers.Main) {
+ galleryblock_pagecount.text = context.getString(R.string.galleryblock_pagecount, pageCount)
+ }
+ }
if (!::favorites.isInitialized)
favorites = (context.applicationContext as Pupil).favorites
diff --git a/app/src/main/java/xyz/quaver/pupil/adapters/MirrorAdapter.kt b/app/src/main/java/xyz/quaver/pupil/adapters/MirrorAdapter.kt
index 273922e9..91362fb6 100644
--- a/app/src/main/java/xyz/quaver/pupil/adapters/MirrorAdapter.kt
+++ b/app/src/main/java/xyz/quaver/pupil/adapters/MirrorAdapter.kt
@@ -18,6 +18,7 @@
package xyz.quaver.pupil.adapters
+import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.MotionEvent
@@ -60,6 +61,7 @@ class MirrorAdapter(context: Context) : RecyclerView.Adapter Unit)? = null
var onItemMoved : ((List) -> (Unit))? = null
+ @SuppressLint("ClickableViewAccessibility")
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
with(holder.view) {
mirror_name.text = mirrors[list.elementAt(position)]
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 04c3aa44..d008e837 100644
--- a/app/src/main/java/xyz/quaver/pupil/adapters/ReaderAdapter.kt
+++ b/app/src/main/java/xyz/quaver/pupil/adapters/ReaderAdapter.kt
@@ -25,15 +25,15 @@ import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.engine.DiskCacheStrategy
-import com.crashlytics.android.Crashlytics
-import io.fabric.sdk.android.Fabric
+import com.google.android.material.snackbar.Snackbar
+import com.google.firebase.crashlytics.FirebaseCrashlytics
+import kotlinx.android.synthetic.main.activity_reader.view.*
import kotlinx.android.synthetic.main.item_reader.view.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import xyz.quaver.hitomi.Reader
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
@@ -51,6 +51,8 @@ class ReaderAdapter(private val glide: RequestManager,
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view)
+ var downloadWorker: DownloadWorker? = null
+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return LayoutInflater.from(parent.context).inflate(
R.layout.item_reader, parent, false
@@ -62,6 +64,9 @@ class ReaderAdapter(private val glide: RequestManager,
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.view as ConstraintLayout
+ if (downloadWorker == null)
+ downloadWorker = DownloadWorker.getInstance(holder.view.context)
+
if (isFullScreen) {
holder.view.layoutParams.height = RecyclerView.LayoutParams.MATCH_PARENT
holder.view.container.layoutParams.height = ConstraintLayout.LayoutParams.MATCH_PARENT
@@ -83,15 +88,15 @@ class ReaderAdapter(private val glide: RequestManager,
holder.view.reader_index.text = (position+1).toString()
- val images = Cache(holder.view.context).getImage(galleryID, position)
- val progress = DownloadWorker.getInstance(holder.view.context).progress[galleryID]?.get(position)
+ val image = downloadWorker!!.results[galleryID]?.get(position)
+ val progress = downloadWorker!!.progress[galleryID]?.get(position)
- if (progress?.isInfinite() == true && images != null) {
+ if (progress?.isInfinite() == true && image != null) {
holder.view.reader_item_progressbar.visibility = View.INVISIBLE
holder.view.image.post {
glide
- .load(images)
+ .load(image)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.fitCenter()
@@ -105,13 +110,22 @@ class ReaderAdapter(private val glide: RequestManager,
glide.clear(holder.view.image)
if (progress?.isNaN() == true) {
- if (Fabric.isInitialized())
- Crashlytics.logException(DownloadWorker.getInstance(holder.view.context).exception[galleryID]?.get(position))
+ 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 =
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/LockActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/LockActivity.kt
index f8d77d95..144ec79d 100644
--- a/app/src/main/java/xyz/quaver/pupil/ui/LockActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/LockActivity.kt
@@ -21,23 +21,157 @@ package xyz.quaver.pupil.ui
import android.app.Activity
import android.app.AlertDialog
import android.os.Bundle
+import android.view.animation.Animation
+import android.view.animation.AnimationUtils
import androidx.appcompat.app.AppCompatActivity
+import androidx.biometric.BiometricManager
+import androidx.biometric.BiometricPrompt
+import androidx.core.content.ContextCompat
+import androidx.preference.PreferenceManager
import com.andrognito.patternlockview.PatternLockView
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_lock.*
import kotlinx.android.synthetic.main.fragment_pattern_lock.*
+import kotlinx.android.synthetic.main.fragment_pin_lock.*
import xyz.quaver.pupil.R
+import xyz.quaver.pupil.ui.fragment.PINLockFragment
import xyz.quaver.pupil.ui.fragment.PatternLockFragment
import xyz.quaver.pupil.util.Lock
import xyz.quaver.pupil.util.LockManager
class LockActivity : AppCompatActivity() {
+ private lateinit var lockManager: LockManager
+ private var mode: String? = null
+
+ private val patternLockFragment = PatternLockFragment().apply {
+ var lastPass = ""
+ onPatternDrawn = {
+ when(mode) {
+ null -> {
+ val result = lockManager.check(it)
+
+ if (result == true) {
+ setResult(Activity.RESULT_OK)
+ finish()
+ } else
+ lock_pattern_view.setViewMode(PatternLockView.PatternViewMode.WRONG)
+ }
+ "add_lock" -> {
+ if (lastPass.isEmpty()) {
+ lastPass = it
+
+ Snackbar.make(view!!, R.string.settings_lock_confirm, Snackbar.LENGTH_LONG).show()
+ } else {
+ if (lastPass == it) {
+ LockManager(context!!).add(Lock.generate(Lock.Type.PATTERN, it))
+ finish()
+ } else {
+ lock_pattern_view.setViewMode(PatternLockView.PatternViewMode.WRONG)
+ lastPass = ""
+
+ Snackbar.make(view!!, R.string.settings_lock_wrong_confirm, Snackbar.LENGTH_LONG).show()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private val pinLockFragment = PINLockFragment().apply {
+ var lastPass = ""
+ onPINEntered = {
+ when(mode) {
+ null -> {
+ val result = lockManager.check(it)
+
+ if (result == true) {
+ setResult(Activity.RESULT_OK)
+ finish()
+ } else {
+ indicator_dots.startAnimation(AnimationUtils.loadAnimation(context, R.anim.shake).apply {
+ setAnimationListener(object: Animation.AnimationListener {
+ override fun onAnimationEnd(animation: Animation?) {
+ pin_lock_view.resetPinLockView()
+ pin_lock_view.isEnabled = true
+ }
+
+ override fun onAnimationStart(animation: Animation?) {
+ pin_lock_view.isEnabled = false
+ }
+
+ override fun onAnimationRepeat(animation: Animation?) {
+ // Do Nothing
+ }
+ })
+ })
+ }
+ }
+ "add_lock" -> {
+ if (lastPass.isEmpty()) {
+ lastPass = it
+
+ pin_lock_view.resetPinLockView()
+ Snackbar.make(view!!, R.string.settings_lock_confirm, Snackbar.LENGTH_LONG).show()
+ } else {
+ if (lastPass == it) {
+ LockManager(context!!).add(Lock.generate(Lock.Type.PIN, it))
+ finish()
+ } else {
+ indicator_dots.startAnimation(AnimationUtils.loadAnimation(context, R.anim.shake).apply {
+ setAnimationListener(object: Animation.AnimationListener {
+ override fun onAnimationEnd(animation: Animation?) {
+ pin_lock_view.resetPinLockView()
+ pin_lock_view.isEnabled = true
+ }
+
+ override fun onAnimationStart(animation: Animation?) {
+ pin_lock_view.isEnabled = false
+ }
+
+ override fun onAnimationRepeat(animation: Animation?) {
+ // Do Nothing
+ }
+ })
+ })
+ lastPass = ""
+
+ Snackbar.make(view!!, R.string.settings_lock_wrong_confirm, Snackbar.LENGTH_LONG).show()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private fun showBiometricPrompt() {
+ val promptInfo = BiometricPrompt.PromptInfo.Builder()
+ .setTitle(getText(R.string.settings_lock_fingerprint_prompt))
+ .setSubtitle(getText(R.string.settings_lock_fingerprint_prompt_subtitle))
+ .setNegativeButtonText(getText(android.R.string.cancel))
+ .setConfirmationRequired(false)
+ .build()
+
+ val biometricPrompt = BiometricPrompt(this, ContextCompat.getMainExecutor(this),
+ object : BiometricPrompt.AuthenticationCallback() {
+ override fun onAuthenticationSucceeded(
+ result: BiometricPrompt.AuthenticationResult) {
+ super.onAuthenticationSucceeded(result)
+ setResult(RESULT_OK)
+ finish()
+ return
+ }
+ })
+
+ // Displays the "log in" prompt.
+ biometricPrompt.authenticate(promptInfo)
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_lock)
- val lockManager = try {
+ lockManager = try {
LockManager(this)
} catch (e: Exception) {
AlertDialog.Builder(this).apply {
@@ -50,12 +184,7 @@ class LockActivity : AppCompatActivity() {
return
}
- val mode = intent.getStringExtra("mode")
-
- lock_pattern.isEnabled = false
- lock_pin.isEnabled = false
- lock_fingerprint.isEnabled = false
- lock_password.isEnabled = false
+ mode = intent.getStringExtra("mode")
when(mode) {
null -> {
@@ -64,52 +193,75 @@ class LockActivity : AppCompatActivity() {
finish()
return
}
+
+ if (
+ PreferenceManager.getDefaultSharedPreferences(this).getBoolean("lock_fingerprint", false)
+ && BiometricManager.from(this).canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS
+ ) {
+ lock_fingerprint.apply {
+ isEnabled = true
+ setOnClickListener {
+ showBiometricPrompt()
+ }
+ }
+ showBiometricPrompt()
+ }
+
+ lock_pattern.apply {
+ isEnabled = lockManager.contains(Lock.Type.PATTERN)
+ setOnClickListener {
+ supportFragmentManager.beginTransaction().replace(
+ R.id.lock_content, patternLockFragment
+ ).commit()
+ }
+ }
+ lock_pin.apply {
+ isEnabled = lockManager.contains(Lock.Type.PIN)
+ setOnClickListener {
+ supportFragmentManager.beginTransaction().replace(
+ R.id.lock_content, pinLockFragment
+ ).commit()
+ }
+ }
+ lock_password.isEnabled = false
+
+ when (lockManager.locks!!.first().type) {
+ Lock.Type.PIN -> {
+
+ supportFragmentManager.beginTransaction().add(
+ R.id.lock_content, pinLockFragment
+ ).commit()
+ }
+ Lock.Type.PATTERN -> {
+ supportFragmentManager.beginTransaction().add(
+ R.id.lock_content, patternLockFragment
+ ).commit()
+ }
+ else -> return
+ }
}
"add_lock" -> {
+ lock_pattern.isEnabled = false
+ lock_pin.isEnabled = false
+ lock_fingerprint.isEnabled = false
+ lock_password.isEnabled = false
+
when(intent.getStringExtra("type")!!) {
"pattern" -> {
-
+ lock_pattern.isEnabled = true
+ supportFragmentManager.beginTransaction().add(
+ R.id.lock_content, patternLockFragment
+ ).commit()
+ }
+ "pin" -> {
+ lock_pin.isEnabled = true
+ supportFragmentManager.beginTransaction().add(
+ R.id.lock_content, pinLockFragment
+ ).commit()
}
}
}
}
-
- supportFragmentManager.beginTransaction().add(
- R.id.lock_content,
- PatternLockFragment().apply {
- var lastPass = ""
- onPatternDrawn = {
- when(mode) {
- null -> {
- val result = lockManager.check(it)
-
- if (result == true) {
- setResult(Activity.RESULT_OK)
- finish()
- } else
- lock_pattern_view.setViewMode(PatternLockView.PatternViewMode.WRONG)
- }
- "add_lock" -> {
- if (lastPass.isEmpty()) {
- lastPass = it
-
- Snackbar.make(view!!, R.string.settings_lock_confirm, Snackbar.LENGTH_LONG).show()
- } else {
- if (lastPass == it) {
- LockManager(context!!).add(Lock.generate(Lock.Type.PATTERN, it))
- finish()
- } else {
- lock_pattern_view.setViewMode(PatternLockView.PatternViewMode.WRONG)
- lastPass = ""
-
- Snackbar.make(view!!, R.string.settings_lock_wrong_confirm, Snackbar.LENGTH_LONG).show()
- }
- }
- }
- }
- }
- }
- ).commit()
}
}
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 714d4fb2..65f37e9e 100644
--- a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt
@@ -18,6 +18,7 @@
package xyz.quaver.pupil.ui
+import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.graphics.drawable.Animatable
@@ -30,10 +31,7 @@ import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.EditorInfo
-import android.widget.EditText
-import android.widget.ImageView
-import android.widget.LinearLayout
-import android.widget.TextView
+import android.widget.*
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.cardview.widget.CardView
@@ -43,12 +41,12 @@ import androidx.core.view.GravityCompat
import androidx.preference.PreferenceManager
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
import com.arlib.floatingsearchview.FloatingSearchView
+import com.arlib.floatingsearchview.FloatingSearchViewDayNight
import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion
import com.arlib.floatingsearchview.util.view.SearchInputView
import com.bumptech.glide.Glide
-import com.crashlytics.android.Crashlytics
import com.google.android.material.appbar.AppBarLayout
-import io.fabric.sdk.android.Fabric
+import com.google.firebase.crashlytics.FirebaseCrashlytics
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.activity_main_content.*
import kotlinx.coroutines.*
@@ -146,6 +144,30 @@ 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) {
@@ -421,6 +443,7 @@ class MainActivity : AppCompatActivity() {
loadBlocks()
}
+ @SuppressLint("ClickableViewAccessibility")
private fun setupRecyclerView() {
with(main_recyclerview) {
adapter = GalleryBlockAdapter(Glide.with(this@MainActivity), galleries).apply {
@@ -438,13 +461,16 @@ class MainActivity : AppCompatActivity() {
onDownloadClickedHandler = { position ->
val galleryID = galleries[position].id
val worker = DownloadWorker.getInstance(context)
-
- if (Cache(context).isDownloading(galleryID)) //download in progress
- worker.cancel(galleryID)
+ if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean("cache_disable", false))
+ Toast.makeText(context, R.string.settings_download_when_cache_disable_warning, Toast.LENGTH_SHORT).show()
else {
- Cache(context).setDownloading(galleryID, true)
+ if (Cache(context).isDownloading(galleryID)) //download in progress
+ worker.cancel(galleryID)
+ else {
+ Cache(context).setDownloading(galleryID, true)
- worker.queue.add(galleryID)
+ worker.queue.add(galleryID)
+ }
}
closeAllItems()
@@ -742,7 +768,7 @@ class MainActivity : AppCompatActivity() {
})
searchInputView.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
- with(main_searchview as FloatingSearchView) {
+ with(main_searchview as FloatingSearchViewDayNight) {
val favoritesFile = File(ContextCompat.getDataDir(context), "favorites_tags.json")
val serializer = Tag.serializer().list
@@ -845,14 +871,14 @@ class MainActivity : AppCompatActivity() {
ResourcesCompat.getDrawable(
resources,
when(item.n) {
- "female" -> R.drawable.ic_gender_female
- "male" -> R.drawable.ic_gender_male
- "language" -> R.drawable.ic_translate
- "group" -> R.drawable.ic_account_group
- "character" -> R.drawable.ic_account_star
- "series" -> R.drawable.ic_book_open
- "artist" -> R.drawable.ic_brush
- else -> R.drawable.ic_tag
+ "female" -> R.drawable.gender_female
+ "male" -> R.drawable.gender_male
+ "language" -> R.drawable.translate
+ "group" -> R.drawable.account_group
+ "character" -> R.drawable.account_star
+ "series" -> R.drawable.book_open
+ "artist" -> R.drawable.brush
+ else -> R.drawable.tag
},
null)
)
@@ -1058,8 +1084,8 @@ class MainActivity : AppCompatActivity() {
}
} catch (e: Exception) {
- if (Fabric.isInitialized() && e.message != "No result")
- Crashlytics.logException(e)
+ if (e.message != "No result")
+ FirebaseCrashlytics.getInstance().recordException(e)
withContext(Dispatchers.Main) {
main_noresult.visibility = View.VISIBLE
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 64cb2b5d..7681698f 100644
--- a/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt
@@ -23,6 +23,7 @@ import android.graphics.drawable.Animatable
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.view.*
+import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
@@ -33,9 +34,8 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
import com.bumptech.glide.Glide
-import com.crashlytics.android.Crashlytics
import com.google.android.material.snackbar.Snackbar
-import io.fabric.sdk.android.Fabric
+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.*
@@ -91,8 +91,7 @@ class ReaderActivity : AppCompatActivity() {
handleIntent(intent)
- if (Fabric.isInitialized())
- Crashlytics.setInt("GalleryID", galleryID)
+ FirebaseCrashlytics.getInstance().setCustomKey("GalleryID", galleryID)
if (galleryID == 0) {
onBackPressed()
@@ -113,14 +112,12 @@ class ReaderActivity : AppCompatActivity() {
val uri = intent.data
val lastPathSegment = uri?.lastPathSegment
if (uri != null && lastPathSegment != null) {
- val nonNumber = Regex("[^-?0-9]+")
-
galleryID = when (uri.host) {
- "hitomi.la" -> lastPathSegment.replace(nonNumber, "").toInt()
- "히요비.asia" -> lastPathSegment.toInt()
- "xn--9w3b15m8vo.asia" -> lastPathSegment.toInt()
+ "hitomi.la" ->
+ Regex("([0-9]+).html").find(lastPathSegment)?.groupValues?.get(1)?.toIntOrNull() ?: 0
+ "hiyobi.me" -> lastPathSegment.toInt()
"e-hentai.org" -> uri.pathSegments[1].toInt()
- else -> return
+ else -> 0
}
}
} else {
@@ -325,13 +322,27 @@ class ReaderActivity : AppCompatActivity() {
animateDownloadFAB(Cache(context).isDownloading(galleryID)) //If download in progress, animate button
setOnClickListener {
- if (Cache(context).isDownloading(galleryID)) {
- Cache(context).setDownloading(galleryID, false)
+ if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean("cache_disable", false))
+ Toast.makeText(context, R.string.settings_download_when_cache_disable_warning, Toast.LENGTH_SHORT).show()
+ else {
+ if (Cache(context).isDownloading(galleryID)) {
+ Cache(context).setDownloading(galleryID, false)
- animateDownloadFAB(false)
- } else {
- Cache(context).setDownloading(galleryID, true)
- animateDownloadFAB(true)
+ animateDownloadFAB(false)
+ } else {
+ Cache(context).setDownloading(galleryID, true)
+ animateDownloadFAB(true)
+ }
+ }
+ }
+ }
+
+ with(reader_fab_retry) {
+ setImageResource(R.drawable.refresh)
+ setOnClickListener {
+ DownloadWorker.getInstance(context).let {
+ it.cancel(galleryID)
+ it.queue.add(galleryID)
}
}
}
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt
index 20621e38..7bc79d66 100644
--- a/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt
@@ -35,7 +35,7 @@ import kotlinx.serialization.builtins.serializer
import net.rdrei.android.dirchooser.DirectoryChooserActivity
import xyz.quaver.pupil.Pupil
import xyz.quaver.pupil.R
-import xyz.quaver.pupil.ui.fragment.LockFragment
+import xyz.quaver.pupil.ui.fragment.LockSettingsFragment
import xyz.quaver.pupil.ui.fragment.SettingsFragment
import xyz.quaver.pupil.util.*
import java.io.File
@@ -84,7 +84,7 @@ class SettingsActivity : AppCompatActivity() {
if (resultCode == Activity.RESULT_OK) {
supportFragmentManager
.beginTransaction()
- .replace(R.id.settings, LockFragment())
+ .replace(R.id.settings, LockSettingsFragment())
.addToBackStack("Lock")
.commitAllowingStateLoss()
}
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/dialog/DefaultQueryDialog.kt b/app/src/main/java/xyz/quaver/pupil/ui/dialog/DefaultQueryDialog.kt
index 3d39c6e4..94029cd5 100644
--- a/app/src/main/java/xyz/quaver/pupil/ui/dialog/DefaultQueryDialog.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/dialog/DefaultQueryDialog.kt
@@ -45,6 +45,7 @@ class DefaultQueryDialog(context : Context) : AlertDialog(context) {
private val excludeBL = "-male:yaoi"
private val excludeGuro = listOf("-female:guro", "-male:guro")
+ private val excludeLoli = listOf("-female:loli", "-male:shota")
var onPositiveButtonClickListener : ((Tags) -> (Unit))? = null
@@ -68,6 +69,11 @@ class DefaultQueryDialog(context : Context) : AlertDialog(context) {
newTags.add(tag)
}
+ if (default_query_dialog_loli_checkbox.isChecked)
+ excludeLoli.forEach { tag ->
+ newTags.add(tag)
+ }
+
onPositiveButtonClickListener?.invoke(newTags)
}
@@ -120,6 +126,14 @@ class DefaultQueryDialog(context : Context) : AlertDialog(context) {
}
}
+ with(view.default_query_dialog_loli_checkbox) {
+ isChecked = excludeLoli.all { tags.contains(it) }
+ if (excludeLoli.all { tags.contains(it) })
+ excludeLoli.forEach {
+ tags.remove(it)
+ }
+ }
+
with(view.default_query_dialog_edittext) {
setText(tags.toString(), android.widget.TextView.BufferType.EDITABLE)
addTextChangedListener(object : TextWatcher {
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/dialog/GalleryDialog.kt b/app/src/main/java/xyz/quaver/pupil/ui/dialog/GalleryDialog.kt
index 06c87882..548c3aec 100644
--- a/app/src/main/java/xyz/quaver/pupil/ui/dialog/GalleryDialog.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/dialog/GalleryDialog.kt
@@ -18,7 +18,6 @@
package xyz.quaver.pupil.ui.dialog
-import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.content.Intent
@@ -170,12 +169,12 @@ class GalleryDialog(context: Context, private val glide: RequestManager, private
"male" -> {
setChipBackgroundColorResource(R.color.material_blue_700)
setTextColor(ContextCompat.getColor(context, android.R.color.white))
- ContextCompat.getDrawable(context, R.drawable.ic_gender_male_white)
+ ContextCompat.getDrawable(context, R.drawable.gender_male)
}
"female" -> {
setChipBackgroundColorResource(R.color.material_pink_600)
setTextColor(ContextCompat.getColor(context, android.R.color.white))
- ContextCompat.getDrawable(context, R.drawable.ic_gender_female_white)
+ ContextCompat.getDrawable(context, R.drawable.gender_female)
}
else -> null
}
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/fragment/LockFragment.kt b/app/src/main/java/xyz/quaver/pupil/ui/fragment/LockFragment.kt
deleted file mode 100644
index b95900c1..00000000
--- a/app/src/main/java/xyz/quaver/pupil/ui/fragment/LockFragment.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Pupil, Hitomi.la viewer for Android
- * Copyright (C) 2020 tom5079
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package xyz.quaver.pupil.ui.fragment
-
-import android.content.Intent
-import android.os.Bundle
-import androidx.appcompat.app.AlertDialog
-import androidx.preference.Preference
-import androidx.preference.PreferenceFragmentCompat
-import xyz.quaver.pupil.R
-import xyz.quaver.pupil.ui.LockActivity
-import xyz.quaver.pupil.util.Lock
-import xyz.quaver.pupil.util.LockManager
-
-class LockFragment : PreferenceFragmentCompat() {
-
- override fun onResume() {
- super.onResume()
-
- val lockManager = LockManager(context!!)
-
- findPreference("lock_pattern")?.summary =
- if (lockManager.contains(Lock.Type.PATTERN))
- getString(R.string.settings_lock_enabled)
- else
- ""
- }
-
- override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
- setPreferencesFromResource(R.xml.lock_preferences, rootKey)
-
- with(findPreference("lock_pattern")) {
- this!!
-
- if (LockManager(context!!).contains(Lock.Type.PATTERN))
- summary = getString(R.string.settings_lock_enabled)
-
- onPreferenceClickListener = Preference.OnPreferenceClickListener {
- val lockManager = LockManager(context!!)
-
- if (lockManager.contains(Lock.Type.PATTERN)) {
- AlertDialog.Builder(context).apply {
- setTitle(R.string.warning)
- setMessage(R.string.settings_lock_remove_message)
-
- setPositiveButton(android.R.string.yes) { _, _ ->
- lockManager.remove(Lock.Type.PATTERN)
- onResume()
- }
- setNegativeButton(android.R.string.no) { _, _ -> }
- }.show()
- } else {
- val intent = Intent(context, LockActivity::class.java).apply {
- putExtra("mode", "add_lock")
- putExtra("type", "pattern")
- }
-
- startActivity(intent)
- }
-
- true
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/fragment/LockSettingsFragment.kt b/app/src/main/java/xyz/quaver/pupil/ui/fragment/LockSettingsFragment.kt
new file mode 100644
index 00000000..c4a76ee0
--- /dev/null
+++ b/app/src/main/java/xyz/quaver/pupil/ui/fragment/LockSettingsFragment.kt
@@ -0,0 +1,147 @@
+/*
+ * Pupil, Hitomi.la viewer for Android
+ * Copyright (C) 2020 tom5079
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package xyz.quaver.pupil.ui.fragment
+
+import android.content.Intent
+import android.os.Bundle
+import android.widget.Toast
+import androidx.appcompat.app.AlertDialog
+import androidx.preference.Preference
+import androidx.preference.PreferenceFragmentCompat
+import androidx.preference.PreferenceManager
+import androidx.preference.SwitchPreferenceCompat
+import xyz.quaver.pupil.R
+import xyz.quaver.pupil.ui.LockActivity
+import xyz.quaver.pupil.util.Lock
+import xyz.quaver.pupil.util.LockManager
+
+class LockSettingsFragment :
+ PreferenceFragmentCompat() {
+
+ override fun onResume() {
+ super.onResume()
+
+ val lockManager = LockManager(requireContext())
+
+ findPreference("lock_pattern")?.summary =
+ if (lockManager.contains(Lock.Type.PATTERN))
+ getString(R.string.settings_lock_enabled)
+ else
+ ""
+
+ findPreference("lock_pin")?.summary =
+ if (lockManager.contains(Lock.Type.PIN))
+ getString(R.string.settings_lock_enabled)
+ else
+ ""
+
+ if (lockManager.isEmpty()) {
+ (findPreference("lock_fingerprint") as SwitchPreferenceCompat).isChecked = false
+
+ PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean("lock_fingerprint", false).apply()
+ }
+ }
+
+ override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+ setPreferencesFromResource(R.xml.lock_preferences, rootKey)
+
+ with(findPreference("lock_pattern")) {
+ this!!
+
+ if (LockManager(requireContext()).contains(Lock.Type.PATTERN))
+ summary = getString(R.string.settings_lock_enabled)
+
+ onPreferenceClickListener = Preference.OnPreferenceClickListener {
+ val lockManager = LockManager(requireContext())
+
+ if (lockManager.contains(Lock.Type.PATTERN)) {
+ AlertDialog.Builder(requireContext()).apply {
+ setTitle(R.string.warning)
+ setMessage(R.string.settings_lock_remove_message)
+
+ setPositiveButton(android.R.string.yes) { _, _ ->
+ lockManager.remove(Lock.Type.PATTERN)
+ onResume()
+ }
+ setNegativeButton(android.R.string.no) { _, _ -> }
+ }.show()
+ } else {
+ val intent = Intent(requireContext(), LockActivity::class.java).apply {
+ putExtra("mode", "add_lock")
+ putExtra("type", "pattern")
+ }
+
+ startActivity(intent)
+ }
+
+ true
+ }
+ }
+
+ with(findPreference("lock_pin")) {
+ this!!
+
+ if (LockManager(requireContext()).contains(Lock.Type.PIN))
+ summary = getString(R.string.settings_lock_enabled)
+
+ onPreferenceClickListener = Preference.OnPreferenceClickListener {
+ val lockManager = LockManager(requireContext())
+
+ if (lockManager.contains(Lock.Type.PIN)) {
+ AlertDialog.Builder(requireContext()).apply {
+ setTitle(R.string.warning)
+ setMessage(R.string.settings_lock_remove_message)
+
+ setPositiveButton(android.R.string.yes) { _, _ ->
+ lockManager.remove(Lock.Type.PIN)
+ onResume()
+ }
+ setNegativeButton(android.R.string.no) { _, _ -> }
+ }.show()
+ } else {
+ val intent = Intent(requireContext(), LockActivity::class.java).apply {
+ putExtra("mode", "add_lock")
+ putExtra("type", "pin")
+ }
+
+ startActivity(intent)
+ }
+
+ true
+ }
+ }
+
+ with(findPreference("lock_fingerprint")) {
+ this!!
+
+ setOnPreferenceChangeListener { _, newValue ->
+ this as SwitchPreferenceCompat
+
+ if (newValue == true && LockManager(requireContext()).isEmpty()) {
+ isChecked = false
+
+ Toast.makeText(requireContext(), R.string.settings_lock_fingerprint_without_lock, Toast.LENGTH_SHORT).show()
+ } else
+ isChecked = newValue as Boolean
+
+ false
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/fragment/PINLockFragment.kt b/app/src/main/java/xyz/quaver/pupil/ui/fragment/PINLockFragment.kt
new file mode 100644
index 00000000..b058840d
--- /dev/null
+++ b/app/src/main/java/xyz/quaver/pupil/ui/fragment/PINLockFragment.kt
@@ -0,0 +1,53 @@
+/*
+ * Pupil, Hitomi.la viewer for Android
+ * Copyright (C) 2020 tom5079
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package xyz.quaver.pupil.ui.fragment
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.andrognito.pinlockview.PinLockListener
+import kotlinx.android.synthetic.main.fragment_pin_lock.view.*
+import xyz.quaver.pupil.R
+
+class PINLockFragment : Fragment(), PinLockListener {
+
+ var onPINEntered: ((String) -> Unit)? = null
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return inflater.inflate(R.layout.fragment_pin_lock, container, false).apply {
+ pin_lock_view.attachIndicatorDots(indicator_dots)
+ pin_lock_view.setPinLockListener(this@PINLockFragment)
+ }
+ }
+
+ override fun onComplete(pin: String?) {
+ onPINEntered?.invoke(pin!!)
+ }
+
+ override fun onEmpty() {
+
+ }
+
+ override fun onPinChange(pinLength: Int, intermediatePin: String?) {
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt b/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt
index 7f6b8004..d975355d 100644
--- a/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt
@@ -19,11 +19,11 @@
package xyz.quaver.pupil.ui.fragment
import android.Manifest
-import android.content.Intent
-import android.content.SharedPreferences
+import android.content.*
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
+import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.app.ActivityCompat
@@ -53,16 +53,12 @@ class SettingsFragment :
Preference.OnPreferenceChangeListener,
SharedPreferences.OnSharedPreferenceChangeListener {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- PreferenceManager.getDefaultSharedPreferences(context).registerOnSharedPreferenceChangeListener(this)
- }
+ lateinit var sharedPreference: SharedPreferences
override fun onResume() {
super.onResume()
- val lockManager = LockManager(context!!)
+ val lockManager = LockManager(requireContext())
findPreference("app_lock")?.summary = if (lockManager.locks.isNullOrEmpty()) {
getString(R.string.settings_lock_none)
@@ -92,9 +88,9 @@ class SettingsFragment :
checkUpdate(activity as SettingsActivity, true)
}
"delete_cache" -> {
- val dir = File(context.cacheDir, "imageCache")
+ val dir = File(requireContext().cacheDir, "imageCache")
- AlertDialog.Builder(context).apply {
+ AlertDialog.Builder(requireContext()).apply {
setTitle(R.string.warning)
setMessage(R.string.settings_clear_cache_alert_message)
setPositiveButton(android.R.string.yes) { _, _ ->
@@ -107,9 +103,9 @@ class SettingsFragment :
}.show()
}
"delete_downloads" -> {
- val dir = getDownloadDirectory(context)
+ val dir = getDownloadDirectory(requireContext())
- AlertDialog.Builder(context).apply {
+ AlertDialog.Builder(requireContext()).apply {
setTitle(R.string.warning)
setMessage(R.string.settings_clear_downloads_alert_message)
setPositiveButton(android.R.string.yes) { _, _ ->
@@ -122,9 +118,9 @@ class SettingsFragment :
}.show()
}
"clear_history" -> {
- val histories = (context.applicationContext as Pupil).histories
+ val histories = (requireContext().applicationContext as Pupil).histories
- AlertDialog.Builder(context).apply {
+ AlertDialog.Builder(requireContext()).apply {
setTitle(R.string.warning)
setMessage(R.string.settings_clear_history_alert_message)
setPositiveButton(android.R.string.yes) { _, _ ->
@@ -135,10 +131,10 @@ class SettingsFragment :
}.show()
}
"dl_location" -> {
- DownloadLocationDialog(activity!!).show()
+ DownloadLocationDialog(requireActivity()).show()
}
"default_query" -> {
- DefaultQueryDialog(context).apply {
+ DefaultQueryDialog(requireContext()).apply {
onPositiveButtonClickListener = { newTags ->
sharedPreferences.edit().putString("default_query", newTags.toString()).apply()
summary = newTags.toString()
@@ -146,20 +142,23 @@ class SettingsFragment :
}.show()
}
"app_lock" -> {
- val intent = Intent(context, LockActivity::class.java)
+ val intent = Intent(requireContext(), LockActivity::class.java)
activity?.startActivityForResult(intent, REQUEST_LOCK)
}
"mirrors" -> {
- MirrorDialog(context)
+ MirrorDialog(requireContext())
.show()
}
"proxy" -> {
- ProxyDialog(context)
+ ProxyDialog(requireContext())
.show()
}
+ "nomedia" -> {
+ File(getDownloadDirectory(context), ".nomedia").createNewFile()
+ }
"backup" -> {
- File(ContextCompat.getDataDir(context), "favorites.json").copyTo(
- File(getDownloadDirectory(context), "favorites.json"),
+ File(ContextCompat.getDataDir(requireContext()), "favorites.json").copyTo(
+ File(getDownloadDirectory(requireContext()), "favorites.json"),
true
)
@@ -177,8 +176,8 @@ class SettingsFragment :
"old_import_galleries" -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
- ActivityCompat.requestPermissions(activity!!, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_WRITE_PERMISSION_AND_SAF)
+ if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
+ ActivityCompat.requestPermissions(requireActivity(), arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_WRITE_PERMISSION_AND_SAF)
else {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
putExtra("android.content.extra.SHOW_ADVANCED", true)
@@ -192,13 +191,19 @@ class SettingsFragment :
.allowNewDirectoryNameModification(true)
.build()
- val intent = Intent(context, DirectoryChooserActivity::class.java).apply {
+ val intent = Intent(requireContext(), DirectoryChooserActivity::class.java).apply {
putExtra(DirectoryChooserActivity.EXTRA_CONFIG, config)
}
activity?.startActivityForResult(intent, REQUEST_IMPORT_OLD_GALLERIES_OLD)
}
}
+ "user_id" -> {
+ (context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager).setPrimaryClip(
+ ClipData.newPlainText("user_id", sharedPreference.getString("user_id", ""))
+ )
+ Toast.makeText(context, R.string.settings_user_id_toast, Toast.LENGTH_SHORT).show()
+ }
else -> return false
}
}
@@ -232,10 +237,10 @@ class SettingsFragment :
when (key) {
"proxy" -> {
- summary = getProxyInfo(context).type.name
+ summary = getProxyInfo(requireContext()).type.name
}
"dl_location" -> {
- summary = getDownloadDirectory(context!!).canonicalPath
+ summary = getDownloadDirectory(requireContext()).canonicalPath
}
}
}
@@ -244,6 +249,9 @@ class SettingsFragment :
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
+ sharedPreference = PreferenceManager.getDefaultSharedPreferences(requireContext())
+ sharedPreference.registerOnSharedPreferenceChangeListener(this)
+
initPreferences()
}
@@ -260,42 +268,42 @@ class SettingsFragment :
when (key) {
"app_version" -> {
- val manager = context.packageManager
- val info = manager.getPackageInfo(context.packageName, 0)
- summary = context.getString(R.string.settings_app_version_description, info.versionName)
+ val manager = requireContext().packageManager
+ val info = manager.getPackageInfo(requireContext().packageName, 0)
+ summary = requireContext().getString(R.string.settings_app_version_description, info.versionName)
onPreferenceClickListener = this@SettingsFragment
}
"delete_cache" -> {
- val dir = File(context.cacheDir, "imageCache")
+ val dir = File(requireContext().cacheDir, "imageCache")
summary = getDirSize(dir)
onPreferenceClickListener = this@SettingsFragment
}
"delete_downloads" -> {
- val dir = getDownloadDirectory(context)
+ val dir = getDownloadDirectory(requireContext())
summary = getDirSize(dir)
onPreferenceClickListener = this@SettingsFragment
}
"clear_history" -> {
- val histories = (activity!!.application as Pupil).histories
+ val histories = (requireActivity().application as Pupil).histories
summary = getString(R.string.settings_clear_history_summary, histories.size)
onPreferenceClickListener = this@SettingsFragment
}
"dl_location" -> {
- summary = getDownloadDirectory(context).canonicalPath
+ summary = getDownloadDirectory(requireContext()).canonicalPath
onPreferenceClickListener = this@SettingsFragment
}
"default_query" -> {
- summary = PreferenceManager.getDefaultSharedPreferences(context).getString("default_query", "") ?: ""
+ summary = sharedPreference.getString("default_query", "") ?: ""
onPreferenceClickListener = this@SettingsFragment
}
"app_lock" -> {
- val lockManager = LockManager(context)
+ val lockManager = LockManager(requireContext())
summary =
if (lockManager.locks.isNullOrEmpty()) {
getString(R.string.settings_lock_none)
@@ -315,13 +323,16 @@ class SettingsFragment :
onPreferenceClickListener = this@SettingsFragment
}
"proxy" -> {
- summary = getProxyInfo(context).type.name
+ summary = getProxyInfo(requireContext()).type.name
onPreferenceClickListener = this@SettingsFragment
}
"dark_mode" -> {
onPreferenceChangeListener = this@SettingsFragment
}
+ "nomedia" -> {
+ onPreferenceClickListener = this@SettingsFragment
+ }
"backup" -> {
onPreferenceClickListener = this@SettingsFragment
}
@@ -331,6 +342,10 @@ class SettingsFragment :
"old_import_galleries" -> {
onPreferenceClickListener = this@SettingsFragment
}
+ "user_id" -> {
+ summary = sharedPreference.getString("user_id", "")
+ onPreferenceClickListener = this@SettingsFragment
+ }
}
}
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 617d3dd3..deb4c25c 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
@@ -24,7 +24,7 @@ import android.util.Base64
import android.util.Log
import android.util.SparseArray
import androidx.preference.PreferenceManager
-import com.crashlytics.android.Crashlytics
+import com.google.firebase.crashlytics.FirebaseCrashlytics
import kotlinx.coroutines.*
import xyz.quaver.Code
import xyz.quaver.hitomi.GalleryBlock
@@ -34,11 +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
import java.util.concurrent.locks.ReentrantLock
@@ -46,6 +45,7 @@ class Cache(context: Context) : ContextWrapper(context) {
companion object {
private val moving = mutableListOf()
+ private val readers = SparseArray()
}
private val locks = SparseArray()
@@ -67,7 +67,7 @@ class Cache(context: Context) : ContextWrapper(context) {
// Search in this order
// Download -> Cache
fun getCachedGallery(galleryID: Int) = getCachedGallery(this, galleryID).also {
- if (!it.exists())
+ if (!it.exists() && !preference.getBoolean("cache_disable", false))
it.mkdirs()
}
@@ -87,6 +87,9 @@ class Cache(context: Context) : ContextWrapper(context) {
}
fun setCachedMetadata(galleryID: Int, metadata: Metadata) {
+ if (preference.getBoolean("cache_disable", false))
+ return
+
val file = File(getCachedGallery(galleryID), ".metadata").also {
if (!it.exists())
it.createNewFile()
@@ -98,6 +101,7 @@ class Cache(context: Context) : ContextWrapper(context) {
suspend fun getThumbnail(galleryID: Int): String? {
val metadata = Cache(this).getCachedMetadata(galleryID)
+ @Suppress("BlockingMethodInNonBlockingContext")
val thumbnail = if (metadata?.thumbnail == null)
withContext(Dispatchers.IO) {
val thumbnails = getGalleryBlock(galleryID)?.thumbnails
@@ -158,7 +162,7 @@ class Cache(context: Context) : ContextWrapper(context) {
}
fun getReaderOrNull(galleryID: Int): Reader? {
- return getCachedMetadata(galleryID)?.reader
+ return readers[galleryID] ?: getCachedMetadata(galleryID)?.reader
}
suspend fun getReader(galleryID: Int): Reader? {
@@ -179,15 +183,21 @@ class Cache(context: Context) : ContextWrapper(context) {
it
}
- val reader = if (metadata?.reader == null) {
- CoroutineScope(Dispatchers.IO).async {
+ val reader =
+ if (readers[galleryID] != null)
+ return readers[galleryID]
+ else if (metadata?.reader == null) {
var retval: Reader? = null
for (source in sources) {
retval = try {
- source.value.invoke()
+ withContext(Dispatchers.IO) {
+ withTimeoutOrNull(1000) {
+ source.value.invoke()
+ }
+ }
} catch (e: Exception) {
- Crashlytics.logException(e)
+ FirebaseCrashlytics.getInstance().recordException(e)
null
}
@@ -196,9 +206,10 @@ class Cache(context: Context) : ContextWrapper(context) {
}
retval
- }.await() ?: return null
- } else
- metadata.reader
+ } else
+ metadata.reader
+
+ readers.put(galleryID, reader)
setCachedMetadata(
galleryID,
@@ -239,18 +250,28 @@ class Cache(context: Context) : ContextWrapper(context) {
}
- fun putImage(galleryID: Int, index: Int, ext: String, data: InputStream) {
+ fun putImage(galleryID: Int, index: Int, ext: String, data: ByteArray) {
+ if (preference.getBoolean("cache_disable", false))
+ return
+
val cache = File(getCachedGallery(galleryID), "%05d.$ext".format(index)).also {
if (!it.exists())
it.createNewFile()
}
- BufferedInputStream(data).use {
- it.copyTo(FileOutputStream(cache))
+ try {
+ FileOutputStream(cache).use {
+ it.write(data)
+ }
+ } catch (e: Exception) {
+ cache.delete()
}
}
fun moveToDownload(galleryID: Int) {
+ if (preference.getBoolean("cache_disable", false))
+ return
+
if (moving.contains(galleryID))
return
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 5c279c3b..587a51c8 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
@@ -29,8 +29,7 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.TaskStackBuilder
import androidx.preference.PreferenceManager
-import com.crashlytics.android.Crashlytics
-import io.fabric.sdk.android.Fabric
+import com.google.firebase.crashlytics.FirebaseCrashlytics
import kotlinx.coroutines.*
import okhttp3.*
import okio.*
@@ -77,7 +76,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
private var bufferedSource : BufferedSource? = null
override fun contentLength() = responseBody.contentLength()
- override fun contentType() = responseBody.contentType() ?: null
+ override fun contentType() = responseBody.contentType()
override fun source(): BufferedSource {
if (bufferedSource == null)
@@ -144,6 +143,7 @@ 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()
@@ -151,11 +151,18 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
val interceptor = Interceptor { chain ->
val request = chain.request()
- val response = chain.proceed(request)
+ var response = chain.proceed(request)
+
+ var retry = 5
+ while (!response.isSuccessful && retry > 0) {
+ response = chain.proceed(request)
+ retry--
+ }
response.newBuilder()
- .body(ProgressResponseBody(request.tag(), response.body(), progressListener))
- .build()
+ .body(response.body()?.let {
+ ProgressResponseBody(request.tag(), it, progressListener)
+ }).build()
}
val client =
@@ -189,6 +196,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
progress.clear()
exception.clear()
+ results.clear()
notification.clear()
notificationManager.cancelAll()
}
@@ -205,6 +213,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
progress.remove(galleryID)
exception.remove(galleryID)
+ results.remove(galleryID)
notification.remove(galleryID)
notificationManager.cancel(galleryID)
@@ -253,6 +262,7 @@ 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
@@ -267,6 +277,9 @@ 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)
@@ -289,8 +302,8 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
val callback = object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.i("PUPILD", "FAIL ${call.request().tag()} (${e.message})")
- if (Fabric.isInitialized() && e.message != "Canceled")
- Crashlytics.logException(e)
+ if (e.message?.contains("cancel", true) != true)
+ FirebaseCrashlytics.getInstance().recordException(e)
progress[galleryID]?.set(i, Float.NaN)
exception[galleryID]?.set(i, e)
@@ -316,13 +329,19 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
try {
response.body().use {
- Cache(this@DownloadWorker).putImage(galleryID, i, ext, it.byteStream())
+ it!!
+
+ results[galleryID]?.set(i, it.source().readByteArray())
}
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/proxy.kt b/app/src/main/java/xyz/quaver/pupil/util/proxy.kt
index 229c5e90..c471d992 100644
--- a/app/src/main/java/xyz/quaver/pupil/util/proxy.kt
+++ b/app/src/main/java/xyz/quaver/pupil/util/proxy.kt
@@ -42,7 +42,7 @@ data class ProxyInfo(
}
fun authenticator() = Authenticator { _, response ->
- val credential = Credentials.basic(username, password)
+ val credential = Credentials.basic(username ?: "", password ?: "")
response.request().newBuilder()
.header("Proxy-Authorization", credential)
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 f56a0540..406837cd 100644
--- a/app/src/main/java/xyz/quaver/pupil/util/update.kt
+++ b/app/src/main/java/xyz/quaver/pupil/util/update.kt
@@ -50,7 +50,6 @@ import java.io.File
import java.io.IOException
import java.net.URL
import java.util.*
-import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
fun getReleases(url: String) : JsonArray {
@@ -320,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.inputStream())
+ Cache(context).putImage(galleryID, index, it.extension, it.readBytes())
}
}
diff --git a/app/src/main/res/anim/shake.xml b/app/src/main/res/anim/shake.xml
new file mode 100644
index 00000000..323768dd
--- /dev/null
+++ b/app/src/main/res/anim/shake.xml
@@ -0,0 +1,24 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/shake_cycle.xml b/app/src/main/res/anim/shake_cycle.xml
new file mode 100644
index 00000000..13dcab54
--- /dev/null
+++ b/app/src/main/res/anim/shake_cycle.xml
@@ -0,0 +1,21 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/color/lock_fab.xml b/app/src/main/res/color/lock_fab.xml
new file mode 100644
index 00000000..197313e3
--- /dev/null
+++ b/app/src/main/res/color/lock_fab.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-hdpi/ic_account_group.png b/app/src/main/res/drawable-hdpi/ic_account_group.png
deleted file mode 100644
index 2e8279db..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_account_group.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_account_star.png b/app/src/main/res/drawable-hdpi/ic_account_star.png
deleted file mode 100644
index 53b16e5d..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_account_star.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_book_open.png b/app/src/main/res/drawable-hdpi/ic_book_open.png
deleted file mode 100644
index 144febb1..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_book_open.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_brush.png b/app/src/main/res/drawable-hdpi/ic_brush.png
deleted file mode 100644
index 5316c732..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_brush.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_gender_female.png b/app/src/main/res/drawable-hdpi/ic_gender_female.png
deleted file mode 100644
index 76a7d4c4..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_gender_female.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_gender_male.png b/app/src/main/res/drawable-hdpi/ic_gender_male.png
deleted file mode 100644
index 4ee6cd07..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_gender_male.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_tag.png b/app/src/main/res/drawable-hdpi/ic_tag.png
deleted file mode 100644
index aa3b8750..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_tag.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_translate.png b/app/src/main/res/drawable-hdpi/ic_translate.png
deleted file mode 100644
index 1a8f4365..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_translate.png and /dev/null differ
diff --git a/app/src/main/res/drawable-ldpi/ic_account_group.png b/app/src/main/res/drawable-ldpi/ic_account_group.png
deleted file mode 100644
index c7cbb8cb..00000000
Binary files a/app/src/main/res/drawable-ldpi/ic_account_group.png and /dev/null differ
diff --git a/app/src/main/res/drawable-ldpi/ic_account_star.png b/app/src/main/res/drawable-ldpi/ic_account_star.png
deleted file mode 100644
index 4373f45f..00000000
Binary files a/app/src/main/res/drawable-ldpi/ic_account_star.png and /dev/null differ
diff --git a/app/src/main/res/drawable-ldpi/ic_book_open.png b/app/src/main/res/drawable-ldpi/ic_book_open.png
deleted file mode 100644
index 1b1c6020..00000000
Binary files a/app/src/main/res/drawable-ldpi/ic_book_open.png and /dev/null differ
diff --git a/app/src/main/res/drawable-ldpi/ic_brush.png b/app/src/main/res/drawable-ldpi/ic_brush.png
deleted file mode 100644
index 48baadd4..00000000
Binary files a/app/src/main/res/drawable-ldpi/ic_brush.png and /dev/null differ
diff --git a/app/src/main/res/drawable-ldpi/ic_gender_female.png b/app/src/main/res/drawable-ldpi/ic_gender_female.png
deleted file mode 100644
index 1070b7d4..00000000
Binary files a/app/src/main/res/drawable-ldpi/ic_gender_female.png and /dev/null differ
diff --git a/app/src/main/res/drawable-ldpi/ic_gender_male.png b/app/src/main/res/drawable-ldpi/ic_gender_male.png
deleted file mode 100644
index fd054d81..00000000
Binary files a/app/src/main/res/drawable-ldpi/ic_gender_male.png and /dev/null differ
diff --git a/app/src/main/res/drawable-ldpi/ic_tag.png b/app/src/main/res/drawable-ldpi/ic_tag.png
deleted file mode 100644
index 39459491..00000000
Binary files a/app/src/main/res/drawable-ldpi/ic_tag.png and /dev/null differ
diff --git a/app/src/main/res/drawable-ldpi/ic_translate.png b/app/src/main/res/drawable-ldpi/ic_translate.png
deleted file mode 100644
index ffe6baf7..00000000
Binary files a/app/src/main/res/drawable-ldpi/ic_translate.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_account_group.png b/app/src/main/res/drawable-mdpi/ic_account_group.png
deleted file mode 100644
index 314120c4..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_account_group.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_account_star.png b/app/src/main/res/drawable-mdpi/ic_account_star.png
deleted file mode 100644
index 48b75fa6..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_account_star.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_book_open.png b/app/src/main/res/drawable-mdpi/ic_book_open.png
deleted file mode 100644
index b76cd538..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_book_open.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_brush.png b/app/src/main/res/drawable-mdpi/ic_brush.png
deleted file mode 100644
index 48ec2743..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_brush.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_gender_female.png b/app/src/main/res/drawable-mdpi/ic_gender_female.png
deleted file mode 100644
index 7000159c..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_gender_female.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_gender_male.png b/app/src/main/res/drawable-mdpi/ic_gender_male.png
deleted file mode 100644
index 211cee7a..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_gender_male.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_tag.png b/app/src/main/res/drawable-mdpi/ic_tag.png
deleted file mode 100644
index 42e8255f..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_tag.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_translate.png b/app/src/main/res/drawable-mdpi/ic_translate.png
deleted file mode 100644
index 1d4c32d6..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_translate.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_account_group.png b/app/src/main/res/drawable-xhdpi/ic_account_group.png
deleted file mode 100644
index 4e6389bc..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_account_group.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_account_star.png b/app/src/main/res/drawable-xhdpi/ic_account_star.png
deleted file mode 100644
index a8dc7cc7..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_account_star.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_book_open.png b/app/src/main/res/drawable-xhdpi/ic_book_open.png
deleted file mode 100644
index dc925c77..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_book_open.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_brush.png b/app/src/main/res/drawable-xhdpi/ic_brush.png
deleted file mode 100644
index 01fde729..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_brush.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_gender_female.png b/app/src/main/res/drawable-xhdpi/ic_gender_female.png
deleted file mode 100644
index 734e0d99..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_gender_female.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_gender_male.png b/app/src/main/res/drawable-xhdpi/ic_gender_male.png
deleted file mode 100644
index 89a1948d..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_gender_male.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_tag.png b/app/src/main/res/drawable-xhdpi/ic_tag.png
deleted file mode 100644
index 23658b82..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_tag.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_translate.png b/app/src/main/res/drawable-xhdpi/ic_translate.png
deleted file mode 100644
index 73a5393b..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_translate.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_account_group.png b/app/src/main/res/drawable-xxhdpi/ic_account_group.png
deleted file mode 100644
index 2080d107..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_account_group.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_account_star.png b/app/src/main/res/drawable-xxhdpi/ic_account_star.png
deleted file mode 100644
index ca802350..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_account_star.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_book_open.png b/app/src/main/res/drawable-xxhdpi/ic_book_open.png
deleted file mode 100644
index fc7ea0d5..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_book_open.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_brush.png b/app/src/main/res/drawable-xxhdpi/ic_brush.png
deleted file mode 100644
index 2a5a71a2..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_brush.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_gender_female.png b/app/src/main/res/drawable-xxhdpi/ic_gender_female.png
deleted file mode 100644
index f2cb8663..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_gender_female.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_gender_male.png b/app/src/main/res/drawable-xxhdpi/ic_gender_male.png
deleted file mode 100644
index 3ba80a52..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_gender_male.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_tag.png b/app/src/main/res/drawable-xxhdpi/ic_tag.png
deleted file mode 100644
index 10494383..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_tag.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_translate.png b/app/src/main/res/drawable-xxhdpi/ic_translate.png
deleted file mode 100644
index 49d105a1..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_translate.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_account_group.png b/app/src/main/res/drawable-xxxhdpi/ic_account_group.png
deleted file mode 100644
index 7ad2921a..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_account_group.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_account_star.png b/app/src/main/res/drawable-xxxhdpi/ic_account_star.png
deleted file mode 100644
index 2fa56e16..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_account_star.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_book_open.png b/app/src/main/res/drawable-xxxhdpi/ic_book_open.png
deleted file mode 100644
index db934527..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_book_open.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_brush.png b/app/src/main/res/drawable-xxxhdpi/ic_brush.png
deleted file mode 100644
index fa47de51..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_brush.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_gender_female.png b/app/src/main/res/drawable-xxxhdpi/ic_gender_female.png
deleted file mode 100644
index 6b0c3dcd..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_gender_female.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_gender_male.png b/app/src/main/res/drawable-xxxhdpi/ic_gender_male.png
deleted file mode 100644
index d7251b2b..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_gender_male.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_tag.png b/app/src/main/res/drawable-xxxhdpi/ic_tag.png
deleted file mode 100644
index d6804b45..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_tag.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_translate.png b/app/src/main/res/drawable-xxxhdpi/ic_translate.png
deleted file mode 100644
index 078e846a..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_translate.png and /dev/null differ
diff --git a/app/src/main/res/drawable/account_group.xml b/app/src/main/res/drawable/account_group.xml
new file mode 100644
index 00000000..9e5f4d81
--- /dev/null
+++ b/app/src/main/res/drawable/account_group.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/account_star.xml b/app/src/main/res/drawable/account_star.xml
new file mode 100644
index 00000000..dc8e4492
--- /dev/null
+++ b/app/src/main/res/drawable/account_star.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/backspace_outline.xml b/app/src/main/res/drawable/backspace_outline.xml
new file mode 100644
index 00000000..201e2e9b
--- /dev/null
+++ b/app/src/main/res/drawable/backspace_outline.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/book_open.xml b/app/src/main/res/drawable/book_open.xml
new file mode 100644
index 00000000..66c81594
--- /dev/null
+++ b/app/src/main/res/drawable/book_open.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/brush.xml b/app/src/main/res/drawable/brush.xml
new file mode 100644
index 00000000..87b7c4c3
--- /dev/null
+++ b/app/src/main/res/drawable/brush.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/fingerprint.xml b/app/src/main/res/drawable/fingerprint.xml
index ffa8a34b..3418d25d 100644
--- a/app/src/main/res/drawable/fingerprint.xml
+++ b/app/src/main/res/drawable/fingerprint.xml
@@ -1,8 +1,10 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_gender_female_white.xml b/app/src/main/res/drawable/gender_female.xml
similarity index 100%
rename from app/src/main/res/drawable/ic_gender_female_white.xml
rename to app/src/main/res/drawable/gender_female.xml
diff --git a/app/src/main/res/drawable/ic_gender_male_white.xml b/app/src/main/res/drawable/gender_male.xml
similarity index 91%
rename from app/src/main/res/drawable/ic_gender_male_white.xml
rename to app/src/main/res/drawable/gender_male.xml
index a6e1a428..eb3750bb 100644
--- a/app/src/main/res/drawable/ic_gender_male_white.xml
+++ b/app/src/main/res/drawable/gender_male.xml
@@ -1,4 +1,4 @@
-
+
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/lock_pattern.xml b/app/src/main/res/drawable/lock_pattern.xml
index f1be51c2..f88355fb 100644
--- a/app/src/main/res/drawable/lock_pattern.xml
+++ b/app/src/main/res/drawable/lock_pattern.xml
@@ -4,5 +4,5 @@
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/pin_filled.xml b/app/src/main/res/drawable/pin_filled.xml
new file mode 100644
index 00000000..98fe185c
--- /dev/null
+++ b/app/src/main/res/drawable/pin_filled.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/refresh.xml b/app/src/main/res/drawable/refresh.xml
new file mode 100644
index 00000000..cfa890d9
--- /dev/null
+++ b/app/src/main/res/drawable/refresh.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/tag.xml b/app/src/main/res/drawable/tag.xml
new file mode 100644
index 00000000..47689267
--- /dev/null
+++ b/app/src/main/res/drawable/tag.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/translate.xml b/app/src/main/res/drawable/translate.xml
new file mode 100644
index 00000000..f357ae5f
--- /dev/null
+++ b/app/src/main/res/drawable/translate.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_lock.xml b/app/src/main/res/layout/activity_lock.xml
index 00cd2898..db5b51be 100644
--- a/app/src/main/res/layout/activity_lock.xml
+++ b/app/src/main/res/layout/activity_lock.xml
@@ -36,7 +36,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
- android:layout_marginBottom="32dp"
android:gravity="center"
app:layout_constraintTop_toBottomOf="@id/lock_content"
app:layout_constraintBottom_toTopOf="@id/lock_button_layout">
@@ -46,9 +45,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/fingerprint"
+ app:backgroundTint="@color/lock_fab"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
- app:backgroundTint="@color/dark_gray"
+ app:tint="@null"
app:fabSize="mini"/>
@@ -67,26 +67,29 @@
android:id="@+id/lock_pattern"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ app:tint="@null"
app:srcCompat="@drawable/lock_pattern"
- app:backgroundTint="@color/colorPrimary"
+ app:backgroundTint="@color/lock_fab"
app:fabSize="mini"/>
diff --git a/app/src/main/res/layout/activity_main_content.xml b/app/src/main/res/layout/activity_main_content.xml
index e3ce7e65..f427226b 100644
--- a/app/src/main/res/layout/activity_main_content.xml
+++ b/app/src/main/res/layout/activity_main_content.xml
@@ -118,11 +118,17 @@
-
+ app:floatingSearch_close_search_on_keyboard_dismiss="true"
+ tools:ignore="NewApi" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_reader.xml b/app/src/main/res/layout/activity_reader.xml
index 303eb3bc..dba09170 100644
--- a/app/src/main/res/layout/activity_reader.xml
+++ b/app/src/main/res/layout/activity_reader.xml
@@ -75,6 +75,13 @@
app:fab_label="@string/reader_fab_download"
app:fab_size="mini"/>
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_pin_lock.xml b/app/src/main/res/layout/fragment_pin_lock.xml
new file mode 100644
index 00000000..7099e499
--- /dev/null
+++ b/app/src/main/res/layout/fragment_pin_lock.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_galleryblock.xml b/app/src/main/res/layout/item_galleryblock.xml
index bef8a183..5ba0e685 100644
--- a/app/src/main/res/layout/item_galleryblock.xml
+++ b/app/src/main/res/layout/item_galleryblock.xml
@@ -197,7 +197,8 @@
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingBottom="8dp"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
+
+
+
+
タグ
サムネイル
おすすめ
- イメージをギャラリーから見えなくする
イメージを隠す
ヘルプ
削除
@@ -141,4 +140,16 @@
旧ギャラリーインポート中…
インポート完了
ランダムギャラリーを開く
+ 予備のロックが設定されていないと指紋ロックは使用できません
+ Pupil指紋ロック™
+ こうかはばつぐんだ!
+ 登場人物を全て18歳以上にする
+ キャッシュを使用しない
+ キャッシュを使用しないため、ダウンロードできません
+ (Korean only)
+ (Korean only)
+ ユーザーID
+ ユーザーIDをクリップボードにコピーしました
+ ダウンロードエラーが発生しました。リトライしますか?
+ リトライ
\ No newline at end of file
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index 598da2cc..e4321f2c 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -97,7 +97,6 @@
태그
관련 갤러리
미리보기
- 갤러리에서 이미지 검색이 되지 않도록 합니다
이미지 숨기기
도움말
삭제
@@ -141,4 +140,16 @@
이전 버전 갤러리 가져오는 중…
가져오기 완료
무작위 갤러리 열기
+ 지문 잠금은 다른 잠금 방식이 활성화 되어 있을 때만 사용 가능합니다
+ Pupil 지문 인식™
+ 힘세고 강한 지문 인식
+ 판사님 저는 페도가 아닙니다
+ 캐시 비활성화
+ 캐시를 활성화 해야 다운로드를 진행할 수 있습니다
+ 아청법 대응 옵션 추가
+ 경찰서 정모 확률을 줄여보고자 캐시 비활성화/태그 필터를 추가하였습니다. 적용하시겠습니까?
+ 유저 ID
+ 유저 ID를 클립보드에 복사했습니다
+ 다운로드 에러가 발생했습니다. 재시도 하시겠습니까?
+ 재시도
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f21275ad..3028ed1a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -27,6 +27,9 @@
(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.
@@ -107,18 +110,22 @@
Series: %1$s
Type: %1$s
Language: %1$s
+ %dP
Loading
Go to page
- Fullscreen
+ Fullscreen>
+ Retry
Background download
Cancel background download
Downloading…
Download complete
Download error
+ Download Error occurred. Retry?
+
Help
@@ -152,6 +159,8 @@
%s available
Custom Location
This folder is not writable. Please select another folder.
+ Disable Cache
+ Download is disabled when the cache is disabled
Low quality images
Load low quality images to improve load speed and data usage
@@ -170,7 +179,6 @@
Dark mode
Protect yourself against light attacks!
Hide image from gallery
- Hides image from gallery
Backup favorites
Backup file created
Check out
@@ -178,6 +186,8 @@
Restore failed
%1$d entries restored
Import old galleries
+ User ID
+ User ID is copied to clipboard
@@ -187,6 +197,8 @@
Password
Biometrics
Fingerprint
+ Fingerprint can be only enabled if one of the other locks are enabled
+ Pupil Fingerprint Lock™
Enabled
Input same lock once more to confirm Lock
Do you want to remove lock?
@@ -198,6 +210,7 @@
Language:
Filter BL
Filter Guro
+ I\'m not a pedophile
Any
Mirrors
@@ -215,5 +228,6 @@
Importing old galleries…
%1$d/%2$d
Importing completed
+ Ah Shit, Here we go again
diff --git a/app/src/main/res/xml/lock_preferences.xml b/app/src/main/res/xml/lock_preferences.xml
index 3c3baab3..f17e5c01 100644
--- a/app/src/main/res/xml/lock_preferences.xml
+++ b/app/src/main/res/xml/lock_preferences.xml
@@ -17,7 +17,7 @@
-
diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml
index cd28fb7b..dff10800 100644
--- a/app/src/main/res/xml/root_preferences.xml
+++ b/app/src/main/res/xml/root_preferences.xml
@@ -47,6 +47,10 @@
app:key="dl_location"
app:title="@string/settings_dl_location"/>
+
+
-
+ app:title="@string/settings_nomedia_title"/>
+
+
-
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index ad7f92dd..5eb988a2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,17 +5,16 @@ buildscript {
repositories {
google()
jcenter()
- maven { url 'https://maven.fabric.io/public' }
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.6.3'
+ classpath 'com.android.tools.build:gradle:4.0.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
- classpath 'io.fabric.tools:gradle:1.31.0'
+ classpath 'com.google.firebase:firebase-crashlytics-gradle:2.2.0'
classpath 'com.google.firebase:perf-plugin:1.3.1'
}
}
@@ -25,7 +24,7 @@ allprojects {
google()
jcenter()
maven { url "https://jitpack.io" }
- maven { url 'http://guardian.github.com/maven/repo-releases' }
+ maven { url 'https://guardian.github.com/maven/repo-releases' }
}
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index ff8fd741..29e5e6d4 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Sat Feb 29 09:07:20 KST 2020
+#Thu Jun 18 15:48:09 KST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
diff --git a/libpupil/build.gradle b/libpupil/build.gradle
index b886c59e..f943ef77 100644
--- a/libpupil/build.gradle
+++ b/libpupil/build.gradle
@@ -5,9 +5,9 @@ apply plugin: 'kotlinx-serialization'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0"
- implementation 'org.jsoup:jsoup:1.12.1'
+ implementation 'org.jsoup:jsoup:1.13.1'
testImplementation 'junit:junit:4.13'
}
diff --git a/libpupil/src/main/java/xyz/quaver/Utils.kt b/libpupil/src/main/java/xyz/quaver/Utils.kt
index c598f697..86fd5b9e 100644
--- a/libpupil/src/main/java/xyz/quaver/Utils.kt
+++ b/libpupil/src/main/java/xyz/quaver/Utils.kt
@@ -20,7 +20,7 @@ import kotlinx.serialization.UnstableDefault
import kotlinx.serialization.json.Json
import java.net.Proxy
-var proxy = Proxy.NO_PROXY
+var proxy : Proxy = Proxy.NO_PROXY
@OptIn(UnstableDefault::class)
var json = Json {
diff --git a/libpupil/src/main/java/xyz/quaver/hiyobi/galleryblock.kt b/libpupil/src/main/java/xyz/quaver/hiyobi/galleryblock.kt
index 6b324ce9..72e4cf48 100644
--- a/libpupil/src/main/java/xyz/quaver/hiyobi/galleryblock.kt
+++ b/libpupil/src/main/java/xyz/quaver/hiyobi/galleryblock.kt
@@ -16,31 +16,54 @@
package xyz.quaver.hiyobi
-import org.jsoup.Jsoup
+import kotlinx.serialization.json.contentOrNull
+import kotlinx.serialization.json.intOrNull
import xyz.quaver.Code
import xyz.quaver.hitomi.GalleryBlock
import xyz.quaver.hitomi.protocol
+import xyz.quaver.json
import xyz.quaver.proxy
+import java.net.URL
+import javax.net.ssl.HttpsURLConnection
fun getGalleryBlock(galleryID: Int) : GalleryBlock? {
- val url = "$protocol//$hiyobi/info/$galleryID"
+ val url = "$protocol//api.$hiyobi/gallery/$galleryID"
- val doc = Jsoup.connect(url).proxy(proxy).get()
+ val galleryBlock = with (URL(url).openConnection(proxy) as HttpsURLConnection) {
+ setRequestProperty("User-Agent", user_agent)
+ setRequestProperty("Cookie", cookie)
+ connectTimeout = 1000
+ connect()
- val galleryBlock = doc.selectFirst(".gallery-content")
+ inputStream.bufferedReader().use { it.readText() }
+ }.let {
+ json.parseJson(it).jsonObject
+ }
- val galleryUrl = galleryBlock.selectFirst("a").attr("href")
+ val galleryUrl = "reader/$galleryID"
- val thumbnails = listOf(galleryBlock.selectFirst("img").attr("abs:src"))
+ val thumbnails = listOf("$protocol//cdn.$hiyobi/tn/$galleryID.jpg")
- val title = galleryBlock.selectFirst("b").text()
- val artists = galleryBlock.select("tr:matches(작가) a[href~=artist]").map { it.text() }
- val series = galleryBlock.select("tr:matches(원작) a").map { it.attr("href").substringAfter("series:").replace('_', ' ') }
- val type = galleryBlock.selectFirst("tr:matches(종류) a").attr("href").substringAfter("type:").replace('_', ' ')
+ val title = galleryBlock["title"]?.contentOrNull ?: ""
+ val artists = galleryBlock["artists"]?.jsonArray?.mapNotNull {
+ it.jsonObject["value"]?.contentOrNull
+ } ?: listOf()
+ val series = galleryBlock["parodys"]?.jsonArray?.mapNotNull {
+ it.jsonObject["value"]?.contentOrNull
+ } ?: listOf()
+ val type = when (galleryBlock["type"]?.intOrNull) {
+ 1 -> "doujinshi"
+ 2 -> "manga"
+ 3 -> "artistcg"
+ 4 -> "gamecg"
+ else -> ""
+ }
val language = "korean"
- val relatedTags = galleryBlock.select("tr:matches(태그) a").map { it.attr("href").substringAfterLast('/').replace('_', ' ') }
+ val relatedTags = galleryBlock["tags"]?.jsonArray?.mapNotNull {
+ it.jsonObject["value"]?.contentOrNull
+ } ?: listOf()
return GalleryBlock(Code.HIYOBI, galleryID, galleryUrl, thumbnails, title, artists, series, type, language, relatedTags)
}
\ No newline at end of file
diff --git a/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt b/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt
index 07babd9d..5ed65661 100644
--- a/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt
+++ b/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt
@@ -18,7 +18,7 @@ package xyz.quaver.hiyobi
import kotlinx.serialization.UnstableDefault
import kotlinx.serialization.builtins.list
-import org.jsoup.Jsoup
+import kotlinx.serialization.json.contentOrNull
import xyz.quaver.Code
import xyz.quaver.hitomi.GalleryFiles
import xyz.quaver.hitomi.GalleryInfo
@@ -64,17 +64,26 @@ fun renewCookie() : String {
@OptIn(UnstableDefault::class)
fun getReader(galleryID: Int) : Reader {
- val reader = "https://$hiyobi/reader/$galleryID"
- val url = "https://cdn.hiyobi.me/data/json/${galleryID}_list.json"
+ val data = "https://cdn.$hiyobi/data/json/$galleryID.json"
+ val list = "https://cdn.$hiyobi/data/json/${galleryID}_list.json"
- val title = Jsoup.connect(reader).proxy(proxy).get().title()
+ val title = with(URL(data).openConnection(proxy) as HttpsURLConnection) {
+ setRequestProperty("User-Agent", user_agent)
+ setRequestProperty("Cookie", cookie)
+ connectTimeout = 1000
+ connect()
+
+ inputStream.bufferedReader().use { it.readText() }
+ }.let {
+ json.parseJson(it).jsonObject["n"]?.contentOrNull
+ }
val galleryFiles = json.parse(
GalleryFiles.serializer().list,
- with(URL(url).openConnection(proxy) as HttpsURLConnection) {
+ with(URL(list).openConnection(proxy) as HttpsURLConnection) {
setRequestProperty("User-Agent", user_agent)
setRequestProperty("Cookie", cookie)
- connectTimeout = 2000
+ connectTimeout = 1000
connect()
inputStream.bufferedReader().use { it.readText() }
diff --git a/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt b/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt
index bd3661a6..b818b7fb 100644
--- a/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt
+++ b/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt
@@ -82,7 +82,7 @@ class UnitTest {
@Test
fun test_hiyobi() {
- val reader = xyz.quaver.hiyobi.getReader(1574736)
+ val reader = xyz.quaver.hiyobi.getReader(1664762)
print(reader)
}