Skip to content

Commit

Permalink
Refactor RoborazziComposeConfigBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
takahirom committed Dec 5, 2024
1 parent 1a687c4 commit d451213
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 70 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
.idea/modules
/.intellijPlatform/
.idea/runConfigurations.xml
.idea/shelf
*.iml
*.ipr
.DS_Store
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,49 +13,52 @@ import sergio.sastre.composable.preview.scanner.core.preview.ComposablePreview
fun ComposablePreview<AndroidPreviewInfo>.captureRoboImage(
filePath: String,
roborazziOptions: RoborazziOptions = provideRoborazziContext().options,
configBuilder: RoborazziComposeConfigBuilder = this.toRoborazziComposeConfigBuilder()
roborazziComposeOptions: RoborazziComposeOptions = this.toRoborazziComposeOptions()
) {
if (!roborazziOptions.taskType.isEnabled()) return
val composablePreview = this
captureRoboImage(filePath, roborazziOptions, configBuilder) {
captureRoboImage(filePath, roborazziOptions, roborazziComposeOptions) {
composablePreview()
}
}

@ExperimentalRoborazziApi
fun ComposablePreview<AndroidPreviewInfo>.toRoborazziComposeConfigBuilder() =
RoborazziComposeConfigBuilder()
.size(
fun ComposablePreview<AndroidPreviewInfo>.toRoborazziComposeOptions(): RoborazziComposeOptions {
return RoborazziComposeOptions {
size(
widthDp = previewInfo.widthDp,
heightDp = previewInfo.heightDp
)
.background(
background(
showBackground = previewInfo.showBackground,
backgroundColor = previewInfo.backgroundColor
)
.locale(previewInfo.locale)
.uiMode(previewInfo.uiMode)
.previewDevice(previewInfo.device)
.fontScale(previewInfo.fontScale)
locale(previewInfo.locale)
uiMode(previewInfo.uiMode)
previewDevice(previewInfo.device)
fontScale(previewInfo.fontScale)
}
}


@Suppress("UnusedReceiverParameter")
@Deprecated(
message = "Use previewInfo.toRoborazziComposeConfigBuilder().apply(scenario, composeContent) or ComposablePreview<AndroidPreviewInfo>.captureRoboImage() instead",
replaceWith = ReplaceWith("previewInfo.toRoborazziComposeConfigBuilder().apply(scenario, composeContent)"),
message = "Use previewInfo.toRoborazziComposeOptions().apply(scenario, composeContent) or ComposablePreview<AndroidPreviewInfo>.captureRoboImage() instead",
replaceWith = ReplaceWith("previewInfo.toRoborazziComposeOptions().apply(scenario, composeContent)"),
level = DeprecationLevel.ERROR
)
fun ComposablePreview<AndroidPreviewInfo>.applyToRobolectricConfiguration() {
throw UnsupportedOperationException("Use previewInfo.toRoborazziComposeConfigBuilder().apply(scenario, composeContent) or ComposablePreview<AndroidPreviewInfo>.captureRoboImage() instead")
throw UnsupportedOperationException("Use previewInfo.toRoborazziComposeOptions().apply(scenario, composeContent) or ComposablePreview<AndroidPreviewInfo>.captureRoboImage() instead")
}

@ExperimentalRoborazziApi
fun RoborazziComposeConfigBuilder.previewDevice(previewDevice: String) =
with(RoborazziComposePreviewDeviceConfig(previewDevice))
fun RoborazziComposeOptions.Builder.previewDevice(previewDevice: String): RoborazziComposeOptions.Builder {
return addOption(RoborazziComposePreviewDeviceOption(previewDevice))
}

@ExperimentalRoborazziApi
data class RoborazziComposePreviewDeviceConfig(private val previewDevice: String) :
RoborazziComposeSetupConfig {
data class RoborazziComposePreviewDeviceOption(private val previewDevice: String) :
RoborazziComposeSetupOption {
override fun configure() {
if (previewDevice.isNotBlank()) {
// Requires `io.github.sergio-sastre.ComposablePreviewScanner:android:0.4.0` or later
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ fun captureRoboImage(
captureRoboImage(
file = file,
roborazziOptions = roborazziOptions,
configBuilder = RoborazziComposeConfigBuilder(),
roborazziComposeOptions = RoborazziComposeOptions(),
content = content
)
}
Expand All @@ -39,13 +39,13 @@ fun captureRoboImage(
fun captureRoboImage(
filePath: String = DefaultFileNameGenerator.generateFilePath(),
roborazziOptions: RoborazziOptions = provideRoborazziContext().options,
configBuilder: RoborazziComposeConfigBuilder = RoborazziComposeConfigBuilder(),
roborazziComposeOptions: RoborazziComposeOptions = RoborazziComposeOptions(),
content: @Composable () -> Unit,
) {
captureRoboImage(
file = fileWithRecordFilePathStrategy(filePath),
roborazziOptions = roborazziOptions,
configBuilder = configBuilder,
roborazziComposeOptions = roborazziComposeOptions,
content = content
)
}
Expand All @@ -54,13 +54,13 @@ fun captureRoboImage(
fun captureRoboImage(
file: File,
roborazziOptions: RoborazziOptions = provideRoborazziContext().options,
configBuilder: RoborazziComposeConfigBuilder = RoborazziComposeConfigBuilder(),
roborazziComposeOptions: RoborazziComposeOptions = RoborazziComposeOptions(),
content: @Composable () -> Unit,
) {
if (!roborazziOptions.taskType.isEnabled()) return
launchRoborazziTransparentActivity { activityScenario ->
val configuredContent = configBuilder
.configure(activityScenario) {
val configuredContent = roborazziComposeOptions
.configured(activityScenario) {
content()
}
activityScenario.captureRoboImage(file, roborazziOptions) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,72 +18,101 @@ import org.robolectric.shadows.ShadowDisplay.getDefaultDisplay
import kotlin.math.roundToInt

@ExperimentalRoborazziApi
interface RoborazziComposeConfig
interface RoborazziComposeOption

@ExperimentalRoborazziApi
interface RoborazziComposeSetupConfig : RoborazziComposeConfig {
interface RoborazziComposeSetupOption : RoborazziComposeOption {
fun configure()
}

@ExperimentalRoborazziApi
interface RoborazziComposeActivityScenarioConfig : RoborazziComposeConfig {
interface RoborazziComposeActivityScenarioOption : RoborazziComposeOption {
fun configureWithActivityScenario(scenario: ActivityScenario<out Activity>)
}

@ExperimentalRoborazziApi
interface RoborazziComposeComposableConfig : RoborazziComposeConfig {
interface RoborazziComposeComposableOption : RoborazziComposeOption {
fun configureWithComposable(content: @Composable () -> Unit): @Composable () -> Unit
}

@ExperimentalRoborazziApi
class RoborazziComposeConfigBuilder {
private val activityScenarioConfigs =
mutableListOf<RoborazziComposeActivityScenarioConfig>()
private val composableConfigs = mutableListOf<RoborazziComposeComposableConfig>()
private val setupConfigs = mutableListOf<RoborazziComposeSetupConfig>()

fun with(config: RoborazziComposeConfig): RoborazziComposeConfigBuilder {
if (config is RoborazziComposeActivityScenarioConfig) {
activityScenarioConfigs.add(config)
}
if (config is RoborazziComposeComposableConfig) {
composableConfigs.add(config)
class RoborazziComposeOptions private constructor(
private val activityScenarioOptions: List<RoborazziComposeActivityScenarioOption>,
private val composableOptions: List<RoborazziComposeComposableOption>,
private val setupOptions: List<RoborazziComposeSetupOption>
) {
class Builder {
private val activityScenarioOptions =
mutableListOf<RoborazziComposeActivityScenarioOption>()
private val composableOptions = mutableListOf<RoborazziComposeComposableOption>()
private val setupOptions = mutableListOf<RoborazziComposeSetupOption>()

fun addOption(option: RoborazziComposeOption): Builder {
if (option is RoborazziComposeActivityScenarioOption) {
activityScenarioOptions.add(option)
}
if (option is RoborazziComposeComposableOption) {
composableOptions.add(option)
}
if (option is RoborazziComposeSetupOption) {
setupOptions.add(option)
}
return this
}
if (config is RoborazziComposeSetupConfig) {
setupConfigs.add(config)

fun build(): RoborazziComposeOptions {
return RoborazziComposeOptions(
activityScenarioOptions = activityScenarioOptions,
composableOptions = composableOptions,
setupOptions = setupOptions
)
}
return this
}

fun builder(): Builder {
return Builder()
.apply {
activityScenarioOptions.forEach { addOption(it) }
composableOptions.forEach { addOption(it) }
setupOptions.forEach { addOption(it) }
}
}

@ExperimentalRoborazziApi
fun configure(
scenario: ActivityScenario<out Activity>,
fun configured(
activityScenario: ActivityScenario<out Activity>,
content: @Composable () -> Unit
): @Composable () -> Unit {
setupConfigs.forEach { it.configure() }
activityScenarioConfigs.forEach { it.configureWithActivityScenario(scenario) }
setupOptions.forEach { it.configure() }
activityScenarioOptions.forEach { it.configureWithActivityScenario(activityScenario) }
var appliedContent = content
composableConfigs.forEach { config ->
composableOptions.forEach { config ->
appliedContent = config.configureWithComposable(appliedContent)
}
return {
appliedContent()
}
}

companion object {
operator fun invoke(block: Builder.() -> Unit = {}): RoborazziComposeOptions {
return Builder().apply(block).build()
}
}
}

@ExperimentalRoborazziApi
fun RoborazziComposeConfigBuilder.size(
fun RoborazziComposeOptions.Builder.size(
widthDp: Int = 0,
heightDp: Int = 0
): RoborazziComposeConfigBuilder {
return with(RoborazziComposeSizeConfig(widthDp, heightDp))
): RoborazziComposeOptions.Builder {
return addOption(RoborazziComposeSizeOption(widthDp, heightDp))
}

@ExperimentalRoborazziApi
data class RoborazziComposeSizeConfig(val widthDp: Int, val heightDp: Int) :
RoborazziComposeActivityScenarioConfig,
RoborazziComposeComposableConfig {
data class RoborazziComposeSizeOption(val widthDp: Int, val heightDp: Int) :
RoborazziComposeActivityScenarioOption,
RoborazziComposeComposableOption {
override fun configureWithActivityScenario(scenario: ActivityScenario<out Activity>) {
scenario.onActivity { activity ->
activity.setDisplaySize(widthDp = widthDp, heightDp = heightDp)
Expand Down Expand Up @@ -130,18 +159,18 @@ data class RoborazziComposeSizeConfig(val widthDp: Int, val heightDp: Int) :
}

@ExperimentalRoborazziApi
fun RoborazziComposeConfigBuilder.background(
fun RoborazziComposeOptions.Builder.background(
showBackground: Boolean,
backgroundColor: Long = 0L
): RoborazziComposeConfigBuilder {
return with(RoborazziComposeBackgroundConfig(showBackground, backgroundColor))
): RoborazziComposeOptions.Builder {
return addOption(RoborazziComposeBackgroundOption(showBackground, backgroundColor))
}

@ExperimentalRoborazziApi
data class RoborazziComposeBackgroundConfig(
data class RoborazziComposeBackgroundOption(
private val showBackground: Boolean,
private val backgroundColor: Long
) : RoborazziComposeActivityScenarioConfig {
) : RoborazziComposeActivityScenarioOption {
override fun configureWithActivityScenario(scenario: ActivityScenario<out Activity>) {
when (showBackground) {
false -> {
Expand All @@ -164,13 +193,13 @@ data class RoborazziComposeBackgroundConfig(
}

@ExperimentalRoborazziApi
fun RoborazziComposeConfigBuilder.uiMode(uiMode: Int): RoborazziComposeConfigBuilder {
return with(RoborazziComposeUiModeConfig(uiMode))
fun RoborazziComposeOptions.Builder.uiMode(uiMode: Int): RoborazziComposeOptions.Builder {
return addOption(RoborazziComposeUiModeOption(uiMode))
}

@ExperimentalRoborazziApi
data class RoborazziComposeUiModeConfig(private val uiMode: Int) :
RoborazziComposeSetupConfig {
data class RoborazziComposeUiModeOption(private val uiMode: Int) :
RoborazziComposeSetupOption {
override fun configure() {
val nightMode =
when (uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES) {
Expand All @@ -182,30 +211,31 @@ data class RoborazziComposeUiModeConfig(private val uiMode: Int) :
}

@ExperimentalRoborazziApi
fun RoborazziComposeConfigBuilder.locale(locale: String): RoborazziComposeConfigBuilder {
return with(RoborazziComposeLocaleConfig(locale))
fun RoborazziComposeOptions.Builder.locale(locale: String): RoborazziComposeOptions.Builder {
return addOption(RoborazziComposeLocaleOption(locale))
}

@ExperimentalRoborazziApi
data class RoborazziComposeLocaleConfig(private val locale: String) :
RoborazziComposeSetupConfig {
data class RoborazziComposeLocaleOption(private val locale: String) :
RoborazziComposeSetupOption {
override fun configure() {
val localeWithFallback = locale.ifBlank { "en" }
setQualifiers("+$localeWithFallback")
}
}

@ExperimentalRoborazziApi
fun RoborazziComposeConfigBuilder.fontScale(fontScale: Float): RoborazziComposeConfigBuilder {
return with(RoborazziComposeFontScaleConfig(fontScale))
fun RoborazziComposeOptions.Builder.fontScale(fontScale: Float): RoborazziComposeOptions.Builder {
return addOption(RoborazziComposeFontScaleOption(fontScale))
}

@ExperimentalRoborazziApi
data class RoborazziComposeFontScaleConfig(private val fontScale: Float) :
RoborazziComposeSetupConfig {
data class RoborazziComposeFontScaleOption(private val fontScale: Float) :
RoborazziComposeSetupOption {
init {
require(fontScale > 0) { "fontScale must be greater than 0" }
}

override fun configure() {
setFontScale(fontScale)
}
Expand Down
Loading

0 comments on commit d451213

Please sign in to comment.