mirror of
https://github.com/revanced/revanced-manager.git
synced 2025-05-25 11:02:13 +02:00
96 lines
2.9 KiB
Kotlin
96 lines
2.9 KiB
Kotlin
package app.revanced.manager.util
|
|
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.content.pm.PackageManager.NameNotFoundException
|
|
import android.graphics.drawable.Drawable
|
|
import android.util.Log
|
|
import android.widget.Toast
|
|
import androidx.annotation.StringRes
|
|
import androidx.core.net.toUri
|
|
import androidx.lifecycle.Lifecycle
|
|
import androidx.lifecycle.LifecycleOwner
|
|
import androidx.lifecycle.lifecycleScope
|
|
import androidx.lifecycle.repeatOnLifecycle
|
|
import io.ktor.http.Url
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
import kotlinx.coroutines.flow.Flow
|
|
import kotlinx.coroutines.flow.combine
|
|
import kotlinx.coroutines.flow.flatMapLatest
|
|
import kotlinx.coroutines.launch
|
|
|
|
typealias PatchesSelection = Map<Int, Set<String>>
|
|
typealias Options = Map<Int, Map<String, Map<String, Any?>>>
|
|
|
|
fun Context.openUrl(url: String) {
|
|
startActivity(Intent(Intent.ACTION_VIEW, url.toUri()).apply {
|
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
})
|
|
}
|
|
|
|
fun Context.loadIcon(string: String): Drawable? {
|
|
return try {
|
|
packageManager.getApplicationIcon(string)
|
|
} catch (e: NameNotFoundException) {
|
|
null
|
|
}
|
|
}
|
|
|
|
fun Context.toast(string: String, duration: Int = Toast.LENGTH_SHORT) {
|
|
Toast.makeText(this, string, duration).show()
|
|
}
|
|
|
|
fun String.parseUrlOrNull() = try {
|
|
Url(this)
|
|
} catch (_: Throwable) {
|
|
null
|
|
}
|
|
|
|
/**
|
|
* Safely perform an operation that may fail to avoid crashing the app.
|
|
* If [block] fails, the error will be logged and a toast will be shown to the user to inform them that the action failed.
|
|
*
|
|
* @param context The android [Context].
|
|
* @param toastMsg The toast message to show if [block] throws.
|
|
* @param logMsg The log message.
|
|
* @param block The code to execute.
|
|
*/
|
|
inline fun uiSafe(context: Context, @StringRes toastMsg: Int, logMsg: String, block: () -> Unit) {
|
|
try {
|
|
block()
|
|
} catch (error: Exception) {
|
|
context.toast(
|
|
context.getString(
|
|
toastMsg,
|
|
error.message ?: error.cause?.message ?: error::class.simpleName
|
|
)
|
|
)
|
|
Log.e(tag, logMsg, error)
|
|
}
|
|
}
|
|
|
|
inline fun LifecycleOwner.launchAndRepeatWithViewLifecycle(
|
|
minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
|
|
crossinline block: suspend CoroutineScope.() -> Unit
|
|
) {
|
|
lifecycleScope.launch {
|
|
lifecycle.repeatOnLifecycle(minActiveState) {
|
|
block()
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run [transformer] on the [Iterable] and then [combine] the result using [combiner].
|
|
* This is used to transform collections that contain [Flow]s into something that is easier to work with.
|
|
*/
|
|
@OptIn(ExperimentalCoroutinesApi::class)
|
|
inline fun <T, reified R, C> Flow<Iterable<T>>.flatMapLatestAndCombine(
|
|
crossinline combiner: (Array<R>) -> C,
|
|
crossinline transformer: (T) -> Flow<R>,
|
|
): Flow<C> = flatMapLatest { iterable ->
|
|
combine(iterable.map(transformer)) {
|
|
combiner(it)
|
|
}
|
|
} |