Aleksey Mikhailov 2 weeks ago committed by GitHub
parent
commit
1f6dbfb473
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      examples/common-platform-uikit/.gitignore
  2. 24
      examples/common-platform-uikit/README.md
  3. 34
      examples/common-platform-uikit/android/build.gradle.kts
  4. 18
      examples/common-platform-uikit/android/src/main/AndroidManifest.xml
  5. 24
      examples/common-platform-uikit/android/src/main/java/com/example/compose/android/MainActivity.kt
  6. 15
      examples/common-platform-uikit/build.gradle.kts
  7. 122
      examples/common-platform-uikit/common/build.gradle.kts
  8. 2
      examples/common-platform-uikit/common/src/androidMain/AndroidManifest.xml
  9. 13
      examples/common-platform-uikit/common/src/androidMain/kotlin/com/example/compose/common/AndroidApp.kt
  10. 43
      examples/common-platform-uikit/common/src/commonMain/kotlin/com/example/compose/common/AuthUI.kt
  11. 43
      examples/common-platform-uikit/common/src/commonMain/kotlin/com/example/compose/common/PlatformKit.kt
  12. 29
      examples/common-platform-uikit/common/src/commonMain/kotlin/com/example/compose/common/PlatformKitExt.kt
  13. 4
      examples/common-platform-uikit/common/src/composeUIKitArm64Main/kotlin/UIViewProtocol.kt
  14. 10
      examples/common-platform-uikit/common/src/composeUIKitMain/cinterop/UIViewProtocol.def
  15. 32
      examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/ComposeAppDelegate.kt
  16. 80
      examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/ComposeViewController.kt
  17. 3
      examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/UIViewProtocol.kt
  18. 74
      examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/com/example/compose/common/Modifier.kt
  19. 76
      examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/com/example/compose/common/PlatformKit.kt
  20. 198
      examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/com/example/compose/common/uikit/ComposableUIKit.kt
  21. 59
      examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/com/example/compose/common/uikit/UIKitApplier.kt
  22. 14
      examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/com/example/compose/ios/IosApp.kt
  23. 17
      examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/main.kt
  24. 4
      examples/common-platform-uikit/common/src/composeUIKitSimulatorArm64Main/kotlin/UIViewProtocol.kt
  25. 4
      examples/common-platform-uikit/common/src/composeUIKitX64Main/kotlin/UIViewProtocol.kt
  26. 105
      examples/common-platform-uikit/common/src/composeUiMain/kotlin/ru/dewish/campus/moderator/common/PlatformKit.kt
  27. 146
      examples/common-platform-uikit/common/src/jsMain/kotlin/com/example/compose/common/PlatformKit.kt
  28. 13
      examples/common-platform-uikit/common/src/jvmMain/kotlin/com/example/compose/common/DesktopApp.kt
  29. 29
      examples/common-platform-uikit/desktop/build.gradle.kts
  30. 21
      examples/common-platform-uikit/desktop/src/main/kotlin/com/example/compose/jvm/Main.kt
  31. 6
      examples/common-platform-uikit/gradle.properties
  32. BIN
      examples/common-platform-uikit/gradle/wrapper/gradle-wrapper.jar
  33. 5
      examples/common-platform-uikit/gradle/wrapper/gradle-wrapper.properties
  34. 234
      examples/common-platform-uikit/gradlew
  35. 89
      examples/common-platform-uikit/gradlew.bat
  36. 344
      examples/common-platform-uikit/ios/iosApp.xcodeproj/project.pbxproj
  37. 7
      examples/common-platform-uikit/ios/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  38. 8
      examples/common-platform-uikit/ios/iosApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  39. BIN
      examples/common-platform-uikit/ios/iosApp.xcodeproj/project.xcworkspace/xcuserdata/amikhailov.xcuserdatad/UserInterfaceState.xcuserstate
  40. 14
      examples/common-platform-uikit/ios/iosApp.xcodeproj/xcuserdata/amikhailov.xcuserdatad/xcschemes/xcschememanagement.plist
  41. 11
      examples/common-platform-uikit/ios/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json
  42. 98
      examples/common-platform-uikit/ios/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json
  43. 6
      examples/common-platform-uikit/ios/iosApp/Assets.xcassets/Contents.json
  44. 25
      examples/common-platform-uikit/ios/iosApp/Base.lproj/LaunchScreen.storyboard
  45. 5
      examples/common-platform-uikit/ios/iosApp/Info.plist
  46. 29
      examples/common-platform-uikit/settings.gradle.kts
  47. 19
      examples/common-platform-uikit/web/build.gradle.kts
  48. 8
      examples/common-platform-uikit/web/src/jsMain/kotlin/Main.kt
  49. 11
      examples/common-platform-uikit/web/src/jsMain/resources/index.html

5
examples/common-platform-uikit/.gitignore vendored

@ -0,0 +1,5 @@
.idea/
.gradle/
build/
local.properties
kotlin-js-store/

24
examples/common-platform-uikit/README.md

@ -0,0 +1,24 @@
# Sample with common UI between android, desktop, web, ios
In this sample all platforms use own native UIKit (except Desktop):
- Android - material Compose UI
- Desktop - material Compose UI
- Web - Compose Web
- iOS - UIKit Compose components
But all application UI implemented in `commonMain` - low level build kit elements like `Text`, `Column` etc is `expect`
and implemented on all platform by platform UI.
# Screenshots
## iOS
![ezgif-3-3924687fe7](https://user-images.githubusercontent.com/5010169/150639117-ce64ecc1-e36a-405b-aaa3-be1b2e32759e.gif)
## Android
![ezgif-3-4ee9b0a5b6](https://user-images.githubusercontent.com/5010169/150639110-58ae9de4-449b-47a2-9aba-ae74b22dfde9.gif)
## Desktop
![ezgif-3-fc12402deb](https://user-images.githubusercontent.com/5010169/150639115-d12f893b-06aa-42c1-95ea-8dce3c3a0778.gif)
## Web
![ezgif-3-bbc7ea0c78](https://user-images.githubusercontent.com/5010169/150639108-4a10d23c-8605-4df4-ba75-aa9b3d6ae6aa.gif)

34
examples/common-platform-uikit/android/build.gradle.kts

@ -0,0 +1,34 @@
plugins {
id("com.android.application")
id("org.jetbrains.compose")
kotlin("android")
}
android {
compileSdk = 31
defaultConfig {
applicationId = "com.example.compose.android"
minSdk = 21
targetSdk = 31
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
}
dependencies {
implementation(project(":common"))
implementation("androidx.activity:activity-compose:1.3.0")
implementation("androidx.compose.ui:ui-tooling:1.0.5")
implementation("androidx.compose.ui:ui-tooling-preview:1.0.5")
}

18
examples/common-platform-uikit/android/src/main/AndroidManifest.xml

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.compose.android">
<application
android:allowBackup="false"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

24
examples/common-platform-uikit/android/src/main/java/com/example/compose/android/MainActivity.kt

@ -0,0 +1,24 @@
/*
* 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.
*/
package com.example.compose.android
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.material.MaterialTheme
import com.example.compose.common.AndroidApp
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
AndroidApp()
}
}
}
}

15
examples/common-platform-uikit/build.gradle.kts

@ -0,0 +1,15 @@
plugins {
val kotlinVersion = "1.6.10"
val composeMultiplatformVersion = "1.1.0-beta04"
val mobileMultiplatformVersion = "0.12.0"
id("com.android.library") apply false
id("dev.icerock.mobile.multiplatform.android-manifest") version mobileMultiplatformVersion apply false
kotlin("jvm") version kotlinVersion apply false
kotlin("multiplatform") version kotlinVersion apply false
id("org.jetbrains.compose") version composeMultiplatformVersion apply false
}
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().nodeVersion = "16.0.0"
}

122
examples/common-platform-uikit/common/build.gradle.kts

@ -0,0 +1,122 @@
plugins {
id("com.android.library")
id("dev.icerock.mobile.multiplatform.android-manifest")
kotlin("multiplatform")
id("org.jetbrains.compose")
}
android {
compileSdk = 31
defaultConfig {
minSdk = 21
targetSdk = 31
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
kotlin {
android()
jvm {
compilations.all {
kotlinOptions.jvmTarget = "11"
}
}
js(IR) {
browser()
}
val composeUIKitArm64 = iosArm64("composeUIKitArm64")
val composeUIKitSimulatorArm64 = iosArm64("composeUIKitSimulatorArm64")
val composeUIKitX64 = iosX64("composeUIKitX64")
configure(listOf(composeUIKitArm64, composeUIKitSimulatorArm64, composeUIKitX64)) {
binaries {
executable {
entryPoint = "main"
freeCompilerArgs += listOf(
"-linker-option", "-framework", "-linker-option", "Metal",
"-linker-option", "-framework", "-linker-option", "CoreText",
"-linker-option", "-framework", "-linker-option", "CoreGraphics"
)
// TODO: the current compose binary surprises LLVM, so disable checks for now.
freeCompilerArgs += "-Xdisable-phases=VerifyBitcode"
}
}
compilations.getByName("main") {
val uiViewProtocol by cinterops.creating {
defFile(project.file("src/composeUIKitMain/cinterop/UIViewProtocol.def"))
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
api(compose.runtime)
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-native-mt") {
isForce = true
}
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val composeUiMain by creating {
dependsOn(commonMain)
dependencies {
api(compose.ui)
api(compose.foundation)
api(compose.material)
}
}
val androidMain by getting {
dependsOn(composeUiMain)
dependencies {
api("androidx.appcompat:appcompat:1.2.0")
api("androidx.core:core-ktx:1.3.1")
implementation("androidx.compose.ui:ui-tooling:1.0.5")
implementation("androidx.navigation:navigation-compose:2.4.0-rc01")
}
}
val jvmMain by getting {
dependsOn(composeUiMain)
dependencies {
api(compose.preview)
implementation(compose.desktop.currentOs)
}
}
val jvmTest by getting
val jsMain by getting {
dependencies {
implementation(compose.web.core)
}
}
// compose uikit
val composeUIKitMain by creating {
dependsOn(commonMain)
}
val composeUIKitArm64Main by getting {
dependsOn(composeUIKitMain)
}
val composeUIKitSimulatorArm64Main by getting {
dependsOn(composeUIKitMain)
}
val composeUIKitX64Main by getting {
dependsOn(composeUIKitMain)
}
}
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
}
}

2
examples/common-platform-uikit/common/src/androidMain/AndroidManifest.xml

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.example.compose.common" />

13
examples/common-platform-uikit/common/src/androidMain/kotlin/com/example/compose/common/AndroidApp.kt

@ -0,0 +1,13 @@
/*
* 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.
*/
package com.example.compose.common
import androidx.compose.runtime.Composable
@Composable
fun AndroidApp() {
LoginScreen()
}

43
examples/common-platform-uikit/common/src/commonMain/kotlin/com/example/compose/common/AuthUI.kt

@ -0,0 +1,43 @@
/*
* 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.
*/
package com.example.compose.common
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@Composable
fun LoginScreen() {
var email: String by remember { mutableStateOf("") }
var password: String by remember { mutableStateOf("") }
var authInProgress: Boolean by remember { mutableStateOf(false) }
Box(modifier = Modifier.fillMaxSize()) {
Column(modifier = Modifier.width(300).align(Alignment.Center)) {
Text(text = "Вход")
TextField(label = "E-mail", value = email) { email = it }
TextField(label = "Password", value = password) { password = it }
if (authInProgress) {
ProgressBar()
} else {
Button(text = "Войти", onClick = {
authInProgress = true
GlobalScope.launch(Dispatchers.Main) {
delay(2000)
authInProgress = false
}
})
}
}
}
}

43
examples/common-platform-uikit/common/src/commonMain/kotlin/com/example/compose/common/PlatformKit.kt

@ -0,0 +1,43 @@
package com.example.compose.common
import androidx.compose.runtime.Composable
@Composable
expect fun Text(modifier: Modifier, text: String)
@Composable
expect fun Column(modifier: Modifier, builder: @Composable () -> Unit)
@Composable
expect fun Box(modifier: Modifier, content: @Composable BoxScope.() -> Unit)
@Composable
expect fun ProgressBar(modifier: Modifier)
@Composable
expect fun TextField(modifier: Modifier, label: String, value: String, onValueChange: (String) -> Unit)
@Composable
expect fun Button(modifier: Modifier, text: String, onClick: () -> Unit)
expect interface Modifier {
companion object : Modifier
}
expect fun Modifier.padding(top: Int = 0, bottom: Int = 0, start: Int = 0, end: Int = 0): Modifier
expect fun Modifier.width(value: Int): Modifier
expect fun Modifier.height(value: Int): Modifier
expect fun Modifier.fillMaxSize(): Modifier
expect fun Modifier.fillMaxWidth(): Modifier
interface BoxScope {
fun Modifier.align(alignment: Alignment): Modifier
}
enum class Alignment {
Center
}

29
examples/common-platform-uikit/common/src/commonMain/kotlin/com/example/compose/common/PlatformKitExt.kt

@ -0,0 +1,29 @@
package com.example.compose.common
import androidx.compose.runtime.Composable
@Composable
fun Text(text: String) {
Text(modifier = Modifier, text = text)
}
@Composable
fun Column(builder: @Composable () -> Unit) {
Column(modifier = Modifier, builder = builder)
}
@Composable
fun ProgressBar() {
ProgressBar(modifier = Modifier)
}
@Composable
fun TextField(label: String, value: String, onValueChange: (String) -> Unit) {
TextField(modifier = Modifier, label = label, value = value, onValueChange = onValueChange)
}
@Composable
fun Button(text: String, onClick: () -> Unit) {
Button(modifier = Modifier, text = text, onClick = onClick)
}

4
examples/common-platform-uikit/common/src/composeUIKitArm64Main/kotlin/UIViewProtocol.kt

@ -0,0 +1,4 @@
import view.cinterop.UIViewWithOverridesProtocol
actual typealias UIViewProtocol = UIViewWithOverridesProtocol

10
examples/common-platform-uikit/common/src/composeUIKitMain/cinterop/UIViewProtocol.def

@ -0,0 +1,10 @@
package = view.cinterop
language = Objective-C
---
#import <Foundation/Foundation.h>
#import <UIKit/UIView.h>
@protocol UIViewWithOverrides
- (void) didMoveToSuperview;
@end

32
examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/ComposeAppDelegate.kt

@ -0,0 +1,32 @@
import com.example.compose.ios.IosApp
import platform.UIKit.UIApplication
import platform.UIKit.UIApplicationDelegateProtocol
import platform.UIKit.UIApplicationDelegateProtocolMeta
import platform.UIKit.UIResponder
import platform.UIKit.UIResponderMeta
import platform.UIKit.UIScreen
import platform.UIKit.UIWindow
class ComposeAppDelegate : UIResponder, UIApplicationDelegateProtocol {
companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta
@OverrideInit
constructor() : super()
private var _window: UIWindow? = null
override fun window() = _window
override fun setWindow(window: UIWindow?) {
_window = window
}
override fun application(application: UIApplication, didFinishLaunchingWithOptions: Map<Any?, *>?): Boolean {
window = UIWindow(frame = UIScreen.mainScreen.bounds)
window!!.rootViewController = ComposeViewController().apply {
setContent {
IosApp()
}
}
window!!.makeKeyAndVisible()
return true
}
}

80
examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/ComposeViewController.kt

@ -0,0 +1,80 @@
import androidx.compose.runtime.BroadcastFrameClock
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Composition
import androidx.compose.runtime.Recomposer
import androidx.compose.runtime.snapshots.Snapshot
import com.example.compose.common.uikit.UIKitApplier
import kotlinx.cinterop.ExportObjCClass
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import platform.Foundation.NSCoder
import platform.UIKit.UIViewController
@ExportObjCClass
class ComposeViewController : UIViewController {
@OverrideInit
constructor() : super(nibName = null, bundle = null)
@OverrideInit
constructor(coder: NSCoder) : super(coder)
private val job = Job()
private val dispatcher = Dispatchers.Main
private val frameClock = BroadcastFrameClock(onNewAwaiters = { })
private val coroutineScope = CoroutineScope(job + dispatcher + frameClock)
private val renderCoroutineScope = CoroutineScope(Dispatchers.Main)
private lateinit var recomposer: Recomposer
private lateinit var composition: Composition
private lateinit var content: @Composable () -> Unit
override fun viewDidLoad() {
super.viewDidLoad()
// useful links
// https://github.com/JakeWharton/mosaic/blob/4cb027c2074d86b3389cbfb5da35468fe7591178/mosaic/mosaic-runtime/src/main/kotlin/com/jakewharton/mosaic/mosaic.kt
// https://github.com/JetBrains/androidx/blob/3ebf1d446089cc8da34bb1b906982327af7b8249/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/ComposeScene.skiko.kt
recomposer = Recomposer(coroutineScope.coroutineContext)
composition = Composition(UIKitApplier(this.view), recomposer)
coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
recomposer.runRecomposeAndApplyChanges()
}
composition.setContent(content)
renderCoroutineScope.launch {
while (isActive) {
frameClock.sendFrame(0L) // Frame time value is not used by Compose runtime.
delay(50)
}
}
Snapshot.registerGlobalWriteObserver {
coroutineScope.launch {
Snapshot.sendApplyNotifications()
}
}
}
override fun viewDidUnload() {
super.viewDidUnload()
renderCoroutineScope.cancel()
composition.dispose()
recomposer.cancel()
job.cancel()
}
fun setContent(content: @Composable () -> Unit) {
this.content = content
}
}

3
examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/UIViewProtocol.kt

@ -0,0 +1,3 @@
expect interface UIViewProtocol {
fun didMoveToSuperview()
}

74
examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/com/example/compose/common/Modifier.kt

@ -0,0 +1,74 @@
/*
* 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.
*/
package com.example.compose.common
import platform.UIKit.UIView
import platform.UIKit.addConstraint
import platform.UIKit.addConstraints
import platform.UIKit.bottomAnchor
import platform.UIKit.heightAnchor
import platform.UIKit.leadingAnchor
import platform.UIKit.superview
import platform.UIKit.topAnchor
import platform.UIKit.trailingAnchor
import platform.UIKit.widthAnchor
actual interface Modifier {
val modifications: List<(UIView) -> Unit>
actual companion object : Modifier {
override val modifications: List<(UIView) -> Unit> = emptyList()
}
}
internal fun UIView.modify(modifier: Modifier) {
modifier.modifications.forEach { it(this) }
}
internal fun Modifier.then(modification: (UIView) -> Unit): Modifier {
val original = this
return object : Modifier {
override val modifications: List<(UIView) -> Unit> = original.modifications + modification
}
}
actual fun Modifier.padding(top: Int, bottom: Int, start: Int, end: Int): Modifier {
return this.then { view ->
// TODO
}
}
actual fun Modifier.width(value: Int): Modifier {
return this.then { view ->
view.addConstraint(view.widthAnchor.constraintEqualToConstant(value.toDouble()).apply { active = true })
}
}
actual fun Modifier.height(value: Int): Modifier {
return this.then { view ->
view.addConstraint(view.heightAnchor.constraintEqualToConstant(value.toDouble()).apply { active = true })
}
}
actual fun Modifier.fillMaxSize(): Modifier {
return this.then { view ->
val parentView: UIView = view.superview
?: throw IllegalStateException("modifier applied to UIView without parent - $view")
parentView.addConstraints(
listOf(
view.leadingAnchor.constraintEqualToAnchor(parentView.leadingAnchor),
view.trailingAnchor.constraintEqualToAnchor(parentView.trailingAnchor),
view.topAnchor.constraintEqualToAnchor(parentView.topAnchor),
view.bottomAnchor.constraintEqualToAnchor(parentView.bottomAnchor)
).onEach { it.active = true }
)
}
}
actual fun Modifier.fillMaxWidth(): Modifier {
return this
}

76
examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/com/example/compose/common/PlatformKit.kt

@ -0,0 +1,76 @@
/*
* 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.
*/
package com.example.compose.common
import androidx.compose.runtime.Composable
import com.example.compose.common.uikit.ActivityIndicator
import com.example.compose.common.uikit.VStack
import com.example.compose.common.uikit.ZStack
import platform.UIKit.UIView
import platform.UIKit.addConstraints
import platform.UIKit.centerXAnchor
import platform.UIKit.centerYAnchor
import platform.UIKit.superview
import com.example.compose.common.uikit.Button as UIKitButton
import com.example.compose.common.uikit.Text as UIKitText
import com.example.compose.common.uikit.TextField as UIKitTextField
@Composable
actual fun Text(modifier: Modifier, text: String) {
UIKitText(modifier = modifier, text = text)
}
@Composable
actual fun Column(modifier: Modifier, builder: @Composable () -> Unit) {
VStack(modifier = modifier) {
builder()
}
}
@Composable
actual fun Box(modifier: Modifier, content: @Composable BoxScope.() -> Unit) {
ZStack(modifier = modifier) {
val scope = object : BoxScope {
override fun Modifier.align(alignment: Alignment): Modifier {
return this.then { view ->
val parentView: UIView = view.superview
?: throw IllegalStateException("modifier applied to UIView without parent - $view")
parentView.addConstraints(
listOf(
view.centerXAnchor.constraintEqualToAnchor(parentView.centerXAnchor),
view.centerYAnchor.constraintEqualToAnchor(parentView.centerYAnchor)
).onEach { it.active = true }
)
}
}
}
scope.content()
}
}
@Composable
actual fun ProgressBar(modifier: Modifier) {
ActivityIndicator(modifier = modifier)
}
@Composable
actual fun TextField(modifier: Modifier, label: String, value: String, onValueChange: (String) -> Unit) {
UIKitTextField(
modifier = modifier,
value = value,
onValueChanged = onValueChange
)
}
@Composable
actual fun Button(modifier: Modifier, text: String, onClick: () -> Unit) {
UIKitButton(
modifier = modifier,
title = text,
onClick = onClick
)
}

198
examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/com/example/compose/common/uikit/ComposableUIKit.kt

@ -0,0 +1,198 @@
package com.example.compose.common.uikit
import UIViewProtocol
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ComposeNode
import com.example.compose.common.Modifier
import com.example.compose.common.modify
import kotlinx.cinterop.useContents
import platform.CoreGraphics.CGRectMake
import platform.UIKit.UIAction
import platform.UIKit.UIActivityIndicatorView
import platform.UIKit.UIButton
import platform.UIKit.UIColor
import platform.UIKit.UIControlEventTouchUpInside
import platform.UIKit.UIControlStateNormal
import platform.UIKit.UIFont
import platform.UIKit.UILabel
import platform.UIKit.UILayoutConstraintAxisVertical
import platform.UIKit.UIStackView
import platform.UIKit.UIStackViewAlignmentFill
import platform.UIKit.UIStackViewDistributionFillEqually
import platform.UIKit.UITextBorderStyle
import platform.UIKit.UITextField
import platform.UIKit.UITextFieldDelegateProtocol
import platform.UIKit.UIView
import platform.darwin.NSObject
private val zeroFrame = CGRectMake(.0, .0, .0, .0)
@Composable
fun VStack(
modifier: Modifier,
content: @Composable () -> Unit
) {
ComposeNode<UIStackView, UIKitApplier>(
factory = {
object : UIStackView(frame = zeroFrame), UIViewProtocol {
override fun didMoveToSuperview() {
println("UIStackView.didMoveToSuperView")
modify(modifier)
}
}.apply {
axis = UILayoutConstraintAxisVertical
alignment = UIStackViewAlignmentFill
distribution = UIStackViewDistributionFillEqually
}
},
update = {
update(modifier) { this.modify(it) }
},
content = content
)
}
@Composable
fun Text(
modifier: Modifier,
text: String,
textColor: UIColor? = null,
font: UIFont? = null
) {
ComposeNode<UILabel, UIKitApplier>(
factory = {
object : UILabel(frame = zeroFrame), UIViewProtocol {
override fun didMoveToSuperview() {
println("UILabel.didMoveToSuperView")
modify(modifier)
}
}.apply {
this.text = text
textColor?.let { this.textColor = it }
font?.let { this.font = it }
}
},
update = {
update(text) { this.text = it }
update(textColor) {
it?.let { this.textColor = it }
}
update(font) { it?.let { this.font = it } }
update(modifier) { this.modify(it) }
}
)
}
@Composable
fun ZStack(
modifier: Modifier,
content: @Composable () -> Unit
) {
ComposeNode<UIView, UIKitApplier>(
factory = {
object : UIView(frame = zeroFrame), UIViewProtocol {
override fun didMoveToSuperview() {
println("UIView.didMoveToSuperView")
modify(modifier)
}
}
},
update = {
update(modifier) { this.modify(it) }
},
content = content
)
}
@Composable
fun Button(
modifier: Modifier,
title: String,
onClick: () -> Unit
) {
ComposeNode<UIButton, UIKitApplier>(
factory = {
object : UIButton(frame = zeroFrame), UIViewProtocol {
override fun didMoveToSuperview() {
println("UIButton.didMoveToSuperView")
modify(modifier)
}
}.apply {
this.setTitle(title, UIControlStateNormal)
this.addAction(UIAction.actionWithHandler { onClick() }, UIControlEventTouchUpInside)
}
},
update = {
update(title) { this.setTitle(it, UIControlStateNormal) }
update(onClick) { this.addAction(UIAction.actionWithHandler { it() }, UIControlEventTouchUpInside) }
update(modifier) { this.modify(it) }
}
)
}
@Composable
fun TextField(
modifier: Modifier,
value: String,
onValueChanged: (String) -> Unit
) {
ComposeNode<UITextField, UIKitApplier>(
factory = {
object : UITextField(frame = zeroFrame), UIViewProtocol {
override fun didMoveToSuperview() {
println("UITextField.didMoveToSuperView")
modify(modifier)
}
}.apply {
this.borderStyle = UITextBorderStyle.UITextBorderStyleRoundedRect
this.text = value
this.delegate = createTextFieldDelegate(onValueChanged)
}
},
update = {
update(value) { this.text = it }
update(onValueChanged) { this.delegate = createTextFieldDelegate(it) }
update(modifier) { this.modify(it) }
}
)
}
@Composable
fun ActivityIndicator(modifier: Modifier) {
ComposeNode<UIActivityIndicatorView, UIKitApplier>(
factory = {
object : UIActivityIndicatorView(frame = zeroFrame), UIViewProtocol {
override fun didMoveToSuperview() {
println("UIActivityIndicatorView.didMoveToSuperView")
modify(modifier)
}
}.apply {
this.startAnimating()
}
},
update = {}
)
}
private fun createTextFieldDelegate(onValueChanged: (String) -> Unit): UITextFieldDelegateProtocol {
return object : NSObject(), UITextFieldDelegateProtocol {
override fun textField(
textField: UITextField,
shouldChangeCharactersInRange: kotlinx.cinterop.CValue<platform.Foundation.NSRange>,
replacementString: String
): Boolean {
val currentValue = textField.text.orEmpty()
val range: IntRange = shouldChangeCharactersInRange.useContents {
IntRange(this.location.toInt(), (this.location + this.length).toInt() + 1)
}
println("value $currentValue range $range replacement $replacementString")
val newValue = if (range.first == currentValue.length) {
currentValue + replacementString
} else {
currentValue.replaceRange(range, replacementString)
}
onValueChanged(newValue)
return false
}
}
}

59
examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/com/example/compose/common/uikit/UIKitApplier.kt

@ -0,0 +1,59 @@
package com.example.compose.common.uikit
import androidx.compose.runtime.AbstractApplier
import platform.UIKit.UIStackView
import platform.UIKit.UIView
import platform.UIKit.insertSubview
import platform.UIKit.removeFromSuperview
import platform.UIKit.subviews
import platform.UIKit.translatesAutoresizingMaskIntoConstraints
class UIKitApplier(
root: UIView
) : AbstractApplier<UIView>(root) {
override fun insertTopDown(index: Int, instance: UIView) {
println("insertTopDown(index = $index, instance = $instance)")
val subView: UIView = instance
subView.translatesAutoresizingMaskIntoConstraints = false
val current = this.current
if (current is UIStackView) {
current.insertArrangedSubview(subView, index.toULong())
} else {
current.insertSubview(subView, index.toLong())
}
}
override fun insertBottomUp(index: Int, instance: UIView) = Unit
override fun remove(index: Int, count: Int) {
println("remove(index = $index, count = $count)")
val current = current
val subviews = if (current is UIStackView) {
current.arrangedSubviews
} else {
current.subviews
}
subviews.subList(index, index + count)
.filterIsInstance<UIView>()
.forEach {
println("i got $it to remove")
it.removeFromSuperview()
}
}
override fun move(from: Int, to: Int, count: Int) {
println("move(from = $from, to = $to, count = $count)")
}
override fun onClear() {
println("onClear()")
root.subviews
.filterIsInstance<UIView>()
.forEach { it.removeFromSuperview() }
}
}

14
examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/com/example/compose/ios/IosApp.kt

@ -0,0 +1,14 @@
/*
* 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.
*/
package com.example.compose.ios
import androidx.compose.runtime.Composable
import com.example.compose.common.LoginScreen
@Composable
fun IosApp() {
LoginScreen()
}

17
examples/common-platform-uikit/common/src/composeUIKitMain/kotlin/main.kt

@ -0,0 +1,17 @@
import kotlinx.cinterop.autoreleasepool
import kotlinx.cinterop.cstr
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.toCValues
import platform.Foundation.NSStringFromClass
import platform.UIKit.UIApplicationMain
fun main() {
val args = emptyArray<String>()
memScoped {
val argc = args.size + 1
val argv = (arrayOf("skikoApp") + args).map { it.cstr.ptr }.toCValues()
autoreleasepool {
UIApplicationMain(argc, argv, null, NSStringFromClass(ComposeAppDelegate))
}
}
}

4
examples/common-platform-uikit/common/src/composeUIKitSimulatorArm64Main/kotlin/UIViewProtocol.kt

@ -0,0 +1,4 @@
import view.cinterop.UIViewWithOverridesProtocol
actual typealias UIViewProtocol = UIViewWithOverridesProtocol

4
examples/common-platform-uikit/common/src/composeUIKitX64Main/kotlin/UIViewProtocol.kt

@ -0,0 +1,4 @@
import view.cinterop.UIViewWithOverridesProtocol
actual typealias UIViewProtocol = UIViewWithOverridesProtocol

105
examples/common-platform-uikit/common/src/composeUiMain/kotlin/ru/dewish/campus/moderator/common/PlatformKit.kt

@ -0,0 +1,105 @@
package com.example.compose.common
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.unit.dp
import com.example.compose.common.Alignment as CommonAlignment
@Composable
actual fun Text(modifier: Modifier, text: String) {
androidx.compose.material.Text(
modifier = modifier.composeModifier,
text = text
)
}
@Composable
actual fun Column(modifier: Modifier, builder: @Composable () -> Unit) {
androidx.compose.foundation.layout.Column(
modifier = modifier.composeModifier
) {
builder()
}
}
@Composable
actual fun Box(modifier: Modifier, content: @Composable BoxScope.() -> Unit) {
Box(modifier = modifier.composeModifier.fillMaxSize()) {
val scope = object : BoxScope {
override fun Modifier.align(alignment: CommonAlignment): Modifier {
val composeAlignment = when (alignment) {
CommonAlignment.Center -> Alignment.Center
}
return compose { this.align(composeAlignment) }
}
}
scope.content()
}
}
@Composable
actual fun ProgressBar(modifier: Modifier) {
CircularProgressIndicator(modifier = modifier.composeModifier)
}
@Composable
actual fun TextField(modifier: Modifier, label: String, value: String, onValueChange: (String) -> Unit) {
androidx.compose.material.TextField(
modifier = modifier.composeModifier,
value = value,
onValueChange = onValueChange,
label = { Text(text = label) }
)
}
@Composable
actual fun Button(modifier: Modifier, text: String, onClick: () -> Unit) {
androidx.compose.material.Button(
modifier = modifier.composeModifier,
onClick = onClick
) {
androidx.compose.material.Text(text = text)
}
}
actual interface Modifier {
val composeModifier: androidx.compose.ui.Modifier
fun compose(block: androidx.compose.ui.Modifier.() -> androidx.compose.ui.Modifier): Modifier {
val result = composeModifier.block()
return object : Modifier {
override val composeModifier: androidx.compose.ui.Modifier = result
}
}
actual companion object : Modifier {
override val composeModifier: androidx.compose.ui.Modifier = androidx.compose.ui.Modifier
}
}
actual fun Modifier.padding(top: Int, bottom: Int, start: Int, end: Int): Modifier {
return compose { this.padding(start = start.dp, end = end.dp, top = top.dp, bottom = bottom.dp) }
}
actual fun Modifier.width(value: Int): Modifier {
return compose { this.width(value.dp) }
}
actual fun Modifier.height(value: Int): Modifier {
return compose { this.height(value.dp) }
}
actual fun Modifier.fillMaxSize(): Modifier {
return compose { this.fillMaxSize() }
}
actual fun Modifier.fillMaxWidth(): Modifier {
return compose { this.fillMaxWidth() }
}

146
examples/common-platform-uikit/common/src/jsMain/kotlin/com/example/compose/common/PlatformKit.kt

@ -0,0 +1,146 @@
/*
* 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.
*/
package com.example.compose.common
import androidx.compose.runtime.Composable
import org.jetbrains.compose.web.attributes.AttrsBuilder
import org.jetbrains.compose.web.attributes.InputType
import org.jetbrains.compose.web.attributes.placeholder
import org.jetbrains.compose.web.css.DisplayStyle
import org.jetbrains.compose.web.css.FlexDirection
import org.jetbrains.compose.web.css.StyleBuilder
import org.jetbrains.compose.web.css.alignSelf
import org.jetbrains.compose.web.css.display
import org.jetbrains.compose.web.css.flexDirection
import org.jetbrains.compose.web.css.height
import org.jetbrains.compose.web.css.paddingBottom
import org.jetbrains.compose.web.css.paddingLeft
import org.jetbrains.compose.web.css.paddingRight
import org.jetbrains.compose.web.css.paddingTop
import org.jetbrains.compose.web.css.percent
import org.jetbrains.compose.web.css.px
import org.jetbrains.compose.web.css.width
import org.jetbrains.compose.web.dom.Button
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.dom.Input
import org.jetbrains.compose.web.dom.Progress
import org.w3c.dom.HTMLElement
@Composable
actual fun Text(modifier: Modifier, text: String) {
org.jetbrains.compose.web.dom.Text(value = text)
}
@Composable
actual fun Column(modifier: Modifier, builder: @Composable () -> Unit) {
Div(attrs = {
modifier.applyAttrs(this)
style {
display(DisplayStyle.Flex)
flexDirection(FlexDirection.Column)
}
}) {
builder()
}
}
@Composable
actual fun Box(modifier: Modifier, content: @Composable BoxScope.() -> Unit) {
Div(attrs = { modifier.applyAttrs(this) }) {
val boxScope = object : BoxScope {
override fun Modifier.align(alignment: Alignment): Modifier {
return style {
when (alignment) {
Alignment.Center -> alignSelf("center")
}
}
}
}
boxScope.content()
}
}
@Composable
actual fun ProgressBar(modifier: Modifier) {
Progress(attrs = { modifier.applyAttrs(this) })
}
@Composable
actual fun TextField(modifier: Modifier, label: String, value: String, onValueChange: (String) -> Unit) {
Input(InputType.Text) {
this.placeholder(label)
this.value(value)
this.onInput { onValueChange(it.value) }
modifier.applyAttrs(this)
}
}
@Composable
actual fun Button(modifier: Modifier, text: String, onClick: () -> Unit) {
Button(
attrs = {
modifier.applyAttrs(this)
this.onClick { onClick() }
}
) {
org.jetbrains.compose.web.dom.Text(value = text)
}
}
actual interface Modifier {
val attrs: List<AttrsBuilder<out HTMLElement>.() -> Unit>
fun applyAttrs(builder: AttrsBuilder<out HTMLElement>) {
attrs.forEach { it(builder) }
}
fun builder(block: AttrsBuilder<out HTMLElement>.() -> Unit): Modifier {
val newAttrs = attrs + block
return object : Modifier {
override val attrs: List<AttrsBuilder<out HTMLElement>.() -> Unit> = newAttrs
}
}
fun style(block: StyleBuilder.() -> Unit): Modifier {
return builder { this.style(block) }
}
actual companion object : Modifier {
override val attrs: List<AttrsBuilder<out HTMLElement>.() -> Unit> = emptyList()
}
}
actual fun Modifier.padding(top: Int, bottom: Int, start: Int, end: Int): Modifier {
return style {
paddingTop(top.px)
paddingBottom(bottom.px)
paddingLeft(start.px)
paddingRight(end.px)
}
}
actual fun Modifier.width(value: Int): Modifier {
return style {
width(value.px)
}
}
actual fun Modifier.height(value: Int): Modifier {
return style { this.height(value.px) }
}
actual fun Modifier.fillMaxSize(): Modifier {
return style {
width(100.percent)
height(100.percent)
}
}
actual fun Modifier.fillMaxWidth(): Modifier {
return style {
width(100.percent)
}
}

13
examples/common-platform-uikit/common/src/jvmMain/kotlin/com/example/compose/common/DesktopApp.kt

@ -0,0 +1,13 @@
/*
* 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.
*/
package com.example.compose.common
import androidx.compose.runtime.Composable
@Composable
fun DesktopApp() {
LoginScreen()
}

29
examples/common-platform-uikit/desktop/build.gradle.kts

@ -0,0 +1,29 @@
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm")
id("org.jetbrains.compose")
}
version = "1.0"
dependencies {
implementation(compose.desktop.currentOs)
implementation(project(":common"))
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "11"
}
compose.desktop {
application {
mainClass = "com.example.compose.jvm.MainKt"
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "PlatformUIKit"
packageVersion = "1.0.0"
}
}
}

21
examples/common-platform-uikit/desktop/src/main/kotlin/com/example/compose/jvm/Main.kt

@ -0,0 +1,21 @@
/*
* 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.
*/
package com.example.compose.jvm
import androidx.compose.material.MaterialTheme
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import com.example.compose.common.DesktopApp
fun main() {
application {
Window(onCloseRequest = ::exitApplication) {
MaterialTheme {
DesktopApp()
}
}
}
}

6
examples/common-platform-uikit/gradle.properties

@ -0,0 +1,6 @@
kotlin.code.style=official
android.useAndroidX=true
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
kotlin.mpp.stability.nowarn=true
kotlin.native.cacheKind=none

BIN
examples/common-platform-uikit/gradle/wrapper/gradle-wrapper.jar vendored

Binary file not shown.

5
examples/common-platform-uikit/gradle/wrapper/gradle-wrapper.properties vendored

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

234
examples/common-platform-uikit/gradlew vendored

@ -0,0 +1,234 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

89
examples/common-platform-uikit/gradlew.bat vendored

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

344
examples/common-platform-uikit/ios/iosApp.xcodeproj/project.pbxproj

@ -0,0 +1,344 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 55;
objects = {
/* Begin PBXBuildFile section */
2230C07C279C2BF900FE44C3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2230C07B279C2BF900FE44C3 /* Assets.xcassets */; };
2230C07F279C2BF900FE44C3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2230C07D279C2BF900FE44C3 /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
2230C070279C2BF800FE44C3 /* iosApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iosApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
2230C07B279C2BF900FE44C3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
2230C07E279C2BF900FE44C3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
2230C080279C2BF900FE44C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
228F9F9C2789CB1000C5A41A /* common.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = common.xcframework; path = ../common/build/XCFrameworks/release/common.xcframework; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXGroup section */
2230C071279C2BF800FE44C3 /* iosApp */ = {
isa = PBXGroup;
children = (
2230C07B279C2BF900FE44C3 /* Assets.xcassets */,
2230C07D279C2BF900FE44C3 /* LaunchScreen.storyboard */,
2230C080279C2BF900FE44C3 /* Info.plist */,
);
path = iosApp;
sourceTree = "<group>";
};
228F9F822789C14A00C5A41A = {
isa = PBXGroup;
children = (
228F9F9C2789CB1000C5A41A /* common.xcframework */,
2230C071279C2BF800FE44C3 /* iosApp */,
228F9F8C2789C14A00C5A41A /* Products */,
);
sourceTree = "<group>";
};
228F9F8C2789C14A00C5A41A /* Products */ = {
isa = PBXGroup;
children = (
2230C070279C2BF800FE44C3 /* iosApp.app */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
2230C06F279C2BF800FE44C3 /* iosApp */ = {
isa = PBXNativeTarget;
buildConfigurationList = 2230C081279C2BF900FE44C3 /* Build configuration list for PBXNativeTarget "iosApp" */;
buildPhases = (
2230C084279C2C5200FE44C3 /* Use Kotlin executable */,
2230C06E279C2BF800FE44C3 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = iosApp;
productName = iosApp;
productReference = 2230C070279C2BF800FE44C3 /* iosApp.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
228F9F832789C14A00C5A41A /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1310;
LastUpgradeCheck = 1310;
TargetAttributes = {
2230C06F279C2BF800FE44C3 = {
CreatedOnToolsVersion = 13.1;
};
};
};
buildConfigurationList = 228F9F862789C14A00C5A41A /* Build configuration list for PBXProject "iosApp" */;
compatibilityVersion = "Xcode 13.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 228F9F822789C14A00C5A41A;
productRefGroup = 228F9F8C2789C14A00C5A41A /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
2230C06F279C2BF800FE44C3 /* iosApp */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
2230C06E279C2BF800FE44C3 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
2230C07F279C2BF900FE44C3 /* LaunchScreen.storyboard in Resources */,
2230C07C279C2BF900FE44C3 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
2230C084279C2C5200FE44C3 /* Use Kotlin executable */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Use Kotlin executable";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\ncd ..\n\n./gradlew linkDebugExecutableComposeUIKitArm64\n\ncp common/build/bin/composeUIKitArm64/debugExecutable/common.kexe \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXVariantGroup section */
2230C07D279C2BF900FE44C3 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
2230C07E279C2BF900FE44C3 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
2230C082279C2BF900FE44C3 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = JHA8M3FGT2;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = iosApp/Info.plist;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.ios.iosApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
2230C083279C2BF900FE44C3 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = JHA8M3FGT2;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = iosApp/Info.plist;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.ios.iosApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
228F9F972789C14B00C5A41A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
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;
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 = 15.0;
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;
};
228F9F982789C14B00C5A41A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
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 = 15.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
2230C081279C2BF900FE44C3 /* Build configuration list for PBXNativeTarget "iosApp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
2230C082279C2BF900FE44C3 /* Debug */,
2230C083279C2BF900FE44C3 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
228F9F862789C14A00C5A41A /* Build configuration list for PBXProject "iosApp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
228F9F972789C14B00C5A41A /* Debug */,
228F9F982789C14B00C5A41A /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 228F9F832789C14A00C5A41A /* Project object */;
}

7
examples/common-platform-uikit/ios/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata generated

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

8
examples/common-platform-uikit/ios/iosApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

BIN
examples/common-platform-uikit/ios/iosApp.xcodeproj/project.xcworkspace/xcuserdata/amikhailov.xcuserdatad/UserInterfaceState.xcuserstate generated

Binary file not shown.

14
examples/common-platform-uikit/ios/iosApp.xcodeproj/xcuserdata/amikhailov.xcuserdatad/xcschemes/xcschememanagement.plist

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>iosApp.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>3</integer>
</dict>
</dict>
</dict>
</plist>

11
examples/common-platform-uikit/ios/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json

@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

98
examples/common-platform-uikit/ios/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json

@ -0,0 +1,98 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

6
examples/common-platform-uikit/ios/iosApp/Assets.xcassets/Contents.json

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

25
examples/common-platform-uikit/ios/iosApp/Base.lproj/LaunchScreen.storyboard

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

5
examples/common-platform-uikit/ios/iosApp/Info.plist

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>

29
examples/common-platform-uikit/settings.gradle.kts

@ -0,0 +1,29 @@
rootProject.name = "common-platform-uikit"
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
mavenLocal()
}
resolutionStrategy {
eachPlugin {
if (requested.id.namespace == "com.android") useModule("com.android.tools.build:gradle:7.0.3")
}
}
}
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
mavenLocal()
}
}
include(":android")
include(":desktop")
include(":web")
include(":common")

19
examples/common-platform-uikit/web/build.gradle.kts

@ -0,0 +1,19 @@
plugins {
kotlin("multiplatform")
id("org.jetbrains.compose")
}
kotlin {
js(IR) {
browser()
binaries.executable()
}
sourceSets {
val jsMain by getting {
dependencies {
implementation(project(":common"))
}
}
}
}

8
examples/common-platform-uikit/web/src/jsMain/kotlin/Main.kt

@ -0,0 +1,8 @@
import com.example.compose.common.LoginScreen
import org.jetbrains.compose.web.renderComposable
fun main() {
renderComposable(rootElementId = "root") {
LoginScreen()
}
}

11
examples/common-platform-uikit/web/src/jsMain/resources/index.html

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Sample</title>
</head>
<body>
<div id="root"></div>
<script src="web.js"></script>
</body>
</html>
Loading…
Cancel
Save