Last active
June 4, 2022 04:30
-
-
Save mbobiosio/20a89a0b2927163a6e958b311495b52e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Get TAG for class name | |
val Any.TAG: String | |
get() { | |
return if (!javaClass.isAnonymousClass) { | |
val name = javaClass.simpleName | |
/** First 23 chars */ | |
if (name.length > 23 && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) | |
name.substring(0, 23) else name | |
} else { | |
val name = javaClass.name | |
/** Last 23 chars */ | |
if (name.length > 23 && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) | |
name.substring(name.length - 23, name.length) else name | |
} | |
} | |
//Change string from pascal case to snake case | |
@SuppressLint("DefaultLocale") | |
fun pascalCaseToSnakeCase(text: String): String { | |
val matcher = Pattern.compile("(?<=[a-z])[A-Z]").matcher(text) | |
val sb = StringBuffer() | |
while (matcher.find()) { | |
matcher.appendReplacement(sb, "_" + matcher.group().toLowerCase()) | |
} | |
matcher.appendTail(sb) | |
return sb.toString().lowercase(Locale.getDefault()) | |
} | |
/* | |
*Handle safe click listener to avoid double clicks | |
*/ | |
fun View.setSafeClickListener(onSafeClick: (View) -> Unit) { | |
val safeClickListener = SafeClickLister { onSafeClick(it) } | |
setOnClickListener(safeClickListener) | |
} | |
class SafeClickLister(private var defaultInterval: Int = 1000, | |
private val onSafeClick: (View) -> Unit): View.OnClickListener { | |
private var lastItemClicked: Long = 0 | |
override fun onClick(v: View) { | |
if (SystemClock.elapsedRealtime() - lastItemClicked < defaultInterval) return | |
lastItemClicked = SystemClock.elapsedRealtime() | |
onSafeClick(v) | |
} | |
} | |
//End safe click listener | |
/* | |
* This returns the sum value of a string by getting the alphabet position value | |
* e.g A=1, B=2, C=3 | |
*/ | |
fun getAlphabetPositionValue(name: String, surname: String): Int { | |
//Convert name to lower string to treat A and a the same | |
//replace spaces in name to eliminate 0 | |
val signature = name.plus(surname).toLowerCase(Locale.ROOT).replace(" ", "") | |
val signatureSum = signature.sumBy { | |
it - 'a' + 1 | |
} | |
return signatureSum | |
} | |
/* | |
* Material Dialog Extension | |
* */ | |
fun Context.alertDialog( | |
@StyleRes style: Int = 0, | |
dialogBuilder: MaterialAlertDialogBuilder.() -> Unit | |
) { | |
MaterialAlertDialogBuilder(this, style) | |
.apply { | |
setCancelable(false) | |
dialogBuilder() | |
create() | |
show() | |
} | |
} | |
fun MaterialAlertDialogBuilder.negativeButton( | |
text: String? = "No", | |
onClick: (dialogInterface: DialogInterface) -> Unit = { it.dismiss() } | |
) { | |
this.setNegativeButton(text) { dialogInterface, _ -> | |
onClick(dialogInterface) | |
} | |
} | |
fun MaterialAlertDialogBuilder.positiveButton( | |
text: String? = "Yes", | |
onClick: (dialogInterface: DialogInterface) -> Unit = { it.dismiss() } | |
) { | |
this.setPositiveButton(text) { dialogInterface, _ -> | |
onClick(dialogInterface) | |
} | |
} | |
fun MaterialAlertDialogBuilder.neutralButton( | |
text: String? = "OK", | |
onClick: (dialogInterface: DialogInterface) -> Unit = { it.dismiss() } | |
) { | |
this.setNeutralButton(text) { dialogInterface, _ -> | |
onClick(dialogInterface) | |
} | |
} | |
/** | |
* | |
* Safely run some delayed tasks in a view as they will be tied to the lifecycle. | |
* | |
* @param durationInMillis delay task in millisecons | |
* @param dispatcher CoroutineDispatcher, defaults to Dispatchers.Main as view work is done on Main thread | |
* @param block the block of work to be done | |
* | |
* example: | |
* | |
* view.delayOnLifeCycle(500L) { | |
* // Do something | |
* } | |
* | |
* */ | |
fun View.delayOnLifecycle( | |
duration: Long, | |
dispatcher: CoroutineDispatcher = Dispatchers.Main, | |
block: () -> Unit | |
): Job? = findViewTreeLifecycleOwner()?.let { lifecycleOwner -> | |
lifecycleOwner.lifecycle.coroutineScope.launch(dispatcher) { | |
delay(duration) | |
block() | |
} | |
} | |
/* | |
* onActivityResult has been deprecated with updates to androidx.activity:activity-ktx to 1.2.0. | |
* It has deprecated startActivityForResult in favour of registerForActivityResult | |
* This is a Kotlin Extension handle results | |
* Example usage | |
* private val result = registerForResult {result, data -> | |
when (result) { | |
RESULT_OK -> { | |
//Do something | |
} else -> { | |
//Do something | |
} | |
} | |
} | |
* */ | |
fun AppCompatActivity.registerForResult( | |
onResult: (resultCode: Int, data: Intent?) -> Unit | |
): ActivityResultLauncher<Intent> { | |
return this.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> | |
onResult(result.resultCode, result.data) | |
} | |
} | |
//End registerForResult | |
/* | |
* Dealing with TMDB genres? | |
* This will help you fix that | |
* This collects a list of Integers(genres ids) and returns a String(genre name) | |
*/ | |
fun getGenre(ids: List<Int>): String{ | |
var genre="" | |
for(i in ids ){ | |
when (i) { | |
28 -> genre+="Action|" | |
12 -> genre+="Adventure|" | |
16 -> genre+="Animation|" | |
35 -> genre+="Comedy|" | |
80 -> genre+="Crime|" | |
99 -> genre+="Documentary|" | |
18 -> genre+="Drama|" | |
10751 -> genre+="Family|" | |
14 -> genre+="Fantasy|" | |
36 -> genre+="History|" | |
27 -> genre+="Horror|" | |
10402 -> genre+="Music|" | |
9648 -> genre+="Mystery|" | |
10749 -> genre+="Romance|" | |
878 -> genre+="Science Fiction|" | |
10770 -> genre+="TV Movie|" | |
53 -> genre+="Thriller|" | |
10752 -> genre+="War|" | |
37 -> genre+="Western|" | |
else -> genre+="Unresolved symbol:"+i | |
} | |
} | |
if(!genre.equals("")) | |
genre=genre.substring(0,genre.length-1) | |
return genre | |
} | |
//Get all viewGroup children | |
fun ViewGroup.getAllChildren(): List<View> { | |
val children = ArrayList<View>() | |
for (i in 0 until this.childCount) { | |
if (getChildAt(i) is ViewGroup) { | |
children.addAll((getChildAt(i) as ViewGroup).getAllChildren()) | |
} | |
children.add(this.getChildAt(i)) | |
} | |
return children | |
} | |
//Get End Index for MetaData | |
fun getMetaDataEndIndex(content: String): Int { | |
// The "cnt" variable stores how many "---" it has seen. | |
// It is sure that the meta data will be enclosed by only 2 of them, | |
var cnt = 0 | |
// idx is the position where the meta data ends. | |
// We keep on increasing the idx until we are sure that meta data has ended. | |
var idx = 0 | |
while (content[idx].isWhitespace()) idx++ | |
while (cnt != 2) { | |
if (content.substring(idx, idx + 3) == "---") cnt++ | |
idx++ | |
} | |
// Increase idx by 2 because it is still at the | |
// first index of the second "---" exist | |
idx += 2 | |
// ignore further whitespaces as they will be added later if needed. | |
while (content[idx].isWhitespace()) idx++ | |
return idx | |
} | |
// Extract domain from email | |
fun domain(string: String): String? { | |
return string.indexOf('@').let { | |
if (it == 1) null else string.substring(it + 1) | |
} | |
} | |
// Convert map to list of maps | |
fun toListOfMaps(map: Map<String, String>): List<Map<String, String>> { | |
return map.map { (key, value) -> | |
mapOf(key to value) | |
} | |
} | |
// Format String as Credit Card Number | |
/** | |
* How to use | |
* val ccFormatted = "1234567890123456".creditCardFormatted | |
*/ | |
val String.creditCardFormatted: String | |
get() { | |
val preparedString = replace(" ", "").trim() | |
val result = StringBuilder() | |
for (i in preparedString.indices) { | |
if (i % 4 == 0 && i != 0) { | |
result.append(" ") | |
} | |
result.append(preparedString[i]) | |
} | |
return result.toString() | |
} | |
/** | |
Combining 3 different lists together. | |
val strings = listOf("1", "2", "3") | |
val ints = listOf(1, 2, 9) | |
val boolean = listOf(true, false, false) | |
strings.zipThree(ints, boolean) { one, two, three -> | |
Timber.d("$one : $two : $three") | |
} | |
*/ | |
inline fun <T, R, E, V> Iterable<T>.zipThree( | |
other1: Iterable<R>, | |
other2: Iterable<E>, | |
transform: (T, R, E) -> V | |
): List<V> { | |
val first = iterator() | |
val second = other1.iterator() | |
val third = other2.iterator() | |
val list = ArrayList<V>() | |
while (first.hasNext() && second.hasNext() && third.hasNext()) { | |
list.add(transform(first.next(), second.next(), third.next())) | |
} | |
return list | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment