From 94a8b61afba8b6b7af510207faa398ed4d2f9c41 Mon Sep 17 00:00:00 2001 From: Geoff Powell Date: Tue, 14 May 2024 11:16:43 -0400 Subject: [PATCH] Cleanup preview param --- buildSrc/build.gradle | 9 -- buildSrc/settings.gradle | 9 -- gradle/aarAsJar.gradle | 114 ----------------- gradle/libs.versions.toml | 2 +- paparazzi/api/paparazzi.api | 17 +-- .../app/cash/paparazzi/preview/Snapshot.kt | 72 +---------- .../java/app/cash/paparazzi/preview/Utils.kt | 119 +----------------- 7 files changed, 6 insertions(+), 336 deletions(-) delete mode 100644 buildSrc/build.gradle delete mode 100644 buildSrc/settings.gradle delete mode 100644 gradle/aarAsJar.gradle diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle deleted file mode 100644 index e82ed683b9..0000000000 --- a/buildSrc/build.gradle +++ /dev/null @@ -1,9 +0,0 @@ -repositories { - mavenCentral() - google() -} - -dependencies { - implementation libs.plugin.android - implementation libs.plugin.kotlin -} diff --git a/buildSrc/settings.gradle b/buildSrc/settings.gradle deleted file mode 100644 index 9f631b5bd5..0000000000 --- a/buildSrc/settings.gradle +++ /dev/null @@ -1,9 +0,0 @@ -rootProject.name = 'build-support' - -dependencyResolutionManagement { - versionCatalogs { - libs { - from(files('../gradle/libs.versions.toml')) - } - } -} diff --git a/gradle/aarAsJar.gradle b/gradle/aarAsJar.gradle deleted file mode 100644 index e6ee46bc7a..0000000000 --- a/gradle/aarAsJar.gradle +++ /dev/null @@ -1,114 +0,0 @@ -import com.android.build.gradle.internal.publishing.AndroidArtifacts -import org.gradle.api.artifacts.transform.TransformParameters -import org.gradle.api.internal.artifacts.transform.UnzipTransform -import org.gradle.work.DisableCachingByDefault -import java.nio.file.Files -import java.util.zip.ZipFile - -configurations { - unzip { - attributes.attribute(AndroidArtifacts.ARTIFACT_TYPE, ArtifactTypeDefinition.DIRECTORY_TYPE) - } -} - -configureAarAsJarForConfiguration("compileOnly") -configureAarAsJarForConfiguration("testImplementation") - -dependencies { - registerTransform(UnzipTransform) { - from.attribute(AndroidArtifacts.ARTIFACT_TYPE, ArtifactTypeDefinition.JAR_TYPE) - to.attribute(AndroidArtifacts.ARTIFACT_TYPE, ArtifactTypeDefinition.DIRECTORY_TYPE) - } - registerTransform(IdentityTransform) { - from.attribute(AndroidArtifacts.ARTIFACT_TYPE, "jar") - to.attribute(AndroidArtifacts.ARTIFACT_TYPE, "aarAsJar") - } - registerTransform(ExtractClassesJarTransform) { - from.attribute(AndroidArtifacts.ARTIFACT_TYPE, "aar") - to.attribute(AndroidArtifacts.ARTIFACT_TYPE, "aarAsJar") - } -} - -def configureAarAsJarForConfiguration(String configuration) { - def aarAsJar = project.configurations - .create("${configuration}AarAsJar") { - canBeResolved = true - attributes.attribute( - AndroidArtifacts.ARTIFACT_TYPE, - "release" - ) - attributes.attribute( - Usage.USAGE_ATTRIBUTE, - project.getObjects().named(Usage, Usage.JAVA_API) - ) - }.incoming - .artifactView { viewConfiguration -> - viewConfiguration.attributes.attribute(AndroidArtifacts.ARTIFACT_TYPE, "aarAsJar") - } - .files - - project.configurations - .getByName(configuration) - .dependencies - .add(project.dependencies.create(aarAsJar)) -} - -@DisableCachingByDefault -abstract class IdentityTransform implements TransformAction { - @PathSensitive(PathSensitivity.ABSOLUTE) - @InputArtifact - abstract Provider getInputArtifact() - - @Override - void transform(TransformOutputs transformOutputs) { - def input = getInputArtifact().get().asFile - if (input.isDirectory()) { - transformOutputs.dir(input) - } else if (input.isFile()) { - transformOutputs.file(input) - } else { - throw new IllegalArgumentException( - "File/directory does not exist: ${input.absolutePath}" - ) - } - } -} - -@DisableCachingByDefault -abstract class ExtractClassesJarTransform implements TransformAction { - @PathSensitive(PathSensitivity.NAME_ONLY) - @InputArtifact - abstract Provider getPrimaryInput() - - @Override - void transform(TransformOutputs outputs) { - ZipFile zip = null - try { - def file = getPrimaryInput().get().asFile - def aarFilename = file.name.substring(0, file.name.lastIndexOf('.')) - zip = new ZipFile(file) - def entries = zip.entries() - while (entries.hasMoreElements()) { - def item = entries.nextElement() - if (item.isDirectory()) continue - - if (item.name == "classes.jar") { - def output = outputs.file(aarFilename + "-" + item.name) - def inputStream = null - try { - inputStream = zip.getInputStream(item) - Files.copy(inputStream, output.toPath()) - } finally { - if (inputStream != null) { - inputStream.close() - } - } - } - } - } finally { - if (zip != null) { - zip.close() - } - } - } -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b48c961209..ad5b35e594 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,7 +25,7 @@ bytebuddy-agent = { module = "net.bytebuddy:byte-buddy-agent", version.ref = "by bytebuddy-core = { module = "net.bytebuddy:byte-buddy", version.ref = "bytebuddy" } 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" } diff --git a/paparazzi/api/paparazzi.api b/paparazzi/api/paparazzi.api index b451ff9db0..b7ab491035 100644 --- a/paparazzi/api/paparazzi.api +++ b/paparazzi/api/paparazzi.api @@ -245,17 +245,8 @@ 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 ()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 (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 { @@ -265,11 +256,7 @@ public class app/cash/paparazzi/preview/PaparazziValuesProvider : com/google/tes } 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 } diff --git a/paparazzi/src/main/java/app/cash/paparazzi/preview/Snapshot.kt b/paparazzi/src/main/java/app/cash/paparazzi/preview/Snapshot.kt index 8c06dcece6..253d2c1773 100644 --- a/paparazzi/src/main/java/app/cash/paparazzi/preview/Snapshot.kt +++ b/paparazzi/src/main/java/app/cash/paparazzi/preview/Snapshot.kt @@ -2,14 +2,9 @@ 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]. @@ -17,55 +12,15 @@ import java.util.Locale 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.flatten(): List = 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]. * @@ -77,28 +32,5 @@ public fun List.flatten(): List = fl public open class PaparazziValuesProvider( private val annotations: List ) : TestParameterValuesProvider { - override fun provideValues(): List = 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 = annotations } diff --git a/paparazzi/src/main/java/app/cash/paparazzi/preview/Utils.kt b/paparazzi/src/main/java/app/cash/paparazzi/preview/Utils.kt index b70b87e662..97c0a4a51e 100644 --- a/paparazzi/src/main/java/app/cash/paparazzi/preview/Utils.kt +++ b/paparazzi/src/main/java/app/cash/paparazzi/preview/Utils.kt @@ -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 Paparazzi.snapshotProvider( - previewData: PaparazziPreviewData.Provider, - 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() } } }