diff --git a/.github/workflows/lightsaber-ci.yml b/.github/workflows/lightsaber-ci.yml index 96fe9d8..dfc6199 100644 --- a/.github/workflows/lightsaber-ci.yml +++ b/.github/workflows/lightsaber-ci.yml @@ -116,16 +116,17 @@ jobs: api-key: ${{ secrets.MAESTRO_CLOUD_API_KEY }} app-file: androidApp/build/outputs/apk/debug/androidApp-debug.apk - e2e-test-iosApp: - runs-on: macos-latest - needs: build-iosApp - steps: - - uses: actions/checkout@v3 - - uses: ./.github/actions/setup-lightsaber-ci - - - name: Check for app file - run: test -e ./iosApp/build/ios/Release-iphonesimulator/Lightsaber.app - - uses: mobile-dev-inc/action-maestro-cloud@v1.1.0 - with: - api-key: ${{ secrets.MAESTRO_CLOUD_API_KEY }} - app-file: ./iosApp/build/ios/Release-iphonesimulator/Lightsaber.app \ No newline at end of file +# TODO Fix maestro tests on x86-64 +# e2e-test-iosApp: +# runs-on: macos-latest +# needs: build-iosApp +# steps: +# - uses: actions/checkout@v3 +# - uses: ./.github/actions/setup-lightsaber-ci +# +# - name: Check for app file +# run: test -e ./iosApp/build/ios/Release-iphonesimulator/Lightsaber.app +# - uses: mobile-dev-inc/action-maestro-cloud@v1.1.0 +# with: +# api-key: ${{ secrets.MAESTRO_CLOUD_API_KEY }} +# app-file: ./iosApp/build/ios/Release-iphonesimulator/Lightsaber.app \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6e5f304..3a54f0a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ iosApp/iosApp.xcworkspace/* iosApp/iosApp.xcodeproj/* !iosApp/iosApp.xcodeproj/project.pbxproj shared/shared.podspec +.kotlin diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index e744f60..de6c256 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -2,6 +2,7 @@ plugins { alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.android.application) alias(libs.plugins.compose) + alias(libs.plugins.compose.compiler) } kotlin { diff --git a/build.gradle.kts b/build.gradle.kts index 5e69dbe..2060751 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.android.application).apply(false) alias(libs.plugins.android.library).apply(false) alias(libs.plugins.compose).apply(false) + alias(libs.plugins.compose.compiler).apply(false) alias(libs.plugins.ksp).apply(false) alias(libs.plugins.kotlin.plugin.parcelize).apply(false) alias(libs.plugins.kotlin.native.cocoapods).apply(false) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f404168..77a3846 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,20 +1,20 @@ [versions] core-splashscreen = "1.0.1" -kotlin = "1.9.22" +kotlin = "2.0.0" agp = "8.2.2" -compose = "1.6.0" -ksp = "1.9.22-1.0.16" -kotlin-inject = "0.6.3" -circuit = "0.19.1" -androidx-activity-compose = "1.8.2" -androidx-appcompat = "1.6.1" -androidx-core-ktx = "1.12.0" -datastore-version = "1.1.0-beta02" -compose-ui-test = "1.6.3" +compose = "1.6.11" +ksp = "2.0.0-1.0.22" +kotlin-inject = "0.7.0-SNAPSHOT" +circuit = "0.22.2" +androidx-activity-compose = "1.9.0" +androidx-appcompat = "1.7.0" +androidx-core-ktx = "1.13.1" +datastore-version = "1.1.1" +compose-ui-test = "1.6.7" [libraries] androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "core-splashscreen" } -kotlin-inject-runtime = { module = "me.tatarka.inject:kotlin-inject-runtime", version.ref = "kotlin-inject" } +kotlin-inject-runtime-kmp = { module = "me.tatarka.inject:kotlin-inject-runtime-kmp", version.ref = "kotlin-inject" } kotlin-inject-ksp = { module = "me.tatarka.inject:kotlin-inject-compiler-ksp", version.ref = "kotlin-inject" } kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } circuit-foundation = { module = "com.slack.circuit:circuit-foundation", version.ref = "circuit" } @@ -33,6 +33,7 @@ kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-plugin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } kotlin-native-cocoapods = { id = "org.jetbrains.kotlin.native.cocoapods", version.ref = "kotlin" } +compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } compose = { id = "org.jetbrains.compose", version.ref = "compose" } android-application = { id = "com.android.application", version.ref = "agp" } android-library = { id = "com.android.library", version.ref = "agp" } diff --git a/settings.gradle.kts b/settings.gradle.kts index b5f31e4..0930bf7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,6 +7,7 @@ pluginManagement { repositories { gradlePluginPortal() maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") + maven("https://oss.sonatype.org/content/repositories/snapshots") google() } } @@ -16,5 +17,6 @@ dependencyResolutionManagement { google() mavenCentral() maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") + maven("https://oss.sonatype.org/content/repositories/snapshots") } } diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 1b8ddf4..2d3db7b 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -1,3 +1,4 @@ +import com.google.devtools.ksp.gradle.KspTaskMetadata import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree @@ -5,6 +6,7 @@ plugins { alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.android.library) alias(libs.plugins.compose) + alias(libs.plugins.compose.compiler) alias(libs.plugins.ksp) alias(libs.plugins.kotlin.plugin.parcelize) alias(libs.plugins.kotlin.native.cocoapods) @@ -48,7 +50,7 @@ kotlin { implementation(compose.material) @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) implementation(compose.components.resources) - implementation(libs.kotlin.inject.runtime) + implementation(libs.kotlin.inject.runtime.kmp) implementation(libs.circuit.foundation) implementation(libs.circuitx.gesture.navigation) implementation(libs.androidx.datastore.preferences.core) diff --git a/shared/src/commonMain/kotlin/xyz/alaniz/aaron/lightsaber/di/DatastoreComponent.kt b/shared/src/commonMain/kotlin/xyz/alaniz/aaron/lightsaber/di/DatastoreComponent.kt index ff7781b..c513e29 100644 --- a/shared/src/commonMain/kotlin/xyz/alaniz/aaron/lightsaber/di/DatastoreComponent.kt +++ b/shared/src/commonMain/kotlin/xyz/alaniz/aaron/lightsaber/di/DatastoreComponent.kt @@ -4,7 +4,6 @@ import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.PreferenceDataStoreFactory import androidx.datastore.preferences.core.Preferences import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.MainScope import me.tatarka.inject.annotations.Component import me.tatarka.inject.annotations.Provides import okio.Path.Companion.toPath @@ -23,4 +22,5 @@ abstract class DatastoreComponent( dataStorePath.toPath() } } + companion object } \ No newline at end of file diff --git a/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/audio/IosSoundPlayer.kt b/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/audio/IosSoundPlayer.kt index 7236ee1..31abc17 100644 --- a/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/audio/IosSoundPlayer.kt +++ b/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/audio/IosSoundPlayer.kt @@ -25,7 +25,7 @@ class IosSoundPlayer(private val audioEngine: AVAudioEngine) : SoundPlayer { NSBundle.mainBundle.pathForResource( name = soundResource.name, ofType = soundResource.fileType, - inDirectory = "compose-resources/${soundResource.directory}" + inDirectory = "compose-resources/composeResources/lightsaber.shared.generated.resources/${soundResource.directory}" ) ) val audioFile = diff --git a/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosApplicationComponent.kt b/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosApplicationComponent.kt index 27db2e8..f6095ed 100644 --- a/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosApplicationComponent.kt +++ b/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosApplicationComponent.kt @@ -3,6 +3,7 @@ package xyz.alaniz.aaron.lightsaber.di import com.slack.circuit.runtime.Navigator import kotlinx.coroutines.CoroutineScope import me.tatarka.inject.annotations.Component +import me.tatarka.inject.annotations.KmpComponentCreate import me.tatarka.inject.annotations.Provides import xyz.alaniz.aaron.lightsaber.ui.settings.IosSettingsScreen import xyz.alaniz.aaron.lightsaber.ui.settings.SettingsScreen @@ -12,13 +13,22 @@ abstract class IosApplicationComponent( @get:Provides protected val navigator: Navigator, @get:Provides protected val appScope: CoroutineScope, dataStorePath: String, - @Component protected val iosSoundComponent: IosSoundComponent = IosSoundComponent::class.create(), - @Component protected val iosMotionComponent: IosMotionComponent = IosMotionComponent::class.create(), - @Component protected val dataStoreComponent: DatastoreComponent = DatastoreComponent::class.create( + @Component protected val iosSoundComponent: IosSoundComponent = IosSoundComponent.create(), + @Component protected val iosMotionComponent: IosMotionComponent = IosMotionComponent.create(), + @Component protected val dataStoreComponent: DatastoreComponent = DatastoreComponent.create( appScope, dataStorePath ) ) : ApplicationComponent() { protected val IosSettingsScreen.bind: SettingsScreen @Provides get() = this -} \ No newline at end of file + + companion object +} + +@KmpComponentCreate +expect fun IosApplicationComponent.Companion.create( + navigator: Navigator, + appScope: CoroutineScope, + dataStorePath: String +): IosApplicationComponent \ No newline at end of file diff --git a/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosDatastoreComponent.kt b/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosDatastoreComponent.kt new file mode 100644 index 0000000..fbdf5f0 --- /dev/null +++ b/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosDatastoreComponent.kt @@ -0,0 +1,8 @@ +package xyz.alaniz.aaron.lightsaber.di + +import kotlinx.coroutines.CoroutineScope +import me.tatarka.inject.annotations.KmpComponentCreate + + +@KmpComponentCreate +expect fun DatastoreComponent.Companion.create(scope: CoroutineScope, dataStorePath: String): DatastoreComponent diff --git a/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosMotionComponent.kt b/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosMotionComponent.kt index 0787eb1..16898b7 100644 --- a/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosMotionComponent.kt +++ b/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosMotionComponent.kt @@ -2,6 +2,7 @@ package xyz.alaniz.aaron.lightsaber.di import kotlinx.coroutines.flow.Flow import me.tatarka.inject.annotations.Component +import me.tatarka.inject.annotations.KmpComponentCreate import me.tatarka.inject.annotations.Provides import xyz.alaniz.aaron.lightsaber.motion.IosSwingDetector import xyz.alaniz.aaron.lightsaber.motion.SwingEvent @@ -21,4 +22,9 @@ abstract class IosMotionComponent { internal val IosSwingDetector.bind: Flow @Provides get() = this.swings -} \ No newline at end of file + + companion object +} + +@KmpComponentCreate +expect fun IosMotionComponent.Companion.create(): IosMotionComponent \ No newline at end of file diff --git a/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosSoundComponent.kt b/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosSoundComponent.kt index 0b39117..9044410 100644 --- a/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosSoundComponent.kt +++ b/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/di/IosSoundComponent.kt @@ -3,6 +3,7 @@ package xyz.alaniz.aaron.lightsaber.di import xyz.alaniz.aaron.lightsaber.audio.IosSoundPlayer import xyz.alaniz.aaron.lightsaber.audio.SoundPlayer import me.tatarka.inject.annotations.Component +import me.tatarka.inject.annotations.KmpComponentCreate import me.tatarka.inject.annotations.Provides import platform.AVFAudio.AVAudioEngine @@ -13,4 +14,9 @@ abstract class IosSoundComponent { @Provides internal fun providesAvAudioEngine(): AVAudioEngine = AVAudioEngine() -} \ No newline at end of file + + companion object +} + +@KmpComponentCreate +expect fun IosSoundComponent.Companion.create(): IosSoundComponent \ No newline at end of file diff --git a/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/main.ios.kt b/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/main.ios.kt index 3ad3c5f..3e6a296 100644 --- a/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/main.ios.kt +++ b/shared/src/iosMain/kotlin/xyz/alaniz/aaron/lightsaber/main.ios.kt @@ -37,7 +37,7 @@ fun MainViewController() = ComposeUIViewController(configure = { ) val dataStorePath = requireNotNull(documentDirectory).path + "/$dataStoreFileName" App(initialScreen = IosLightsaberScreen) { scope, navigator -> - IosApplicationComponent::class.create( + IosApplicationComponent.create( navigator = navigator, appScope = scope, dataStorePath = dataStorePath