278 lines
9.0 KiB
Kotlin
278 lines
9.0 KiB
Kotlin
package com.tommasoberlose.anotherwidget.utils
|
|
|
|
import android.animation.*
|
|
import android.content.pm.PackageManager
|
|
import android.view.View
|
|
import android.view.ViewAnimationUtils
|
|
import android.widget.Toast
|
|
import android.app.Activity
|
|
import android.app.WallpaperManager
|
|
import android.content.*
|
|
import android.net.Uri
|
|
import androidx.browser.customtabs.CustomTabsIntent
|
|
import androidx.core.content.ContextCompat
|
|
import android.content.res.Configuration
|
|
import android.provider.Settings
|
|
import android.util.Patterns
|
|
import java.security.NoSuchAlgorithmException
|
|
import kotlin.math.max
|
|
import android.content.Intent
|
|
import android.content.res.Resources
|
|
import android.graphics.drawable.Drawable
|
|
import android.util.DisplayMetrics
|
|
import android.util.TypedValue
|
|
import android.view.animation.AlphaAnimation
|
|
import android.widget.RelativeLayout
|
|
import androidx.annotation.UiThread
|
|
import androidx.appcompat.app.AppCompatDelegate
|
|
import androidx.browser.customtabs.CustomTabColorSchemeParams
|
|
import androidx.core.animation.addListener
|
|
import androidx.core.view.isVisible
|
|
import com.tommasoberlose.anotherwidget.R
|
|
import com.tommasoberlose.anotherwidget.components.OnSingleClickListener
|
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
import java.util.*
|
|
|
|
|
|
fun PackageManager.missingSystemFeature(name: String): Boolean = !hasSystemFeature(name)
|
|
|
|
fun Context.toast(message: String, long: Boolean = false) {
|
|
val toast = Toast.makeText(this, message, if (long) Toast.LENGTH_LONG else Toast.LENGTH_SHORT)
|
|
// toast.setGravity(Gravity.CENTER, 0, 0)
|
|
toast.show()
|
|
}
|
|
|
|
fun Int.toPixel(context: Context): Int = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), context.resources.displayMetrics).toInt()
|
|
fun Float.toPixel(context: Context): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, context.resources.displayMetrics)
|
|
|
|
fun View.reveal(initialX: Int? = null, initialY: Int? = null) {
|
|
|
|
when (visibility) {
|
|
View.VISIBLE -> {
|
|
val anim = ViewAnimationUtils.createCircularReveal(this, initialX ?: this.measuredWidth / 2, initialY ?: this.measuredHeight / 2, max(width.toFloat(), height.toFloat()), 0f)
|
|
.apply {
|
|
duration = 200
|
|
}
|
|
anim.addListener(object : AnimatorListenerAdapter() {
|
|
override fun onAnimationEnd(animation: Animator) {
|
|
visibility = View.GONE
|
|
super.onAnimationEnd(animation)
|
|
}
|
|
})
|
|
anim.start()
|
|
} else -> {
|
|
val anim = ViewAnimationUtils.createCircularReveal(this, initialX ?: this.measuredWidth / 2, initialY ?: this.measuredHeight / 2, 0f, max(width.toFloat(), height.toFloat()))
|
|
.apply {
|
|
duration = 200
|
|
}
|
|
visibility = View.VISIBLE
|
|
anim.start()
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
fun View.expand(duration: Long = 500L) {
|
|
clearAnimation()
|
|
try {
|
|
val animator = (tag as ValueAnimator)
|
|
animator.removeAllListeners()
|
|
animator.cancel()
|
|
} catch (ex: java.lang.Exception) {}
|
|
|
|
layoutParams = layoutParams.apply {
|
|
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
|
}
|
|
measure(0, 0)
|
|
|
|
val initialHeight = measuredHeight
|
|
val anim = ValueAnimator.ofFloat(
|
|
alpha,
|
|
1f
|
|
).apply {
|
|
this.duration = duration
|
|
addUpdateListener {
|
|
val animatedValue = animatedValue as Float
|
|
layoutParams = layoutParams.apply {
|
|
height = (initialHeight * animatedValue).toInt()
|
|
}
|
|
translationY = (initialHeight * animatedValue - initialHeight)
|
|
alpha = animatedValue
|
|
}
|
|
addListener(
|
|
onStart = {
|
|
isVisible = true
|
|
}
|
|
)
|
|
}
|
|
tag = anim
|
|
anim.start()
|
|
}
|
|
|
|
fun View.collapse(duration: Long = 500L) {
|
|
clearAnimation()
|
|
try {
|
|
val animator = (tag as ValueAnimator)
|
|
animator.removeAllListeners()
|
|
animator.cancel()
|
|
} catch (ex: java.lang.Exception) {}
|
|
val initialHeight = measuredHeight
|
|
val anim = ValueAnimator.ofFloat(
|
|
alpha,
|
|
0f
|
|
).apply {
|
|
this.duration = duration
|
|
addUpdateListener {
|
|
val animatedValue = animatedValue as Float
|
|
layoutParams = layoutParams.apply {
|
|
height = (initialHeight * animatedValue).toInt()
|
|
}
|
|
translationY = (initialHeight * animatedValue - initialHeight)
|
|
alpha = animatedValue
|
|
}
|
|
addListener(
|
|
onEnd = {
|
|
isVisible = false
|
|
}
|
|
)
|
|
}
|
|
tag = anim
|
|
anim.start()
|
|
}
|
|
|
|
fun Context.openURI(url: String) {
|
|
try {
|
|
val builder: CustomTabsIntent.Builder = CustomTabsIntent.Builder()
|
|
builder.setDefaultColorSchemeParams(CustomTabColorSchemeParams.Builder().setToolbarColor(ContextCompat.getColor(this, R.color.colorPrimary)).build())
|
|
val customTabsIntent: CustomTabsIntent = builder.build()
|
|
customTabsIntent.launchUrl(this, Uri.parse(url))
|
|
} catch (e: Exception) {
|
|
try {
|
|
val openIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
|
startActivity(openIntent)
|
|
} catch (ignored: Exception) {
|
|
val clipboard: ClipboardManager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
val clip = ClipData.newPlainText(getString(R.string.app_name), url)
|
|
clipboard.setPrimaryClip(clip)
|
|
Toast.makeText(this, R.string.error_opening_uri, Toast.LENGTH_LONG).show()
|
|
}
|
|
}
|
|
}
|
|
|
|
fun Context.isTablet(): Boolean {
|
|
return (resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE
|
|
}
|
|
|
|
fun String.md5(): String {
|
|
val mD5 = "MD5"
|
|
try {
|
|
// Create MD5 Hash
|
|
val digest = java.security.MessageDigest
|
|
.getInstance(mD5)
|
|
digest.update(toByteArray())
|
|
val messageDigest = digest.digest()
|
|
|
|
// Create Hex String
|
|
val hexString = StringBuilder()
|
|
for (aMessageDigest in messageDigest) {
|
|
var h = Integer.toHexString(0xFF and aMessageDigest.toInt())
|
|
while (h.length < 2)
|
|
h = "0$h"
|
|
hexString.append(h)
|
|
}
|
|
return hexString.toString()
|
|
|
|
} catch (e: NoSuchAlgorithmException) {
|
|
e.printStackTrace()
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
fun String.isValidEmail(): Boolean
|
|
= this.isNotEmpty() &&
|
|
Patterns.EMAIL_ADDRESS.matcher(this).matches()
|
|
|
|
fun Context.isDarkTheme(): Boolean {
|
|
return Preferences.darkThemePreference == AppCompatDelegate.MODE_NIGHT_YES || Preferences.darkThemePreference == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM && resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
|
|
}
|
|
|
|
fun Activity.isNotificationAccessGranted(): Boolean = Settings.Secure.getString(this.contentResolver,"enabled_notification_listeners").contains(this.packageName)
|
|
|
|
fun Float.convertDpToPixel(context: Context): Float {
|
|
val resources: Resources = context.resources
|
|
val metrics: DisplayMetrics = resources.displayMetrics
|
|
val px: Float = this * (metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT)
|
|
return px
|
|
}
|
|
|
|
fun Float.convertSpToPixels(context: Context): Float {
|
|
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this, context.resources.displayMetrics)
|
|
}
|
|
|
|
fun Context.checkGrantedPermission(permission: String): Boolean {
|
|
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
|
|
}
|
|
|
|
fun Context.getCurrentWallpaper(): Drawable? = try {
|
|
WallpaperManager.getInstance(this).drawable
|
|
} catch (e: Exception) {
|
|
null
|
|
}
|
|
|
|
fun String.getCapWordString(): String {
|
|
return try {
|
|
val ar = this.split(" ")
|
|
var newText = ""
|
|
for (t: String in ar) {
|
|
newText += " "
|
|
newText += t.substring(0, 1).toUpperCase(Locale.getDefault())
|
|
newText += t.substring(1)
|
|
}
|
|
newText.substring(1)
|
|
} catch (e: Exception) {
|
|
this
|
|
}
|
|
}
|
|
|
|
fun Context.checkIfFitInstalled(): Boolean {
|
|
return try {
|
|
packageManager.getPackageInfo("com.google.android.apps.fitness", PackageManager.GET_ACTIVITIES)
|
|
true
|
|
} catch (e: Exception) {
|
|
false
|
|
}
|
|
}
|
|
|
|
fun Intent.isDefaultSet(context: Context): Boolean {
|
|
val pm = context.packageManager
|
|
return try {
|
|
resolveActivity(pm) != null && resolveActivity(pm).packageName.isNotBlank()
|
|
} catch (ex: java.lang.Exception) {
|
|
false
|
|
}
|
|
}
|
|
|
|
fun Locale.isMetric(): Boolean {
|
|
return when (country.toUpperCase(this)) {
|
|
"US", "LR", "MM", "GB" -> false
|
|
else -> true
|
|
}
|
|
}
|
|
|
|
fun View.setOnSingleClickListener(l: View.OnClickListener) {
|
|
setOnClickListener(OnSingleClickListener(l))
|
|
}
|
|
|
|
fun View.setOnSingleClickListener(l: (View) -> Unit) {
|
|
setOnClickListener(OnSingleClickListener(l))
|
|
}
|
|
|
|
fun ignoreExceptions(function: () -> Unit) = run {
|
|
try {
|
|
function.invoke()
|
|
} catch (ex: Exception) {
|
|
ex.printStackTrace()
|
|
}
|
|
}
|