Skip to content

Instantly share code, notes, and snippets.

@rharter
rharter / RoundedRect.kt
Created September 20, 2022 03:17
A simple demonstration of rectangles with extra large corner radii. From https://ryanharter.com/blog/2022/09/rounded-corners/
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.Slider
import androidx.compose.material.Surface
import androidx.compose.material.Text
@rharter
rharter / make_launcher.sh
Created September 23, 2020 16:08
Using this script you can create a tiny macOS app that will always launch the latest version of any JetBrains Toolbox installed IDE. Simply pass the target IDE application as the first argument and the script will create a launcher that you can add to your dock that will always point to the latest installed version of the IDE.
#!/bin/bash
APP_DIR=$1
APP_SCRIPT_NAME="$(ls "${APP_DIR}/Contents/MacOS/")"
APP_FILE_NAME="$(basename "${APP_DIR}")"
CHANNEL_DIR="$(dirname "$(dirname "$1")")"
CHANNEL_NAME="$(basename "$CHANNEL_DIR")"
TOOLBOX_APP_NAME="$(basename "$(dirname "$CHANNEL_DIR")")"
@rharter
rharter / StoreRepository.kt
Created August 19, 2020 14:50
Extension function to convert a store, which emits a stream of **events**, to a repository which emits a stream of **states**. This hides implementation details, like which datasource is providing the data, from consumers.
sealed class Resource<T> {
data class Loading<T>(val data: T? = null, val message: Int? = null) : Resource<T>()
data class Success<T>(val data: T) : Resource<T>()
data class Error<T>(val throwable: Throwable?, val data: T? = null) : Resource<T>()
}
fun <T> Resource<T>.dataOrNull(): T? = when (this) {
is Resource.Loading -> data
is Resource.Success -> data
is Resource.Error -> data
@rharter
rharter / Scoped.kt
Last active August 12, 2024 09:48
A kotlin property delegate to scope any object to an android lifecycle. Blog post at https://ryanharter.com/blog/easy-android-scopes/
import androidx.lifecycle.get
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner
/**
* Returns a property delegate to access the wrapped value, which will be retained for the
* duration of the lifecycle of this [ViewModelStoreOwner].
*
@rharter
rharter / Notes.md
Last active September 10, 2019 15:31

Dagger/Android with Internal Dependencies

I’ve figured out how to do what I wanted, though without some generation I’m not actually sure it’s worth it. Here’s a bunch more code with the solution I’ve figured out, in case anyone knows how to auto-generate this stuff, or if there’s a better way to do this.

The Goal: Allow use of Dagger-android AndroidInjectors without needing to make all dependencies of the target public.

The Scenario: I have a modular app where each feature is a separate module (among others). I have always hated making the ViewModels/ViewStates/ViewActions and other internal parts of the feature public, but that’s required with the current Dagger-android subcomponent approach.

Here’s my module setup:

@rharter
rharter / InjectableActivityScenario.kt
Created July 19, 2019 15:27
An ActivityScenario that allows you to use Dagger Android's automatic, lifecycle based injection without making your Application class `open`, or overriding it in tests.
package com.pixite.pigment.testing
import android.app.Activity
import android.app.Instrumentation
import android.content.Context
import android.content.Intent
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
@rharter
rharter / InjectableActivityTestRule.kt
Last active December 6, 2021 12:07
Test Rule that allows you to use Dagger Android's automatic lifecycle based injection without making your Application class `open`, or overriding it in tests.
package com.pixite.pigment.testing
import android.app.Activity
import android.app.Application
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
@rharter
rharter / config.yaml
Created May 24, 2018 21:07
Example Circle CI config file
version: 2.0
defaults: &defaults
docker:
- image: menny/android_ndk:latest
working_directory: ~/pigment
environment:
_JAVA_OPTIONS: "-Xmx1400m -XX:ParallelGCThreads=2 -XX:ConcGCThreads=2 -XX:ParallelGCThreads=2 -Djava.util.concurrent.ForkJoinPool.common.parallelism=2"
TERM: dumb
@rharter
rharter / LiveEvent.kt
Last active April 8, 2020 20:31
LiveData that only delivers new events to observers.
import android.arch.lifecycle.LifecycleOwner
import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MediatorLiveData
import android.arch.lifecycle.Observer
fun <T> LiveData<T>.toLiveEvent(): LiveEvent<T> {
return when (this) {
is LiveEvent -> this
else -> LiveEvent<T>().apply {
@rharter
rharter / ViewCompatExt.kt
Last active February 4, 2018 01:12
Extension methods to easily provide all functionality in ViewCompat. This makes it super easy to see when there is a compat method available in code completion right alongside the framework methods.
import android.content.ClipData
import android.graphics.Paint
import android.os.Build
import android.os.Bundle
import android.support.v4.view.*
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat
import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat
import android.view.*
/**