Merge branch 'devel' into feature/shikimori
This commit is contained in:
@@ -10,7 +10,7 @@ import androidx.lifecycle.LifecycleOwner
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
class LifecycleAwareServiceConnection private constructor(
|
||||
class LifecycleAwareServiceConnection(
|
||||
private val host: Activity,
|
||||
) : ServiceConnection, DefaultLifecycleObserver {
|
||||
|
||||
@@ -31,19 +31,15 @@ class LifecycleAwareServiceConnection private constructor(
|
||||
super.onDestroy(owner)
|
||||
host.unbindService(this)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun bindService(
|
||||
host: Activity,
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
service: Intent,
|
||||
flags: Int,
|
||||
): LifecycleAwareServiceConnection {
|
||||
val connection = LifecycleAwareServiceConnection(host)
|
||||
host.bindService(service, connection, flags)
|
||||
lifecycleOwner.lifecycle.addObserver(connection)
|
||||
return connection
|
||||
}
|
||||
}
|
||||
fun Activity.bindServiceWithLifecycle(
|
||||
owner: LifecycleOwner,
|
||||
service: Intent,
|
||||
flags: Int
|
||||
): LifecycleAwareServiceConnection {
|
||||
val connection = LifecycleAwareServiceConnection(this)
|
||||
bindService(service, connection, flags)
|
||||
owner.lifecycle.addObserver(connection)
|
||||
return connection
|
||||
}
|
||||
@@ -10,14 +10,18 @@ import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.core.app.ActivityOptionsCompat
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.coroutineScope
|
||||
import androidx.work.CoroutineWorker
|
||||
import kotlin.coroutines.resume
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.channels.trySendBlocking
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
|
||||
val Context.connectivityManager: ConnectivityManager
|
||||
@@ -81,4 +85,11 @@ fun <T> SharedPreferences.observe(key: String, valueProducer: suspend () -> T):
|
||||
emit(valueProducer())
|
||||
}
|
||||
}
|
||||
}.distinctUntilChanged()
|
||||
}.distinctUntilChanged()
|
||||
|
||||
fun Lifecycle.postDelayed(runnable: Runnable, delay: Long) {
|
||||
coroutineScope.launch {
|
||||
delay(delay)
|
||||
runnable.run()
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,6 @@ package org.koitharu.kotatsu.utils.ext
|
||||
import androidx.collection.ArraySet
|
||||
import java.util.*
|
||||
|
||||
fun <T : Enum<T>> Array<T>.names() = Array(size) { i ->
|
||||
this[i].name
|
||||
}
|
||||
|
||||
fun <T> MutableList<T>.move(sourceIndex: Int, targetIndex: Int) {
|
||||
if (sourceIndex <= targetIndex) {
|
||||
Collections.rotate(subList(sourceIndex, targetIndex + 1), -1)
|
||||
|
||||
@@ -3,15 +3,6 @@ package org.koitharu.kotatsu.utils.ext
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
|
||||
val IgnoreErrors
|
||||
get() = CoroutineExceptionHandler { _, e ->
|
||||
if (BuildConfig.DEBUG) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
val processLifecycleScope: LifecycleCoroutineScope
|
||||
inline get() = ProcessLifecycleOwner.get().lifecycleScope
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.koitharu.kotatsu.utils.ext
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.view.Display
|
||||
import android.view.WindowManager
|
||||
import androidx.core.content.getSystemService
|
||||
|
||||
val Context.displayCompat: Display?
|
||||
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
display
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
getSystemService<WindowManager>()?.defaultDisplay
|
||||
}
|
||||
@@ -2,9 +2,11 @@ package org.koitharu.kotatsu.utils.ext
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.coroutineScope
|
||||
import java.io.Serializable
|
||||
|
||||
@@ -43,4 +45,8 @@ fun DialogFragment.showAllowStateLoss(manager: FragmentManager, tag: String?) {
|
||||
if (!manager.isStateSaved) {
|
||||
show(manager, tag)
|
||||
}
|
||||
}
|
||||
|
||||
fun Fragment.addMenuProvider(provider: MenuProvider) {
|
||||
requireActivity().addMenuProvider(provider, viewLifecycleOwner, Lifecycle.State.RESUMED)
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.liveData
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@@ -3,12 +3,14 @@ package org.koitharu.kotatsu.utils.ext
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import java.util.*
|
||||
|
||||
fun LocaleListCompat.toList(): List<Locale> = createList(size()) { i -> get(i) }
|
||||
fun LocaleListCompat.getOrThrow(index: Int) = get(index) ?: throw kotlin.NoSuchElementException()
|
||||
|
||||
fun LocaleListCompat.toList(): List<Locale> = createList(size()) { i -> getOrThrow(i) }
|
||||
|
||||
operator fun LocaleListCompat.iterator() = object : Iterator<Locale> {
|
||||
private var index = 0
|
||||
override fun hasNext(): Boolean = index < size()
|
||||
override fun next(): Locale = get(index++)
|
||||
override fun next(): Locale = getOrThrow(index++)
|
||||
}
|
||||
|
||||
inline fun <R, C : MutableCollection<in R>> LocaleListCompat.mapTo(
|
||||
@@ -17,7 +19,7 @@ inline fun <R, C : MutableCollection<in R>> LocaleListCompat.mapTo(
|
||||
): C {
|
||||
val len = size()
|
||||
for (i in 0 until len) {
|
||||
val item = get(i)
|
||||
val item = get(i) ?: continue
|
||||
destination.add(block(item))
|
||||
}
|
||||
return destination
|
||||
|
||||
@@ -2,4 +2,13 @@ package org.koitharu.kotatsu.utils.ext
|
||||
|
||||
inline fun String?.ifNullOrEmpty(defaultValue: () -> String): String {
|
||||
return if (this.isNullOrEmpty()) defaultValue() else this
|
||||
}
|
||||
|
||||
fun String.longHashCode(): Long {
|
||||
var h = 1125899906842597L
|
||||
val len: Int = this.length
|
||||
for (i in 0 until len) {
|
||||
h = 31 * h + this[i].code
|
||||
}
|
||||
return h
|
||||
}
|
||||
@@ -3,7 +3,10 @@ package org.koitharu.kotatsu.utils.ext
|
||||
import android.app.Activity
|
||||
import android.graphics.Rect
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.widget.TooltipCompat
|
||||
import androidx.core.view.children
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@@ -138,4 +141,19 @@ val RecyclerView.isScrolledToTop: Boolean
|
||||
}
|
||||
val holder = findViewHolderForAdapterPosition(0)
|
||||
return holder != null && holder.itemView.top >= 0
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : View> ViewGroup.findViewsByType(clazz: Class<T>): Sequence<T> {
|
||||
if (childCount == 0) {
|
||||
return emptySequence()
|
||||
}
|
||||
return sequence {
|
||||
for (view in children) {
|
||||
if (clazz.isInstance(view)) {
|
||||
yield(clazz.cast(view)!!)
|
||||
} else if (view is ViewGroup && view.childCount != 0) {
|
||||
yieldAll(view.findViewsByType(clazz))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user