Fix some StrictMode warnings
This commit is contained in:
@@ -3,6 +3,7 @@ package org.koitharu.kotatsu.core.network
|
||||
import okhttp3.CookieJar
|
||||
import okhttp3.OkHttpClient
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.core.qualifier.named
|
||||
import org.koin.dsl.module
|
||||
import org.koitharu.kotatsu.core.network.cookies.PersistentCookieJar
|
||||
import org.koitharu.kotatsu.core.network.cookies.cache.SetCookieCache
|
||||
@@ -18,13 +19,14 @@ val networkModule
|
||||
SharedPrefsCookiePersistor(androidContext())
|
||||
)
|
||||
}
|
||||
single(named(CacheUtils.QUALIFIER_HTTP)) { CacheUtils.createHttpCache(androidContext()) }
|
||||
single {
|
||||
OkHttpClient.Builder().apply {
|
||||
connectTimeout(20, TimeUnit.SECONDS)
|
||||
readTimeout(60, TimeUnit.SECONDS)
|
||||
writeTimeout(20, TimeUnit.SECONDS)
|
||||
cookieJar(get())
|
||||
cache(CacheUtils.createHttpCache(androidContext()))
|
||||
cache(get(named(CacheUtils.QUALIFIER_HTTP)))
|
||||
addInterceptor(UserAgentInterceptor())
|
||||
addInterceptor(CloudFlareInterceptor())
|
||||
}.build()
|
||||
|
||||
@@ -20,24 +20,29 @@ import okhttp3.HttpUrl
|
||||
import org.koitharu.kotatsu.core.network.cookies.cache.CookieCache
|
||||
import org.koitharu.kotatsu.core.network.cookies.persistence.CookiePersistor
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
class PersistentCookieJar(
|
||||
private val cache: CookieCache,
|
||||
private val persistor: CookiePersistor
|
||||
) : ClearableCookieJar {
|
||||
|
||||
init {
|
||||
cache.addAll(persistor.loadAll())
|
||||
}
|
||||
private var isLoaded = AtomicBoolean(false)
|
||||
|
||||
@Synchronized
|
||||
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
|
||||
if (isLoaded.compareAndSet(false, true)) {
|
||||
cache.addAll(persistor.loadAll())
|
||||
}
|
||||
cache.addAll(cookies)
|
||||
persistor.saveAll(filterPersistentCookies(cookies))
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun loadForRequest(url: HttpUrl): List<Cookie> {
|
||||
if (isLoaded.compareAndSet(false, true)) {
|
||||
cache.addAll(persistor.loadAll())
|
||||
}
|
||||
val cookiesToRemove: MutableList<Cookie> = ArrayList()
|
||||
val validCookies: MutableList<Cookie> = ArrayList()
|
||||
val it = cache.iterator()
|
||||
|
||||
@@ -15,22 +15,15 @@
|
||||
*/
|
||||
package org.koitharu.kotatsu.core.network.cookies.persistence
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import okhttp3.Cookie
|
||||
import java.util.*
|
||||
|
||||
@SuppressLint("CommitPrefEdits")
|
||||
class SharedPrefsCookiePersistor(private val sharedPreferences: SharedPreferences) :
|
||||
CookiePersistor {
|
||||
class SharedPrefsCookiePersistor(context: Context) : CookiePersistor {
|
||||
|
||||
constructor(context: Context) : this(
|
||||
context.getSharedPreferences(
|
||||
"cookies",
|
||||
Context.MODE_PRIVATE
|
||||
)
|
||||
)
|
||||
private val sharedPreferences by lazy {
|
||||
context.getSharedPreferences("cookies", Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
override fun loadAll(): List<Cookie> {
|
||||
val cookies: MutableList<Cookie> = ArrayList(sharedPreferences.all.size)
|
||||
|
||||
@@ -16,6 +16,7 @@ import okhttp3.Request
|
||||
import okio.IOException
|
||||
import org.koin.android.ext.android.get
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.core.context.GlobalContext
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.local.PagesCache
|
||||
@@ -231,7 +232,7 @@ class DownloadService : BaseService() {
|
||||
|
||||
private fun confirmDataTransfer(context: Context, callback: () -> Unit) {
|
||||
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
val settings = AppSettings(context)
|
||||
val settings = GlobalContext.get().get<AppSettings>()
|
||||
if (cm.isActiveNetworkMetered && settings.isTrafficWarningEnabled) {
|
||||
CheckBoxAlertDialog.Builder(context)
|
||||
.setTitle(R.string.warning)
|
||||
|
||||
@@ -12,6 +12,10 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.cursoradapter.widget.CursorAdapter
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.R
|
||||
|
||||
@@ -50,27 +54,35 @@ class MangaSuggestionsProvider : SearchRecentSuggestionsProvider() {
|
||||
private const val AUTHORITY = "${BuildConfig.APPLICATION_ID}.MangaSuggestionsProvider"
|
||||
private const val MODE = DATABASE_MODE_QUERIES
|
||||
|
||||
@JvmStatic
|
||||
private val uri = Uri.Builder()
|
||||
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(AUTHORITY)
|
||||
.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY)
|
||||
.build()
|
||||
|
||||
@JvmStatic
|
||||
private val projection = arrayOf("_id", SearchManager.SUGGEST_COLUMN_QUERY)
|
||||
|
||||
@JvmStatic
|
||||
fun saveQuery(context: Context, query: String) {
|
||||
SearchRecentSuggestions(
|
||||
context,
|
||||
AUTHORITY,
|
||||
MODE
|
||||
).saveRecentQuery(query, null)
|
||||
fun saveQueryAsync(context: Context, query: String) {
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
saveQuery(context, query)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun clearHistory(context: Context) {
|
||||
fun saveQuery(context: Context, query: String) {
|
||||
runCatching {
|
||||
SearchRecentSuggestions(
|
||||
context,
|
||||
AUTHORITY,
|
||||
MODE
|
||||
).saveRecentQuery(query, null)
|
||||
}.onFailure {
|
||||
if (BuildConfig.DEBUG) {
|
||||
it.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun clearHistory(context: Context) = withContext(Dispatchers.IO) {
|
||||
SearchRecentSuggestions(
|
||||
context,
|
||||
AUTHORITY,
|
||||
@@ -78,15 +90,15 @@ class MangaSuggestionsProvider : SearchRecentSuggestionsProvider() {
|
||||
).clearHistory()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getItemsCount(context: Context) = getCursor(context)?.use { it.count } ?: 0
|
||||
suspend fun getItemsCount(context: Context) = withContext(Dispatchers.IO) {
|
||||
getCursor(context)?.use { it.count } ?: 0
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
private fun getCursor(context: Context): Cursor? {
|
||||
return context.contentResolver?.query(uri, projection, null, arrayOf(""), null)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Deprecated("Need async implementation")
|
||||
fun getSuggestionAdapter(context: Context): CursorAdapter? = getCursor(
|
||||
context
|
||||
)?.let { cursor ->
|
||||
@@ -102,6 +114,5 @@ class MangaSuggestionsProvider : SearchRecentSuggestionsProvider() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ class SearchActivity : BaseActivity(), SearchView.OnQueryTextListener {
|
||||
.replace(R.id.container, SearchFragment.newInstance(source, query))
|
||||
.commit()
|
||||
searchView.clearFocus()
|
||||
MangaSuggestionsProvider.saveQuery(this, query)
|
||||
MangaSuggestionsProvider.saveQueryAsync(applicationContext, query)
|
||||
true
|
||||
} else false
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ object SearchHelper {
|
||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
||||
return if (!query.isNullOrBlank()) {
|
||||
context.startActivity(GlobalSearchActivity.newIntent(context, query.trim()))
|
||||
MangaSuggestionsProvider.saveQuery(context, query)
|
||||
MangaSuggestionsProvider.saveQueryAsync(context.applicationContext, query)
|
||||
true
|
||||
} else false
|
||||
}
|
||||
|
||||
@@ -45,14 +45,18 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach
|
||||
pref.summary = FileSizeUtils.formatBytes(pref.context, size)
|
||||
}
|
||||
}
|
||||
findPreference<Preference>(AppSettings.KEY_SEARCH_HISTORY_CLEAR)?.let { p ->
|
||||
val items = MangaSuggestionsProvider.getItemsCount(p.context)
|
||||
p.summary = p.context.resources.getQuantityString(R.plurals.items, items, items)
|
||||
findPreference<Preference>(AppSettings.KEY_SEARCH_HISTORY_CLEAR)?.let { pref ->
|
||||
viewLifecycleScope.launchWhenResumed {
|
||||
val items = MangaSuggestionsProvider.getItemsCount(pref.context)
|
||||
pref.summary =
|
||||
pref.context.resources.getQuantityString(R.plurals.items, items, items)
|
||||
}
|
||||
}
|
||||
findPreference<Preference>(AppSettings.KEY_UPDATES_FEED_CLEAR)?.let { p ->
|
||||
findPreference<Preference>(AppSettings.KEY_UPDATES_FEED_CLEAR)?.let { pref ->
|
||||
viewLifecycleScope.launchWhenResumed {
|
||||
val items = trackerRepo.count()
|
||||
p.summary = p.context.resources.getQuantityString(R.plurals.items, items, items)
|
||||
pref.summary =
|
||||
pref.context.resources.getQuantityString(R.plurals.items, items, items)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,14 +72,16 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach
|
||||
true
|
||||
}
|
||||
AppSettings.KEY_SEARCH_HISTORY_CLEAR -> {
|
||||
MangaSuggestionsProvider.clearHistory(preference.context)
|
||||
preference.summary = preference.context.resources
|
||||
.getQuantityString(R.plurals.items, 0, 0)
|
||||
Snackbar.make(
|
||||
view ?: return true,
|
||||
R.string.search_history_cleared,
|
||||
Snackbar.LENGTH_SHORT
|
||||
).show()
|
||||
viewLifecycleScope.launch {
|
||||
MangaSuggestionsProvider.clearHistory(preference.context)
|
||||
preference.summary = preference.context.resources
|
||||
.getQuantityString(R.plurals.items, 0, 0)
|
||||
Snackbar.make(
|
||||
view ?: return@launch,
|
||||
R.string.search_history_cleared,
|
||||
Snackbar.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
true
|
||||
}
|
||||
AppSettings.KEY_UPDATES_FEED_CLEAR -> {
|
||||
|
||||
@@ -12,6 +12,8 @@ import java.io.File
|
||||
|
||||
object CacheUtils {
|
||||
|
||||
const val QUALIFIER_HTTP = "cache_http"
|
||||
|
||||
val CONTROL_DISABLED = CacheControl.Builder()
|
||||
.noStore()
|
||||
.build()
|
||||
@@ -30,6 +32,7 @@ object CacheUtils {
|
||||
.map { it.sub(name) }
|
||||
.forEach { it.deleteRecursively() }
|
||||
|
||||
// FIXME need async implementation
|
||||
fun createHttpCache(context: Context): Cache {
|
||||
val directory = (context.externalCacheDir ?: context.cacheDir).sub("http")
|
||||
directory.mkdirs()
|
||||
|
||||
@@ -4,16 +4,18 @@ import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.get
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.utils.ext.measureWidth
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object UiUtils {
|
||||
object UiUtils : KoinComponent {
|
||||
|
||||
fun resolveGridSpanCount(context: Context, width: Int = 0): Int {
|
||||
val scaleFactor = AppSettings(context).gridSize / 100f
|
||||
val scaleFactor = get<AppSettings>().gridSize / 100f
|
||||
val cellWidth = context.resources.getDimension(R.dimen.preferred_grid_width) * scaleFactor
|
||||
val screenWidth = (if (width <= 0) {
|
||||
context.resources.displayMetrics.widthPixels
|
||||
|
||||
Reference in New Issue
Block a user