diff --git a/images/ktor-sql/create-ktor-sqldelight-multiplatform-project.png b/images/ktor-sql/create-ktor-sqldelight-multiplatform-project.png index 47cf74d0..b5943396 100644 Binary files a/images/ktor-sql/create-ktor-sqldelight-multiplatform-project.png and b/images/ktor-sql/create-ktor-sqldelight-multiplatform-project.png differ diff --git a/snippets/multiplatform-tutorial/Entity.kt b/snippets/multiplatform-tutorial/Entity.kt index edc1c784..c19c7919 100644 --- a/snippets/multiplatform-tutorial/Entity.kt +++ b/snippets/multiplatform-tutorial/Entity.kt @@ -1,10 +1,10 @@ package com.jetbrains.spacetutorial.entity import kotlinx.datetime.TimeZone -import kotlinx.datetime.toInstant import kotlinx.datetime.toLocalDateTime import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import kotlin.time.Instant @Serializable data class RocketLaunch( diff --git a/topics/development/multiplatform-ktor-sqldelight.md b/topics/development/multiplatform-ktor-sqldelight.md index fc1dcee7..fa6a8bc9 100644 --- a/topics/development/multiplatform-ktor-sqldelight.md +++ b/topics/development/multiplatform-ktor-sqldelight.md @@ -48,12 +48,12 @@ You will use the following multiplatform libraries in the project: * **Group**: com.jetbrains * **Artifact**: spacetutorial - ![Create Ktor and SQLDelight Multiplatform project](create-ktor-sqldelight-multiplatform-project.png){width=800} - 5. Select **Android** and **iOS** targets. 6. For iOS, select the **Do not share UI** option. You will implement a native UI for both platforms. 7. Once you've specified all the fields and targets, click **Create**. + ![Create Ktor and SQLDelight Multiplatform project](create-ktor-sqldelight-multiplatform-project.png){width=800} + ## Add Gradle dependencies To add a multiplatform library to the shared module, you need to add dependency instructions (`implementation`) @@ -67,14 +67,15 @@ Change or add lines in the version catalog in the `gradle/libs.versions.toml` fi ``` [versions] - agp = "8.7.3" + agp = "9.0.1" + material3 = "1.10.0-alpha05" ... coroutinesVersion = "%coroutinesVersion%" dateTimeVersion = "%dateTimeVersion%" koin = "%koinVersion%" ktor = "%ktorVersion%" sqlDelight = "%sqlDelightVersion%" - material3 = "1.3.2" + ``` {initial-collapse-state="collapsed" collapsible="true" collapsed-title="[versions]"} @@ -84,7 +85,6 @@ Change or add lines in the version catalog in the `gradle/libs.versions.toml` fi [libraries] ... android-driver = { module = "app.cash.sqldelight:android-driver", version.ref = "sqlDelight" } - koin-androidx-compose = { module = "io.insert-koin:koin-androidx-compose", version.ref = "koin" } koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutinesVersion" } kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "dateTimeVersion" } @@ -95,9 +95,9 @@ Change or add lines in the version catalog in the `gradle/libs.versions.toml` fi ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" } native-driver = { module = "app.cash.sqldelight:native-driver", version.ref = "sqlDelight" } runtime = { module = "app.cash.sqldelight:runtime", version.ref = "sqlDelight" } - androidx-compose-material3 = { module = "androidx.compose.material3:material3", version.ref="material3" } ``` {initial-collapse-state="collapsed" collapsible="true" collapsed-title="[libraries]"} + 3. In the `[plugins]` block, specify the necessary Gradle plugins: @@ -110,7 +110,7 @@ Change or add lines in the version catalog in the `gradle/libs.versions.toml` fi 4. Once the dependencies are added, you're prompted to resync the project. Click the **Sync Gradle Changes** button to synchronize Gradle files: ![Synchronize Gradle files](gradle-sync.png){width=50} -5. At the very beginning of the `shared/build.gradle.kts` file, add the following lines to the +5. At the very beginning of the `sharedLogic/build.gradle.kts` file, add the following lines to the `plugins {}` block: ```kotlin @@ -125,7 +125,7 @@ Change or add lines in the version catalog in the `gradle/libs.versions.toml` fi to use `kotlinx.serialization` for processing network requests and responses. The iOS and Android source sets also need SQLDelight and Ktor platform drivers. - In the same `shared/build.gradle.kts` file, add all the required dependencies: + In the same `sharedLogic/build.gradle.kts` file, add all the required dependencies: ```kotlin kotlin { @@ -154,6 +154,7 @@ Change or add lines in the version catalog in the `gradle/libs.versions.toml` fi ``` 7. At the beginning of the `sourseSets` block, opt in for the experimental time API of the standard Kotlin library: + ```kotlin kotlin { @@ -194,13 +195,13 @@ The application data model will have three entity classes with: Create the necessary data classes: -1. In the `shared/src/commonMain/kotlin/com/jetbrains/spacetutorial` directory, create the `entity` package, +1. In the `sharedLogic/src/commonMain/kotlin/com/jetbrains/spacetutorial` directory, create the `entity` package, then create the `Entity.kt` file inside that package. 2. Declare all the data classes for basic entities: ```kotlin ``` - {src="multiplatform-tutorial/Entity.kt" initial-collapse-state="collapsed" collapsible="true" collapsed-title="data class RocketLaunch" include-lines="3-41" } + {src="multiplatform-tutorial/Entity.kt" initial-collapse-state="collapsed" collapsible="true" collapsed-title="data class RocketLaunch" include-lines="3-40" } Each serializable class must be marked with the `@Serializable` annotation. The `kotlinx.serialization` plugin automatically generates a default serializer for `@Serializable` classes unless you explicitly pass a link to a @@ -216,7 +217,7 @@ using more readable identifiers. The SQLDelight library allows you to generate a type-safe Kotlin database API from SQL queries. During compilation, the generator validates the SQL queries and turns them into Kotlin code that can be used in the shared module. -The SQLDelight dependency is already included in the project. To configure the library, open the `shared/build.gradle.kts` file +The SQLDelight dependency is already included in the project. To configure the library, open the `sharedLogic/build.gradle.kts` file and add the `sqldelight {}` block in the end. This block contains a list of databases and their parameters: ```kotlin @@ -244,14 +245,14 @@ Sync the Gradle project files when prompted, or press double ShiftShift` tag: +In the `androidApp/src/main/AndroidManifest.xml` file, add the `` tag: ```xml @@ -618,7 +605,7 @@ Then, you will start Koin for each native UI using the corresponding module. Declare a Koin module that will contain the components for the Android app: -1. In the `composeApp/src/androidMain/kotlin` directory, create the `AppModule.kt` file in the `com.jetbrains.spacetutorial` package. +1. In the `androidApp/src/main/kotlin` directory, create the `AppModule.kt` file in the `com.jetbrains.spacetutorial` package. In that file, declare the module as two [singletons](https://insert-koin.io/docs/reference/koin-core/definitions#defining-a-singleton), one for the `SpaceXApi` class and one for the `SpaceXSDK` class: @@ -649,7 +636,7 @@ Declare a Koin module that will contain the components for the Android app: 2. Create a custom `Application` class, which will start the Koin module. - Next to the `AppModule.kt` file, create the `Application.kt` file with the following code, specifying the module + Next to the `AppModule.kt` file you created, create the `Application.kt` file with the following code, specifying the module you declared in the `modules()` function call: ```kotlin @@ -692,7 +679,7 @@ You will implement the Android UI using Jetpack Compose and Material 3. First, y uses the SDK to get the list of launches. Then, you'll set up the Material theme, and finally, you'll write the composable function that brings it all together. -1. In the `composeApp/src/androidMain` source set, in the `com.jetbrains.spacetutorial` package, create +1. In the `androidApp/src/main/kotlin` directory, in the `com.jetbrains.spacetutorial` package, create the `RocketLaunchViewModel.kt` file: ```kotlin @@ -773,8 +760,8 @@ You will build your main `App()` composable around the `AppTheme` function suppl Pick your colors, pick your fonts, then click **Export theme** in the bottom right corner. 2. On the export screen, click the **Export** dropdown and select the **Jetpack Compose (Theme.kt)** option. -3. Unpack the archive and copy the `theme` folder into the `composeApp/src/androidMain/kotlin/com/jetbrains/spacetutorial` - directory. +3. Unpack the archive and copy the `theme` folder into the `androidApp/src/main/kotlin/com/jetbrains/spacetutorial` + directory: ![theme directory location](theme-directory.png){width=299} @@ -968,8 +955,8 @@ For the iOS part of the project, you'll make use of [SwiftUI](https://developer. interface and the [Model View View-Model](https://en.wikipedia.org/wiki/Model–view–viewmodel) pattern. IntelliJ IDEA generates an iOS project that is already connected to the shared module. The Kotlin module -is exported with the name specified in the `shared/build.gradle.kts` file (`baseName = "Shared"`), and imported -using a regular `import` statement: `import Shared`. +is exported with the name specified in the `sharedLogic/build.gradle.kts` file (`baseName = "SharedLogic"`), and imported +using a regular `import` statement: `import SharedLogic`. ### Add the dynamic linking flag for SQLDelight @@ -992,8 +979,7 @@ system-provided SQLite binary: To use Koin classes and functions in Swift code, create a special `KoinComponent` class and declare the Koin module for iOS. -1. In the `shared/src/iosMain/kotlin/` source set, create a file with the name `com/jetbrains/spacetutorial/KoinHelper.kt` - (it will appear next to the `cache` folder). +1. In the `sharedLogic/src/iosMain/kotlin/` source set, create the `KoinHelper.kt` file. 2. Add the `KoinHelper` class, which will wrap the `SpaceXSDK` class with a lazy Koin injection: ```kotlin @@ -1048,7 +1034,7 @@ data. ```Swift import SwiftUI - import Shared + import SharedLogic struct RocketLaunchRow: View { var rocketLaunch: RocketLaunch @@ -1167,7 +1153,6 @@ It will allow you to call the SDK function with the correct database driver. ```Swift extension ContentView { // ... - @MainActor class ViewModel: ObservableObject { // ... let helper: KoinHelper = KoinHelper() @@ -1211,7 +1196,7 @@ It will allow you to call the SDK function with the correct database driver. ```Swift import SwiftUI - import Shared + import SharedLogic @main struct iOSApp: App { diff --git a/v.list b/v.list index c5633307..947d7e22 100644 --- a/v.list +++ b/v.list @@ -38,10 +38,10 @@ - + - +