Skip to content

Instantly share code, notes, and snippets.

View NikolaDespotoski's full-sized avatar

Nikola Despotoski NikolaDespotoski

View GitHub Profile
@NikolaDespotoski
NikolaDespotoski / TintModifier.kt
Last active June 28, 2023 21:49
Compose tint modifier that will apply color tint over composable
View TintModifier.kt
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.DrawModifier
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.Paint
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
@NikolaDespotoski
NikolaDespotoski / CameraControllCompose.kt
Created March 4, 2023 16:34
Exposing CameraController in Compose.
View CameraControllCompose.kt
import androidx.camera.core.CameraSelector
import androidx.camera.view.CameraController
import androidx.camera.view.LifecycleCameraController
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@NikolaDespotoski
NikolaDespotoski / MlKitAnalyzerKtx.kt
Created November 22, 2022 17:49
Convert MlKitAnalyzer.Result into kotlin.Result so you can utilize kotlin's Result API
View MlKitAnalyzerKtx.kt
/**
* Converts [MlKitAnalyzer.Result] into [kotlin.Result]
* @param detector Any [Detector]
* @returns [kotlin.Result]
*/
fun <T> MlKitAnalyzer.Result.toResult(detector: Detector<T>): Result<T> =
kotlin.runCatching {
val value = getValue(detector) ?: throw getThrowable(detector)!!
value
}
@NikolaDespotoski
NikolaDespotoski / CancelFlow.kt
Created April 12, 2022 00:00
cancelWhen operator for Kotlin Flow
View CancelFlow.kt
/**
* Cancels current flow when the predicate is matched, throws [CancellationException] up in
* current coroutine.
* @param cause class that will be used as cause for [CancellationException]
* @param predicate if result of this function is [true] then the flow is stopped
*/
inline fun <T> Flow<T>.cancelWhen(
cause: KClass<out Throwable>? = null,
crossinline predicate: (T) -> Boolean
): Flow<T> = transform {
@NikolaDespotoski
NikolaDespotoski / KSPExtensions.kt
Last active February 19, 2023 05:56
KSP extensions
View KSPExtensions.kt
import com.google.devtools.ksp.getClassDeclarationByName
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.*
/**
* Reified function to check if receiver [KSType] is assignable from [T] class
*/
inline fun <reified T> KSType.isAssignableFrom(resolver: Resolver): Boolean {
val classDeclaration = requireNotNull(resolver.getClassDeclarationByName<T>()) {
"Unable to resolve ${KSClassDeclaration::class.simpleName} for type ${T::class.simpleName}"
@NikolaDespotoski
NikolaDespotoski / RegisterForActivityResultDetector.kt
Last active November 2, 2020 15:00
RegisterForActivityResultDetector LINT detector that warns on incorrect usage of registerForActivityResult
View RegisterForActivityResultDetector.kt
/*
* Copyright (C) 2020 Nikola Despotoski
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
@NikolaDespotoski
NikolaDespotoski / FlowIterable.kt
Last active October 5, 2020 23:04
Filter items from Iterable with Flow
View FlowIterable.kt
suspend fun <T, R : Iterable<T>> Flow<Iterable<T>>.filterIterable(predicate: suspend (T) -> Boolean): Flow<R> =
transform {
flow {
val emitted = arrayListOf<T>()
for (item in it) {
if (predicate(item)) {
emitted.add(item)
}
}
emit(emitted)
@NikolaDespotoski
NikolaDespotoski / TaskKt.kt
Created September 8, 2020 21:09
Await Google Play Services Task in coroutine
View TaskKt.kt
suspend fun <TResult> Task<TResult>.awaitTask() =
suspendCancellableCoroutine<Task<TResult>> { continuation ->
addOnCompleteListener {
continuation.resume(it)
}
}
suspend fun <TResult> Task<TResult>.awaitTaskResult() =
suspendCancellableCoroutine<TResult> { continuation ->
addOnCanceledListener {
@NikolaDespotoski
NikolaDespotoski / AnimationKtx.kt
Last active September 8, 2020 12:11
Extensions for Android Animation package.
View AnimationKtx.kt
data class AnimationListenerChain(val animation: Animation, val listener: Animation.AnimationListener = object : Animation.AnimationListener() {
override fun onAnimationStart(animation: Animation?) {}
override fun onAnimationEnd(animation: Animation?) {}
override fun onAnimationRepeat(animation: Animation?) {}
})
inline fun Animation.doOnStart(crossinline onStart: () -> Unit): AnimationListenerChain {
val chain = AnimationListenerChain(this)
@NikolaDespotoski
NikolaDespotoski / ChainActivityResultCallback.kt
Created July 22, 2020 18:06
Chain activity result callbacks using plus operator
View ChainActivityResultCallback.kt
operator fun <O> ActivityResultCallback<O>.plus(another: ActivityResultCallback<O>) = ActivityResultCallback<O> {
this@plus.onActivityResult(it)
another.onActivityResult(it)
}