Compare commits

...

1 Commits

Author SHA1 Message Date
Koitharu
5fe40ac17e Fix old api compatibility 2020-04-25 21:29:46 +03:00
72 changed files with 229 additions and 151 deletions

View File

@@ -12,13 +12,14 @@ android {
defaultConfig { defaultConfig {
applicationId 'org.koitharu.kotatsu' applicationId 'org.koitharu.kotatsu'
minSdkVersion 21 minSdkVersion 16
maxSdkVersion 20
targetSdkVersion 29 targetSdkVersion 29
versionCode gitCommits versionCode gitCommits
versionName '0.3' versionName '0.3'
buildConfigField 'String', 'GIT_BRANCH', "\"${gitBranch}\"" buildConfigField 'String', 'GIT_BRANCH', "\"${gitBranch}\""
vectorDrawables.useSupportLibrary = true
kapt { kapt {
arguments { arguments {
arg('room.schemaLocation', "$projectDir/schemas".toString()) arg('room.schemaLocation', "$projectDir/schemas".toString())
@@ -82,7 +83,7 @@ dependencies {
implementation 'com.github.moxy-community:moxy-ktx:2.1.2' implementation 'com.github.moxy-community:moxy-ktx:2.1.2'
kapt 'com.github.moxy-community:moxy-compiler: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 'com.squareup.okio:okio:2.5.0'
implementation 'org.jsoup:jsoup:1.13.1' implementation 'org.jsoup:jsoup:1.13.1'

View File

@@ -44,6 +44,7 @@ class KotatsuApp : Application() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
initKoin() initKoin()
initCoil() initCoil()
Thread.setDefaultUncaughtExceptionHandler(AppCrashHandler(applicationContext)) Thread.setDefaultUncaughtExceptionHandler(AppCrashHandler(applicationContext))

View File

@@ -15,10 +15,10 @@
*/ */
package org.koitharu.kotatsu.core.local.cookies package org.koitharu.kotatsu.core.local.cookies
import org.koitharu.kotatsu.core.local.cookies.persistence.CookiePersistor
import okhttp3.Cookie import okhttp3.Cookie
import okhttp3.HttpUrl import okhttp3.HttpUrl
import org.koitharu.kotatsu.core.local.cookies.cache.CookieCache import org.koitharu.kotatsu.core.local.cookies.cache.CookieCache
import org.koitharu.kotatsu.core.local.cookies.persistence.CookiePersistor
import java.util.* import java.util.*
class PersistentCookieJar( class PersistentCookieJar(
@@ -72,7 +72,7 @@ class PersistentCookieJar(
fun filterPersistentCookies(cookies: List<Cookie>): List<Cookie> { fun filterPersistentCookies(cookies: List<Cookie>): List<Cookie> {
val persistentCookies: MutableList<Cookie> = ArrayList() val persistentCookies: MutableList<Cookie> = ArrayList()
for (cookie in cookies) { for (cookie in cookies) {
if (cookie.persistent) { if (cookie.persistent()) {
persistentCookies.add(cookie) persistentCookies.add(cookie)
} }
} }
@@ -81,7 +81,7 @@ class PersistentCookieJar(
@JvmStatic @JvmStatic
fun isCookieExpired(cookie: Cookie): Boolean { fun isCookieExpired(cookie: Cookie): Boolean {
return cookie.expiresAt < System.currentTimeMillis() return cookie.expiresAt() < System.currentTimeMillis()
} }
} }
} }

View File

@@ -30,18 +30,18 @@ internal class IdentifiableCookie(val cookie: Cookie) {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is IdentifiableCookie) return false if (other !is IdentifiableCookie) return false
return other.cookie.name == cookie.name && other.cookie.domain == cookie.domain return other.cookie.name() == cookie.name() && other.cookie.domain() == cookie.domain()
&& other.cookie.path == cookie.path && other.cookie.secure == cookie.secure && other.cookie.path() == cookie.path() && other.cookie.secure() == cookie.secure()
&& other.cookie.hostOnly == cookie.hostOnly && other.cookie.hostOnly() == cookie.hostOnly()
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var hash = 17 var hash = 17
hash = 31 * hash + cookie.name.hashCode() hash = 31 * hash + cookie.name().hashCode()
hash = 31 * hash + cookie.domain.hashCode() hash = 31 * hash + cookie.domain().hashCode()
hash = 31 * hash + cookie.path.hashCode() hash = 31 * hash + cookie.path().hashCode()
hash = 31 * hash + if (cookie.secure) 0 else 1 hash = 31 * hash + if (cookie.secure()) 0 else 1
hash = 31 * hash + if (cookie.hostOnly) 0 else 1 hash = 31 * hash + if (cookie.hostOnly()) 0 else 1
return hash return hash
} }

View File

@@ -73,14 +73,14 @@ class SerializableCookie : Serializable {
@Throws(IOException::class) @Throws(IOException::class)
private fun writeObject(out: ObjectOutputStream) { private fun writeObject(out: ObjectOutputStream) {
out.writeObject(cookie!!.name) out.writeObject(cookie!!.name())
out.writeObject(cookie!!.value) out.writeObject(cookie!!.value())
out.writeLong(if (cookie!!.persistent) cookie!!.expiresAt else NON_VALID_EXPIRES_AT) out.writeLong(if (cookie!!.persistent()) cookie!!.expiresAt() else NON_VALID_EXPIRES_AT)
out.writeObject(cookie!!.domain) out.writeObject(cookie!!.domain())
out.writeObject(cookie!!.path) out.writeObject(cookie!!.path())
out.writeBoolean(cookie!!.secure) out.writeBoolean(cookie!!.secure())
out.writeBoolean(cookie!!.httpOnly) out.writeBoolean(cookie!!.httpOnly())
out.writeBoolean(cookie!!.hostOnly) out.writeBoolean(cookie!!.hostOnly())
} }
@Throws(IOException::class, ClassNotFoundException::class) @Throws(IOException::class, ClassNotFoundException::class)

View File

@@ -64,7 +64,7 @@ class SharedPrefsCookiePersistor(private val sharedPreferences: SharedPreference
private companion object { private companion object {
fun createCookieKey(cookie: Cookie): String { 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()
} }
} }

View File

@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.core.parser
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import android.os.Build
import androidx.core.net.toFile import androidx.core.net.toFile
import androidx.core.net.toUri import androidx.core.net.toUri
import org.koin.core.KoinComponent 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.longHashCode
import org.koitharu.kotatsu.utils.ext.readText import org.koitharu.kotatsu.utils.ext.readText
import org.koitharu.kotatsu.utils.ext.safe import org.koitharu.kotatsu.utils.ext.safe
import org.koitharu.kotatsu.utils.ext.sub
import java.io.File import java.io.File
import java.util.* import java.util.*
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
@@ -29,8 +31,11 @@ class LocalMangaRepository : MangaRepository, KoinComponent {
sortOrder: SortOrder?, sortOrder: SortOrder?,
tag: MangaTag? tag: MangaTag?
): List<Manga> { ): List<Manga> {
val files = context.getExternalFilesDirs("manga") val files = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
.flatMap { x -> x?.listFiles(CbzFilter())?.toList().orEmpty() } 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) } } return files.mapNotNull { x -> safe { getFromFile(x) } }
} }

View File

@@ -1,7 +1,7 @@
package org.koitharu.kotatsu.domain package org.koitharu.kotatsu.domain
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.util.Size import android.graphics.Point
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.koin.core.KoinComponent import org.koin.core.KoinComponent
@@ -29,10 +29,10 @@ object MangaUtils : KoinComponent {
.get() .get()
.build() .build()
val size = client.newCall(request).await().use { val size = client.newCall(request).await().use {
getBitmapSize(it.body?.byteStream()) getBitmapSize(it.body()?.byteStream())
} }
return when { return when {
size.width * 2 < size.height -> ReaderMode.WEBTOON size.x * 2 < size.y -> ReaderMode.WEBTOON
else -> ReaderMode.STANDARD else -> ReaderMode.STANDARD
} }
} catch (e: Exception) { } catch (e: Exception) {
@@ -44,7 +44,7 @@ object MangaUtils : KoinComponent {
} }
@JvmStatic @JvmStatic
private fun getBitmapSize(input: InputStream?): Size { private fun getBitmapSize(input: InputStream?): Point {
val options = BitmapFactory.Options().apply { val options = BitmapFactory.Options().apply {
inJustDecodeBounds = true inJustDecodeBounds = true
} }
@@ -52,6 +52,6 @@ object MangaUtils : KoinComponent {
val imageHeight: Int = options.outHeight val imageHeight: Int = options.outHeight
val imageWidth: Int = options.outWidth val imageWidth: Int = options.outWidth
check(imageHeight > 0 && imageWidth > 0) check(imageHeight > 0 && imageWidth > 0)
return Size(imageWidth, imageHeight) return Point(imageWidth, imageHeight)
} }
} }

View File

@@ -47,6 +47,9 @@ class MangaZip(val file: File) {
if (!file.exists()) { if (!file.exists()) {
return return
} }
dir.listFiles()?.forEach {
it?.deleteRecursively()
}
ZipInputStream(file.inputStream()).use { input -> ZipInputStream(file.inputStream()).use { input ->
while (true) { while (true) {
val entry = input.nextEntry ?: return val entry = input.nextEntry ?: return

View File

@@ -1,10 +1,12 @@
package org.koitharu.kotatsu.ui.browser package org.koitharu.kotatsu.ui.browser
import android.graphics.Bitmap import android.graphics.Bitmap
import android.os.Build
import android.webkit.WebResourceRequest import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse import android.webkit.WebResourceResponse
import android.webkit.WebView import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
import androidx.annotation.RequiresApi
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.koin.core.KoinComponent import org.koin.core.KoinComponent
@@ -38,6 +40,7 @@ class BrowserClient(private val callback: BrowserCallback) : WebViewClient(), Ko
return url?.let(::doRequest) return url?.let(::doRequest)
} }
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? { override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? {
return request?.url?.toString()?.let(::doRequest) return request?.url?.toString()?.let(::doRequest)
} }
@@ -47,11 +50,11 @@ class BrowserClient(private val callback: BrowserCallback) : WebViewClient(), Ko
.url(url) .url(url)
.build() .build()
val response = okHttp.newCall(request).execute() val response = okHttp.newCall(request).execute()
val ct = response.body?.contentType() val ct = response.body()?.contentType()
WebResourceResponse( WebResourceResponse(
"${ct?.type}/${ct?.subtype}", "${ct?.type()}/${ct?.subtype()}",
ct?.charset()?.name() ?: "utf-8", ct?.charset()?.name() ?: "utf-8",
response.body?.byteStream() response.body()?.byteStream()
) )
} }
} }

View File

@@ -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 { override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
//TODO remove. Just for testing //TODO remove. Just for testing
if (BuildConfig.DEBUG && keyCode == KeyEvent.KEYCODE_VOLUME_UP) { if (BuildConfig.DEBUG && keyCode == KeyEvent.KEYCODE_VOLUME_UP) {

View File

@@ -1,36 +1,37 @@
package org.koitharu.kotatsu.ui.common package org.koitharu.kotatsu.ui.common
import android.graphics.Color
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.WindowManager
abstract class BaseFullscreenActivity : BaseActivity() { abstract class BaseFullscreenActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) 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() showSystemUI()
} }
protected fun hideSystemUI() { protected fun hideSystemUI() {
window.decorView.systemUiVisibility = ( window.decorView.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION (
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // прячем панель навигации or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN // прячем строку состояния or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 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 // прячем строку состояния
)
}
} }

View File

@@ -2,10 +2,12 @@ package org.koitharu.kotatsu.ui.common.dialog
import android.content.Context import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import android.os.Build
import android.os.Environment import android.os.Environment
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.BaseAdapter import android.widget.BaseAdapter
import androidx.annotation.RequiresApi
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import kotlinx.android.synthetic.main.item_storage.view.* 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 org.koitharu.kotatsu.utils.ext.longHashCode
import java.io.File import java.io.File
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
class StorageSelectDialog private constructor(private val delegate: AlertDialog) : class StorageSelectDialog private constructor(private val delegate: AlertDialog) :
DialogInterface by delegate { DialogInterface by delegate {

View File

@@ -2,7 +2,6 @@ package org.koitharu.kotatsu.ui.common.list
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import java.util.*
class AdapterUpdater<T>(oldList: List<T>, newList: List<T>, getId: (T) -> Long) { class AdapterUpdater<T>(oldList: List<T>, newList: List<T>, getId: (T) -> Long) {
@@ -12,7 +11,7 @@ class AdapterUpdater<T>(oldList: List<T>, newList: List<T>, getId: (T) -> Long)
getId(oldList[oldItemPosition]) == getId(newList[newItemPosition]) getId(oldList[oldItemPosition]) == getId(newList[newItemPosition])
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
Objects.equals(oldList[oldItemPosition], newList[newItemPosition]) oldList[oldItemPosition]?.equals(newList[newItemPosition]) == true
override fun getOldListSize() = oldList.size override fun getOldListSize() = oldList.size

View File

@@ -2,9 +2,10 @@ package org.koitharu.kotatsu.ui.common.list
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import okhttp3.internal.toImmutableList
import org.koin.core.KoinComponent import org.koin.core.KoinComponent
import org.koitharu.kotatsu.utils.ext.replaceWith import org.koitharu.kotatsu.utils.ext.replaceWith
import java.util.*
import kotlin.collections.ArrayList
abstract class BaseRecyclerAdapter<T, E>(private val onItemClickListener: OnRecyclerItemClickListener<T>? = null) : abstract class BaseRecyclerAdapter<T, E>(private val onItemClickListener: OnRecyclerItemClickListener<T>? = null) :
RecyclerView.Adapter<BaseViewHolder<T, E>>(), RecyclerView.Adapter<BaseViewHolder<T, E>>(),
@@ -12,7 +13,8 @@ abstract class BaseRecyclerAdapter<T, E>(private val onItemClickListener: OnRecy
protected val dataSet = ArrayList<T>() //TODO make private protected val dataSet = ArrayList<T>() //TODO make private
val items get() = dataSet.toImmutableList() val items: List<T>
get() = Collections.unmodifiableList(dataSet)
val hasItems get() = dataSet.isNotEmpty() val hasItems get() = dataSet.isNotEmpty()

View File

@@ -44,6 +44,7 @@ class DownloadNotification(private val context: Context) {
fun fillFrom(manga: Manga) { fun fillFrom(manga: Manga) {
builder.setContentTitle(manga.title) builder.setContentTitle(manga.title)
builder.setContentText(context.getString(R.string.manga_downloading_)) builder.setContentText(context.getString(R.string.manga_downloading_))
builder.setTicker(context.getString(R.string.manga_downloading_))
builder.setProgress(1, 0, true) builder.setProgress(1, 0, true)
builder.setSmallIcon(android.R.drawable.stat_sys_download) builder.setSmallIcon(android.R.drawable.stat_sys_download)
builder.setLargeIcon(null) builder.setLargeIcon(null)
@@ -56,7 +57,7 @@ class DownloadNotification(private val context: Context) {
} else { } else {
val intent = DownloadService.getCancelIntent(context, startId) val intent = DownloadService.getCancelIntent(context, startId)
builder.addAction( builder.addAction(
R.drawable.ic_cross, R.drawable.ic_cross_compat,
context.getString(android.R.string.cancel), context.getString(android.R.string.cancel),
PendingIntent.getService( PendingIntent.getService(
context, context,

View File

@@ -80,7 +80,10 @@ class DownloadService : BaseService() {
notification.setCancelId(startId) notification.setCancelId(startId)
startForeground(DownloadNotification.NOTIFICATION_ID, notification()) 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 var output: MangaZip? = null
try { try {
val repo = MangaProviderFactory.create(manga.source) val repo = MangaProviderFactory.create(manga.source)
@@ -146,6 +149,7 @@ class DownloadService : BaseService() {
notification.update() notification.update()
} }
} catch (e: Throwable) { } catch (e: Throwable) {
e.printStackTrace()
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
notification.setError(e) notification.setError(e)
notification.setCancelId(0) notification.setCancelId(0)
@@ -179,7 +183,7 @@ class DownloadService : BaseService() {
okHttp.newCall(request).await().use { response -> okHttp.newCall(request).await().use { response ->
val file = destination.sub("page.tmp") val file = destination.sub("page.tmp")
file.outputStream().use { out -> file.outputStream().use { out ->
response.body!!.byteStream().copyTo(out) response.body()!!.byteStream().copyTo(out)
} }
file file
} }

View File

@@ -56,7 +56,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
navigationView.setNavigationItemSelectedListener(this) navigationView.setNavigationItemSelectedListener(this)
settings.subscribe(this) settings.subscribe(this)
fab.imageTintList = ColorStateList.valueOf(Color.WHITE) fab.supportImageTintList = ColorStateList.valueOf(Color.WHITE)
fab.isVisible = true fab.isVisible = true
fab.setOnClickListener { fab.setOnClickListener {
presenter.openLastReader() presenter.openLastReader()

View File

@@ -160,7 +160,7 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
.show() .show()
} else { } else {
textView_holder.text = e.getDisplayMessage(resources) textView_holder.text = e.getDisplayMessage(resources)
textView_holder.setCompoundDrawablesRelativeWithIntrinsicBounds( textView_holder.setCompoundDrawablesWithIntrinsicBounds(
0, 0,
R.drawable.ic_error_large, R.drawable.ic_error_large,
0, 0,
@@ -221,7 +221,7 @@ abstract class MangaListFragment<E> : BaseFragment(R.layout.fragment_list), Mang
} }
protected open fun setUpEmptyListHolder() { 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) textView_holder.setText(R.string.nothing_found)
} }

View File

@@ -55,7 +55,7 @@ abstract class MangaListSheet<E> : BaseBottomSheet(R.layout.sheet_list), MangaLi
if (dialog !is BottomSheetDialog) { if (dialog !is BottomSheetDialog) {
toolbar.isVisible = true toolbar.isVisible = true
textView_title.isVisible = false 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<E> : BaseBottomSheet(R.layout.sheet_list), MangaLi
if (newState == BottomSheetBehavior.STATE_EXPANDED) { if (newState == BottomSheetBehavior.STATE_EXPANDED) {
toolbar.isVisible = true toolbar.isVisible = true
textView_title.isVisible = false textView_title.isVisible = false
appbar.elevation = elevation // appbar.elevation = elevation
} else { } else {
toolbar.isVisible = false toolbar.isVisible = false
textView_title.isVisible = true textView_title.isVisible = true
appbar.elevation = 0f // appbar.elevation = 0f
} }
} }
}) })

View File

@@ -39,7 +39,7 @@ class FavouritesListFragment : MangaListFragment<Unit>(), MangaListView<Unit> {
override fun setUpEmptyListHolder() { override fun setUpEmptyListHolder() {
textView_holder.setText(R.string.you_have_not_favourites_yet) 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 { companion object {

View File

@@ -33,7 +33,7 @@ class CategoriesActivity : BaseActivity(), OnRecyclerItemClickListener<Favourite
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_categories) setContentView(R.layout.activity_categories)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
fab_add.imageTintList = ColorStateList.valueOf(Color.WHITE) fab_add.supportImageTintList = ColorStateList.valueOf(Color.WHITE)
adapter = CategoriesAdapter(this) adapter = CategoriesAdapter(this)
recyclerView.addItemDecoration(DividerItemDecoration(this, RecyclerView.VERTICAL)) recyclerView.addItemDecoration(DividerItemDecoration(this, RecyclerView.VERTICAL))
recyclerView.adapter = adapter recyclerView.adapter = adapter

View File

@@ -49,7 +49,7 @@ class HistoryListFragment : MangaListFragment<MangaHistory>(), MangaListView<Man
override fun setUpEmptyListHolder() { override fun setUpEmptyListHolder() {
textView_holder.setText(R.string.text_history_holder) textView_holder.setText(R.string.text_history_holder)
textView_holder.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0) textView_holder.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0)
} }
override fun onCreatePopupMenu(inflater: MenuInflater, menu: Menu, data: Manga) { override fun onCreatePopupMenu(inflater: MenuInflater, menu: Menu, data: Manga) {

View File

@@ -60,7 +60,7 @@ class LocalListFragment : MangaListFragment<File>() {
override fun setUpEmptyListHolder() { override fun setUpEmptyListHolder() {
textView_holder.setText(R.string.text_local_holder) 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?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

View File

@@ -51,13 +51,13 @@ class PageLoader : KoinComponent, CoroutineScope, DisposableHandle {
.cacheControl(CacheUtils.CONTROL_DISABLED) .cacheControl(CacheUtils.CONTROL_DISABLED)
.build() .build()
okHttp.newCall(request).await().use { response -> okHttp.newCall(request).await().use { response ->
val body = response.body!! val body = response.body()!!
val type = body.contentType() val type = body.contentType()
check(type?.type == "image") { check(type?.type() == "image") {
"Unexpected content type ${type?.type}/${type?.subtype}" "Unexpected content type ${type?.type()}/${type?.subtype()}"
} }
cache.put(url) { out -> cache.put(url) { out ->
response.body!!.byteStream().copyTo(out) response.body()!!.byteStream().copyTo(out)
} }
} }
} }

View File

@@ -12,7 +12,6 @@ import android.widget.Toast
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.postDelayed import androidx.core.view.postDelayed
import androidx.core.view.updatePadding
import androidx.fragment.app.commit import androidx.fragment.app.commit
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_reader.* 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) 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) view.updatePadding(bottom = insets.systemWindowInsetBottom)
insets insets
} }*/
settings.subscribe(this) settings.subscribe(this)
loadSettings() loadSettings()
@@ -286,6 +285,10 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
setUiIsVisible(!appbar_top.isVisible) setUiIsVisible(!appbar_top.isVisible)
true true
} }
KeyEvent.KEYCODE_MENU -> {
setUiIsVisible(!appbar_top.isVisible)
true
}
else -> super.onKeyDown(keyCode, event) else -> super.onKeyDown(keyCode, event)
} }

View File

@@ -83,7 +83,7 @@ class ReaderPresenter : BasePresenter<ReaderView>() {
val fileName = val fileName =
URLUtil.guessFileName(url, response.contentDisposition, response.mimeType) URLUtil.guessFileName(url, response.contentDisposition, response.mimeType)
MediaStoreCompat.insertImage(resolver, fileName) { MediaStoreCompat.insertImage(resolver, fileName) {
response.body!!.byteStream().copyTo(it) response.body()!!.byteStream().copyTo(it)
} }
} }
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {

View File

@@ -13,14 +13,14 @@ class PageAnimTransformer : ViewPager2.PageTransformer {
position <= 0 -> { // [-1,0] position <= 0 -> { // [-1,0]
alpha = 1f alpha = 1f
translationX = 0f translationX = 0f
translationZ = 0f // translationZ = 0f
scaleX = 1 + FACTOR * position scaleX = 1 + FACTOR * position
scaleY = 1f scaleY = 1f
} }
position <= 1 -> { // (0,1] position <= 1 -> { // (0,1]
alpha = 1f alpha = 1f
translationX = pageWidth * -position translationX = pageWidth * -position
translationZ = -1f // translationZ = -1f
scaleX = 1f scaleX = 1f
scaleY = 1f scaleY = 1f
} }

View File

@@ -40,7 +40,7 @@ class PagesThumbnailsSheet : BaseBottomSheet(R.layout.sheet_pages),
if (dialog !is BottomSheetDialog) { if (dialog !is BottomSheetDialog) {
toolbar.isVisible = true toolbar.isVisible = true
textView_title.isVisible = false textView_title.isVisible = false
appbar.elevation = resources.getDimension(R.dimen.elevation_large) // appbar.elevation = resources.getDimension(R.dimen.elevation_large)
} }
recyclerView.addOnLayoutChangeListener(UiUtils.SpanCountResolver) recyclerView.addOnLayoutChangeListener(UiUtils.SpanCountResolver)
} }
@@ -57,11 +57,11 @@ class PagesThumbnailsSheet : BaseBottomSheet(R.layout.sheet_pages),
if (newState == BottomSheetBehavior.STATE_EXPANDED) { if (newState == BottomSheetBehavior.STATE_EXPANDED) {
toolbar.isVisible = true toolbar.isVisible = true
textView_title.isVisible = false textView_title.isVisible = false
appbar.elevation = elevation // appbar.elevation = elevation
} else { } else {
toolbar.isVisible = false toolbar.isVisible = false
textView_title.isVisible = true textView_title.isVisible = true
appbar.elevation = 0f // appbar.elevation = 0f
} }
} }
}) })

View File

@@ -116,9 +116,8 @@ class AppUpdateService : BaseService() {
private const val CHANNEL_ID = "update" private const val CHANNEL_ID = "update"
private val PERIOD = TimeUnit.HOURS.toMillis(6) private val PERIOD = TimeUnit.HOURS.toMillis(6)
fun isUpdateSupported(context: Context): Boolean { @Suppress("UNUSED_PARAMETER")
return getCertificateSHA1Fingerprint(context) == CERT_SHA1 fun isUpdateSupported(context: Context) = false
}
fun startIfRequired(context: Context) { fun startIfRequired(context: Context) {
if (!isUpdateSupported(context)) { if (!isUpdateSupported(context)) {

View File

@@ -3,8 +3,6 @@ package org.koitharu.kotatsu.ui.settings
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.transition.Slide
import android.view.Gravity
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.commit import androidx.fragment.app.commit
import androidx.preference.Preference import androidx.preference.Preference
@@ -24,7 +22,7 @@ class SettingsActivity : BaseActivity(),
if (supportFragmentManager.findFragmentById(R.id.container) == null) { if (supportFragmentManager.findFragmentById(R.id.container) == null) {
supportFragmentManager.commit { supportFragmentManager.commit {
replace(R.id.container, MainSettingsFragment().also { 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) { private fun openFragment(fragment: Fragment) {
fragment.enterTransition = Slide(Gravity.END) // fragment.enterTransition = Slide(Gravity.END)
fragment.exitTransition = Slide(Gravity.START) // fragment.exitTransition = Slide(Gravity.START)
supportFragmentManager.commit { supportFragmentManager.commit {
replace(R.id.container, fragment) replace(R.id.container, fragment)
addToBackStack(null) addToBackStack(null)

View File

@@ -1,6 +1,7 @@
package org.koitharu.kotatsu.utils package org.koitharu.kotatsu.utils
import android.content.Context import android.content.Context
import android.os.Build
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import okhttp3.Cache import okhttp3.Cache
import okhttp3.CacheControl import okhttp3.CacheControl
@@ -17,8 +18,11 @@ object CacheUtils {
.build() .build()
@JvmStatic @JvmStatic
fun getCacheDirs(context: Context) = (context.externalCacheDirs + context.cacheDir) fun getCacheDirs(context: Context) = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
.filterNotNull() (context.externalCacheDirs + context.cacheDir)
} else {
arrayOf(context.externalCacheDir, context.cacheDir)
}.filterNotNull()
.distinctBy { it.absolutePath } .distinctBy { it.absolutePath }
@JvmStatic @JvmStatic
@@ -35,7 +39,7 @@ object CacheUtils {
@JvmStatic @JvmStatic
fun createHttpCache(context: Context) = Cache( fun createHttpCache(context: Context) = Cache(
directory = (context.externalCacheDir ?: context.cacheDir).sub("http"), (context.externalCacheDir ?: context.cacheDir).sub("http"),
maxSize = FileSizeUtils.mbToBytes(60) FileSizeUtils.mbToBytes(60)
) )
} }

View File

@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.utils.ext
import okhttp3.Response import okhttp3.Response
val Response.mimeType: String? val Response.mimeType: String?
get() = body?.contentType()?.run { "$type/$subtype" } get() = body()?.contentType()?.run { "${type()}/${subtype()}" }
val Response.contentDisposition: String? val Response.contentDisposition: String?
get() = header("Content-Disposition") get() = header("Content-Disposition")

View File

@@ -1,30 +1,30 @@
package org.koitharu.kotatsu.utils.ext package org.koitharu.kotatsu.utils.ext
import okhttp3.Response import okhttp3.Response
import okhttp3.internal.closeQuietly import okhttp3.internal.Util.closeQuietly
import org.json.JSONObject import org.json.JSONObject
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
fun Response.parseHtml(): Document { fun Response.parseHtml(): Document {
try { try {
val stream = body?.byteStream() ?: throw NullPointerException("Response body is null") val stream = body()?.byteStream() ?: throw NullPointerException("Response body is null")
val charset = body!!.contentType()?.charset()?.name() val charset = body()!!.contentType()?.charset()?.name()
return Jsoup.parse( return Jsoup.parse(
stream, stream,
charset, charset,
request.url.toString() request().url().toString()
) )
} finally { } finally {
closeQuietly() closeQuietly(this)
} }
} }
fun Response.parseJson(): JSONObject { fun Response.parseJson(): JSONObject {
try { try {
val string = body?.string() ?: throw NullPointerException("Response body is null") val string = body()?.string() ?: throw NullPointerException("Response body is null")
return JSONObject(string) return JSONObject(string)
} finally { } finally {
closeQuietly() closeQuietly(this)
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

View File

@@ -2,7 +2,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:shape="rectangle">
<corners android:radius="5dp" /> <corners android:radius="5dp" />
<solid android:color="?colorAccent" /> <solid android:color="@color/red_accent" />
<padding <padding
android:bottom="2dp" android:bottom="2dp"
android:left="2dp" android:left="2dp"

View File

@@ -2,7 +2,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:shape="rectangle">
<corners android:radius="5dp" /> <corners android:radius="5dp" />
<solid android:color="?android:textColorTertiary" /> <solid android:color="@android:color/darker_gray" />
<padding <padding
android:bottom="2dp" android:bottom="2dp"
android:left="2dp" android:left="2dp"

View File

@@ -4,7 +4,7 @@
<corners android:radius="5dp" /> <corners android:radius="5dp" />
<stroke <stroke
android:width="2dp" android:width="2dp"
android:color="?android:textColorTertiary" /> android:color="@android:color/darker_gray" />
<padding <padding
android:bottom="2dp" android:bottom="2dp"
android:left="2dp" android:left="2dp"

View File

@@ -4,7 +4,7 @@
<corners android:radius="5dp" /> <corners android:radius="5dp" />
<stroke <stroke
android:width="2dp" android:width="2dp"
android:color="?android:colorAccent" /> android:color="@color/red_accent" />
<padding <padding
android:bottom="2dp" android:bottom="2dp"
android:left="2dp" android:left="2dp"

View File

@@ -3,7 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:tint="?android:textColorPrimary" android:tint="@android:color/darker_gray"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path <path

View File

@@ -2,7 +2,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12dp" android:width="12dp"
android:height="12dp" android:height="12dp"
android:tint="?android:textColorPrimary" android:tint="?attr/android:textColorPrimary"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path <path

View File

@@ -3,7 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12dp" android:width="12dp"
android:height="12dp" android:height="12dp"
android:tint="?android:textColorPrimary" android:tint="?attr/android:textColorPrimary"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">
<path <path

View File

@@ -2,7 +2,7 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:tint="?android:textColorPrimary" android:tint="?attr/android:textColorPrimary"
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path

View File

@@ -1,7 +1,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="60dp" android:width="60dp"
android:height="60dp" android:height="60dp"
android:tint="?android:textColorTertiary" android:tint="?attr/android:textColorTertiary"
android:viewportWidth="60" android:viewportWidth="60"
android:viewportHeight="60"> android:viewportHeight="60">
<path <path

View File

@@ -2,7 +2,7 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:tint="?android:colorControlNormal" android:tint="?attr/android:textColorPrimary"
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path

View File

@@ -8,6 +8,6 @@
android:fillColor="?attr/colorAccent" android:fillColor="?attr/colorAccent"
android:pathData="M12,15.4l-3.76,2.27l1,-4.28l-3.32,-2.88l4.38,-0.38l1.7,-4.03l1.71,4.04l4.38,0.38l-3.32,2.88l1,4.28z" /> android:pathData="M12,15.4l-3.76,2.27l1,-4.28l-3.32,-2.88l4.38,-0.38l1.7,-4.03l1.71,4.04l4.38,0.38l-3.32,2.88l1,4.28z" />
<path <path
android:fillColor="?android:textColorPrimary" android:fillColor="?attr/android:textColorPrimary"
android:pathData="M22,9.24l-7.19,-0.62L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27L18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27l1,-4.28l-3.32,-2.88l4.38,-0.38L12,6.1l1.71,4.04l4.38,0.38l-3.32,2.88l1,4.28L12,15.4z" /> android:pathData="M22,9.24l-7.19,-0.62L12,2L9.19,8.63L2,9.24l5.46,4.73L5.82,21L12,17.27L18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27l1,-4.28l-3.32,-2.88l4.38,-0.38L12,6.1l1.71,4.04l4.38,0.38l-3.32,2.88l1,4.28L12,15.4z" />
</vector> </vector>

View File

@@ -2,7 +2,7 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:tint="?android:textColorPrimary" android:tint="?attr/android:textColorPrimary"
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path

View File

@@ -20,7 +20,8 @@
app:layout_constraintDimensionRatio="13:18" app:layout_constraintDimensionRatio="13:18"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.3" /> app:layout_constraintWidth_percent="0.3"
android:layout_marginLeft="8dp" />
<TextView <TextView
android:id="@+id/textView_title" android:id="@+id/textView_title"
@@ -73,7 +74,8 @@
app:icon="@drawable/ic_read" app:icon="@drawable/ic_read"
app:iconPadding="12dp" app:iconPadding="12dp"
app:layout_constraintEnd_toEndOf="@id/textView_title" app:layout_constraintEnd_toEndOf="@id/textView_title"
app:layout_constraintTop_toBottomOf="@id/ratingBar" /> app:layout_constraintTop_toBottomOf="@id/ratingBar"
android:layout_marginRight="4dp" />
<ImageView <ImageView
android:id="@+id/imageView_favourite" android:id="@+id/imageView_favourite"
@@ -83,12 +85,13 @@
android:background="?selectableItemBackgroundBorderless" android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/add_to_favourites" android:contentDescription="@string/add_to_favourites"
android:scaleType="center" android:scaleType="center"
android:src="@drawable/ic_tag_heart_outline" app:srcCompat="@drawable/ic_tag_heart_outline"
app:layout_constraintBottom_toBottomOf="@id/button_read" app:layout_constraintBottom_toBottomOf="@id/button_read"
app:layout_constraintDimensionRatio="1:1" app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toStartOf="@id/button_read" app:layout_constraintEnd_toStartOf="@id/button_read"
app:layout_constraintTop_toTopOf="@id/button_read" app:layout_constraintTop_toTopOf="@id/button_read"
app:tint="?colorAccent" /> app:tint="?colorAccent"
android:layout_marginRight="4dp" />
<View <View
android:id="@+id/divider_top" android:id="@+id/divider_top"

View File

@@ -50,7 +50,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="16dp" android:layout_margin="16dp"
android:contentDescription="@string/add_new_category" android:contentDescription="@string/add_new_category"
android:src="@drawable/ic_add" app:srcCompat="@drawable/ic_add"
app:backgroundTint="?colorAccent" app:backgroundTint="?colorAccent"
app:fabSize="normal" app:fabSize="normal"
app:layout_anchor="@id/recyclerView" app:layout_anchor="@id/recyclerView"

View File

@@ -13,7 +13,9 @@
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"> android:layout_marginBottom="2dp"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true">
<TextView <TextView
android:id="@+id/textView" android:id="@+id/textView"
@@ -31,7 +33,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_toStartOf="@id/button_restart" android:layout_toStartOf="@id/button_restart"
android:text="@string/close" /> android:text="@string/close"
android:layout_toLeftOf="@id/button_restart" />
<Button <Button
android:id="@+id/button_restart" android:id="@+id/button_restart"
@@ -40,6 +43,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:text="@string/restart" /> android:text="@string/restart"
android:layout_alignParentRight="true" />
</RelativeLayout> </RelativeLayout>

View File

@@ -39,7 +39,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="16dp" android:layout_margin="16dp"
android:src="@drawable/ic_read_fill" app:srcCompat="@drawable/ic_read_fill"
android:visibility="gone" android:visibility="gone"
app:fabSize="normal" app:fabSize="normal"
app:backgroundTint="?colorAccent" app:backgroundTint="?colorAccent"

View File

@@ -5,7 +5,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingStart="?android:listPreferredItemPaddingStart" android:paddingStart="?android:listPreferredItemPaddingStart"
android:paddingEnd="?android:listPreferredItemPaddingEnd"> android:paddingEnd="?android:listPreferredItemPaddingEnd"
android:paddingRight="?android:listPreferredItemPaddingRight"
android:paddingLeft="?android:listPreferredItemPaddingLeft">
<com.google.android.material.checkbox.MaterialCheckBox <com.google.android.material.checkbox.MaterialCheckBox
android:id="@android:id/checkbox" android:id="@android:id/checkbox"

View File

@@ -40,12 +40,14 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?android:listPreferredItemHeightSmall" android:layout_height="?android:listPreferredItemHeightSmall"
android:background="?android:selectableItemBackground" android:background="?android:selectableItemBackground"
android:drawableEnd="@drawable/ic_add"
android:gravity="start|center_vertical" android:gravity="start|center_vertical"
android:paddingStart="?android:listPreferredItemPaddingStart" android:paddingStart="?android:listPreferredItemPaddingStart"
android:paddingEnd="?android:listPreferredItemPaddingEnd" android:paddingEnd="?android:listPreferredItemPaddingEnd"
android:text="@string/add_new_category" android:text="@string/add_new_category"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:textColor="?android:textColorPrimary" /> android:textColor="?android:textColorPrimary"
app:drawableEndCompat="@drawable/ic_add"
android:paddingRight="?android:listPreferredItemPaddingRight"
android:paddingLeft="?android:listPreferredItemPaddingLeft" />
</LinearLayout> </LinearLayout>

View File

@@ -20,7 +20,8 @@
app:layout_constraintDimensionRatio="13:18" app:layout_constraintDimensionRatio="13:18"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.3" /> app:layout_constraintWidth_percent="0.3"
android:layout_marginLeft="8dp" />
<TextView <TextView
android:id="@+id/textView_title" android:id="@+id/textView_title"
@@ -76,7 +77,8 @@
app:layout_constraintBottom_toBottomOf="@id/imageView_cover" app:layout_constraintBottom_toBottomOf="@id/imageView_cover"
app:layout_constraintEnd_toEndOf="@id/textView_title" app:layout_constraintEnd_toEndOf="@id/textView_title"
app:layout_constraintTop_toBottomOf="@id/ratingBar" app:layout_constraintTop_toBottomOf="@id/ratingBar"
app:layout_constraintVertical_bias="1" /> app:layout_constraintVertical_bias="1"
android:layout_marginRight="4dp" />
<ImageView <ImageView
android:id="@+id/imageView_favourite" android:id="@+id/imageView_favourite"
@@ -86,14 +88,15 @@
android:background="?selectableItemBackgroundBorderless" android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/add_to_favourites" android:contentDescription="@string/add_to_favourites"
android:scaleType="center" android:scaleType="center"
android:src="@drawable/ic_tag_heart_outline" app:srcCompat="@drawable/ic_tag_heart_outline"
app:layout_constraintBottom_toBottomOf="@id/button_read" app:layout_constraintBottom_toBottomOf="@id/button_read"
app:layout_constraintDimensionRatio="1:1" app:layout_constraintDimensionRatio="1:1"
app:layout_constraintHorizontal_bias="1" app:layout_constraintHorizontal_bias="1"
app:layout_constraintEnd_toStartOf="@id/button_read" app:layout_constraintEnd_toStartOf="@id/button_read"
app:layout_constraintTop_toTopOf="@id/button_read" app:layout_constraintTop_toTopOf="@id/button_read"
app:layout_constraintStart_toStartOf="@id/textView_title" app:layout_constraintStart_toStartOf="@id/textView_title"
app:tint="?colorAccent" /> app:tint="?colorAccent"
android:layout_marginRight="4dp" />
<androidx.constraintlayout.widget.Barrier <androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_title" android:id="@+id/barrier_title"

View File

@@ -11,4 +11,6 @@
android:paddingEnd="?android:listPreferredItemPaddingEnd" android:paddingEnd="?android:listPreferredItemPaddingEnd"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
tools:text="@tools:sample/lorem[4]" /> tools:text="@tools:sample/lorem[4]"
android:paddingLeft="?android:listPreferredItemPaddingLeft"
android:paddingRight="?android:listPreferredItemPaddingRight" />

View File

@@ -13,4 +13,6 @@
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
tools:checked="true" tools:checked="true"
tools:text="@tools:sample/lorem[4]" /> tools:text="@tools:sample/lorem[4]"
android:paddingLeft="?android:listPreferredItemPaddingLeft"
android:paddingRight="?android:listPreferredItemPaddingRight" />

View File

@@ -28,6 +28,7 @@
android:maxLines="2" android:maxLines="2"
android:text="?android:textColorPrimary" android:text="?android:textColorPrimary"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" android:textAppearance="@style/TextAppearance.AppCompat.Body1"
tools:text="@tools:sample/lorem[15]" /> tools:text="@tools:sample/lorem[15]"
android:layout_marginLeft="10dp" />
</LinearLayout> </LinearLayout>

View File

@@ -2,6 +2,7 @@
<CheckedTextView <CheckedTextView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/radio" android:id="@+id/radio"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?android:listPreferredItemHeightSmall" android:layout_height="?android:listPreferredItemHeightSmall"
@@ -11,4 +12,7 @@
android:gravity="center_vertical|start" android:gravity="center_vertical|start"
android:paddingStart="?android:listPreferredItemPaddingStart" android:paddingStart="?android:listPreferredItemPaddingStart"
android:paddingEnd="?android:listPreferredItemPaddingEnd" android:paddingEnd="?android:listPreferredItemPaddingEnd"
tools:text="@tools:sample/full_names" /> tools:text="@tools:sample/full_names"
android:drawableLeft="?android:listChoiceIndicatorSingle"
android:paddingLeft="?android:listPreferredItemPaddingLeft"
android:paddingRight="?android:listPreferredItemPaddingRight" />

View File

@@ -12,4 +12,6 @@
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2" android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textColor="?android:textColorSecondary" android:textColor="?android:textColorSecondary"
android:textStyle="bold" android:textStyle="bold"
tools:text="@tools:sample/lorem[2]" /> tools:text="@tools:sample/lorem[2]"
android:paddingLeft="?android:listPreferredItemPaddingLeft"
android:paddingRight="?android:listPreferredItemPaddingRight" />

View File

@@ -8,7 +8,7 @@
app:cardBackgroundColor="?android:windowBackground" app:cardBackgroundColor="?android:windowBackground"
app:cardElevation="0dp" app:cardElevation="0dp"
app:cardMaxElevation="0dp" app:cardMaxElevation="0dp"
app:strokeColor="?android:colorControlNormal" app:strokeColor="?attr/colorControlNormal"
app:strokeWidth="1px"> app:strokeWidth="1px">
<LinearLayout <LinearLayout

View File

@@ -8,7 +8,7 @@
app:cardBackgroundColor="?android:windowBackground" app:cardBackgroundColor="?android:windowBackground"
app:cardElevation="0dp" app:cardElevation="0dp"
app:cardMaxElevation="0dp" app:cardMaxElevation="0dp"
app:strokeColor="?android:colorControlNormal" app:strokeColor="?attr/colorControlNormal"
app:strokeWidth="1px"> app:strokeWidth="1px">
<LinearLayout <LinearLayout
@@ -89,10 +89,10 @@
android:id="@+id/textView_rating" android:id="@+id/textView_rating"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_star_rating"
android:drawablePadding="4dp" android:drawablePadding="4dp"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2" android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
tools:text="10/10" /> tools:text="10/10"
app:drawableStartCompat="@drawable/ic_star_rating" />
</LinearLayout> </LinearLayout>

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:background="?android:windowBackground" android:background="?android:windowBackground"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -33,11 +34,11 @@
android:id="@+id/textView_error" android:id="@+id/textView_error"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_error_large"
android:drawablePadding="12dp" android:drawablePadding="12dp"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:text="@tools:sample/lorem[6]" /> tools:text="@tools:sample/lorem[6]"
app:drawableTopCompat="@drawable/ic_error_large" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/button_retry" android:id="@+id/button_retry"

View File

@@ -34,11 +34,11 @@
android:id="@+id/textView_error" android:id="@+id/textView_error"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:drawableTop="@drawable/ic_error_large"
android:drawablePadding="12dp" android:drawablePadding="12dp"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:text="@tools:sample/lorem[6]" /> tools:text="@tools:sample/lorem[6]"
app:drawableTopCompat="@drawable/ic_error_large" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/button_retry" android:id="@+id/button_retry"

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<TextView <TextView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?listPreferredItemHeightSmall" android:layout_height="?listPreferredItemHeightSmall"
android:background="?selectableItemBackground" android:background="?selectableItemBackground"
android:drawableStart="@drawable/ic_history"
android:drawablePadding="20dp" android:drawablePadding="20dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:paddingStart="?listPreferredItemPaddingStart" android:paddingStart="?listPreferredItemPaddingStart"
@@ -13,4 +13,7 @@
android:textAppearance="?textAppearanceListItemSmall" android:textAppearance="?textAppearanceListItemSmall"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
android:theme="@style/AppPopupTheme" android:theme="@style/AppPopupTheme"
tools:text="@tools:sample/full_names" /> tools:text="@tools:sample/full_names"
app:drawableStartCompat="@drawable/ic_history"
android:paddingLeft="?listPreferredItemPaddingLeft"
android:paddingRight="?listPreferredItemPaddingRight" />

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?android:listPreferredItemHeightSmall" android:layout_height="?android:listPreferredItemHeightSmall"
@@ -14,7 +15,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="?listPreferredItemPaddingStart" android:padding="?listPreferredItemPaddingStart"
android:scaleType="center" android:scaleType="center"
android:src="@drawable/ic_reorder_handle" /> app:srcCompat="@drawable/ic_reorder_handle" />
<TextView <TextView
android:id="@+id/textView_title" android:id="@+id/textView_title"
@@ -44,6 +45,6 @@
android:background="?selectableItemBackgroundBorderless" android:background="?selectableItemBackgroundBorderless"
android:padding="?listPreferredItemPaddingEnd" android:padding="?listPreferredItemPaddingEnd"
android:scaleType="center" android:scaleType="center"
android:src="@drawable/ic_settings" /> app:srcCompat="@drawable/ic_settings" />
</LinearLayout> </LinearLayout>

View File

@@ -9,7 +9,9 @@
android:paddingEnd="?listPreferredItemPaddingEnd" android:paddingEnd="?listPreferredItemPaddingEnd"
android:gravity="center_vertical" android:gravity="center_vertical"
android:background="?selectableItemBackground" android:background="?selectableItemBackground"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:paddingLeft="?listPreferredItemPaddingLeft"
android:paddingRight="?listPreferredItemPaddingRight">
<TextView <TextView
android:id="@+id/textView_title" android:id="@+id/textView_title"

View File

@@ -1,15 +1,17 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout <RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="92dp"> android:layout_height="92dp">
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:src="@drawable/ic_launcher_foreground" app:srcCompat="@drawable/ic_launcher_foreground"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_centerVertical="true" /> android:layout_centerVertical="true"
android:layout_alignParentLeft="true" />
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -17,6 +19,8 @@
android:background="?android:listDivider" android:background="?android:listDivider"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true" /> android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true" />
</RelativeLayout> </RelativeLayout>

View File

@@ -2,7 +2,7 @@
<appwidget-provider <appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/widget_recent" android:initialLayout="@layout/widget_recent"
android:minWidth="40dp" android:minWidth="110dp"
android:minHeight="110dp" android:minHeight="110dp"
android:minResizeWidth="40dp" android:minResizeWidth="40dp"
android:minResizeHeight="40dp" android:minResizeHeight="40dp"