diff --git a/app/build.gradle b/app/build.gradle index ad07dec78..0a8daa60c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,13 +12,14 @@ android { defaultConfig { applicationId 'org.koitharu.kotatsu' - minSdkVersion 21 + minSdkVersion 16 + maxSdkVersion 20 targetSdkVersion 29 versionCode gitCommits versionName '0.3' buildConfigField 'String', 'GIT_BRANCH', "\"${gitBranch}\"" - + vectorDrawables.useSupportLibrary = true kapt { arguments { arg('room.schemaLocation', "$projectDir/schemas".toString()) @@ -82,7 +83,7 @@ dependencies { implementation 'com.github.moxy-community:moxy-ktx:2.1.2' kapt 'com.github.moxy-community:moxy-compiler:2.1.2' - implementation 'com.squareup.okhttp3:okhttp:4.5.0' + implementation 'com.squareup.okhttp3:okhttp:3.12.10' implementation 'com.squareup.okio:okio:2.5.0' implementation 'org.jsoup:jsoup:1.13.1' diff --git a/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt b/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt index d0cf6ef3a..307e17a6d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt +++ b/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt @@ -44,6 +44,7 @@ class KotatsuApp : Application() { override fun onCreate() { super.onCreate() + AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) initKoin() initCoil() Thread.setDefaultUncaughtExceptionHandler(AppCrashHandler(applicationContext)) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/PersistentCookieJar.kt b/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/PersistentCookieJar.kt index 5a39be07e..9a0dfd7c4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/PersistentCookieJar.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/PersistentCookieJar.kt @@ -15,10 +15,10 @@ */ package org.koitharu.kotatsu.core.local.cookies -import org.koitharu.kotatsu.core.local.cookies.persistence.CookiePersistor import okhttp3.Cookie import okhttp3.HttpUrl import org.koitharu.kotatsu.core.local.cookies.cache.CookieCache +import org.koitharu.kotatsu.core.local.cookies.persistence.CookiePersistor import java.util.* class PersistentCookieJar( @@ -72,7 +72,7 @@ class PersistentCookieJar( fun filterPersistentCookies(cookies: List): List { val persistentCookies: MutableList = ArrayList() for (cookie in cookies) { - if (cookie.persistent) { + if (cookie.persistent()) { persistentCookies.add(cookie) } } @@ -81,7 +81,7 @@ class PersistentCookieJar( @JvmStatic fun isCookieExpired(cookie: Cookie): Boolean { - return cookie.expiresAt < System.currentTimeMillis() + return cookie.expiresAt() < System.currentTimeMillis() } } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/cache/IdentifiableCookie.kt b/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/cache/IdentifiableCookie.kt index 6ff70030e..868bfc227 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/cache/IdentifiableCookie.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/cache/IdentifiableCookie.kt @@ -30,18 +30,18 @@ internal class IdentifiableCookie(val cookie: Cookie) { override fun equals(other: Any?): Boolean { if (other !is IdentifiableCookie) return false - return other.cookie.name == cookie.name && other.cookie.domain == cookie.domain - && other.cookie.path == cookie.path && other.cookie.secure == cookie.secure - && other.cookie.hostOnly == cookie.hostOnly + return other.cookie.name() == cookie.name() && other.cookie.domain() == cookie.domain() + && other.cookie.path() == cookie.path() && other.cookie.secure() == cookie.secure() + && other.cookie.hostOnly() == cookie.hostOnly() } override fun hashCode(): Int { var hash = 17 - hash = 31 * hash + cookie.name.hashCode() - hash = 31 * hash + cookie.domain.hashCode() - hash = 31 * hash + cookie.path.hashCode() - hash = 31 * hash + if (cookie.secure) 0 else 1 - hash = 31 * hash + if (cookie.hostOnly) 0 else 1 + hash = 31 * hash + cookie.name().hashCode() + hash = 31 * hash + cookie.domain().hashCode() + hash = 31 * hash + cookie.path().hashCode() + hash = 31 * hash + if (cookie.secure()) 0 else 1 + hash = 31 * hash + if (cookie.hostOnly()) 0 else 1 return hash } diff --git a/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/persistence/SerializableCookie.kt b/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/persistence/SerializableCookie.kt index 88f882633..b367143ae 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/persistence/SerializableCookie.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/persistence/SerializableCookie.kt @@ -73,14 +73,14 @@ class SerializableCookie : Serializable { @Throws(IOException::class) private fun writeObject(out: ObjectOutputStream) { - out.writeObject(cookie!!.name) - out.writeObject(cookie!!.value) - out.writeLong(if (cookie!!.persistent) cookie!!.expiresAt else NON_VALID_EXPIRES_AT) - out.writeObject(cookie!!.domain) - out.writeObject(cookie!!.path) - out.writeBoolean(cookie!!.secure) - out.writeBoolean(cookie!!.httpOnly) - out.writeBoolean(cookie!!.hostOnly) + out.writeObject(cookie!!.name()) + out.writeObject(cookie!!.value()) + out.writeLong(if (cookie!!.persistent()) cookie!!.expiresAt() else NON_VALID_EXPIRES_AT) + out.writeObject(cookie!!.domain()) + out.writeObject(cookie!!.path()) + out.writeBoolean(cookie!!.secure()) + out.writeBoolean(cookie!!.httpOnly()) + out.writeBoolean(cookie!!.hostOnly()) } @Throws(IOException::class, ClassNotFoundException::class) diff --git a/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/persistence/SharedPrefsCookiePersistor.kt b/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/persistence/SharedPrefsCookiePersistor.kt index 044180bb4..4a0fa1cef 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/persistence/SharedPrefsCookiePersistor.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/local/cookies/persistence/SharedPrefsCookiePersistor.kt @@ -64,7 +64,7 @@ class SharedPrefsCookiePersistor(private val sharedPreferences: SharedPreference private companion object { fun createCookieKey(cookie: Cookie): String { - return (if (cookie.secure) "https" else "http") + "://" + cookie.domain + cookie.path + "|" + cookie.name + return (if (cookie.secure()) "https" else "http") + "://" + cookie.domain() + cookie.path() + "|" + cookie.name() } } diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/LocalMangaRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/LocalMangaRepository.kt index 8a98d8398..b51ad078e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/LocalMangaRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/LocalMangaRepository.kt @@ -2,6 +2,7 @@ package org.koitharu.kotatsu.core.parser import android.content.Context import android.net.Uri +import android.os.Build import androidx.core.net.toFile import androidx.core.net.toUri import org.koin.core.KoinComponent @@ -14,6 +15,7 @@ import org.koitharu.kotatsu.utils.AlphanumComparator import org.koitharu.kotatsu.utils.ext.longHashCode import org.koitharu.kotatsu.utils.ext.readText import org.koitharu.kotatsu.utils.ext.safe +import org.koitharu.kotatsu.utils.ext.sub import java.io.File import java.util.* import java.util.zip.ZipEntry @@ -29,8 +31,11 @@ class LocalMangaRepository : MangaRepository, KoinComponent { sortOrder: SortOrder?, tag: MangaTag? ): List { - val files = context.getExternalFilesDirs("manga") - .flatMap { x -> x?.listFiles(CbzFilter())?.toList().orEmpty() } + val files = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + context.getExternalFilesDirs("manga") + context.filesDir.sub("manga") + } else { + arrayOf(context.getExternalFilesDir("manga"), context.filesDir.sub("manga")) + }.flatMap { x -> x?.listFiles(CbzFilter())?.toList().orEmpty() } return files.mapNotNull { x -> safe { getFromFile(x) } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt b/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt index 7a79c011a..b93ab077e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt +++ b/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt @@ -1,7 +1,7 @@ package org.koitharu.kotatsu.domain import android.graphics.BitmapFactory -import android.util.Size +import android.graphics.Point import okhttp3.OkHttpClient import okhttp3.Request import org.koin.core.KoinComponent @@ -29,10 +29,10 @@ object MangaUtils : KoinComponent { .get() .build() val size = client.newCall(request).await().use { - getBitmapSize(it.body?.byteStream()) + getBitmapSize(it.body()?.byteStream()) } return when { - size.width * 2 < size.height -> ReaderMode.WEBTOON + size.x * 2 < size.y -> ReaderMode.WEBTOON else -> ReaderMode.STANDARD } } catch (e: Exception) { @@ -44,7 +44,7 @@ object MangaUtils : KoinComponent { } @JvmStatic - private fun getBitmapSize(input: InputStream?): Size { + private fun getBitmapSize(input: InputStream?): Point { val options = BitmapFactory.Options().apply { inJustDecodeBounds = true } @@ -52,6 +52,6 @@ object MangaUtils : KoinComponent { val imageHeight: Int = options.outHeight val imageWidth: Int = options.outWidth check(imageHeight > 0 && imageWidth > 0) - return Size(imageWidth, imageHeight) + return Point(imageWidth, imageHeight) } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/domain/local/MangaZip.kt b/app/src/main/java/org/koitharu/kotatsu/domain/local/MangaZip.kt index 8a48d40d9..3caecdb04 100644 --- a/app/src/main/java/org/koitharu/kotatsu/domain/local/MangaZip.kt +++ b/app/src/main/java/org/koitharu/kotatsu/domain/local/MangaZip.kt @@ -47,6 +47,9 @@ class MangaZip(val file: File) { if (!file.exists()) { return } + dir.listFiles()?.forEach { + it?.deleteRecursively() + } ZipInputStream(file.inputStream()).use { input -> while (true) { val entry = input.nextEntry ?: return diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/browser/BrowserClient.kt b/app/src/main/java/org/koitharu/kotatsu/ui/browser/BrowserClient.kt index 842c712f6..dbe4b42f4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/browser/BrowserClient.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/browser/BrowserClient.kt @@ -1,10 +1,12 @@ package org.koitharu.kotatsu.ui.browser import android.graphics.Bitmap +import android.os.Build import android.webkit.WebResourceRequest import android.webkit.WebResourceResponse import android.webkit.WebView import android.webkit.WebViewClient +import androidx.annotation.RequiresApi import okhttp3.OkHttpClient import okhttp3.Request import org.koin.core.KoinComponent @@ -38,6 +40,7 @@ class BrowserClient(private val callback: BrowserCallback) : WebViewClient(), Ko return url?.let(::doRequest) } + @RequiresApi(Build.VERSION_CODES.LOLLIPOP) override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? { return request?.url?.toString()?.let(::doRequest) } @@ -47,11 +50,11 @@ class BrowserClient(private val callback: BrowserCallback) : WebViewClient(), Ko .url(url) .build() val response = okHttp.newCall(request).execute() - val ct = response.body?.contentType() + val ct = response.body()?.contentType() WebResourceResponse( - "${ct?.type}/${ct?.subtype}", + "${ct?.type()}/${ct?.subtype()}", ct?.charset()?.name() ?: "utf-8", - response.body?.byteStream() + response.body()?.byteStream() ) } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/BaseActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/BaseActivity.kt index 3644b7968..50a17b6e6 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/common/BaseActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/BaseActivity.kt @@ -62,6 +62,21 @@ abstract class BaseActivity : MvpAppCompatActivity(), KoinComponent { } } + override fun dispatchKeyEvent(event: KeyEvent): Boolean { + val keyCode = event.keyCode + val action = event.action + val isDown = action == KeyEvent.ACTION_DOWN + return if (keyCode == KeyEvent.KEYCODE_MENU) { + if (isDown) { + onKeyDown(keyCode, event) + } else { + onKeyUp(keyCode, event) + } + } else { + super.dispatchKeyEvent(event) + } + } + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { //TODO remove. Just for testing if (BuildConfig.DEBUG && keyCode == KeyEvent.KEYCODE_VOLUME_UP) { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/BaseFullscreenActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/BaseFullscreenActivity.kt index f51235f31..8d829425e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/common/BaseFullscreenActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/BaseFullscreenActivity.kt @@ -1,36 +1,37 @@ package org.koitharu.kotatsu.ui.common -import android.graphics.Color import android.os.Build import android.os.Bundle import android.view.View -import android.view.WindowManager abstract class BaseFullscreenActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - with(window) { - // addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) - statusBarColor = Color.TRANSPARENT - navigationBarColor = Color.TRANSPARENT - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES - } - } showSystemUI() } protected fun hideSystemUI() { - window.decorView.systemUiVisibility = ( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE - or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // прячем панель навигации - or View.SYSTEM_UI_FLAG_FULLSCREEN // прячем строку состояния - or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - ) + window.decorView.systemUiVisibility = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + ( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE + or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // прячем панель навигации + or View.SYSTEM_UI_FLAG_FULLSCREEN // прячем строку состояния + or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + ) + } else { + ( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE + or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // прячем панель навигации + or View.SYSTEM_UI_FLAG_FULLSCREEN // прячем строку состояния + ) + } } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/dialog/StorageSelectDialog.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/dialog/StorageSelectDialog.kt index 57e881b5f..db80cce99 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/common/dialog/StorageSelectDialog.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/dialog/StorageSelectDialog.kt @@ -2,10 +2,12 @@ package org.koitharu.kotatsu.ui.common.dialog import android.content.Context import android.content.DialogInterface +import android.os.Build import android.os.Environment import android.view.View import android.view.ViewGroup import android.widget.BaseAdapter +import androidx.annotation.RequiresApi import androidx.annotation.StringRes import androidx.appcompat.app.AlertDialog import kotlinx.android.synthetic.main.item_storage.view.* @@ -15,6 +17,7 @@ import org.koitharu.kotatsu.utils.ext.inflate import org.koitharu.kotatsu.utils.ext.longHashCode import java.io.File +@RequiresApi(Build.VERSION_CODES.LOLLIPOP) class StorageSelectDialog private constructor(private val delegate: AlertDialog) : DialogInterface by delegate { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/list/AdapterUpdater.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/list/AdapterUpdater.kt index 60a9242c4..7b21c9545 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/common/list/AdapterUpdater.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/list/AdapterUpdater.kt @@ -2,7 +2,6 @@ package org.koitharu.kotatsu.ui.common.list import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView -import java.util.* class AdapterUpdater(oldList: List, newList: List, getId: (T) -> Long) { @@ -12,7 +11,7 @@ class AdapterUpdater(oldList: List, newList: List, getId: (T) -> Long) getId(oldList[oldItemPosition]) == getId(newList[newItemPosition]) override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = - Objects.equals(oldList[oldItemPosition], newList[newItemPosition]) + oldList[oldItemPosition]?.equals(newList[newItemPosition]) == true override fun getOldListSize() = oldList.size diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseRecyclerAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseRecyclerAdapter.kt index 686873a91..0a4bf8834 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseRecyclerAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseRecyclerAdapter.kt @@ -2,9 +2,10 @@ package org.koitharu.kotatsu.ui.common.list import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView -import okhttp3.internal.toImmutableList import org.koin.core.KoinComponent import org.koitharu.kotatsu.utils.ext.replaceWith +import java.util.* +import kotlin.collections.ArrayList abstract class BaseRecyclerAdapter(private val onItemClickListener: OnRecyclerItemClickListener? = null) : RecyclerView.Adapter>(), @@ -12,7 +13,8 @@ abstract class BaseRecyclerAdapter(private val onItemClickListener: OnRecy protected val dataSet = ArrayList() //TODO make private - val items get() = dataSet.toImmutableList() + val items: List + get() = Collections.unmodifiableList(dataSet) val hasItems get() = dataSet.isNotEmpty() diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/download/DownloadNotification.kt b/app/src/main/java/org/koitharu/kotatsu/ui/download/DownloadNotification.kt index 2ec22af54..4b05da98e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/download/DownloadNotification.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/download/DownloadNotification.kt @@ -44,6 +44,7 @@ class DownloadNotification(private val context: Context) { fun fillFrom(manga: Manga) { builder.setContentTitle(manga.title) builder.setContentText(context.getString(R.string.manga_downloading_)) + builder.setTicker(context.getString(R.string.manga_downloading_)) builder.setProgress(1, 0, true) builder.setSmallIcon(android.R.drawable.stat_sys_download) builder.setLargeIcon(null) @@ -56,7 +57,7 @@ class DownloadNotification(private val context: Context) { } else { val intent = DownloadService.getCancelIntent(context, startId) builder.addAction( - R.drawable.ic_cross, + R.drawable.ic_cross_compat, context.getString(android.R.string.cancel), PendingIntent.getService( context, diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/download/DownloadService.kt b/app/src/main/java/org/koitharu/kotatsu/ui/download/DownloadService.kt index 7ed72e49d..14d407bfc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/download/DownloadService.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/download/DownloadService.kt @@ -80,7 +80,10 @@ class DownloadService : BaseService() { notification.setCancelId(startId) startForeground(DownloadNotification.NOTIFICATION_ID, notification()) } - val destination = getExternalFilesDir("manga")!! + val destination = getExternalFilesDir("manga") ?: filesDir.sub("manga").takeIf { + it.exists() || it.mkdir() + } + checkNotNull(destination) { "Cannot find place to store file" } var output: MangaZip? = null try { val repo = MangaProviderFactory.create(manga.source) @@ -146,6 +149,7 @@ class DownloadService : BaseService() { notification.update() } } catch (e: Throwable) { + e.printStackTrace() withContext(Dispatchers.Main) { notification.setError(e) notification.setCancelId(0) @@ -179,7 +183,7 @@ class DownloadService : BaseService() { okHttp.newCall(request).await().use { response -> val file = destination.sub("page.tmp") file.outputStream().use { out -> - response.body!!.byteStream().copyTo(out) + response.body()!!.byteStream().copyTo(out) } file } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/MainActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/MainActivity.kt index 1e16a5811..ad82476a7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/MainActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/MainActivity.kt @@ -56,7 +56,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList navigationView.setNavigationItemSelectedListener(this) settings.subscribe(this) - fab.imageTintList = ColorStateList.valueOf(Color.WHITE) + fab.supportImageTintList = ColorStateList.valueOf(Color.WHITE) fab.isVisible = true fab.setOnClickListener { presenter.openLastReader() diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListFragment.kt index d94f1500c..da1b2d8bc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListFragment.kt @@ -160,7 +160,7 @@ abstract class MangaListFragment : BaseFragment(R.layout.fragment_list), Mang .show() } else { textView_holder.text = e.getDisplayMessage(resources) - textView_holder.setCompoundDrawablesRelativeWithIntrinsicBounds( + textView_holder.setCompoundDrawablesWithIntrinsicBounds( 0, R.drawable.ic_error_large, 0, @@ -221,7 +221,7 @@ abstract class MangaListFragment : BaseFragment(R.layout.fragment_list), Mang } protected open fun setUpEmptyListHolder() { - textView_holder.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, null, null) + textView_holder.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null) textView_holder.setText(R.string.nothing_found) } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListSheet.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListSheet.kt index 46afb54b8..940a8f916 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/MangaListSheet.kt @@ -55,7 +55,7 @@ abstract class MangaListSheet : BaseBottomSheet(R.layout.sheet_list), MangaLi if (dialog !is BottomSheetDialog) { toolbar.isVisible = true textView_title.isVisible = false - appbar.elevation = resources.getDimension(R.dimen.elevation_large) + // appbar.elevation = resources.getDimension(R.dimen.elevation_large) } } @@ -93,11 +93,11 @@ abstract class MangaListSheet : BaseBottomSheet(R.layout.sheet_list), MangaLi if (newState == BottomSheetBehavior.STATE_EXPANDED) { toolbar.isVisible = true textView_title.isVisible = false - appbar.elevation = elevation + // appbar.elevation = elevation } else { toolbar.isVisible = false textView_title.isVisible = true - appbar.elevation = 0f + // appbar.elevation = 0f } } }) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/FavouritesListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/FavouritesListFragment.kt index b61836f3b..b5c53f6d4 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/FavouritesListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/FavouritesListFragment.kt @@ -39,7 +39,7 @@ class FavouritesListFragment : MangaListFragment(), MangaListView { override fun setUpEmptyListHolder() { textView_holder.setText(R.string.you_have_not_favourites_yet) - textView_holder.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0) + textView_holder.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0) } companion object { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoriesActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoriesActivity.kt index f3e77211d..6cb7aa632 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoriesActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/main/list/favourites/categories/CategoriesActivity.kt @@ -33,7 +33,7 @@ class CategoriesActivity : BaseActivity(), OnRecyclerItemClickListener(), MangaListView() { override fun setUpEmptyListHolder() { textView_holder.setText(R.string.text_local_holder) - textView_holder.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0) + textView_holder.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/PageLoader.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/PageLoader.kt index 39be815a7..ed532fa70 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/PageLoader.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/PageLoader.kt @@ -51,13 +51,13 @@ class PageLoader : KoinComponent, CoroutineScope, DisposableHandle { .cacheControl(CacheUtils.CONTROL_DISABLED) .build() okHttp.newCall(request).await().use { response -> - val body = response.body!! + val body = response.body()!! val type = body.contentType() - check(type?.type == "image") { - "Unexpected content type ${type?.type}/${type?.subtype}" + check(type?.type() == "image") { + "Unexpected content type ${type?.type()}/${type?.subtype()}" } cache.put(url) { out -> - response.body!!.byteStream().copyTo(out) + response.body()!!.byteStream().copyTo(out) } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt index f842297a6..572530295 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderActivity.kt @@ -12,7 +12,6 @@ import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible import androidx.core.view.postDelayed -import androidx.core.view.updatePadding import androidx.fragment.app.commit import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.activity_reader.* @@ -79,10 +78,10 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh getString(R.string.chapter_d_of_d, state.chapter?.number ?: 0, size) } - appbar_bottom.setOnApplyWindowInsetsListener { view, insets -> + /*appbar_bottom.setOnApplyWindowInsetsListener { view, insets -> view.updatePadding(bottom = insets.systemWindowInsetBottom) insets - } + }*/ settings.subscribe(this) loadSettings() @@ -286,6 +285,10 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh setUiIsVisible(!appbar_top.isVisible) true } + KeyEvent.KEYCODE_MENU -> { + setUiIsVisible(!appbar_top.isVisible) + true + } else -> super.onKeyDown(keyCode, event) } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderPresenter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderPresenter.kt index 2bc094545..e98f14381 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderPresenter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/ReaderPresenter.kt @@ -83,7 +83,7 @@ class ReaderPresenter : BasePresenter() { val fileName = URLUtil.guessFileName(url, response.contentDisposition, response.mimeType) MediaStoreCompat.insertImage(resolver, fileName) { - response.body!!.byteStream().copyTo(it) + response.body()!!.byteStream().copyTo(it) } } withContext(Dispatchers.Main) { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/standard/PageAnimTransformer.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/standard/PageAnimTransformer.kt index 584f7cf64..0411b9fe0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/standard/PageAnimTransformer.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/standard/PageAnimTransformer.kt @@ -13,14 +13,14 @@ class PageAnimTransformer : ViewPager2.PageTransformer { position <= 0 -> { // [-1,0] alpha = 1f translationX = 0f - translationZ = 0f + // translationZ = 0f scaleX = 1 + FACTOR * position scaleY = 1f } position <= 1 -> { // (0,1] alpha = 1f translationX = pageWidth * -position - translationZ = -1f + // translationZ = -1f scaleX = 1f scaleY = 1f } diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/thumbnails/PagesThumbnailsSheet.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/thumbnails/PagesThumbnailsSheet.kt index c672e0bd0..f5492b745 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/thumbnails/PagesThumbnailsSheet.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/thumbnails/PagesThumbnailsSheet.kt @@ -40,7 +40,7 @@ class PagesThumbnailsSheet : BaseBottomSheet(R.layout.sheet_pages), if (dialog !is BottomSheetDialog) { toolbar.isVisible = true textView_title.isVisible = false - appbar.elevation = resources.getDimension(R.dimen.elevation_large) + // appbar.elevation = resources.getDimension(R.dimen.elevation_large) } recyclerView.addOnLayoutChangeListener(UiUtils.SpanCountResolver) } @@ -57,11 +57,11 @@ class PagesThumbnailsSheet : BaseBottomSheet(R.layout.sheet_pages), if (newState == BottomSheetBehavior.STATE_EXPANDED) { toolbar.isVisible = true textView_title.isVisible = false - appbar.elevation = elevation + // appbar.elevation = elevation } else { toolbar.isVisible = false textView_title.isVisible = true - appbar.elevation = 0f + // appbar.elevation = 0f } } }) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/settings/AppUpdateService.kt b/app/src/main/java/org/koitharu/kotatsu/ui/settings/AppUpdateService.kt index 2cec9ce62..4a5b21a98 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/settings/AppUpdateService.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/settings/AppUpdateService.kt @@ -116,9 +116,8 @@ class AppUpdateService : BaseService() { private const val CHANNEL_ID = "update" private val PERIOD = TimeUnit.HOURS.toMillis(6) - fun isUpdateSupported(context: Context): Boolean { - return getCertificateSHA1Fingerprint(context) == CERT_SHA1 - } + @Suppress("UNUSED_PARAMETER") + fun isUpdateSupported(context: Context) = false fun startIfRequired(context: Context) { if (!isUpdateSupported(context)) { diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/settings/SettingsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/settings/SettingsActivity.kt index e8efb163a..2768497ec 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/settings/SettingsActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/settings/SettingsActivity.kt @@ -3,8 +3,6 @@ package org.koitharu.kotatsu.ui.settings import android.content.Context import android.content.Intent import android.os.Bundle -import android.transition.Slide -import android.view.Gravity import androidx.fragment.app.Fragment import androidx.fragment.app.commit import androidx.preference.Preference @@ -24,7 +22,7 @@ class SettingsActivity : BaseActivity(), if (supportFragmentManager.findFragmentById(R.id.container) == null) { supportFragmentManager.commit { replace(R.id.container, MainSettingsFragment().also { - it.exitTransition = Slide(Gravity.START) + // it.exitTransition = Slide(Gravity.START) }) } } @@ -48,8 +46,8 @@ class SettingsActivity : BaseActivity(), } private fun openFragment(fragment: Fragment) { - fragment.enterTransition = Slide(Gravity.END) - fragment.exitTransition = Slide(Gravity.START) + // fragment.enterTransition = Slide(Gravity.END) + // fragment.exitTransition = Slide(Gravity.START) supportFragmentManager.commit { replace(R.id.container, fragment) addToBackStack(null) diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/CacheUtils.kt b/app/src/main/java/org/koitharu/kotatsu/utils/CacheUtils.kt index d4f21c2ea..046223be7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/CacheUtils.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/CacheUtils.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.utils import android.content.Context +import android.os.Build import androidx.annotation.WorkerThread import okhttp3.Cache import okhttp3.CacheControl @@ -17,8 +18,11 @@ object CacheUtils { .build() @JvmStatic - fun getCacheDirs(context: Context) = (context.externalCacheDirs + context.cacheDir) - .filterNotNull() + fun getCacheDirs(context: Context) = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + (context.externalCacheDirs + context.cacheDir) + } else { + arrayOf(context.externalCacheDir, context.cacheDir) + }.filterNotNull() .distinctBy { it.absolutePath } @JvmStatic @@ -35,7 +39,7 @@ object CacheUtils { @JvmStatic fun createHttpCache(context: Context) = Cache( - directory = (context.externalCacheDir ?: context.cacheDir).sub("http"), - maxSize = FileSizeUtils.mbToBytes(60) + (context.externalCacheDir ?: context.cacheDir).sub("http"), + FileSizeUtils.mbToBytes(60) ) } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/HttpExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/HttpExt.kt index e8a8a0766..0b6d7155f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/HttpExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/HttpExt.kt @@ -3,7 +3,7 @@ package org.koitharu.kotatsu.utils.ext import okhttp3.Response val Response.mimeType: String? - get() = body?.contentType()?.run { "$type/$subtype" } + get() = body()?.contentType()?.run { "${type()}/${subtype()}" } val Response.contentDisposition: String? get() = header("Content-Disposition") \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ParseExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/ParseExt.kt index ea3cfd91e..7c00f8c5b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/ParseExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/ParseExt.kt @@ -1,30 +1,30 @@ package org.koitharu.kotatsu.utils.ext import okhttp3.Response -import okhttp3.internal.closeQuietly +import okhttp3.internal.Util.closeQuietly import org.json.JSONObject import org.jsoup.Jsoup import org.jsoup.nodes.Document fun Response.parseHtml(): Document { try { - val stream = body?.byteStream() ?: throw NullPointerException("Response body is null") - val charset = body!!.contentType()?.charset()?.name() + val stream = body()?.byteStream() ?: throw NullPointerException("Response body is null") + val charset = body()!!.contentType()?.charset()?.name() return Jsoup.parse( stream, charset, - request.url.toString() + request().url().toString() ) } finally { - closeQuietly() + closeQuietly(this) } } fun Response.parseJson(): JSONObject { try { - val string = body?.string() ?: throw NullPointerException("Response body is null") + val string = body()?.string() ?: throw NullPointerException("Response body is null") return JSONObject(string) } finally { - closeQuietly() + closeQuietly(this) } } \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/ic_cross_compat.png b/app/src/main/res/drawable-hdpi/ic_cross_compat.png new file mode 100644 index 000000000..8656c8ad3 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_cross_compat.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_cross_compat.png b/app/src/main/res/drawable-mdpi/ic_cross_compat.png new file mode 100644 index 000000000..4f73198ce Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_cross_compat.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_cross_compat.png b/app/src/main/res/drawable-xhdpi/ic_cross_compat.png new file mode 100644 index 000000000..e7dce2d07 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_cross_compat.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_cross_compat.png b/app/src/main/res/drawable-xxhdpi/ic_cross_compat.png new file mode 100644 index 000000000..ae680f21e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_cross_compat.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_cross_compat.png b/app/src/main/res/drawable-xxxhdpi/ic_cross_compat.png new file mode 100644 index 000000000..edac08bb8 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_cross_compat.png differ diff --git a/app/src/main/res/drawable/bg_badge_accent.xml b/app/src/main/res/drawable/bg_badge_accent.xml index 240151434..badaac2a4 100644 --- a/app/src/main/res/drawable/bg_badge_accent.xml +++ b/app/src/main/res/drawable/bg_badge_accent.xml @@ -2,7 +2,7 @@ - + - + + android:color="@android:color/darker_gray" /> + android:color="@color/red_accent" /> diff --git a/app/src/main/res/drawable/ic_tune.xml b/app/src/main/res/drawable/ic_tune.xml index 810bd9420..3819a0d26 100644 --- a/app/src/main/res/drawable/ic_tune.xml +++ b/app/src/main/res/drawable/ic_tune.xml @@ -2,7 +2,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" - android:tint="?android:textColorPrimary" + android:tint="?attr/android:textColorPrimary" android:viewportWidth="24.0" android:viewportHeight="24.0"> + app:layout_constraintWidth_percent="0.3" + android:layout_marginLeft="8dp" /> + app:layout_constraintTop_toBottomOf="@id/ratingBar" + android:layout_marginRight="4dp" /> + app:tint="?colorAccent" + android:layout_marginRight="4dp" /> + android:layout_marginBottom="2dp" + android:layout_alignParentLeft="true" + android:layout_alignParentRight="true"> + android:text="@string/close" + android:layout_toLeftOf="@id/button_restart" />