From 23e6c6ba4bd612ea781f0c95c00eb3255d2bcb82 Mon Sep 17 00:00:00 2001 From: Nikita Lipsky Date: Tue, 10 Jan 2023 12:38:34 +0200 Subject: [PATCH] Move Minesweeper to KMM project structure and load resources the same way for all platforms (#2619) --- experimental/examples/minesweeper/.gitignore | 6 + .../minesweeper/.run/desktopApp.run.xml | 28 ++ .../.run/iosApp (Android Studio).run.xml | 7 + .../examples/minesweeper/.run/iosApp.run.xml | 8 + .../examples/minesweeper/.run/jsApp.run.xml | 28 ++ experimental/examples/minesweeper/README.md | 38 +- .../minesweeper/androidApp/build.gradle.kts | 33 ++ .../src/main}/AndroidManifest.xml | 0 .../src/main}/kotlin/MainActivity.kt | 4 +- .../src/main}/res/values/strings.xml | 0 .../examples/minesweeper/build.gradle.kts | 231 +--------- .../minesweeper/desktopApp/build.gradle.kts | 35 ++ .../desktopApp/src/jvmMain/kotlin/Main.kt | 22 + .../examples/minesweeper/gradle.properties | 20 +- .../iosApp/Configuration/TeamId.xcconfig | 1 + .../Minesweeper.xcodeproj/project.pbxproj | 398 ++++++++++++++++++ .../examples/minesweeper/iosApp/Podfile | 5 + .../minesweeper/iosApp/iosApp/Info.plist | 48 +++ .../minesweeper/iosApp/iosApp/iosApp.swift | 15 + .../minesweeper/jsApp/build.gradle.kts | 23 + .../jsApp/src/jsMain/kotlin/main.js.kt | 16 + .../src/jsMain}/resources/assets/clock.png | Bin .../src/jsMain}/resources/assets/flag.png | Bin .../src/jsMain}/resources/assets/mine.png | Bin .../src/jsMain/resources/index.html | 2 +- .../minesweeper/run-configurations.png | Bin 0 -> 21525 bytes .../examples/minesweeper/settings.gradle.kts | 18 +- .../minesweeper/shared/build.gradle.kts | 117 +++++ .../src/androidMain/AndroidManifest.xml | 2 + .../src/androidMain/kotlin/main.android.kt | 5 + .../src/commonMain/kotlin/BoardView.kt | 2 +- .../src/commonMain/kotlin/GameController.kt | 0 .../src/commonMain/kotlin/game.kt | 33 +- .../src/commonMain/kotlin/gameInteraction.kt | 4 +- .../src/commonMain/kotlin/widgets.kt | 12 +- .../src/commonMain/resources/assets/clock.png | Bin 0 -> 896 bytes .../src/commonMain/resources/assets/flag.png | Bin 0 -> 780 bytes .../src/commonMain/resources/assets/mine.png | Bin 0 -> 1934 bytes .../commonTest/kotlin/GameControllerTest.kt | 0 .../src/desktopMain/kotlin/main.desktop.kt | 15 + .../shared/src/iosMain/kotlin/main.ios.kt | 15 + .../shared/src/jsMain/kotlin/main.js.kt | 6 + .../src/macosMain/kotlin/main.macos.kt | 5 +- .../androidMain/kotlin/actualfuns.android.kt | 7 - .../src/desktopMain/kotlin/main.desktop.kt | 32 -- .../minesweeper/src/jsMain/kotlin/main.js.kt | 24 -- .../src/uikitMain/kotlin/main.uikit.kt | 23 - 47 files changed, 919 insertions(+), 369 deletions(-) create mode 100644 experimental/examples/minesweeper/.run/desktopApp.run.xml create mode 100644 experimental/examples/minesweeper/.run/iosApp (Android Studio).run.xml create mode 100644 experimental/examples/minesweeper/.run/iosApp.run.xml create mode 100644 experimental/examples/minesweeper/.run/jsApp.run.xml create mode 100644 experimental/examples/minesweeper/androidApp/build.gradle.kts rename experimental/examples/minesweeper/{src/androidMain => androidApp/src/main}/AndroidManifest.xml (100%) rename experimental/examples/minesweeper/{src/androidMain => androidApp/src/main}/kotlin/MainActivity.kt (89%) rename experimental/examples/minesweeper/{src/androidMain => androidApp/src/main}/res/values/strings.xml (100%) create mode 100644 experimental/examples/minesweeper/desktopApp/build.gradle.kts create mode 100644 experimental/examples/minesweeper/desktopApp/src/jvmMain/kotlin/Main.kt create mode 100644 experimental/examples/minesweeper/iosApp/Configuration/TeamId.xcconfig create mode 100644 experimental/examples/minesweeper/iosApp/Minesweeper.xcodeproj/project.pbxproj create mode 100644 experimental/examples/minesweeper/iosApp/Podfile create mode 100644 experimental/examples/minesweeper/iosApp/iosApp/Info.plist create mode 100644 experimental/examples/minesweeper/iosApp/iosApp/iosApp.swift create mode 100644 experimental/examples/minesweeper/jsApp/build.gradle.kts create mode 100644 experimental/examples/minesweeper/jsApp/src/jsMain/kotlin/main.js.kt rename experimental/examples/minesweeper/{src/desktopMain => jsApp/src/jsMain}/resources/assets/clock.png (100%) rename experimental/examples/minesweeper/{src/desktopMain => jsApp/src/jsMain}/resources/assets/flag.png (100%) rename experimental/examples/minesweeper/{src/desktopMain => jsApp/src/jsMain}/resources/assets/mine.png (100%) rename experimental/examples/minesweeper/{ => jsApp}/src/jsMain/resources/index.html (85%) create mode 100644 experimental/examples/minesweeper/run-configurations.png create mode 100644 experimental/examples/minesweeper/shared/build.gradle.kts create mode 100644 experimental/examples/minesweeper/shared/src/androidMain/AndroidManifest.xml create mode 100644 experimental/examples/minesweeper/shared/src/androidMain/kotlin/main.android.kt rename experimental/examples/minesweeper/{ => shared}/src/commonMain/kotlin/BoardView.kt (93%) rename experimental/examples/minesweeper/{ => shared}/src/commonMain/kotlin/GameController.kt (100%) rename experimental/examples/minesweeper/{ => shared}/src/commonMain/kotlin/game.kt (81%) rename experimental/examples/minesweeper/{ => shared}/src/commonMain/kotlin/gameInteraction.kt (92%) rename experimental/examples/minesweeper/{ => shared}/src/commonMain/kotlin/widgets.kt (87%) create mode 100644 experimental/examples/minesweeper/shared/src/commonMain/resources/assets/clock.png create mode 100644 experimental/examples/minesweeper/shared/src/commonMain/resources/assets/flag.png create mode 100644 experimental/examples/minesweeper/shared/src/commonMain/resources/assets/mine.png rename experimental/examples/minesweeper/{ => shared}/src/commonTest/kotlin/GameControllerTest.kt (100%) create mode 100644 experimental/examples/minesweeper/shared/src/desktopMain/kotlin/main.desktop.kt create mode 100644 experimental/examples/minesweeper/shared/src/iosMain/kotlin/main.ios.kt create mode 100644 experimental/examples/minesweeper/shared/src/jsMain/kotlin/main.js.kt rename experimental/examples/minesweeper/{ => shared}/src/macosMain/kotlin/main.macos.kt (88%) delete mode 100644 experimental/examples/minesweeper/src/androidMain/kotlin/actualfuns.android.kt delete mode 100644 experimental/examples/minesweeper/src/desktopMain/kotlin/main.desktop.kt delete mode 100644 experimental/examples/minesweeper/src/jsMain/kotlin/main.js.kt delete mode 100644 experimental/examples/minesweeper/src/uikitMain/kotlin/main.uikit.kt diff --git a/experimental/examples/minesweeper/.gitignore b/experimental/examples/minesweeper/.gitignore index 639cdd514d..0903344480 100644 --- a/experimental/examples/minesweeper/.gitignore +++ b/experimental/examples/minesweeper/.gitignore @@ -1 +1,7 @@ local.properties +iosApp/Podfile.lock +iosApp/Pods/* +iosApp/Minesweeper.xcworkspace/* +iosApp/Minesweeper.xcodeproj/* +!iosApp/Minesweeper.xcodeproj/project.pbxproj +shared/shared.podspec diff --git a/experimental/examples/minesweeper/.run/desktopApp.run.xml b/experimental/examples/minesweeper/.run/desktopApp.run.xml new file mode 100644 index 0000000000..7af7e15f4b --- /dev/null +++ b/experimental/examples/minesweeper/.run/desktopApp.run.xml @@ -0,0 +1,28 @@ + + + + + + + + true + true + false + + + \ No newline at end of file diff --git a/experimental/examples/minesweeper/.run/iosApp (Android Studio).run.xml b/experimental/examples/minesweeper/.run/iosApp (Android Studio).run.xml new file mode 100644 index 0000000000..553dd92ab1 --- /dev/null +++ b/experimental/examples/minesweeper/.run/iosApp (Android Studio).run.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/experimental/examples/minesweeper/.run/iosApp.run.xml b/experimental/examples/minesweeper/.run/iosApp.run.xml new file mode 100644 index 0000000000..31a15653b2 --- /dev/null +++ b/experimental/examples/minesweeper/.run/iosApp.run.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/experimental/examples/minesweeper/.run/jsApp.run.xml b/experimental/examples/minesweeper/.run/jsApp.run.xml new file mode 100644 index 0000000000..6135d902e4 --- /dev/null +++ b/experimental/examples/minesweeper/.run/jsApp.run.xml @@ -0,0 +1,28 @@ + + + + + + + + true + true + false + + + \ No newline at end of file diff --git a/experimental/examples/minesweeper/README.md b/experimental/examples/minesweeper/README.md index 94504bdf43..f03076ebf3 100644 --- a/experimental/examples/minesweeper/README.md +++ b/experimental/examples/minesweeper/README.md @@ -1,20 +1,36 @@ # Minesweeper -A simple game powered by Compose Multiplatform +A simple game powered by Compose Multiplatform. -## Run native on MacOS -`./gradlew runDebugExecutableMacosX64` (Works on Intel processors) +Game can run on Android, iOS, desktop or in a browser. + +*Prerequisites*: to run on iOS and Android, you should have "Kotlin Multiplatform Mobile" plugin installed either + in Android Studio or in AppCode with [installed CocoaPods](https://kotlinlang.org/docs/native-cocoapods.html). + + +## How to run + +Choose a run configuration for an appropriate target in IDE and run it. + +![run-configurations.png](run-configurations.png) -## Run web assembly in browser -`./gradlew jsBrowserDevelopmentRun` +To run on iOS device, please correct `iosApp/Configuration/TeamId.xcconfig` with your Apple Team ID. +Alternatively, you may setup signing within XCode opening `iosApp/Minesweeper.xcworkspace` and then +using "Signing & Capabilities" tab of `Minesweeper` target. -## Run on iOS simulator -`./gradlew iosDeployIPhone8Debug` -`./gradlew iosDeployIPadDebug` +Then choose **iosApp** configuration in IDE and run it +(may also be referred as `Minesweeper` in the Run Configurations or `iosApp (Android Studio)` for Android studio). -## Run on iOS device -- Read about iOS target in [falling-balls-mpp/README.md](../falling-balls-mpp/README.md) -- `./gradlew iosDeployDeviceRelease` +## Run on desktop via Gradle + +`./gradlew desktopApp:run` + +## Run JS in browser with WebAssembly Skia via Gradle + +`./gradlew jsApp:jsBrowserDevelopmentRun` + +## Run native on MacOS +`./gradlew runDebugExecutableMacosX64` (Works on Intel processors) ## Credits
Icons made by Creaticca Creative Agency from www.flaticon.com
\ No newline at end of file diff --git a/experimental/examples/minesweeper/androidApp/build.gradle.kts b/experimental/examples/minesweeper/androidApp/build.gradle.kts new file mode 100644 index 0000000000..0c592a144c --- /dev/null +++ b/experimental/examples/minesweeper/androidApp/build.gradle.kts @@ -0,0 +1,33 @@ +plugins { + kotlin("multiplatform") + id("com.android.application") + id("org.jetbrains.compose") +} + +kotlin { + android() + sourceSets { + val androidMain by getting { + dependencies { + implementation(project(":shared")) + implementation("androidx.appcompat:appcompat:1.5.1") + implementation("androidx.activity:activity-compose:1.6.1") + } + } + } +} + +android { + compileSdk = 33 + defaultConfig { + applicationId = "org.jetbrains.ComposeMinesweeper" + minSdk = 24 + targetSdk = 33 + versionCode = 1 + versionName = "1.0" + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } +} diff --git a/experimental/examples/minesweeper/src/androidMain/AndroidManifest.xml b/experimental/examples/minesweeper/androidApp/src/main/AndroidManifest.xml similarity index 100% rename from experimental/examples/minesweeper/src/androidMain/AndroidManifest.xml rename to experimental/examples/minesweeper/androidApp/src/main/AndroidManifest.xml diff --git a/experimental/examples/minesweeper/src/androidMain/kotlin/MainActivity.kt b/experimental/examples/minesweeper/androidApp/src/main/kotlin/MainActivity.kt similarity index 89% rename from experimental/examples/minesweeper/src/androidMain/kotlin/MainActivity.kt rename to experimental/examples/minesweeper/androidApp/src/main/kotlin/MainActivity.kt index e3b0d1e9f3..4970ea42ed 100644 --- a/experimental/examples/minesweeper/src/androidMain/kotlin/MainActivity.kt +++ b/experimental/examples/minesweeper/androidApp/src/main/kotlin/MainActivity.kt @@ -3,13 +3,13 @@ package org.jetbrains.minesweeper import android.os.Bundle import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity -import Game +import MainView class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - Game() + MainView() } } } diff --git a/experimental/examples/minesweeper/src/androidMain/res/values/strings.xml b/experimental/examples/minesweeper/androidApp/src/main/res/values/strings.xml similarity index 100% rename from experimental/examples/minesweeper/src/androidMain/res/values/strings.xml rename to experimental/examples/minesweeper/androidApp/src/main/res/values/strings.xml diff --git a/experimental/examples/minesweeper/build.gradle.kts b/experimental/examples/minesweeper/build.gradle.kts index a5045597e5..0c00883af5 100644 --- a/experimental/examples/minesweeper/build.gradle.kts +++ b/experimental/examples/minesweeper/build.gradle.kts @@ -1,219 +1,18 @@ -import org.jetbrains.compose.compose -import org.jetbrains.compose.desktop.application.dsl.TargetFormat -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension -import org.jetbrains.compose.experimental.dsl.IOSDevices - plugins { - id("com.android.application") - kotlin("multiplatform") - id("org.jetbrains.compose") -} - -version = "1.0-SNAPSHOT" - -repositories { - mavenLocal() - google() - mavenCentral() - maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") -} - -kotlin { - android() - jvm("desktop") - js(IR) { - browser() - binaries.executable() - } - macosX64 { - binaries { - executable { - entryPoint = "main" - freeCompilerArgs += listOf( - "-linker-option", "-framework", "-linker-option", "Metal" - ) - } - } - } - macosArm64 { - binaries { - executable { - entryPoint = "main" - freeCompilerArgs += listOf( - "-linker-option", "-framework", "-linker-option", "Metal" - ) - } - } - } - - // Workaround for an issue: - // https://youtrack.jetbrains.com/issue/KT-53561/Invalid-LLVM-module-inlinable-function-call-in-a-function-with-debug-info-must-have-a-dbg-location - // Compose compiler produces nodes without line information sometimes that provokes Kotlin native compiler to report errors. - // TODO: remove workaround when switch to Kotlin 1.8 - val disableKonanVerification = "-Xverify-compiler=false" - - iosX64("uikitX64") { - binaries { - executable() { - entryPoint = "main" - freeCompilerArgs += listOf( - "-linker-option", "-framework", "-linker-option", "Metal", - "-linker-option", "-framework", "-linker-option", "CoreText", - "-linker-option", "-framework", "-linker-option", "CoreGraphics", - disableKonanVerification - ) - } - } - } - iosArm64("uikitArm64") { - binaries { - executable() { - entryPoint = "main" - freeCompilerArgs += listOf( - "-linker-option", "-framework", "-linker-option", "Metal", - "-linker-option", "-framework", "-linker-option", "CoreText", - "-linker-option", "-framework", "-linker-option", "CoreGraphics", - disableKonanVerification - ) - } - } - } - - sourceSets { - val commonMain by getting { - dependencies { - implementation(compose.ui) - implementation(compose.foundation) - implementation(compose.material) - implementation(compose.runtime) - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.3") - } - } - - val commonTest by getting { - dependencies { - implementation(kotlin("test-common")) - implementation(kotlin("test-annotations-common")) - } - } - - val androidMain by getting { - dependsOn(commonMain) - kotlin.srcDirs("src/jvmMain/kotlin") - dependencies { - implementation("androidx.appcompat:appcompat:1.5.1") - implementation("androidx.activity:activity-compose:1.5.0") - } - } - - val desktopMain by getting { - dependencies { - implementation(compose.desktop.currentOs) - } - } - - val jsMain by getting { - dependencies { - implementation(compose.web.core) - } - } - - val nativeMain by creating { - dependsOn(commonMain) - } - val macosMain by creating { - dependsOn(nativeMain) - } - val macosX64Main by getting { - dependsOn(macosMain) - } - val macosArm64Main by getting { - dependsOn(macosMain) - } - val uikitMain by creating { - dependsOn(nativeMain) - } - val uikitX64Main by getting { - dependsOn(uikitMain) - } - val uikitArm64Main by getting { - dependsOn(uikitMain) - } - } -} - -compose.desktop { - application { - mainClass = "Main_desktopKt" - nativeDistributions { - targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) - packageName = "Minesweeper" - packageVersion = "1.0.0" - - windows { - menuGroup = "Compose Examples" - // see https://wixtoolset.org/documentation/manual/v3/howtos/general/generate_guids.html - upgradeUuid = "2bf169f9-d851-49f0-b3a1-308966d473ca" - } - } - } -} - -compose.experimental { - web.application {} - uikit.application { - bundleIdPrefix = "org.jetbrains" - projectName = "ComposeMinesweeper" - deployConfigurations { - simulator("IPhone8") { - //Usage: ./gradlew iosDeployIPhone8Debug - device = IOSDevices.IPHONE_8 - } - simulator("IPad") { - //Usage: ./gradlew iosDeployIPadDebug - device = IOSDevices.IPAD_MINI_6th_Gen - } - connectedDevice("Device") { - //First need specify your teamId here, or in local.properties (compose.ios.teamId=***) - //teamId="***" - //Usage: ./gradlew iosDeployDeviceRelease - } - } - } -} - -tasks.withType { - kotlinOptions.jvmTarget = "11" -} - -// a temporary workaround for a bug in jsRun invocation - see https://youtrack.jetbrains.com/issue/KT-48273 -afterEvaluate { - rootProject.extensions.configure { - versions.webpackDevServer.version = "4.0.0" - versions.webpackCli.version = "4.9.0" - nodeVersion = "16.0.0" - } -} - -android { - compileSdk = 32 - - defaultConfig { - minSdk = 26 - targetSdk = 32 - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } - - sourceSets { - named("main") { - manifest.srcFile("src/androidMain/AndroidManifest.xml") - res.srcDirs("src/androidMain/res", "src/commonMain/resources") - } + // this is necessary to avoid the plugins to be loaded multiple times + // in each subproject's classloader + kotlin("jvm") apply false + kotlin("multiplatform") apply false + kotlin("android") apply false + id("com.android.application") apply false + id("com.android.library") apply false + id("org.jetbrains.compose") apply false +} + +allprojects { + repositories { + google() + mavenCentral() + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } } diff --git a/experimental/examples/minesweeper/desktopApp/build.gradle.kts b/experimental/examples/minesweeper/desktopApp/build.gradle.kts new file mode 100644 index 0000000000..730a5109ad --- /dev/null +++ b/experimental/examples/minesweeper/desktopApp/build.gradle.kts @@ -0,0 +1,35 @@ +import org.jetbrains.compose.desktop.application.dsl.TargetFormat + +plugins { + kotlin("multiplatform") + id("org.jetbrains.compose") +} + +kotlin { + jvm {} + sourceSets { + val jvmMain by getting { + dependencies { + implementation(compose.desktop.currentOs) + implementation(project(":shared")) + } + } + } +} + +compose.desktop { + application { + mainClass = "MainKt" + nativeDistributions { + targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) + packageName = "Minesweeper" + packageVersion = "1.0.0" + + windows { + menuGroup = "Compose Examples" + // see https://wixtoolset.org/documentation/manual/v3/howtos/general/generate_guids.html + upgradeUuid = "2bf169f9-d851-49f0-b3a1-308966d473ca" + } + } + } +} diff --git a/experimental/examples/minesweeper/desktopApp/src/jvmMain/kotlin/Main.kt b/experimental/examples/minesweeper/desktopApp/src/jvmMain/kotlin/Main.kt new file mode 100644 index 0000000000..732c30af6a --- /dev/null +++ b/experimental/examples/minesweeper/desktopApp/src/jvmMain/kotlin/Main.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2020-2021 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. + */ + +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.window.* + +fun main() = application { + val windowState = rememberWindowState() + + Window( + onCloseRequest = ::exitApplication, + resizable = false, + title = "Minesweeper", + icon = painterResource("assets/mine.png"), + state = windowState + ) { + MainView(windowState) + } +} \ No newline at end of file diff --git a/experimental/examples/minesweeper/gradle.properties b/experimental/examples/minesweeper/gradle.properties index e6fa271a3c..ea83c74d6a 100644 --- a/experimental/examples/minesweeper/gradle.properties +++ b/experimental/examples/minesweeper/gradle.properties @@ -1,17 +1,17 @@ -compose.version=1.3.0-alpha01-dev827 -kotlin.version=1.7.10 -agp.version=7.0.4 -org.gradle.jvmargs=-Xmx3g kotlin.code.style=official +xcodeproj=./iosApp +kotlin.native.cocoapods.generate.wrapper=true +android.useAndroidX=true +org.gradle.jvmargs=-Xmx3g +org.jetbrains.compose.experimental.jscanvas.enabled=true +org.jetbrains.compose.experimental.macos.enabled=true +org.jetbrains.compose.experimental.uikit.enabled=true kotlin.native.cacheKind=none kotlin.native.useEmbeddableCompilerJar=true kotlin.native.enableDependencyPropagation=false kotlin.mpp.enableGranularSourceSetsMetadata=true # Enable kotlin/native experimental memory model kotlin.native.binary.memoryModel=experimental -compose.desktop.verbose=true -android.useAndroidX=true -kotlin.js.webpack.major.version=4 -org.jetbrains.compose.experimental.jscanvas.enabled=true -org.jetbrains.compose.experimental.macos.enabled=true -org.jetbrains.compose.experimental.uikit.enabled=true +kotlin.version=1.7.20 +agp.version=7.1.3 +compose.version=1.3.0-beta04-dev885 diff --git a/experimental/examples/minesweeper/iosApp/Configuration/TeamId.xcconfig b/experimental/examples/minesweeper/iosApp/Configuration/TeamId.xcconfig new file mode 100644 index 0000000000..bf06eb27e9 --- /dev/null +++ b/experimental/examples/minesweeper/iosApp/Configuration/TeamId.xcconfig @@ -0,0 +1 @@ +TEAM_ID= diff --git a/experimental/examples/minesweeper/iosApp/Minesweeper.xcodeproj/project.pbxproj b/experimental/examples/minesweeper/iosApp/Minesweeper.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..af3f99d747 --- /dev/null +++ b/experimental/examples/minesweeper/iosApp/Minesweeper.xcodeproj/project.pbxproj @@ -0,0 +1,398 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 2152FB042600AC8F00CF470E /* iosApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2152FB032600AC8F00CF470E /* iosApp.swift */; }; + C1FC908188C4E8695729CB06 /* Pods_Minesweeper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DE96E47030356CE6AD9794A /* Pods_Minesweeper.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1EB65E27D2C0F884D0A1A133 /* Pods-Minesweeper.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Minesweeper.debug.xcconfig"; path = "Target Support Files/Pods-Minesweeper/Pods-Minesweeper.debug.xcconfig"; sourceTree = ""; }; + 2152FB032600AC8F00CF470E /* iosApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iosApp.swift; sourceTree = ""; }; + 3D7A606AB0AD7636269BD9D0 /* Pods-Minesweeper.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Minesweeper.release.xcconfig"; path = "Target Support Files/Pods-Minesweeper/Pods-Minesweeper.release.xcconfig"; sourceTree = ""; }; + 7555FF7B242A565900829871 /* Minesweeper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Minesweeper.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8DE96E47030356CE6AD9794A /* Pods_Minesweeper.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Minesweeper.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + AB3632DC29227652001CCB65 /* TeamId.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = TeamId.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9964867F0862B4D9FB6ABFC7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C1FC908188C4E8695729CB06 /* Pods_Minesweeper.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7555FF72242A565900829871 = { + isa = PBXGroup; + children = ( + AB1DB47929225F7C00F7AF9C /* Configuration */, + 7555FF7D242A565900829871 /* iosApp */, + 7555FF7C242A565900829871 /* Products */, + E1DAFBE8E1CFC0878361EF0E /* Pods */, + B62309C7396AD7BF607A63B2 /* Frameworks */, + ); + sourceTree = ""; + }; + 7555FF7C242A565900829871 /* Products */ = { + isa = PBXGroup; + children = ( + 7555FF7B242A565900829871 /* Minesweeper.app */, + ); + name = Products; + sourceTree = ""; + }; + 7555FF7D242A565900829871 /* iosApp */ = { + isa = PBXGroup; + children = ( + 7555FF8C242A565B00829871 /* Info.plist */, + 2152FB032600AC8F00CF470E /* iosApp.swift */, + ); + path = iosApp; + sourceTree = ""; + }; + AB1DB47929225F7C00F7AF9C /* Configuration */ = { + isa = PBXGroup; + children = ( + AB3632DC29227652001CCB65 /* TeamId.xcconfig */, + ); + path = Configuration; + sourceTree = ""; + }; + B62309C7396AD7BF607A63B2 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8DE96E47030356CE6AD9794A /* Pods_Minesweeper.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + E1DAFBE8E1CFC0878361EF0E /* Pods */ = { + isa = PBXGroup; + children = ( + 1EB65E27D2C0F884D0A1A133 /* Pods-Minesweeper.debug.xcconfig */, + 3D7A606AB0AD7636269BD9D0 /* Pods-Minesweeper.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7555FF7A242A565900829871 /* Minesweeper */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "Minesweeper" */; + buildPhases = ( + E8D673591E7196AEA2EA10E2 /* [CP] Check Pods Manifest.lock */, + 7555FF77242A565900829871 /* Sources */, + 7555FF79242A565900829871 /* Resources */, + 9964867F0862B4D9FB6ABFC7 /* Frameworks */, + AC9253D086E81B65FAE159E1 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Minesweeper; + productName = iosApp; + productReference = 7555FF7B242A565900829871 /* Minesweeper.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7555FF73242A565900829871 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1130; + LastUpgradeCheck = 1130; + ORGANIZATIONNAME = org.jetbrains; + TargetAttributes = { + 7555FF7A242A565900829871 = { + CreatedOnToolsVersion = 11.3.1; + }; + }; + }; + buildConfigurationList = 7555FF76242A565900829871 /* Build configuration list for PBXProject "Minesweeper" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7555FF72242A565900829871; + productRefGroup = 7555FF7C242A565900829871 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7555FF7A242A565900829871 /* Minesweeper */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7555FF79242A565900829871 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + AC9253D086E81B65FAE159E1 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Minesweeper/Pods-Minesweeper-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Minesweeper/Pods-Minesweeper-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Minesweeper/Pods-Minesweeper-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + E8D673591E7196AEA2EA10E2 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Minesweeper-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7555FF77242A565900829871 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2152FB042600AC8F00CF470E /* iosApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7555FFA3242A565B00829871 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AB3632DC29227652001CCB65 /* TeamId.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 7555FFA4242A565B00829871 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AB3632DC29227652001CCB65 /* TeamId.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 7555FFA6242A565B00829871 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1EB65E27D2C0F884D0A1A133 /* Pods-Minesweeper.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = ""; + DEVELOPMENT_TEAM = "${TEAM_ID}"; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = iosApp/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.jetbrains.Minesweeper${TEAM_ID}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 7555FFA7242A565B00829871 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3D7A606AB0AD7636269BD9D0 /* Pods-Minesweeper.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = ""; + DEVELOPMENT_TEAM = "${TEAM_ID}"; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = iosApp/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.jetbrains.Minesweeper${TEAM_ID}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7555FF76242A565900829871 /* Build configuration list for PBXProject "Minesweeper" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7555FFA3242A565B00829871 /* Debug */, + 7555FFA4242A565B00829871 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "Minesweeper" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7555FFA6242A565B00829871 /* Debug */, + 7555FFA7242A565B00829871 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7555FF73242A565900829871 /* Project object */; +} diff --git a/experimental/examples/minesweeper/iosApp/Podfile b/experimental/examples/minesweeper/iosApp/Podfile new file mode 100644 index 0000000000..43dcabd199 --- /dev/null +++ b/experimental/examples/minesweeper/iosApp/Podfile @@ -0,0 +1,5 @@ +target 'Minesweeper' do + use_frameworks! + platform :ios, '14.1' + pod 'shared', :path => '../shared' +end \ No newline at end of file diff --git a/experimental/examples/minesweeper/iosApp/iosApp/Info.plist b/experimental/examples/minesweeper/iosApp/iosApp/Info.plist new file mode 100644 index 0000000000..9a269f5eaa --- /dev/null +++ b/experimental/examples/minesweeper/iosApp/iosApp/Info.plist @@ -0,0 +1,48 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + + UILaunchScreen + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/experimental/examples/minesweeper/iosApp/iosApp/iosApp.swift b/experimental/examples/minesweeper/iosApp/iosApp/iosApp.swift new file mode 100644 index 0000000000..b42016a6fc --- /dev/null +++ b/experimental/examples/minesweeper/iosApp/iosApp/iosApp.swift @@ -0,0 +1,15 @@ +import UIKit +import shared + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + window = UIWindow(frame: UIScreen.main.bounds) + let mainViewController = Main_iosKt.MainViewController() + window?.rootViewController = mainViewController + window?.makeKeyAndVisible() + return true + } +} diff --git a/experimental/examples/minesweeper/jsApp/build.gradle.kts b/experimental/examples/minesweeper/jsApp/build.gradle.kts new file mode 100644 index 0000000000..99f2073a62 --- /dev/null +++ b/experimental/examples/minesweeper/jsApp/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + kotlin("multiplatform") + id("org.jetbrains.compose") +} + +kotlin { + js(IR) { + browser() + binaries.executable() + } + sourceSets { + val jsMain by getting { + dependencies { + implementation(project(":shared")) + } + } + } +} + +compose.experimental { + web.application {} +} + diff --git a/experimental/examples/minesweeper/jsApp/src/jsMain/kotlin/main.js.kt b/experimental/examples/minesweeper/jsApp/src/jsMain/kotlin/main.js.kt new file mode 100644 index 0000000000..b36b64e9ad --- /dev/null +++ b/experimental/examples/minesweeper/jsApp/src/jsMain/kotlin/main.js.kt @@ -0,0 +1,16 @@ + /* + * Copyright 2020-2021 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. + */ + +import androidx.compose.ui.window.Window +import org.jetbrains.skiko.wasm.onWasmReady + + +fun main() { + onWasmReady { + Window("Minesweeper") { + MainView() + } + } +} diff --git a/experimental/examples/minesweeper/src/desktopMain/resources/assets/clock.png b/experimental/examples/minesweeper/jsApp/src/jsMain/resources/assets/clock.png similarity index 100% rename from experimental/examples/minesweeper/src/desktopMain/resources/assets/clock.png rename to experimental/examples/minesweeper/jsApp/src/jsMain/resources/assets/clock.png diff --git a/experimental/examples/minesweeper/src/desktopMain/resources/assets/flag.png b/experimental/examples/minesweeper/jsApp/src/jsMain/resources/assets/flag.png similarity index 100% rename from experimental/examples/minesweeper/src/desktopMain/resources/assets/flag.png rename to experimental/examples/minesweeper/jsApp/src/jsMain/resources/assets/flag.png diff --git a/experimental/examples/minesweeper/src/desktopMain/resources/assets/mine.png b/experimental/examples/minesweeper/jsApp/src/jsMain/resources/assets/mine.png similarity index 100% rename from experimental/examples/minesweeper/src/desktopMain/resources/assets/mine.png rename to experimental/examples/minesweeper/jsApp/src/jsMain/resources/assets/mine.png diff --git a/experimental/examples/minesweeper/src/jsMain/resources/index.html b/experimental/examples/minesweeper/jsApp/src/jsMain/resources/index.html similarity index 85% rename from experimental/examples/minesweeper/src/jsMain/resources/index.html rename to experimental/examples/minesweeper/jsApp/src/jsMain/resources/index.html index c0a74e6acf..9dd212786b 100644 --- a/experimental/examples/minesweeper/src/jsMain/resources/index.html +++ b/experimental/examples/minesweeper/jsApp/src/jsMain/resources/index.html @@ -11,6 +11,6 @@ - + \ No newline at end of file diff --git a/experimental/examples/minesweeper/run-configurations.png b/experimental/examples/minesweeper/run-configurations.png new file mode 100644 index 0000000000000000000000000000000000000000..3a904f61c36240ae5ede721c07f09506d7914fbf GIT binary patch literal 21525 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 literal 0 HcmV?d00001 diff --git a/experimental/examples/minesweeper/settings.gradle.kts b/experimental/examples/minesweeper/settings.gradle.kts index 037941996c..a5c3565b83 100644 --- a/experimental/examples/minesweeper/settings.gradle.kts +++ b/experimental/examples/minesweeper/settings.gradle.kts @@ -1,7 +1,5 @@ pluginManagement { repositories { - mavenLocal() - mavenCentral() gradlePluginPortal() maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") google() @@ -9,14 +7,22 @@ pluginManagement { plugins { val kotlinVersion = extra["kotlin.version"] as String + val agpVersion = extra["agp.version"] as String + val composeVersion = extra["compose.version"] as String + + kotlin("jvm").version(kotlinVersion) kotlin("multiplatform").version(kotlinVersion) kotlin("android").version(kotlinVersion) - - val agpVersion = extra["agp.version"] as String + id("com.android.base").version(agpVersion) id("com.android.application").version(agpVersion) - - val composeVersion = extra["compose.version"] as String + id("com.android.library").version(agpVersion) id("org.jetbrains.compose").version(composeVersion) } } + rootProject.name = "minesweeper" + +include(":androidApp") +include(":shared") +include(":desktopApp") +include(":jsApp") diff --git a/experimental/examples/minesweeper/shared/build.gradle.kts b/experimental/examples/minesweeper/shared/build.gradle.kts new file mode 100644 index 0000000000..2477df7e4a --- /dev/null +++ b/experimental/examples/minesweeper/shared/build.gradle.kts @@ -0,0 +1,117 @@ +plugins { + kotlin("multiplatform") + kotlin("native.cocoapods") + id("com.android.library") + id("org.jetbrains.compose") +} + +version = "1.0-SNAPSHOT" + +kotlin { + android() + + jvm("desktop") + + ios() + iosSimulatorArm64() + + js(IR) { + browser() + } + + macosX64 { + binaries { + executable { + entryPoint = "main" + } + } + } + macosArm64 { + binaries { + executable { + entryPoint = "main" + } + } + } + + cocoapods { + summary = "Shared code for the sample" + homepage = "https://github.com/JetBrains/compose-jb" + ios.deploymentTarget = "14.1" + podfile = project.file("../iosApp/Podfile") + framework { + baseName = "shared" + isStatic = true + } + extraSpecAttributes["resources"] = "['src/commonMain/resources/**', 'src/iosMain/resources/**']" + } + + val composeVersion = extra["compose.version"] as String + + sourceSets { + val commonMain by getting { + dependencies { + implementation(compose.ui) + implementation(compose.foundation) + implementation(compose.material) + implementation(compose.runtime) + implementation("org.jetbrains.compose.components:components-resources:$composeVersion") + } + } + val commonTest by getting { + dependencies { + implementation(kotlin("test")) + implementation(kotlin("test-annotations-common")) } + } + + val androidMain by getting { + dependencies { + implementation("com.google.android.material:material:1.7.0") + } + } + val androidTest by getting { + dependencies { + implementation("junit:junit:4.13.2") + } + } + val iosMain by getting + val iosTest by getting + val iosSimulatorArm64Main by getting { + dependsOn(iosMain) + } + val iosSimulatorArm64Test by getting { + dependsOn(iosTest) + } + + val desktopMain by getting { + dependencies { + implementation(compose.desktop.common) + } + } + + val macosMain by creating { + dependsOn(commonMain) + } + val macosX64Main by getting { + dependsOn(macosMain) + } + val macosArm64Main by getting { + dependsOn(macosMain) + } + } +} + +android { + compileSdk = 33 + sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") + sourceSets["main"].res.srcDirs("src/androidMain/res") + sourceSets["main"].resources.srcDirs("src/commonMain/resources") + defaultConfig { + minSdk = 24 + targetSdk = 33 + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } +} diff --git a/experimental/examples/minesweeper/shared/src/androidMain/AndroidManifest.xml b/experimental/examples/minesweeper/shared/src/androidMain/AndroidManifest.xml new file mode 100644 index 0000000000..77790de2eb --- /dev/null +++ b/experimental/examples/minesweeper/shared/src/androidMain/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/experimental/examples/minesweeper/shared/src/androidMain/kotlin/main.android.kt b/experimental/examples/minesweeper/shared/src/androidMain/kotlin/main.android.kt new file mode 100644 index 0000000000..460fdeb8f2 --- /dev/null +++ b/experimental/examples/minesweeper/shared/src/androidMain/kotlin/main.android.kt @@ -0,0 +1,5 @@ +import androidx.compose.runtime.Composable + +@Composable fun MainView() = Game() + +actual fun hasRightClick() = false diff --git a/experimental/examples/minesweeper/src/commonMain/kotlin/BoardView.kt b/experimental/examples/minesweeper/shared/src/commonMain/kotlin/BoardView.kt similarity index 93% rename from experimental/examples/minesweeper/src/commonMain/kotlin/BoardView.kt rename to experimental/examples/minesweeper/shared/src/commonMain/kotlin/BoardView.kt index a72e93b88b..86c51edd8a 100644 --- a/experimental/examples/minesweeper/src/commonMain/kotlin/BoardView.kt +++ b/experimental/examples/minesweeper/shared/src/commonMain/kotlin/BoardView.kt @@ -10,7 +10,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @Composable -fun BoardView(game: GameController) = with(GameStyles) { +internal fun BoardView(game: GameController) = with(GameStyles) { Column { for (row in 0 until game.rows) { Row(verticalAlignment = Alignment.CenterVertically) { diff --git a/experimental/examples/minesweeper/src/commonMain/kotlin/GameController.kt b/experimental/examples/minesweeper/shared/src/commonMain/kotlin/GameController.kt similarity index 100% rename from experimental/examples/minesweeper/src/commonMain/kotlin/GameController.kt rename to experimental/examples/minesweeper/shared/src/commonMain/kotlin/GameController.kt diff --git a/experimental/examples/minesweeper/src/commonMain/kotlin/game.kt b/experimental/examples/minesweeper/shared/src/commonMain/kotlin/game.kt similarity index 81% rename from experimental/examples/minesweeper/src/commonMain/kotlin/game.kt rename to experimental/examples/minesweeper/shared/src/commonMain/kotlin/game.kt index 90768fa701..ea6893597b 100644 --- a/experimental/examples/minesweeper/src/commonMain/kotlin/game.kt +++ b/experimental/examples/minesweeper/shared/src/commonMain/kotlin/game.kt @@ -5,36 +5,21 @@ import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.ui.* -import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.unit.* +import org.jetbrains.compose.resources.ExperimentalResourceApi +import org.jetbrains.compose.resources.orEmpty +import org.jetbrains.compose.resources.rememberImageBitmap +import org.jetbrains.compose.resources.resource import kotlin.math.max +@OptIn(ExperimentalResourceApi::class) @Composable -expect fun loadImage(src: String): Painter - -fun loadImageAsColoredRect(src: String): Painter { - // TODO Bundle pics and show images properly - val color = when (src) { - "assets/clock.png" -> Color.Blue - "assets/flag.png" -> Color.Green - "assets/mine.png" -> Color.Red - else -> Color.White - } - - return object : Painter() { - override val intrinsicSize: Size - get() = Size(16f, 16f) - - override fun DrawScope.onDraw() { - drawRect(color = color) - } - } -} +internal fun loadImage(res: String): Painter = BitmapPainter(resource(res).rememberImageBitmap().orEmpty()) -expect fun isMobileDevice(): Boolean +expect fun hasRightClick(): Boolean object Difficulty { val EASY = GameSettings(9, 9, 10) @@ -56,7 +41,7 @@ object GameStyles { } @Composable -fun Game(requestWindowSize: ((width: Dp, height: Dp) -> Unit)? = null) = MainLayout { +internal fun Game(requestWindowSize: ((width: Dp, height: Dp) -> Unit)? = null) = MainLayout { var message by remember { mutableStateOf(null) } val onWin = { message = "You win!" } diff --git a/experimental/examples/minesweeper/src/commonMain/kotlin/gameInteraction.kt b/experimental/examples/minesweeper/shared/src/commonMain/kotlin/gameInteraction.kt similarity index 92% rename from experimental/examples/minesweeper/src/commonMain/kotlin/gameInteraction.kt rename to experimental/examples/minesweeper/shared/src/commonMain/kotlin/gameInteraction.kt index 32b0261038..e744152ec9 100644 --- a/experimental/examples/minesweeper/src/commonMain/kotlin/gameInteraction.kt +++ b/experimental/examples/minesweeper/shared/src/commonMain/kotlin/gameInteraction.kt @@ -6,8 +6,8 @@ import androidx.compose.ui.input.pointer.* @OptIn(ExperimentalFoundationApi::class) @Composable -fun Modifier.gameInteraction(open: () -> Unit, flag: () -> Unit, seek: () -> Unit): Modifier = - if (isMobileDevice()) { +internal fun Modifier.gameInteraction(open: () -> Unit, flag: () -> Unit, seek: () -> Unit): Modifier = + if (!hasRightClick()) { combinedClickable( onClick = { open() diff --git a/experimental/examples/minesweeper/src/commonMain/kotlin/widgets.kt b/experimental/examples/minesweeper/shared/src/commonMain/kotlin/widgets.kt similarity index 87% rename from experimental/examples/minesweeper/src/commonMain/kotlin/widgets.kt rename to experimental/examples/minesweeper/shared/src/commonMain/kotlin/widgets.kt index 3a81aca773..8b262ee713 100644 --- a/experimental/examples/minesweeper/src/commonMain/kotlin/widgets.kt +++ b/experimental/examples/minesweeper/shared/src/commonMain/kotlin/widgets.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @Composable -fun OpenedCell(cell: Cell) { +internal fun OpenedCell(cell: Cell) { Text( text = cell.bombsNear.toString(), textAlign = TextAlign.Center, @@ -28,7 +28,7 @@ fun OpenedCell(cell: Cell) { } @Composable -fun CellWithIcon(src: String, alt: String) { +internal fun CellWithIcon(src: String, alt: String) { Image( painter = loadImage(src), contentDescription = alt, @@ -37,17 +37,17 @@ fun CellWithIcon(src: String, alt: String) { } @Composable -fun Mine() { +internal fun Mine() { CellWithIcon(src = "assets/mine.png", alt = "Bomb") } @Composable -fun Flag() { +internal fun Flag() { CellWithIcon(src = "assets/flag.png", alt = "Flag") } @Composable -fun IndicatorWithIcon(iconPath: String, alt: String, value: Int) { +internal fun IndicatorWithIcon(iconPath: String, alt: String, value: Int) { Box(modifier = Modifier.background(Color(0x8e, 0x6e, 0x0e))) { Row(verticalAlignment = Alignment.CenterVertically) { Box(modifier = Modifier.size(40.dp, 40.dp)) { @@ -66,7 +66,7 @@ fun IndicatorWithIcon(iconPath: String, alt: String, value: Int) { } @Composable -fun NewGameButton(text: String, onClick: () -> Unit) { +internal fun NewGameButton(text: String, onClick: () -> Unit) { Box( Modifier .background(color = Color(0x42, 0x8e, 0x04)) diff --git a/experimental/examples/minesweeper/shared/src/commonMain/resources/assets/clock.png b/experimental/examples/minesweeper/shared/src/commonMain/resources/assets/clock.png new file mode 100644 index 0000000000000000000000000000000000000000..d36975927b1f9ab46d4f468b92f839fb1a01b9be GIT binary patch literal 896 zcmV-`1AqL9P)ax^Yb|USu^(r`;8tz?6{9}ChSS(L zj^hrFqn8=IfET2%@6=@HW9>plwucvMvO{4O--VHNoYdd$9Nido>x+0Jes}bbEvi;28$L9qHO<1!11Lp8A zHnETko(X0rS~@s_r(5d08ou7DCU#44+p}}1m2g!`L~SsW`P(%qrPnULl2U3LbZ}=& zomG4-<%%aJrQ8mmwKOyiDqn};XX#8928s{HFnM4nJQzMNkc%YuQ%`~o*ja~x^$5T;YirJ5w@#~ejOW=@n<4a$kXp;1A!lL556prxI_PV15!wC zNv+$%P0lOK;@eQ%#M`)c2f4j=ZcJvRh^iWsWh1m{Q+PQDR2|YMI4Zs8)0yma%pDDx z_0ZYCOPc$OA{L|qvg#4@aXm(Tz9+@`e3S8sCV>oHDd#_qM}t_sJ-;lq=U+&>(1_c? Wq2Dl#9r9fO0000l5 zRzVQ$a%HrLphX~Ulpv^OK`vTE(548X2%%l{ArTSUA{RQk7%*qX8Ry-1+Bi|8qmv(j zG=DgobMF1~d+%QEJr`Bw_wYQg&vBfj=Xv)EIUoWY0xkfTfFnS4@!a*qvV<`v)!Esp zj^kv3{Y@fI9I!1S_PFB&$9#XG-f>a_wo2qB(7F)-mm-B>Sku(pj4_5t7{2RL^{)VR zs$eZx>trJlCgX92Q>hcr(&?{`$h8pes%lv5x0Xz)f(-({Pt_j)>WXU7T#ntdv-JDE zce|mXYNzYo@Bbpn)J0@w3$$uPXJpxX4q+96f_tg5-C7*o~ZIn}mLs&~4<4g;%Qh5EMu zA`${4s+uins+yZu?a#pB2O?AFMRXKMEY%l1kMFS!5gXtJDf+v^~z08{`f0RIPoF(#duo+bza7f5b7K{?O!t&E>H4*=_pt%!gC0000< KMNUMnLSTZ<-%#iP literal 0 HcmV?d00001 diff --git a/experimental/examples/minesweeper/shared/src/commonMain/resources/assets/mine.png b/experimental/examples/minesweeper/shared/src/commonMain/resources/assets/mine.png new file mode 100644 index 0000000000000000000000000000000000000000..d42eca2f389ca25fa2e4060a09c0c479c53bb5de GIT binary patch literal 1934 zcmV;92XXj`P)jwlR~KNwpLx#ncjUlw>+IKg@{GDTH-# znE+!kvM$T+-Mt^DKOhujF$_-Hcjo@M?|IMrJoh>0J?Fk)jA1bk08tdhegL}`n}aci z#ZLq_0br`CUV9V*92RMUAZ#rz_M6FMasv@bi_Nnr0z||~l34X*c{y*l+f4wKUpfII zN++UfS(Y1ko{z+0@yC7n`AA=~#70E#+HAIo<&Qn~4|yw7(OPi->Y;Hd`xz9sq}Ck(%1k005rn4~wFB%$=Q`2!%ok z2FQNDU;SoD3GqBX9an$q6ck0lQkM$=5E>lBQ(L#f=kra+Xqtxh_I7qF5J(acS6EQM zb@%kZvaABeSYJv7EXz6tV6b%4Ms;sZjgv8E>+bHRo}QjrQf?|O#j@qgF+4JYn5Lni zpa82@t(qQZjN!u%K0u(qpX@f9{IjD+MF2^j=TFWApQFIkI+cln(01arU7bkj6l zjIrp<9I2{6&<#U4cKkJ{ih@JW9fYbV7#|-`5jxixV@MB39C)6` zn!G%^6$qRLuy$SoMD!H^dF$7&hpy{*E}O zvq}KK-Z{7?5sI9GqYw1$RQtCU&G)=@}F~l_ugP{;xl9m>q zh{ZTT5YBN#M3^i`4gguE`A~2GAOMzSePP_^_IatZsX3-)0h2yXh{xmKC!zz9NMyYr z2xnGiW`1qmx^)jtI504P)2B~kU|;}&KmdkeOskQ~qR}YA;V^FBzKzk*(Y|OjS_j~| zZWsnP#n5DoePkHMUqhh~0KhN|+`M@chGEP}n3I!(ot2enYiolbir7_Mof0?_iJH-%mC(ALD%rm5VI_c-n)1a!C(-bot>zwtD94XE|&|UD8l1* z&%05Zo0?!*7M|F!0UnPBcR%~gibkXF&5V2SBz)hpEWPW-4FrQhd~e@Aa71|X>{%od ziPZY0u+Z(>XliW4TAvTaem_3GejVfE;|Pz9naO1G%De;^V-X_yO-Dxuva_3bFM0oMY zVZ`Hcynf~kG)+T#disJ02!a4vmeC&wpry4HilSiW_U+I#jV2~0UVbos)@?{cf-KAZ zdv;fQW3f0jHa9~M1bnNk3~Sf^_Xxk))rI~*03*Z0$Z$HbV#NxSl$1bK)#;dvt*rd6HXlZSY_xASvTG#a>^Ag~B{;(hjzg*?@#%~3KBuSE5vv)5!9FAG6U$3u+ zEX#1YTp%KZLLroI*@B{?BIvq~d-v`^*LB>#e;@6aF9U#CR9J{F{2>tp;fJPa8o_~q zW2R{?<2ddo@0>el1cSj@1RM?r+-^6H{o)lI`Oymi0JqzXNF;(gckV#fbqsy_DXv|; zs;R2_l4V(Idi(m?EX(2n?3;x-^Cg)~ZUZpP7`r>=I!;6%{_WDG_SLIb+l%~u%FN7! z*Xu=ZZ!ZAg{q}ZF9%;V}C8`n2Jpp|D{XPbU(IkEe1yO+|X~&~9r;kEF6h-l0c*OSnKQ-F( U1 + windowState.size = windowState.size.copy(width = w, height = h) + } + ) + } + +actual fun hasRightClick() = true diff --git a/experimental/examples/minesweeper/shared/src/iosMain/kotlin/main.ios.kt b/experimental/examples/minesweeper/shared/src/iosMain/kotlin/main.ios.kt new file mode 100644 index 0000000000..0ccba7c43a --- /dev/null +++ b/experimental/examples/minesweeper/shared/src/iosMain/kotlin/main.ios.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. + * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. + */ + +import androidx.compose.ui.window.Application +import platform.UIKit.UIViewController + +fun MainViewController() : UIViewController = + Application("Minesweeper") { + Game() + } + + +actual fun hasRightClick() = false \ No newline at end of file diff --git a/experimental/examples/minesweeper/shared/src/jsMain/kotlin/main.js.kt b/experimental/examples/minesweeper/shared/src/jsMain/kotlin/main.js.kt new file mode 100644 index 0000000000..5e07958636 --- /dev/null +++ b/experimental/examples/minesweeper/shared/src/jsMain/kotlin/main.js.kt @@ -0,0 +1,6 @@ +import androidx.compose.runtime.Composable + +@Composable +fun MainView() = Game() + +actual fun hasRightClick() = false diff --git a/experimental/examples/minesweeper/src/macosMain/kotlin/main.macos.kt b/experimental/examples/minesweeper/shared/src/macosMain/kotlin/main.macos.kt similarity index 88% rename from experimental/examples/minesweeper/src/macosMain/kotlin/main.macos.kt rename to experimental/examples/minesweeper/shared/src/macosMain/kotlin/main.macos.kt index 41ae920d49..88b034d366 100644 --- a/experimental/examples/minesweeper/src/macosMain/kotlin/main.macos.kt +++ b/experimental/examples/minesweeper/shared/src/macosMain/kotlin/main.macos.kt @@ -29,7 +29,4 @@ fun main() { NSApp?.run() } -@Composable -actual fun loadImage(src: String): Painter = loadImageAsColoredRect(src) - -actual fun isMobileDevice() = false \ No newline at end of file +actual fun hasRightClick() = false \ No newline at end of file diff --git a/experimental/examples/minesweeper/src/androidMain/kotlin/actualfuns.android.kt b/experimental/examples/minesweeper/src/androidMain/kotlin/actualfuns.android.kt deleted file mode 100644 index b8ac63873d..0000000000 --- a/experimental/examples/minesweeper/src/androidMain/kotlin/actualfuns.android.kt +++ /dev/null @@ -1,7 +0,0 @@ -import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.painter.Painter - -@Composable -actual fun loadImage(src: String): Painter = loadImageAsColoredRect(src) - -actual fun isMobileDevice() = true \ No newline at end of file diff --git a/experimental/examples/minesweeper/src/desktopMain/kotlin/main.desktop.kt b/experimental/examples/minesweeper/src/desktopMain/kotlin/main.desktop.kt deleted file mode 100644 index c12de62591..0000000000 --- a/experimental/examples/minesweeper/src/desktopMain/kotlin/main.desktop.kt +++ /dev/null @@ -1,32 +0,0 @@ -import androidx.compose.material.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.window.Window -import androidx.compose.ui.window.application -import androidx.compose.ui.window.rememberWindowState - -fun main() = application { - val windowState = rememberWindowState() - - Window( - onCloseRequest = ::exitApplication, - resizable = false, - title = "Minesweeper", - icon = painterResource("assets/mine.png"), - state = windowState - ) { - MaterialTheme { - Game( - requestWindowSize = { w, h -> - windowState.size = windowState.size.copy(width = w, height = h) - } - ) - } - } -} - -@Composable -actual fun loadImage(src: String): Painter = painterResource(src) - -actual fun isMobileDevice() = false diff --git a/experimental/examples/minesweeper/src/jsMain/kotlin/main.js.kt b/experimental/examples/minesweeper/src/jsMain/kotlin/main.js.kt deleted file mode 100644 index 1d1dd2d69f..0000000000 --- a/experimental/examples/minesweeper/src/jsMain/kotlin/main.js.kt +++ /dev/null @@ -1,24 +0,0 @@ -import androidx.compose.runtime.Composable -import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.drawscope.DrawScope -import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.window.Window -import org.jetbrains.skiko.wasm.onWasmReady - -fun main() { - onWasmReady { - Window("Minesweeper") { - Game( - requestWindowSize = { _, _ -> - // TODO(not implemented yet) - } - ) - } - } -} - -@Composable -actual fun loadImage(src: String): Painter = loadImageAsColoredRect(src) - -actual fun isMobileDevice() = false diff --git a/experimental/examples/minesweeper/src/uikitMain/kotlin/main.uikit.kt b/experimental/examples/minesweeper/src/uikitMain/kotlin/main.uikit.kt deleted file mode 100644 index 1cfea076b5..0000000000 --- a/experimental/examples/minesweeper/src/uikitMain/kotlin/main.uikit.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers. - * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. - */ - -import androidx.compose.runtime.Composable -import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.drawscope.DrawScope -import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.window.Application -import androidx.compose.ui.main.defaultUIKitMain - -fun main() { - defaultUIKitMain("Minesweeper", Application("Minesweeper") { - Game() - }) -} - -@Composable -actual fun loadImage(src: String): Painter = loadImageAsColoredRect(src) - -actual fun isMobileDevice() = true \ No newline at end of file