Skip to content

Instantly share code, notes, and snippets.

View gpeal's full-sized avatar

Gabriel Peal gpeal

View GitHub Profile
@gpeal
gpeal / ContributesApiCodeGenerator.kt
Last active February 12, 2024 20:10
Anvil Code Generator
package com.tonal.trainer.anvilcompilers
import com.google.auto.service.AutoService
import com.squareup.anvil.annotations.ContributesTo
import com.squareup.anvil.compiler.api.AnvilContext
import com.squareup.anvil.compiler.api.CodeGenerator
import com.squareup.anvil.compiler.api.GeneratedFile
import com.squareup.anvil.compiler.api.createGeneratedFile
import com.squareup.anvil.compiler.internal.asClassName
import com.squareup.anvil.compiler.internal.buildFile
@gpeal
gpeal / FragmentA.kt
Last active December 27, 2023 06:50
View Binding Delegates
class WifiNetworksFragment : TonalFragment(R.layout.wifi_networks_fragment) {
// This automatically creates and clears the binding in a lifecycle-aware way.
private val binding: WifiNetworksFragmentBinding by viewBinding()
...
}
class WifiNetworkView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
import timber.log.Timber
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
class MyClass {
// This will automatically have the TAG "MyClass"
private val log by timber()
fun logSomething() {
log.i("Hello")
@gpeal
gpeal / ConflatedJob.kt
Last active September 5, 2023 19:10
Conflated Job
class MyClass(private val scope: CoroutineScope) {
private val job = ConflatedJob()
fun retry() {
retryJob += scope.launch {
delay(Long.MAX_VALUE)
}
}
}
@gpeal
gpeal / uniqueObservable.kt
Created March 14, 2021 02:34
Unique Observable
/**
* Like Delegates.observable except it only calls the callback when the value actually changes.
*/
public inline fun <T> uniqueObservable(initialValue: T, emitInitial: Boolean = false, crossinline onChange: (value: T) -> Unit): ReadWriteProperty<Any?, T> {
if (emitInitial) onChange(initialValue)
return object : ObservableProperty<T>(initialValue) {
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) {
if (oldValue != newValue) onChange(newValue)
}
}
@gpeal
gpeal / fadeTo.kt
Last active August 19, 2023 21:22
Fade To
/**
* Fade a view to visible or gone. This function is idempotent - it can be called over and over again with the same
* value without affecting an in-progress animation.
*/
fun View.fadeTo(visible: Boolean, duration: Long = 500, startDelay: Long = 0, toAlpha: Float = 1f) {
// Make this idempotent.
val tagKey = "fadeTo".hashCode()
if (visible == isVisible && animation == null && getTag(tagKey) == null) return
if (getTag(tagKey) == visible) return
@gpeal
gpeal / s1-metrics-collector.sh
Created March 9, 2023 22:41
SentinelOne metrics collector
sentinelctl metrics enable ; sentinelctl metrics dump > /tmp/metrics.json ; count=0 ; while :; do clear; sentinelctl metrics dump > /tmp/metrics-tmp.log ; if grep -q "no metrics available" /tmp/metrics-tmp.log; then echo "Metrics Disabled" ; exit ; fi ; if [ $count = 0 ]; then echo "Starting Metrics Collection" ; count=$((count + 10)) ; else echo "Metrics have been collected for $count seconds" ; count=$((count + 10)) ; fi ; sleep 3 ; diff -u /tmp/metrics.json /tmp/metrics-tmp.log > /tmp/metrics-new.patch ; patch /tmp/metrics.json /tmp/metrics-new.patch ; sleep 3 ; echo "Collecting Metrics & writing to /tmp/metrics.json" ; sleep 4 ; done
@gpeal
gpeal / BroadcastReceiver.kt
Last active February 21, 2023 11:07
Coroutine Broadcast Receivers
context.registerReceiverInScope(scope, WifiManager.WIFI_STATE_CHANGED_ACTION) { intent ->
val state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED)
// Use wifi state here
}
/**
* Register a broadcast receiver in the given coroutine scope for any of the specified actions
* and call the callback when it is invoked.
*/
fun Context.registerReceiverInScope(
class GuidedWorkoutFragment : TonalFragment(R.layout.guided_workout_fragment) {
override val daggerComponent: GuidedWorkoutMergeComponent by fragmentComponent { scope, app ->
app.bindings<GuidedWorkoutMergeComponent.Parent>().guidedWorkoutComponentBuilder()
.coroutineScope(WorkoutCoroutineScope(scope))
.args(arg)
.build()
}
}
export {};
export type PropertyValue<TValue> = TValue extends Array<infer AValue>
? Array<AValue extends infer TUnpacked & {} ? TUnpacked : AValue>
: TValue extends infer TUnpacked & {}
? TUnpacked
: TValue;
export type Fallback<T> = { [P in keyof T]: T[P] | NonNullable<T[P]>[] };