Limit cache max-age and action to clear cache manually

This commit is contained in:
Koitharu
2023-05-19 14:52:07 +03:00
parent 96c89a716e
commit e02899c3f2
7 changed files with 82 additions and 2 deletions

View File

@@ -23,6 +23,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import okhttp3.Cache
import okhttp3.CookieJar
import okhttp3.OkHttpClient
import org.koitharu.kotatsu.BuildConfig
@@ -90,14 +91,19 @@ interface AppModule {
@Provides
@Singleton
fun provideOkHttpClient(
fun provideHttpCache(
localStorageManager: LocalStorageManager,
): Cache = localStorageManager.createHttpCache()
@Provides
@Singleton
fun provideOkHttpClient(
cache: Cache,
commonHeadersInterceptor: CommonHeadersInterceptor,
mirrorSwitchInterceptor: MirrorSwitchInterceptor,
cookieJar: CookieJar,
settings: AppSettings,
): OkHttpClient {
val cache = localStorageManager.createHttpCache()
return OkHttpClient.Builder().apply {
connectTimeout(20, TimeUnit.SECONDS)
readTimeout(60, TimeUnit.SECONDS)
@@ -108,6 +114,7 @@ interface AppModule {
bypassSSLErrors()
}
cache(cache)
addNetworkInterceptor(CacheLimitInterceptor())
addInterceptor(GZipInterceptor())
addInterceptor(commonHeadersInterceptor)
addInterceptor(CloudFlareInterceptor())

View File

@@ -0,0 +1,26 @@
package org.koitharu.kotatsu.core.network
import okhttp3.CacheControl
import okhttp3.Interceptor
import okhttp3.Response
import java.util.concurrent.TimeUnit
class CacheLimitInterceptor : Interceptor {
private val defaultMaxAge = TimeUnit.HOURS.toSeconds(1)
private val defaultCacheControl = CacheControl.Builder()
.maxAge(defaultMaxAge.toInt(), TimeUnit.SECONDS)
.build()
.toString()
override fun intercept(chain: Interceptor.Chain): Response {
val response = chain.proceed(chain.request())
val responseCacheControl = CacheControl.parse(response.headers)
if (responseCacheControl.noStore || responseCacheControl.maxAgeSeconds <= defaultMaxAge) {
return response
}
return response.newBuilder()
.header(CommonHeaders.CACHE_CONTROL, defaultCacheControl)
.build()
}
}

View File

@@ -13,6 +13,7 @@ object CommonHeaders {
const val CONTENT_ENCODING = "Content-Encoding"
const val ACCEPT_ENCODING = "Accept-Encoding"
const val AUTHORIZATION = "Authorization"
const val CACHE_CONTROL = "Cache-Control"
val CACHE_CONTROL_NO_STORE: CacheControl
get() = CacheControl.Builder().noStore().build()

View File

@@ -345,6 +345,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
const val KEY_SOURCES_HIDDEN = "sources_hidden"
const val KEY_TRAFFIC_WARNING = "traffic_warning"
const val KEY_PAGES_CACHE_CLEAR = "pages_cache_clear"
const val KEY_HTTP_CACHE_CLEAR = "http_cache_clear"
const val KEY_COOKIES_CLEAR = "cookies_clear"
const val KEY_THUMBS_CACHE_CLEAR = "thumbs_cache_clear"
const val KEY_SEARCH_HISTORY_CLEAR = "search_history_clear"

View File

@@ -8,7 +8,10 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runInterruptible
import okhttp3.Cache
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar
import org.koitharu.kotatsu.core.os.ShortcutsUpdater
@@ -39,6 +42,9 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach
@Inject
lateinit var cookieJar: MutableCookieJar
@Inject
lateinit var cache: Cache
@Inject
lateinit var shortcutsUpdater: ShortcutsUpdater
@@ -52,6 +58,7 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach
super.onViewCreated(view, savedInstanceState)
findPreference<Preference>(AppSettings.KEY_PAGES_CACHE_CLEAR)?.bindSummaryToCacheSize(CacheDir.PAGES)
findPreference<Preference>(AppSettings.KEY_THUMBS_CACHE_CLEAR)?.bindSummaryToCacheSize(CacheDir.THUMBS)
findPreference<Preference>(AppSettings.KEY_HTTP_CACHE_CLEAR)?.bindSummaryToHttpCacheSize()
findPreference<Preference>(AppSettings.KEY_SEARCH_HISTORY_CLEAR)?.let { pref ->
viewLifecycleScope.launch {
lifecycle.awaitStateAtLeast(Lifecycle.State.RESUMED)
@@ -90,6 +97,11 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach
true
}
AppSettings.KEY_HTTP_CACHE_CLEAR -> {
clearHttpCache()
true
}
AppSettings.KEY_UPDATES_FEED_CLEAR -> {
viewLifecycleScope.launch {
trackerRepo.clearLogs()
@@ -131,6 +143,32 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach
summary = FileSize.BYTES.format(context, size)
}
private fun Preference.bindSummaryToHttpCacheSize() = viewLifecycleScope.launch {
val size = runInterruptible(Dispatchers.IO) { cache.size() }
summary = FileSize.BYTES.format(context, size)
}
private fun clearHttpCache() {
val preference = findPreference<Preference>(AppSettings.KEY_HTTP_CACHE_CLEAR) ?: return
val ctx = preference.context.applicationContext
viewLifecycleScope.launch {
try {
preference.isEnabled = false
val size = runInterruptible(Dispatchers.IO) {
cache.evictAll()
cache.size()
}
preference.summary = FileSize.BYTES.format(ctx, size)
} catch (e: CancellationException) {
throw e
} catch (e: Exception) {
preference.summary = e.getDisplayMessage(ctx.resources)
} finally {
preference.isEnabled = true
}
}
}
private fun clearSearchHistory(preference: Preference) {
MaterialAlertDialogBuilder(context ?: return)
.setTitle(R.string.clear_search_history)

View File

@@ -416,4 +416,5 @@
<string name="suggestions_enable_prompt">Do you want to receive personalized manga suggestions?</string>
<string name="translations">Translations</string>
<string name="web_view_unavailable">WebView not available: check if WebView provider is installed</string>
<string name="clear_network_cache">Clear network cache</string>
</resources>

View File

@@ -39,6 +39,12 @@
android:summary="@string/computing_"
android:title="@string/clear_pages_cache" />
<Preference
android:key="http_cache_clear"
android:persistent="false"
android:summary="@string/loading_"
android:title="@string/clear_network_cache" />
<Preference
android:key="cookies_clear"
android:persistent="false"