Refactor: Created more usable functions.

This commit is contained in:
HeCodes2Much
2024-05-25 19:47:42 +01:00
parent 629b675471
commit bd23849c53
18 changed files with 965 additions and 153 deletions

View File

@@ -0,0 +1,101 @@
package com.github.droidworksstudio.ktx
import android.app.Activity
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.net.Uri
import android.os.Build
import android.provider.Settings
import android.util.DisplayMetrics
import android.view.WindowManager
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.content.getSystemService
import androidx.fragment.app.Fragment
fun Activity.getDisplayWidth(): Int {
val windowManager = getSystemService<WindowManager>() ?: return 0
val width = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val windowMetrics = windowManager.currentWindowMetrics
val bounds = windowMetrics.bounds
bounds.width()
} else {
val displayMetrics = DisplayMetrics()
@Suppress("DEPRECATION")
windowManager.defaultDisplay.getMetrics(displayMetrics)
displayMetrics.widthPixels
}
return width
}
fun Activity.enablePortraitScreenOrientationForMobile(isPortrait: Boolean) {
if (!isTabletConfig()) {
requestedOrientation = if (isPortrait) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
else ActivityInfo.SCREEN_ORIENTATION_SENSOR
}
}
fun Activity.lockScreenOrientationChanges(lock: Boolean) {
requestedOrientation =
if (lock) ActivityInfo.SCREEN_ORIENTATION_LOCKED else ActivityInfo.SCREEN_ORIENTATION_SENSOR
}
fun Activity.openEmailClient(emailTo: String, subject: String) {
val uriString = "mailto:$emailTo?subject=$subject"
val emailIntent = Intent(Intent.ACTION_SENDTO)
emailIntent.data = Uri.parse(uriString)
if (emailIntent.resolveActivity(packageManager) != null) {
startActivity(emailIntent)
} else {
startActivity(Intent.createChooser(emailIntent, null))
}
}
@RequiresApi(Build.VERSION_CODES.O)
fun Activity.openNotificationSettings() {
val intent = Intent()
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
intent.putExtra("app_package", packageName)
intent.putExtra("app_uid", applicationInfo.uid)
startActivity(intent)
}
/**
* Starting from appcompat v.1.1.0 system overrides baseContext after [attachBaseContext]
* causing resetting locale settings. To prevent this we must call [applyOverrideConfiguration]
* with modified [overrideConfiguration] object.
*
* That's a workaround until this behaviour will be fixed in future appcompat releases.
*/
fun Activity.setupOverrideConfiguration(overrideConfiguration: Configuration?): Configuration? {
if (overrideConfiguration != null) {
val uiMode = overrideConfiguration.uiMode
overrideConfiguration.setTo(baseContext.resources.configuration)
overrideConfiguration.uiMode = uiMode
}
return overrideConfiguration
}
/**
* Navigates to the current Google user's account
* subscriptions in Google Play app.
*/
fun Activity.openGooglePlaySubscriptions() {
val uriString = "https://play.google.com/store/account/subscriptions"
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(uriString))
startActivity(intent)
}
fun Activity.showLongToast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
}
fun Activity.showShortToast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}

View File

@@ -0,0 +1,130 @@
package com.github.droidworksstudio.ktx
import android.app.SearchManager
import android.content.Context
import android.content.Intent
import android.content.pm.LauncherApps
import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.drawable.AdaptiveIconDrawable
import android.net.Uri
import android.os.Build
import android.os.UserHandle
import android.view.ContextThemeWrapper
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.IconCompat
import androidx.core.graphics.drawable.toBitmap
import androidx.core.os.ConfigurationCompat
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
fun Context.isTabletConfig(): Boolean =
resources.configuration.smallestScreenWidthDp >= SMALLEST_WIDTH_600
fun Context.isPortraitSw600Config(): Boolean =
resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT &&
resources.configuration.smallestScreenWidthDp >= SMALLEST_WIDTH_600
fun Context.isLandscapeSw600Config(): Boolean =
resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE &&
resources.configuration.smallestScreenWidthDp >= SMALLEST_WIDTH_600
fun Context.isLandscapeDisplayOrientation(): Boolean =
resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
internal fun Context.addLifecycleObserver(observer: LifecycleObserver) {
when (this) {
is LifecycleOwner -> this.lifecycle.addObserver(observer)
is ContextThemeWrapper -> this.baseContext.addLifecycleObserver(observer)
is androidx.appcompat.view.ContextThemeWrapper -> this.baseContext.addLifecycleObserver(
observer
)
}
}
fun Context.getMiddleScreenX(): Int {
val screenEndX = this.resources.displayMetrics.widthPixels
return (screenEndX / 2)
}
fun Context.getMiddleScreenY(): Int {
val screenEndY = this.resources.displayMetrics.heightPixels
return (screenEndY / 2)
}
const val SMALLEST_WIDTH_600: Int = 600
fun Context.createIconWithResourceCompat(
@DrawableRes vectorIconId: Int,
@DrawableRes adaptiveIconForegroundId: Int,
@DrawableRes adaptiveIconBackgroundId: Int
): IconCompat {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val adaptiveIconDrawable = AdaptiveIconDrawable(
ContextCompat.getDrawable(this, adaptiveIconBackgroundId),
ContextCompat.getDrawable(this, adaptiveIconForegroundId)
)
IconCompat.createWithAdaptiveBitmap(
adaptiveIconDrawable.toBitmap(
config = Bitmap.Config.ARGB_8888
)
)
} else {
IconCompat.createWithResource(this, vectorIconId)
}
}
fun Context.currentLanguage() = ConfigurationCompat.getLocales(resources.configuration)[0]?.language
fun Context.openBrowser(url: String, clearFromRecent: Boolean = true) {
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
browserIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
if (clearFromRecent) browserIntent.flags =
browserIntent.flags or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
startActivity(browserIntent)
}
fun Context.inflate(resource: Int, root: ViewGroup? = null, attachToRoot: Boolean = false): View {
return LayoutInflater.from(this).inflate(resource, root, attachToRoot)
}
fun Context.getColorCompat(@ColorRes color: Int) = ContextCompat.getColor(this, color)
fun Context.getDrawableCompat(@DrawableRes drawable: Int) =
ContextCompat.getDrawable(this, drawable)
fun Context.showLongToast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
}
fun Context.showShortToast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
fun Context.openSearch(query: String? = null) {
val intent = Intent(Intent.ACTION_WEB_SEARCH)
intent.putExtra(SearchManager.QUERY, query ?: "")
startActivity(intent)
}
fun Context.openUrl(url: String) {
if (url.isEmpty()) return
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(url)
startActivity(intent)
}
fun Context.isPackageInstalled(
packageName: String,
userHandle: UserHandle = android.os.Process.myUserHandle()
): Boolean {
val launcher = getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
val activityInfo = launcher.getActivityList(packageName, userHandle)
return activityInfo.size > 0
}

View File

@@ -0,0 +1,41 @@
package com.github.droidworksstudio.ktx
import android.content.Context
import android.content.Intent
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.fragment.app.Fragment
fun Fragment.showKeyboard() {
val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
view?.let { v ->
v.requestFocus()
imm?.showSoftInput(v, InputMethodManager.SHOW_IMPLICIT)
}
}
fun Fragment.hideKeyboard() {
val view = view?.findFocus() ?: return
val imm: InputMethodManager? =
view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?
imm?.hideSoftInputFromWindow(view.windowToken, 0)
view.clearFocus()
}
fun Fragment.showLongToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_LONG).show()
}
fun Fragment.showShortToast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
fun Fragment.restartApp() {
val packageManager = requireContext().packageManager
val intent = packageManager.getLaunchIntentForPackage(requireContext().packageName)
intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
if (intent != null) {
startActivity(intent)
}
requireActivity().finish()
}

View File

@@ -0,0 +1,53 @@
package com.github.droidworksstudio.ktx
import android.content.res.Resources
import android.util.TypedValue
/**
* Converts value in pixels (px) into value in device-independent pixels (dp)
*/
fun Int.pxToDp(): Int {
val metrics = Resources.getSystem().displayMetrics
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, this.toFloat(), metrics).toInt()
}
/**
* Converts value in pixels (px) into value in scaled pixels (sp)
*/
fun Int.pxToSp(): Int {
val metrics = Resources.getSystem().displayMetrics
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, this.toFloat(), metrics).toInt()
}
/**
* Converts value in device-independent pixels (dp) into value in pixels (px)
*/
fun Int.dpToPx(): Int {
val metrics = Resources.getSystem().displayMetrics
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), metrics).toInt()
}
/**
* Converts value in density-independent pixels (dp) into value in scaled pixels (sp)
*/
fun Int.dpToSp(): Int {
val metrics = Resources.getSystem().displayMetrics
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), metrics).toInt()
}
/**
* Converts value in scaled pixels (sp) into value in device-independent pixels (dp)
*/
fun Int.spToDp(): Int {
val metrics = Resources.getSystem().displayMetrics
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this.toFloat(), metrics).toInt()
}
/**
* Converts value in scaled pixels (sp) into value in pixels (px)
*/
fun Int.spToPx(): Int {
val metrics = Resources.getSystem().displayMetrics
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this.toFloat(), metrics).toInt()
}

View File

@@ -0,0 +1,104 @@
package com.github.droidworksstudio.ktx
import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.text.Html
import android.text.Spannable
import android.text.SpannableString
import android.text.TextPaint
import android.text.style.ClickableSpan
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.view.View
import android.widget.Toast
import androidx.core.text.getSpans
/**
* Returns [Spannable] where the term is
* highlighted as a bold text.
*/
fun String.highlightTerm(term: String): SpannableString {
val regex = Regex(term.lowercase())
val matches = regex.findAll(this.lowercase())
val ranges = matches.map { it.range }
val spannable = SpannableString(this)
ranges.forEach {
spannable.setSpan(
ForegroundColorSpan(Color.BLACK),
it.first,
it.last + 1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
return spannable
}
/**
* Returns [Spannable] where all <em> (e.g. italic) tags are replaced
* with <strong> (e.g. bold)
*
* Important: works only with <em> tags replacing it only with <strong> tags.
* Using deprecated [Html.fromHtml] as it's deprecated only from API 24.
*/
fun String.replaceItalicWithBold(): SpannableString {
val spannable = SpannableString(Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY))
spannable.getSpans<StyleSpan>(0, spannable.length)
.replaceItalicInSpannable(spannable)
return spannable
}
fun Array<out StyleSpan>.replaceItalicInSpannable(spannable: SpannableString) = forEach {
if (it.style == Typeface.ITALIC) {
spannable.setSpan(
StyleSpan(Typeface.BOLD),
spannable.getSpanStart(it),
spannable.getSpanEnd(it),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
spannable.setSpan(
ForegroundColorSpan(Color.BLACK),
spannable.getSpanStart(it),
spannable.getSpanEnd(it),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
spannable.removeSpan(it)
}
}
fun CharSequence.makeTextClickable(
clickableText: String,
clickableTextColor: Int,
clickListener: () -> (Unit)
): SpannableString {
val regex = Regex(clickableText)
val matches = regex.findAll(this)
val ranges = matches.map { it.range }
val spannable = SpannableString(this)
val clickableSpan = object : ClickableSpan() {
override fun onClick(widget: View) {
clickListener.invoke()
}
override fun updateDrawState(ds: TextPaint) {
ds.color = clickableTextColor
ds.isUnderlineText = false
}
}
ranges.forEach {
spannable.setSpan(clickableSpan, it.first, it.last + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
return spannable
}
fun String.showLongToast(context: Context) {
Toast.makeText(context, this, Toast.LENGTH_LONG).show()
}
fun String.showShortToast(context: Context) {
Toast.makeText(context, this, Toast.LENGTH_SHORT).show()
}

View File

@@ -0,0 +1,375 @@
package com.github.droidworksstudio.ktx
import android.annotation.SuppressLint
import android.content.Context
import android.text.Editable
import android.text.TextWatcher
import android.text.method.LinkMovementMethod
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.AutoCompleteTextView
import android.widget.CheckBox
import android.widget.EditText
import android.widget.TextView
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.text.toSpannable
import androidx.core.view.ViewCompat
import androidx.core.view.children
import androidx.core.view.doOnPreDraw
import androidx.core.widget.TextViewCompat
import androidx.lifecycle.MutableLiveData
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.snackbar.Snackbar
fun EditText.value() = text.toString()
inline fun EditText.setOnEditorActionListener(crossinline onAction: (Int) -> Boolean) {
setOnEditorActionListener { _, actionId, _ -> onAction(actionId) }
}
inline fun EditText.setOnDoneEditorActionListener(crossinline onAction: (Int) -> Unit = {}) {
setOnEditorActionListener { actionId ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
onAction(actionId)
true
} else false
}
}
/**
* Runs [onAction] block and hides a keyboard when [EditorInfo.IME_ACTION_DONE] is fired.
*
* @param onAction function to be called when [[EditorInfo.IME_ACTION_DONE] is fired
*/
inline fun EditText.setHideKeyboardEditorActionListener(crossinline onAction: (Int) -> Unit = {}) {
setOnDoneEditorActionListener {
hideKeyboard()
onAction(it)
}
}
fun View.showKeyboard() {
val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
this.let { v ->
v.requestFocus()
imm?.showSoftInput(v, InputMethodManager.SHOW_IMPLICIT)
}
}
fun View.hideKeyboard() {
val imm: InputMethodManager? =
context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?
imm?.hideSoftInputFromWindow(windowToken, 0)
this.clearFocus()
}
/**
* @return [View.VISIBLE] if Boolean value is true, [View.GONE] otherwise.
*/
fun Boolean.asVisibleOrGoneFlag() = if (this) View.VISIBLE else View.GONE
/**
* @return [View.GONE] if Boolean value is true, [View.VISIBLE] otherwise.
*/
fun Boolean.asGoneOrVisibleFlag() = if (this) View.GONE else View.VISIBLE
/**
* @return [View.VISIBLE] if Boolean value is true, [View.INVISIBLE] otherwise.
*/
fun Boolean.asVisibleOrInvisibleFlag() = if (this) View.VISIBLE else View.INVISIBLE
/**
* Resets nested vertical scroll position.
*
* Can be used to reset [CoordinatorLayout]'s behaviours that depends on scrolling views.
*/
fun RecyclerView.resetNestedVerticalScroll() {
startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL)
dispatchNestedPreScroll(0, -Integer.MAX_VALUE, null, null)
dispatchNestedScroll(0, -Integer.MAX_VALUE, 0, 0, null)
stopNestedScroll()
}
@SuppressLint("SwitchIntDef")
fun LinearLayoutManager.getCurrentPosition(midScreenX: Int, midScreenY: Int): Int =
when (this.orientation) {
LinearLayoutManager.HORIZONTAL -> getCurrentPositionForHorizontalOrientation(midScreenX)
LinearLayoutManager.VERTICAL -> getCurrentPositionForVerticalOrientation(midScreenY)
else -> RecyclerView.NO_POSITION
}
/**
* Get current position for [LinearLayoutManager.HORIZONTAL]
*
* @return position of center item if it exists else
* @return first completely visible or first visible item position
*
* @return [RecyclerView.NO_POSITION] if [LinearLayoutManager] doesn't have horizontal orientation
*/
private fun LinearLayoutManager.getCurrentPositionForHorizontalOrientation(midScreenX: Int): Int {
if (this.orientation == LinearLayoutManager.HORIZONTAL) {
val centerPosition = getCenterPositionForHorizontalOrientation(midScreenX)
return if (centerPosition == RecyclerView.NO_POSITION) {
getCompletelyVisibleOrFirstPosition()
} else centerPosition
}
return RecyclerView.NO_POSITION
}
private fun LinearLayoutManager.getCompletelyVisibleOrFirstPosition(): Int {
val firstCompletelyVisiblePosition = findFirstCompletelyVisibleItemPosition()
return if (firstCompletelyVisiblePosition == RecyclerView.NO_POSITION) {
findFirstVisibleItemPosition()
} else {
firstCompletelyVisiblePosition
}
}
/**
* Get position of center item for [LinearLayoutManager.HORIZONTAL]
*
* @return position of item with start X less than middle of the screen and end X more than middle of the screen
*
* @return [RecyclerView.NO_POSITION] if [LinearLayoutManager] doesn't have horizontal orientation or there is no item that meets requirements
*/
private fun LinearLayoutManager.getCenterPositionForHorizontalOrientation(midScreenX: Int): Int {
if (this.orientation == LinearLayoutManager.HORIZONTAL) {
val firstPosition = this.findFirstVisibleItemPosition()
val lastPosition = this.findLastVisibleItemPosition()
for (position in firstPosition..lastPosition) {
val view = this.findViewByPosition(position)
if (view != null) {
val viewWidth = view.measuredWidth
val viewStartX = view.x
val viewEndX = viewStartX + viewWidth
if (viewStartX < midScreenX && viewEndX > midScreenX) {
return position
}
}
}
return RecyclerView.NO_POSITION
}
return RecyclerView.NO_POSITION
}
/**
* Get current position for [LinearLayoutManager.VERTICAL]
*
* @return position of center item if it exists else
* @return first completely visible or first visible item position
*
* @return [RecyclerView.NO_POSITION] if [LinearLayoutManager] doesn't have vertical orientation
*/
private fun LinearLayoutManager.getCurrentPositionForVerticalOrientation(midScreenY: Int): Int {
if (this.orientation == LinearLayoutManager.VERTICAL) {
val centerPosition = getCenterPositionForVerticalOrientation(midScreenY)
return if (centerPosition == RecyclerView.NO_POSITION) {
getCompletelyVisibleOrFirstPosition()
} else centerPosition
}
return RecyclerView.NO_POSITION
}
/**
* Get position of center item for [LinearLayoutManager.VERTICAL]
*
* @return position of item with start Y less than middle of the screen and end Y more than middle of the screen
*
* @return [RecyclerView.NO_POSITION] if [LinearLayoutManager] doesn't have vertical orientation or there is no item that meets requirements
*/
private fun LinearLayoutManager.getCenterPositionForVerticalOrientation(midScreenY: Int): Int {
if (this.orientation == LinearLayoutManager.VERTICAL) {
val firstPosition = this.findFirstVisibleItemPosition()
val lastPosition = this.findLastVisibleItemPosition()
for (position in firstPosition..lastPosition) {
val view = this.findViewByPosition(position)
if (view != null) {
val viewHeight = view.measuredHeight
val viewStartY = view.y
val viewEndY = viewStartY + viewHeight
if (viewStartY < midScreenY && viewEndY > midScreenY) {
return position
}
}
}
return RecyclerView.NO_POSITION
}
return RecyclerView.NO_POSITION
}
fun View.setBottomPadding(bottomPadding: Int) {
setPadding(paddingLeft, paddingTop, paddingRight, bottomPadding)
}
/**
* Triggers when recycler view state changes to [RecyclerView.SCROLL_STATE_IDLE].
*/
inline fun RecyclerView.addOnIdleStateListener(crossinline listener: (RecyclerView) -> Unit) {
addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
listener.invoke(recyclerView)
}
}
})
}
fun View.setProportionalHeight(imageWidth: Float, imageHeight: Float) {
doOnPreDraw {
val maxWidth = it.width.toFloat()
it.layoutParams =
it.layoutParams.calculateProportionalHeight(maxWidth, imageWidth, imageHeight)
}
}
fun View.setProportionalAspectRatio(imageWidth: Float, imageHeight: Float) {
doOnPreDraw {
val maxWidth = it.width.toFloat()
val maxHeight = it.height.toFloat()
it.layoutParams =
it.layoutParams.calculateAspectRatio(maxWidth, maxHeight, imageWidth, imageHeight)
}
}
fun View.setElevationCompat(value: Float) {
ViewCompat.setElevation(this, value)
}
fun View.getElevationCompat() = ViewCompat.getElevation(this)
fun View.enableChildrenViews(enable: Boolean) {
this.isEnabled = enable
if (this is ViewGroup) {
this.children.forEach { it.enableChildrenViews(enable) }
}
}
/**
* Attaches Live data to Edit Text.
* This will update Live Data data with all text changes from Edit Text.
*/
fun <T> AutoCompleteTextView.attachLiveData(data: MutableLiveData<T>) {
setOnItemClickListener { parent, _, position, _ ->
@Suppress("UNCHECKED_CAST")
data.value = parent.adapter.getItem(position) as T
}
}
/**
* Attaches Live data to Edit Text.
* This will update Live Data data with all text changes from Edit Text.
*/
fun EditText.attachLiveData(data: MutableLiveData<String>) {
data.value = text.toString()
addTextChangedListener {
data.value = it.toString()
}
}
/**
* Attaches Live data to Check Box.
* This will update Live Data data with all state changes from Check Box.
*/
fun CheckBox.attachLiveData(data: MutableLiveData<Boolean>) {
data.value = isChecked
setOnCheckedChangeListener { _, isChecked ->
data.value = isChecked
}
}
inline fun EditText.addTextChangedListener(crossinline onTextChanged: (text: CharSequence?) -> Unit) {
addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(p0: Editable?) {
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
onTextChanged.invoke(p0)
}
})
}
fun TextView.setTextAppearanceCompat(appearanceId: Int) {
TextViewCompat.setTextAppearance(this, appearanceId)
}
fun Window.disableScreenshots() {
this.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
)
}
fun Snackbar.centerMessage(): Snackbar = apply {
val textView =
this.view.findViewById<AppCompatTextView>(com.google.android.material.R.id.snackbar_text)
textView.textAlignment = View.TEXT_ALIGNMENT_CENTER
}
fun Snackbar.show(isCentered: Boolean) {
if (isCentered) {
this.centerMessage()
}
this.show()
}
/**
* Searches for [clickableText] inside the TextView's text property.
* If found, highlights [clickableText] with [clickableTextColor] and sets [clickListener] to it.
*
* @param clickableText text that must be present inside TextView's text property
* @param clickableTextColor color for highlighting [clickableText]
* @param clickListener functions that will we invoked on [clickableText] click
*/
fun TextView.makeTextClickable(
clickableText: String,
clickableTextColor: Int,
clickListener: () -> (Unit)
) {
this.movementMethod = LinkMovementMethod.getInstance()
this.text =
this.text.toString().makeTextClickable(clickableText, clickableTextColor, clickListener)
}
fun TextView.makeSpannableTextClickable(
clickableText: String,
clickableTextColor: Int,
clickListener: () -> (Unit)
) {
this.movementMethod = LinkMovementMethod.getInstance()
this.text =
this.text.toSpannable().makeTextClickable(clickableText, clickableTextColor, clickListener)
}
fun View.removeFocus() {
clearFocus()
isFocusable = false
isFocusableInTouchMode = false
}
fun View.setFocus() {
isFocusable = true
isFocusableInTouchMode = true
}
fun Boolean.asTextOrNullInputType() = if (this) EditorInfo.TYPE_CLASS_TEXT else EditorInfo.TYPE_NULL

View File

@@ -0,0 +1,61 @@
package com.github.droidworksstudio.ktx
import android.annotation.SuppressLint
import android.view.ViewGroup
import android.widget.RadioButton
import android.widget.RadioGroup
import androidx.appcompat.view.SupportMenuInflater
import androidx.appcompat.widget.ActionMenuView
import androidx.lifecycle.MutableLiveData
import kotlin.math.min
fun ViewGroup.LayoutParams.calculateAspectRatio(
maxWidth: Float,
maxHeight: Float,
imageWidth: Float,
imageHeight: Float
): ViewGroup.LayoutParams = apply {
val widthRatio = maxWidth / imageWidth
val heightRatio = maxHeight / imageHeight
val bestRatio = min(widthRatio, heightRatio)
this.width = (imageWidth * bestRatio).toInt()
this.height = (imageHeight * bestRatio).toInt()
}
fun ViewGroup.LayoutParams.calculateProportionalHeight(
maxWidth: Float,
imageWidth: Float,
imageHeight: Float
): ViewGroup.LayoutParams = apply {
val aspectRatio = maxWidth / imageWidth
this.height = (imageHeight * aspectRatio).toInt()
}
/**
* Attaches Live data to Radio Group.
* This will update Live Data data with selected radio button text.
*/
fun RadioGroup.attachLiveDataForValue(data: MutableLiveData<String>) {
data.value = getCheckedView()?.text.toString()
setOnCheckedChangeListener { group, checkedId ->
val checkedView = group.findViewById<RadioButton>(checkedId)
data.value = checkedView.text.toString()
}
}
/**
* Attaches Live data to Radio Group.
* This will update Live Data data with selected radio button text.
*/
fun RadioGroup.attachLiveDataForId(data: MutableLiveData<Int>) {
data.value = checkedRadioButtonId
setOnCheckedChangeListener { _, checkedId ->
data.value = checkedId
}
}
fun RadioGroup.getCheckedView() = findViewById<RadioButton>(checkedRadioButtonId) ?: null
@SuppressLint("RestrictedApi")
fun ActionMenuView.inflateMenu(menuId: Int) = SupportMenuInflater(context).inflate(menuId, menu)

View File

@@ -1,53 +1,15 @@
package com.github.droidworksstudio.launcher.helper
import android.app.SearchManager
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.LauncherApps
import android.net.Uri
import android.os.UserHandle
import android.util.Log
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import androidx.fragment.app.Fragment
import com.github.droidworksstudio.ktx.openUrl
import com.github.droidworksstudio.launcher.Constants
import java.io.File
import java.io.IOException
fun View.hideKeyboard() {
this.clearFocus()
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(windowToken, 0)
}
fun View.showKeyboard(show: Boolean = true) {
if (show.not()) return
if (this.requestFocus())
this.postDelayed({
this.findViewById<EditText>(androidx.appcompat.R.id.search_src_text).apply {
isCursorVisible = false
}
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
@Suppress("DEPRECATION")
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY)
}, 100)
}
fun Context.openSearch(query: String? = null) {
val intent = Intent(Intent.ACTION_WEB_SEARCH)
intent.putExtra(SearchManager.QUERY, query ?: "")
startActivity(intent)
}
fun Context.openUrl(url: String) {
if (url.isEmpty()) return
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(url)
startActivity(intent)
}
fun Context.searchOnPlayStore(query: String? = null): Boolean {
return try {
val playStoreIntent = Intent(Intent.ACTION_VIEW)
@@ -78,7 +40,8 @@ fun Context.searchCustomSearchEngine(searchQuery: String? = null): Boolean {
}
fun Context.backupSharedPreferences(backupFileName: String) {
val sharedPreferences: SharedPreferences = this.getSharedPreferences(Constants.PREFS_FILENAME, 0)
val sharedPreferences: SharedPreferences =
this.getSharedPreferences(Constants.PREFS_FILENAME, 0)
val allPrefs = sharedPreferences.all
val backupFile = File(filesDir, backupFileName)
@@ -116,7 +79,8 @@ fun Context.backupSharedPreferences(backupFileName: String) {
}
fun Context.restoreSharedPreferences(backupFileName: String) {
val sharedPreferences: SharedPreferences = this.getSharedPreferences(Constants.PREFS_FILENAME, 0)
val sharedPreferences: SharedPreferences =
this.getSharedPreferences(Constants.PREFS_FILENAME, 0)
val editor = sharedPreferences.edit()
val backupFile = File(filesDir, backupFileName)
@@ -127,7 +91,11 @@ fun Context.restoreSharedPreferences(backupFileName: String) {
backupFile.forEachLine { line ->
val (key, value) = line.split("=", limit = 2)
when {
value.toBooleanStrictOrNull() != null -> editor.putBoolean(key, value.toBoolean())
value.toBooleanStrictOrNull() != null -> editor.putBoolean(
key,
value.toBoolean()
)
value.toIntOrNull() != null -> editor.putInt(key, value.toInt())
value.toFloatOrNull() != null -> editor.putFloat(key, value.toFloat())
value.toLongOrNull() != null -> editor.putLong(key, value.toLong())
@@ -145,20 +113,4 @@ fun Context.restoreSharedPreferences(backupFileName: String) {
} else {
println("Backup file does not exist.")
}
}
fun Fragment.restartApp() {
val packageManager = requireContext().packageManager
val intent = packageManager.getLaunchIntentForPackage(requireContext().packageName)
intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
if (intent != null) {
startActivity(intent)
}
requireActivity().finish()
}
fun Context.isPackageInstalled(packageName: String, userHandle: UserHandle = android.os.Process.myUserHandle()): Boolean {
val launcher = getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
val activityInfo = launcher.getActivityList(packageName, userHandle)
return activityInfo.size > 0
}

View File

@@ -24,6 +24,7 @@ import android.view.WindowManager
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.widget.LinearLayoutCompat
import com.github.droidworksstudio.ktx.showLongToast
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.github.droidworksstudio.launcher.Constants
import com.github.droidworksstudio.launcher.R
@@ -163,7 +164,7 @@ class AppHelper @Inject constructor() {
if (intent != null) {
context.startActivity(intent)
} else {
showToast(context, "Failed to open the application")
context.showLongToast("Failed to open the application")
}
}
@@ -208,7 +209,7 @@ class AppHelper @Inject constructor() {
} catch (e: ActivityNotFoundException) {
// Digital Wellbeing app is not installed or cannot be opened
// Handle this case as needed
showToast(context, "Digital Wellbeing is not available on this device.")
context.showLongToast("Digital Wellbeing is not available on this device.")
}
}
@@ -220,7 +221,7 @@ class AppHelper @Inject constructor() {
} catch (e: ActivityNotFoundException) {
// Battery manager settings cannot be opened
// Handle this case as needed
showToast(context, "Battery manager settings are not available on this device.")
context.showLongToast("Battery manager settings are not available on this device.")
}
}
@@ -256,11 +257,6 @@ class AppHelper @Inject constructor() {
}
}
fun showToast(context: Context, message: String) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
fun showStatusBar(window: Window) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.insetsController?.show(WindowInsets.Type.statusBars())

View File

@@ -5,6 +5,7 @@ import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.github.droidworksstudio.ktx.showLongToast
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import javax.inject.Inject
@@ -66,21 +67,16 @@ class FingerprintHelper @Inject constructor(private val fragment: Fragment) {
}
override fun onAuthenticationFailed() {
appHelper.showToast(
fragment.requireContext(),
fragment.getString(R.string.authentication_failed)
)
fragment.requireContext()
.showLongToast(fragment.getString(R.string.authentication_failed))
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence) {
when (errorCode) {
BiometricPrompt.ERROR_USER_CANCELED -> appHelper.showToast(
fragment.requireContext(),
fragment.getString(R.string.authentication_cancel)
)
BiometricPrompt.ERROR_USER_CANCELED -> fragment.requireContext()
.showLongToast(fragment.getString(R.string.authentication_cancel))
else -> appHelper.showToast(
fragment.requireContext(),
else -> fragment.requireContext().showLongToast(
fragment.getString(R.string.authentication_error)
.format(errorMessage, errorCode)
)
@@ -111,10 +107,8 @@ class FingerprintHelper @Inject constructor(private val fragment: Fragment) {
BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE,
BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> sendToTarget(runNavigation)
else -> appHelper.showToast(
fragment.requireContext(),
fragment.getString(R.string.authentication_failed)
)
else -> fragment.requireContext()
.showLongToast(fragment.getString(R.string.authentication_failed))
}
}
@@ -122,10 +116,8 @@ class FingerprintHelper @Inject constructor(private val fragment: Fragment) {
try {
fragment.findNavController().navigate(runNavigation)
} catch (e: Exception) {
appHelper.showToast(
fragment.requireContext(),
fragment.getString(R.string.authentication_failed)
)
fragment.requireContext()
.showLongToast(fragment.getString(R.string.authentication_failed))
}
}
}

View File

@@ -4,15 +4,16 @@ import android.app.admin.DeviceAdminReceiver
import android.content.Context
import android.content.Intent
import android.widget.Toast
import com.github.droidworksstudio.ktx.showLongToast
class DeviceAdmin : DeviceAdminReceiver() {
override fun onEnabled(context: Context, intent: Intent) {
super.onEnabled(context, intent)
Toast.makeText(context, "Enabled", Toast.LENGTH_SHORT).show()
context.showLongToast("Enabled")
}
override fun onDisabled(context: Context, intent: Intent) {
super.onDisabled(context, intent)
Toast.makeText(context, "Disabled", Toast.LENGTH_SHORT).show()
context.showLongToast("Disabled")
}
}

View File

@@ -11,6 +11,7 @@ import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.fragment.app.viewModels
import com.github.droidworksstudio.ktx.showLongToast
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.data.entities.AppInfo
@@ -74,9 +75,12 @@ class AppInfoBottomSheetFragment(private val appInfo: AppInfo) : BottomSheetDial
bottomDialogHelper.setupDialogStyle(dialog)
binding.run {
bottomSheetFavHidden.text = getString(if (!appInfo.favorite) R.string.bottom_dialog_add_to_home else R.string.bottom_dialog_remove_from_home)
bottomSheetHidden.text = getString(if (!appInfo.hidden) R.string.bottom_dialog_add_to_hidden else R.string.bottom_dialog_remove_to_hidden)
bottomSheetLock.text = getString(if (!appInfo.lock) R.string.bottom_dialog_add_to_lock else R.string.bottom_dialog_remove_to_unlock)
bottomSheetFavHidden.text =
getString(if (!appInfo.favorite) R.string.bottom_dialog_add_to_home else R.string.bottom_dialog_remove_from_home)
bottomSheetHidden.text =
getString(if (!appInfo.hidden) R.string.bottom_dialog_add_to_hidden else R.string.bottom_dialog_remove_to_hidden)
bottomSheetLock.text =
getString(if (!appInfo.lock) R.string.bottom_dialog_add_to_lock else R.string.bottom_dialog_remove_to_unlock)
bottomSheetRename.setText(appInfo.appName)
bottomSheetOrder.text = appInfo.appOrder.toString()
}
@@ -121,7 +125,12 @@ class AppInfoBottomSheetFragment(private val appInfo: AppInfo) : BottomSheetDial
override fun afterTextChanged(s: Editable?) {
if (s.isNullOrEmpty()) {
binding.bottomSheetRename.setHintTextColor(ContextCompat.getColor(requireContext(), R.color.white))
binding.bottomSheetRename.setHintTextColor(
ContextCompat.getColor(
requireContext(),
R.color.white
)
)
binding.bottomSheetRename.hint = appName
appInfo.appName = appName ?: ""
} else {
@@ -149,8 +158,7 @@ class AppInfoBottomSheetFragment(private val appInfo: AppInfo) : BottomSheetDial
binding.bottomSheetLock.setOnClickListener {
if (appInfo.lock) {
fingerHelper.startFingerprintAuth(appInfo, this)
}
else {
} else {
appInfo.lock = true
viewModel.updateAppLock(appInfo, appInfo.lock)
dismiss()
@@ -175,14 +183,19 @@ class AppInfoBottomSheetFragment(private val appInfo: AppInfo) : BottomSheetDial
viewModel.updateAppLock(appInfo, appInfo.lock)
dismiss()
appHelper.showToast(requireContext(), getString(R.string.authentication_succeeded))
requireContext().showLongToast(getString(R.string.authentication_succeeded))
}
override fun onAuthenticationFailed() {
appHelper.showToast(requireContext(), getString(R.string.authentication_failed))
requireContext().showLongToast(getString(R.string.authentication_failed))
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence?) {
appHelper.showToast(requireContext(), getString(R.string.authentication_error))
requireContext().showLongToast(
getString(R.string.authentication_error).format(
errorMessage,
errorCode
)
)
}
}

View File

@@ -8,9 +8,9 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.fragment.app.viewModels
import com.github.droidworksstudio.ktx.showLongToast
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.github.droidworksstudio.launcher.databinding.BottomsheetdialogColorSettingsBinding
import com.github.droidworksstudio.launcher.helper.BottomDialogHelper
@@ -52,7 +52,7 @@ class ColorBottomSheetDialogFragment : BottomSheetDialogFragment() {
observeClickListener()
}
private fun initView(){
private fun initView() {
bottomDialogHelper.setupDialogStyle(dialog)
binding.selectDateTextColor.apply {
@@ -82,7 +82,7 @@ class ColorBottomSheetDialogFragment : BottomSheetDialogFragment() {
}
private fun observeClickListener(){
private fun observeClickListener() {
binding.bottomColorDateView.setOnClickListener {
showColorPickerDialog(
binding.selectDateTextColor,
@@ -165,7 +165,7 @@ class ColorBottomSheetDialogFragment : BottomSheetDialogFragment() {
}
}
}) {
Toast.makeText(context, "onCancel", Toast.LENGTH_SHORT).show()
context?.showLongToast("onCancel")
}
}

View File

@@ -7,7 +7,6 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
@@ -15,17 +14,18 @@ import androidx.lifecycle.coroutineScope
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.github.droidworksstudio.ktx.hideKeyboard
import com.github.droidworksstudio.ktx.openSearch
import com.github.droidworksstudio.ktx.showKeyboard
import com.github.droidworksstudio.ktx.showLongToast
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.FragmentDrawBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.FingerprintHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.helper.hideKeyboard
import com.github.droidworksstudio.launcher.helper.openSearch
import com.github.droidworksstudio.launcher.helper.searchCustomSearchEngine
import com.github.droidworksstudio.launcher.helper.searchOnPlayStore
import com.github.droidworksstudio.launcher.helper.showKeyboard
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
import com.github.droidworksstudio.launcher.listener.ScrollEventListener
@@ -244,19 +244,21 @@ class DrawFragment : Fragment(),
}
override fun onAuthenticationSucceeded(appInfo: AppInfo) {
Toast.makeText(context, getString(R.string.authentication_succeeded), Toast.LENGTH_SHORT)
.show()
context.showLongToast(getString(R.string.authentication_succeeded))
appHelper.launchApp(context, appInfo)
}
override fun onAuthenticationFailed() {
Toast.makeText(context, getString(R.string.authentication_failed), Toast.LENGTH_SHORT)
.show()
context.showLongToast(getString(R.string.authentication_failed))
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence?) {
Toast.makeText(context, getString(R.string.authentication_error), Toast.LENGTH_SHORT)
.show()
context.showLongToast(
getString(R.string.authentication_error).format(
errorMessage,
errorCode
)
)
}
}

View File

@@ -8,7 +8,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
@@ -17,6 +16,7 @@ import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.github.droidworksstudio.ktx.showLongToast
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.FragmentFavoriteBinding
@@ -214,19 +214,21 @@ class FavoriteFragment : Fragment(),
}
override fun onAuthenticationSucceeded(appInfo: AppInfo) {
Toast.makeText(context, getString(R.string.authentication_succeeded), Toast.LENGTH_SHORT)
.show()
context.showLongToast(getString(R.string.authentication_succeeded))
appHelper.launchApp(context, appInfo)
}
override fun onAuthenticationFailed() {
Toast.makeText(context, getString(R.string.authentication_failed), Toast.LENGTH_SHORT)
.show()
context.showLongToast(getString(R.string.authentication_failed))
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence?) {
Toast.makeText(context, getString(R.string.authentication_error), Toast.LENGTH_SHORT)
.show()
context.showLongToast(
getString(R.string.authentication_error).format(
errorMessage,
errorCode
)
)
}
override fun onViewMoved(oldPosition: Int, newPosition: Int): Boolean {

View File

@@ -7,13 +7,13 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.github.droidworksstudio.ktx.showLongToast
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.FragmentHiddenBinding
@@ -155,18 +155,20 @@ class HiddenFragment : Fragment(),
}
override fun onAuthenticationSucceeded(appInfo: AppInfo) {
Toast.makeText(context, getString(R.string.authentication_succeeded), Toast.LENGTH_SHORT)
.show()
context.showLongToast(getString(R.string.authentication_succeeded))
appHelper.launchApp(context, appInfo)
}
override fun onAuthenticationFailed() {
Toast.makeText(context, getString(R.string.authentication_failed), Toast.LENGTH_SHORT)
.show()
context.showLongToast(getString(R.string.authentication_failed))
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence?) {
Toast.makeText(context, getString(R.string.authentication_error), Toast.LENGTH_SHORT)
.show()
context.showLongToast(
getString(R.string.authentication_error).format(
errorMessage,
errorCode
)
)
}
}

View File

@@ -19,6 +19,8 @@ import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.github.droidworksstudio.ktx.hideKeyboard
import com.github.droidworksstudio.ktx.showLongToast
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.accessibility.ActionService
import com.github.droidworksstudio.launcher.data.entities.AppInfo
@@ -26,7 +28,6 @@ import com.github.droidworksstudio.launcher.databinding.FragmentHomeBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.FingerprintHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.helper.hideKeyboard
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
import com.github.droidworksstudio.launcher.listener.ScrollEventListener
@@ -295,13 +296,11 @@ class HomeFragment : Fragment(),
errString: CharSequence
) {
when (errorCode) {
BiometricPrompt.ERROR_USER_CANCELED -> appHelper.showToast(
requireContext(),
BiometricPrompt.ERROR_USER_CANCELED -> requireContext().showLongToast(
getString(R.string.authentication_cancel)
)
else -> appHelper.showToast(
requireContext(),
else -> requireContext().showLongToast(
getString(R.string.authentication_error).format(
errString,
errorCode
@@ -315,10 +314,7 @@ class HomeFragment : Fragment(),
}
override fun onAuthenticationFailed() {
appHelper.showToast(
requireContext(),
getString(R.string.authentication_failed)
)
requireContext().showLongToast(getString(R.string.authentication_failed))
}
})
@@ -364,23 +360,22 @@ class HomeFragment : Fragment(),
override fun onAuthenticationSucceeded(appInfo: AppInfo) {
appHelper.launchApp(context, appInfo)
appHelper.showToast(context, getString(R.string.authentication_succeeded))
requireContext().showLongToast(getString(R.string.authentication_succeeded))
}
override fun onAuthenticationFailed() {
appHelper.showToast(context, getString(R.string.authentication_failed))
requireContext().showLongToast(getString(R.string.authentication_failed))
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence?) {
when (errorCode) {
BiometricPrompt.ERROR_USER_CANCELED -> appHelper.showToast(
requireContext(),
getString(R.string.authentication_cancel)
)
BiometricPrompt.ERROR_USER_CANCELED -> requireContext().showLongToast(getString(R.string.authentication_cancel))
else -> appHelper.showToast(
requireContext(),
getString(R.string.authentication_error).format(errorMessage, errorCode)
else -> requireContext().showLongToast(
getString(R.string.authentication_error).format(
errorMessage,
errorCode
)
)
}
}

View File

@@ -7,16 +7,16 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.github.droidworksstudio.ktx.restartApp
import com.github.droidworksstudio.ktx.showLongToast
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.databinding.FragmentSettingsBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.helper.restartApp
import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
import com.github.droidworksstudio.launcher.listener.ScrollEventListener
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.AlignmentBottomSheetDialogFragment
@@ -154,20 +154,12 @@ class SettingsFragment : Fragment(),
binding.backupView.setOnClickListener {
appHelper.backupSharedPreferences(requireContext())
Toast.makeText(
requireContext(),
getString(R.string.settings_reload_app_backup),
Toast.LENGTH_SHORT
).show()
context.showLongToast(getString(R.string.settings_reload_app_backup))
}
binding.restoreView.setOnClickListener {
appHelper.restoreSharedPreferences(requireContext())
Toast.makeText(
requireContext(),
getString(R.string.settings_reload_app_restore),
Toast.LENGTH_SHORT
).show()
context.showLongToast(getString(R.string.settings_reload_app_restore))
restartApp()
}
}