From 0d5099f23028c6c378d1907a61367537c1083d01 Mon Sep 17 00:00:00 2001 From: arkon Date: Tue, 7 Jan 2020 18:46:31 -0500 Subject: [PATCH] Drop support for Android 4.x (#2440) * Bump minSdkVersion * Remove Android 4.x specific logic * Consolidate res assets * Add note about minimum Android version to README * Restore incorrectly removed method, remove unneeded Lollipop TargetApi annotations --- README.md | 2 +- app/build.gradle | 2 +- .../tachiyomi/network/AndroidCookieJar.kt | 30 +----- .../network/CloudflareInterceptor.kt | 6 +- .../kanade/tachiyomi/network/NetworkHelper.kt | 98 +------------------ .../tachiyomi/ui/base/holder/SlicedHolder.kt | 7 +- .../tachiyomi/ui/reader/ReaderActivity.kt | 16 +-- .../viewer/webtoon/WebtoonRecyclerView.kt | 7 +- .../ui/setting/SettingsBackupController.kt | 64 ++++-------- .../ui/setting/SettingsDownloadController.kt | 28 ++---- .../java/eu/kanade/tachiyomi/util/DiskUtil.kt | 14 +-- .../tachiyomi/util/WebViewClientCompat.kt | 1 - .../tachiyomi/widget/ElevationAppBarLayout.kt | 28 +++--- .../tachiyomi/widget/RevealAnimationView.kt | 61 +++++------- .../library_item_selector_amoled.xml | 21 ---- .../library_item_selector_dark.xml | 21 ---- .../library_item_selector_light.xml | 21 ---- .../list_item_selector_amoled.xml | 19 ---- .../drawable-v21/list_item_selector_dark.xml | 19 ---- .../drawable-v21/list_item_selector_light.xml | 19 ---- .../drawable/library_item_selector_amoled.xml | 23 +++-- .../drawable/library_item_selector_dark.xml | 23 +++-- .../drawable/library_item_selector_light.xml | 23 +++-- .../drawable/list_item_selector_amoled.xml | 23 +++-- .../res/drawable/list_item_selector_dark.xml | 23 +++-- .../res/drawable/list_item_selector_light.xml | 23 +++-- app/src/main/res/values-v21/dimens.xml | 5 - app/src/main/res/values-v21/keys.xml | 6 -- app/src/main/res/values-v21/themes.xml | 58 ----------- app/src/main/res/values/dimens.xml | 3 +- app/src/main/res/values/keys.xml | 7 -- app/src/main/res/values/styles.xml | 4 +- app/src/main/res/values/themes.xml | 25 ++++- 33 files changed, 200 insertions(+), 530 deletions(-) delete mode 100644 app/src/main/res/drawable-v21/library_item_selector_amoled.xml delete mode 100644 app/src/main/res/drawable-v21/library_item_selector_dark.xml delete mode 100644 app/src/main/res/drawable-v21/library_item_selector_light.xml delete mode 100644 app/src/main/res/drawable-v21/list_item_selector_amoled.xml delete mode 100644 app/src/main/res/drawable-v21/list_item_selector_dark.xml delete mode 100644 app/src/main/res/drawable-v21/list_item_selector_light.xml delete mode 100644 app/src/main/res/values-v21/dimens.xml delete mode 100644 app/src/main/res/values-v21/keys.xml delete mode 100644 app/src/main/res/values-v21/themes.xml delete mode 100644 app/src/main/res/values/keys.xml diff --git a/README.md b/README.md index ea0b8fb32c..21f8adffb1 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # ![app icon](./.github/readme-images/app-icon.png)Tachiyomi -Tachiyomi is a free and open source manga reader for Android. +Tachiyomi is a free and open source manga reader for Android 5.0 and above. ![screenshots of app](./.github/readme-images/screens.png) diff --git a/app/build.gradle b/app/build.gradle index 91153d2617..53b39b8765 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -35,7 +35,7 @@ android { defaultConfig { applicationId "eu.kanade.tachiyomi" - minSdkVersion 16 + minSdkVersion 21 targetSdkVersion 28 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" versionCode 41 diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/AndroidCookieJar.kt b/app/src/main/java/eu/kanade/tachiyomi/network/AndroidCookieJar.kt index ff231ed421..7db589a551 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/AndroidCookieJar.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/AndroidCookieJar.kt @@ -1,35 +1,20 @@ package eu.kanade.tachiyomi.network -import android.content.Context -import android.os.Build import android.webkit.CookieManager -import android.webkit.CookieSyncManager import okhttp3.Cookie import okhttp3.CookieJar import okhttp3.HttpUrl -class AndroidCookieJar(context: Context) : CookieJar { +class AndroidCookieJar : CookieJar { private val manager = CookieManager.getInstance() - private val syncManager by lazy { CookieSyncManager.createInstance(context) } - - init { - // Init sync manager when using anything below L - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - syncManager - } - } - override fun saveFromResponse(url: HttpUrl, cookies: List) { val urlString = url.toString() for (cookie in cookies) { manager.setCookie(urlString, cookie.toString()) } - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - syncManager.sync() - } } override fun loadForRequest(url: HttpUrl): List { @@ -39,7 +24,7 @@ class AndroidCookieJar(context: Context) : CookieJar { fun get(url: HttpUrl): List { val cookies = manager.getCookie(url.toString()) - return if (cookies != null && !cookies.isEmpty()) { + return if (cookies != null && cookies.isNotEmpty()) { cookies.split(";").mapNotNull { Cookie.parse(url, it) } } else { emptyList() @@ -53,19 +38,10 @@ class AndroidCookieJar(context: Context) : CookieJar { cookies.split(";") .map { it.substringBefore("=") } .onEach { manager.setCookie(urlString, "$it=;Max-Age=-1") } - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - syncManager.sync() - } } fun removeAll() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - manager.removeAllCookies {} - } else { - manager.removeAllCookie() - syncManager.sync() - } + manager.removeAllCookies {} } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/CloudflareInterceptor.kt b/app/src/main/java/eu/kanade/tachiyomi/network/CloudflareInterceptor.kt index 7a320ba49f..ec66d2df40 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/CloudflareInterceptor.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/CloudflareInterceptor.kt @@ -28,11 +28,7 @@ class CloudflareInterceptor(private val context: Context) : Interceptor { * Application class. */ private val initWebView by lazy { - if (Build.VERSION.SDK_INT >= 17) { - WebSettings.getDefaultUserAgent(context) - } else { - null - } + WebSettings.getDefaultUserAgent(context) } @Synchronized diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt index fa0b70660d..21445593e4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt @@ -1,17 +1,9 @@ package eu.kanade.tachiyomi.network import android.content.Context -import android.os.Build -import okhttp3.* +import okhttp3.Cache +import okhttp3.OkHttpClient import java.io.File -import java.io.IOException -import java.net.InetAddress -import java.net.Socket -import java.net.UnknownHostException -import java.security.KeyManagementException -import java.security.KeyStore -import java.security.NoSuchAlgorithmException -import javax.net.ssl.* class NetworkHelper(context: Context) { @@ -19,99 +11,15 @@ class NetworkHelper(context: Context) { private val cacheSize = 5L * 1024 * 1024 // 5 MiB - val cookieManager = AndroidCookieJar(context) + val cookieManager = AndroidCookieJar() val client = OkHttpClient.Builder() .cookieJar(cookieManager) .cache(Cache(cacheDir, cacheSize)) - .enableTLS12() .build() val cloudflareClient = client.newBuilder() .addInterceptor(CloudflareInterceptor(context)) .build() - private fun OkHttpClient.Builder.enableTLS12(): OkHttpClient.Builder { - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { - return this - } - - val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) - trustManagerFactory.init(null as KeyStore?) - val trustManagers = trustManagerFactory.trustManagers - if (trustManagers.size == 1 && trustManagers[0] is X509TrustManager) { - class TLSSocketFactory @Throws(KeyManagementException::class, NoSuchAlgorithmException::class) - constructor() : SSLSocketFactory() { - - private val internalSSLSocketFactory: SSLSocketFactory - - init { - val context = SSLContext.getInstance("TLS") - context.init(null, null, null) - internalSSLSocketFactory = context.socketFactory - } - - override fun getDefaultCipherSuites(): Array { - return internalSSLSocketFactory.defaultCipherSuites - } - - override fun getSupportedCipherSuites(): Array { - return internalSSLSocketFactory.supportedCipherSuites - } - - @Throws(IOException::class) - override fun createSocket(): Socket? { - return enableTLSOnSocket(internalSSLSocketFactory.createSocket()) - } - - @Throws(IOException::class) - override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean): Socket? { - return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose)) - } - - @Throws(IOException::class, UnknownHostException::class) - override fun createSocket(host: String, port: Int): Socket? { - return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)) - } - - @Throws(IOException::class, UnknownHostException::class) - override fun createSocket(host: String, port: Int, localHost: InetAddress, localPort: Int): Socket? { - return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort)) - } - - @Throws(IOException::class) - override fun createSocket(host: InetAddress, port: Int): Socket? { - return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)) - } - - @Throws(IOException::class) - override fun createSocket(address: InetAddress, port: Int, localAddress: InetAddress, localPort: Int): Socket? { - return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort)) - } - - private fun enableTLSOnSocket(socket: Socket?): Socket? { - if (socket != null && socket is SSLSocket) { - socket.enabledProtocols = socket.supportedProtocols - } - return socket - } - } - - sslSocketFactory(TLSSocketFactory(), trustManagers[0] as X509TrustManager) - } - - val specCompat = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) - .tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0) - .cipherSuites( - *ConnectionSpec.MODERN_TLS.cipherSuites.orEmpty().toTypedArray(), - CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - ) - .build() - - val specs = listOf(specCompat, ConnectionSpec.CLEARTEXT) - connectionSpecs(specs) - - return this - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/holder/SlicedHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/holder/SlicedHolder.kt index b2fc8fd26f..2d7efa2489 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/holder/SlicedHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/holder/SlicedHolder.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.ui.base.holder -import android.os.Build import android.view.View import android.view.ViewGroup import eu.davidea.flexibleadapter.FlexibleAdapter @@ -51,10 +50,6 @@ interface SlicedHolder { slice.showRightTopRect(topRect) slice.showLeftBottomRect(bottomRect) slice.showRightBottomRect(bottomRect) - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - slice.showTopEdgeShadow(topShadow) - slice.showBottomEdgeShadow(bottomShadow) - } setMargins(margin, if (topShadow) margin else 0, margin, if (bottomShadow) margin else 0) } @@ -68,4 +63,4 @@ interface SlicedHolder { val margin get() = 8.dpToPx -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index c245f3375b..d72b993a3a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -8,7 +8,6 @@ import android.content.pm.ActivityInfo import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.Color -import android.os.Build import android.os.Bundle import android.view.* import android.view.animation.Animation @@ -21,9 +20,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity -import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.AddToLibraryFirst -import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.Error -import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.Success +import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.* import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters @@ -276,10 +273,7 @@ class ReaderActivity : BaseRxActivity() { toolbarAnimation.setAnimationListener(object : SimpleAnimationListener() { override fun onAnimationStart(animation: Animation) { // Fix status bar being translucent the first time it's opened. - if (Build.VERSION.SDK_INT >= 21) { - window.addFlags( - WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) - } + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) } }) toolbar.startAnimation(toolbarAnimation) @@ -637,11 +631,7 @@ class ReaderActivity : BaseRxActivity() { */ private fun setFullscreen(enabled: Boolean) { systemUi = if (enabled) { - val level = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - SystemUiHelper.LEVEL_IMMERSIVE - } else { - SystemUiHelper.LEVEL_HIDE_STATUS_BAR - } + val level = SystemUiHelper.LEVEL_IMMERSIVE val flags = SystemUiHelper.FLAG_IMMERSIVE_STICKY or SystemUiHelper.FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonRecyclerView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonRecyclerView.kt index 52600d0e20..b6597cba36 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonRecyclerView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonRecyclerView.kt @@ -3,16 +3,14 @@ package eu.kanade.tachiyomi.ui.reader.viewer.webtoon import android.animation.Animator import android.animation.AnimatorSet import android.animation.ValueAnimator -import android.annotation.TargetApi import android.content.Context -import android.os.Build -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import android.util.AttributeSet import android.view.HapticFeedbackConstants import android.view.MotionEvent import android.view.ViewConfiguration import android.view.animation.DecelerateInterpolator +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import eu.kanade.tachiyomi.ui.reader.viewer.GestureDetectorWithLongTap /** @@ -58,7 +56,6 @@ open class WebtoonRecyclerView @JvmOverloads constructor( firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition() } - @TargetApi(Build.VERSION_CODES.KITKAT) override fun onScrollStateChanged(state: Int) { super.onScrollStateChanged(state) val layoutManager = layoutManager diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt index 8ba0798fe8..005ec1aaf1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt @@ -5,10 +5,9 @@ import android.app.Activity import android.app.Dialog import android.content.* import android.net.Uri -import android.os.Build import android.os.Bundle -import androidx.preference.PreferenceScreen import android.view.View +import androidx.preference.PreferenceScreen import com.afollestad.materialdialogs.MaterialDialog import com.hippo.unifile.UniFile import eu.kanade.tachiyomi.R @@ -106,21 +105,12 @@ class SettingsBackupController : SettingsController() { onClick { val currentDir = preferences.backupsDirectory().getOrDefault() try{ - val intent = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - // Custom dir selected, open directory selector - preferences.context.getFilePicker(currentDir) - } else { - Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) - } - + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) startActivityForResult(intent, CODE_BACKUP_DIR) } catch (e: ActivityNotFoundException){ - //Fall back to custom picker on error - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){ - startActivityForResult(preferences.context.getFilePicker(currentDir), CODE_BACKUP_DIR) - } + // Fall back to custom picker on error + startActivityForResult(preferences.context.getFilePicker(currentDir), CODE_BACKUP_DIR) } - } preferences.backupsDirectory().asObservable() @@ -154,37 +144,27 @@ class SettingsBackupController : SettingsController() { // Get uri of backup folder. val uri = data.data - // Get UriPermission so it's possible to write files post kitkat. - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { - val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or - Intent.FLAG_GRANT_WRITE_URI_PERMISSION + // Get UriPermission so it's possible to write files + val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or + Intent.FLAG_GRANT_WRITE_URI_PERMISSION - activity.contentResolver.takePersistableUriPermission(uri, flags) - } + activity.contentResolver.takePersistableUriPermission(uri, flags) - // Set backup Uri. + // Set backup Uri preferences.backupsDirectory().set(uri.toString()) } CODE_BACKUP_CREATE -> if (data != null && resultCode == Activity.RESULT_OK) { val activity = activity ?: return - val uri = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - val dir = data.data.path - val file = File(dir, Backup.getDefaultFilename()) - Uri.fromFile(file) - } else { - val uri = data.data - val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or - Intent.FLAG_GRANT_WRITE_URI_PERMISSION + val uri = data.data + val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or + Intent.FLAG_GRANT_WRITE_URI_PERMISSION - activity.contentResolver.takePersistableUriPermission(uri, flags) - val file = UniFile.fromUri(activity, uri) - - file.uri - } + activity.contentResolver.takePersistableUriPermission(uri, flags) + val file = UniFile.fromUri(activity, uri) CreatingBackupDialog().showDialog(router, TAG_CREATING_BACKUP_DIALOG) - BackupCreateService.makeBackup(activity, uri, backupFlags) + BackupCreateService.makeBackup(activity, file.uri, backupFlags) } CODE_BACKUP_RESTORE -> if (data != null && resultCode == Activity.RESULT_OK) { val uri = data.data @@ -201,25 +181,17 @@ class SettingsBackupController : SettingsController() { val currentDir = preferences.backupsDirectory().getOrDefault() try { - // If API is lower than Lollipop use custom picker - val intent = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - preferences.context.getFilePicker(currentDir) - } else { - // Use Androids build in file creator - Intent(Intent.ACTION_CREATE_DOCUMENT) + // Use Android's built-in file creator + val intent = Intent(Intent.ACTION_CREATE_DOCUMENT) .addCategory(Intent.CATEGORY_OPENABLE) .setType("application/*") .putExtra(Intent.EXTRA_TITLE, Backup.getDefaultFilename()) - } startActivityForResult(intent, CODE_BACKUP_CREATE) } catch (e: ActivityNotFoundException) { // Handle errors where the android ROM doesn't support the built in picker - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){ - startActivityForResult(preferences.context.getFilePicker(currentDir), CODE_BACKUP_CREATE) - } + startActivityForResult(preferences.context.getFilePicker(currentDir), CODE_BACKUP_CREATE) } - } class CreateBackupDialog : DialogController() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt index e4531de8d6..cd2b41a49f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt @@ -5,7 +5,6 @@ import android.app.Dialog import android.content.ActivityNotFoundException import android.content.Intent import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.Environment import androidx.core.content.ContextCompat @@ -107,11 +106,7 @@ class SettingsDownloadController : SettingsController() { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { when (requestCode) { - DOWNLOAD_DIR_PRE_L -> if (data != null && resultCode == Activity.RESULT_OK) { - val uri = Uri.fromFile(File(data.data.path)) - preferences.downloadsDirectory().set(uri.toString()) - } - DOWNLOAD_DIR_L -> if (data != null && resultCode == Activity.RESULT_OK) { + DOWNLOAD_DIR -> if (data != null && resultCode == Activity.RESULT_OK) { val context = applicationContext ?: return val uri = data.data val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or @@ -132,19 +127,11 @@ class SettingsDownloadController : SettingsController() { } fun customDirectorySelected(currentDir: String) { - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - startActivityForResult(preferences.context.getFilePicker(currentDir), DOWNLOAD_DIR_PRE_L) - } else { - val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) - try { - startActivityForResult(intent, DOWNLOAD_DIR_L) - } catch (e: ActivityNotFoundException) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - startActivityForResult(preferences.context.getFilePicker(currentDir), DOWNLOAD_DIR_L) - } - } - + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) + try { + startActivityForResult(intent, DOWNLOAD_DIR) + } catch (e: ActivityNotFoundException) { + startActivityForResult(preferences.context.getFilePicker(currentDir), DOWNLOAD_DIR) } } @@ -183,7 +170,6 @@ class SettingsDownloadController : SettingsController() { } private companion object { - const val DOWNLOAD_DIR_PRE_L = 103 - const val DOWNLOAD_DIR_L = 104 + const val DOWNLOAD_DIR = 104 } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/DiskUtil.kt b/app/src/main/java/eu/kanade/tachiyomi/util/DiskUtil.kt index 4f0375e423..e089c9ebc9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/DiskUtil.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/DiskUtil.kt @@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.util import android.content.Context import android.content.Intent import android.net.Uri -import android.os.Build import android.os.Environment import androidx.core.content.ContextCompat import androidx.core.os.EnvironmentCompat @@ -45,13 +44,6 @@ object DiskUtil { } } - if (Build.VERSION.SDK_INT < 21) { - val extStorages = System.getenv("SECONDARY_STORAGE") - if (extStorages != null) { - directories += extStorages.split(":").map(::File) - } - } - return directories } @@ -79,11 +71,7 @@ object DiskUtil { * Scans the given file so that it can be shown in gallery apps, for example. */ fun scanMedia(context: Context, uri: Uri) { - val action = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { - Intent.ACTION_MEDIA_MOUNTED - } else { - Intent.ACTION_MEDIA_SCANNER_SCAN_FILE - } + val action = Intent.ACTION_MEDIA_SCANNER_SCAN_FILE val mediaScanIntent = Intent(action) mediaScanIntent.data = uri context.sendBroadcast(mediaScanIntent) diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/WebViewClientCompat.kt b/app/src/main/java/eu/kanade/tachiyomi/util/WebViewClientCompat.kt index 977dca5e6d..911a40714c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/WebViewClientCompat.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/WebViewClientCompat.kt @@ -36,7 +36,6 @@ abstract class WebViewClientCompat : WebViewClient() { return shouldOverrideUrlCompat(view, url) } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) final override fun shouldInterceptRequest( view: WebView, request: WebResourceRequest diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/ElevationAppBarLayout.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/ElevationAppBarLayout.kt index 32a959e663..8ae15900f2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/ElevationAppBarLayout.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/ElevationAppBarLayout.kt @@ -16,32 +16,26 @@ class ElevationAppBarLayout @JvmOverloads constructor( private var origStateAnimator: StateListAnimator? = null init { - if (Build.VERSION.SDK_INT >= 21) { - origStateAnimator = stateListAnimator - } + origStateAnimator = stateListAnimator } fun enableElevation() { - if (Build.VERSION.SDK_INT >= 21) { - stateListAnimator = origStateAnimator - } + stateListAnimator = origStateAnimator } fun disableElevation() { - if (Build.VERSION.SDK_INT >= 21) { - stateListAnimator = StateListAnimator().apply { - val objAnimator = ObjectAnimator.ofFloat(this, "elevation", 0f) + stateListAnimator = StateListAnimator().apply { + val objAnimator = ObjectAnimator.ofFloat(this, "elevation", 0f) - // Enabled and collapsible, but not collapsed means not elevated - addState(intArrayOf(android.R.attr.enabled, R.attr.state_collapsible, -R.attr.state_collapsed), - objAnimator) + // Enabled and collapsible, but not collapsed means not elevated + addState(intArrayOf(android.R.attr.enabled, R.attr.state_collapsible, -R.attr.state_collapsed), + objAnimator) - // Default enabled state - addState(intArrayOf(android.R.attr.enabled), objAnimator) + // Default enabled state + addState(intArrayOf(android.R.attr.enabled), objAnimator) - // Disabled state - addState(IntArray(0), objAnimator) - } + // Disabled state + addState(IntArray(0), objAnimator) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/RevealAnimationView.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/RevealAnimationView.kt index f5718e75df..a78a678034 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/RevealAnimationView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/RevealAnimationView.kt @@ -2,14 +2,11 @@ package eu.kanade.tachiyomi.widget import android.animation.Animator import android.animation.AnimatorListenerAdapter -import android.annotation.TargetApi import android.content.Context -import android.os.Build import android.util.AttributeSet import android.view.View import android.view.ViewAnimationUtils -@TargetApi(Build.VERSION_CODES.LOLLIPOP) class RevealAnimationView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : View(context, attrs) { @@ -21,28 +18,25 @@ class RevealAnimationView @JvmOverloads constructor(context: Context, attrs: Att * @param initialRadius size of radius of animation */ fun hideRevealEffect(centerX: Int, centerY: Int, initialRadius: Int) { - if (Build.VERSION.SDK_INT >= 21) { + // Make the view visible. + this.visibility = View.VISIBLE - // Make the view visible. - this.visibility = View.VISIBLE + // Create the animation (the final radius is zero). + val anim = ViewAnimationUtils.createCircularReveal( + this, centerX, centerY, initialRadius.toFloat(), 0f) - // Create the animation (the final radius is zero). - val anim = ViewAnimationUtils.createCircularReveal( - this, centerX, centerY, initialRadius.toFloat(), 0f) + // Set duration of animation. + anim.duration = 500 - // Set duration of animation. - anim.duration = 500 + // make the view invisible when the animation is done + anim.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + super.onAnimationEnd(animation) + this@RevealAnimationView.visibility = View.INVISIBLE + } + }) - // make the view invisible when the animation is done - anim.addListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator) { - super.onAnimationEnd(animation) - this@RevealAnimationView.visibility = View.INVISIBLE - } - }) - - anim.start() - } + anim.start() } /** @@ -55,25 +49,20 @@ class RevealAnimationView @JvmOverloads constructor(context: Context, attrs: Att * @return sdk version lower then 21 */ fun showRevealEffect(centerX: Int, centerY: Int, listener: Animator.AnimatorListener): Boolean { - if (Build.VERSION.SDK_INT >= 21) { + this.visibility = View.VISIBLE - this.visibility = View.VISIBLE + val height = this.height - val height = this.height + // Create animation + val anim = ViewAnimationUtils.createCircularReveal( + this, centerX, centerY, 0f, height.toFloat()) - // Create animation - val anim = ViewAnimationUtils.createCircularReveal( - this, centerX, centerY, 0f, height.toFloat()) + // Set duration of animation + anim.duration = 350 - // Set duration of animation - anim.duration = 350 - - anim.addListener(listener) - anim.start() - return true - } - return false + anim.addListener(listener) + anim.start() + return true } - } diff --git a/app/src/main/res/drawable-v21/library_item_selector_amoled.xml b/app/src/main/res/drawable-v21/library_item_selector_amoled.xml deleted file mode 100644 index b21f488c29..0000000000 --- a/app/src/main/res/drawable-v21/library_item_selector_amoled.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/library_item_selector_dark.xml b/app/src/main/res/drawable-v21/library_item_selector_dark.xml deleted file mode 100644 index 82a72da4aa..0000000000 --- a/app/src/main/res/drawable-v21/library_item_selector_dark.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/library_item_selector_light.xml b/app/src/main/res/drawable-v21/library_item_selector_light.xml deleted file mode 100644 index 1f2e8bf89c..0000000000 --- a/app/src/main/res/drawable-v21/library_item_selector_light.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/list_item_selector_amoled.xml b/app/src/main/res/drawable-v21/list_item_selector_amoled.xml deleted file mode 100644 index 0fce81a343..0000000000 --- a/app/src/main/res/drawable-v21/list_item_selector_amoled.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/list_item_selector_dark.xml b/app/src/main/res/drawable-v21/list_item_selector_dark.xml deleted file mode 100644 index 07b9ef6d5b..0000000000 --- a/app/src/main/res/drawable-v21/list_item_selector_dark.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/list_item_selector_light.xml b/app/src/main/res/drawable-v21/list_item_selector_light.xml deleted file mode 100644 index 942446ef06..0000000000 --- a/app/src/main/res/drawable-v21/list_item_selector_light.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/library_item_selector_amoled.xml b/app/src/main/res/drawable/library_item_selector_amoled.xml index 1cf05bdc96..18b0fb40eb 100644 --- a/app/src/main/res/drawable/library_item_selector_amoled.xml +++ b/app/src/main/res/drawable/library_item_selector_amoled.xml @@ -1,10 +1,19 @@ - + + + + + + - - - - + + + - \ No newline at end of file + + + + + + diff --git a/app/src/main/res/drawable/library_item_selector_dark.xml b/app/src/main/res/drawable/library_item_selector_dark.xml index 9880c4b38c..7e2dc8b749 100644 --- a/app/src/main/res/drawable/library_item_selector_dark.xml +++ b/app/src/main/res/drawable/library_item_selector_dark.xml @@ -1,10 +1,19 @@ - + + + + + + - - - - + + + - \ No newline at end of file + + + + + + diff --git a/app/src/main/res/drawable/library_item_selector_light.xml b/app/src/main/res/drawable/library_item_selector_light.xml index 70f7b85b47..e51877cc91 100644 --- a/app/src/main/res/drawable/library_item_selector_light.xml +++ b/app/src/main/res/drawable/library_item_selector_light.xml @@ -1,10 +1,19 @@ - + + + + + + - - - - + + + - \ No newline at end of file + + + + + + diff --git a/app/src/main/res/drawable/list_item_selector_amoled.xml b/app/src/main/res/drawable/list_item_selector_amoled.xml index 9bbf565786..f3a9c3e06f 100644 --- a/app/src/main/res/drawable/list_item_selector_amoled.xml +++ b/app/src/main/res/drawable/list_item_selector_amoled.xml @@ -1,10 +1,19 @@ - + + + + + + - - - - + + + - \ No newline at end of file + + + + + + diff --git a/app/src/main/res/drawable/list_item_selector_dark.xml b/app/src/main/res/drawable/list_item_selector_dark.xml index 60034f8183..5b08a69f78 100644 --- a/app/src/main/res/drawable/list_item_selector_dark.xml +++ b/app/src/main/res/drawable/list_item_selector_dark.xml @@ -1,10 +1,19 @@ - + + + + + + - - - - + + + - \ No newline at end of file + + + + + + diff --git a/app/src/main/res/drawable/list_item_selector_light.xml b/app/src/main/res/drawable/list_item_selector_light.xml index 92bed9fc90..3fa9224b93 100644 --- a/app/src/main/res/drawable/list_item_selector_light.xml +++ b/app/src/main/res/drawable/list_item_selector_light.xml @@ -1,10 +1,19 @@ - + + + + + + - - - - + + + - \ No newline at end of file + + + + + + diff --git a/app/src/main/res/values-v21/dimens.xml b/app/src/main/res/values-v21/dimens.xml deleted file mode 100644 index 8b96d2cadc..0000000000 --- a/app/src/main/res/values-v21/dimens.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - 41dp - \ No newline at end of file diff --git a/app/src/main/res/values-v21/keys.xml b/app/src/main/res/values-v21/keys.xml deleted file mode 100644 index 0a74c875b1..0000000000 --- a/app/src/main/res/values-v21/keys.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - sans-serif-medium - sans-serif-regular - \ No newline at end of file diff --git a/app/src/main/res/values-v21/themes.xml b/app/src/main/res/values-v21/themes.xml deleted file mode 100644 index a7ff1d5c4b..0000000000 --- a/app/src/main/res/values-v21/themes.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 77114a2479..8b6231cdf4 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -20,10 +20,9 @@ 16sp 14sp - 158dp - 16dp + 41dp 0dp diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml deleted file mode 100644 index 6f662810f2..0000000000 --- a/app/src/main/res/values/keys.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - sans-serif - sans-serif - diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index d52818314c..d2100ea3b6 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -50,7 +50,7 @@ + + + @@ -61,6 +66,10 @@ @color/dividerDark @drawable/line_divider_dark + true + @android:color/transparent + @color/colorDarkPrimaryDark + true @style/ThemeOverlay.AppCompat.Dark.ActionBar @@ -86,6 +95,10 @@ @@ -96,6 +109,10 @@ @color/colorAmoledPrimary @color/md_black_1000 + true + @android:color/transparent + @android:color/transparent + @drawable/list_item_selector_amoled @drawable/library_item_selector_amoled @@ -113,12 +130,18 @@ @color/colorDarkPrimary @color/colorDarkPrimaryDark @android:color/black + + ?colorPrimaryDark + ?colorPrimaryDark