From d705cd15b747f5aa64e1596f1f453ed272c85a4b Mon Sep 17 00:00:00 2001 From: tom5079 Date: Sun, 23 Jun 2019 00:23:17 +0900 Subject: [PATCH] Migrate to Android 29 Re-Added Cache clear to prevent deleting downloading images --- .idea/misc.xml | 2 +- app/build.gradle | 16 +++-- app/proguard-rules.pro | 9 +-- app/release/output.json | 2 +- .../quaver/pupil/ExampleInstrumentedTest.kt | 13 ++-- app/src/main/AndroidManifest.xml | 49 ++++++++------- .../pupil/adapters/GalleryBlockAdapter.kt | 2 +- .../quaver/pupil/adapters/ReaderAdapter.kt | 3 - .../java/xyz/quaver/pupil/ui/LockActivity.kt | 29 +++++++++ .../xyz/quaver/pupil/{ => ui}/MainActivity.kt | 47 +++++++------- .../quaver/pupil/ui/PatternLockFragment.kt | 46 ++++++++++++++ .../java/xyz/quaver/pupil/{ => ui}/Pupil.kt | 6 +- .../quaver/pupil/{ => ui}/ReaderActivity.kt | 8 ++- .../quaver/pupil/{ => ui}/SettingsActivity.kt | 61 +++++++++++++++---- .../quaver/pupil/util/GalleryDownloader.kt | 32 +++++----- .../main/java/xyz/quaver/pupil/util/file.kt | 3 +- .../main/java/xyz/quaver/pupil/util/lock.kt | 39 ++++++++++++ .../main/java/xyz/quaver/pupil/util/update.kt | 19 +++++- app/src/main/res/drawable/fingerprint.xml | 8 +++ app/src/main/res/drawable/lastpass.xml | 8 +++ app/src/main/res/drawable/lock_pattern.xml | 8 +++ app/src/main/res/layout/activity_lock.xml | 54 ++++++++++++++++ .../main/res/layout/activity_main_content.xml | 2 +- app/src/main/res/layout/activity_reader.xml | 2 +- .../main/res/layout/fragment_pattern_lock.xml | 19 ++++++ app/src/main/res/values-ja/strings.xml | 6 +- app/src/main/res/values-ko/strings.xml | 6 +- app/src/main/res/values/strings.xml | 6 +- app/src/main/res/xml/root_preferences.xml | 17 ++++++ .../test/java/xyz/quaver/hitomi/UnitTest.kt | 17 ++++-- 30 files changed, 420 insertions(+), 119 deletions(-) create mode 100644 app/src/main/java/xyz/quaver/pupil/ui/LockActivity.kt rename app/src/main/java/xyz/quaver/pupil/{ => ui}/MainActivity.kt (97%) create mode 100644 app/src/main/java/xyz/quaver/pupil/ui/PatternLockFragment.kt rename app/src/main/java/xyz/quaver/pupil/{ => ui}/Pupil.kt (94%) rename app/src/main/java/xyz/quaver/pupil/{ => ui}/ReaderActivity.kt (98%) rename app/src/main/java/xyz/quaver/pupil/{ => ui}/SettingsActivity.kt (81%) create mode 100644 app/src/main/java/xyz/quaver/pupil/util/lock.kt create mode 100644 app/src/main/res/drawable/fingerprint.xml create mode 100644 app/src/main/res/drawable/lastpass.xml create mode 100644 app/src/main/res/drawable/lock_pattern.xml create mode 100644 app/src/main/res/layout/activity_lock.xml create mode 100644 app/src/main/res/layout/fragment_pattern_lock.xml 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