From 93228459d7936fa8a4a6cb129fb5d5f055ff786e Mon Sep 17 00:00:00 2001 From: Pupil Date: Mon, 13 Jan 2020 20:53:27 +0900 Subject: [PATCH 01/15] Fixed language selection based on locale --- app/release/output.json | 2 +- app/src/main/java/xyz/quaver/pupil/util/misc.kt | 3 +-- app/src/main/java/xyz/quaver/pupil/util/update.kt | 6 +++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/release/output.json b/app/release/output.json index 4abc5e8a..0d9cdd3c 100644 --- a/app/release/output.json +++ b/app/release/output.json @@ -1 +1 @@ -[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":31,"versionName":"4.2","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":32,"versionName":"4.3","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/main/java/xyz/quaver/pupil/util/misc.kt b/app/src/main/java/xyz/quaver/pupil/util/misc.kt index 81dbb368..342e794b 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/misc.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/misc.kt @@ -49,8 +49,7 @@ fun byteToString(byte: Long, precision : Int = 1) : String { "GB", "TB" //really? ) - var size = byte.toDouble() - var suffixIndex = 0 + var size = byte.toDouble(); var suffixIndex = 0 while (size >= 1024) { size /= 1024 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 a206be15..c133ab94 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/update.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/update.kt @@ -93,9 +93,9 @@ fun checkUpdate(context: AppCompatActivity, force: Boolean = false) { fun extractReleaseNote(update: JsonObject, locale: Locale) : String { val markdown = update["body"]!!.content - val target = when(locale) { - Locale.KOREAN -> "한국어" - Locale.JAPANESE -> "日本語" + val target = when(locale.language) { + "ko" -> "한국어" + "ja" -> "日本語" else -> "English" } From e0ccac13c134d09aaa47c50163e43575848b7fc9 Mon Sep 17 00:00:00 2001 From: Pupil Date: Wed, 15 Jan 2020 10:58:53 +0900 Subject: [PATCH 02/15] Forgot to handle error :P --- app/build.gradle | 2 +- .../main/java/xyz/quaver/pupil/util/update.kt | 19 ++++++++++++++++--- app/src/main/res/values-ja/strings.xml | 2 +- app/src/main/res/values-ko/strings.xml | 4 ++-- app/src/main/res/values/strings.xml | 2 +- .../src/main/java/xyz/quaver/hitomi/reader.kt | 1 - 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 4b25e81b..db753c3c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,7 +20,7 @@ android { minSdkVersion 16 targetSdkVersion 29 versionCode 32 - versionName "4.3" + versionName "4.3-beta1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled true vectorDrawables.useSupportLibrary = true 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 c133ab94..e0c7d43c 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/update.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/update.kt @@ -151,12 +151,25 @@ fun checkUpdate(context: AppCompatActivity, force: Boolean = false) { priority = NotificationCompat.PRIORITY_LOW } - CoroutineScope(Dispatchers.IO).launch { + CoroutineScope(Dispatchers.IO).launch io@{ val target = File(getDownloadDirectory(context), "Pupil.apk") - URL(url).download(target) { progress, fileSize -> - builder.setProgress(fileSize.toInt(), progress.toInt(), false) + try { + URL(url).download(target) { progress, fileSize -> + builder.setProgress(fileSize.toInt(), progress.toInt(), false) + notificationManager.notify(UPDATE_NOTIFICATION_ID, builder.build()) + } + } catch (e: Exception) { + builder.apply { + setContentText(context.getString(R.string.update_failed)) + setMessage(context.getString(R.string.update_failed_message)) + setSmallIcon(android.R.drawable.stat_sys_download_done) + } + + notificationManager.cancel(UPDATE_NOTIFICATION_ID) notificationManager.notify(UPDATE_NOTIFICATION_ID, builder.build()) + + return@io } val install = Intent(Intent.ACTION_VIEW).apply { diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 74bf6715..37dc05d8 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -84,7 +84,7 @@ 投稿日時順 人気順 アップデートに失敗しました - マニュアルインストールが必要です。APKファイルは + アップデート中エラーが発生しました 無視 ロックファイルが破損されています。Pupilを再再インストールしてください。 権限がないため自動アップデートを行えません。ホームページで直接ダウンロードしてください。 diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index bbaa7d97..f574795f 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -83,8 +83,8 @@ 정렬 인기순 시간순 - "업데이트 " - 수동 업데이트가 필요합니다. APK 파일은 다운로드 폴더에 있습니다. + "업데이트 에러 + 업데이트 중 에러가 발생했습니다 무시 잠금 파일이 손상되었습니다! 앱을 재설치 해 주시기 바랍니다. 권한이 부여되어 있지 않아 자동 업데이트를 진행할 수 없습니다. 홈페이지에서 직접 다운로드 받으시기 바랍니다. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d2852e5b..df9688b9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -28,7 +28,7 @@ (Korean only) Update failed - Please install manually. APK file is in the Downloads folder. + Please install manually by visiting github release page :{ (or try again!) Cannot auto update because permission is denied. Please download manually from the webpage. Ignore diff --git a/libpupil/src/main/java/xyz/quaver/hitomi/reader.kt b/libpupil/src/main/java/xyz/quaver/hitomi/reader.kt index 4ed503a9..e3cfb193 100644 --- a/libpupil/src/main/java/xyz/quaver/hitomi/reader.kt +++ b/libpupil/src/main/java/xyz/quaver/hitomi/reader.kt @@ -20,7 +20,6 @@ import kotlinx.serialization.Serializable import org.jsoup.Jsoup fun getReferer(galleryID: Int) = "https://hitomi.la/reader/$galleryID.html" -fun webpUrlFromUrl(url: String) = url.replace("/galleries/", "/webp/") + ".webp" @Serializable data class GalleryInfo( From e81c189afc5732bd64e2f93375697f8b3a4cceac Mon Sep 17 00:00:00 2001 From: Pupil Date: Wed, 15 Jan 2020 11:28:38 +0900 Subject: [PATCH 03/15] Fixed thumbnail on gallery info --- .../src/main/java/xyz/quaver/hitomi/common.kt | 31 ++++++------------- .../main/java/xyz/quaver/hitomi/galleries.kt | 4 +-- .../test/java/xyz/quaver/hitomi/UnitTest.kt | 2 +- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/libpupil/src/main/java/xyz/quaver/hitomi/common.kt b/libpupil/src/main/java/xyz/quaver/hitomi/common.kt index ee84c3e2..82327704 100644 --- a/libpupil/src/main/java/xyz/quaver/hitomi/common.kt +++ b/libpupil/src/main/java/xyz/quaver/hitomi/common.kt @@ -54,17 +54,9 @@ fun subdomainFromURL(url: String, base: String? = null) : String { if (!base.isNullOrBlank()) retval = base - val r = Regex("""/galleries/\d*(\d)/""") - var m = r.find(url) - var b = 10 - - if (m == null) { - b = 16 - val r2 = Regex("""/[0-9a-f]/([0-9a-f]{2})/""") - m = r2.find(url) - if (m == null) - return retval - } + val b = 16 + val r = Regex("""/[0-9a-f]/([0-9a-f]{2})/""") + val m = r.find(url) ?: return retval val g = m.groupValues[1].toIntOrNull(b) ?: return retval @@ -84,15 +76,12 @@ fun fullPathFromHash(hash: String?) : String? { } } -fun urlFromHash(galleryID: Int, image: GalleryInfo, webp: String? = null) : String { - val ext = webp ?: image.name.split('.').last() - return when { - image.hash.isNullOrBlank() -> - "$protocol//a.hitomi.la/galleries/$galleryID/${image.name}" - else -> - "$protocol//a.hitomi.la/${webp?:"images"}/${fullPathFromHash(image.hash)}.$ext" - } +@Suppress("NAME_SHADOWING", "UNUSED_PARAMETER") +fun urlFromHash(galleryID: Int, image: GalleryInfo, dir: String? = null, ext: String? = null) : String { + val ext = ext ?: dir ?: image.name.split('.').last() + val dir = dir ?: "images" + return "$protocol//a.hitomi.la/$dir/${fullPathFromHash(image.hash)}.$ext" } -fun urlFromUrlFromHash(galleryID: Int, image: GalleryInfo, webp: String? = null) = - urlFromURL(urlFromHash(galleryID, image, webp)) \ No newline at end of file +fun urlFromUrlFromHash(galleryID: Int, image: GalleryInfo, dir: String? = null, ext: String? = null, base: String? = null) = + urlFromURL(urlFromHash(galleryID, image, dir, ext), base) \ No newline at end of file diff --git a/libpupil/src/main/java/xyz/quaver/hitomi/galleries.kt b/libpupil/src/main/java/xyz/quaver/hitomi/galleries.kt index dd52d235..1b88018e 100644 --- a/libpupil/src/main/java/xyz/quaver/hitomi/galleries.kt +++ b/libpupil/src/main/java/xyz/quaver/hitomi/galleries.kt @@ -68,8 +68,8 @@ fun getGallery(galleryID: Int) : Gallery { href.slice(5 until href.indexOf('-')) } - val thumbnails = getGalleryInfo(galleryID).map { - "$protocol//tn.hitomi.la/smalltn/$galleryID/${it.name}.jpg" + val thumbnails = getGalleryInfo(galleryID).map { galleryInfo -> + urlFromUrlFromHash(galleryID, galleryInfo, "smalltn", "jpg", "tn") } return Gallery(related, langList, cover, title, artists, groups, type, language, series, characters, tags, thumbnails) diff --git a/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt b/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt index 7d40a893..99b98087 100644 --- a/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt +++ b/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt @@ -68,7 +68,7 @@ class UnitTest { @Test fun test_getGallery() { - val gallery = getGallery(1510566) + val gallery = getGallery(1552751) print(gallery) } From c468764234d5b457ca076881bbc615df90b7b014 Mon Sep 17 00:00:00 2001 From: Pupil Date: Thu, 16 Jan 2020 20:37:43 +0900 Subject: [PATCH 04/15] Fixed enlarged chip spacing --- .../main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt | 1 + 1 file changed, 1 insertion(+) 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 1a65a3e4..eccc0556 100644 --- a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt +++ b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt @@ -220,6 +220,7 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri else -> null } text = tag.tag.wordCapitalize() + setEnsureMinTouchTargetSize(false) setOnClickListener { for (callback in onChipClickedHandler) callback.invoke(tag) From f3019e9b84a74bdad7830c2d8836b8eda927c85c Mon Sep 17 00:00:00 2001 From: Pupil Date: Mon, 20 Jan 2020 18:58:19 +0900 Subject: [PATCH 05/15] Some code cleanups :P #37 --- .../xyz/quaver/pupil/ui/SettingsActivity.kt | 376 +----------------- .../pupil/ui/dialog/DefaultQueryDialog.kt | 141 +++++++ .../quaver/pupil/ui/fragment/LockFragment.kt | 81 ++++ .../pupil/ui/fragment/SettingsFragment.kt | 275 +++++++++++++ .../main/java/xyz/quaver/pupil/util/misc.kt | 12 +- 5 files changed, 502 insertions(+), 383 deletions(-) create mode 100644 app/src/main/java/xyz/quaver/pupil/ui/dialog/DefaultQueryDialog.kt create mode 100644 app/src/main/java/xyz/quaver/pupil/ui/fragment/LockFragment.kt create mode 100644 app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt 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 61b0fe96..b3b0e6f6 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt @@ -45,6 +45,8 @@ import xyz.quaver.pupil.Pupil import xyz.quaver.pupil.R import xyz.quaver.pupil.types.Tags import xyz.quaver.pupil.ui.dialog.DownloadLocationDialog +import xyz.quaver.pupil.ui.fragment.LockFragment +import xyz.quaver.pupil.ui.fragment.SettingsFragment import xyz.quaver.pupil.util.* import java.io.File import java.nio.charset.Charset @@ -82,380 +84,6 @@ class SettingsActivity : AppCompatActivity() { super.onResume() } - class SettingsFragment : PreferenceFragmentCompat() { - - override fun onResume() { - super.onResume() - - val lockManager = LockManager(context!!) - - findPreference("app_lock")?.summary = if (lockManager.locks.isNullOrEmpty()) { - getString(R.string.settings_lock_none) - } else { - lockManager.locks?.joinToString(", ") { - when(it.type) { - Lock.Type.PATTERN -> getString(R.string.settings_lock_pattern) - Lock.Type.PIN -> getString(R.string.settings_lock_pin) - Lock.Type.PASSWORD -> getString(R.string.settings_lock_password) - } - } - } - } - - private fun getDirSize(dir: File) : String { - val size = dir.walk().map { it.length() }.sum() - - return getString(R.string.settings_clear_summary, byteToString(size)) - } - - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - setPreferencesFromResource(R.xml.root_preferences, rootKey) - - with(findPreference("app_version")) { - this!! - - val manager = context.packageManager - val info = manager.getPackageInfo(context.packageName, 0) - - summary = context.getString(R.string.settings_app_version_description, info.versionName) - - setOnPreferenceClickListener { - checkUpdate(activity as SettingsActivity, true) - - true - } - } - - with(findPreference("delete_cache")) { - this!! - - 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!! - - val dir = getDownloadDirectory(context) - - summary = getDirSize(dir) - - onPreferenceClickListener = Preference.OnPreferenceClickListener { - AlertDialog.Builder(context).apply { - setTitle(R.string.warning) - setMessage(R.string.settings_clear_downloads_alert_message) - setPositiveButton(android.R.string.yes) { _, _ -> - if (dir.exists()) - dir.deleteRecursively() - - val downloads = (activity!!.application as Pupil).downloads - - downloads.clear() - - summary = getDirSize(dir) - } - setNegativeButton(android.R.string.no) { _, _ -> } - }.show() - - true - } - } - with(findPreference("clear_history")) { - this!! - - val histories = (activity!!.application as Pupil).histories - - summary = getString(R.string.settings_clear_history_summary, histories.size) - - onPreferenceClickListener = Preference.OnPreferenceClickListener { - AlertDialog.Builder(context).apply { - setTitle(R.string.warning) - setMessage(R.string.settings_clear_history_alert_message) - setPositiveButton(android.R.string.yes) { _, _ -> - histories.clear() - summary = getString(R.string.settings_clear_history_summary, histories.size) - } - setNegativeButton(android.R.string.no) { _, _ -> } - }.show() - - true - } - } - - with(findPreference("dl_location")) { - this!! - - summary = getDownloadDirectory(context).absolutePath - - onPreferenceClickListener = Preference.OnPreferenceClickListener { - DownloadLocationDialog(context).apply { - onDownloadLocationChangedListener = { value -> - PreferenceManager.getDefaultSharedPreferences(context).edit() - .putInt(key, value) - .apply() - summary = getDownloadDirectory(context).absolutePath - } - }.show() - - true - } - } - - with(findPreference("default_query")) { - this!! - - val preferences = PreferenceManager.getDefaultSharedPreferences(context) - - summary = preferences.getString("default_query", "") ?: "" - - val languages = resources.getStringArray(R.array.languages).map { - it.split("|").let { split -> - Pair(split[0], split[1]) - } - }.toMap() - val reverseLanguages = languages.entries.associate { (k, v) -> v to k } - - val excludeBL = "-male:yaoi" - val excludeGuro = listOf("-female:guro", "-male:guro") - - onPreferenceClickListener = Preference.OnPreferenceClickListener { - val dialogView = LayoutInflater.from(context).inflate( - R.layout.dialog_default_query, - LinearLayout(context), - false - ) - - val tags = Tags.parse( - preferences.getString("default_query", "") ?: "" - ) - - summary = tags.toString() - - with(dialogView.default_query_dialog_language_selector) { - adapter = - ArrayAdapter( - context, - android.R.layout.simple_spinner_dropdown_item, - arrayListOf( - getString(R.string.default_query_dialog_language_selector_none) - ).apply { - addAll(languages.values) - } - ) - if (tags.any { it.area == "language" && !it.isNegative }) { - val tag = languages[tags.first { it.area == "language" }.tag] - if (tag != null) { - setSelection( - @Suppress("UNCHECKED_CAST") - (adapter as ArrayAdapter).getPosition(tag) - ) - tags.removeByArea("language", false) - } - } - } - - with(dialogView.default_query_dialog_BL_checkbox) { - isChecked = tags.contains(excludeBL) - if (tags.contains(excludeBL)) - tags.remove(excludeBL) - } - - with(dialogView.default_query_dialog_guro_checkbox) { - isChecked = excludeGuro.all { tags.contains(it) } - if (excludeGuro.all { tags.contains(it) }) - excludeGuro.forEach { - tags.remove(it) - } - } - - with(dialogView.default_query_dialog_edittext) { - setText(tags.toString(), TextView.BufferType.EDITABLE) - addTextChangedListener(object : TextWatcher { - override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} - - override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} - - override fun afterTextChanged(s: Editable?) { - s ?: return - - if (s.any { it.isUpperCase() }) - s.replace(0, s.length, s.toString().toLowerCase(Locale.getDefault())) - } - }) - } - - val dialog = AlertDialog.Builder(context!!).apply { - setView(dialogView) - }.create() - - dialogView.default_query_dialog_ok.setOnClickListener { - val newTags = Tags.parse(dialogView.default_query_dialog_edittext.text.toString()) - - with(dialogView.default_query_dialog_language_selector) { - if (selectedItemPosition != 0) - newTags.add("language:${reverseLanguages[selectedItem]}") - } - - if (dialogView.default_query_dialog_BL_checkbox.isChecked) - newTags.add(excludeBL) - - if (dialogView.default_query_dialog_guro_checkbox.isChecked) - excludeGuro.forEach { tag -> - newTags.add(tag) - } - - preferenceManager.sharedPreferences.edit().putString("default_query", newTags.toString()).apply() - summary = preferences.getString("default_query", "") ?: "" - tags.clear() - tags.addAll(newTags) - dialog.dismiss() - } - - dialog.show() - - true - } - } - with(findPreference("app_lock")) { - this!! - - val lockManager = LockManager(context) - - summary = if (lockManager.locks.isNullOrEmpty()) { - getString(R.string.settings_lock_none) - } else { - lockManager.locks?.joinToString(", ") { - when(it.type) { - Lock.Type.PATTERN -> getString(R.string.settings_lock_pattern) - Lock.Type.PIN -> getString(R.string.settings_lock_pin) - Lock.Type.PASSWORD -> getString(R.string.settings_lock_password) - } - } - } - - onPreferenceClickListener = Preference.OnPreferenceClickListener { - val intent = Intent(context, LockActivity::class.java) - activity?.startActivityForResult(intent, (activity as SettingsActivity).REQUEST_LOCK) - - true - } - } - - with(findPreference("dark_mode")) { - this!! - - onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> - AppCompatDelegate.setDefaultNightMode(when (newValue as Boolean) { - true -> AppCompatDelegate.MODE_NIGHT_YES - false -> AppCompatDelegate.MODE_NIGHT_NO - }) - - true - } - } - - with(findPreference("backup")) { - this!! - - onPreferenceClickListener = Preference.OnPreferenceClickListener { - File(ContextCompat.getDataDir(context), "favorites.json").copyTo( - File(getDownloadDirectory(context), "favorites.json"), - true - ) - - Snackbar.make(this@SettingsFragment.listView, R.string.settings_backup_snackbar, Snackbar.LENGTH_LONG) - .show() - - true - } - } - - with(findPreference("restore")) { - this!! - - onPreferenceClickListener = Preference.OnPreferenceClickListener { - val intent = Intent(Intent.ACTION_GET_CONTENT).apply { - addCategory(Intent.CATEGORY_OPENABLE) - type = "*/*" - } - - activity?.startActivityForResult(intent, (activity as SettingsActivity).REQUEST_RESTORE) - - true - } - } - } - } - - 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 - } - } - } - } - override fun onOptionsItemSelected(item: MenuItem?): Boolean { when (item?.itemId) { android.R.id.home -> onBackPressed() 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 new file mode 100644 index 00000000..6506cfab --- /dev/null +++ b/app/src/main/java/xyz/quaver/pupil/ui/dialog/DefaultQueryDialog.kt @@ -0,0 +1,141 @@ +/* + * 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.dialog + +import android.annotation.SuppressLint +import android.app.AlertDialog +import android.content.Context +import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher +import android.view.LayoutInflater +import android.view.View +import android.widget.ArrayAdapter +import androidx.preference.PreferenceManager +import kotlinx.android.synthetic.main.dialog_default_query.view.* +import xyz.quaver.pupil.R +import xyz.quaver.pupil.types.Tags + +class DefaultQueryDialog(context : Context) : AlertDialog(context) { + + private val languages = context.resources.getStringArray(R.array.languages).map { + it.split("|").let { split -> + Pair(split[0], split[1]) + } + }.toMap() + private val reverseLanguages = languages.entries.associate { (k, v) -> v to k } + + private val excludeBL = "-male:yaoi" + private val excludeGuro = listOf("-female:guro", "-male:guro") + + private lateinit var dialogView : View + + var onPositiveButtonClickListener : ((Tags) -> (Unit))? = null + + @SuppressLint("InflateParams") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + dialogView = LayoutInflater.from(context).inflate(R.layout.dialog_default_query, null) + + initView() + + setContentView(dialogView) + } + + private fun initView() { + val preferences = PreferenceManager.getDefaultSharedPreferences(context) + val tags = Tags.parse( + preferences.getString("default_query", "") ?: "" + ) + + with(dialogView.default_query_dialog_language_selector) { + adapter = + ArrayAdapter( + context, + android.R.layout.simple_spinner_dropdown_item, + arrayListOf( + context.getString(R.string.default_query_dialog_language_selector_none) + ).apply { + addAll(languages.values) + } + ) + if (tags.any { it.area == "language" && !it.isNegative }) { + val tag = languages[tags.first { it.area == "language" }.tag] + if (tag != null) { + setSelection( + @Suppress("UNCHECKED_CAST") + (adapter as ArrayAdapter).getPosition(tag) + ) + tags.removeByArea("language", false) + } + } + } + + with(dialogView.default_query_dialog_BL_checkbox) { + isChecked = tags.contains(excludeBL) + if (tags.contains(excludeBL)) + tags.remove(excludeBL) + } + + with(dialogView.default_query_dialog_guro_checkbox) { + isChecked = excludeGuro.all { tags.contains(it) } + if (excludeGuro.all { tags.contains(it) }) + excludeGuro.forEach { + tags.remove(it) + } + } + + with(dialogView.default_query_dialog_edittext) { + setText(tags.toString(), android.widget.TextView.BufferType.EDITABLE) + addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} + + override fun afterTextChanged(s: Editable?) { + s ?: return + + if (s.any { it.isUpperCase() }) + s.replace(0, s.length, s.toString().toLowerCase(java.util.Locale.getDefault())) + } + }) + } + + dialogView.default_query_dialog_ok.setOnClickListener { + val newTags = Tags.parse(dialogView.default_query_dialog_edittext.text.toString()) + + with(dialogView.default_query_dialog_language_selector) { + if (selectedItemPosition != 0) + newTags.add("language:${reverseLanguages[selectedItem]}") + } + + if (dialogView.default_query_dialog_BL_checkbox.isChecked) + newTags.add(excludeBL) + + if (dialogView.default_query_dialog_guro_checkbox.isChecked) + excludeGuro.forEach { tag -> + newTags.add(tag) + } + + onPositiveButtonClickListener?.invoke(newTags) + } + } + +} \ No newline at end of file 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 new file mode 100644 index 00000000..b95900c1 --- /dev/null +++ b/app/src/main/java/xyz/quaver/pupil/ui/fragment/LockFragment.kt @@ -0,0 +1,81 @@ +/* + * 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/SettingsFragment.kt b/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt new file mode 100644 index 00000000..7657fd5b --- /dev/null +++ b/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt @@ -0,0 +1,275 @@ +/* + * 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.appcompat.app.AppCompatDelegate +import androidx.core.content.ContextCompat +import androidx.preference.Preference +import androidx.preference.PreferenceCategory +import androidx.preference.PreferenceFragmentCompat +import androidx.preference.PreferenceManager +import com.google.android.material.snackbar.Snackbar +import xyz.quaver.pupil.Pupil +import xyz.quaver.pupil.R +import xyz.quaver.pupil.ui.LockActivity +import xyz.quaver.pupil.ui.SettingsActivity +import xyz.quaver.pupil.ui.dialog.DefaultQueryDialog +import xyz.quaver.pupil.ui.dialog.DownloadLocationDialog +import xyz.quaver.pupil.util.* +import java.io.File + + +class SettingsFragment : + PreferenceFragmentCompat(), + Preference.OnPreferenceClickListener, + Preference.OnPreferenceChangeListener { + + override fun onResume() { + super.onResume() + + val lockManager = LockManager(context!!) + + findPreference("app_lock")?.summary = if (lockManager.locks.isNullOrEmpty()) { + getString(R.string.settings_lock_none) + } else { + lockManager.locks?.joinToString(", ") { + when(it.type) { + Lock.Type.PATTERN -> getString(R.string.settings_lock_pattern) + Lock.Type.PIN -> getString(R.string.settings_lock_pin) + Lock.Type.PASSWORD -> getString(R.string.settings_lock_password) + } + } + } + } + + private fun getDirSize(dir: File) : String { + val size = dir.walk().map { it.length() }.sum() + + return getString(R.string.settings_clear_summary, byteToString(size)) + } + + override fun onPreferenceClick(preference: Preference?): Boolean { + with (preference) { + this ?: return false + + when (key) { + "app_version" -> { + checkUpdate(activity as SettingsActivity, true) + } + "delete_cache" -> { + val dir = File(context.cacheDir, "imageCache") + + 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() + } + "delete_downloads" -> { + val dir = getDownloadDirectory(context) + + AlertDialog.Builder(context).apply { + setTitle(R.string.warning) + setMessage(R.string.settings_clear_downloads_alert_message) + setPositiveButton(android.R.string.yes) { _, _ -> + if (dir.exists()) + dir.deleteRecursively() + + val downloads = (activity!!.application as Pupil).downloads + + downloads.clear() + + summary = getDirSize(dir) + } + setNegativeButton(android.R.string.no) { _, _ -> } + }.show() + } + "clear_history" -> { + val histories = (context.applicationContext as Pupil).histories + + AlertDialog.Builder(context).apply { + setTitle(R.string.warning) + setMessage(R.string.settings_clear_history_alert_message) + setPositiveButton(android.R.string.yes) { _, _ -> + histories.clear() + summary = getString(R.string.settings_clear_history_summary, histories.size) + } + setNegativeButton(android.R.string.no) { _, _ -> } + }.show() + } + "dl_location" -> { + DownloadLocationDialog(context).apply { + onDownloadLocationChangedListener = { value -> + PreferenceManager.getDefaultSharedPreferences(context).edit() + .putInt(key, value) + .apply() + summary = getDownloadDirectory(context).absolutePath + } + }.show() + } + "default_query" -> { + DefaultQueryDialog(context).apply { + onPositiveButtonClickListener = { newTags -> + sharedPreferences.edit().putString("default_query", newTags.toString()).apply() + summary = newTags.toString() + } + }.show() + } + "app_lock" -> { + val intent = Intent(context, LockActivity::class.java) + activity?.startActivityForResult(intent, (activity as SettingsActivity).REQUEST_LOCK) + } + "backup" -> { + File(ContextCompat.getDataDir(context), "favorites.json").copyTo( + File(getDownloadDirectory(context), "favorites.json"), + true + ) + + Snackbar.make(this@SettingsFragment.listView, R.string.settings_backup_snackbar, Snackbar.LENGTH_LONG) + .show() + } + "restore" -> { + val intent = Intent(Intent.ACTION_GET_CONTENT).apply { + addCategory(Intent.CATEGORY_OPENABLE) + type = "*/*" + } + + activity?.startActivityForResult(intent, (activity as SettingsActivity).REQUEST_RESTORE) + } + else -> return false + } + } + + return true + } + + override fun onPreferenceChange(preference: Preference?, newValue: Any?): Boolean { + with (preference) { + this ?: return false + + when (key) { + "dark_mode" -> { + AppCompatDelegate.setDefaultNightMode(when (newValue as Boolean) { + true -> AppCompatDelegate.MODE_NIGHT_YES + false -> AppCompatDelegate.MODE_NIGHT_NO + }) + } + else -> return false + } + } + + return true + } + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.root_preferences, rootKey) + + initPreferences() + } + + private fun initPreferences() { + for (i in 0 until preferenceScreen.preferenceCount) { + + preferenceScreen.getPreference(i).run { + if (this is PreferenceCategory) + (0 until preferenceCount).map { getPreference(it) } + else + listOf(this) + }.forEach { preference -> + with (preference) { + + 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) + + onPreferenceClickListener = this@SettingsFragment + } + "delete_cache" -> { + val dir = File(context.cacheDir, "imageCache") + summary = getDirSize(dir) + + onPreferenceClickListener = this@SettingsFragment + } + "delete_downloads" -> { + val dir = getDownloadDirectory(context) + summary = getDirSize(dir) + + onPreferenceClickListener = this@SettingsFragment + } + "clear_history" -> { + val histories = (activity!!.application as Pupil).histories + summary = getString(R.string.settings_clear_history_summary, histories.size) + + onPreferenceClickListener = this@SettingsFragment + } + "dl_location" -> { + summary = getDownloadDirectory(context).absolutePath + + onPreferenceClickListener = this@SettingsFragment + } + "default_query" -> { + val preferences = PreferenceManager.getDefaultSharedPreferences(context) + summary = preferences.getString("default_query", "") ?: "" + + onPreferenceClickListener = this@SettingsFragment + } + "app_lock" -> { + val lockManager = LockManager(context) + summary = + if (lockManager.locks.isNullOrEmpty()) { + getString(R.string.settings_lock_none) + } else { + lockManager.locks?.joinToString(", ") { + when (it.type) { + Lock.Type.PATTERN -> getString(R.string.settings_lock_pattern) + Lock.Type.PIN -> getString(R.string.settings_lock_pin) + Lock.Type.PASSWORD -> getString(R.string.settings_lock_password) + } + } + } + + onPreferenceClickListener = this@SettingsFragment + } + "dark_mode" -> { + onPreferenceChangeListener = this@SettingsFragment + } + "backup" -> { + onPreferenceClickListener = this@SettingsFragment + } + "restore" -> { + onPreferenceClickListener = this@SettingsFragment + } + } + + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/xyz/quaver/pupil/util/misc.kt b/app/src/main/java/xyz/quaver/pupil/util/misc.kt index 342e794b..67cbbf77 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/misc.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/misc.kt @@ -18,10 +18,12 @@ package xyz.quaver.pupil.util +import android.annotation.SuppressLint import java.util.* import kotlin.collections.ArrayList import kotlin.math.round +@SuppressLint("DefaultLocale") @UseExperimental(ExperimentalStdlibApi::class) fun String.wordCapitalize() : String { val result = ArrayList() @@ -32,14 +34,6 @@ fun String.wordCapitalize() : String { return result.joinToString(" ") } - -//https://discuss.kotlinlang.org/t/how-do-you-round-a-number-to-n-decimal-places/8843(fvasco) -fun Double.round(decimals: Int): Double { - var multiplier = 1.0 - repeat(decimals) { multiplier *= 10 } - return round(this * multiplier) / multiplier -} - fun byteToString(byte: Long, precision : Int = 1) : String { val suffix = listOf( @@ -56,6 +50,6 @@ fun byteToString(byte: Long, precision : Int = 1) : String { suffixIndex++ } - return "${size.round(precision)} ${suffix[suffixIndex]}" + return "%.${precision}f ${suffix[suffixIndex]}".format(size) } \ No newline at end of file From 7abf08f1fb8ad5e74a02965070ace87493df0607 Mon Sep 17 00:00:00 2001 From: Pupil Date: Mon, 20 Jan 2020 18:59:18 +0900 Subject: [PATCH 06/15] Some code cleanups :P #37 --- .../xyz/quaver/pupil/ui/SettingsActivity.kt | 17 ----------------- app/src/main/java/xyz/quaver/pupil/util/misc.kt | 3 +-- 2 files changed, 1 insertion(+), 19 deletions(-) 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 b3b0e6f6..e806513b 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt @@ -21,36 +21,19 @@ package xyz.quaver.pupil.ui import android.app.Activity import android.content.Intent import android.os.Bundle -import android.text.Editable -import android.text.TextWatcher -import android.view.LayoutInflater import android.view.MenuItem import android.view.WindowManager -import android.widget.ArrayAdapter -import android.widget.LinearLayout -import android.widget.TextView -import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.app.AppCompatDelegate -import androidx.core.content.ContextCompat -import androidx.preference.Preference -import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceManager import com.google.android.material.snackbar.Snackbar -import kotlinx.android.synthetic.main.dialog_default_query.view.* import kotlinx.serialization.ImplicitReflectionSerializer import kotlinx.serialization.json.Json import kotlinx.serialization.parseList import xyz.quaver.pupil.Pupil import xyz.quaver.pupil.R -import xyz.quaver.pupil.types.Tags -import xyz.quaver.pupil.ui.dialog.DownloadLocationDialog import xyz.quaver.pupil.ui.fragment.LockFragment import xyz.quaver.pupil.ui.fragment.SettingsFragment -import xyz.quaver.pupil.util.* -import java.io.File import java.nio.charset.Charset -import java.util.* class SettingsActivity : AppCompatActivity() { diff --git a/app/src/main/java/xyz/quaver/pupil/util/misc.kt b/app/src/main/java/xyz/quaver/pupil/util/misc.kt index 67cbbf77..ddee2443 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/misc.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/misc.kt @@ -21,13 +21,12 @@ package xyz.quaver.pupil.util import android.annotation.SuppressLint import java.util.* import kotlin.collections.ArrayList -import kotlin.math.round -@SuppressLint("DefaultLocale") @UseExperimental(ExperimentalStdlibApi::class) fun String.wordCapitalize() : String { val result = ArrayList() + @SuppressLint("DefaultLocale") for (word in this.split(" ")) result.add(word.capitalize(Locale.US)) From 08e38ed45c8dcaf50366d15c24fb3dcd23bfa11e Mon Sep 17 00:00:00 2001 From: Pupil Date: Wed, 22 Jan 2020 10:50:55 +0900 Subject: [PATCH 07/15] Pupil-25 Add option to download jpg instead of webp files --- .../pupil/ui/dialog/DefaultQueryDialog.kt | 2 +- .../pupil/ui/fragment/SettingsFragment.kt | 2 ++ .../quaver/pupil/util/GalleryDownloader.kt | 10 +++--- app/src/main/res/layout/nav_header_main.xml | 1 - app/src/main/res/values-ja/strings.xml | 2 ++ app/src/main/res/values-ko/strings.xml | 2 ++ app/src/main/res/values/strings.xml | 2 ++ app/src/main/res/xml/root_preferences.xml | 33 +++++++++++-------- .../src/main/java/xyz/quaver/hiyobi/reader.kt | 10 ++++-- 9 files changed, 42 insertions(+), 22 deletions(-) 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 6506cfab..09341979 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 @@ -19,7 +19,6 @@ package xyz.quaver.pupil.ui.dialog import android.annotation.SuppressLint -import android.app.AlertDialog import android.content.Context import android.os.Bundle import android.text.Editable @@ -27,6 +26,7 @@ import android.text.TextWatcher import android.view.LayoutInflater import android.view.View import android.widget.ArrayAdapter +import androidx.appcompat.app.AlertDialog import androidx.preference.PreferenceManager import kotlinx.android.synthetic.main.dialog_default_query.view.* import xyz.quaver.pupil.R 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 7657fd5b..58d8af96 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 @@ -137,6 +137,8 @@ class SettingsFragment : onPositiveButtonClickListener = { newTags -> sharedPreferences.edit().putString("default_query", newTags.toString()).apply() summary = newTags.toString() + dismiss() //This sucks + // TODO: make dialog dissmiss itself :P } }.show() } 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 2eb58b08..660bb913 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt @@ -166,6 +166,8 @@ class GalleryDownloader( fun start() { downloadJob = CoroutineScope(Dispatchers.Default).launch { val reader = reader!!.await() ?: return@launch + val lowQuality = PreferenceManager.getDefaultSharedPreferences(this@GalleryDownloader) + .getBoolean("low_quality", false) notificationBuilder.setContentTitle(reader.title) @@ -177,15 +179,15 @@ class GalleryDownloader( .setProgress(reader.galleryInfo.size, 0, false) .setContentText("0/${reader.galleryInfo.size}") - reader.galleryInfo.chunked(4).forEachIndexed { chunkIndex, chunked -> - chunked.mapIndexed { i, galleryInfo -> + reader.galleryInfo.chunked(4).forEachIndexed { chunkIndex, chunk -> + chunk.mapIndexed { i, galleryInfo -> val index = chunkIndex*4+i async(Dispatchers.IO) { val url = when(useHiyobi) { - true -> createImgList(galleryID, reader)[index].path + true -> createImgList(galleryID, reader, lowQuality)[index].path false -> when { - (!galleryInfo.hash.isNullOrBlank()) and (galleryInfo.haswebp == 1) -> + (!galleryInfo.hash.isNullOrBlank()) && (galleryInfo.haswebp == 1) && lowQuality -> urlFromUrlFromHash(galleryID, galleryInfo, "webp") else -> urlFromUrlFromHash(galleryID, galleryInfo) diff --git a/app/src/main/res/layout/nav_header_main.xml b/app/src/main/res/layout/nav_header_main.xml index 05a58114..22f041be 100644 --- a/app/src/main/res/layout/nav_header_main.xml +++ b/app/src/main/res/layout/nav_header_main.xml @@ -19,7 +19,6 @@ ここをクリックしてアップデートを行えます ベータチャンネルでアップデートを受信 v%s + 低解像度イメージ + ロード速度とデータ使用料を改善するため低解像度イメージをロード \ 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 f574795f..323652db 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -118,4 +118,6 @@ 여기를 클릭해서 업데이트를 진행할 수 있습니다 베타 채널에서 업데이트 v%s + 저해상도 이미지 + 로드 속도와 데이터 사용량을 줄이기 위해 저해상도 이미지를 로드 \ 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 df9688b9..18e36b99 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -140,6 +140,8 @@ Removable Storage Internal Storage %s available + Low quality images + Load low quality images to improve load speed and data usage diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index 17e0b78c..6b7bc320 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -3,12 +3,12 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> + app:key="app_version" + app:title="@string/settings_app_version_title"/> + app:key="beta" + app:title="@string/settings_beta"/> @@ -32,20 +32,25 @@ app:title="@string/settings_storage"> + app:key="delete_cache" + app:title="@string/settings_clear_cache"/> + app:key="delete_downloads" + app:title="@string/settings_clear_downloads"/> + app:key="clear_history" + app:title="@string/settings_clear_history"/> + app:key="dl_location" + app:title="@string/settings_dl_location"/> + + @@ -53,8 +58,8 @@ app:title="@string/settings_app_lock"> + app:key="app_lock" + app:title="@string/settings_app_lock_type"/> diff --git a/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt b/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt index 07c0a357..d464e0f4 100644 --- a/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt +++ b/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt @@ -79,5 +79,11 @@ fun getReader(galleryID: Int) : Reader { return Reader(Reader.Code.HIYOBI, title, galleryInfo) } -fun createImgList(galleryID: Int, reader: Reader) = - reader.galleryInfo.map { Images("$protocol//$hiyobi/data/$galleryID/${it.name}", galleryID, it.name) } \ No newline at end of file +fun createImgList(galleryID: Int, reader: Reader, lowQuality: Boolean = false) = + if (lowQuality) + reader.galleryInfo.map { + val name = it.name.replace(Regex("/.[^/.]+$"), "") + ".jpg" + Images("$protocol//$hiyobi/data/$galleryID/$name.jpg", galleryID, it.name) + } + else + reader.galleryInfo.map { Images("$protocol//$hiyobi/data/$galleryID/${it.name}", galleryID, it.name) } \ No newline at end of file From 683118a3f49dfb68701241b4a6955f7553965989 Mon Sep 17 00:00:00 2001 From: Pupil Date: Wed, 22 Jan 2020 11:07:55 +0900 Subject: [PATCH 08/15] Fixed old android not supporting ContentProvider --- app/src/main/java/xyz/quaver/pupil/util/update.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 e0c7d43c..a95f7b0e 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/update.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/update.kt @@ -21,6 +21,7 @@ package xyz.quaver.pupil.util import android.app.PendingIntent import android.content.Context import android.content.Intent +import android.net.Uri import android.webkit.MimeTypeMap import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity @@ -178,7 +179,11 @@ fun checkUpdate(context: AppCompatActivity, force: Boolean = false) { context, context.applicationContext.packageName + ".fileprovider", target - ), MimeTypeMap.getSingleton().getExtensionFromMimeType(".apk")) + ), MimeTypeMap.getSingleton().getMimeTypeFromExtension("apk")) + + if (resolveActivity(context.packageManager) == null) + setDataAndType(Uri.fromFile(target), + MimeTypeMap.getSingleton().getMimeTypeFromExtension("apk")) } builder.apply { From a6de64ceb9db6c4e262696659e181554593e4667 Mon Sep 17 00:00:00 2001 From: Pupil Date: Wed, 22 Jan 2020 11:21:18 +0900 Subject: [PATCH 09/15] Some code cleanups :P #37 --- app/src/main/java/xyz/quaver/pupil/ui/LockActivity.kt | 1 + .../xyz/quaver/pupil/ui/{ => fragment}/PatternLockFragment.kt | 2 +- app/src/main/res/layout/fragment_pattern_lock.xml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) rename app/src/main/java/xyz/quaver/pupil/ui/{ => fragment}/PatternLockFragment.kt (98%) 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 804d9d6a..f8d77d95 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/LockActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/LockActivity.kt @@ -27,6 +27,7 @@ import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.activity_lock.* import kotlinx.android.synthetic.main.fragment_pattern_lock.* import xyz.quaver.pupil.R +import xyz.quaver.pupil.ui.fragment.PatternLockFragment import xyz.quaver.pupil.util.Lock import xyz.quaver.pupil.util.LockManager diff --git a/app/src/main/java/xyz/quaver/pupil/ui/PatternLockFragment.kt b/app/src/main/java/xyz/quaver/pupil/ui/fragment/PatternLockFragment.kt similarity index 98% rename from app/src/main/java/xyz/quaver/pupil/ui/PatternLockFragment.kt rename to app/src/main/java/xyz/quaver/pupil/ui/fragment/PatternLockFragment.kt index 58c83689..a500d898 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/PatternLockFragment.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/fragment/PatternLockFragment.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package xyz.quaver.pupil.ui +package xyz.quaver.pupil.ui.fragment import android.os.Bundle import android.view.LayoutInflater diff --git a/app/src/main/res/layout/fragment_pattern_lock.xml b/app/src/main/res/layout/fragment_pattern_lock.xml index c5b05c51..ca208b32 100644 --- a/app/src/main/res/layout/fragment_pattern_lock.xml +++ b/app/src/main/res/layout/fragment_pattern_lock.xml @@ -22,7 +22,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" - tools:context=".ui.PatternLockFragment"> + tools:context=".ui.fragment.PatternLockFragment"> Date: Wed, 22 Jan 2020 11:42:27 +0900 Subject: [PATCH 10/15] Pupil-57 about the horizontal and search --- app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt | 2 ++ 1 file changed, 2 insertions(+) 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 a536dd36..b8f33aa6 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt @@ -29,6 +29,7 @@ import android.view.KeyEvent 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 @@ -729,6 +730,7 @@ class MainActivity : AppCompatActivity() { s.replace(0, s.length, s.toString().toLowerCase(Locale.getDefault())) } }) + searchInputView.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI with(main_searchview as FloatingSearchView) { val favoritesFile = File(ContextCompat.getDataDir(context), "favorites_tags.json") From 0b87c57fbff1a5be2d7dcb6798e34c7e35544a03 Mon Sep 17 00:00:00 2001 From: Pupil Date: Wed, 22 Jan 2020 23:11:54 +0900 Subject: [PATCH 11/15] Dependency update --- app/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index db753c3c..2a35109e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,7 +56,6 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.preference:preference:1.1.0' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0' @@ -65,8 +64,8 @@ dependencies { implementation 'com.android.support:multidex:1.0.3' implementation "com.daimajia.swipelayout:library:1.2.0@aar" implementation 'com.google.android.material:material:1.2.0-alpha03' - implementation 'com.google.firebase:firebase-core:17.2.1' - implementation 'com.google.firebase:firebase-perf:19.0.4' + implementation 'com.google.firebase:firebase-core:17.2.2' + implementation 'com.google.firebase:firebase-perf:19.0.5' 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' @@ -74,6 +73,7 @@ dependencies { implementation ("com.github.bumptech.glide:recyclerview-integration:4.9.0") { transitive = false } + implementation 'com.github.chrisbanes:PhotoView:2.0.0' implementation 'com.andrognito.patternlockview:patternlockview:1.0.0' implementation "ru.noties.markwon:core:${markwonVersion}" kapt 'com.github.bumptech.glide:compiler:4.9.0' From e81b5a4e3aafdf3434dc2035e7a566caf1213c63 Mon Sep 17 00:00:00 2001 From: Pupil Date: Wed, 22 Jan 2020 23:14:57 +0900 Subject: [PATCH 12/15] Added pinch-zoom --- app/src/main/res/layout/item_reader.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/layout/item_reader.xml b/app/src/main/res/layout/item_reader.xml index de2c4621..4a9ceffd 100644 --- a/app/src/main/res/layout/item_reader.xml +++ b/app/src/main/res/layout/item_reader.xml @@ -17,7 +17,7 @@ ~ along with this program. If not, see . --> - Date: Thu, 30 Jan 2020 00:01:53 +0900 Subject: [PATCH 13/15] Fixes bug when trying to open hiyobi-only galleries --- .../java/xyz/quaver/pupil/ui/MainActivity.kt | 22 ++++++------------- .../test/java/xyz/quaver/hitomi/UnitTest.kt | 4 +++- 2 files changed, 10 insertions(+), 16 deletions(-) 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 b8f33aa6..3ab6bd63 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt @@ -47,7 +47,6 @@ import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion import com.arlib.floatingsearchview.util.view.SearchInputView import com.bumptech.glide.Glide import com.google.android.material.appbar.AppBarLayout -import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main_content.* import kotlinx.coroutines.* @@ -366,21 +365,14 @@ class MainActivity : AppCompatActivity() { setTitle(R.string.main_open_gallery_by_id) setPositiveButton(android.R.string.ok) { _, _ -> - CoroutineScope(Dispatchers.Default).launch { - try { - val intent = Intent(this@MainActivity, ReaderActivity::class.java) - val gallery = - getGalleryBlock(editText.text.toString().toInt()) ?: throw Exception() - intent.putExtra("galleryID", gallery.id) - - startActivity(intent) - - histories.add(gallery.id) - } catch (e: Exception) { - Snackbar.make(main_layout, - R.string.main_open_gallery_by_id_error, Snackbar.LENGTH_LONG).show() + val galleryID = editText.text.toString().toInt() + val intent = Intent(this@MainActivity, ReaderActivity::class.java).apply { + putExtra("galleryID", galleryID) } - } + + startActivity(intent) + + histories.add(galleryID) } }.show() } diff --git a/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt b/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt index 99b98087..8d291e16 100644 --- a/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt +++ b/libpupil/src/test/java/xyz/quaver/hitomi/UnitTest.kt @@ -82,7 +82,9 @@ class UnitTest { @Test fun test_hiyobi() { - xyz.quaver.hiyobi.getReader(1510567) + val reader = xyz.quaver.hiyobi.getReader(10000062) + + print(reader) } @Test From e46d1123df11a07a25999f5b89ea7ec3c7025cd8 Mon Sep 17 00:00:00 2001 From: Pupil Date: Fri, 31 Jan 2020 10:24:19 +0900 Subject: [PATCH 14/15] resolves #62 --- libpupil/src/main/java/xyz/quaver/hitomi/common.kt | 7 +++---- libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/libpupil/src/main/java/xyz/quaver/hitomi/common.kt b/libpupil/src/main/java/xyz/quaver/hitomi/common.kt index 82327704..7901fbef 100644 --- a/libpupil/src/main/java/xyz/quaver/hitomi/common.kt +++ b/libpupil/src/main/java/xyz/quaver/hitomi/common.kt @@ -17,20 +17,19 @@ package xyz.quaver.hitomi import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonConfiguration import kotlinx.serialization.list import java.net.URL const val protocol = "https:" -fun getGalleryInfo(galleryID: Int): List { - return Json(JsonConfiguration.Stable).parse( +@Suppress("EXPERIMENTAL_API_USAGE") +fun getGalleryInfo(galleryID: Int) = + Json.nonstrict.parse( GalleryInfo.serializer().list, Regex("""\[.+]""").find( URL("$protocol//$domain/galleries/$galleryID.js").readText() )?.value ?: "[]" ) -} //common.js var adapose = false diff --git a/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt b/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt index d464e0f4..9500513e 100644 --- a/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt +++ b/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt @@ -17,7 +17,6 @@ package xyz.quaver.hiyobi import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonConfiguration import kotlinx.serialization.list import org.jsoup.Jsoup import xyz.quaver.hitomi.GalleryInfo @@ -64,7 +63,8 @@ fun getReader(galleryID: Int) : Reader { val title = Jsoup.connect(reader).get().title() - val galleryInfo = Json(JsonConfiguration.Stable).parse( + @Suppress("EXPERIMENTAL_API_USAGE") + val galleryInfo = Json.parse( GalleryInfo.serializer().list, with(URL(url).openConnection() as HttpsURLConnection) { setRequestProperty("User-Agent", user_agent) From b84cddffdc855675d4b51431878eda599a2aed06 Mon Sep 17 00:00:00 2001 From: Pupil Date: Fri, 31 Jan 2020 10:32:21 +0900 Subject: [PATCH 15/15] Version up & dependency update --- app/build.gradle | 22 +++++++++++----------- app/release/output.json | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 2a35109e..c0ea8a75 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,7 +20,7 @@ android { minSdkVersion 16 targetSdkVersion 29 versionCode 32 - versionName "4.3-beta1" + versionName "4.3-hotfix1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled true vectorDrawables.useSupportLibrary = true @@ -50,34 +50,34 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1' - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1' + 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-serialization-runtime:0.14.0" implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.preference:preference:1.1.0' implementation 'androidx.gridlayout:gridlayout:1.0.0' - implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0' - implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0' + implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation "androidx.biometric:biometric:1.0.1" implementation 'com.android.support:multidex:1.0.3' implementation "com.daimajia.swipelayout:library:1.2.0@aar" - implementation 'com.google.android.material:material:1.2.0-alpha03' + implementation 'com.google.android.material:material:1.2.0-alpha04' implementation 'com.google.firebase:firebase-core:17.2.2' implementation 'com.google.firebase:firebase-perf:19.0.5' 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.9.0' - implementation ("com.github.bumptech.glide:recyclerview-integration:4.9.0") { + implementation 'com.github.bumptech.glide:glide:4.10.0' + implementation ("com.github.bumptech.glide:recyclerview-integration:4.10.0") { transitive = false } - implementation 'com.github.chrisbanes:PhotoView:2.0.0' + implementation 'com.github.chrisbanes:PhotoView:2.3.0' implementation 'com.andrognito.patternlockview:patternlockview:1.0.0' implementation "ru.noties.markwon:core:${markwonVersion}" - kapt 'com.github.bumptech.glide:compiler:4.9.0' - testImplementation 'junit:junit:4.12' + kapt 'com.github.bumptech.glide:compiler:4.10.0' + testImplementation 'junit:junit:4.13' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test:rules:1.2.0' androidTestImplementation 'androidx.test:runner:1.2.0' diff --git a/app/release/output.json b/app/release/output.json index 0d9cdd3c..59883138 100644 --- a/app/release/output.json +++ b/app/release/output.json @@ -1 +1 @@ -[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":32,"versionName":"4.3","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":32,"versionName":"4.3-hotfix1","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file