Added global preferences object

This commit is contained in:
tom5079
2020-08-30 19:52:51 +09:00
parent fdd9b02388
commit 7ca4418a50
23 changed files with 157 additions and 248 deletions

View File

@@ -99,6 +99,7 @@ dependencies {
implementation ("xyz.quaver:libpupil:1.1") {
exclude group: 'org.jetbrains.kotlinx', module: 'kotlinx-serialization-core-jvm'
}
implementation "xyz.quaver:documentfilex:0.2"
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test:rules:1.3.0'

View File

@@ -35,12 +35,10 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.Dispatcher
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import xyz.quaver.pupil.util.GalleryList
import xyz.quaver.pupil.util.getProxyInfo
import xyz.quaver.pupil.util.*
import xyz.quaver.setClient
import java.io.File
import java.util.*
@@ -72,25 +70,18 @@ class Pupil : Application() {
}
override fun onCreate() {
val preference = PreferenceManager.getDefaultSharedPreferences(this)
preferences = PreferenceManager.getDefaultSharedPreferences(this)
val userID =
if (preference.getString("user_id", "").isNullOrEmpty()) {
UUID.randomUUID().toString().also {
preference.edit().putString("user_id", it).apply()
}
} else
preference.getString("user_id", "") ?: ""
val userID = Preferences["user_id", UUID.randomUUID().toString(), true]
FirebaseCrashlytics.getInstance().setUserId(userID)
val proxyInfo = getProxyInfo(this)
val proxyInfo = getProxyInfo()
clientBuilder = OkHttpClient.Builder()
.connectTimeout(0, TimeUnit.SECONDS)
.readTimeout(0, TimeUnit.SECONDS)
.proxy(proxyInfo.proxy())
.proxyAuthenticator(proxyInfo.authenticator())
.proxyInfo(proxyInfo)
.addInterceptor { chain ->
val request = chain.request()
val tag = request.tag() ?: return@addInterceptor chain.proceed(request)
@@ -99,18 +90,18 @@ class Pupil : Application() {
}
try {
preference.getString("dl_location", null).also {
if (!File(it!!).canWrite())
Preferences.get<String>("dl_location").also {
if (!File(it).canWrite())
throw Exception()
}
} catch (e: Exception) {
preference.edit().remove("dl_location").apply()
Preferences.remove("dl_location")
}
histories = GalleryList(File(ContextCompat.getDataDir(this), "histories.json"))
favorites = GalleryList(File(ContextCompat.getDataDir(this), "favorites.json"))
if (preference.getBoolean("old_history", true)) {
if (Preferences["new_history"]) {
CoroutineScope(Dispatchers.IO).launch {
histories.reversed().let {
histories.clear()
@@ -121,7 +112,7 @@ class Pupil : Application() {
favorites.addAll(it)
}
}
preference.edit().putBoolean("old_history", false).apply()
Preferences["new_history"] = true
}
if (BuildConfig.DEBUG)
@@ -167,7 +158,7 @@ class Pupil : Application() {
})
}
AppCompatDelegate.setDefaultNightMode(when (preference.getBoolean("dark_mode", false)) {
AppCompatDelegate.setDefaultNightMode(when (Preferences.get<Boolean>("dark_mode")) {
true -> AppCompatDelegate.MODE_NIGHT_YES
false -> AppCompatDelegate.MODE_NIGHT_NO
})

View File

@@ -31,7 +31,6 @@ import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.cardview.widget.CardView
import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.CircularProgressDrawable
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
@@ -55,6 +54,7 @@ import xyz.quaver.pupil.R
import xyz.quaver.pupil.favorites
import xyz.quaver.pupil.types.Tag
import xyz.quaver.pupil.util.GalleryList
import xyz.quaver.pupil.util.Preferences
import xyz.quaver.pupil.util.download.Cache
import xyz.quaver.pupil.util.wordCapitalize
import java.util.*
@@ -80,7 +80,7 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri
val reader = Cache(context).getReaderOrNull(galleryID)
CoroutineScope(Dispatchers.Main).launch {
if (reader == null || PreferenceManager.getDefaultSharedPreferences(context).getBoolean("cache_disable", false)) {
if (reader == null || Preferences["cache_disable"]) {
view.galleryblock_progressbar.visibility = View.GONE
view.galleryblock_progress_complete.visibility = View.GONE
return@launch

View File

@@ -24,10 +24,10 @@ import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.item_mirrors.view.*
import xyz.quaver.pupil.R
import xyz.quaver.pupil.util.Preferences
import java.util.*
class MirrorAdapter(context: Context) : RecyclerView.Adapter<MirrorAdapter.ViewHolder>() {
@@ -41,8 +41,7 @@ class MirrorAdapter(context: Context) : RecyclerView.Adapter<MirrorAdapter.ViewH
}.toMap()
val list = mirrors.keys.toMutableList().apply {
PreferenceManager.getDefaultSharedPreferences(context)
.getString("mirrors", "")!!
Preferences.get<String>("mirrors")
.split(">")
.reversed()
.forEach {

View File

@@ -18,12 +18,10 @@
package xyz.quaver.pupil.adapters
import android.app.Activity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.engine.DiskCacheStrategy
@@ -41,6 +39,7 @@ import xyz.quaver.hiyobi.cookie
import xyz.quaver.hiyobi.createImgList
import xyz.quaver.hiyobi.user_agent
import xyz.quaver.pupil.R
import xyz.quaver.pupil.util.Preferences
import xyz.quaver.pupil.util.download.Cache
import xyz.quaver.pupil.util.download.DownloadWorker
import java.util.*
@@ -96,9 +95,8 @@ class ReaderAdapter(private val glide: RequestManager,
holder.view.reader_index.text = (position+1).toString()
val preferences = PreferenceManager.getDefaultSharedPreferences(holder.view.context)
if (preferences.getBoolean("cache_disable", false)) {
val lowQuality = preferences.getBoolean("low_quality", false)
if (Preferences["cache_disable"]) {
val lowQuality: Boolean = Preferences["low_quality"]
val url = when (reader!!.code) {
Code.HITOMI ->

View File

@@ -28,8 +28,8 @@ import android.webkit.MimeTypeMap
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.FileProvider
import androidx.preference.PreferenceManager
import xyz.quaver.pupil.R
import xyz.quaver.pupil.util.Preferences
import java.io.File
class UpdateBroadcastReciever : BroadcastReceiver() {
@@ -41,9 +41,7 @@ class UpdateBroadcastReciever : BroadcastReceiver() {
DownloadManager.ACTION_DOWNLOAD_COMPLETE -> {
// Validate download
val preference = PreferenceManager.getDefaultSharedPreferences(context)
val downloadID = preference.getLong("update_download_id", -1)
val downloadID: Long = Preferences["update_download_id"]
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
if (intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) != downloadID)

View File

@@ -33,9 +33,11 @@ import kotlinx.coroutines.launch
import okhttp3.Interceptor
import okhttp3.ResponseBody
import okio.*
import xyz.quaver.pupil.PupilInterceptor
import xyz.quaver.pupil.R
import xyz.quaver.pupil.interceptors
private typealias ProgressListener = (Any?, Long, Long, Boolean) -> Unit
private typealias ProgressListener = (DownloadService.Tag, Long, Long, Boolean) -> Unit
class Cache(context: Context) : ContextWrapper(context) {
@@ -45,6 +47,8 @@ class Cache(context: Context) : ContextWrapper(context) {
class DownloadService : Service() {
data class Tag(val galleryID: Int, val index: Int)
//region Notification
private val notificationManager by lazy {
NotificationManagerCompat.from(this)
@@ -61,9 +65,7 @@ class DownloadService : Service() {
//region ProgressListener
@Suppress("UNCHECKED_CAST")
private val progressListener: ProgressListener = listener@{ tag, bytesRead, contentLength, done ->
val (galleryID, index) = (tag as? Pair<Int, Int>) ?: return@listener
private val progressListener: ProgressListener = { (galleryID, index), bytesRead, contentLength, done ->
if (!done && progress[galleryID]?.get(index)?.isFinite() == true)
progress[galleryID]?.set(index, bytesRead * 100F / contentLength)
}
@@ -92,14 +94,14 @@ class DownloadService : Service() {
val bytesRead = super.read(sink, byteCount)
totalBytesRead += if (bytesRead == -1L) 0L else bytesRead
progressListener.invoke(tag, totalBytesRead, responseBody.contentLength(), bytesRead == -1L)
progressListener.invoke(tag as Tag, totalBytesRead, responseBody.contentLength(), bytesRead == -1L)
return bytesRead
}
}
}
val interceptor = Interceptor { chain ->
private val interceptor: PupilInterceptor = { chain ->
val request = chain.request()
var response = chain.proceed(request)
@@ -131,10 +133,7 @@ class DownloadService : Service() {
override fun onCreate() {
startForeground(R.id.downloader_notification_id, serviceNotification.build())
}
override fun onDestroy() {
interceptors[Tag::class] = interceptor
}
@@ -146,7 +145,7 @@ class DownloadService : Service() {
override fun onBind(p0: Intent?) = binder
fun load(galleryID: Int) {
}
fun download(galleryID: Int) = CoroutineScope(Dispatchers.IO).launch {

View File

@@ -27,7 +27,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager
import com.andrognito.patternlockview.PatternLockView
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_lock.*
@@ -38,6 +37,7 @@ import xyz.quaver.pupil.ui.fragment.PINLockFragment
import xyz.quaver.pupil.ui.fragment.PatternLockFragment
import xyz.quaver.pupil.util.Lock
import xyz.quaver.pupil.util.LockManager
import xyz.quaver.pupil.util.Preferences
class LockActivity : AppCompatActivity() {
@@ -195,7 +195,7 @@ class LockActivity : AppCompatActivity() {
}
if (
PreferenceManager.getDefaultSharedPreferences(this).getBoolean("lock_fingerprint", false)
Preferences["lock_fingerprint"]
&& BiometricManager.from(this).canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS
) {
lock_fingerprint.apply {

View File

@@ -22,7 +22,6 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.graphics.drawable.Animatable
import android.net.Proxy
import android.net.Uri
import android.os.Build
import android.os.Bundle
@@ -41,7 +40,6 @@ import androidx.cardview.widget.CardView
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.FloatingSearchViewDayNight
@@ -88,7 +86,7 @@ class MainActivity : AppCompatActivity() {
DOWNLOAD,
FAVORITE
}
enum class SortMode {
NEWEST,
POPULAR
@@ -134,17 +132,15 @@ class MainActivity : AppCompatActivity() {
if (lockManager.isNotEmpty())
startActivityForResult(Intent(this, LockActivity::class.java), R.id.request_lock.normalizeID())
val preference = PreferenceManager.getDefaultSharedPreferences(this)
if (Locale.getDefault().language == "ko") {
if (!preference.getBoolean("https_block_alert", false)) {
if (Preferences["https_block_alert"]) {
android.app.AlertDialog.Builder(this).apply {
setTitle(R.string.https_block_alert_title)
setMessage(R.string.https_block_alert)
setPositiveButton(android.R.string.ok) { _, _ -> }
}.show()
preference.edit().putBoolean("https_block_alert", true).apply()
Preferences["https_block_alert"] = false
}
}
@@ -199,9 +195,7 @@ class MainActivity : AppCompatActivity() {
}
override fun onResume() {
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
if (preferences.getBoolean("security_mode", false))
if (Preferences["security_mode"])
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE)
@@ -212,8 +206,7 @@ class MainActivity : AppCompatActivity() {
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
val preference = PreferenceManager.getDefaultSharedPreferences(this)
val perPage = preference.getString("per_page", "25")!!.toIntOrNull() ?: 25
val perPage = Preferences["per_page", "25"].toInt()
val maxPage = ceil(totalItems / perPage.toDouble()).roundToInt()
return when(keyCode) {
@@ -362,8 +355,7 @@ class MainActivity : AppCompatActivity() {
with(main_fab_jump) {
setImageResource(R.drawable.ic_jump)
setOnClickListener {
val preference = PreferenceManager.getDefaultSharedPreferences(context)
val perPage = preference.getString("per_page", "25")!!.toIntOrNull() ?: 25
val perPage = Preferences["per_page", "25"].toInt()
val editText = EditText(context)
AlertDialog.Builder(context).apply {
@@ -469,7 +461,7 @@ class MainActivity : AppCompatActivity() {
onDownloadClickedHandler = { position ->
val galleryID = galleries[position].id
val worker = DownloadWorker.getInstance(context)
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean("cache_disable", false))
if (Preferences["cache_disable"])
Toast.makeText(context, R.string.settings_download_when_cache_disable_warning, Toast.LENGTH_SHORT).show()
else {
if (worker.progress.indexOfKey(galleryID) >= 0 && Cache(context).isDownloading(galleryID)) { //download in progress
@@ -554,8 +546,7 @@ class MainActivity : AppCompatActivity() {
var origin = 0f
var target = -1
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
val perPage = preferences.getString("per_page", "25")!!.toInt()
val perPage = Preferences["per_page", "25"].toInt()
setOnTouchListener { _, event ->
when(event.action) {
MotionEvent.ACTION_UP -> {
@@ -1006,8 +997,7 @@ class MainActivity : AppCompatActivity() {
}
private fun fetchGalleries(query: String, sortMode: SortMode) {
val preference = PreferenceManager.getDefaultSharedPreferences(this)
val defaultQuery = preference.getString("default_query", "")!!
val defaultQuery: String = Preferences["default_query"]
if (query != queryStack.lastOrNull()) {
queryStack.remove(query)
@@ -1104,8 +1094,7 @@ class MainActivity : AppCompatActivity() {
}
private fun loadBlocks() {
val preference = PreferenceManager.getDefaultSharedPreferences(this)
val perPage = preference.getString("per_page", "25")?.toInt() ?: 25
val perPage = Preferences["per_page", "25"].toInt()
loadingJob = CoroutineScope(Dispatchers.IO).launch {
val galleryIDs = try {

View File

@@ -43,12 +43,11 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import xyz.quaver.Code
import xyz.quaver.pupil.Pupil
import xyz.quaver.pupil.R
import xyz.quaver.pupil.adapters.ReaderAdapter
import xyz.quaver.pupil.favorites
import xyz.quaver.pupil.histories
import xyz.quaver.pupil.util.GalleryList
import xyz.quaver.pupil.util.Preferences
import xyz.quaver.pupil.util.download.Cache
import xyz.quaver.pupil.util.download.DownloadWorker
import java.util.*
@@ -103,7 +102,7 @@ class ReaderActivity : AppCompatActivity() {
}
initView()
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("cache_disable", false)) {
if (Preferences["cache_disable"]) {
reader_download_progressbar.visibility = View.GONE
CoroutineScope(Dispatchers.IO).launch {
val reader = Cache(this@ReaderActivity).getReader(galleryID)
@@ -159,9 +158,7 @@ class ReaderActivity : AppCompatActivity() {
}
override fun onResume() {
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
if (preferences.getBoolean("security_mode", false))
if (Preferences["security_mode"])
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE)

View File

@@ -27,12 +27,14 @@ import android.os.Bundle
import android.view.MenuItem
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.Preference
import androidx.preference.PreferenceManager
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.settings_activity.*
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import net.rdrei.android.dirchooser.DirectoryChooserActivity
import xyz.quaver.io.util.toFile
import xyz.quaver.pupil.Pupil
import xyz.quaver.pupil.R
import xyz.quaver.pupil.favorites
@@ -60,9 +62,7 @@ class SettingsActivity : AppCompatActivity() {
}
override fun onResume() {
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
if (preferences.getBoolean("security_mode", false))
if (Preferences["security_mode"])
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE)
@@ -135,9 +135,7 @@ class SettingsActivity : AppCompatActivity() {
Snackbar.LENGTH_LONG
).show()
else
PreferenceManager.getDefaultSharedPreferences(this).edit()
.putString("dl_location", file.canonicalPath)
.apply()
Preferences["dl_location"] = file.canonicalPath
}
}
}
@@ -152,9 +150,7 @@ class SettingsActivity : AppCompatActivity() {
Snackbar.LENGTH_LONG
).show()
else
PreferenceManager.getDefaultSharedPreferences(this).edit()
.putString("dl_location", File(directory).canonicalPath)
.apply()
Preferences["dl_location"] = File(directory).canonicalPath
}
}
else -> super.onActivityResult(requestCode, resultCode, data)

View File

@@ -28,11 +28,11 @@ 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.*
import kotlinx.android.synthetic.main.dialog_default_query.view.*
import xyz.quaver.pupil.R
import xyz.quaver.pupil.types.Tags
import xyz.quaver.pupil.util.Preferences
class DefaultQueryDialog(context : Context) : AlertDialog(context) {
@@ -82,9 +82,8 @@ class DefaultQueryDialog(context : Context) : AlertDialog(context) {
@SuppressLint("InflateParams")
private fun build() : View {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
val tags = Tags.parse(
preferences.getString("default_query", "") ?: ""
Preferences["default_query"]
)
val view = LayoutInflater.from(context).inflate(R.layout.dialog_default_query, null)

View File

@@ -32,7 +32,6 @@ import android.widget.RadioButton
import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager
import kotlinx.android.synthetic.main.item_dl_location.view.*
import net.rdrei.android.dirchooser.DirectoryChooserActivity
import net.rdrei.android.dirchooser.DirectoryChooserConfig
@@ -42,8 +41,6 @@ import java.io.File
@SuppressLint("InflateParams")
class DownloadLocationDialog(val activity: Activity) : AlertDialog(activity) {
private val preference = PreferenceManager.getDefaultSharedPreferences(context)
private val buttons = mutableListOf<Pair<RadioButton, File?>>()
override fun onCreate(savedInstanceState: Bundle?) {
@@ -79,7 +76,7 @@ class DownloadLocationDialog(val activity: Activity) : AlertDialog(activity) {
pair.first.isChecked = false
}
button.performClick()
preference.edit().putString("dl_location", dir.canonicalPath).apply()
Preferences["dl_location"] = dir.canonicalPath
}
buttons.add(button to dir)
})

View File

@@ -24,13 +24,13 @@ import android.content.Context
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import xyz.quaver.pupil.R
import xyz.quaver.pupil.adapters.MirrorAdapter
import xyz.quaver.pupil.util.Preferences
class MirrorDialog(context: Context) : AlertDialog(context) {
@@ -82,10 +82,7 @@ class MirrorDialog(context: Context) : AlertDialog(context) {
}
onItemMoved = {
PreferenceManager.getDefaultSharedPreferences(context)
.edit()
.putString("mirrors", it.joinToString(">"))
.apply()
Preferences["mirrors", it.joinToString(">")]
}
}
}

View File

@@ -27,7 +27,6 @@ import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import androidx.preference.PreferenceManager
import kotlinx.android.synthetic.main.dialog_proxy.view.*
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
@@ -35,8 +34,10 @@ import xyz.quaver.pupil.R
import xyz.quaver.pupil.client
import xyz.quaver.pupil.clientBuilder
import xyz.quaver.pupil.clientHolder
import xyz.quaver.pupil.util.Preferences
import xyz.quaver.pupil.util.ProxyInfo
import xyz.quaver.pupil.util.getProxyInfo
import xyz.quaver.pupil.util.proxyInfo
import java.net.Proxy
class ProxyDialog(context: Context) : Dialog(context) {
@@ -54,7 +55,7 @@ class ProxyDialog(context: Context) : Dialog(context) {
@SuppressLint("InflateParams")
private fun build() : View {
val proxyInfo = getProxyInfo(context)
val proxyInfo = getProxyInfo()
val view = LayoutInflater.from(context).inflate(R.layout.dialog_proxy, null)
@@ -119,13 +120,10 @@ class ProxyDialog(context: Context) : Dialog(context) {
}
ProxyInfo(type, addr, port, username, password).let {
PreferenceManager.getDefaultSharedPreferences(context).edit().putString("proxy",
Json.encodeToString(it)
).apply()
Preferences["proxy"] = Json.encodeToString(it)
clientBuilder
.proxy(it.proxy())
.proxyAuthenticator(it.authenticator())
.proxyInfo(it)
clientHolder = null
client
}

View File

@@ -24,12 +24,12 @@ import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import androidx.preference.SwitchPreferenceCompat
import xyz.quaver.pupil.R
import xyz.quaver.pupil.ui.LockActivity
import xyz.quaver.pupil.util.Lock
import xyz.quaver.pupil.util.LockManager
import xyz.quaver.pupil.util.Preferences
class LockSettingsFragment : PreferenceFragmentCompat() {
@@ -53,7 +53,7 @@ class LockSettingsFragment : PreferenceFragmentCompat() {
if (lockManager.isEmpty()) {
(findPreference<Preference>("lock_fingerprint") as SwitchPreferenceCompat).isChecked = false
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean("lock_fingerprint", false).apply()
Preferences["lock_fingerprint"] = false
}
}

View File

@@ -18,27 +18,17 @@
package xyz.quaver.pupil.ui.fragment
import android.Manifest
import android.content.*
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.app.ActivityCompat
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 kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import net.rdrei.android.dirchooser.DirectoryChooserActivity
import net.rdrei.android.dirchooser.DirectoryChooserConfig
import xyz.quaver.pupil.Pupil
import xyz.quaver.pupil.R
import xyz.quaver.pupil.histories
import xyz.quaver.pupil.ui.LockActivity
@@ -52,15 +42,12 @@ import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader
class SettingsFragment :
PreferenceFragmentCompat(),
Preference.OnPreferenceClickListener,
Preference.OnPreferenceChangeListener,
SharedPreferences.OnSharedPreferenceChangeListener {
lateinit var sharedPreference: SharedPreferences
override fun onResume() {
super.onResume()
@@ -160,7 +147,7 @@ class SettingsFragment :
"default_query" -> {
DefaultQueryDialog(requireContext()).apply {
onPositiveButtonClickListener = { newTags ->
sharedPreferences.edit().putString("default_query", newTags.toString()).apply()
Preferences["default_query"] = newTags.toString()
summary = newTags.toString()
}
}.show()
@@ -182,7 +169,7 @@ class SettingsFragment :
}
"user_id" -> {
(context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager).setPrimaryClip(
ClipData.newPlainText("user_id", sharedPreference.getString("user_id", ""))
ClipData.newPlainText("user_id", Preferences.get<String>("user_id"))
)
Toast.makeText(context, R.string.settings_user_id_toast, Toast.LENGTH_SHORT).show()
}
@@ -219,7 +206,7 @@ class SettingsFragment :
when (key) {
"proxy" -> {
summary = context?.let { getProxyInfo(it).type.name }
summary = context?.let { getProxyInfo().type.name }
}
"dl_location" -> {
summary = context?.let { getDownloadDirectory(it).canonicalPath }
@@ -231,8 +218,7 @@ class SettingsFragment :
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
sharedPreference = PreferenceManager.getDefaultSharedPreferences(requireContext())
sharedPreference.registerOnSharedPreferenceChangeListener(this)
Preferences.registerOnSharedPreferenceChangeListener(this)
initPreferences()
}
@@ -295,7 +281,7 @@ class SettingsFragment :
onPreferenceClickListener = this@SettingsFragment
}
"default_query" -> {
summary = sharedPreference.getString("default_query", "") ?: ""
summary = Preferences.get<String>("default_query")
onPreferenceClickListener = this@SettingsFragment
}
@@ -320,7 +306,7 @@ class SettingsFragment :
onPreferenceClickListener = this@SettingsFragment
}
"proxy" -> {
summary = getProxyInfo(requireContext()).type.name
summary = getProxyInfo().type.name
onPreferenceClickListener = this@SettingsFragment
}
@@ -334,7 +320,7 @@ class SettingsFragment :
onPreferenceClickListener = this@SettingsFragment
}
"user_id" -> {
summary = sharedPreference.getString("user_id", "")
summary = Preferences.get<String>("user_id")
onPreferenceClickListener = this@SettingsFragment
}
}

View File

@@ -0,0 +1,55 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package xyz.quaver.pupil.util
import android.content.SharedPreferences
import kotlin.reflect.KClass
lateinit var preferences: SharedPreferences
object Preferences: SharedPreferences by preferences {
@Suppress("UNCHECKED_CAST")
val putMap = mapOf<KClass<out Any>, (String, Any) -> Unit>(
String::class to { k, v -> edit().putString(k, v as String).apply() },
Int::class to { k, v -> edit().putBoolean(k, v as Boolean).apply() },
Long::class to { k, v -> edit().putLong(k, v as Long).apply() },
Boolean::class to { k, v -> edit().putBoolean(k, v as Boolean).apply() },
Set::class to { k, v -> edit().putStringSet(k, v as Set<String>).apply() }
)
val defMap = mapOf(
String::class to "",
Int::class to -1,
Long::class to -1,
Boolean::class to false,
Set::class to emptySet<Any>()
)
inline operator fun <reified T: Any> set(key: String, value: T) {
putMap[T::class]?.invoke(key, value)
}
inline operator fun <reified T: Any> get(key: String, defaultVal: T = defMap[T::class] as T, setIfNull: Boolean = false): T =
(all[key] as? T) ?: defaultVal.also { if (setIfNull) set(key, defaultVal) }
fun remove(key: String) {
edit().remove(key).apply()
}
}

View File

@@ -25,7 +25,6 @@ import android.os.Build
import android.os.storage.StorageManager
import android.provider.DocumentsContract
import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager
import java.io.File
import java.io.FileOutputStream
import java.lang.reflect.Array
@@ -41,8 +40,8 @@ fun getCachedGallery(context: Context, galleryID: Int) =
}
fun getDownloadDirectory(context: Context) =
PreferenceManager.getDefaultSharedPreferences(context).getString("dl_location", null).let {
if (it != null && !it.startsWith("content"))
Preferences.get<String>("dl_location").let {
if (it.isNotEmpty() && !it.startsWith("content"))
File(it)
else
context.getExternalFilesDir(null)!!
@@ -124,94 +123,5 @@ fun getVolumePath(context: Context, volumeID: String?): String? {
}.getOrNull()
}
// Credits go to https://stackoverflow.com/questions/34927748/android-5-0-documentfile-from-tree-uri/36162691#36162691
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
fun getVolumeIdFromTreeUri(uri: Uri) =
DocumentsContract.getTreeDocumentId(uri).split(':').let {
if (it.isNotEmpty())
it[0]
else
null
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
fun getDocumentPathFromTreeUri(uri: Uri) =
DocumentsContract.getTreeDocumentId(uri).split(':').let {
if (it.size >= 2)
it[1]
else
File.separator
}
fun getFullPathFromTreeUri(context: Context, uri: Uri) : String? {
val volumePath = getVolumePath(context, getVolumeIdFromTreeUri(uri) ?: return null).let {
it ?: return File.separator
if (it.endsWith(File.separator))
it.dropLast(1)
else
it
}
val documentPath = getDocumentPathFromTreeUri(uri).let {
if (it.endsWith(File.separator))
it.dropLast(1)
else
it
}
return if (documentPath.isNotEmpty()) {
if (documentPath.startsWith(File.separator))
volumePath + documentPath
else
volumePath + File.separator + documentPath
} else
volumePath
}
// Huge thanks to avluis(https://github.com/avluis)
// This code is originated from Hentoid(https://github.com/avluis/Hentoid) under Apache-2.0 license.
fun Uri.toFile(context: Context): File? {
val path = this.path ?: return null
val pathSeparator = path.indexOf(':')
val folderName = path.substring(pathSeparator+1)
// Determine whether the designated file is
// - on a removable media (e.g. SD card, OTG)
// or
// - on the internal phone memory
val removableMediaFolderRoots = getExtSdCardPaths(context)
/* First test is to compare root names with known roots of removable media
* In many cases, the SD card root name is shared between pre-SAF (File) and SAF (DocumentFile) frameworks
* (e.g. /storage/3437-3934 vs. /tree/3437-3934)
* This is what the following block is trying to do
*/
for (s in removableMediaFolderRoots) {
val sRoot = s.substring(s.lastIndexOf(File.separatorChar))
val root = path.substring(0, pathSeparator).let {
it.substring(it.lastIndexOf(File.separatorChar))
}
if (sRoot.equals(root, true)) {
return File(s + File.separatorChar + folderName)
}
}
/* In some other cases, there is no common name (e.g. /storage/sdcard1 vs. /tree/3437-3934)
* We can use a slower method to translate the Uri obtained with SAF into a pre-SAF path
* and compare it to the known removable media volume names
*/
val root = getFullPathFromTreeUri(context, this)
for (s in removableMediaFolderRoots) {
if (root?.startsWith(s) == true) {
return File(root)
}
}
return File(context.getExternalFilesDir(null)?.canonicalPath?.substringBeforeLast("/Android/data") ?: return null, folderName)
}
fun File.isParentOf(another: File) =
another.absolutePath.startsWith(this.absolutePath)

View File

@@ -19,6 +19,7 @@
package xyz.quaver.pupil.util
import android.annotation.SuppressLint
import okhttp3.OkHttpClient
import java.util.*
import kotlin.collections.ArrayList
@@ -59,4 +60,11 @@ fun byteToString(byte: Long, precision : Int = 1) : String {
*
* https://stackoverflow.com/questions/38072322/generate-16-bit-unique-ids-in-android-for-startactivityforresult
*/
fun Int.normalizeID() = this.and(0xFFFF)
fun Int.normalizeID() = this.and(0xFFFF)
fun OkHttpClient.Builder.proxyInfo(proxyInfo: ProxyInfo) = this.apply {
proxy(proxyInfo.proxy())
proxyInfo.authenticator()?.let {
proxyAuthenticator(it)
}
}

View File

@@ -19,11 +19,12 @@
package xyz.quaver.pupil.util
import android.content.Context
import androidx.preference.PreferenceManager
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import okhttp3.*
import okhttp3.Authenticator
import okhttp3.Credentials
import java.net.InetSocketAddress
import java.net.Proxy
@@ -36,29 +37,22 @@ data class ProxyInfo(
val password: String? = null
) {
fun proxy() : Proxy {
return if (host == null || port == null)
return if (host.isNullOrBlank() || port == null)
return Proxy.NO_PROXY
else
Proxy(type, InetSocketAddress.createUnresolved(host, port))
}
fun authenticator() = Authenticator { _, response ->
val credential = Credentials.basic(username ?: "", password ?: "")
fun authenticator(): Authenticator? = if (username.isNullOrBlank() || password.isNullOrBlank()) null else
Authenticator { _, response ->
val credential = Credentials.basic(username, password)
response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build()
}
response.request().newBuilder()
.header("Proxy-Authorization", credential)
.build()
}
}
fun getProxy(context: Context) =
getProxyInfo(context).proxy()
fun getProxyInfo(context: Context) =
PreferenceManager.getDefaultSharedPreferences(context).getString("proxy", null).let {
if (it == null)
ProxyInfo(Proxy.Type.DIRECT)
else
Json.decodeFromString(it)
}
fun getProxyInfo(): ProxyInfo =
Json.decodeFromString(Preferences["proxy", Json.encodeToString(ProxyInfo(Proxy.Type.DIRECT))])

View File

@@ -24,14 +24,15 @@ import android.net.Uri
import android.webkit.URLUtil
import androidx.appcompat.app.AlertDialog
import androidx.preference.PreferenceManager
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_main_content.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.*
import okhttp3.*
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Request
import okhttp3.Response
import ru.noties.markwon.Markwon
import xyz.quaver.pupil.BuildConfig
import xyz.quaver.pupil.R
@@ -51,17 +52,14 @@ fun getReleases(url: String) : JsonArray {
}
}
fun checkUpdate(context: Context, url: String) : JsonObject? {
fun checkUpdate(url: String) : JsonObject? {
val releases = getReleases(url)
if (releases.isEmpty())
return null
return releases.firstOrNull {
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean("beta", false))
true
else
it.jsonObject["prerelease"]?.jsonPrimitive?.booleanOrNull == false
Preferences["beta"] || it.jsonObject["prerelease"]?.jsonPrimitive?.booleanOrNull == false
}?.let {
if (it.jsonObject["tag_name"]?.jsonPrimitive?.contentOrNull == BuildConfig.VERSION_NAME)
null
@@ -130,7 +128,7 @@ fun checkUpdate(context: Context, force: Boolean = false) {
CoroutineScope(Dispatchers.Default).launch {
val update =
checkUpdate(context, context.getString(R.string.release_url)) ?: return@launch
checkUpdate(context.getString(R.string.release_url)) ?: return@launch
val url = getApkUrl(update) ?: return@launch

View File

@@ -88,8 +88,7 @@
<SwitchPreferenceCompat
app:key="security_mode"
app:title="@string/settings_security_mode_title"
app:summary="@string/settings_security_mode_summary"
app:defaultValue="true"/>
app:summary="@string/settings_security_mode_summary"/>
<SwitchPreferenceCompat
app:key="dark_mode"