Cleanup extensions
This commit is contained in:
@@ -2,8 +2,8 @@ package org.koitharu.kotatsu.utils
|
||||
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.R as materialR
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
|
||||
open class BottomSheetToolbarController(
|
||||
protected val toolbar: Toolbar,
|
||||
@@ -17,7 +17,5 @@ open class BottomSheetToolbarController(
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSlide(bottomSheet: View, slideOffset: Float) {
|
||||
|
||||
}
|
||||
override fun onSlide(bottomSheet: View, slideOffset: Float) = Unit
|
||||
}
|
||||
@@ -32,4 +32,4 @@ enum class FileSize(private val multiplier: Int) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,10 @@ import android.view.GestureDetector
|
||||
import android.view.MotionEvent
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class GridTouchHelper(context: Context, private val listener: OnGridTouchListener) :
|
||||
GestureDetector.SimpleOnGestureListener() {
|
||||
class GridTouchHelper(
|
||||
context: Context,
|
||||
private val listener: OnGridTouchListener
|
||||
) : GestureDetector.SimpleOnGestureListener() {
|
||||
|
||||
private val detector = GestureDetector(context, this)
|
||||
private val width = context.resources.displayMetrics.widthPixels
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils
|
||||
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
class SelectionController {
|
||||
|
||||
private val state = MutableStateFlow(emptySet<Int>())
|
||||
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils
|
||||
|
||||
class WordSet(private vararg val words: String) {
|
||||
|
||||
fun anyWordIn(dateString: String): Boolean = words.any {
|
||||
dateString.contains(it, ignoreCase = true)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +1,14 @@
|
||||
package org.koitharu.kotatsu.utils.ext
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.util.Log
|
||||
import java.io.FileNotFoundException
|
||||
import java.net.SocketTimeoutException
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
|
||||
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
|
||||
import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException
|
||||
import org.koitharu.kotatsu.core.exceptions.WrongPasswordException
|
||||
import org.koitharu.kotatsu.parsers.exception.AuthRequiredException
|
||||
import org.koitharu.kotatsu.parsers.util.format
|
||||
import java.io.FileNotFoundException
|
||||
import java.net.SocketTimeoutException
|
||||
|
||||
fun Throwable.getDisplayMessage(resources: Resources) = when (this) {
|
||||
is AuthRequiredException -> resources.getString(R.string.auth_required)
|
||||
@@ -22,12 +20,4 @@ fun Throwable.getDisplayMessage(resources: Resources) = when (this) {
|
||||
is SocketTimeoutException -> resources.getString(R.string.network_error)
|
||||
is WrongPasswordException -> resources.getString(R.string.wrong_password)
|
||||
else -> localizedMessage ?: resources.getString(R.string.error_occurred)
|
||||
}
|
||||
|
||||
inline fun <T> measured(tag: String, block: () -> T): T {
|
||||
val time = System.currentTimeMillis()
|
||||
val res = block()
|
||||
val spent = System.currentTimeMillis() - time
|
||||
Log.d("measured", "$tag ${spent.format(1)} ms")
|
||||
return res
|
||||
}
|
||||
@@ -3,10 +3,8 @@ package org.koitharu.kotatsu.utils.ext
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
val IgnoreErrors
|
||||
get() = CoroutineExceptionHandler { _, e ->
|
||||
|
||||
@@ -15,6 +15,6 @@ fun Date.formatRelative(minResolution: Long): CharSequence = DateUtils.getRelati
|
||||
|
||||
fun Date.daysDiff(other: Long): Int {
|
||||
val thisDay = time / TimeUnit.DAYS.toMillis(1L)
|
||||
val otherDay = other/ TimeUnit.DAYS.toMillis(1L)
|
||||
val otherDay = other / TimeUnit.DAYS.toMillis(1L)
|
||||
return (thisDay - otherDay).toInt()
|
||||
}
|
||||
@@ -26,11 +26,12 @@ fun <T : Parcelable> Fragment.parcelableArgument(name: String): Lazy<T> {
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : Serializable> Fragment.serializableArgument(name: String): Lazy<T> {
|
||||
fun <T : Serializable> Fragment.serializableArgument(name: String): Lazy<T> {
|
||||
return lazy(LazyThreadSafetyMode.NONE) {
|
||||
requireNotNull(arguments?.getSerializable(name) as? T) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
requireNotNull(arguments?.getSerializable(name)) {
|
||||
"No argument $name passed into ${javaClass.simpleName}"
|
||||
}
|
||||
} as T
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.liveData
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.koitharu.kotatsu.utils.BufferedObserver
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.koitharu.kotatsu.utils.BufferedObserver
|
||||
|
||||
fun <T> LiveData<T?>.observeNotNull(owner: LifecycleOwner, observer: Observer<T>) {
|
||||
this.observe(owner) {
|
||||
|
||||
@@ -9,17 +9,17 @@ fun ListPreference.setDefaultValueCompat(defaultValue: String) {
|
||||
}
|
||||
}
|
||||
|
||||
fun <E: Enum<E>> SharedPreferences.getEnumValue(key: String, enumClass: Class<E>): E? {
|
||||
fun <E : Enum<E>> SharedPreferences.getEnumValue(key: String, enumClass: Class<E>): E? {
|
||||
val stringValue = getString(key, null) ?: return null
|
||||
return enumClass.enumConstants?.find {
|
||||
it.name == stringValue
|
||||
}
|
||||
}
|
||||
|
||||
fun <E: Enum<E>> SharedPreferences.getEnumValue(key: String, defaultValue: E): E {
|
||||
fun <E : Enum<E>> SharedPreferences.getEnumValue(key: String, defaultValue: E): E {
|
||||
return getEnumValue(key, defaultValue.javaClass) ?: defaultValue
|
||||
}
|
||||
|
||||
fun <E: Enum<E>> SharedPreferences.Editor.putEnumValue(key: String, value: E?) {
|
||||
fun <E : Enum<E>> SharedPreferences.Editor.putEnumValue(key: String, value: E?) {
|
||||
putString(key, value?.name)
|
||||
}
|
||||
@@ -5,12 +5,11 @@ import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.res.use
|
||||
import androidx.core.view.isGone
|
||||
|
||||
var TextView.textAndVisible: CharSequence?
|
||||
inline get() = text?.takeIf { visibility == View.VISIBLE }
|
||||
inline set(value) {
|
||||
get() = text?.takeIf { visibility == View.VISIBLE }
|
||||
set(value) {
|
||||
text = value
|
||||
isGone = value.isNullOrEmpty()
|
||||
}
|
||||
@@ -40,8 +39,5 @@ fun TextView.setTextAndVisible(@StringRes textResId: Int) {
|
||||
}
|
||||
|
||||
fun TextView.setTextColorAttr(@AttrRes attrResId: Int) {
|
||||
val colors = context.obtainStyledAttributes(intArrayOf(attrResId)).use {
|
||||
it.getColorStateList(0)
|
||||
}
|
||||
setTextColor(colors)
|
||||
setTextColor(context.getThemeColorStateList(attrResId))
|
||||
}
|
||||
@@ -4,20 +4,24 @@ import android.content.Context
|
||||
import android.graphics.Color
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.Px
|
||||
import androidx.core.content.res.use
|
||||
|
||||
@Px
|
||||
fun Context.getThemeDimen(@AttrRes resId: Int) = obtainStyledAttributes(intArrayOf(resId)).use {
|
||||
it.getDimension(0, 0f)
|
||||
}
|
||||
|
||||
fun Context.getThemeDrawable(@AttrRes resId: Int) = obtainStyledAttributes(intArrayOf(resId)).use {
|
||||
fun Context.getThemeDrawable(
|
||||
@AttrRes resId: Int,
|
||||
) = obtainStyledAttributes(intArrayOf(resId)).use {
|
||||
it.getDrawable(0)
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
fun Context.getThemeColor(@AttrRes resId: Int, @ColorInt default: Int = Color.TRANSPARENT) =
|
||||
obtainStyledAttributes(intArrayOf(resId)).use {
|
||||
it.getColor(0, default)
|
||||
}
|
||||
fun Context.getThemeColor(
|
||||
@AttrRes resId: Int,
|
||||
@ColorInt default: Int = Color.TRANSPARENT
|
||||
) = obtainStyledAttributes(intArrayOf(resId)).use {
|
||||
it.getColor(0, default)
|
||||
}
|
||||
|
||||
fun Context.getThemeColorStateList(
|
||||
@AttrRes resId: Int,
|
||||
) = obtainStyledAttributes(intArrayOf(resId)).use {
|
||||
it.getColorStateList(0)
|
||||
}
|
||||
@@ -2,20 +2,15 @@ package org.koitharu.kotatsu.utils.ext
|
||||
|
||||
import android.app.Activity
|
||||
import android.graphics.Rect
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.annotation.MenuRes
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.view.children
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.google.android.material.slider.Slider
|
||||
import com.hannesdorfmann.adapterdelegates4.dsl.AdapterDelegateViewBindingViewHolder
|
||||
import com.hannesdorfmann.adapterdelegates4.dsl.AdapterDelegateViewHolder
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
fun View.hideKeyboard() {
|
||||
@@ -28,19 +23,15 @@ fun View.showKeyboard() {
|
||||
imm.showSoftInput(this, 0)
|
||||
}
|
||||
|
||||
inline fun <reified T : View> ViewGroup.inflate(@LayoutRes resId: Int) =
|
||||
LayoutInflater.from(context).inflate(resId, this, false) as T
|
||||
|
||||
val RecyclerView.hasItems: Boolean
|
||||
get() = (adapter?.itemCount ?: 0) > 0
|
||||
|
||||
fun RecyclerView.clearItemDecorations() {
|
||||
suppressLayout(true)
|
||||
while (itemDecorationCount > 0) {
|
||||
removeItemDecorationAt(0)
|
||||
}
|
||||
suppressLayout(false)
|
||||
}
|
||||
|
||||
var RecyclerView.firstItem: Int
|
||||
var RecyclerView.firstVisibleItemPosition: Int
|
||||
get() = (layoutManager as? LinearLayoutManager)?.findFirstVisibleItemPosition()
|
||||
?: RecyclerView.NO_POSITION
|
||||
set(value) {
|
||||
@@ -49,18 +40,6 @@ var RecyclerView.firstItem: Int
|
||||
}
|
||||
}
|
||||
|
||||
inline fun View.showPopupMenu(
|
||||
@MenuRes menuRes: Int,
|
||||
onPrepare: (Menu) -> Unit = {},
|
||||
onItemClick: PopupMenu.OnMenuItemClickListener,
|
||||
) {
|
||||
val menu = PopupMenu(context, this)
|
||||
menu.inflate(menuRes)
|
||||
menu.setOnMenuItemClickListener(onItemClick)
|
||||
onPrepare(menu.menu)
|
||||
menu.show()
|
||||
}
|
||||
|
||||
fun View.hasGlobalPoint(x: Int, y: Int): Boolean {
|
||||
if (visibility != View.VISIBLE) {
|
||||
return false
|
||||
@@ -97,7 +76,7 @@ inline fun ViewPager2.doOnPageChanged(crossinline callback: (Int) -> Unit) {
|
||||
}
|
||||
|
||||
val ViewPager2.recyclerView: RecyclerView?
|
||||
inline get() = children.find { it is RecyclerView } as? RecyclerView
|
||||
get() = children.firstNotNullOfOrNull { it as? RecyclerView }
|
||||
|
||||
fun View.resetTransformations() {
|
||||
alpha = 1f
|
||||
@@ -106,6 +85,7 @@ fun View.resetTransformations() {
|
||||
translationZ = 0f
|
||||
scaleX = 1f
|
||||
scaleY = 1f
|
||||
rotation = 0f
|
||||
rotationX = 0f
|
||||
rotationY = 0f
|
||||
}
|
||||
@@ -133,8 +113,17 @@ fun RecyclerView.findCenterViewPosition(): Int {
|
||||
return getChildAdapterPosition(view)
|
||||
}
|
||||
|
||||
inline fun <reified T> RecyclerView.ViewHolder.getItem(): T? {
|
||||
return ((this as? AdapterDelegateViewBindingViewHolder<*, *>)?.item as? T)
|
||||
fun <T> RecyclerView.ViewHolder.getItem(clazz: Class<T>): T? {
|
||||
val rawItem = when (this) {
|
||||
is AdapterDelegateViewBindingViewHolder<*, *> -> item
|
||||
is AdapterDelegateViewHolder<*> -> item
|
||||
else -> null
|
||||
} ?: return null
|
||||
return if (clazz.isAssignableFrom(rawItem.javaClass)) {
|
||||
clazz.cast(rawItem)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun Slider.setValueRounded(newValue: Float) {
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
package org.koitharu.kotatsu.utils.progress
|
||||
|
||||
import android.content.Context
|
||||
import com.google.android.material.slider.LabelFormatter
|
||||
import org.koitharu.kotatsu.R
|
||||
|
||||
class IntPercentLabelFormatter : LabelFormatter {
|
||||
override fun getFormattedValue(value: Float) = "%d%%".format(value.toInt())
|
||||
class IntPercentLabelFormatter(context: Context) : LabelFormatter {
|
||||
|
||||
private val pattern = context.getString(R.string.percent_string_pattern)
|
||||
|
||||
override fun getFormattedValue(value: Float) = pattern.format(value.toInt().toString())
|
||||
}
|
||||
Reference in New Issue
Block a user