diff --git a/compose/mpp/compilation-tests/build.gradle.kts b/compose/mpp/compilation-tests/build.gradle.kts new file mode 100644 index 0000000000000..dd00bedcb975d --- /dev/null +++ b/compose/mpp/compilation-tests/build.gradle.kts @@ -0,0 +1,140 @@ +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig + +import androidx.build.AndroidXComposePlugin +import androidx.build.JetbrainsAndroidXPlugin + +plugins { + id("AndroidXPlugin") + id("AndroidXComposePlugin") + id("kotlin-multiplatform") +// [1.4 Update] id("application") + id("JetbrainsAndroidXPlugin") +} + +AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project) +JetbrainsAndroidXPlugin.applyAndConfigure(project) + +val skikoWasm = configurations.findByName("skikoWasm") ?: configurations.create("skikoWasm") + +dependencies { + skikoWasm(libs.skikoWasm) +} + +val resourcesDir = "$buildDir/resources" +val unzipTask = tasks.register("unzipWasm", Copy::class) { + destinationDir = file(resourcesDir) + from(skikoWasm.map { zipTree(it) }) +} + +kotlin { + jvm() + + js { + outputModuleName = "compilation-tests" + browser { + commonWebpackConfig { + outputFileName = "compilation-tests.js" + } + } + binaries.executable() + } + + @OptIn(ExperimentalWasmDsl::class) + wasmJs { + outputModuleName = "compilation-tests" + browser { + commonWebpackConfig { + outputFileName = "compilation-tests.js" + devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply { + static = (static ?: mutableListOf()).apply { + // Serve sources to debug inside browser + add(project.rootDir.path) + add(project.projectDir.path) + } + } + } + } + binaries.executable() + } + + sourceSets { + val commonMain by getting { + dependencies { + implementation(project(":compose:foundation:foundation")) + implementation(project(":compose:foundation:foundation-layout")) + implementation(project(":compose:material3:material3")) + implementation(project(":compose:material3:material3-window-size-class")) + implementation(project(":compose:material3:adaptive:adaptive")) + implementation(project(":compose:material3:adaptive:adaptive-layout")) + implementation(project(":compose:material3:adaptive:adaptive-navigation")) + implementation(project(":compose:material:material")) + implementation(project(":compose:mpp")) + implementation(project(":compose:runtime:runtime")) + implementation(project(":compose:ui:ui")) + implementation(project(":compose:ui:ui-graphics")) + implementation(project(":compose:ui:ui-text")) + implementation(project(":compose:ui:ui-backhandler")) + implementation(project(":lifecycle:lifecycle-common")) + implementation(project(":lifecycle:lifecycle-runtime")) + implementation(project(":lifecycle:lifecycle-runtime-compose")) + implementation(project(":navigation:navigation-common")) + implementation(project(":navigation:navigation-compose")) + implementation(project(":navigation:navigation-runtime")) + implementation(libs.kotlinStdlib) + implementation(libs.kotlinCoroutinesCore) + + implementation("org.jetbrains.compose.material:material-icons-core:1.7.3") { + // exclude dependencies, because they override local projects when we build 0.0.0-* version + // (see https://repo1.maven.org/maven2/org/jetbrains/compose/material/material-icons-core-desktop/1.6.11/material-icons-core-desktop-1.6.11.module) + exclude("org.jetbrains.compose.runtime") + exclude("org.jetbrains.compose.ui") + } + } + } + + val skikoMain by creating { + dependsOn(commonMain) + dependencies { + implementation(libs.skikoCommon) + } + } + + val jvmMain by getting { + dependsOn(skikoMain) + dependencies { + implementation(libs.skikoCurrentOs) + implementation(project(":compose:desktop:desktop")) + } + } + + val webMain by creating { + dependsOn(skikoMain) + resources.setSrcDirs(resources.srcDirs) + resources.srcDirs(unzipTask.map { it.destinationDir }) + } + + val jsMain by getting { + dependsOn(webMain) + } + + val wasmJsMain by getting { + dependsOn(webMain) + } + } + + compilerOptions { freeCompilerArgs.add("-Xpartial-linkage=disable") } +} + +tasks.create("runDesktop", JavaExec::class.java) { + dependsOn(":compose:desktop:desktop:jar") + mainClass.set("androidx.compose.mpp.compilation-tests.MainKt") + args = listOfNotNull(project.findProperty("args")?.toString()) + systemProperty("skiko.fps.enabled", "true") + val compilation = kotlin.jvm().compilations["main"] + classpath = + compilation.output.allOutputs + + compilation.runtimeDependencyFiles +} \ No newline at end of file diff --git a/compose/mpp/compilation-tests/src/commonMain/kotlin/androidx/compose/mpp/compilation-tests/App.kt b/compose/mpp/compilation-tests/src/commonMain/kotlin/androidx/compose/mpp/compilation-tests/App.kt new file mode 100644 index 0000000000000..dcedf82228a74 --- /dev/null +++ b/compose/mpp/compilation-tests/src/commonMain/kotlin/androidx/compose/mpp/compilation-tests/App.kt @@ -0,0 +1,84 @@ +package androidx.compose.mpp.`compilation-tests` + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Home +import androidx.compose.material.icons.filled.Search +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material.icons.outlined.Home +import androidx.compose.material.icons.outlined.Search +import androidx.compose.material.icons.outlined.Settings +import androidx.compose.material3.Button +import androidx.compose.material3.Icon +import androidx.compose.material3.ModalWideNavigationRail +import androidx.compose.material3.Text +import androidx.compose.material3.WideNavigationRailItem +import androidx.compose.material3.rememberWideNavigationRailState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import kotlinx.coroutines.launch + +/** + * https://youtrack.jetbrains.com/issue/CMP-7505 + */ +@Composable +fun ModalNavigationRail() { + var selectedItem by remember { mutableIntStateOf(0) } + val items = listOf("Home", "Search", "Settings") + val selectedIcons = listOf(Icons.Filled.Home, Icons.Filled.Search, Icons.Filled.Settings) + val unselectedIcons = listOf(Icons.Outlined.Home, Icons.Outlined.Search, Icons.Outlined.Settings) + + val state = rememberWideNavigationRailState() + val scope = rememberCoroutineScope() + + Row(Modifier.fillMaxSize()) { + ModalWideNavigationRail(state = state, hideOnCollapse = true) { + items.forEachIndexed { index, item -> + WideNavigationRailItem( + railExpanded = true, + icon = { + Icon( + if (selectedItem == index) selectedIcons[index] + else unselectedIcons[index], + contentDescription = null + ) + }, + label = { Text(item) }, + selected = selectedItem == index, + onClick = { + selectedItem = index + scope.launch { state.collapse() } + } + ) + } + } + + Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { + val currentPage = items[selectedItem] + Spacer(modifier = Modifier.size(54.dp)) + Text(text = "$currentPage Page", textAlign = TextAlign.Center) + Button(onClick = { scope.launch { state.expand() } }, Modifier.padding(32.dp)) { + Text(text = "Open modal rail", textAlign = TextAlign.Center) + } + } + } +} + +@Composable +fun App() { + ModalNavigationRail() +} \ No newline at end of file diff --git a/compose/mpp/compilation-tests/src/jvmMain/kotlin/androidx/compose/mpp/compilation-tests/main.kt b/compose/mpp/compilation-tests/src/jvmMain/kotlin/androidx/compose/mpp/compilation-tests/main.kt new file mode 100644 index 0000000000000..b4ac816398c57 --- /dev/null +++ b/compose/mpp/compilation-tests/src/jvmMain/kotlin/androidx/compose/mpp/compilation-tests/main.kt @@ -0,0 +1,13 @@ +package androidx.compose.mpp.`compilation-tests` + +import androidx.compose.ui.window.Window +import androidx.compose.ui.window.application + +fun main() = application { + Window( + onCloseRequest = ::exitApplication, + title = "compilation-tests", + ) { + App() + } +} \ No newline at end of file diff --git a/compose/mpp/compilation-tests/src/webMain/kotlin/androidx/compose/mpp/compilation-tests/main.kt b/compose/mpp/compilation-tests/src/webMain/kotlin/androidx/compose/mpp/compilation-tests/main.kt new file mode 100644 index 0000000000000..6dc2b4c593ab3 --- /dev/null +++ b/compose/mpp/compilation-tests/src/webMain/kotlin/androidx/compose/mpp/compilation-tests/main.kt @@ -0,0 +1,7 @@ +package androidx.compose.mpp.`compilation-tests` + +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.window.ComposeViewport + +@OptIn(ExperimentalComposeUiApi::class) +fun main() = ComposeViewport { App() } \ No newline at end of file diff --git a/compose/mpp/compilation-tests/src/webMain/resources/index.html b/compose/mpp/compilation-tests/src/webMain/resources/index.html new file mode 100644 index 0000000000000..e3a39060739ff --- /dev/null +++ b/compose/mpp/compilation-tests/src/webMain/resources/index.html @@ -0,0 +1,24 @@ + + + + + + + + + + compilation-tests + + + + + diff --git a/compose/mpp/compilation-tests/src/webMain/resources/manifest.json b/compose/mpp/compilation-tests/src/webMain/resources/manifest.json new file mode 100644 index 0000000000000..d0a8b2f937809 --- /dev/null +++ b/compose/mpp/compilation-tests/src/webMain/resources/manifest.json @@ -0,0 +1,7 @@ +{ + "name": "mpp:compilation-tests", + "short_name": "mpp:compilation-tests", + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} \ No newline at end of file diff --git a/mpp/build.gradle.kts b/mpp/build.gradle.kts index df80309f99453..6d496a6e8cac7 100644 --- a/mpp/build.gradle.kts +++ b/mpp/build.gradle.kts @@ -192,6 +192,7 @@ tasks.register("checkDesktop") { tasks.register("testDesktop") { dependsOn(allTasksWith(name = "desktopTest")) dependsOn(":collection:collection:jvmTest") + dependsOn(":compose:mpp:compilation-tests:jvmJar") } tasks.register("testWeb") { @@ -208,6 +209,7 @@ val testWebJs = tasks.register("testWebJs") { dependsOn(":compose:ui:ui:jsTest") dependsOn(":compose:ui:ui-test:jsTest") dependsOn(":navigation:navigation-runtime:jsTest") + dependsOn(":compose:mpp:compilation-tests:compileDevelopmentExecutableKotlinJs") } val testWebWasm = tasks.register("testWebWasm") { @@ -220,6 +222,7 @@ val testWebWasm = tasks.register("testWebWasm") { dependsOn(":compose:ui:ui:wasmJsTest") dependsOn(":compose:ui:ui-test:wasmJsTest") dependsOn(":navigation:navigation-runtime:wasmJsTest") + dependsOn(":compose:mpp:compilation-tests:compileDevelopmentExecutableKotlinWasmJs") } tasks.register("testUIKit") { diff --git a/settings.gradle b/settings.gradle index 725dca8a0f5ec..caa85c42121e7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -140,6 +140,7 @@ includeProject(":compose:desktop:desktop:desktop-samples", "compose/desktop/desk includeProject(":compose:desktop:desktop:desktop-samples-material3", "compose/desktop/desktop/samples-material3") includeProject(":compose:mpp") includeProject(":compose:mpp:demo") +includeProject(":compose:mpp:compilation-tests") // workaround for issue that on linux and windows CommonizeCInterop task fails // It seems that this workaround can be removed after Kotlin 1.8.20