Misc fixes

This commit is contained in:
Koitharu
2020-02-24 18:48:37 +02:00
parent f02c233292
commit a2a0e62b47
19 changed files with 218 additions and 30 deletions

View File

@@ -0,0 +1,6 @@
package org.koitharu.kotatsu.core.local
enum class Cache(val dir: String) {
PAGES("pages");
}

View File

@@ -12,7 +12,7 @@ import java.io.OutputStream
class PagesCache(context: Context) {
private val cacheDir = context.externalCacheDir ?: context.cacheDir
private val lruCache = DiskLruCache.create(cacheDir.sub("pages"), FileSizeUtils.mbToBytes(200))
private val lruCache = DiskLruCache.create(cacheDir.sub(Cache.PAGES.dir), FileSizeUtils.mbToBytes(200))
operator fun get(url: String): File? {
return lruCache.get(url)?.takeIfReadable()

View File

@@ -20,7 +20,6 @@ class MangaGridHolder(parent: ViewGroup) : BaseViewHolder<Manga, MangaHistory?>(
placeholder(R.drawable.ic_placeholder)
fallback(R.drawable.ic_placeholder)
error(R.drawable.ic_placeholder)
crossfade(true)
}
}
}

View File

@@ -5,6 +5,7 @@ import android.view.ViewGroup
import androidx.core.view.isVisible
import coil.api.load
import coil.request.RequestDisposable
import coil.size.Scale
import kotlinx.android.synthetic.main.item_manga_list_details.*
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.Manga
@@ -26,7 +27,6 @@ class MangaListDetailsHolder(parent: ViewGroup) : BaseViewHolder<Manga, MangaHis
placeholder(R.drawable.ic_placeholder)
fallback(R.drawable.ic_placeholder)
error(R.drawable.ic_placeholder)
crossfade(true)
}
if(data.rating == Manga.NO_RATING) {
textView_rating.isVisible = false

View File

@@ -23,7 +23,6 @@ class MangaListHolder(parent: ViewGroup) :
placeholder(R.drawable.ic_placeholder)
fallback(R.drawable.ic_placeholder)
error(R.drawable.ic_placeholder)
crossfade(true)
}
}
}

View File

@@ -0,0 +1,57 @@
package org.koitharu.kotatsu.ui.settings
import android.os.Bundle
import androidx.lifecycle.lifecycleScope
import androidx.preference.Preference
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.local.Cache
import org.koitharu.kotatsu.ui.common.BasePreferenceFragment
import org.koitharu.kotatsu.utils.CacheUtils
import org.koitharu.kotatsu.utils.FileSizeUtils
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cache) {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.pref_history)
findPreference<Preference>(R.string.key_pages_cache_clear)?.let { pref ->
lifecycleScope.launchWhenStarted {
val size = withContext(Dispatchers.IO) {
CacheUtils.computeCacheSize(pref.context, Cache.PAGES.dir)
}
pref.summary = FileSizeUtils.formatBytes(pref.context, size)
}
}
}
override fun onPreferenceTreeClick(preference: Preference): Boolean {
return when(preference.key) {
getString(R.string.key_pages_cache_clear) -> {
clearCache(preference, Cache.PAGES)
true
}
else -> super.onPreferenceTreeClick(preference)
}
}
private fun clearCache(preference: Preference, cache: Cache) {
val ctx = preference.context.applicationContext
lifecycleScope.launch {
try {
preference.isEnabled = false
val size = withContext(Dispatchers.IO) {
CacheUtils.clearCache(ctx, cache.dir)
CacheUtils.computeCacheSize(ctx, cache.dir)
}
preference.summary = FileSizeUtils.formatBytes(ctx, size)
} catch (e: Exception) {
preference.summary = e.getDisplayMessage(ctx.resources)
} finally {
preference.isEnabled = true
}
}
}
}

View File

@@ -0,0 +1,12 @@
package org.koitharu.kotatsu.ui.settings.sources
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.ui.common.BaseFragment
class SourcesSettingsFragment : BaseFragment(R.layout.fragment_settings_sources) {
override fun onResume() {
super.onResume()
activity?.setTitle(R.string.remote_sources)
}
}

View File

@@ -0,0 +1,27 @@
package org.koitharu.kotatsu.utils
import android.content.Context
import androidx.annotation.WorkerThread
import org.koitharu.kotatsu.utils.ext.computeSize
import org.koitharu.kotatsu.utils.ext.sub
import org.koitharu.kotatsu.utils.ext.sumByLong
object CacheUtils {
@JvmStatic
fun getCacheDirs(context: Context) = (context.externalCacheDirs + context.cacheDir)
.filterNotNull()
.distinctBy { it.absolutePath }
@JvmStatic
@WorkerThread
fun computeCacheSize(context: Context, name: String) = getCacheDirs(context)
.map { it.sub(name) }
.sumByLong { x -> x.computeSize() }
@JvmStatic
@WorkerThread
fun clearCache(context: Context, name: String) = getCacheDirs(context)
.map { it.sub(name) }
.forEach { it.deleteRecursively() }
}

View File

@@ -1,5 +1,12 @@
package org.koitharu.kotatsu.utils
import android.content.Context
import org.koitharu.kotatsu.R
import java.text.DecimalFormat
import kotlin.math.log10
import kotlin.math.pow
object FileSizeUtils {
@JvmStatic
@@ -7,4 +14,22 @@ object FileSizeUtils {
@JvmStatic
fun kbToBytes(kb: Int) = 1024L * kb
@JvmStatic
fun formatBytes(context: Context, bytes: Long): String {
val units = context.getString(R.string.text_file_sizes).split('|')
if (bytes <= 0) {
return "0 ${units.first()}"
}
val digitGroups = (log10(bytes.toDouble()) / log10(1024.0)).toInt()
return buildString {
append(
DecimalFormat("#,##0.#").format(
bytes / 1024.0.pow(digitGroups.toDouble())
).toString()
)
append(' ')
append(units.getOrNull(digitGroups).orEmpty())
}
}
}

View File

@@ -3,4 +3,20 @@ package org.koitharu.kotatsu.utils.ext
fun <T> MutableCollection<T>.replaceWith(subject: Iterable<T>) {
clear()
addAll(subject)
}
inline fun <T> Array<out T>.sumByLong(selector: (T) -> Long): Long {
var sum = 0L
for (element in this) {
sum += selector(element)
}
return sum
}
inline fun <T> Iterable<T>.sumByLong(selector: (T) -> Long): Long {
var sum = 0L
for (element in this) {
sum += selector(element)
}
return sum
}

View File

@@ -10,4 +10,12 @@ fun File.takeIfReadable() = takeIf { it.exists() && it.canRead() }
fun ZipFile.readText(entry: ZipEntry) = getInputStream(entry).bufferedReader().use {
it.readText()
}
}
fun File.computeSize(): Long = listFiles()?.sumByLong { x ->
if (x.isDirectory) {
x.computeSize()
} else {
x.length()
}
} ?: 0L

View File

@@ -1,11 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/ic_placeholder_raw"
android:top="20dp"
android:bottom="20dp"
android:left="20dp"
android:right="20dp"
android:gravity="center" />
</layer-list>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="60dp"
android:height="60dp"
android:tint="?android:textColorTertiary"
android:viewportWidth="60"
android:viewportHeight="60">
<path
android:fillColor="#FF000000"
android:pathData="m20,37.8913c0,1.1647 0.9481,2.1087 2.1087,2.1087l15.7826,0c1.1647,0 2.1087,-0.9481 2.1087,-2.1087L40,22.1087C40,20.944 39.0519,20 37.8913,20L22.1087,20C20.944,20 20,20.9481 20,22.1087c0,0 0,15.7826 0,15.7826zM37.8913,38.9988L22.1087,38.9988c-0.6089,0 -1.1075,-0.4986 -1.1075,-1.1075l0,-2.6359l3.7924,-3.7924 3.2407,3.2407c0.1962,0.1962 0.5108,0.1962 0.707,0L34.5934,28.8517 38.9988,33.257l0,4.6342c0,0.6089 -0.4986,1.1075 -1.1075,1.1075zM22.1087,21.0012l15.7826,0c0.6089,0 1.1075,0.4986 1.1075,1.1075l0,9.7303l-4.0539,-4.0499c-0.1962,-0.1962 -0.5108,-0.1962 -0.707,0L28.3858,33.6412 25.1451,30.4005c-0.1962,-0.1962 -0.5108,-0.1962 -0.707,0l-3.4369,3.4369l0,-11.7286c0,-0.6089 0.4986,-1.1075 1.1075,-1.1075z"/>
<path
android:fillColor="#FF000000"
android:pathData="m26.1994,28.0139c1.4058,0 2.546,-1.1443 2.546,-2.546 0,-1.4017 -1.1443,-2.546 -2.546,-2.546 -1.4017,0 -2.546,1.1443 -2.546,2.546 0,1.4017 1.1402,2.546 2.546,2.546zM26.1994,23.9232c0.8541,0 1.5447,0.6947 1.5447,1.5447 0,0.85 -0.6947,1.5447 -1.5447,1.5447 -0.85,0 -1.5447,-0.6947 -1.5447,-1.5447 0,-0.85 0.6906,-1.5447 1.5447,-1.5447z"/>
</vector>

View File

@@ -1,14 +0,0 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:tint="?android:textColorTertiary"
android:viewportWidth="489.4"
android:viewportHeight="489.4">
<path
android:fillColor="#FF000000"
android:pathData="M0,437.8c0,28.5 23.2,51.6 51.6,51.6h386.2c28.5,0 51.6,-23.2 51.6,-51.6V51.6c0,-28.5 -23.2,-51.6 -51.6,-51.6H51.6C23.1,0 0,23.2 0,51.6C0,51.6 0,437.8 0,437.8zM437.8,464.9H51.6c-14.9,0 -27.1,-12.2 -27.1,-27.1v-64.5l92.8,-92.8l79.3,79.3c4.8,4.8 12.5,4.8 17.3,0l143.2,-143.2l107.8,107.8v113.4C464.9,452.7 452.7,464.9 437.8,464.9zM51.6,24.5h386.2c14.9,0 27.1,12.2 27.1,27.1v238.1l-99.2,-99.1c-4.8,-4.8 -12.5,-4.8 -17.3,0L205.2,333.8l-79.3,-79.3c-4.8,-4.8 -12.5,-4.8 -17.3,0l-84.1,84.1v-287C24.5,36.7 36.7,24.5 51.6,24.5z" />
<path
android:fillColor="#FF000000"
android:pathData="M151.7,196.1c34.4,0 62.3,-28 62.3,-62.3s-28,-62.3 -62.3,-62.3s-62.3,28 -62.3,62.3S117.3,196.1 151.7,196.1zM151.7,96c20.9,0 37.8,17 37.8,37.8s-17,37.8 -37.8,37.8s-37.8,-17 -37.8,-37.8S130.8,96 151.7,96z" />
</vector>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000"
android:pathData="M16.36,14C16.44,13.34 16.5,12.68 16.5,12C16.5,11.32 16.44,10.66 16.36,10H19.74C19.9,10.64 20,11.31 20,12C20,12.69 19.9,13.36 19.74,14M14.59,19.56C15.19,18.45 15.65,17.25 15.97,16H18.92C17.96,17.65 16.43,18.93 14.59,19.56M14.34,14H9.66C9.56,13.34 9.5,12.68 9.5,12C9.5,11.32 9.56,10.65 9.66,10H14.34C14.43,10.65 14.5,11.32 14.5,12C14.5,12.68 14.43,13.34 14.34,14M12,19.96C11.17,18.76 10.5,17.43 10.09,16H13.91C13.5,17.43 12.83,18.76 12,19.96M8,8H5.08C6.03,6.34 7.57,5.06 9.4,4.44C8.8,5.55 8.35,6.75 8,8M5.08,16H8C8.35,17.25 8.8,18.45 9.4,19.56C7.57,18.93 6.03,17.65 5.08,16M4.26,14C4.1,13.36 4,12.69 4,12C4,11.31 4.1,10.64 4.26,10H7.64C7.56,10.66 7.5,11.32 7.5,12C7.5,12.68 7.56,13.34 7.64,14M12,4.03C12.83,5.23 13.5,6.57 13.91,8H10.09C10.5,6.57 11.17,5.23 12,4.03M18.92,8H15.97C15.65,6.75 15.19,5.55 14.59,4.44C16.43,5.07 17.96,6.34 18.92,8M12,2C6.47,2 2,6.5 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" />
</vector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>

View File

@@ -2,6 +2,7 @@
<resources>
<string name="key_list_mode">list_mode</string>
<string name="key_theme">theme</string>
<string name="key_pages_cache_clear">pages_cache_clear</string>
<string-array name="values_theme">
<item>-1</item>
<item>1</item>

View File

@@ -75,4 +75,8 @@
<string name="operation_not_supported">This operation is not supported</string>
<string name="text_file_not_supported">Invalid file. Only ZIP and CBZ are supported.</string>
<string name="no_description">No description</string>
<string name="history_and_cache">History and cache</string>
<string name="clear_pages_cache">Clear pages cache</string>
<string name="cache">Cache</string>
<string name="text_file_sizes">B|kB|MB|GB|TB</string>
</resources>

View File

@@ -8,4 +8,14 @@
android:icon="@drawable/ic_palette"
android:title="@string/appearance" />
<PreferenceScreen
android:fragment="org.koitharu.kotatsu.ui.settings.sources.SourcesSettingsFragment"
android:icon="@drawable/ic_web"
android:title="@string/remote_sources" />
<PreferenceScreen
android:fragment="org.koitharu.kotatsu.ui.settings.HistorySettingsFragment"
android:icon="@drawable/ic_history"
android:title="@string/history_and_cache" />
</PreferenceScreen>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
app:iconSpaceReserved="false"
android:title="@string/cache">
<Preference
android:key="@string/key_pages_cache_clear"
android:persistent="false"
android:title="@string/clear_pages_cache"
app:iconSpaceReserved="false" />
</PreferenceCategory>
</PreferenceScreen>