chore: merge upstream.

This commit is contained in:
KaiserBh
2023-11-09 23:37:56 +11:00
275 changed files with 4294 additions and 2587 deletions

View File

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.core.security
import eu.kanade.tachiyomi.core.R
import tachiyomi.core.preference.Preference
import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.preference.getEnum
@ -20,7 +21,10 @@ class SecurityPreferences(
* For app lock. Will be set when there is a pending timed lock.
* Otherwise this pref should be deleted.
*/
fun lastAppClosed() = preferenceStore.getLong("last_app_closed", 0)
fun lastAppClosed() = preferenceStore.getLong(
Preference.appStateKey("last_app_closed"),
0,
)
enum class SecureScreenMode(val titleResId: Int) {
ALWAYS(R.string.lock_always),

View File

@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.network.interceptor.UncaughtExceptionInterceptor
import eu.kanade.tachiyomi.network.interceptor.UserAgentInterceptor
import okhttp3.Cache
import okhttp3.OkHttpClient
import okhttp3.brotli.BrotliInterceptor
import okhttp3.logging.HttpLoggingInterceptor
import java.io.File
import java.util.concurrent.TimeUnit
@ -29,6 +30,7 @@ class NetworkHelper(
maxSize = 5L * 1024 * 1024, // 5 MiB
),
)
.addInterceptor(BrotliInterceptor)
.addInterceptor(UncaughtExceptionInterceptor())
.addInterceptor(UserAgentInterceptor(::defaultUserAgentProvider))

View File

@ -19,7 +19,7 @@ class NetworkPreferences(
fun defaultUserAgent(): Preference<String> {
return preferenceStore.getString(
"default_user_agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0",
)
}
}

View File

@ -89,7 +89,8 @@ abstract class WebViewInterceptor(
}
}
// Based on [IsRequestHeaderSafe] in https://source.chromium.org/chromium/chromium/src/+/main:services/network/public/cpp/header_util.cc
// Based on [IsRequestHeaderSafe] in
// https://source.chromium.org/chromium/chromium/src/+/main:services/network/public/cpp/header_util.cc
private fun isRequestHeaderSafe(_name: String, _value: String): Boolean {
val name = _name.lowercase(Locale.ENGLISH)
val value = _value.lowercase(Locale.ENGLISH)
@ -97,4 +98,6 @@ private fun isRequestHeaderSafe(_name: String, _value: String): Boolean {
if (name == "connection" && value == "upgrade") return false
return true
}
private val unsafeHeaderNames = listOf("content-length", "host", "trailer", "te", "upgrade", "cookie2", "keep-alive", "transfer-encoding", "set-cookie")
private val unsafeHeaderNames = listOf(
"content-length", "host", "trailer", "te", "upgrade", "cookie2", "keep-alive", "transfer-encoding", "set-cookie",
)

View File

@ -28,6 +28,30 @@ object DiskUtil {
return size
}
/**
* Gets the total space for the disk that a file path points to, in bytes.
*/
fun getTotalStorageSpace(file: File): Long {
return try {
val stat = StatFs(file.absolutePath)
stat.blockCountLong * stat.blockSizeLong
} catch (_: Exception) {
-1L
}
}
/**
* Gets the available space for the disk that a file path points to, in bytes.
*/
fun getAvailableStorageSpace(file: File): Long {
return try {
val stat = StatFs(file.absolutePath)
stat.availableBlocksLong * stat.blockSizeLong
} catch (_: Exception) {
-1L
}
}
/**
* Gets the available space for the disk that a file path points to, in bytes.
*/

View File

@ -22,21 +22,29 @@ interface Preference<T> {
fun stateIn(scope: CoroutineScope): StateFlow<T>
val isPrivate: Boolean
get() = key().startsWith(PRIVATE_PREFIX)
companion object {
/**
* A preference that should not be exposed in places like backups.
* A preference that should not be exposed in places like backups without user consent.
*/
fun isPrivate(key: String): Boolean {
return key.startsWith(PRIVATE_PREFIX)
}
fun privateKey(key: String): String {
return "${PRIVATE_PREFIX}$key"
}
/**
* A preference used for internal app state that isn't really a user preference
* and therefore should not be in places like backups.
*/
fun isAppState(key: String): Boolean {
return key.startsWith(APP_STATE_PREFIX)
}
fun appStateKey(key: String): String {
return "${APP_STATE_PREFIX}$key"
}
private const val APP_STATE_PREFIX = "__APP_STATE_"
private const val PRIVATE_PREFIX = "__PRIVATE_"
}
}

View File

@ -0,0 +1,15 @@
package tachiyomi.core.util.lang
import java.text.Collator
import java.util.Locale
private val collator by lazy {
val locale = Locale.getDefault()
Collator.getInstance(locale).apply {
strength = Collator.PRIMARY
}
}
fun String.compareToWithCollator(other: String): Int {
return collator.compare(this, other)
}

View File

@ -271,7 +271,9 @@ object ImageUtil {
}
}
private fun splitImageName(filenamePrefix: String, index: Int) = "${filenamePrefix}__${"%03d".format(index + 1)}.jpg"
private fun splitImageName(filenamePrefix: String, index: Int) = "${filenamePrefix}__${"%03d".format(
index + 1,
)}.jpg"
private val BitmapFactory.Options.splitData
get(): List<SplitData> {
@ -356,10 +358,12 @@ object ImageUtil {
val botLeftIsDark = botLeftPixel.isDark()
val botRightIsDark = botRightPixel.isDark()
var darkBG = (topLeftIsDark && (botLeftIsDark || botRightIsDark || topRightIsDark || midLeftIsDark || topMidIsDark)) ||
(topRightIsDark && (botRightIsDark || botLeftIsDark || midRightIsDark || topMidIsDark))
var darkBG =
(topLeftIsDark && (botLeftIsDark || botRightIsDark || topRightIsDark || midLeftIsDark || topMidIsDark)) ||
(topRightIsDark && (botRightIsDark || botLeftIsDark || midRightIsDark || topMidIsDark))
val topAndBotPixels = listOf(topLeftPixel, topCenterPixel, topRightPixel, botRightPixel, bottomCenterPixel, botLeftPixel)
val topAndBotPixels =
listOf(topLeftPixel, topCenterPixel, topRightPixel, botRightPixel, bottomCenterPixel, botLeftPixel)
val isNotWhiteAndCloseTo = topAndBotPixels.mapIndexed { index, color ->
val other = topAndBotPixels[(index + 1) % topAndBotPixels.size]
!color.isWhite() && color.isCloseTo(other)
@ -504,10 +508,16 @@ object ImageUtil {
darkBG -> {
return ColorDrawable(blackColor)
}
topIsBlackStreak || (topCornersIsDark && topOffsetCornersIsDark && (topMidIsDark || overallBlackPixels > 9)) -> {
topIsBlackStreak || (
topCornersIsDark && topOffsetCornersIsDark &&
(topMidIsDark || overallBlackPixels > 9)
) -> {
intArrayOf(blackColor, blackColor, whiteColor, whiteColor)
}
bottomIsBlackStreak || (botCornersIsDark && botOffsetCornersIsDark && (bottomCenterPixel.isDark() || overallBlackPixels > 9)) -> {
bottomIsBlackStreak || (
botCornersIsDark && botOffsetCornersIsDark &&
(bottomCenterPixel.isDark() || overallBlackPixels > 9)
) -> {
intArrayOf(whiteColor, whiteColor, blackColor, blackColor)
}
else -> {