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") { implementation ("xyz.quaver:libpupil:1.1") {
exclude group: 'org.jetbrains.kotlinx', module: 'kotlinx-serialization-core-jvm' exclude group: 'org.jetbrains.kotlinx', module: 'kotlinx-serialization-core-jvm'
} }
implementation "xyz.quaver:documentfilex:0.2"
testImplementation 'junit:junit:4.13' testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test:rules:1.3.0' 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.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import okhttp3.Dispatcher
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Response import okhttp3.Response
import xyz.quaver.pupil.util.GalleryList import xyz.quaver.pupil.util.*
import xyz.quaver.pupil.util.getProxyInfo
import xyz.quaver.setClient import xyz.quaver.setClient
import java.io.File import java.io.File
import java.util.* import java.util.*
@@ -72,25 +70,18 @@ class Pupil : Application() {
} }
override fun onCreate() { override fun onCreate() {
val preference = PreferenceManager.getDefaultSharedPreferences(this) preferences = PreferenceManager.getDefaultSharedPreferences(this)
val userID = val userID = Preferences["user_id", UUID.randomUUID().toString(), true]
if (preference.getString("user_id", "").isNullOrEmpty()) {
UUID.randomUUID().toString().also {
preference.edit().putString("user_id", it).apply()
}
} else
preference.getString("user_id", "") ?: ""
FirebaseCrashlytics.getInstance().setUserId(userID) FirebaseCrashlytics.getInstance().setUserId(userID)
val proxyInfo = getProxyInfo(this) val proxyInfo = getProxyInfo()
clientBuilder = OkHttpClient.Builder() clientBuilder = OkHttpClient.Builder()
.connectTimeout(0, TimeUnit.SECONDS) .connectTimeout(0, TimeUnit.SECONDS)
.readTimeout(0, TimeUnit.SECONDS) .readTimeout(0, TimeUnit.SECONDS)
.proxy(proxyInfo.proxy()) .proxyInfo(proxyInfo)
.proxyAuthenticator(proxyInfo.authenticator())
.addInterceptor { chain -> .addInterceptor { chain ->
val request = chain.request() val request = chain.request()
val tag = request.tag() ?: return@addInterceptor chain.proceed(request) val tag = request.tag() ?: return@addInterceptor chain.proceed(request)
@@ -99,18 +90,18 @@ class Pupil : Application() {
} }
try { try {
preference.getString("dl_location", null).also { Preferences.get<String>("dl_location").also {
if (!File(it!!).canWrite()) if (!File(it).canWrite())
throw Exception() throw Exception()
} }
} catch (e: Exception) { } catch (e: Exception) {
preference.edit().remove("dl_location").apply() Preferences.remove("dl_location")
} }
histories = GalleryList(File(ContextCompat.getDataDir(this), "histories.json")) histories = GalleryList(File(ContextCompat.getDataDir(this), "histories.json"))
favorites = GalleryList(File(ContextCompat.getDataDir(this), "favorites.json")) favorites = GalleryList(File(ContextCompat.getDataDir(this), "favorites.json"))
if (preference.getBoolean("old_history", true)) { if (Preferences["new_history"]) {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
histories.reversed().let { histories.reversed().let {
histories.clear() histories.clear()
@@ -121,7 +112,7 @@ class Pupil : Application() {
favorites.addAll(it) favorites.addAll(it)
} }
} }
preference.edit().putBoolean("old_history", false).apply() Preferences["new_history"] = true
} }
if (BuildConfig.DEBUG) 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 true -> AppCompatDelegate.MODE_NIGHT_YES
false -> AppCompatDelegate.MODE_NIGHT_NO false -> AppCompatDelegate.MODE_NIGHT_NO
}) })

View File

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

View File

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

View File

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

View File

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

View File

@@ -33,9 +33,11 @@ import kotlinx.coroutines.launch
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.ResponseBody import okhttp3.ResponseBody
import okio.* import okio.*
import xyz.quaver.pupil.PupilInterceptor
import xyz.quaver.pupil.R 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) { class Cache(context: Context) : ContextWrapper(context) {
@@ -45,6 +47,8 @@ class Cache(context: Context) : ContextWrapper(context) {
class DownloadService : Service() { class DownloadService : Service() {
data class Tag(val galleryID: Int, val index: Int)
//region Notification //region Notification
private val notificationManager by lazy { private val notificationManager by lazy {
NotificationManagerCompat.from(this) NotificationManagerCompat.from(this)
@@ -61,9 +65,7 @@ class DownloadService : Service() {
//region ProgressListener //region ProgressListener
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private val progressListener: ProgressListener = listener@{ tag, bytesRead, contentLength, done -> private val progressListener: ProgressListener = { (galleryID, index), bytesRead, contentLength, done ->
val (galleryID, index) = (tag as? Pair<Int, Int>) ?: return@listener
if (!done && progress[galleryID]?.get(index)?.isFinite() == true) if (!done && progress[galleryID]?.get(index)?.isFinite() == true)
progress[galleryID]?.set(index, bytesRead * 100F / contentLength) progress[galleryID]?.set(index, bytesRead * 100F / contentLength)
} }
@@ -92,14 +94,14 @@ class DownloadService : Service() {
val bytesRead = super.read(sink, byteCount) val bytesRead = super.read(sink, byteCount)
totalBytesRead += if (bytesRead == -1L) 0L else bytesRead 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 return bytesRead
} }
} }
} }
val interceptor = Interceptor { chain -> private val interceptor: PupilInterceptor = { chain ->
val request = chain.request() val request = chain.request()
var response = chain.proceed(request) var response = chain.proceed(request)
@@ -131,10 +133,7 @@ class DownloadService : Service() {
override fun onCreate() { override fun onCreate() {
startForeground(R.id.downloader_notification_id, serviceNotification.build()) startForeground(R.id.downloader_notification_id, serviceNotification.build())
} interceptors[Tag::class] = interceptor
override fun onDestroy() {
} }
@@ -146,7 +145,7 @@ class DownloadService : Service() {
override fun onBind(p0: Intent?) = binder override fun onBind(p0: Intent?) = binder
fun load(galleryID: Int) { fun load(galleryID: Int) {
} }
fun download(galleryID: Int) = CoroutineScope(Dispatchers.IO).launch { 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.BiometricManager
import androidx.biometric.BiometricPrompt import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager
import com.andrognito.patternlockview.PatternLockView import com.andrognito.patternlockview.PatternLockView
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_lock.* 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.ui.fragment.PatternLockFragment
import xyz.quaver.pupil.util.Lock import xyz.quaver.pupil.util.Lock
import xyz.quaver.pupil.util.LockManager import xyz.quaver.pupil.util.LockManager
import xyz.quaver.pupil.util.Preferences
class LockActivity : AppCompatActivity() { class LockActivity : AppCompatActivity() {
@@ -195,7 +195,7 @@ class LockActivity : AppCompatActivity() {
} }
if ( if (
PreferenceManager.getDefaultSharedPreferences(this).getBoolean("lock_fingerprint", false) Preferences["lock_fingerprint"]
&& BiometricManager.from(this).canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS && BiometricManager.from(this).canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS
) { ) {
lock_fingerprint.apply { lock_fingerprint.apply {

View File

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

View File

@@ -43,12 +43,11 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import xyz.quaver.Code import xyz.quaver.Code
import xyz.quaver.pupil.Pupil
import xyz.quaver.pupil.R import xyz.quaver.pupil.R
import xyz.quaver.pupil.adapters.ReaderAdapter import xyz.quaver.pupil.adapters.ReaderAdapter
import xyz.quaver.pupil.favorites import xyz.quaver.pupil.favorites
import xyz.quaver.pupil.histories 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.Cache
import xyz.quaver.pupil.util.download.DownloadWorker import xyz.quaver.pupil.util.download.DownloadWorker
import java.util.* import java.util.*
@@ -103,7 +102,7 @@ class ReaderActivity : AppCompatActivity() {
} }
initView() initView()
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("cache_disable", false)) { if (Preferences["cache_disable"]) {
reader_download_progressbar.visibility = View.GONE reader_download_progressbar.visibility = View.GONE
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
val reader = Cache(this@ReaderActivity).getReader(galleryID) val reader = Cache(this@ReaderActivity).getReader(galleryID)
@@ -159,9 +158,7 @@ class ReaderActivity : AppCompatActivity() {
} }
override fun onResume() { override fun onResume() {
val preferences = PreferenceManager.getDefaultSharedPreferences(this) if (Preferences["security_mode"])
if (preferences.getBoolean("security_mode", false))
window.setFlags( window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE,
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.MenuItem
import android.view.WindowManager import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.preference.Preference
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.settings_activity.* import kotlinx.android.synthetic.main.settings_activity.*
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import net.rdrei.android.dirchooser.DirectoryChooserActivity import net.rdrei.android.dirchooser.DirectoryChooserActivity
import xyz.quaver.io.util.toFile
import xyz.quaver.pupil.Pupil import xyz.quaver.pupil.Pupil
import xyz.quaver.pupil.R import xyz.quaver.pupil.R
import xyz.quaver.pupil.favorites import xyz.quaver.pupil.favorites
@@ -60,9 +62,7 @@ class SettingsActivity : AppCompatActivity() {
} }
override fun onResume() { override fun onResume() {
val preferences = PreferenceManager.getDefaultSharedPreferences(this) if (Preferences["security_mode"])
if (preferences.getBoolean("security_mode", false))
window.setFlags( window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE) WindowManager.LayoutParams.FLAG_SECURE)
@@ -135,9 +135,7 @@ class SettingsActivity : AppCompatActivity() {
Snackbar.LENGTH_LONG Snackbar.LENGTH_LONG
).show() ).show()
else else
PreferenceManager.getDefaultSharedPreferences(this).edit() Preferences["dl_location"] = file.canonicalPath
.putString("dl_location", file.canonicalPath)
.apply()
} }
} }
} }
@@ -152,9 +150,7 @@ class SettingsActivity : AppCompatActivity() {
Snackbar.LENGTH_LONG Snackbar.LENGTH_LONG
).show() ).show()
else else
PreferenceManager.getDefaultSharedPreferences(this).edit() Preferences["dl_location"] = File(directory).canonicalPath
.putString("dl_location", File(directory).canonicalPath)
.apply()
} }
} }
else -> super.onActivityResult(requestCode, resultCode, data) else -> super.onActivityResult(requestCode, resultCode, data)

View File

@@ -28,11 +28,11 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import androidx.appcompat.app.AlertDialog 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.*
import kotlinx.android.synthetic.main.dialog_default_query.view.* import kotlinx.android.synthetic.main.dialog_default_query.view.*
import xyz.quaver.pupil.R import xyz.quaver.pupil.R
import xyz.quaver.pupil.types.Tags import xyz.quaver.pupil.types.Tags
import xyz.quaver.pupil.util.Preferences
class DefaultQueryDialog(context : Context) : AlertDialog(context) { class DefaultQueryDialog(context : Context) : AlertDialog(context) {
@@ -82,9 +82,8 @@ class DefaultQueryDialog(context : Context) : AlertDialog(context) {
@SuppressLint("InflateParams") @SuppressLint("InflateParams")
private fun build() : View { private fun build() : View {
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
val tags = Tags.parse( val tags = Tags.parse(
preferences.getString("default_query", "") ?: "" Preferences["default_query"]
) )
val view = LayoutInflater.from(context).inflate(R.layout.dialog_default_query, null) 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.appcompat.app.AlertDialog
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager
import kotlinx.android.synthetic.main.item_dl_location.view.* import kotlinx.android.synthetic.main.item_dl_location.view.*
import net.rdrei.android.dirchooser.DirectoryChooserActivity import net.rdrei.android.dirchooser.DirectoryChooserActivity
import net.rdrei.android.dirchooser.DirectoryChooserConfig import net.rdrei.android.dirchooser.DirectoryChooserConfig
@@ -42,8 +41,6 @@ import java.io.File
@SuppressLint("InflateParams") @SuppressLint("InflateParams")
class DownloadLocationDialog(val activity: Activity) : AlertDialog(activity) { class DownloadLocationDialog(val activity: Activity) : AlertDialog(activity) {
private val preference = PreferenceManager.getDefaultSharedPreferences(context)
private val buttons = mutableListOf<Pair<RadioButton, File?>>() private val buttons = mutableListOf<Pair<RadioButton, File?>>()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@@ -79,7 +76,7 @@ class DownloadLocationDialog(val activity: Activity) : AlertDialog(activity) {
pair.first.isChecked = false pair.first.isChecked = false
} }
button.performClick() button.performClick()
preference.edit().putString("dl_location", dir.canonicalPath).apply() Preferences["dl_location"] = dir.canonicalPath
} }
buttons.add(button to dir) buttons.add(button to dir)
}) })

View File

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

View File

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

View File

@@ -24,12 +24,12 @@ import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import androidx.preference.SwitchPreferenceCompat import androidx.preference.SwitchPreferenceCompat
import xyz.quaver.pupil.R import xyz.quaver.pupil.R
import xyz.quaver.pupil.ui.LockActivity import xyz.quaver.pupil.ui.LockActivity
import xyz.quaver.pupil.util.Lock import xyz.quaver.pupil.util.Lock
import xyz.quaver.pupil.util.LockManager import xyz.quaver.pupil.util.LockManager
import xyz.quaver.pupil.util.Preferences
class LockSettingsFragment : PreferenceFragmentCompat() { class LockSettingsFragment : PreferenceFragmentCompat() {
@@ -53,7 +53,7 @@ class LockSettingsFragment : PreferenceFragmentCompat() {
if (lockManager.isEmpty()) { if (lockManager.isEmpty()) {
(findPreference<Preference>("lock_fingerprint") as SwitchPreferenceCompat).isChecked = false (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 package xyz.quaver.pupil.ui.fragment
import android.Manifest
import android.content.* import android.content.*
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceCategory import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch 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.R
import xyz.quaver.pupil.histories import xyz.quaver.pupil.histories
import xyz.quaver.pupil.ui.LockActivity import xyz.quaver.pupil.ui.LockActivity
@@ -52,15 +42,12 @@ import java.io.BufferedReader
import java.io.File import java.io.File
import java.io.InputStreamReader import java.io.InputStreamReader
class SettingsFragment : class SettingsFragment :
PreferenceFragmentCompat(), PreferenceFragmentCompat(),
Preference.OnPreferenceClickListener, Preference.OnPreferenceClickListener,
Preference.OnPreferenceChangeListener, Preference.OnPreferenceChangeListener,
SharedPreferences.OnSharedPreferenceChangeListener { SharedPreferences.OnSharedPreferenceChangeListener {
lateinit var sharedPreference: SharedPreferences
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
@@ -160,7 +147,7 @@ class SettingsFragment :
"default_query" -> { "default_query" -> {
DefaultQueryDialog(requireContext()).apply { DefaultQueryDialog(requireContext()).apply {
onPositiveButtonClickListener = { newTags -> onPositiveButtonClickListener = { newTags ->
sharedPreferences.edit().putString("default_query", newTags.toString()).apply() Preferences["default_query"] = newTags.toString()
summary = newTags.toString() summary = newTags.toString()
} }
}.show() }.show()
@@ -182,7 +169,7 @@ class SettingsFragment :
} }
"user_id" -> { "user_id" -> {
(context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager).setPrimaryClip( (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() Toast.makeText(context, R.string.settings_user_id_toast, Toast.LENGTH_SHORT).show()
} }
@@ -219,7 +206,7 @@ class SettingsFragment :
when (key) { when (key) {
"proxy" -> { "proxy" -> {
summary = context?.let { getProxyInfo(it).type.name } summary = context?.let { getProxyInfo().type.name }
} }
"dl_location" -> { "dl_location" -> {
summary = context?.let { getDownloadDirectory(it).canonicalPath } summary = context?.let { getDownloadDirectory(it).canonicalPath }
@@ -231,8 +218,7 @@ class SettingsFragment :
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey) setPreferencesFromResource(R.xml.root_preferences, rootKey)
sharedPreference = PreferenceManager.getDefaultSharedPreferences(requireContext()) Preferences.registerOnSharedPreferenceChangeListener(this)
sharedPreference.registerOnSharedPreferenceChangeListener(this)
initPreferences() initPreferences()
} }
@@ -295,7 +281,7 @@ class SettingsFragment :
onPreferenceClickListener = this@SettingsFragment onPreferenceClickListener = this@SettingsFragment
} }
"default_query" -> { "default_query" -> {
summary = sharedPreference.getString("default_query", "") ?: "" summary = Preferences.get<String>("default_query")
onPreferenceClickListener = this@SettingsFragment onPreferenceClickListener = this@SettingsFragment
} }
@@ -320,7 +306,7 @@ class SettingsFragment :
onPreferenceClickListener = this@SettingsFragment onPreferenceClickListener = this@SettingsFragment
} }
"proxy" -> { "proxy" -> {
summary = getProxyInfo(requireContext()).type.name summary = getProxyInfo().type.name
onPreferenceClickListener = this@SettingsFragment onPreferenceClickListener = this@SettingsFragment
} }
@@ -334,7 +320,7 @@ class SettingsFragment :
onPreferenceClickListener = this@SettingsFragment onPreferenceClickListener = this@SettingsFragment
} }
"user_id" -> { "user_id" -> {
summary = sharedPreference.getString("user_id", "") summary = Preferences.get<String>("user_id")
onPreferenceClickListener = this@SettingsFragment 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.os.storage.StorageManager
import android.provider.DocumentsContract import android.provider.DocumentsContract
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.lang.reflect.Array import java.lang.reflect.Array
@@ -41,8 +40,8 @@ fun getCachedGallery(context: Context, galleryID: Int) =
} }
fun getDownloadDirectory(context: Context) = fun getDownloadDirectory(context: Context) =
PreferenceManager.getDefaultSharedPreferences(context).getString("dl_location", null).let { Preferences.get<String>("dl_location").let {
if (it != null && !it.startsWith("content")) if (it.isNotEmpty() && !it.startsWith("content"))
File(it) File(it)
else else
context.getExternalFilesDir(null)!! context.getExternalFilesDir(null)!!
@@ -124,94 +123,5 @@ fun getVolumePath(context: Context, volumeID: String?): String? {
}.getOrNull() }.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) = fun File.isParentOf(another: File) =
another.absolutePath.startsWith(this.absolutePath) another.absolutePath.startsWith(this.absolutePath)

View File

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

View File

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

View File

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