diff --git a/.idea/misc.xml b/.idea/misc.xml
index fb8c126a..7631aec3 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index b92db1e7..97cb1eb5 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -7,13 +7,13 @@ apply plugin: 'io.fabric'
apply plugin: 'com.google.firebase.firebase-perf'
android {
- compileSdkVersion 28
+ compileSdkVersion 29
defaultConfig {
applicationId "xyz.quaver.pupil"
minSdkVersion 16
- targetSdkVersion 28
+ targetSdkVersion 29
versionCode 17
- versionName "2.9.1"
+ versionName "2.10-alpha"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
@@ -42,17 +42,21 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.preference:preference:1.1.0-beta01'
implementation 'com.google.android.material:material:1.0.0'
- implementation 'com.google.firebase:firebase-core:16.0.9'
- implementation 'com.google.firebase:firebase-perf:17.0.2'
+ implementation 'com.google.firebase:firebase-core:17.0.0'
+ implementation 'com.google.firebase:firebase-perf:18.0.1'
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
implementation 'com.github.arimorty:floatingsearchview:2.1.1'
- implementation 'com.github.deano2390:MaterialShowcaseView:1.3.4'
+ implementation 'com.andrognito.patternlockview:patternlockview:1.0.0'
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation "ru.noties.markwon:core:${markwonVersion}"
implementation 'com.github.clans:fab:1.6.4'
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+ implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
+ androidTestImplementation 'androidx.test:rules:1.2.0'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation project(path: ':libpupil')
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index efb4fd24..481bb434 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -18,11 +18,4 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
-#-renamesourcefileattribute SourceFile
--keep class com.finotes.android.finotescore.* { *; }
-
--keepclassmembers class * {
- @com.finotes.android.finotescore.annotation.Observe *;
-}
-
--keepattributes SourceFile,LineNumberTable
\ No newline at end of file
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/app/release/output.json b/app/release/output.json
index 0cc69cca..f084575a 100644
--- a/app/release/output.json
+++ b/app/release/output.json
@@ -1 +1 @@
-[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":16,"versionName":"2.9","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
\ No newline at end of file
+[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":17,"versionName":"2.9.1","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
\ No newline at end of file
diff --git a/app/src/androidTest/java/xyz/quaver/pupil/ExampleInstrumentedTest.kt b/app/src/androidTest/java/xyz/quaver/pupil/ExampleInstrumentedTest.kt
index 79db10d2..facb9b50 100644
--- a/app/src/androidTest/java/xyz/quaver/pupil/ExampleInstrumentedTest.kt
+++ b/app/src/androidTest/java/xyz/quaver/pupil/ExampleInstrumentedTest.kt
@@ -1,16 +1,18 @@
package xyz.quaver.pupil
-import android.graphics.BitmapFactory
+import android.content.Intent
import android.util.Log
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.rule.ActivityTestRule
import org.junit.Assert.assertEquals
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import xyz.quaver.hiyobi.cookie
import xyz.quaver.hiyobi.getReader
import xyz.quaver.hiyobi.user_agent
-import java.io.File
+import xyz.quaver.pupil.ui.LockActivity
import java.net.URL
import javax.net.ssl.HttpsURLConnection
@@ -21,6 +23,7 @@ import javax.net.ssl.HttpsURLConnection
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
+
@Test
fun useAppContext() {
// Context of the app under test.
@@ -30,12 +33,12 @@ class ExampleInstrumentedTest {
@Test
fun checkCacheDir() {
+ val activityTestRule = ActivityTestRule(LockActivity::class.java)
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
- val file = File(appContext.cacheDir, "imageCache/1412251/01.jpg.webp")
- val bitmap = BitmapFactory.decodeFile(file.absolutePath)
+ activityTestRule.launchActivity(Intent())
- Log.d("Pupil", bitmap.byteCount.toString())
+ while(true);
}
@Test
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 294d57a0..c3e6686f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,20 +6,19 @@
-
+ android:theme="@style/AppTheme">
+
-
+ android:name=".ui.ReaderActivity"
+ android:configChanges="keyboardHidden|orientation|screenSize"
+ android:parentActivityName=".ui.MainActivity">
@@ -27,9 +26,9 @@
+ android:pathPrefix="/galleries"
+ android:scheme="https" />
@@ -38,9 +37,9 @@
+ android:pathPrefix="/reader"
+ android:scheme="https" />
@@ -49,9 +48,9 @@
+ android:pathPrefix="/reader"
+ android:scheme="https" />
@@ -60,9 +59,9 @@
+ android:pathPrefix="/g"
+ android:scheme="https" />
@@ -71,9 +70,9 @@
+ android:pathPrefix="/galleries"
+ android:scheme="http" />
@@ -82,9 +81,9 @@
+ android:pathPrefix="/reader"
+ android:scheme="http" />
@@ -93,9 +92,9 @@
+ android:pathPrefix="/reader"
+ android:scheme="http" />
@@ -104,16 +103,16 @@
+ android:pathPrefix="/g"
+ android:scheme="http" />
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 12080356..9cf73343 100644
--- a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt
+++ b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt
@@ -24,7 +24,7 @@ import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.list
import xyz.quaver.hitomi.GalleryBlock
import xyz.quaver.hitomi.ReaderItem
-import xyz.quaver.pupil.Pupil
+import xyz.quaver.pupil.ui.Pupil
import xyz.quaver.pupil.R
import xyz.quaver.pupil.types.Tag
import xyz.quaver.pupil.util.Histories
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 f4f33a09..e75617c4 100644
--- a/app/src/main/java/xyz/quaver/pupil/adapters/ReaderAdapter.kt
+++ b/app/src/main/java/xyz/quaver/pupil/adapters/ReaderAdapter.kt
@@ -6,9 +6,6 @@ import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
import xyz.quaver.pupil.R
class ReaderAdapter(private val images: List) : RecyclerView.Adapter() {
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/LockActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/LockActivity.kt
new file mode 100644
index 00000000..30f1ce1b
--- /dev/null
+++ b/app/src/main/java/xyz/quaver/pupil/ui/LockActivity.kt
@@ -0,0 +1,29 @@
+package xyz.quaver.pupil.ui
+
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import android.widget.Toast
+import kotlinx.android.synthetic.main.activity_lock.*
+import xyz.quaver.pupil.R
+
+class LockActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_lock)
+
+ supportFragmentManager.beginTransaction().add(
+ R.id.lock_content,
+ PatternLockFragment().apply {
+ onPatternDrawn = {
+ Toast.makeText(context, it, Toast.LENGTH_SHORT).show()
+ }
+ }
+ ).commit()
+
+ lock_pattern.isEnabled = false
+ lock_fingerprint.isEnabled = false
+ lock_password.isEnabled = false
+ }
+
+}
diff --git a/app/src/main/java/xyz/quaver/pupil/MainActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt
similarity index 97%
rename from app/src/main/java/xyz/quaver/pupil/MainActivity.kt
rename to app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt
index 1933c54e..87cd9027 100644
--- a/app/src/main/java/xyz/quaver/pupil/MainActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt
@@ -1,4 +1,4 @@
-package xyz.quaver.pupil
+package xyz.quaver.pupil.ui
import android.Manifest
import android.content.Intent
@@ -6,7 +6,6 @@ import android.content.pm.PackageManager
import android.graphics.drawable.Animatable
import android.net.Uri
import android.os.Bundle
-import android.preference.PreferenceManager
import android.text.*
import android.text.style.AlignmentSpan
import android.view.*
@@ -21,6 +20,7 @@ import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.GravityCompat
+import androidx.preference.PreferenceManager
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
import com.arlib.floatingsearchview.FloatingSearchView
import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion
@@ -40,6 +40,8 @@ import kotlinx.serialization.list
import kotlinx.serialization.stringify
import ru.noties.markwon.Markwon
import xyz.quaver.hitomi.*
+import xyz.quaver.pupil.BuildConfig
+import xyz.quaver.pupil.R
import xyz.quaver.pupil.adapters.GalleryBlockAdapter
import xyz.quaver.pupil.types.Tag
import xyz.quaver.pupil.types.TagSuggestion
@@ -51,6 +53,7 @@ import java.net.URL
import java.util.*
import javax.net.ssl.HttpsURLConnection
import kotlin.collections.ArrayList
+import kotlin.math.min
import kotlin.math.roundToInt
class MainActivity : AppCompatActivity() {
@@ -65,6 +68,12 @@ class MainActivity : AppCompatActivity() {
private val galleries = ArrayList>>()
private var query = ""
+ set(value) {
+ field = value
+ findViewById(R.id.search_bar_text)
+ .setText(query, TextView.BufferType.EDITABLE)
+ }
+
private var mode = Mode.SEARCH
private val SETTINGS = 45162
@@ -110,19 +119,11 @@ class MainActivity : AppCompatActivity() {
initView()
}
- override fun onDestroy() {
- super.onDestroy()
-
- if (cacheDir.exists())
- cacheDir.deleteRecursively()
- }
-
override fun onBackPressed() {
when {
main_drawer_layout.isDrawerOpen(GravityCompat.START) -> main_drawer_layout.closeDrawer(GravityCompat.START)
query.isNotEmpty() -> runOnUiThread {
query = ""
- findViewById(R.id.search_bar_text).setText(query, TextView.BufferType.EDITABLE)
cancelFetch()
clearGalleries()
@@ -352,8 +353,7 @@ class MainActivity : AppCompatActivity() {
onChipClickedHandler.add {
runOnUiThread {
query = it.toQuery()
- this@MainActivity.findViewById(R.id.search_bar_text)
- .setText(query, TextView.BufferType.EDITABLE)
+ currentPage = 0
cancelFetch()
clearGalleries()
@@ -726,7 +726,8 @@ class MainActivity : AppCompatActivity() {
startActivity(intent)
} catch (e: Exception) {
- Snackbar.make(main_layout, R.string.main_open_gallery_by_id_error, Snackbar.LENGTH_LONG).show()
+ Snackbar.make(main_layout,
+ R.string.main_open_gallery_by_id_error, Snackbar.LENGTH_LONG).show()
}
}
}
@@ -804,7 +805,9 @@ class MainActivity : AppCompatActivity() {
favorites.remove(tag)
}
else {
- setImageDrawable(AnimatedVectorDrawableCompat.create(context, R.drawable.avd_star))
+ setImageDrawable(AnimatedVectorDrawableCompat.create(context,
+ R.drawable.avd_star
+ ))
(drawable as Animatable).start()
favorites.add(tag)
@@ -880,10 +883,8 @@ class MainActivity : AppCompatActivity() {
}
private fun cancelFetch() {
- runBlocking {
- galleryIDs?.cancelAndJoin()
- loadingJob?.cancelAndJoin()
- }
+ galleryIDs?.cancel()
+ loadingJob?.cancel()
}
private fun clearGalleries() {
@@ -992,7 +993,7 @@ class MainActivity : AppCompatActivity() {
query.isEmpty() and defaultQuery.isEmpty() and (mode == Mode.SEARCH) ->
galleryIDs
else ->
- galleryIDs.slice(currentPage*perPage until Math.min(currentPage*perPage+perPage, galleryIDs.size))
+ galleryIDs.slice(currentPage*perPage until min(currentPage*perPage+perPage, galleryIDs.size))
}.chunked(5).let { chunks ->
for (chunk in chunks)
chunk.map { galleryID ->
@@ -1009,8 +1010,8 @@ class MainActivity : AppCompatActivity() {
getGalleryBlock(galleryID).apply {
this ?: return@apply
- if (!cache.parentFile.exists())
- cache.parentFile.mkdirs()
+ if (cache.parentFile?.exists() == false)
+ cache.parentFile!!.mkdirs()
cache.writeText(json.stringify(serializer, this))
}
@@ -1024,8 +1025,8 @@ class MainActivity : AppCompatActivity() {
if (!exists())
try {
with(URL(galleryBlock.thumbnails[0]).openConnection() as HttpsURLConnection) {
- if (!this@apply.parentFile.exists())
- this@apply.parentFile.mkdirs()
+ if (this@apply.parentFile?.exists() == false)
+ this@apply.parentFile!!.mkdirs()
inputStream.copyTo(FileOutputStream(this@apply))
}
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/PatternLockFragment.kt b/app/src/main/java/xyz/quaver/pupil/ui/PatternLockFragment.kt
new file mode 100644
index 00000000..73a7197f
--- /dev/null
+++ b/app/src/main/java/xyz/quaver/pupil/ui/PatternLockFragment.kt
@@ -0,0 +1,46 @@
+package xyz.quaver.pupil.ui
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.andrognito.patternlockview.PatternLockView
+import com.andrognito.patternlockview.listener.PatternLockViewListener
+import com.andrognito.patternlockview.utils.PatternLockUtils
+import kotlinx.android.synthetic.main.fragment_pattern_lock.*
+import kotlinx.android.synthetic.main.fragment_pattern_lock.view.*
+import xyz.quaver.pupil.R
+import xyz.quaver.pupil.util.hash
+
+class PatternLockFragment : Fragment(), PatternLockViewListener {
+
+ var onPatternDrawn: ((String) -> Unit)? = null
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ return inflater.inflate(R.layout.fragment_pattern_lock, container, false).apply {
+ lock_pattern_view.addPatternLockListener(this@PatternLockFragment)
+ }
+ }
+
+ override fun onCleared() {
+
+ }
+
+ override fun onComplete(pattern: MutableList?) {
+ val password = PatternLockUtils.patternToMD5(lock_pattern_view, pattern)
+ onPatternDrawn?.invoke(hash(password))
+ }
+
+ override fun onProgress(progressPattern: MutableList?) {
+
+ }
+
+ override fun onStarted() {
+
+ }
+
+}
diff --git a/app/src/main/java/xyz/quaver/pupil/Pupil.kt b/app/src/main/java/xyz/quaver/pupil/ui/Pupil.kt
similarity index 94%
rename from app/src/main/java/xyz/quaver/pupil/Pupil.kt
rename to app/src/main/java/xyz/quaver/pupil/ui/Pupil.kt
index add8d659..c1859fe3 100644
--- a/app/src/main/java/xyz/quaver/pupil/Pupil.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/Pupil.kt
@@ -1,14 +1,14 @@
-package xyz.quaver.pupil
+package xyz.quaver.pupil.ui
-import android.app.Application
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.os.Build
-import android.preference.PreferenceManager
import androidx.core.content.ContextCompat
import androidx.multidex.MultiDexApplication
+import androidx.preference.PreferenceManager
+import xyz.quaver.pupil.R
import xyz.quaver.pupil.util.Histories
import java.io.File
diff --git a/app/src/main/java/xyz/quaver/pupil/ReaderActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt
similarity index 98%
rename from app/src/main/java/xyz/quaver/pupil/ReaderActivity.kt
rename to app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt
index fadaf454..990f7b50 100644
--- a/app/src/main/java/xyz/quaver/pupil/ReaderActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt
@@ -1,4 +1,4 @@
-package xyz.quaver.pupil
+package xyz.quaver.pupil.ui
import android.content.Intent
import android.graphics.drawable.Animatable
@@ -13,6 +13,7 @@ import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
+import com.crashlytics.android.Crashlytics
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_reader.*
import kotlinx.android.synthetic.main.activity_reader.view.*
@@ -27,6 +28,7 @@ import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import xyz.quaver.hitomi.GalleryBlock
import xyz.quaver.hitomi.getGalleryBlock
+import xyz.quaver.pupil.R
import xyz.quaver.pupil.adapters.ReaderAdapter
import xyz.quaver.pupil.util.GalleryDownloader
import xyz.quaver.pupil.util.Histories
@@ -71,6 +73,8 @@ class ReaderActivity : AppCompatActivity() {
handleIntent(intent)
+ Crashlytics.setInt("GalleryID", galleryBlock.id)
+
if (!::galleryBlock.isInitialized) {
onBackPressed()
return
@@ -116,7 +120,7 @@ class ReaderActivity : AppCompatActivity() {
} else {
galleryBlock = Json(JsonConfiguration.Stable).parse(
GalleryBlock.serializer(),
- intent.getStringExtra("galleryblock")
+ intent.getStringExtra("galleryblock")!!
)
}
}
diff --git a/app/src/main/java/xyz/quaver/pupil/SettingsActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt
similarity index 81%
rename from app/src/main/java/xyz/quaver/pupil/SettingsActivity.kt
rename to app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt
index e93b0166..850ed55d 100644
--- a/app/src/main/java/xyz/quaver/pupil/SettingsActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt
@@ -1,8 +1,6 @@
-package xyz.quaver.pupil
+package xyz.quaver.pupil.ui
import android.os.Bundle
-import android.os.Environment
-import android.preference.PreferenceManager
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
@@ -15,7 +13,10 @@ import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
+import androidx.preference.PreferenceManager
+import io.fabric.sdk.android.BuildConfig
import kotlinx.android.synthetic.main.dialog_default_query.view.*
+import xyz.quaver.pupil.R
import xyz.quaver.pupil.types.Tags
import java.io.File
@@ -58,7 +59,7 @@ class SettingsActivity : AppCompatActivity() {
"TB" //really?
)
- private fun getCacheSize(dir: File) : String {
+ private fun getDirSize(dir: File) : String {
var size = dir.walk().map { it.length() }.sum()
var suffixIndex = 0
@@ -67,20 +68,53 @@ class SettingsActivity : AppCompatActivity() {
suffixIndex++
}
- return getString(R.string.settings_clear_downloads_summary, size, suffix[suffixIndex])
+ return getString(R.string.settings_clear_summary, size, suffix[suffixIndex])
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
+ with(findPreference("app_version")) {
+ this ?: return@with
+
+ val manager = context.packageManager
+ val info = manager.getPackageInfo(context.packageName, 0)
+
+ summary = info.versionName
+ }
+
+ with(findPreference("delete_cache")) {
+ this ?: return@with
+
+ val dir = File(context.cacheDir, "imageCache")
+
+ summary = getDirSize(dir)
+
+ onPreferenceClickListener = Preference.OnPreferenceClickListener {
+ AlertDialog.Builder(context).apply {
+ setTitle(R.string.warning)
+ setMessage(R.string.settings_clear_cache_alert_message)
+ setPositiveButton(android.R.string.yes) { _, _ ->
+ if (dir.exists())
+ dir.deleteRecursively()
+
+ summary = getDirSize(dir)
+ }
+ setNegativeButton(android.R.string.no) { _, _ -> }
+ }.show()
+
+ true
+ }
+ }
+
with(findPreference("delete_downloads")) {
this ?: return@with
- val dir = File(Environment.getExternalStorageDirectory(), "Pupil")
+ val dir = context.getExternalFilesDir("Pupil") ?: return@with
- summary = getCacheSize(dir)
+ summary = getDirSize(dir)
- setOnPreferenceClickListener {
+ onPreferenceClickListener = Preference.OnPreferenceClickListener {
AlertDialog.Builder(context).apply {
setTitle(R.string.warning)
setMessage(R.string.settings_clear_downloads_alert_message)
@@ -92,7 +126,7 @@ class SettingsActivity : AppCompatActivity() {
downloads.clear()
- summary = getCacheSize(dir)
+ summary = getDirSize(dir)
}
setNegativeButton(android.R.string.no) { _, _ -> }
}.show()
@@ -107,7 +141,7 @@ class SettingsActivity : AppCompatActivity() {
summary = getString(R.string.settings_clear_history_summary, histories.size)
- setOnPreferenceClickListener {
+ onPreferenceClickListener = Preference.OnPreferenceClickListener {
AlertDialog.Builder(context).apply {
setTitle(R.string.warning)
setMessage(R.string.settings_clear_history_alert_message)
@@ -139,7 +173,7 @@ class SettingsActivity : AppCompatActivity() {
val excludeBL = "-male:yaoi"
val excludeGuro = listOf("-female:guro", "-male:guro")
- setOnPreferenceClickListener {
+ onPreferenceClickListener = Preference.OnPreferenceClickListener {
val dialogView = LayoutInflater.from(context).inflate(
R.layout.dialog_default_query,
LinearLayout(context),
@@ -154,7 +188,7 @@ class SettingsActivity : AppCompatActivity() {
with(dialogView.default_query_dialog_language_selector) {
adapter =
- ArrayAdapter(
+ ArrayAdapter(
context,
android.R.layout.simple_spinner_dropdown_item,
arrayListOf(
@@ -237,6 +271,9 @@ class SettingsActivity : AppCompatActivity() {
true
}
}
+ with(findPreference("app_lock")) {
+
+ }
}
}
diff --git a/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt b/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt
index f4e08369..fda31db8 100644
--- a/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt
+++ b/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt
@@ -4,7 +4,7 @@ import android.app.PendingIntent
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
-import android.os.Environment
+import android.util.Log
import android.util.SparseArray
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
@@ -18,9 +18,9 @@ import kotlinx.serialization.list
import xyz.quaver.hitomi.*
import xyz.quaver.hiyobi.cookie
import xyz.quaver.hiyobi.user_agent
-import xyz.quaver.pupil.Pupil
+import xyz.quaver.pupil.ui.Pupil
import xyz.quaver.pupil.R
-import xyz.quaver.pupil.ReaderActivity
+import xyz.quaver.pupil.ui.ReaderActivity
import java.io.File
import java.io.FileOutputStream
import java.net.URL
@@ -52,7 +52,7 @@ class GalleryDownloader(
cache.deleteRecursively()
}
- if (!reader.isActive && downloadJob?.isActive != true)
+ if (reader?.isActive == false && downloadJob?.isActive != true)
field = false
downloads.add(galleryBlock.id)
@@ -63,7 +63,7 @@ class GalleryDownloader(
onNotifyChangedHandler?.invoke(value)
}
- private val reader: Deferred
+ private val reader: Deferred?
private var downloadJob: Job? = null
private lateinit var notificationBuilder: NotificationCompat.Builder
@@ -126,8 +126,8 @@ class GalleryDownloader(
if (reader.isNotEmpty()) {
//Save cache
- if (!cache.parentFile.exists())
- cache.parentFile.mkdirs()
+ if (cache.parentFile?.exists() == false)
+ cache.parentFile!!.mkdirs()
cache.writeText(json.stringify(serializer, reader))
}
@@ -140,7 +140,7 @@ class GalleryDownloader(
fun start() {
downloadJob = CoroutineScope(Dispatchers.Default).launch {
- val reader = reader.await()
+ val reader = reader!!.await()
if (reader.isEmpty())
onErrorHandler?.invoke(IOException("Couldn't retrieve Reader"))
@@ -183,8 +183,8 @@ class GalleryDownloader(
} else
setRequestProperty("Referer", getReferer(galleryBlock.id))
- if (!cache.parentFile.exists())
- cache.parentFile.mkdirs()
+ if (cache.parentFile?.exists() == false)
+ cache.parentFile!!.mkdirs()
inputStream.copyTo(FileOutputStream(cache))
}
@@ -209,8 +209,6 @@ class GalleryDownloader(
}
}
- onCompleteHandler?.invoke()
-
Timer(false).schedule(1000) {
notificationBuilder
.setContentTitle(galleryBlock.title)
@@ -220,7 +218,7 @@ class GalleryDownloader(
if (download) {
File(cacheDir, "imageCache/${galleryBlock.id}").let {
if (it.exists()) {
- val target = File(Environment.getExternalStorageDirectory(), "Pupil/${galleryBlock.id}")
+ val target = File(getExternalFilesDir("Pupil"), galleryBlock.id.toString())
if (!target.exists())
target.mkdirs()
@@ -231,9 +229,11 @@ class GalleryDownloader(
}
notificationManager.notify(galleryBlock.id, notificationBuilder.build())
- }
- download = false
+ onCompleteHandler?.invoke()
+
+ download = false
+ }
}
remove(galleryBlock.id)
@@ -254,7 +254,7 @@ class GalleryDownloader(
fun invokeOnReaderLoaded() {
CoroutineScope(Dispatchers.Default).launch {
- onReaderLoadedHandler?.invoke(reader.await())
+ onReaderLoadedHandler?.invoke(reader?.await() ?: return@launch)
}
}
diff --git a/app/src/main/java/xyz/quaver/pupil/util/file.kt b/app/src/main/java/xyz/quaver/pupil/util/file.kt
index 7e085650..f351dcd2 100644
--- a/app/src/main/java/xyz/quaver/pupil/util/file.kt
+++ b/app/src/main/java/xyz/quaver/pupil/util/file.kt
@@ -2,10 +2,11 @@ package xyz.quaver.pupil.util
import android.content.Context
import android.os.Environment
+import android.provider.MediaStore
import java.io.File
fun getCachedGallery(context: Context, galleryID: Int): File {
- return File(Environment.getExternalStorageDirectory(), "Pupil/$galleryID").let {
+ return File(context.getExternalFilesDir("Pupil"), galleryID.toString()).let {
when {
it.exists() -> it
else -> File(context.cacheDir, "imageCache/$galleryID")
diff --git a/app/src/main/java/xyz/quaver/pupil/util/lock.kt b/app/src/main/java/xyz/quaver/pupil/util/lock.kt
new file mode 100644
index 00000000..fefcc698
--- /dev/null
+++ b/app/src/main/java/xyz/quaver/pupil/util/lock.kt
@@ -0,0 +1,39 @@
+package xyz.quaver.pupil.util
+
+import android.content.Context
+import android.content.ContextWrapper
+import java.security.MessageDigest
+
+fun hash(password: String): String {
+ val bytes = password.toByteArray()
+ val md = MessageDigest.getInstance("SHA-256")
+
+ return md.digest(bytes).fold("") { str, it -> str + "%02x".format(it) }
+}
+
+// Ret1: SHA-256 Hash
+// Ret2: Hash salt
+fun hashWithSalt(password: String): Pair {
+ val salt = (0 until 12).map { source.random() }.joinToString()
+
+ return Pair(hash(password+salt), salt)
+}
+
+val source = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+
+data class Lock(private val type: Type, private val hash: String, private val salt: String) {
+
+ enum class Type {
+ PATTERN
+ }
+
+ fun match(password: String): Boolean {
+ return hash(password+salt) == hash
+ }
+}
+
+class LockManager(base: Context): ContextWrapper(base) {
+
+
+
+}
\ No newline at end of file
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 2c951cbe..1461f75c 100644
--- a/app/src/main/java/xyz/quaver/pupil/util/update.kt
+++ b/app/src/main/java/xyz/quaver/pupil/util/update.kt
@@ -1,5 +1,6 @@
package xyz.quaver.pupil.util
+import android.util.Log
import kotlinx.serialization.json.*
import java.net.URL
@@ -19,8 +20,20 @@ fun checkUpdate(url: String, currentVersion: String) : JsonObject? {
if (releases.isEmpty())
return null
- if (currentVersion != releases[0].jsonObject["tag_name"]?.content)
- return releases[0].jsonObject
+ val latestVersion = releases[0].jsonObject["tag_name"]?.content
- return null
+ return when {
+ currentVersion.split('-').size == 1 -> {
+ when {
+ currentVersion != latestVersion -> releases[0].jsonObject
+ else -> null
+ }
+ }
+ else -> {
+ when {
+ (currentVersion.split('-')[0] == latestVersion) -> releases[0].jsonObject
+ else -> null
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/fingerprint.xml b/app/src/main/res/drawable/fingerprint.xml
new file mode 100644
index 00000000..ffa8a34b
--- /dev/null
+++ b/app/src/main/res/drawable/fingerprint.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/lastpass.xml b/app/src/main/res/drawable/lastpass.xml
new file mode 100644
index 00000000..9dbf638b
--- /dev/null
+++ b/app/src/main/res/drawable/lastpass.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ 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
new file mode 100644
index 00000000..f1be51c2
--- /dev/null
+++ b/app/src/main/res/drawable/lock_pattern.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
new file mode 100644
index 00000000..6cb1e1c8
--- /dev/null
+++ b/app/src/main/res/layout/activity_lock.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main_content.xml b/app/src/main/res/layout/activity_main_content.xml
index a5b3b266..bde8ddf4 100644
--- a/app/src/main/res/layout/activity_main_content.xml
+++ b/app/src/main/res/layout/activity_main_content.xml
@@ -6,7 +6,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".MainActivity">
+ tools:context=".ui.MainActivity">
+ tools:context=".ui.ReaderActivity">
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index 8e7dd7d0..683b49d7 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -8,7 +8,8 @@
ギャラリー検索
ギャラリー検索
イメージキャッシュクリア
- サイズ: %1$d%2$s
+ キャッシュをクリアするとイメージのロード速度に影響を与えます。実行しますか?
+ サイズ: %1$d%2$s
デフォルトキーワード
一回にロードするギャラリー数
検索設定
@@ -66,4 +67,7 @@
エラーが発生しました
ストレージ
カカオトーク
+ アプリロック
+ アップロックの種類
+ バージョン
\ 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 0b99f608..2ffdb6ec 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -7,7 +7,8 @@
갤러리 검색
기본 검색어
이미지 캐시 정리하기
- 사용량: %1$d%2$s
+ 캐시를 정리하면 이미지 로딩속도가 느려질 수 있습니다. 계속하시겠습니까?
+ 사용량: %1$d%2$s
한 번에 로드할 갤러리 수
검색 설정
설정
@@ -66,4 +67,7 @@
갤러리를 찾지 못했습니다
저장 공간
카카오톡 오픈채팅방
+ 앱 잠금
+ 앱 잠금 종류
+ 앱 버전
\ 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 2cc8d514..b8fd3621 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -80,17 +80,21 @@
Download error
Settings
+ App version
Search Settings
Galleries per page
Default query
Storage
Clear image cache
- Currently using %1$d%2$s
+ Deleting cache can affect image loading speed. Do you want to continue?
+ Currently using %1$d%2$s
Clear downloads
Delete all downloaded galleries.\nDo you want to continue?
Clear history
Do you want to clear histories?
%1$d histories saved
+ App lock
+ App lock type
Miscellaneous
Use hiyobi.me
Load images from hiyobi.me to improve loading speed (if available)
diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml
index 0ccfbbb2..5a802f27 100644
--- a/app/src/main/res/xml/root_preferences.xml
+++ b/app/src/main/res/xml/root_preferences.xml
@@ -2,6 +2,10 @@
+
+
@@ -24,6 +28,10 @@
+
+
@@ -34,6 +42,15 @@
+
+
+
+
+
+
diff --git a/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt b/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt
index bc7c0d78..1b864d91 100644
--- a/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt
+++ b/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt
@@ -1,15 +1,24 @@
package xyz.quaver.hitomi
import org.junit.Test
-import java.io.File
-import java.net.URL
+import java.net.InetAddress
+import java.net.UnknownHostException
+
class UnitTest {
@Test
fun test() {
- val galleries = getGalleryIDsForQuery("series:touhou_project")
- println(galleries.size)
+ }
+
+ private fun getByIp(host: String): InetAddress {
+ try {
+ return InetAddress.getByName(host)
+ } catch (e: UnknownHostException) {
+ // unlikely
+ throw RuntimeException(e)
+ }
+
}
@Test