diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/alternatives/domain/AlternativesUseCase.kt b/app/src/main/kotlin/org/koitharu/kotatsu/alternatives/domain/AlternativesUseCase.kt index 85fc2278d..83ea79193 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/alternatives/domain/AlternativesUseCase.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/alternatives/domain/AlternativesUseCase.kt @@ -42,7 +42,7 @@ class AlternativesUseCase @Inject constructor( } }.getOrDefault(emptyList()) for (item in list) { - if (item != manga && item.matches(manga)) { + if (item.matches(manga)) { send(item) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ContentCache.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ContentCache.kt index 0e42ddde2..a48011836 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ContentCache.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ContentCache.kt @@ -20,6 +20,8 @@ interface ContentCache { fun putRelatedManga(source: MangaSource, url: String, related: SafeDeferred>) + fun clear(source: MangaSource) + data class Key( val source: MangaSource, val url: String, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt index aa9465c32..d669b7b76 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt @@ -7,10 +7,12 @@ class ExpiringLruCache( val maxSize: Int, private val lifetime: Long, private val timeUnit: TimeUnit, -) { +) : Iterable { private val cache = LruCache>(maxSize) + override fun iterator(): Iterator = cache.snapshot().keys.iterator() + operator fun get(key: ContentCache.Key): T? { val value = cache[key] ?: return null if (value.isExpired) { @@ -30,4 +32,8 @@ class ExpiringLruCache( fun trimToSize(size: Int) { cache.trimToSize(size) } + + fun remove(key: ContentCache.Key) { + cache.remove(key) + } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/MemoryContentCache.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/MemoryContentCache.kt index 986b61947..d99152d90 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/MemoryContentCache.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/MemoryContentCache.kt @@ -44,6 +44,12 @@ class MemoryContentCache(application: Application) : ContentCache, ComponentCall relatedMangaCache[ContentCache.Key(source, url)] = related } + override fun clear(source: MangaSource) { + clearCache(detailsCache, source) + clearCache(pagesCache, source) + clearCache(relatedMangaCache, source) + } + override fun onConfigurationChanged(newConfig: Configuration) = Unit override fun onLowMemory() = Unit @@ -67,4 +73,12 @@ class MemoryContentCache(application: Application) : ContentCache, ComponentCall else -> cache.trimToSize(cache.maxSize / 2) } } + + private fun clearCache(cache: ExpiringLruCache<*>, source: MangaSource) { + cache.forEach { key -> + if (key.source == source) { + cache.remove(key) + } + } + } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/StubContentCache.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/StubContentCache.kt index ade77ea97..e68d4d885 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/StubContentCache.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/StubContentCache.kt @@ -19,4 +19,6 @@ class StubContentCache : ContentCache { override suspend fun getRelatedManga(source: MangaSource, url: String): List? = null override fun putRelatedManga(source: MangaSource, url: String, related: SafeDeferred>) = Unit + + override fun clear(source: MangaSource) = Unit } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt index 9c87abc88..7abaad424 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt @@ -171,7 +171,11 @@ class RemoteMangaRepository( return getConfig().isSlowdownEnabled } - private fun getConfig() = parser.config as SourceSettings + fun invalidateCache() { + cache.clear(source) + } + + fun getConfig() = parser.config as SourceSettings private suspend fun asyncSafe(block: suspend CoroutineScope.() -> T): SafeDeferred { var dispatcher = currentCoroutineContext()[CoroutineDispatcher.Key] diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/SourceSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/SourceSettings.kt index a2b38fffe..482de71a9 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/SourceSettings.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/SourceSettings.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.core.prefs import android.content.Context +import android.content.SharedPreferences.OnSharedPreferenceChangeListener import androidx.core.content.edit import org.koitharu.kotatsu.core.util.ext.getEnumValue import org.koitharu.kotatsu.core.util.ext.ifNullOrEmpty @@ -10,9 +11,6 @@ import org.koitharu.kotatsu.parsers.config.MangaSourceConfig import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.SortOrder -private const val KEY_SORT_ORDER = "sort_order" -private const val KEY_SLOWDOWN = "slowdown" - class SourceSettings(context: Context, source: MangaSource) : MangaSourceConfig { private val prefs = context.getSharedPreferences(source.name, Context.MODE_PRIVATE) @@ -42,4 +40,18 @@ class SourceSettings(context: Context, source: MangaSource) : MangaSourceConfig is ConfigKey.SplitByTranslations -> putBoolean(key.key, value as Boolean) } } + + fun subscribe(listener: OnSharedPreferenceChangeListener) { + prefs.registerOnSharedPreferenceChangeListener(listener) + } + + fun unsubscribe(listener: OnSharedPreferenceChangeListener) { + prefs.unregisterOnSharedPreferenceChangeListener(listener) + } + + companion object { + + const val KEY_SORT_ORDER = "sort_order" + const val KEY_SLOWDOWN = "slowdown" + } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourceSettingsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourceSettingsViewModel.kt index 687a6d92e..484547b76 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourceSettingsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/settings/sources/SourceSettingsViewModel.kt @@ -1,5 +1,6 @@ package org.koitharu.kotatsu.settings.sources +import android.content.SharedPreferences import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers @@ -10,11 +11,13 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository +import org.koitharu.kotatsu.core.prefs.SourceSettings import org.koitharu.kotatsu.core.ui.BaseViewModel import org.koitharu.kotatsu.core.ui.util.ReversibleAction import org.koitharu.kotatsu.core.util.ext.MutableEventFlow import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.core.util.ext.require +import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.exception.AuthRequiredException import org.koitharu.kotatsu.parsers.model.MangaSource import javax.inject.Inject @@ -24,7 +27,7 @@ class SourceSettingsViewModel @Inject constructor( savedStateHandle: SavedStateHandle, mangaRepositoryFactory: MangaRepository.Factory, private val cookieJar: MutableCookieJar, -) : BaseViewModel() { +) : BaseViewModel(), SharedPreferences.OnSharedPreferenceChangeListener { val source = savedStateHandle.require(SourceSettingsFragment.EXTRA_SOURCE) val repository = mangaRepositoryFactory.create(source) as RemoteMangaRepository @@ -34,9 +37,21 @@ class SourceSettingsViewModel @Inject constructor( private var usernameLoadJob: Job? = null init { + repository.getConfig().subscribe(this) loadUsername() } + override fun onCleared() { + repository.getConfig().unsubscribe(this) + super.onCleared() + } + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + if (key != SourceSettings.KEY_SLOWDOWN && key != SourceSettings.KEY_SORT_ORDER) { + repository.invalidateCache() + } + } + fun onResume() { if (usernameLoadJob?.isActive != true) { loadUsername()