mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-10 10:47:48 +01:00
Revert "Drop support for Android 5.x"
This reverts commit 443024cebb
. Guess I'll do this a bit later so scb can get another major update first.
April Fools or whatever.
This commit is contained in:
parent
7aa379a857
commit
f7a6cbe5e2
15 changed files with 91 additions and 37 deletions
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.network
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.webkit.WebSettings
|
import android.webkit.WebSettings
|
||||||
|
@ -113,7 +114,10 @@ class CloudflareInterceptor(private val context: Context) : Interceptor {
|
||||||
latch.countDown()
|
latch.countDown()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url == origRequestUrl && !challengeFound) {
|
// HTTP error codes are only received since M
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
|
||||||
|
url == origRequestUrl && !challengeFound
|
||||||
|
) {
|
||||||
// The first request didn't return the challenge, abort.
|
// The first request didn't return the challenge, abort.
|
||||||
latch.countDown()
|
latch.countDown()
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,10 @@ abstract class BaseThemedActivity : AppCompatActivity() {
|
||||||
R.style.Theme_Tachiyomi_Light_Api27
|
R.style.Theme_Tachiyomi_Light_Api27
|
||||||
}
|
}
|
||||||
// Light status bar + fallback gray navigation bar
|
// Light status bar + fallback gray navigation bar
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
|
||||||
|
R.style.Theme_Tachiyomi_Light_Api23
|
||||||
|
}
|
||||||
|
// Fallback gray status + navigation bar
|
||||||
else -> {
|
else -> {
|
||||||
R.style.Theme_Tachiyomi_Light
|
R.style.Theme_Tachiyomi_Light
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.base.controller
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager.PERMISSION_GRANTED
|
import android.content.pm.PackageManager.PERMISSION_GRANTED
|
||||||
|
import android.os.Build
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import com.bluelinelabs.conductor.Controller
|
import com.bluelinelabs.conductor.Controller
|
||||||
|
@ -20,9 +21,11 @@ fun Router.popControllerWithTag(tag: String): Boolean {
|
||||||
|
|
||||||
fun Controller.requestPermissionsSafe(permissions: Array<String>, requestCode: Int) {
|
fun Controller.requestPermissionsSafe(permissions: Array<String>, requestCode: Int) {
|
||||||
val activity = activity ?: return
|
val activity = activity ?: return
|
||||||
permissions.forEach { permission ->
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
if (ContextCompat.checkSelfPermission(activity, permission) != PERMISSION_GRANTED) {
|
permissions.forEach { permission ->
|
||||||
requestPermissions(arrayOf(permission), requestCode)
|
if (ContextCompat.checkSelfPermission(activity, permission) != PERMISSION_GRANTED) {
|
||||||
|
requestPermissions(arrayOf(permission), requestCode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -290,17 +290,23 @@ class MangaController :
|
||||||
fab.setOnClickListener {
|
fab.setOnClickListener {
|
||||||
val item = presenter.getNextUnreadChapter()
|
val item = presenter.getNextUnreadChapter()
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
|
// Create animation listener
|
||||||
|
val revealAnimationListener: Animator.AnimatorListener = object : AnimatorListenerAdapter() {
|
||||||
|
override fun onAnimationStart(animation: Animator?) {
|
||||||
|
openChapter(item.chapter, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get coordinates and start animation
|
// Get coordinates and start animation
|
||||||
actionFab?.getCoordinates()?.let { coordinates ->
|
actionFab?.getCoordinates()?.let { coordinates ->
|
||||||
binding.revealView.showRevealEffect(
|
if (!binding.revealView.showRevealEffect(
|
||||||
coordinates.x,
|
coordinates.x,
|
||||||
coordinates.y,
|
coordinates.y,
|
||||||
object : AnimatorListenerAdapter() {
|
revealAnimationListener
|
||||||
override fun onAnimationStart(animation: Animator?) {
|
)
|
||||||
openChapter(item.chapter, true)
|
) {
|
||||||
}
|
openChapter(item.chapter)
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
view?.context?.toast(R.string.no_next_chapter)
|
view?.context?.toast(R.string.no_next_chapter)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package eu.kanade.tachiyomi.ui.manga.info
|
package eu.kanade.tachiyomi.ui.manga.info
|
||||||
|
|
||||||
|
import android.graphics.PorterDuff
|
||||||
|
import android.os.Build
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -19,6 +21,7 @@ import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||||
|
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||||
import eu.kanade.tachiyomi.util.view.setChips
|
import eu.kanade.tachiyomi.util.view.setChips
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.merge
|
import kotlinx.coroutines.flow.merge
|
||||||
|
@ -301,6 +304,18 @@ class MangaInfoHeaderAdapter(
|
||||||
initialLoad = false
|
initialLoad = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// backgroundTint attribute doesn't work properly on Android 5
|
||||||
|
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
listOf(binding.backdropOverlay, binding.mangaInfoToggleMoreScrim)
|
||||||
|
.forEach {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
it.background.setColorFilter(
|
||||||
|
view.context.getResourceColor(android.R.attr.colorBackground),
|
||||||
|
PorterDuff.Mode.SRC_ATOP
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showMangaInfo(visible: Boolean) {
|
private fun showMangaInfo(visible: Boolean) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
@ -63,25 +64,27 @@ class SettingsAdvancedController : SettingsController() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
preference {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
key = "pref_disable_battery_optimization"
|
preference {
|
||||||
titleRes = R.string.pref_disable_battery_optimization
|
key = "pref_disable_battery_optimization"
|
||||||
summaryRes = R.string.pref_disable_battery_optimization_summary
|
titleRes = R.string.pref_disable_battery_optimization
|
||||||
|
summaryRes = R.string.pref_disable_battery_optimization_summary
|
||||||
|
|
||||||
onClick {
|
onClick {
|
||||||
val packageName: String = context.packageName
|
val packageName: String = context.packageName
|
||||||
if (!context.powerManager.isIgnoringBatteryOptimizations(packageName)) {
|
if (!context.powerManager.isIgnoringBatteryOptimizations(packageName)) {
|
||||||
try {
|
try {
|
||||||
val intent = Intent().apply {
|
val intent = Intent().apply {
|
||||||
action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
|
action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
|
||||||
data = "package:$packageName".toUri()
|
data = "package:$packageName".toUri()
|
||||||
|
}
|
||||||
|
startActivity(intent)
|
||||||
|
} catch (e: ActivityNotFoundException) {
|
||||||
|
context.toast(R.string.battery_optimization_setting_activity_not_found)
|
||||||
}
|
}
|
||||||
startActivity(intent)
|
} else {
|
||||||
} catch (e: ActivityNotFoundException) {
|
context.toast(R.string.battery_optimization_disabled)
|
||||||
context.toast(R.string.battery_optimization_setting_activity_not_found)
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
context.toast(R.string.battery_optimization_disabled)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ abstract class WebViewClientCompat : WebViewClient() {
|
||||||
return shouldInterceptRequestCompat(view, url)
|
return shouldInterceptRequestCompat(view, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.M)
|
||||||
final override fun onReceivedError(
|
final override fun onReceivedError(
|
||||||
view: WebView,
|
view: WebView,
|
||||||
request: WebResourceRequest,
|
request: WebResourceRequest,
|
||||||
|
@ -77,6 +78,7 @@ abstract class WebViewClientCompat : WebViewClient() {
|
||||||
onReceivedErrorCompat(view, errorCode, description, failingUrl, failingUrl == view.url)
|
onReceivedErrorCompat(view, errorCode, description, failingUrl, failingUrl == view.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.M)
|
||||||
final override fun onReceivedHttpError(
|
final override fun onReceivedHttpError(
|
||||||
view: WebView,
|
view: WebView,
|
||||||
request: WebResourceRequest,
|
request: WebResourceRequest,
|
||||||
|
|
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.widget
|
||||||
import android.animation.ObjectAnimator
|
import android.animation.ObjectAnimator
|
||||||
import android.animation.StateListAnimator
|
import android.animation.StateListAnimator
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import com.google.android.material.R
|
import com.google.android.material.R
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
|
@ -19,7 +20,12 @@ class ElevationAppBarLayout @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enableElevation(liftOnScroll: Boolean) {
|
fun enableElevation(liftOnScroll: Boolean) {
|
||||||
setElevation(liftOnScroll)
|
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
// Delay to avoid crash
|
||||||
|
post { setElevation(liftOnScroll) }
|
||||||
|
} else {
|
||||||
|
setElevation(liftOnScroll)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setElevation(liftOnScroll: Boolean) {
|
private fun setElevation(liftOnScroll: Boolean) {
|
||||||
|
|
|
@ -49,8 +49,10 @@ class RevealAnimationView @JvmOverloads constructor(context: Context, attrs: Att
|
||||||
* @param centerX x starting point
|
* @param centerX x starting point
|
||||||
* @param centerY y starting point
|
* @param centerY y starting point
|
||||||
* @param listener animation listener
|
* @param listener animation listener
|
||||||
|
*
|
||||||
|
* @return sdk version lower then 21
|
||||||
*/
|
*/
|
||||||
fun showRevealEffect(centerX: Int, centerY: Int, listener: Animator.AnimatorListener) {
|
fun showRevealEffect(centerX: Int, centerY: Int, listener: Animator.AnimatorListener): Boolean {
|
||||||
this.isVisible = true
|
this.isVisible = true
|
||||||
|
|
||||||
val height = this.height
|
val height = this.height
|
||||||
|
@ -69,5 +71,6 @@ class RevealAnimationView @JvmOverloads constructor(context: Context, attrs: Att
|
||||||
|
|
||||||
anim.addListener(listener)
|
anim.addListener(listener)
|
||||||
anim.start()
|
anim.start()
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
app/src/main/res/values-v23/themes.xml
Normal file
9
app/src/main/res/values-v23/themes.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<style name="Theme.Tachiyomi.Light.Api23">
|
||||||
|
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||||
|
<item name="android:windowLightStatusBar">true</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -88,8 +88,7 @@
|
||||||
<!-- Main Theme-->
|
<!-- Main Theme-->
|
||||||
<!--===========-->
|
<!--===========-->
|
||||||
<style name="Theme.Tachiyomi.Light" parent="Theme.Base">
|
<style name="Theme.Tachiyomi.Light" parent="Theme.Base">
|
||||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
<item name="android:statusBarColor">@color/md_black_1000_54</item>
|
||||||
<item name="android:windowLightStatusBar">true</item>
|
|
||||||
<item name="android:navigationBarColor">@color/md_black_1000_54</item>
|
<item name="android:navigationBarColor">@color/md_black_1000_54</item>
|
||||||
|
|
||||||
<item name="colorFilterActive">@color/filterColorLight</item>
|
<item name="colorFilterActive">@color/filterColorLight</item>
|
||||||
|
|
|
@ -41,7 +41,7 @@ import uy.kohesive.injekt.api.addSingleton
|
||||||
* Test class for the [LegacyBackupManager].
|
* Test class for the [LegacyBackupManager].
|
||||||
* Note that this does not include the backup create/restore services.
|
* Note that this does not include the backup create/restore services.
|
||||||
*/
|
*/
|
||||||
@Config(constants = BuildConfig::class, sdk = [Build.VERSION_CODES.M])
|
@Config(constants = BuildConfig::class, sdk = [Build.VERSION_CODES.LOLLIPOP])
|
||||||
@RunWith(CustomRobolectricGradleTestRunner::class)
|
@RunWith(CustomRobolectricGradleTestRunner::class)
|
||||||
class BackupTest {
|
class BackupTest {
|
||||||
// Create root object
|
// Create root object
|
||||||
|
|
|
@ -13,7 +13,7 @@ import org.junit.runner.RunWith
|
||||||
import org.robolectric.RuntimeEnvironment
|
import org.robolectric.RuntimeEnvironment
|
||||||
import org.robolectric.annotation.Config
|
import org.robolectric.annotation.Config
|
||||||
|
|
||||||
@Config(constants = BuildConfig::class, sdk = [Build.VERSION_CODES.M])
|
@Config(constants = BuildConfig::class, sdk = [Build.VERSION_CODES.LOLLIPOP])
|
||||||
@RunWith(CustomRobolectricGradleTestRunner::class)
|
@RunWith(CustomRobolectricGradleTestRunner::class)
|
||||||
class CategoryTest {
|
class CategoryTest {
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ import uy.kohesive.injekt.api.InjektModule
|
||||||
import uy.kohesive.injekt.api.InjektRegistrar
|
import uy.kohesive.injekt.api.InjektRegistrar
|
||||||
import uy.kohesive.injekt.api.addSingleton
|
import uy.kohesive.injekt.api.addSingleton
|
||||||
|
|
||||||
@Config(constants = BuildConfig::class, sdk = [Build.VERSION_CODES.M])
|
@Config(constants = BuildConfig::class, sdk = [Build.VERSION_CODES.LOLLIPOP])
|
||||||
@RunWith(CustomRobolectricGradleTestRunner::class)
|
@RunWith(CustomRobolectricGradleTestRunner::class)
|
||||||
class LibraryUpdateServiceTest {
|
class LibraryUpdateServiceTest {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
object AndroidConfig {
|
object AndroidConfig {
|
||||||
const val compileSdk = 29
|
const val compileSdk = 29
|
||||||
const val minSdk = 23
|
const val minSdk = 21
|
||||||
const val targetSdk = 29
|
const val targetSdk = 29
|
||||||
const val buildTools = "30.0.3"
|
const val buildTools = "30.0.3"
|
||||||
const val ndk = "22.0.7026061"
|
const val ndk = "22.0.7026061"
|
||||||
|
|
Loading…
Reference in a new issue