diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b603bdf --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ + +*.iml +.gradle +.idea +.DS_Store +build +*/build +captures +.externalNativeBuild +.cxx +local.properties +xcuserdata/ +Pods/ +*.jks +*yarn.lock diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..86df443 --- /dev/null +++ b/README.MD @@ -0,0 +1,27 @@ +# Compose Multiplatform Application + +## Before running! + - check your system with [KDoctor](https://github.com/Kotlin/kdoctor) + - install JDK 8 on your machine + - add `local.properties` file to the project root and set a path to Android SDK there + - run `./gradlew podInstall` in the project root + +### Android +To run the application on android device/emulator: + - open project in Android Studio and run imported android run configuration + +To build the application bundle: + - run `./gradlew :composeApp:assembleDebug` + - find `.apk` file in `composeApp/build/outputs/apk/debug/composeApp-debug.apk` + +### Desktop +Run the desktop application: `./gradlew :composeApp:run` + +### iOS +To run the application on iPhone device/simulator: + - Open `iosApp/iosApp.xcworkspace` in Xcode and run standard configuration + - Or use [Kotlin Multiplatform Mobile plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile) for Android Studio + +### Browser +Run the browser application: `./gradlew :composeApp:jsBrowserDevelopmentRun` + diff --git a/adapt/adapt.podspec b/adapt/adapt.podspec new file mode 100644 index 0000000..96ca9e9 --- /dev/null +++ b/adapt/adapt.podspec @@ -0,0 +1,39 @@ +Pod::Spec.new do |spec| + spec.name = 'adapt' + spec.version = '1.0.0' + spec.homepage = 'empty' + spec.source = { :http=> ''} + spec.authors = '' + spec.license = '' + spec.summary = 'Adapt UI library' + spec.vendored_frameworks = 'build/cocoapods/framework/adapt.framework' + spec.libraries = 'c++' + spec.ios.deployment_target = '11.0' + + + spec.pod_target_xcconfig = { + 'KOTLIN_PROJECT_PATH' => ':adapt', + 'PRODUCT_MODULE_NAME' => 'adapt', + } + + spec.script_phases = [ + { + :name => 'Build adapt', + :execution_position => :before_compile, + :shell_path => '/bin/sh', + :script => <<-SCRIPT + if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then + echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\"" + exit 0 + fi + set -ev + REPO_ROOT="$PODS_TARGET_SRCROOT" + "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework \ + -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME \ + -Pkotlin.native.cocoapods.archs="$ARCHS" \ + -Pkotlin.native.cocoapods.configuration="$CONFIGURATION" + SCRIPT + } + ] + spec.resources = ['build/compose/ios/adapt/compose-resources'] +end \ No newline at end of file diff --git a/adapt/build.gradle.kts b/adapt/build.gradle.kts new file mode 100644 index 0000000..effd1a3 --- /dev/null +++ b/adapt/build.gradle.kts @@ -0,0 +1,119 @@ +import org.jetbrains.compose.desktop.application.dsl.TargetFormat + +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.cocoapods) + alias(libs.plugins.compose) + alias(libs.plugins.multiplatform) +} + +@OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class) +kotlin { + targetHierarchy.default() + androidTarget { + compilations.all { + kotlinOptions { + jvmTarget = "1.8" + } + } + } + + jvm("desktop") + + js { + browser() + binaries.executable() + } + + iosX64() + iosArm64() + iosSimulatorArm64() + + cocoapods { + version = "1.0.0" + summary = "Adapt UI library" + homepage = "empty" + ios.deploymentTarget = "11.0" + framework { + baseName = "adapt" + isStatic = true + } + } + + sourceSets { + all { + languageSettings { + optIn("org.jetbrains.compose.resources.ExperimentalResourceApi") + } + } + val commonMain by getting { + dependencies { + @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) + implementation(compose.components.resources) + implementation(compose.foundation) + implementation(compose.material3) + implementation(compose.runtime) + implementation(compose.ui) + } + } + + val commonTest by getting { + dependencies { + implementation(kotlin("test")) + } + } + + val androidMain by getting { + dependencies { + implementation(compose.uiTooling) + implementation(compose.preview) + } + } + } +} + +// TODO: Remove this when JetBrains Compose supports Kotlin 1.9.10 +compose { + kotlinCompilerPlugin.set(dependencies.compiler.forKotlin("1.9.0")) + kotlinCompilerPluginArgs.add("suppressKotlinVersionCompatibilityCheck=1.9.10") +} + +android { + namespace = "design.adapt" + compileSdk = 34 + + defaultConfig { + minSdk = 21 + } + sourceSets["main"].apply { + manifest.srcFile("src/androidMain/AndroidManifest.xml") + res.srcDirs("src/androidMain/resources") + resources.srcDirs("src/commonMain/resources") + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + composeOptions { + kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get() + } + buildFeatures { + compose = true + } +} + +compose.desktop { + application { + mainClass = "MainKt" + + nativeDistributions { + targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) + packageName = "design.adapt.desktopApp" + packageVersion = "1.0.0" + } + } +} + +compose.experimental { + web.application {} +} diff --git a/adapt/src/androidMain/kotlin/design/adapt/previews/AdaptButtonPreview.kt b/adapt/src/androidMain/kotlin/design/adapt/previews/AdaptButtonPreview.kt new file mode 100644 index 0000000..991a258 --- /dev/null +++ b/adapt/src/androidMain/kotlin/design/adapt/previews/AdaptButtonPreview.kt @@ -0,0 +1,12 @@ +package design.adapt.previews + +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import design.adapt.AdaptButton + +@Preview +@Composable +fun AdaptButtonPreview() { + AdaptButton { + } +} diff --git a/adapt/src/commonMain/kotlin/design/adapt/AdaptButton.kt b/adapt/src/commonMain/kotlin/design/adapt/AdaptButton.kt new file mode 100644 index 0000000..c9e6a45 --- /dev/null +++ b/adapt/src/commonMain/kotlin/design/adapt/AdaptButton.kt @@ -0,0 +1,71 @@ +package design.adapt + +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.spring +import androidx.compose.foundation.Indication +import androidx.compose.foundation.IndicationInstance +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.InteractionSource +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.collectIsPressedAsState +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import androidx.compose.runtime.State +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.drawscope.ContentDrawScope +import androidx.compose.ui.graphics.drawscope.scale +import androidx.compose.ui.unit.dp + +@Composable +fun AdaptButton( + modifier: Modifier = Modifier, + onClick: () -> Unit, +) { + Text( + modifier = modifier + .clickable( + onClick = onClick, + interactionSource = remember { MutableInteractionSource() }, + indication = remember { ScaleIndication() } + ) + .clip(RoundedCornerShape(16.dp)) + .background(MaterialTheme.colorScheme.primaryContainer) + .padding(16.dp), + text = "Adapt Button" + ) +} + +@Stable +class ScaleIndication : Indication { + @Composable + override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance { + val isPressed by interactionSource.collectIsPressedAsState() + val animatedScale = animateFloatAsState( + targetValue = if (isPressed) 0.93f else 1f, + animationSpec = spring( + dampingRatio = Spring.DampingRatioMediumBouncy, + stiffness = Spring.StiffnessMediumLow, + ) + ) + return remember { + ScaleIndicationInstance(scale = animatedScale) + } + } + + class ScaleIndicationInstance(private val scale: State) : IndicationInstance { + override fun ContentDrawScope.drawIndication() { + scale(scale = scale.value) { + this@drawIndication.drawContent() + } + } + } +} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..594de0b --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,8 @@ +plugins { + alias(libs.plugins.android.application).apply(false) + alias(libs.plugins.android.library).apply(false) + alias(libs.plugins.cocoapods).apply(false) + alias(libs.plugins.compose).apply(false) + alias(libs.plugins.kotlin.android).apply(false) + alias(libs.plugins.multiplatform).apply(false) +} diff --git a/gradle.bat b/gradle.bat new file mode 100644 index 0000000..e34f491 --- /dev/null +++ b/gradle.bat @@ -0,0 +1,90 @@ + +@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 diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..4c19543 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,14 @@ +#Gradle +org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M" +#Kotlin +kotlin.code.style=official +kotlin.js.compiler=ir +#MPP +kotlin.mpp.enableCInteropCommonization=true +kotlin.mpp.androidSourceSetLayoutVersion=2 +#Compose +org.jetbrains.compose.experimental.uikit.enabled=true +org.jetbrains.compose.experimental.jscanvas.enabled=true +#Android +android.useAndroidX=true +android.nonTransitiveRClass=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..43285c0 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,20 @@ +[versions] +agp = "8.1.1" +androidx-activityCompose = "1.7.2" +androidx-appcompat = "1.6.1" +compose = "1.5.0" +# This needs to be at least 1.5.2 (reason: https://github.com/JetBrains/compose-multiplatform/issues/3531#issuecomment-1690831975) +compose-compiler = "1.5.2" +kotlin = "1.9.10" + +[libraries] +androidx-activityCompose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" } +androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } +android-library = { id = "com.android.library", version.ref = "agp" } +cocoapods = { id = "org.jetbrains.kotlin.native.cocoapods", version.ref = "kotlin" } +compose = { id = "org.jetbrains.compose", version.ref = "compose" } +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..7454180 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..822b841 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ + +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..43bed5d --- /dev/null +++ b/gradlew @@ -0,0 +1,186 @@ + +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or 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 UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: ${'$'}0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)${'$'}'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$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 "${'$'}*" +} + +die () { + echo + echo "${'$'}*" + echo + exit 1 +} + +# 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" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/sample/composeApp/build.gradle.kts b/sample/composeApp/build.gradle.kts new file mode 100644 index 0000000..60d4c5a --- /dev/null +++ b/sample/composeApp/build.gradle.kts @@ -0,0 +1,139 @@ +import org.jetbrains.compose.desktop.application.dsl.TargetFormat + +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.cocoapods) + alias(libs.plugins.compose) + alias(libs.plugins.multiplatform) +} + +@OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class) +kotlin { + targetHierarchy.default() + androidTarget { + compilations.all { + kotlinOptions { + jvmTarget = "1.8" + } + } + } + + jvm("desktop") + + js { + browser() + binaries.executable() + } + + iosX64() + iosArm64() + iosSimulatorArm64() + + cocoapods { + version = "1.0.0" + summary = "Compose application framework" + homepage = "empty" + ios.deploymentTarget = "11.0" + podfile = project.file("../iosApp/Podfile") + framework { + baseName = "ComposeApp" + isStatic = true + } + } + + sourceSets { + all { + languageSettings { + optIn("org.jetbrains.compose.resources.ExperimentalResourceApi") + } + } + val commonMain by getting { + dependencies { + @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) + implementation(compose.components.resources) + implementation(compose.material3) + implementation(compose.runtime) + implementation(project(":adapt")) + } + } + + val commonTest by getting { + dependencies { + implementation(kotlin("test")) + } + } + + val androidMain by getting { + dependencies { + implementation(libs.androidx.activityCompose) + implementation(libs.androidx.appcompat) + implementation(compose.uiTooling) + implementation(compose.preview) + } + } + + val desktopMain by getting { + dependencies { + implementation(compose.desktop.common) + implementation(compose.desktop.currentOs) + } + } + + val jsMain by getting { + dependencies { + implementation(compose.html.core) + } + } + + val iosMain by getting { + dependencies { + } + } + + } +} + +// TODO: Remove this when JetBrains Compose supports Kotlin 1.9.10 +compose { + kotlinCompilerPlugin.set(dependencies.compiler.forKotlin("1.9.0")) + kotlinCompilerPluginArgs.add("suppressKotlinVersionCompatibilityCheck=1.9.10") +} + +android { + namespace = "design.adapt" + compileSdk = 34 + + defaultConfig { + minSdk = 21 + targetSdk = 34 + + applicationId = "design.adapt.androidApp" + versionCode = 1 + versionName = "1.0.0" + } + sourceSets["main"].apply { + manifest.srcFile("src/androidMain/AndroidManifest.xml") + res.srcDirs("src/androidMain/resources") + resources.srcDirs("src/commonMain/resources") + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } +} + +compose.desktop { + application { + mainClass = "MainKt" + + nativeDistributions { + targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) + packageName = "design.adapt.desktopApp" + packageVersion = "1.0.0" + } + } +} + +compose.experimental { + web.application {} +} diff --git a/sample/composeApp/composeApp.podspec b/sample/composeApp/composeApp.podspec new file mode 100644 index 0000000..8f055a1 --- /dev/null +++ b/sample/composeApp/composeApp.podspec @@ -0,0 +1,39 @@ +Pod::Spec.new do |spec| + spec.name = 'composeApp' + spec.version = '1.0.0' + spec.homepage = 'empty' + spec.source = { :http=> ''} + spec.authors = '' + spec.license = '' + spec.summary = 'Compose application framework' + spec.vendored_frameworks = 'build/cocoapods/framework/ComposeApp.framework' + spec.libraries = 'c++' + spec.ios.deployment_target = '11.0' + + + spec.pod_target_xcconfig = { + 'KOTLIN_PROJECT_PATH' => ':sample:composeApp', + 'PRODUCT_MODULE_NAME' => 'ComposeApp', + } + + spec.script_phases = [ + { + :name => 'Build composeApp', + :execution_position => :before_compile, + :shell_path => '/bin/sh', + :script => <<-SCRIPT + if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then + echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\"" + exit 0 + fi + set -ev + REPO_ROOT="$PODS_TARGET_SRCROOT" + "$REPO_ROOT/../../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework \ + -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME \ + -Pkotlin.native.cocoapods.archs="$ARCHS" \ + -Pkotlin.native.cocoapods.configuration="$CONFIGURATION" + SCRIPT + } + ] + spec.resources = ['build/compose/ios/ComposeApp/compose-resources'] +end \ No newline at end of file diff --git a/sample/composeApp/src/androidMain/AndroidManifest.xml b/sample/composeApp/src/androidMain/AndroidManifest.xml new file mode 100644 index 0000000..7c50f05 --- /dev/null +++ b/sample/composeApp/src/androidMain/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/sample/composeApp/src/androidMain/kotlin/design/adapt/App.android.kt b/sample/composeApp/src/androidMain/kotlin/design/adapt/App.android.kt new file mode 100644 index 0000000..4744880 --- /dev/null +++ b/sample/composeApp/src/androidMain/kotlin/design/adapt/App.android.kt @@ -0,0 +1,36 @@ +package design.adapt + +import android.app.Application +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent + +class AndroidApp : Application() { + companion object { + lateinit var INSTANCE: AndroidApp + } + + override fun onCreate() { + super.onCreate() + INSTANCE = this + } +} + +class AppActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { App() } + } +} + +internal actual fun openUrl(url: String?) { + val uri = url?.let { Uri.parse(it) } ?: return + val intent = Intent().apply { + action = Intent.ACTION_VIEW + data = uri + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + AndroidApp.INSTANCE.startActivity(intent) +} \ No newline at end of file diff --git a/sample/composeApp/src/commonMain/kotlin/design/adapt/App.kt b/sample/composeApp/src/commonMain/kotlin/design/adapt/App.kt new file mode 100644 index 0000000..ef184a2 --- /dev/null +++ b/sample/composeApp/src/commonMain/kotlin/design/adapt/App.kt @@ -0,0 +1,19 @@ +package design.adapt + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import design.adapt.theme.AppTheme + +@Composable +internal fun App() = AppTheme { + Column { + AdaptButton(modifier = Modifier.padding(32.dp)) { + println("Welcome to Adapt!") + } + } +} + +internal expect fun openUrl(url: String?) diff --git a/sample/composeApp/src/commonMain/kotlin/design/adapt/theme/Color.kt b/sample/composeApp/src/commonMain/kotlin/design/adapt/theme/Color.kt new file mode 100644 index 0000000..3c76b98 --- /dev/null +++ b/sample/composeApp/src/commonMain/kotlin/design/adapt/theme/Color.kt @@ -0,0 +1,71 @@ +package design.adapt.theme + +import androidx.compose.ui.graphics.Color + +//generated by https://m3.material.io/theme-builder#/custom +//Color palette was taken here: https://colorhunt.co/palettes/popular + +internal val md_theme_light_primary = Color(0xFF00687A) +internal val md_theme_light_onPrimary = Color(0xFFFFFFFF) +internal val md_theme_light_primaryContainer = Color(0xFFABEDFF) +internal val md_theme_light_onPrimaryContainer = Color(0xFF001F26) +internal val md_theme_light_secondary = Color(0xFF00696E) +internal val md_theme_light_onSecondary = Color(0xFFFFFFFF) +internal val md_theme_light_secondaryContainer = Color(0xFF6FF6FE) +internal val md_theme_light_onSecondaryContainer = Color(0xFF002022) +internal val md_theme_light_tertiary = Color(0xFF904D00) +internal val md_theme_light_onTertiary = Color(0xFFFFFFFF) +internal val md_theme_light_tertiaryContainer = Color(0xFFFFDCC2) +internal val md_theme_light_onTertiaryContainer = Color(0xFF2E1500) +internal val md_theme_light_error = Color(0xFFBA1A1A) +internal val md_theme_light_errorContainer = Color(0xFFFFDAD6) +internal val md_theme_light_onError = Color(0xFFFFFFFF) +internal val md_theme_light_onErrorContainer = Color(0xFF410002) +internal val md_theme_light_background = Color(0xFFFFFBFF) +internal val md_theme_light_onBackground = Color(0xFF221B00) +internal val md_theme_light_surface = Color(0xFFFFFBFF) +internal val md_theme_light_onSurface = Color(0xFF221B00) +internal val md_theme_light_surfaceVariant = Color(0xFFDBE4E7) +internal val md_theme_light_onSurfaceVariant = Color(0xFF3F484B) +internal val md_theme_light_outline = Color(0xFF70797B) +internal val md_theme_light_inverseOnSurface = Color(0xFFFFF0C0) +internal val md_theme_light_inverseSurface = Color(0xFF3A3000) +internal val md_theme_light_inversePrimary = Color(0xFF55D6F4) +internal val md_theme_light_shadow = Color(0xFF000000) +internal val md_theme_light_surfaceTint = Color(0xFF00687A) +internal val md_theme_light_outlineVariant = Color(0xFFBFC8CB) +internal val md_theme_light_scrim = Color(0xFF000000) + +internal val md_theme_dark_primary = Color(0xFF55D6F4) +internal val md_theme_dark_onPrimary = Color(0xFF003640) +internal val md_theme_dark_primaryContainer = Color(0xFF004E5C) +internal val md_theme_dark_onPrimaryContainer = Color(0xFFABEDFF) +internal val md_theme_dark_secondary = Color(0xFF4CD9E2) +internal val md_theme_dark_onSecondary = Color(0xFF00373A) +internal val md_theme_dark_secondaryContainer = Color(0xFF004F53) +internal val md_theme_dark_onSecondaryContainer = Color(0xFF6FF6FE) +internal val md_theme_dark_tertiary = Color(0xFFFFB77C) +internal val md_theme_dark_onTertiary = Color(0xFF4D2700) +internal val md_theme_dark_tertiaryContainer = Color(0xFF6D3900) +internal val md_theme_dark_onTertiaryContainer = Color(0xFFFFDCC2) +internal val md_theme_dark_error = Color(0xFFFFB4AB) +internal val md_theme_dark_errorContainer = Color(0xFF93000A) +internal val md_theme_dark_onError = Color(0xFF690005) +internal val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) +internal val md_theme_dark_background = Color(0xFF221B00) +internal val md_theme_dark_onBackground = Color(0xFFFFE264) +internal val md_theme_dark_surface = Color(0xFF221B00) +internal val md_theme_dark_onSurface = Color(0xFFFFE264) +internal val md_theme_dark_surfaceVariant = Color(0xFF3F484B) +internal val md_theme_dark_onSurfaceVariant = Color(0xFFBFC8CB) +internal val md_theme_dark_outline = Color(0xFF899295) +internal val md_theme_dark_inverseOnSurface = Color(0xFF221B00) +internal val md_theme_dark_inverseSurface = Color(0xFFFFE264) +internal val md_theme_dark_inversePrimary = Color(0xFF00687A) +internal val md_theme_dark_shadow = Color(0xFF000000) +internal val md_theme_dark_surfaceTint = Color(0xFF55D6F4) +internal val md_theme_dark_outlineVariant = Color(0xFF3F484B) +internal val md_theme_dark_scrim = Color(0xFF000000) + + +internal val seed = Color(0xFF2C3639) diff --git a/sample/composeApp/src/commonMain/kotlin/design/adapt/theme/Theme.kt b/sample/composeApp/src/commonMain/kotlin/design/adapt/theme/Theme.kt new file mode 100644 index 0000000..0f5ccf8 --- /dev/null +++ b/sample/composeApp/src/commonMain/kotlin/design/adapt/theme/Theme.kt @@ -0,0 +1,122 @@ +package design.adapt.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Shapes +import androidx.compose.material3.Surface +import androidx.compose.material3.Typography +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +private val LightColorScheme = lightColorScheme( + primary = md_theme_light_primary, + onPrimary = md_theme_light_onPrimary, + primaryContainer = md_theme_light_primaryContainer, + onPrimaryContainer = md_theme_light_onPrimaryContainer, + secondary = md_theme_light_secondary, + onSecondary = md_theme_light_onSecondary, + secondaryContainer = md_theme_light_secondaryContainer, + onSecondaryContainer = md_theme_light_onSecondaryContainer, + tertiary = md_theme_light_tertiary, + onTertiary = md_theme_light_onTertiary, + tertiaryContainer = md_theme_light_tertiaryContainer, + onTertiaryContainer = md_theme_light_onTertiaryContainer, + error = md_theme_light_error, + errorContainer = md_theme_light_errorContainer, + onError = md_theme_light_onError, + onErrorContainer = md_theme_light_onErrorContainer, + background = md_theme_light_background, + onBackground = md_theme_light_onBackground, + surface = md_theme_light_surface, + onSurface = md_theme_light_onSurface, + surfaceVariant = md_theme_light_surfaceVariant, + onSurfaceVariant = md_theme_light_onSurfaceVariant, + outline = md_theme_light_outline, + inverseOnSurface = md_theme_light_inverseOnSurface, + inverseSurface = md_theme_light_inverseSurface, + inversePrimary = md_theme_light_inversePrimary, + surfaceTint = md_theme_light_surfaceTint, + outlineVariant = md_theme_light_outlineVariant, + scrim = md_theme_light_scrim, +) + +private val DarkColorScheme = darkColorScheme( + primary = md_theme_dark_primary, + onPrimary = md_theme_dark_onPrimary, + primaryContainer = md_theme_dark_primaryContainer, + onPrimaryContainer = md_theme_dark_onPrimaryContainer, + secondary = md_theme_dark_secondary, + onSecondary = md_theme_dark_onSecondary, + secondaryContainer = md_theme_dark_secondaryContainer, + onSecondaryContainer = md_theme_dark_onSecondaryContainer, + tertiary = md_theme_dark_tertiary, + onTertiary = md_theme_dark_onTertiary, + tertiaryContainer = md_theme_dark_tertiaryContainer, + onTertiaryContainer = md_theme_dark_onTertiaryContainer, + error = md_theme_dark_error, + errorContainer = md_theme_dark_errorContainer, + onError = md_theme_dark_onError, + onErrorContainer = md_theme_dark_onErrorContainer, + background = md_theme_dark_background, + onBackground = md_theme_dark_onBackground, + surface = md_theme_dark_surface, + onSurface = md_theme_dark_onSurface, + surfaceVariant = md_theme_dark_surfaceVariant, + onSurfaceVariant = md_theme_dark_onSurfaceVariant, + outline = md_theme_dark_outline, + inverseOnSurface = md_theme_dark_inverseOnSurface, + inverseSurface = md_theme_dark_inverseSurface, + inversePrimary = md_theme_dark_inversePrimary, + surfaceTint = md_theme_dark_surfaceTint, + outlineVariant = md_theme_dark_outlineVariant, + scrim = md_theme_dark_scrim, +) + +private val AppShapes = Shapes( + extraSmall = RoundedCornerShape(2.dp), + small = RoundedCornerShape(4.dp), + medium = RoundedCornerShape(8.dp), + large = RoundedCornerShape(16.dp), + extraLarge = RoundedCornerShape(32.dp) +) + +private val AppTypography = Typography( + bodyMedium = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 16.sp + ) +) + +@Composable +internal fun AppTheme( + useDarkTheme: Boolean = isSystemInDarkTheme(), + content: @Composable() () -> Unit +) { + val colors = if (!useDarkTheme) { + LightColorScheme + } else { + DarkColorScheme + } + + MaterialTheme( + colorScheme = colors, + typography = AppTypography, + shapes = AppShapes, + content = { + Surface( + modifier = Modifier.fillMaxSize(), + content = content + ) + } + ) +} diff --git a/sample/composeApp/src/desktopMain/kotlin/design/adapt/App.jvm.kt b/sample/composeApp/src/desktopMain/kotlin/design/adapt/App.jvm.kt new file mode 100644 index 0000000..cc5b7fb --- /dev/null +++ b/sample/composeApp/src/desktopMain/kotlin/design/adapt/App.jvm.kt @@ -0,0 +1,9 @@ +package design.adapt + +import java.awt.Desktop +import java.net.URI + +internal actual fun openUrl(url: String?) { + val uri = url?.let { URI.create(it) } ?: return + Desktop.getDesktop().browse(uri) +} \ No newline at end of file diff --git a/sample/composeApp/src/desktopMain/kotlin/main.kt b/sample/composeApp/src/desktopMain/kotlin/main.kt new file mode 100644 index 0000000..5c9d7f0 --- /dev/null +++ b/sample/composeApp/src/desktopMain/kotlin/main.kt @@ -0,0 +1,13 @@ +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Window +import androidx.compose.ui.window.application +import androidx.compose.ui.window.rememberWindowState +import design.adapt.App + +fun main() = application { + Window( + title = "Adapt", + state = rememberWindowState(width = 800.dp, height = 600.dp), + onCloseRequest = ::exitApplication, + ) { App() } +} \ No newline at end of file diff --git a/sample/composeApp/src/iosMain/kotlin/design/adapt/App.ios.kt b/sample/composeApp/src/iosMain/kotlin/design/adapt/App.ios.kt new file mode 100644 index 0000000..b18c8cd --- /dev/null +++ b/sample/composeApp/src/iosMain/kotlin/design/adapt/App.ios.kt @@ -0,0 +1,9 @@ +package design.adapt + +import platform.Foundation.NSURL +import platform.UIKit.UIApplication + +internal actual fun openUrl(url: String?) { + val nsUrl = url?.let { NSURL.URLWithString(it) } ?: return + UIApplication.sharedApplication.openURL(nsUrl) +} \ No newline at end of file diff --git a/sample/composeApp/src/iosMain/kotlin/main.kt b/sample/composeApp/src/iosMain/kotlin/main.kt new file mode 100644 index 0000000..3850eb4 --- /dev/null +++ b/sample/composeApp/src/iosMain/kotlin/main.kt @@ -0,0 +1,7 @@ +import androidx.compose.ui.window.ComposeUIViewController +import design.adapt.App +import platform.UIKit.UIViewController + +fun MainViewController(): UIViewController { + return ComposeUIViewController { App() } +} diff --git a/sample/composeApp/src/jsMain/kotlin/BrowserViewportWindow.kt b/sample/composeApp/src/jsMain/kotlin/BrowserViewportWindow.kt new file mode 100644 index 0000000..e579d78 --- /dev/null +++ b/sample/composeApp/src/jsMain/kotlin/BrowserViewportWindow.kt @@ -0,0 +1,79 @@ +@file:Suppress( + "INVISIBLE_MEMBER", + "INVISIBLE_REFERENCE", + "EXPOSED_PARAMETER_TYPE" +) // WORKAROUND: ComposeWindow and ComposeLayer are internal + +import androidx.compose.runtime.Composable +import androidx.compose.ui.window.ComposeWindow +import kotlinx.browser.document +import kotlinx.browser.window +import org.w3c.dom.HTMLCanvasElement +import org.w3c.dom.HTMLStyleElement +import org.w3c.dom.HTMLTitleElement + +private const val CANVAS_ELEMENT_ID = "ComposeTarget" // Hardwired into ComposeWindow + +/** + * A Skiko/Canvas-based top-level window using the browser's entire viewport. Supports resizing. + * Author: https://github.com/OliverO2 + * Source: https://github.com/OliverO2/compose-counting-grid/blob/eb79f7c8be7804d4323114be30ce498cfac6d2b0/src/frontendWebMain/kotlin/BrowserViewportWindow.kt + */ +@Suppress("FunctionName") +fun BrowserViewportWindow( + title: String = "Untitled", + content: @Composable ComposeWindow.() -> Unit +) { + val htmlHeadElement = document.head!! + htmlHeadElement.appendChild( + (document.createElement("style") as HTMLStyleElement).apply { + type = "text/css" + appendChild( + document.createTextNode( + """ + html, body { + overflow: hidden; + margin: 0 !important; + padding: 0 !important; + } + + #$CANVAS_ELEMENT_ID { + outline: none; + } + """.trimIndent() + ) + ) + } + ) + + fun HTMLCanvasElement.fillViewportSize() { + setAttribute("width", "${window.innerWidth}") + setAttribute("height", "${window.innerHeight}") + } + + val canvas = (document.getElementById(CANVAS_ELEMENT_ID) as HTMLCanvasElement).apply { + fillViewportSize() + } + + ComposeWindow().apply { + window.addEventListener("resize", { + val scale = layer.layer.contentScale + val density = window.devicePixelRatio.toFloat() + canvas.fillViewportSize() + layer.layer.attachTo(canvas) + layer.layer.needRedraw() + layer.setSize((canvas.width / scale * density).toInt(), (canvas.height / scale * density).toInt()) + }) + + // WORKAROUND: ComposeWindow does not implement `setTitle(title)` + val htmlTitleElement = ( + htmlHeadElement.getElementsByTagName("title").item(0) + ?: document.createElement("title").also { htmlHeadElement.appendChild(it) } + ) as HTMLTitleElement + htmlTitleElement.textContent = title + + setContent { + content(this) + } + } +} diff --git a/sample/composeApp/src/jsMain/kotlin/design/adapt/App.js.kt b/sample/composeApp/src/jsMain/kotlin/design/adapt/App.js.kt new file mode 100644 index 0000000..5c1a02f --- /dev/null +++ b/sample/composeApp/src/jsMain/kotlin/design/adapt/App.js.kt @@ -0,0 +1,7 @@ +package design.adapt + +import kotlinx.browser.window + +internal actual fun openUrl(url: String?) { + url?.let { window.open(it) } +} \ No newline at end of file diff --git a/sample/composeApp/src/jsMain/kotlin/main.kt b/sample/composeApp/src/jsMain/kotlin/main.kt new file mode 100644 index 0000000..294dd9e --- /dev/null +++ b/sample/composeApp/src/jsMain/kotlin/main.kt @@ -0,0 +1,10 @@ +import design.adapt.App +import org.jetbrains.skiko.wasm.onWasmReady + +fun main() { + onWasmReady { + BrowserViewportWindow("Adapt") { + App() + } + } +} diff --git a/sample/composeApp/src/jsMain/resources/index.html b/sample/composeApp/src/jsMain/resources/index.html new file mode 100644 index 0000000..fb309c0 --- /dev/null +++ b/sample/composeApp/src/jsMain/resources/index.html @@ -0,0 +1,14 @@ + + + + + Adapt + + + +
+ +
+ + + \ No newline at end of file diff --git a/sample/iosApp/Podfile b/sample/iosApp/Podfile new file mode 100644 index 0000000..ed22a78 --- /dev/null +++ b/sample/iosApp/Podfile @@ -0,0 +1,5 @@ +target 'iosApp' do + use_frameworks! + platform :ios, '16.2' + pod 'composeApp', :path => '../composeApp' +end diff --git a/sample/iosApp/Podfile.lock b/sample/iosApp/Podfile.lock new file mode 100644 index 0000000..7cf9bf7 --- /dev/null +++ b/sample/iosApp/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - composeApp (1.0.0) + +DEPENDENCIES: + - composeApp (from `../composeApp`) + +EXTERNAL SOURCES: + composeApp: + :path: "../composeApp" + +SPEC CHECKSUMS: + composeApp: ea61662387fc72eaa04653a3bc307a660476dc48 + +PODFILE CHECKSUM: 3313a530e4ca4361dd2a9b97cf3c536967731c31 + +COCOAPODS: 1.12.1 diff --git a/sample/iosApp/iosApp.xcodeproj/project.pbxproj b/sample/iosApp/iosApp.xcodeproj/project.pbxproj new file mode 100644 index 0000000..27c6ba0 --- /dev/null +++ b/sample/iosApp/iosApp.xcodeproj/project.pbxproj @@ -0,0 +1,408 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 2E8B03050D9DA10FC5001441 /* Pods_iosApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4519E5654F91EC0B9696D248 /* Pods_iosApp.framework */; }; + A93A953B29CC810C00F8E227 /* iosApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A93A953A29CC810C00F8E227 /* iosApp.swift */; }; + A93A953F29CC810D00F8E227 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A93A953E29CC810D00F8E227 /* Assets.xcassets */; }; + A93A954229CC810D00F8E227 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A93A954129CC810D00F8E227 /* Preview Assets.xcassets */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 00F6B57D2F073A7469C15440 /* Pods-iosApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iosApp.debug.xcconfig"; path = "Target Support Files/Pods-iosApp/Pods-iosApp.debug.xcconfig"; sourceTree = ""; }; + 1948B6A255A7F1375DD8B1D4 /* Pods-iosApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iosApp.release.xcconfig"; path = "Target Support Files/Pods-iosApp/Pods-iosApp.release.xcconfig"; sourceTree = ""; }; + 4519E5654F91EC0B9696D248 /* Pods_iosApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_iosApp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A93A953729CC810C00F8E227 /* Adapt.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Adapt.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A93A953A29CC810C00F8E227 /* iosApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iosApp.swift; sourceTree = ""; }; + A93A953E29CC810D00F8E227 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + A93A954129CC810D00F8E227 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + A93A953429CC810C00F8E227 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2E8B03050D9DA10FC5001441 /* Pods_iosApp.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 5B41659B76FDF0879476171C /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4519E5654F91EC0B9696D248 /* Pods_iosApp.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 979913F6AE5D271756D4649D /* Pods */ = { + isa = PBXGroup; + children = ( + 00F6B57D2F073A7469C15440 /* Pods-iosApp.debug.xcconfig */, + 1948B6A255A7F1375DD8B1D4 /* Pods-iosApp.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + A93A952E29CC810C00F8E227 = { + isa = PBXGroup; + children = ( + A93A953929CC810C00F8E227 /* iosApp */, + A93A953829CC810C00F8E227 /* Products */, + 979913F6AE5D271756D4649D /* Pods */, + 5B41659B76FDF0879476171C /* Frameworks */, + ); + sourceTree = ""; + }; + A93A953829CC810C00F8E227 /* Products */ = { + isa = PBXGroup; + children = ( + A93A953729CC810C00F8E227 /* Adapt.app */, + ); + name = Products; + sourceTree = ""; + }; + A93A953929CC810C00F8E227 /* iosApp */ = { + isa = PBXGroup; + children = ( + A93A953A29CC810C00F8E227 /* iosApp.swift */, + A93A953E29CC810D00F8E227 /* Assets.xcassets */, + A93A954029CC810D00F8E227 /* Preview Content */, + ); + path = iosApp; + sourceTree = ""; + }; + A93A954029CC810D00F8E227 /* Preview Content */ = { + isa = PBXGroup; + children = ( + A93A954129CC810D00F8E227 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + A93A953629CC810C00F8E227 /* iosApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = A93A954529CC810D00F8E227 /* Build configuration list for PBXNativeTarget "iosApp" */; + buildPhases = ( + D364935F638B05A2E8A3471D /* [CP] Check Pods Manifest.lock */, + A93A953329CC810C00F8E227 /* Sources */, + A93A953429CC810C00F8E227 /* Frameworks */, + A93A953529CC810C00F8E227 /* Resources */, + FB338EEE91532E3EC88EA63C /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = iosApp; + productName = iosApp; + productReference = A93A953729CC810C00F8E227 /* Adapt.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A93A952F29CC810C00F8E227 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1420; + LastUpgradeCheck = 1420; + TargetAttributes = { + A93A953629CC810C00F8E227 = { + CreatedOnToolsVersion = 14.2; + }; + }; + }; + buildConfigurationList = A93A953229CC810C00F8E227 /* Build configuration list for PBXProject "iosApp" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = A93A952E29CC810C00F8E227; + productRefGroup = A93A953829CC810C00F8E227 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A93A953629CC810C00F8E227 /* iosApp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + A93A953529CC810C00F8E227 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A93A954229CC810D00F8E227 /* Preview Assets.xcassets in Resources */, + A93A953F29CC810D00F8E227 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + D364935F638B05A2E8A3471D /* [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-iosApp-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; + }; + FB338EEE91532E3EC88EA63C /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + A93A953329CC810C00F8E227 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A93A953B29CC810C00F8E227 /* iosApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + A93A954329CC810D00F8E227 /* 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++20"; + 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 = 16.2; + 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; + }; + A93A954429CC810D00F8E227 /* 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++20"; + 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 = 16.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + A93A954629CC810D00F8E227 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 00F6B57D2F073A7469C15440 /* Pods-iosApp.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = design.adapt.iosApp; + PRODUCT_NAME = Adapt; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A93A954729CC810D00F8E227 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1948B6A255A7F1375DD8B1D4 /* Pods-iosApp.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = design.adapt.iosApp; + PRODUCT_NAME = Adapt; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A93A953229CC810C00F8E227 /* Build configuration list for PBXProject "iosApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A93A954329CC810D00F8E227 /* Debug */, + A93A954429CC810D00F8E227 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A93A954529CC810D00F8E227 /* Build configuration list for PBXNativeTarget "iosApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A93A954629CC810D00F8E227 /* Debug */, + A93A954729CC810D00F8E227 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = A93A952F29CC810C00F8E227 /* Project object */; +} diff --git a/sample/iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/sample/iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/sample/iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/sample/iosApp/iosApp.xcworkspace/contents.xcworkspacedata b/sample/iosApp/iosApp.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..c009e7d --- /dev/null +++ b/sample/iosApp/iosApp.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/sample/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json b/sample/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/sample/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/sample/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/sample/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..13613e3 --- /dev/null +++ b/sample/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/sample/iosApp/iosApp/Assets.xcassets/Contents.json b/sample/iosApp/iosApp/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/sample/iosApp/iosApp/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/sample/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json b/sample/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/sample/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/sample/iosApp/iosApp/iosApp.swift b/sample/iosApp/iosApp/iosApp.swift new file mode 100644 index 0000000..9c80b76 --- /dev/null +++ b/sample/iosApp/iosApp/iosApp.swift @@ -0,0 +1,26 @@ +import UIKit +import SwiftUI +import ComposeApp + +@main +struct iosApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} + +struct ContentView: View { + var body: some View { + ComposeView().ignoresSafeArea(.keyboard) + } +} + +struct ComposeView: UIViewControllerRepresentable { + func makeUIViewController(context: Context) -> UIViewController { + MainKt.MainViewController() + } + + func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} +} diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..0047d64 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,22 @@ +@file:Suppress("UnstableApiUsage") + +rootProject.name = "Adapt" +include(":sample:composeApp") +include(":adapt") + +pluginManagement { + repositories { + google() + gradlePluginPortal() + mavenCentral() + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") + } +} + +dependencyResolutionManagement { + repositories { + google() + mavenCentral() + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") + } +}