Skip to content

feat: Generate stories from @Preview composables #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
30fba00
add :modules:preview-processor
congvc-dev May 8, 2025
e343aa5
Add PreviewProcessor and first good test
congvc-dev May 8, 2025
b89fdcf
Implement PreviewProcessor
congvc-dev May 10, 2025
909d4d7
Add missing SymbolProcessorProvider metadata
congvc-dev May 10, 2025
ec79a93
generated stories are in org.jetbrains.compose.storytale.generated
congvc-dev May 10, 2025
fba031b
Add previewParameter functions for non Story scopes
congvc-dev May 10, 2025
704cb23
apply spotless
congvc-dev May 10, 2025
9ba6ec2
add :modules:preview-processor-test
congvc-dev May 10, 2025
885c84e
move PreviewProcessorTest to :modules:preview-processor-test
congvc-dev May 11, 2025
1ac4019
add AssertableFile.kt and Compilation.kt
congvc-dev May 11, 2025
0eb1388
apply spotless
congvc-dev May 11, 2025
c0ce783
bump JDK version v21 in github workflows
congvc-dev May 11, 2025
2f1cd84
disable proguard for :gallery-demo desktop target
congvc-dev May 11, 2025
a498709
pretty PreviewProcessorTest
congvc-dev May 11, 2025
2350e9a
Support multiple @Preview composables
congvc-dev May 11, 2025
b84713d
Add @Preview composables samples in :gallery-demo
congvc-dev May 11, 2025
6df79a6
apply spotless
congvc-dev May 11, 2025
e74c5e6
Merge branch 'ci-java-21' into preview-scanner
congvc-dev May 11, 2025
2d1634a
Sort validPreviewFunctions before generatePreviewFile in PreviewProce…
congvc-dev May 17, 2025
a233b23
apply spotless
congvc-dev May 17, 2025
53680fb
Add PublicPreviewComposableRegistrar
congvc-dev May 17, 2025
146268d
Add MakePreviewPublicFirExtensionRegistrar
congvc-dev May 18, 2025
2fa23cb
apply spotless
congvc-dev May 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '17'
java-version: '21'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know yet what exactly requires java 21 in this PR, but we need to stick to java 17 (should be compatible with java 17), because it's used in Compose repository.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on this job, I suspect that my PR uses KSP 2.1.20-2.0.1 which was compiled with Java 21. Lowering KSP version perhaps the plausible option here


- name: Checkout code
uses: actions/checkout@v3
Expand Down Expand Up @@ -54,4 +54,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@v4
2 changes: 1 addition & 1 deletion .github/workflows/smokebuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '17'
java-version: '21'

- name: Checkout code
uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/spotless.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'
cache: gradle

Expand Down
7 changes: 7 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ plugins {
alias(libs.plugins.kotlin.jvm) apply false
alias(libs.plugins.dokka) apply false
alias(libs.plugins.spotless) apply false
alias(libs.plugins.ksp) apply false
}

buildscript {
dependencies {
classpath(kotlin("gradle-plugin", version = libs.versions.kotlin.asProvider().get()))
}
}

subprojects {
Expand Down
32 changes: 32 additions & 0 deletions gallery-demo/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ plugins {
alias(libs.plugins.compose.compiler)
alias(libs.plugins.serialization)
id("org.jetbrains.compose.hot-reload") version "1.0.0-alpha03"
alias(libs.plugins.ksp)
}

class StorytaleCompilerPlugin : KotlinCompilerPluginSupportPlugin {
Expand All @@ -34,13 +35,36 @@ class StorytaleCompilerPlugin : KotlinCompilerPluginSupportPlugin {
)
}
}
class MakePreviewPublicCompilerPlugin : KotlinCompilerPluginSupportPlugin {
override fun applyToCompilation(kotlinCompilation: KotlinCompilation<*>): Provider<List<SubpluginOption>> {
return kotlinCompilation.project.provider { emptyList() }
}

override fun getCompilerPluginId(): String {
return "org.jetbrains.compose.compiler.plugins.storytale.preview.public"
}

override fun getPluginArtifact(): SubpluginArtifact {
return SubpluginArtifact("org.jetbrains.compose.storytale.preview.public", "local-compiler-plugin")
}

override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean {
return kotlinCompilation.target.platformType in setOf(
org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.jvm,
org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.wasm,
)
}
}

apply<StorytaleCompilerPlugin>()
apply<MakePreviewPublicCompilerPlugin>()

configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(module("org.jetbrains.compose.storytale:local-compiler-plugin"))
.using(project(":modules:compiler-plugin"))
substitute(module("org.jetbrains.compose.storytale.preview.public:local-compiler-plugin"))
.using(project(":modules:preview-processor"))
}
}

Expand Down Expand Up @@ -107,9 +131,17 @@ kotlin {
}
}

dependencies {
add("kspCommonMainMetadata", project(":modules:preview-processor"))
add("ksp", project(":modules:preview-processor"))
}

compose.desktop {
application {
mainClass = "storytale.gallery.demo.MainKt"
buildTypes.release.proguard {
isEnabled.set(false)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package storytale.gallery.demo

import androidx.compose.material3.TriStateCheckbox
import androidx.compose.runtime.Composable
import androidx.compose.ui.state.ToggleableState
import androidx.compose.ui.state.ToggleableState.Indeterminate
import androidx.compose.ui.state.ToggleableState.Off
import androidx.compose.ui.state.ToggleableState.On
import org.jetbrains.compose.storytale.previewParameter
import org.jetbrains.compose.ui.tooling.preview.Preview

@Preview
@Composable
@Suppress("ktlint")
private fun PreviewCheckbox() {
var state by previewParameter(ToggleableState.entries)

TriStateCheckbox(
state = state,
onClick = {
state = when (state) {
On -> Indeterminate
Off -> On
Indeterminate -> Off
}
},
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package storytale.gallery.demo

import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddCircle
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.storytale.previewParameter

@org.jetbrains.compose.ui.tooling.preview.Preview
@Composable
@Suppress("ktlint")
private fun PreviewExtendedFAB() {
val bgColor by previewParameter(MaterialTheme.colorScheme.primary)

ExtendedFloatingActionButton(onClick = {}, containerColor = bgColor) {
Icon(imageVector = Icons.Default.AddCircle, contentDescription = null)
Spacer(Modifier.padding(4.dp))
Text("Extended")
}
}

@androidx.compose.desktop.ui.tooling.preview.Preview
@Composable
@Suppress("ktlint")
private fun PreviewSegmentedButton() {
val selectedIndex = remember { mutableIntStateOf(0) }

SingleChoiceSegmentedButtonRow {
repeat(3) { index ->
SegmentedButton(
selected = index == selectedIndex.value,
onClick = { selectedIndex.value = index },
shape = SegmentedButtonDefaults.itemShape(index, 3),
) {
Text("Button $index", modifier = Modifier.padding(4.dp))
}
}
}
}
5 changes: 4 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ dokka = "1.9.10"
kotlinx-html = "0.7.3"
junit = "5.10.1"
jsoup = "1.16.1"
ksp = "2.1.20-2.0.1"

[libraries]
assertj-core = { module = "org.assertj:assertj-core", version.ref = "assertj" }
kotlinCompileTesting-core = { module = "dev.zacsweers.kctfork:core", version.ref = "kotlinCompileTesting" }
kotlinCompileTesting-ksp = { module = "dev.zacsweers.kctfork:ksp", version.ref = "kotlinCompileTesting" }
junit = { module = "junit:junit", version.ref = "junitVersion" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" }
Expand All @@ -45,6 +47,7 @@ junit-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "jun
jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
ktlint = "com.pinterest.ktlint:ktlint-cli:1.5.0"
composeRules = "io.nlopez.compose.rules:ktlint:0.4.22"
ksp-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" }

[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
Expand All @@ -57,6 +60,6 @@ buildTimeConfig = { id = "dev.limebeck.build-time-config", version.ref = "build-
storytale = { id = "org.jetbrains.compose.storytale", version.ref = "storytale" }
kotlinDsl = { id = "kotlin-dsl" }
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }

ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
1 change: 1 addition & 0 deletions modules/preview-processor-test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
70 changes: 70 additions & 0 deletions modules/preview-processor-test/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import org.gradle.kotlin.dsl.compileOnly
import org.gradle.kotlin.dsl.kotlin
import org.gradle.kotlin.dsl.project
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask

plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidLibrary)
alias(libs.plugins.jetbrainsCompose)
alias(libs.plugins.compose.compiler)
}

kotlin {
jvm()
androidTarget()

sourceSets {
val commonMain by getting {
dependencies {
compileOnly(compose.runtime)
}
}
val jvmMain by getting {
dependencies {
implementation(compose.components.uiToolingPreview)
implementation(project(":modules:preview-processor"))
implementation(kotlin("test"))

implementation(compose.runtime)
implementation(kotlin("compiler-embeddable"))
implementation(kotlin("compose-compiler-plugin-embeddable"))
implementation(kotlin("test"))
implementation(libs.assertj.core)
implementation(libs.junit)
implementation(libs.kotlinCompileTesting.ksp)
implementation(project(":modules:runtime-api"))
}
}
val androidUnitTest by getting {
dependsOn(jvmMain)

dependencies {
implementation("androidx.compose.ui:ui-tooling-preview-android:1.7.0")
}
}
val jvmTest by getting {
dependencies {
implementation("androidx.compose.ui:ui-tooling-preview-desktop:1.7.0")
}
}
}
}

android {
compileSdk = 35
namespace = "org.jetbrains.compose.storytale.preview.processor.test"
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 24
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
}

tasks.withType<KotlinCompilationTask<*>>().configureEach {
compilerOptions.optIn.add("org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi")
}
Loading