Cleanup extensions

This commit is contained in:
Koitharu
2022-04-15 09:09:40 +03:00
parent 9c9a389aa5
commit 5e82c75893
29 changed files with 119 additions and 145 deletions

View File

@@ -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
}

View File

@@ -32,4 +32,4 @@ enum class FileSize(private val multiplier: Int) {
}
}
}
}
}

View File

@@ -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

View File

@@ -1,10 +0,0 @@
package org.koitharu.kotatsu.utils
import kotlinx.coroutines.flow.MutableStateFlow
class SelectionController {
private val state = MutableStateFlow(emptySet<Int>())
}

View File

@@ -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)
}
}

View File

@@ -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
}

View File

@@ -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 ->

View File

@@ -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()
}

View File

@@ -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
}
}

View File

@@ -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) {

View File

@@ -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)
}

View File

@@ -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))
}

View File

@@ -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)
}

View File

@@ -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) {

View File

@@ -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())
}