Fixes and improvements batch
This commit is contained in:
@@ -18,7 +18,6 @@ import org.koitharu.kotatsu.core.util.ext.configureForParser
|
||||
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
|
||||
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
|
||||
import javax.inject.Inject
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@AndroidEntryPoint
|
||||
class BrowserActivity : BaseBrowserActivity() {
|
||||
@@ -28,10 +27,7 @@ class BrowserActivity : BaseBrowserActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
|
||||
}
|
||||
setDisplayHomeAsUp(true, true)
|
||||
val mangaSource = MangaSource(intent?.getStringExtra(AppRouter.KEY_SOURCE))
|
||||
val repository = mangaRepositoryFactory.create(mangaSource) as? ParserMangaRepository
|
||||
val userAgent = repository?.getRequestHeaders()?.get(CommonHeaders.USER_AGENT)
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.koitharu.kotatsu.core.util.ext.configureForParser
|
||||
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
|
||||
import org.koitharu.kotatsu.parsers.network.CloudFlareHelper
|
||||
import javax.inject.Inject
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@AndroidEntryPoint
|
||||
class CloudFlareActivity : BaseBrowserActivity(), CloudFlareCallback {
|
||||
@@ -40,10 +39,7 @@ class CloudFlareActivity : BaseBrowserActivity(), CloudFlareCallback {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
|
||||
}
|
||||
setDisplayHomeAsUp(true, true)
|
||||
val url = intent?.dataString
|
||||
if (url.isNullOrEmpty()) {
|
||||
finishAfterTransition()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.koitharu.kotatsu.core.cache
|
||||
|
||||
import androidx.collection.LruCache
|
||||
import androidx.collection.SieveCache
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import java.util.concurrent.TimeUnit
|
||||
import org.koitharu.kotatsu.core.cache.MemoryContentCache.Key as CacheKey
|
||||
|
||||
@@ -8,11 +9,9 @@ class ExpiringLruCache<T>(
|
||||
val maxSize: Int,
|
||||
private val lifetime: Long,
|
||||
private val timeUnit: TimeUnit,
|
||||
) : Iterable<CacheKey> {
|
||||
) {
|
||||
|
||||
private val cache = LruCache<CacheKey, ExpiringValue<T>>(maxSize)
|
||||
|
||||
override fun iterator(): Iterator<CacheKey> = cache.snapshot().keys.iterator()
|
||||
private val cache = SieveCache<CacheKey, ExpiringValue<T>>(maxSize)
|
||||
|
||||
operator fun get(key: CacheKey): T? {
|
||||
val value = cache[key] ?: return null
|
||||
@@ -37,4 +36,8 @@ class ExpiringLruCache<T>(
|
||||
fun remove(key: CacheKey) {
|
||||
cache.remove(key)
|
||||
}
|
||||
|
||||
fun removeAll(source: MangaSource) {
|
||||
cache.removeIf { key, _ -> key.source == source }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,11 +81,7 @@ class MemoryContentCache @Inject constructor(application: Application) : Compone
|
||||
}
|
||||
|
||||
private fun clearCache(cache: ExpiringLruCache<*>, source: MangaSource) {
|
||||
cache.forEach { key ->
|
||||
if (key.source == source) {
|
||||
cache.remove(key)
|
||||
}
|
||||
}
|
||||
cache.removeAll(source)
|
||||
}
|
||||
|
||||
data class Key(
|
||||
|
||||
@@ -749,6 +749,12 @@ class AppRouter private constructor(
|
||||
.putExtra(KEY_SOURCE, source.name)
|
||||
}
|
||||
|
||||
fun isShareSupported(manga: Manga): Boolean = when {
|
||||
manga.isBroken -> false
|
||||
manga.isLocal -> manga.url.toUri().toFileOrNull() != null
|
||||
else -> true
|
||||
}
|
||||
|
||||
const val KEY_DATA = "data"
|
||||
const val KEY_ENTRIES = "entries"
|
||||
const val KEY_ERROR = "error"
|
||||
|
||||
@@ -65,7 +65,7 @@ class CommonHeadersInterceptor @Inject constructor(
|
||||
private fun Interceptor.interceptSafe(chain: Chain): Response = runCatchingCancellable {
|
||||
intercept(chain)
|
||||
}.getOrElse { e ->
|
||||
if (e is IOException) {
|
||||
if (e is IOException || e is Error) {
|
||||
throw e
|
||||
} else {
|
||||
// only IOException can be safely thrown from an Interceptor
|
||||
|
||||
@@ -133,7 +133,7 @@ class AppShortcutManager @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun buildShortcutInfo(manga: Manga): ShortcutInfoCompat {
|
||||
private suspend fun buildShortcutInfo(manga: Manga): ShortcutInfoCompat = withContext(Dispatchers.Default) {
|
||||
val icon = runCatchingCancellable {
|
||||
coil.execute(
|
||||
ImageRequest.Builder(context)
|
||||
@@ -149,7 +149,7 @@ class AppShortcutManager @Inject constructor(
|
||||
onFailure = { IconCompat.createWithResource(context, R.drawable.ic_shortcut_default) },
|
||||
)
|
||||
mangaRepository.storeManga(manga)
|
||||
return ShortcutInfoCompat.Builder(context, manga.id.toString())
|
||||
ShortcutInfoCompat.Builder(context, manga.id.toString())
|
||||
.setShortLabel(manga.title)
|
||||
.setLongLabel(manga.title)
|
||||
.setIcon(icon)
|
||||
@@ -159,8 +159,7 @@ class AppShortcutManager @Inject constructor(
|
||||
.mangaId(manga.id)
|
||||
.build()
|
||||
.intent,
|
||||
)
|
||||
.build()
|
||||
).build()
|
||||
}
|
||||
|
||||
private suspend fun buildShortcutInfo(source: MangaSource): ShortcutInfoCompat = withContext(Dispatchers.Default) {
|
||||
|
||||
@@ -18,7 +18,6 @@ import org.koitharu.kotatsu.parsers.model.MangaListFilterOptions
|
||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
|
||||
import org.koitharu.kotatsu.parsers.util.suspendlazy.suspendLazy
|
||||
|
||||
@@ -58,13 +57,7 @@ class ParserMangaRepository(
|
||||
val domains: Array<out String>
|
||||
get() = parser.configKeyDomain.presetValues
|
||||
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
return if (parser is Interceptor) {
|
||||
parser.intercept(chain)
|
||||
} else {
|
||||
chain.proceed(chain.request())
|
||||
}
|
||||
}
|
||||
override fun intercept(chain: Interceptor.Chain): Response = parser.intercept(chain)
|
||||
|
||||
override suspend fun getList(offset: Int, order: SortOrder?, filter: MangaListFilter?): List<Manga> {
|
||||
return mirrorSwitchInterceptor.withMirrorSwitching {
|
||||
@@ -96,7 +89,7 @@ class ParserMangaRepository(
|
||||
parser.getDetails(manga)
|
||||
}
|
||||
|
||||
fun getAuthProvider(): MangaParserAuthProvider? = parser as? MangaParserAuthProvider
|
||||
fun getAuthProvider(): MangaParserAuthProvider? = parser.authorizationProvider
|
||||
|
||||
fun getRequestHeaders() = parser.getRequestHeaders()
|
||||
|
||||
|
||||
@@ -741,6 +741,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
||||
const val KEY_BACKUP_TG_TEST = "backup_periodic_tg_test"
|
||||
const val KEY_CLEAR_MANGA_DATA = "manga_data_clear"
|
||||
const val KEY_STORAGE_USAGE = "storage_usage"
|
||||
const val KEY_WEBVIEW_CLEAR = "webview_clear"
|
||||
|
||||
// old keys are for migration only
|
||||
private const val KEY_IMAGES_PROXY_OLD = "images_proxy"
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.koitharu.kotatsu.core.nav.AppRouter
|
||||
import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate
|
||||
import org.koitharu.kotatsu.core.util.ext.isWebViewUnavailable
|
||||
import org.koitharu.kotatsu.main.ui.protect.ScreenshotPolicyHelper
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
abstract class BaseActivity<B : ViewBinding> :
|
||||
AppCompatActivity(),
|
||||
@@ -98,6 +99,15 @@ abstract class BaseActivity<B : ViewBinding> :
|
||||
toolbar?.let(this::setSupportActionBar)
|
||||
}
|
||||
|
||||
protected fun setDisplayHomeAsUp(isEnabled: Boolean, showUpAsClose: Boolean) {
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(isEnabled)
|
||||
if (showUpAsClose) {
|
||||
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
val fm = supportFragmentManager
|
||||
if (fm.isStateSaved) {
|
||||
|
||||
@@ -30,7 +30,7 @@ abstract class FragmentContainerActivity(private val fragmentClass: Class<out Fr
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityContainerBinding.inflate(layoutInflater))
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayHomeAsUp(true, false)
|
||||
val fm = supportFragmentManager
|
||||
if (fm.findFragmentById(R.id.container) == null) {
|
||||
fm.commit {
|
||||
|
||||
@@ -131,10 +131,8 @@ class DetailsActivity :
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityDetailsBinding.inflate(layoutInflater))
|
||||
infoBinding = LayoutDetailsTableBinding.bind(viewBinding.root)
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowTitleEnabled(false)
|
||||
}
|
||||
setDisplayHomeAsUp(true, false)
|
||||
supportActionBar?.setDisplayShowTitleEnabled(false)
|
||||
viewBinding.chipFavorite.setOnClickListener(this)
|
||||
infoBinding.textViewLocal.setOnClickListener(this)
|
||||
infoBinding.textViewAuthor.setOnClickListener(this)
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.LocalMangaSource
|
||||
import org.koitharu.kotatsu.core.nav.AppRouter
|
||||
import org.koitharu.kotatsu.core.nav.router
|
||||
import org.koitharu.kotatsu.core.os.AppShortcutManager
|
||||
import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
|
||||
@@ -23,12 +24,16 @@ class DetailsMenuProvider(
|
||||
private val appShortcutManager: AppShortcutManager,
|
||||
) : MenuProvider {
|
||||
|
||||
private val router: AppRouter
|
||||
get() = activity.router
|
||||
|
||||
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||
menuInflater.inflate(R.menu.opt_details, menu)
|
||||
}
|
||||
|
||||
override fun onPrepareMenu(menu: Menu) {
|
||||
val manga = viewModel.manga.value
|
||||
menu.findItem(R.id.action_share).isVisible = manga != null && AppRouter.isShareSupported(manga)
|
||||
menu.findItem(R.id.action_save).isVisible = manga?.source != null && manga.source != LocalMangaSource
|
||||
menu.findItem(R.id.action_delete).isVisible = manga?.source == LocalMangaSource
|
||||
menu.findItem(R.id.action_browser).isVisible = manga?.source != LocalMangaSource
|
||||
@@ -43,7 +48,7 @@ class DetailsMenuProvider(
|
||||
val manga = viewModel.getMangaOrNull() ?: return false
|
||||
when (menuItem.itemId) {
|
||||
R.id.action_share -> {
|
||||
activity.router.showShareDialog(manga)
|
||||
router.showShareDialog(manga)
|
||||
}
|
||||
|
||||
R.id.action_delete -> {
|
||||
@@ -56,31 +61,31 @@ class DetailsMenuProvider(
|
||||
}
|
||||
|
||||
R.id.action_save -> {
|
||||
activity.router.showDownloadDialog(manga, snackbarHost)
|
||||
router.showDownloadDialog(manga, snackbarHost)
|
||||
}
|
||||
|
||||
R.id.action_browser -> {
|
||||
activity.router.openBrowser(url = manga.publicUrl, source = manga.source, title = manga.title)
|
||||
router.openBrowser(url = manga.publicUrl, source = manga.source, title = manga.title)
|
||||
}
|
||||
|
||||
R.id.action_online -> {
|
||||
activity.router.openDetails(manga)
|
||||
router.openDetails(manga)
|
||||
}
|
||||
|
||||
R.id.action_related -> {
|
||||
activity.router.openSearch(manga.title)
|
||||
router.openSearch(manga.title)
|
||||
}
|
||||
|
||||
R.id.action_alternatives -> {
|
||||
activity.router.openAlternatives(manga)
|
||||
router.openAlternatives(manga)
|
||||
}
|
||||
|
||||
R.id.action_stats -> {
|
||||
activity.router.showStatisticSheet(manga)
|
||||
router.showStatisticSheet(manga)
|
||||
}
|
||||
|
||||
R.id.action_scrobbling -> {
|
||||
activity.router.showScrobblingSelectorSheet(manga, null)
|
||||
router.showScrobblingSelectorSheet(manga, null)
|
||||
}
|
||||
|
||||
R.id.action_shortcut -> {
|
||||
|
||||
@@ -43,7 +43,7 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityDownloadsBinding.inflate(layoutInflater))
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayHomeAsUp(true, false)
|
||||
val downloadsAdapter = DownloadsAdapter(this, coil, this)
|
||||
val decoration = TypedListSpacingDecoration(this, false)
|
||||
selectionController = ListSelectionController(
|
||||
|
||||
@@ -49,7 +49,7 @@ class FavouriteCategoriesActivity :
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityCategoriesBinding.inflate(layoutInflater))
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayHomeAsUp(true, false)
|
||||
adapter = CategoriesAdapter(coil, this, this, this)
|
||||
selectionController = ListSelectionController(
|
||||
appCompatDelegate = delegate,
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.koitharu.kotatsu.core.util.ext.sortedByOrdinal
|
||||
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
|
||||
import org.koitharu.kotatsu.databinding.ActivityCategoryEditBinding
|
||||
import org.koitharu.kotatsu.list.domain.ListSortOrder
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@AndroidEntryPoint
|
||||
class FavouritesCategoryEditActivity :
|
||||
@@ -41,10 +40,7 @@ class FavouritesCategoryEditActivity :
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityCategoryEditBinding.inflate(layoutInflater))
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
|
||||
}
|
||||
setDisplayHomeAsUp(true, true)
|
||||
initSortSpinner()
|
||||
viewBinding.buttonDone.setOnClickListener(this)
|
||||
viewBinding.editName.addTextChangedListener(this)
|
||||
|
||||
@@ -6,7 +6,7 @@ import android.graphics.Color
|
||||
import android.graphics.Point
|
||||
import android.graphics.Rect
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.collection.LruCache
|
||||
import androidx.collection.SieveCache
|
||||
import androidx.core.graphics.alpha
|
||||
import androidx.core.graphics.blue
|
||||
import androidx.core.graphics.get
|
||||
@@ -29,7 +29,7 @@ import kotlin.math.abs
|
||||
class EdgeDetector(private val context: Context) {
|
||||
|
||||
private val mutex = Mutex()
|
||||
private val cache = LruCache<ImageSource, Rect>(CACHE_SIZE)
|
||||
private val cache = SieveCache<ImageSource, Rect>(CACHE_SIZE)
|
||||
|
||||
suspend fun getBounds(imageSource: ImageSource): Rect? {
|
||||
cache[imageSource]?.let { rect ->
|
||||
|
||||
@@ -105,7 +105,7 @@ class ReaderActivity :
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityReaderBinding.inflate(layoutInflater))
|
||||
readerManager = ReaderManager(supportFragmentManager, viewBinding.container, settings)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayHomeAsUp(true, false)
|
||||
touchHelper = TapGridDispatcher(this, this)
|
||||
scrollTimer = scrollTimerFactory.create(this, this)
|
||||
pageSaveHelper = pageSaveHelperFactory.create(this)
|
||||
|
||||
@@ -35,7 +35,6 @@ import org.koitharu.kotatsu.parsers.util.format
|
||||
import org.koitharu.kotatsu.parsers.util.nullIfEmpty
|
||||
import org.koitharu.kotatsu.reader.domain.ReaderColorFilter
|
||||
import javax.inject.Inject
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@AndroidEntryPoint
|
||||
class ColorFilterConfigActivity :
|
||||
@@ -51,10 +50,7 @@ class ColorFilterConfigActivity :
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityColorFilterBinding.inflate(layoutInflater))
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
|
||||
}
|
||||
setDisplayHomeAsUp(true, true)
|
||||
viewBinding.sliderBrightness.addOnChangeListener(this)
|
||||
viewBinding.sliderContrast.addOnChangeListener(this)
|
||||
val formatter = PercentLabelFormatter(resources)
|
||||
|
||||
@@ -46,7 +46,7 @@ class ScrobblerConfigActivity : BaseActivity<ActivityScrobblerConfigBinding>(),
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityScrobblerConfigBinding.inflate(layoutInflater))
|
||||
setTitle(viewModel.titleResId)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayHomeAsUp(true, false)
|
||||
|
||||
val listAdapter = ScrobblingMangaAdapter(this, coil, this)
|
||||
with(viewBinding.recyclerView) {
|
||||
|
||||
@@ -76,7 +76,7 @@ class MangaListActivity :
|
||||
val filter = intent.getParcelableExtraCompat<ParcelableMangaListFilter>(AppRouter.KEY_FILTER)?.filter
|
||||
val sortOrder = intent.getSerializableExtraCompat<SortOrder>(AppRouter.KEY_SORT_ORDER)
|
||||
source = MangaSource(intent.getStringExtra(AppRouter.KEY_SOURCE))
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayHomeAsUp(true, false)
|
||||
if (viewBinding.containerFilterHeader != null) {
|
||||
viewBinding.appbar.addOnOffsetChangedListener(this)
|
||||
}
|
||||
|
||||
@@ -96,10 +96,8 @@ class SearchActivity :
|
||||
viewBinding.recyclerView.setHasFixedSize(true)
|
||||
viewBinding.recyclerView.addItemDecoration(TypedListSpacingDecoration(this, true))
|
||||
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setSubtitle(R.string.search_results)
|
||||
}
|
||||
setDisplayHomeAsUp(true, false)
|
||||
supportActionBar?.setSubtitle(R.string.search_results)
|
||||
|
||||
addMenuProvider(SearchKindMenuProvider(this, viewModel.query, viewModel.kind))
|
||||
|
||||
|
||||
@@ -122,8 +122,9 @@ class ProxySettingsFragment : BasePreferenceFragment(R.string.proxy),
|
||||
.get()
|
||||
.url("http://neverssl.com")
|
||||
.build()
|
||||
val response = okHttpClient.newCall(request).await()
|
||||
check(response.isSuccessful) { response.message }
|
||||
okHttpClient.newCall(request).await().use { response ->
|
||||
check(response.isSuccessful) { response.message }
|
||||
}
|
||||
}
|
||||
showTestResult(null)
|
||||
} catch (e: CancellationException) {
|
||||
|
||||
@@ -57,7 +57,7 @@ class SettingsActivity :
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivitySettingsBinding.inflate(layoutInflater))
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayHomeAsUp(true, false)
|
||||
val fm = supportFragmentManager
|
||||
val currentFragment = fm.findFragmentById(R.id.container)
|
||||
if (currentFragment == null || (isMasterDetails && currentFragment is RootSettingsFragment)) {
|
||||
|
||||
@@ -40,7 +40,7 @@ class ReaderTapGridConfigActivity : BaseActivity<ActivityReaderTapActionsBinding
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityReaderTapActionsBinding.inflate(layoutInflater))
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayHomeAsUp(true, false)
|
||||
controls[TapGridArea.TOP_LEFT] = viewBinding.textViewTopLeft
|
||||
controls[TapGridArea.TOP_CENTER] = viewBinding.textViewTopCenter
|
||||
controls[TapGridArea.TOP_RIGHT] = viewBinding.textViewTopRight
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.settings.sources.SourceSettingsFragment.Companion.EXTRA_SOURCE
|
||||
import javax.inject.Inject
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@AndroidEntryPoint
|
||||
class SourceAuthActivity : BaseBrowserActivity(), BrowserCallback {
|
||||
@@ -57,10 +56,7 @@ class SourceAuthActivity : BaseBrowserActivity(), BrowserCallback {
|
||||
finishAfterTransition()
|
||||
return
|
||||
}
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
|
||||
}
|
||||
setDisplayHomeAsUp(true, true)
|
||||
viewBinding.webView.configureForParser(repository.getRequestHeaders()[CommonHeaders.USER_AGENT])
|
||||
viewBinding.webView.webViewClient = BrowserClient(proxyProvider, this)
|
||||
lifecycleScope.launch {
|
||||
|
||||
@@ -53,7 +53,7 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivitySourcesCatalogBinding.inflate(layoutInflater))
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayHomeAsUp(true, false)
|
||||
val sourcesAdapter = SourcesCatalogAdapter(this, coil, this)
|
||||
with(viewBinding.recyclerView) {
|
||||
setHasFixedSize(true)
|
||||
|
||||
@@ -62,7 +62,7 @@ class MangaDirectoriesActivity : BaseActivity<ActivityMangaDirectoriesBinding>()
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityMangaDirectoriesBinding.inflate(layoutInflater))
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayHomeAsUp(true, false)
|
||||
val adapter = AsyncListDifferDelegationAdapter(DirectoryDiffCallback(), directoryConfigAD(this))
|
||||
viewBinding.recyclerView.adapter = adapter
|
||||
viewBinding.fabAdd.setOnClickListener(this)
|
||||
|
||||
@@ -55,6 +55,7 @@ class StorageManageSettingsFragment : BasePreferenceFragment(R.string.storage_us
|
||||
findPreference<StorageUsagePreference>(AppSettings.KEY_STORAGE_USAGE)?.let { pref ->
|
||||
viewModel.storageUsage.observe(viewLifecycleOwner, pref)
|
||||
}
|
||||
findPreference<Preference>(AppSettings.KEY_WEBVIEW_CLEAR)?.isVisible = viewModel.isBrowserDataCleanupEnabled
|
||||
|
||||
viewModel.loadingKeys.observe(viewLifecycleOwner) { keys ->
|
||||
loadingPrefs.addAll(keys)
|
||||
@@ -98,6 +99,10 @@ class StorageManageSettingsFragment : BasePreferenceFragment(R.string.storage_us
|
||||
true
|
||||
}
|
||||
|
||||
AppSettings.KEY_WEBVIEW_CLEAR -> {
|
||||
viewModel.clearBrowserData()
|
||||
true
|
||||
}
|
||||
|
||||
AppSettings.KEY_CLEAR_MANGA_DATA -> {
|
||||
viewModel.clearMangaData()
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package org.koitharu.kotatsu.settings.userdata.storage
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.webkit.WebStorage
|
||||
import androidx.webkit.WebStorageCompat
|
||||
import androidx.webkit.WebViewFeature
|
||||
import coil3.ImageLoader
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -26,6 +30,8 @@ import org.koitharu.kotatsu.tracker.domain.TrackingRepository
|
||||
import java.util.EnumMap
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
@HiltViewModel
|
||||
class StorageManageSettingsViewModel @Inject constructor(
|
||||
@@ -50,6 +56,9 @@ class StorageManageSettingsViewModel @Inject constructor(
|
||||
|
||||
val onChaptersCleanedUp = MutableEventFlow<Pair<Int, Long>>()
|
||||
|
||||
val isBrowserDataCleanupEnabled: Boolean
|
||||
get() = WebViewFeature.isFeatureSupported(WebViewFeature.DELETE_BROWSING_DATA)
|
||||
|
||||
private var storageUsageJob: Job? = null
|
||||
|
||||
init {
|
||||
@@ -120,11 +129,34 @@ class StorageManageSettingsViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("RequiresFeature")
|
||||
fun clearBrowserData() {
|
||||
launchJob {
|
||||
try {
|
||||
loadingKeys.update { it + AppSettings.KEY_WEBVIEW_CLEAR }
|
||||
val storage = WebStorage.getInstance()
|
||||
suspendCoroutine { cont ->
|
||||
WebStorageCompat.deleteBrowsingData(storage) {
|
||||
cont.resume(Unit)
|
||||
}
|
||||
}
|
||||
onActionDone.call(ReversibleAction(R.string.updates_feed_cleared, null))
|
||||
} finally {
|
||||
loadingKeys.update { it - AppSettings.KEY_WEBVIEW_CLEAR }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clearUpdatesFeed() {
|
||||
launchJob(Dispatchers.Default) {
|
||||
trackingRepository.clearLogs()
|
||||
feedItemsCount.value = trackingRepository.getLogsCount()
|
||||
onActionDone.call(ReversibleAction(R.string.updates_feed_cleared, null))
|
||||
try {
|
||||
loadingKeys.update { it + AppSettings.KEY_UPDATES_FEED_CLEAR }
|
||||
trackingRepository.clearLogs()
|
||||
feedItemsCount.value = trackingRepository.getLogsCount()
|
||||
onActionDone.call(ReversibleAction(R.string.updates_feed_cleared, null))
|
||||
} finally {
|
||||
loadingKeys.update { it - AppSettings.KEY_UPDATES_FEED_CLEAR }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ class StatsActivity : BaseActivity<ActivityStatsBinding>(),
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityStatsBinding.inflate(layoutInflater))
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayHomeAsUp(true, false)
|
||||
val adapter = BaseListAdapter<StatsRecord>()
|
||||
.addDelegate(ListItemType.FEED, statsAD(this))
|
||||
.addListListener(this)
|
||||
|
||||
@@ -30,7 +30,7 @@ class TrackerDebugActivity : BaseActivity<ActivityTrackerDebugBinding>(), OnList
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityTrackerDebugBinding.inflate(layoutInflater))
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayHomeAsUp(true, false)
|
||||
val tracksAdapter = BaseListAdapter<TrackDebugItem>()
|
||||
.addDelegate(ListItemType.FEED, trackDebugAD(this, coil, this))
|
||||
with(viewBinding.recyclerView) {
|
||||
|
||||
@@ -12,7 +12,6 @@ import org.koitharu.kotatsu.core.ui.BaseActivity
|
||||
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
|
||||
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
|
||||
import org.koitharu.kotatsu.databinding.ActivityAppwidgetRecentBinding
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@AndroidEntryPoint
|
||||
class RecentWidgetConfigActivity :
|
||||
@@ -24,10 +23,7 @@ class RecentWidgetConfigActivity :
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityAppwidgetRecentBinding.inflate(layoutInflater))
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
|
||||
}
|
||||
setDisplayHomeAsUp(true, true)
|
||||
viewBinding.buttonDone.setOnClickListener(this)
|
||||
val appWidgetId = intent?.getIntExtra(
|
||||
AppWidgetManager.EXTRA_APPWIDGET_ID,
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
|
||||
import org.koitharu.kotatsu.databinding.ActivityAppwidgetShelfBinding
|
||||
import org.koitharu.kotatsu.widget.shelf.adapter.CategorySelectAdapter
|
||||
import org.koitharu.kotatsu.widget.shelf.model.CategoryItem
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@AndroidEntryPoint
|
||||
class ShelfWidgetConfigActivity :
|
||||
@@ -36,10 +35,7 @@ class ShelfWidgetConfigActivity :
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityAppwidgetShelfBinding.inflate(layoutInflater))
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
|
||||
}
|
||||
setDisplayHomeAsUp(true, true)
|
||||
adapter = CategorySelectAdapter(this)
|
||||
viewBinding.recyclerView.adapter = adapter
|
||||
viewBinding.buttonDone.setOnClickListener(this)
|
||||
|
||||
@@ -816,4 +816,6 @@
|
||||
<string name="error_disclaimer_report">You can submit a bug report to the developers. This will help us investigate and fix the issue.</string>
|
||||
<string name="link_to_manga_on_s">Link to manga on %s</string>
|
||||
<string name="link_to_manga_in_app">Link to manga in Kotatsu</string>
|
||||
<string name="clear_browser_data">Clear browser data</string>
|
||||
<string name="clear_browser_data_summary">Clear browser data such as cache and cookies. Warning: Authorization in manga sources may become invalid</string>
|
||||
</resources>
|
||||
|
||||
@@ -49,6 +49,12 @@
|
||||
android:summary="@string/clear_cookies_summary"
|
||||
android:title="@string/clear_cookies" />
|
||||
|
||||
<Preference
|
||||
android:key="webview_clear"
|
||||
android:persistent="false"
|
||||
android:summary="@string/clear_browser_data_summary"
|
||||
android:title="@string/clear_browser_data" />
|
||||
|
||||
<Preference
|
||||
android:key="chapters_clear"
|
||||
android:persistent="false"
|
||||
|
||||
@@ -6,7 +6,7 @@ appcompat = "1.7.0"
|
||||
avifDecoder = "1.1.1.14d8e3c4"
|
||||
biometric = "1.2.0-alpha05"
|
||||
coil = "3.1.0"
|
||||
collections = "1.4.5"
|
||||
collections = "1.5.0"
|
||||
#noinspection GradleDependency - 2.5.3 cause crashes
|
||||
conscrypt = "2.5.2"
|
||||
constraintlayout = "2.2.1"
|
||||
@@ -31,7 +31,7 @@ material = "1.13.0-alpha11"
|
||||
moshi = "1.15.2"
|
||||
okhttp = "4.12.0"
|
||||
okio = "3.10.2"
|
||||
parsers = "e83636edc0"
|
||||
parsers = "0847baf17b"
|
||||
preference = "1.2.1"
|
||||
recyclerview = "1.4.0"
|
||||
room = "2.6.1"
|
||||
@@ -41,7 +41,7 @@ testRules = "1.6.1"
|
||||
testRunner = "1.6.2"
|
||||
transition = "1.5.1"
|
||||
viewpager2 = "1.1.0"
|
||||
webkit = "1.12.1"
|
||||
webkit = "1.13.0"
|
||||
workRuntime = "2.10.0"
|
||||
workinspector = "1.2"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user