Skip to content

Instantly share code, notes, and snippets.

View NikolaDespotoski's full-sized avatar

Nikola Despotoski NikolaDespotoski

View GitHub Profile
@NikolaDespotoski
NikolaDespotoski / ChainActivityResultCallback.kt
Created July 22, 2020 18:06
Chain activity result callbacks using plus operator
operator fun <O> ActivityResultCallback<O>.plus(another: ActivityResultCallback<O>) = ActivityResultCallback<O> {
this@plus.onActivityResult(it)
another.onActivityResult(it)
}
suspend fun <F : Fragment> FragmentManager.awaitFragmentById(idRes: Int) =
suspendCancellableCoroutine<F> {
val backStackListener = object : FragmentManager.OnBackStackChangedListener {
override fun onBackStackChanged() {
val f = findFragmentById(idRes) as F?
if (f != null) {
removeOnBackStackChangedListener(this)
it.resume(f)
}
}
object SuspendingBleScanner {
suspend fun BluetoothLeScanner.startScan(timeout: Long, scanFilters: List<ScanFilter>? = null, settings: ScanSettings? = null): List<ScanResult> {
check(timeout <= 0L) { "BLE scan timeout must be > 0" }
var scanCallback: ScanCallback? = null
val accumulator = mutableListOf<ScanResult>()
return try {
withTimeout(timeout) {
suspendCancellableCoroutine<List<ScanResult>> { continuation ->
scanCallback = object : ScanCallback() {
fun <I, O> prepareCall(activityResultContractor: ActivityResultContractor<I, O>,activityResultCallback: ActivityResultCallback<O>)
: ActivityResultLauncher<I> = prepareCall(object : ActivityResultContract<I, O>() {
override fun createIntent(input: I): Intent = activityResultContractor.createIntent(input)
override fun parseResult(resultCode: Int, intent: Intent?): O = activityResultContractor.parseResult(resultCode, intent)
}, activityResultCallback)
}
class ProductsViewModel @Inject constructor(
 private val activityResultContractor: ActivityResultContractor<Nothing, String>,
  private val coroutineProvider: CoroutineProvider,
 private val productInteractor: ProductInteractor
) : ViewModel(), ActivityResultCallback<String>,
 ActivityResultContractor<Unit, String> by activityResultContractor{
override fun onActivityResult(result: String?) {
 // do something with the result
 }
@FragmentScope
class ChooseFilterContractor @Inject constructor(private val context: Context) : ActivityResultContractor<Unit, String> {
  override fun createIntent(input: Unit): Intent = Intent(context, ChooseFilterActivity::class.java)
 
override fun parseResult(resultCode: Int, intent: Intent?): String = if (resultCode == Activity.RESULT_OK) {
 intent?.getStringExtra(KEY_FILTER)?: error("Dispatched RESULT_OK, but no payload)
 } else {
 ""
 }
}
@NikolaDespotoski
NikolaDespotoski / LazyLiveDataBlockInitializer.kt
Created March 18, 2020 13:06
Lazy Live Data block initializer
fun <T> lazyLiveData(function: suspend LiveDataScope<T>.() -> Unit) = object : kotlin.Lazy<LiveData<T>> {
lateinit var liveDataCached: LiveData<T>
override val value: LiveData<T>
get() {
if (!isInitialized()) {
liveDataCached = liveData { function() }
}
return liveDataCached
}
abstract class LiveDataSharedPreferences<T>(val sharedPreferences: SharedPreferences,
val key: String,
val default: T) : MutableLiveData<T>(), SharedPreferences.OnSharedPreferenceChangeListener {
override fun onActive() {
super.onActive()
sharedPreferences.registerOnSharedPreferenceChangeListener(this)
}
override fun onInactive() {
super.onInactive()
@NikolaDespotoski
NikolaDespotoski / ViewModelProperty.kt
Created October 24, 2019 23:53
ViewModel Kotlin Property
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
import kotlin.reflect.jvm.javaType
class FragmentViewModelProperty<VM : ViewModel>(private val viewModelFactoryProvider: () -> ViewModelProvider.Factory? = { null },
@NikolaDespotoski
NikolaDespotoski / kotlinLast.kt
Created July 23, 2019 08:32
Kotlin Flows last operator
public fun <T> Flow<T>.last(): Flow<T> = flow {
try {
var last : Any? = null
collect { value ->
last = value
}
emit(last as T)
} catch (e: Throwable) {
// Nothing, bail out
}