Skip to content

Commit

Permalink
Cleanup preview param
Browse files Browse the repository at this point in the history
  • Loading branch information
geoff-powell committed May 14, 2024
1 parent d8403e6 commit ebe41be
Show file tree
Hide file tree
Showing 4 changed files with 6 additions and 210 deletions.
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ bytebuddy-core = { module = "net.bytebuddy:byte-buddy", version.ref = "bytebuddy

compose-compiler = { module = "androidx.compose.compiler:compiler", version.ref = "composeCompiler" }
compose-runtime = { module = "androidx.compose.runtime:runtime", version.ref = "compose" }
composeUi-foundation = { module = "androidx.compose.foundation:foundation" }
composeUi-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "compose" }
composeUi-material = { module = "androidx.compose.material:material", version.ref = "compose" }
composeUi-uiTooling = { module = "androidx.compose.ui:ui-tooling" }

Expand Down
23 changes: 2 additions & 21 deletions paparazzi/api/paparazzi.api
Original file line number Diff line number Diff line change
Expand Up @@ -245,31 +245,12 @@ public final class app/cash/paparazzi/preview/ComposableSingletons$SnapshotKt {
public final class app/cash/paparazzi/preview/ComposableSingletons$UtilsKt {
public static final field INSTANCE Lapp/cash/paparazzi/preview/ComposableSingletons$UtilsKt;
public static field lambda-1 Lkotlin/jvm/functions/Function3;
public static field lambda-2 Lkotlin/jvm/functions/Function3;
public fun <init> ()V
public final fun getLambda-1$paparazzi ()Lkotlin/jvm/functions/Function3;
public final fun getLambda-2$paparazzi ()Lkotlin/jvm/functions/Function3;
}

public final class app/cash/paparazzi/preview/DefaultLocaleRule : org/junit/rules/TestRule {
public static final field $stable I
public fun <init> (Ljava/lang/String;)V
public fun apply (Lorg/junit/runners/model/Statement;Lorg/junit/runner/Description;)Lorg/junit/runners/model/Statement;
public final fun getLocale ()Ljava/lang/String;
}

public class app/cash/paparazzi/preview/PaparazziValuesProvider : com/google/testing/junit/testparameterinjector/TestParameter$TestParameterValuesProvider {
public static final field $stable I
public fun <init> (Ljava/util/List;)V
public fun provideValues ()Ljava/util/List;
}

public final class app/cash/paparazzi/preview/SnapshotKt {
public static final fun deviceConfig (Lapp/cash/paparazzi/annotations/PaparazziPreviewData;Lapp/cash/paparazzi/DeviceConfig;)Lapp/cash/paparazzi/DeviceConfig;
public static synthetic fun deviceConfig$default (Lapp/cash/paparazzi/annotations/PaparazziPreviewData;Lapp/cash/paparazzi/DeviceConfig;ILjava/lang/Object;)Lapp/cash/paparazzi/DeviceConfig;
public static final fun flatten (Ljava/util/List;)Ljava/util/List;
public static final fun locale (Lapp/cash/paparazzi/annotations/PaparazziPreviewData;)Ljava/lang/String;
public static final fun snapshot (Lapp/cash/paparazzi/Paparazzi;Lapp/cash/paparazzi/annotations/PaparazziPreviewData;Ljava/lang/String;ZLkotlin/jvm/functions/Function3;)V
public static synthetic fun snapshot$default (Lapp/cash/paparazzi/Paparazzi;Lapp/cash/paparazzi/annotations/PaparazziPreviewData;Ljava/lang/String;ZLkotlin/jvm/functions/Function3;ILjava/lang/Object;)V
public static final fun snapshot (Lapp/cash/paparazzi/Paparazzi;Lapp/cash/paparazzi/annotations/PaparazziPreviewData;Ljava/lang/String;Lkotlin/jvm/functions/Function3;)V
public static synthetic fun snapshot$default (Lapp/cash/paparazzi/Paparazzi;Lapp/cash/paparazzi/annotations/PaparazziPreviewData;Ljava/lang/String;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)V
}

72 changes: 2 additions & 70 deletions paparazzi/src/main/java/app/cash/paparazzi/preview/Snapshot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,70 +2,25 @@
package app.cash.paparazzi.preview

import androidx.compose.runtime.Composable
import app.cash.paparazzi.DeviceConfig
import app.cash.paparazzi.Paparazzi
import app.cash.paparazzi.annotations.PaparazziPreviewData
import com.google.testing.junit.testparameterinjector.TestParameter.TestParameterValuesProvider
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
import java.util.Locale

/**
* Take a snapshot of the given [previewData].
*/
public fun Paparazzi.snapshot(
previewData: PaparazziPreviewData,
name: String? = null,
localInspectionMode: Boolean = true,
wrapper: @Composable (@Composable () -> Unit) -> Unit = { it() }
) {
when (previewData) {
is PaparazziPreviewData.Default -> snapshotDefault(previewData, name, localInspectionMode, wrapper)
is PaparazziPreviewData.Provider<*> -> snapshotProvider(previewData, name, localInspectionMode, wrapper)
is PaparazziPreviewData.Default -> snapshotDefault(previewData, name, wrapper)
is PaparazziPreviewData.Empty -> Unit
is PaparazziPreviewData.Error -> throw Exception(previewData.message)
}
}

/**
* Generate a Paparazzi DeviceConfig for the given preview
* using the given [default] DeviceConfig.
*
* default: The IDE renders a preview with a higher resolution than
* the default device set by Paparazzi (which is currently Nexus 5). Defaulting to
* a larger device brings the previews and snapshots closer in parity.
*/
public fun PaparazziPreviewData.deviceConfig(
default: DeviceConfig = DeviceConfig.PIXEL_5
): DeviceConfig = when (this) {
is PaparazziPreviewData.Default -> preview.deviceConfig(default)
is PaparazziPreviewData.Provider<*> -> preview.deviceConfig(default)
else -> default
}

/**
* Returns a locale for the given preview, or null if error or empty.
*/
public fun PaparazziPreviewData.locale(): String? = when (this) {
is PaparazziPreviewData.Default -> preview.locale
is PaparazziPreviewData.Provider<*> -> preview.locale
else -> null
}

/**
* Convert a list of generated [PaparazziPreviewData]
* to a flat list of [PaparazziPreviewData]s.
*/
public fun List<PaparazziPreviewData>.flatten(): List<PaparazziPreviewData> = flatMap {
when (it) {
is PaparazziPreviewData.Provider<*> -> List(it.previewParameter.values.count()) { i ->
it.withPreviewParameterIndex(i)
}
else -> listOf(it)
}
}

/**
* A `@TestParameter` values provider for the given [annotations].
*
Expand All @@ -77,28 +32,5 @@ public fun List<PaparazziPreviewData>.flatten(): List<PaparazziPreviewData> = fl
public open class PaparazziValuesProvider(
private val annotations: List<PaparazziPreviewData>
) : TestParameterValuesProvider {
override fun provideValues(): List<PaparazziPreviewData> = annotations.flatten()
}

/**
* Enforce a particular default locale for a test. Resets back to default on completion.
*/
public class DefaultLocaleRule(public val locale: String?) : TestRule {
override fun apply(
base: Statement,
description: Description
): Statement {
return object : Statement() {
override fun evaluate() {
val default = Locale.getDefault()

try {
locale?.let { Locale.setDefault(Locale.forLanguageTag(it)) }
base.evaluate()
} finally {
Locale.setDefault(default)
}
}
}
}
override fun provideValues(): List<PaparazziPreviewData> = annotations
}
119 changes: 1 addition & 118 deletions paparazzi/src/main/java/app/cash/paparazzi/preview/Utils.kt
Original file line number Diff line number Diff line change
@@ -1,133 +1,16 @@
// Copyright Square, Inc.
package app.cash.paparazzi.preview

import android.content.res.Configuration
import android.util.DisplayMetrics
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalInspectionMode
import app.cash.paparazzi.DeviceConfig
import app.cash.paparazzi.Paparazzi
import app.cash.paparazzi.annotations.PaparazziPreviewData
import app.cash.paparazzi.annotations.PreviewData
import com.android.resources.NightMode
import com.android.resources.UiMode
import java.util.Locale
import kotlin.math.roundToInt

internal fun String.deviceConfig() = when (this) {
"id:Nexus 7" -> DeviceConfig.NEXUS_7
"id:Nexus 7 2013" -> DeviceConfig.NEXUS_7_2012
"id:Nexus 5" -> DeviceConfig.NEXUS_5
"id:Nexus 6" -> DeviceConfig.NEXUS_7
"id:Nexus 9" -> DeviceConfig.NEXUS_10
"name:Nexus 10" -> DeviceConfig.NEXUS_10
"id:Nexus 5X" -> DeviceConfig.NEXUS_5
"id:Nexus 6P" -> DeviceConfig.NEXUS_7
"id:pixel_c" -> DeviceConfig.PIXEL_C
"id:pixel" -> DeviceConfig.PIXEL
"id:pixel_xl" -> DeviceConfig.PIXEL_XL
"id:pixel_2" -> DeviceConfig.PIXEL_2
"id:pixel_2_xl" -> DeviceConfig.PIXEL_2_XL
"id:pixel_3" -> DeviceConfig.PIXEL_3
"id:pixel_3_xl" -> DeviceConfig.PIXEL_3_XL
"id:pixel_3a" -> DeviceConfig.PIXEL_3A
"id:pixel_3a_xl" -> DeviceConfig.PIXEL_3A_XL
"id:pixel_4" -> DeviceConfig.PIXEL_4
"id:pixel_4_xl" -> DeviceConfig.PIXEL_4_XL
"id:pixel_5" -> DeviceConfig.PIXEL_5
"id:pixel_6" -> DeviceConfig.PIXEL_6
"id:pixel_6_pro" -> DeviceConfig.PIXEL_6_PRO
"id:wearos_small_round" -> DeviceConfig.WEAR_OS_SMALL_ROUND
"id:wearos_square" -> DeviceConfig.WEAR_OS_SQUARE
else -> null
}

internal fun Int.uiMode() = when (this and Configuration.UI_MODE_TYPE_MASK) {
Configuration.UI_MODE_TYPE_NORMAL -> UiMode.NORMAL
Configuration.UI_MODE_TYPE_CAR -> UiMode.CAR
Configuration.UI_MODE_TYPE_DESK -> UiMode.DESK
Configuration.UI_MODE_TYPE_APPLIANCE -> UiMode.APPLIANCE
Configuration.UI_MODE_TYPE_WATCH -> UiMode.WATCH
Configuration.UI_MODE_TYPE_VR_HEADSET -> UiMode.VR_HEADSET
else -> null
}

internal fun Int.nightMode() = when (this and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_NO -> NightMode.NOTNIGHT
Configuration.UI_MODE_NIGHT_YES -> NightMode.NIGHT
else -> null
}

internal fun String.localeQualifierString() =
Locale.forLanguageTag(this).run {
"$language-r$country"
}

internal fun PreviewData?.deviceConfig(defaultDeviceConfig: DeviceConfig) =
(this?.device?.deviceConfig() ?: defaultDeviceConfig).let { config ->
config.copy(
screenWidth = this?.widthDp?.toPx(config.density.dpiValue) ?: config.screenWidth,
screenHeight = this?.heightDp?.toPx(config.density.dpiValue) ?: config.screenHeight,
fontScale = this?.fontScale ?: config.fontScale,
uiMode = this?.uiMode?.uiMode() ?: config.uiMode,
nightMode = this?.uiMode?.nightMode() ?: config.nightMode,
locale = this?.locale?.localeQualifierString() ?: config.locale
)
}

private fun Int.toPx(dpi: Int) =
(this * (dpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)).roundToInt()

internal fun Paparazzi.snapshotDefault(
previewData: PaparazziPreviewData.Default,
name: String?,
localInspectionMode: Boolean,
wrapper: @Composable (@Composable () -> Unit) -> Unit = { it() }
) {
snapshot(name) {
PreviewWrapper(previewData.preview.backgroundColor, localInspectionMode) {
wrapper { previewData.composable() }
}
}
}

internal fun <T> Paparazzi.snapshotProvider(
previewData: PaparazziPreviewData.Provider<T>,
name: String?,
localInspectionMode: Boolean,
wrapper: @Composable (@Composable () -> Unit) -> Unit = { it() }
) {
val paramValue = previewData.previewParameter.values
.elementAt(previewData.previewParameter.index)

snapshot(name) {
PreviewWrapper(previewData.preview.backgroundColor, localInspectionMode) {
wrapper { previewData.composable(paramValue) }
}
}
}

@Composable
private fun PreviewWrapper(
backgroundColor: String?,
localInspectionMode: Boolean,
content: @Composable BoxScope.() -> Unit
) {
CompositionLocalProvider(LocalInspectionMode provides localInspectionMode) {
Box(
modifier = Modifier
.then(
backgroundColor?.toLong(16)
?.let { Modifier.background(Color(it)) }
?: Modifier
),
content = content
)
wrapper { previewData.composable() }
}
}

0 comments on commit ebe41be

Please sign in to comment.