-
Notifications
You must be signed in to change notification settings - Fork 344
KTOR-8556 Update the client KMP tutorial to use IntelliJ IDEA #691
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…ate sample project
WalkthroughReorganizes the KMM tutorial: replaces the androidApp module with composeApp, renames package paths to com.example.ktor.kmmktor and Greeting.greeting()→greet(), upgrades Gradle/Kotlin/tooling and wrapper, adds Android/iOS resources and KMM-focused Xcode changes, updates docs and .gitignore. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Nitpick comments (5)
codeSnippets/snippets/tutorial-client-kmm/gradle/wrapper/gradle-wrapper.properties (1)
3-3
: Use the latest Gradle distribution.
As of October 2, 2025, the current stable Gradle release is 9.1.0; updatedistributionUrl
to https://services.gradle.org/distributions/gradle-9.1.0-bin.zip.codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json (1)
2-35
: App icon entries lack image file references.The asset catalog defines universal icon slots for base, dark, and tinted appearances, but none include
"filename"
keys pointing to actual image files. The app will display a default/placeholder icon. For a tutorial project, consider either providing placeholder images (e.g.,icon-1024.png
) or documenting that users should add their own icons.codeSnippets/snippets/tutorial-client-kmm/README.md (1)
11-16
: Adjust nested list indentation for Markdown consistency.The nested list items are indented with 4 spaces instead of the expected 2 spaces, which may cause rendering issues in some Markdown processors.
Apply this diff to correct the indentation:
* [/composeApp](./composeApp/src) is for code that will be shared across your Compose Multiplatform applications. It contains several subfolders: - - [commonMain](./composeApp/src/commonMain/kotlin) is for code that's common for all targets. - - Other folders are for Kotlin code that will be compiled for only the platform indicated in the folder name. + - [commonMain](./composeApp/src/commonMain/kotlin) is for code that's common for all targets. + - Other folders are for Kotlin code that will be compiled for only the platform indicated in the folder name. For example, if you want to use Apple's CoreCrypto for the iOS part of your Kotlin app, the [iosMain](./composeApp/src/iosMain/kotlin) folder would be the right place for such calls. Similarly, if you want to edit the Desktop (JVM) specific part, the [jvmMain](./composeApp/src/jvmMain/kotlin) folder is the appropriate location.codeSnippets/snippets/tutorial-client-kmm/composeApp/build.gradle.kts (2)
1-1
: Remove unused import.The
TargetFormat
import is not used in this build file. It's typically needed for desktop targets but not for this Android-focused configuration.Apply this diff:
-import org.jetbrains.compose.desktop.application.dsl.TargetFormat import org.jetbrains.kotlin.gradle.dsl.JvmTarget
22-22
: Clarify or expand the comment.The
// ...
comment is ambiguous and could confuse tutorial users. Either expand it to explain what dependencies might be added here, or remove it if the dependency list is complete.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (19)
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.png
is excluded by!**/*.png
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png
is excluded by!**/*.png
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.png
is excluded by!**/*.png
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png
is excluded by!**/*.png
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png
is excluded by!**/*.png
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png
is excluded by!**/*.png
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png
is excluded by!**/*.png
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png
is excluded by!**/*.png
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png
is excluded by!**/*.png
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png
is excluded by!**/*.png
codeSnippets/snippets/tutorial-client-kmm/gradle/wrapper/gradle-wrapper.jar
is excluded by!**/*.jar
images/kmm_tutorial_create_project.png
is excluded by!**/*.png
images/kmm_tutorial_create_project_dark.png
is excluded by!**/*.png
images/kmm_tutorial_run_android.png
is excluded by!**/*.png
images/kmm_tutorial_run_android_dark.png
is excluded by!**/*.png
images/kmm_tutorial_run_ios.png
is excluded by!**/*.png
images/kmm_tutorial_run_ios_dark.png
is excluded by!**/*.png
images/tutorial_client_kmm_android.png
is excluded by!**/*.png
images/tutorial_client_kmm_ios.png
is excluded by!**/*.png
📒 Files selected for processing (42)
codeSnippets/snippets/tutorial-client-kmm/.gitignore
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/README.md
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/androidApp/build.gradle.kts
(0 hunks)codeSnippets/snippets/tutorial-client-kmm/androidApp/src/main/java/com/example/kmmktor/android/MainActivity.kt
(0 hunks)codeSnippets/snippets/tutorial-client-kmm/androidApp/src/main/java/com/example/kmmktor/android/MyApplicationTheme.kt
(0 hunks)codeSnippets/snippets/tutorial-client-kmm/androidApp/src/main/res/values/styles.xml
(0 hunks)codeSnippets/snippets/tutorial-client-kmm/build.gradle.kts
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/composeApp/build.gradle.kts
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/AndroidManifest.xml
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/composeResources/drawable/compose-multiplatform.xml
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/kotlin/com/example/ktor/kmmktor/App.kt
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/kotlin/com/example/ktor/kmmktor/MainActivity.kt
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/drawable/ic_launcher_background.xml
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/values/strings.xml
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidUnitTest/kotlin/com/example/ktor/kmmktor/ComposeAppAndroidUnitTest.kt
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/gradle.properties
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/gradle/libs.versions.toml
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/gradle/wrapper/gradle-wrapper.properties
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/gradlew
(3 hunks)codeSnippets/snippets/tutorial-client-kmm/gradlew.bat
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/iosApp/Configuration/Config.xcconfig
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp.xcodeproj/project.pbxproj
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/Assets.xcassets/Contents.json
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/ContentView.swift
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/Info.plist
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/iOSApp.swift
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/settings.gradle.kts
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/shared/build.gradle.kts
(2 hunks)codeSnippets/snippets/tutorial-client-kmm/shared/src/androidMain/kotlin/com/example/kmmktor/Platform.android.kt
(0 hunks)codeSnippets/snippets/tutorial-client-kmm/shared/src/androidMain/kotlin/com/example/ktor/kmmktor/Platform.android.kt
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/shared/src/commonMain/kotlin/com/example/ktor/kmmktor/Greeting.kt
(2 hunks)codeSnippets/snippets/tutorial-client-kmm/shared/src/commonMain/kotlin/com/example/ktor/kmmktor/Platform.kt
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/shared/src/commonTest/kotlin/com/example/ktor/kmmktor/SharedCommonTest.kt
(1 hunks)codeSnippets/snippets/tutorial-client-kmm/shared/src/iosMain/kotlin/com/example/ktor/kmmktor/Platform.ios.kt
(1 hunks)topics/client-create-multiplatform-application.md
(3 hunks)
💤 Files with no reviewable changes (5)
- codeSnippets/snippets/tutorial-client-kmm/androidApp/src/main/res/values/styles.xml
- codeSnippets/snippets/tutorial-client-kmm/androidApp/src/main/java/com/example/kmmktor/android/MyApplicationTheme.kt
- codeSnippets/snippets/tutorial-client-kmm/androidApp/build.gradle.kts
- codeSnippets/snippets/tutorial-client-kmm/androidApp/src/main/java/com/example/kmmktor/android/MainActivity.kt
- codeSnippets/snippets/tutorial-client-kmm/shared/src/androidMain/kotlin/com/example/kmmktor/Platform.android.kt
🧰 Additional context used
🧬 Code graph analysis (2)
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/kotlin/com/example/ktor/kmmktor/MainActivity.kt (1)
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/kotlin/com/example/ktor/kmmktor/App.kt (1)
App
(14-36)
codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/ContentView.swift (1)
codeSnippets/snippets/tutorial-client-kmm/shared/src/commonMain/kotlin/com/example/ktor/kmmktor/Greeting.kt (1)
greet
(10-13)
🪛 markdownlint-cli2 (0.18.1)
codeSnippets/snippets/tutorial-client-kmm/README.md
11-11: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
12-12: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
topics/client-create-multiplatform-application.md
94-94: Link fragments should be valid
(MD051, link-fragments)
🔇 Additional comments (27)
codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata (1)
1-7
: LGTM! Standard Xcode workspace configuration.The XML structure is valid and follows Xcode workspace conventions. This file properly establishes the workspace reference for the iOS project.
codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/iOSApp.swift (1)
5-9
: LGTM! Simplified ContentView initialization.The change to a parameterless
ContentView()
initializer is appropriate and aligns with SwiftUI best practices where views manage their own state objects internally. This simplifies the app entry point.codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json (1)
1-7
: LGTM! Formatting normalization.This is a formatting-only change that normalizes spacing in the JSON asset metadata. No semantic changes.
codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json (1)
1-12
: LGTM! Formatting normalization.JSON formatting has been normalized by removing extraneous spaces around colons. No semantic changes to the color set definition.
codeSnippets/snippets/tutorial-client-kmm/shared/src/commonTest/kotlin/com/example/ktor/kmmktor/SharedCommonTest.kt (1)
1-12
: LGTM! Valid test structure.The test file follows Kotlin Multiplatform testing conventions and uses the correct package namespace. While the test itself is a placeholder assertion, this is standard for initial project setup and provides a foundation for adding meaningful tests later.
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/drawable/ic_launcher_background.xml (1)
1-170
: LGTM! Standard Android adaptive icon background.The vector drawable follows Android conventions for adaptive launcher icons with the standard 108dp dimensions and proper XML structure. The grid pattern and color scheme are typical for launcher backgrounds.
codeSnippets/snippets/tutorial-client-kmm/gradlew.bat (1)
1-95
: LGTM! Gradle wrapper modernization.The Windows Gradle wrapper has been appropriately updated with:
- SPDX license identifier for clarity
- Proper error message redirection to stderr
- More explicit ERRORLEVEL comparisons
These changes improve error handling and licensing clarity while preserving functionality.
codeSnippets/snippets/tutorial-client-kmm/shared/src/commonMain/kotlin/com/example/ktor/kmmktor/Platform.kt (1)
1-1
: Consistent package rename verified
All occurrences ofcom.example.kmmktor
have been updated tocom.example.ktor.kmmktor
.codeSnippets/snippets/tutorial-client-kmm/gradle/libs.versions.toml (2)
18-33
: LGTM!Library declarations are well-structured with proper version references. The addition of AndroidX lifecycle, testing libraries, and Ktor client dependencies appropriately supports the KMM tutorial requirements.
36-41
: LGTM!Plugin declarations are correctly structured and align with the Kotlin Multiplatform and Compose Multiplatform setup, assuming the versions referenced are valid.
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml (1)
1-5
: LGTM!The adaptive icon configuration is correctly structured and properly references the required background and foreground drawables for Android API 26+.
codeSnippets/snippets/tutorial-client-kmm/shared/src/iosMain/kotlin/com/example/ktor/kmmktor/Platform.ios.kt (1)
1-9
: LGTM!The package refactoring to
com.example.ktor.kmmktor
is consistent with the PR's restructuring objectives. The iOS platform implementation correctly provides system name and version information.codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml (1)
1-5
: LGTM!The round adaptive icon configuration is correctly structured and reuses the same background and foreground drawables as the standard launcher icon, which is the standard approach.
codeSnippets/snippets/tutorial-client-kmm/gradle/wrapper/gradle-wrapper.properties (1)
4-5
: LGTM! Security settings are appropriate.The addition of
networkTimeout=10000
andvalidateDistributionUrl=true
are good security and reliability practices for the Gradle wrapper.codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/Assets.xcassets/Contents.json (1)
1-7
: LGTM!This is a formatting-only change to the asset catalog metadata with no semantic impact.
codeSnippets/snippets/tutorial-client-kmm/iosApp/Configuration/Config.xcconfig (1)
1-1
: LGTM!The empty
TEAM_ID
placeholder, product name, and version settings are appropriate for a tutorial project template where users will provide their own team identifier.Also applies to: 3-3, 6-7
codeSnippets/snippets/tutorial-client-kmm/shared/src/commonMain/kotlin/com/example/ktor/kmmktor/Greeting.kt (1)
1-14
: Rename Verified Across All Call Sites No occurrences ofgreeting()
remain; all call sites usegreet()
.codeSnippets/snippets/tutorial-client-kmm/shared/src/androidMain/kotlin/com/example/ktor/kmmktor/Platform.android.kt (1)
1-9
: LGTM!The Android platform implementation correctly follows the Kotlin Multiplatform expect/actual pattern. The
AndroidPlatform
class properly implements thePlatform
interface, and thegetPlatform()
function returns the expected instance.codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/kotlin/com/example/ktor/kmmktor/MainActivity.kt (2)
10-19
: LGTM!The
MainActivity
correctly extendsComponentActivity
, enables edge-to-edge display, and sets up the Compose content. The implementation follows modern Android development best practices.
21-25
: LGTM!The preview function is properly annotated and will enable design-time rendering in Android Studio.
codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/ContentView.swift (3)
2-2
: LGTM!The import name change from
shared
toShared
correctly follows KMM framework naming conventions.
5-5
: LGTM!Switching from
@ObservedObject
to@StateObject
is correct, asContentView
now owns theViewModel
lifecycle.
13-23
: Ensure Kotlin suspend function interop matches Swift usage.The shared code defines
suspend fun greet(): String
. Without acocoapods { … }
plugin block to generate callback-based bindings, Swift sees it asfunc greet() async throws -> String
, not a closure API. Either add acocoapods { }
configuration in your Gradle build or update the Swift call to:Task { do { let greeting = try await Greeting().greet() self.text = greeting } catch { self.text = error.localizedDescription } }codeSnippets/snippets/tutorial-client-kmm/composeApp/build.gradle.kts (2)
4-40
: LGTM!The Kotlin Multiplatform and Compose configuration is well-structured with appropriate dependencies for a KMM Android tutorial project.
42-67
: LGTM!The Android configuration is properly set up with appropriate SDK versions, packaging rules, and Java compatibility settings for a tutorial project.
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml (1)
1-30
: LGTM!The launcher foreground vector drawable is correctly structured and uses the standard Android robot icon, which is appropriate for a tutorial project.
codeSnippets/snippets/tutorial-client-kmm/iosApp/iosApp/Info.plist (1)
4-7
: Bundle metadata provided via Config.xcconfig
Essential keys (CFBundleIdentifier, CFBundleName, CFBundleVersion) are defined inConfiguration/Config.xcconfig
and injected at build time; Info.plist is intentionally minimal.
**/build/ | ||
xcuserdata | ||
!src/**/build/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Fix the unignore for source folders named build
.
!src/**/build/
never fires for modules like composeApp/src/...
or shared/src/...
, so legitimate source directories named build
inside those modules stay ignored. Replace it with a pattern that accounts for the module segment (for example, !**/src/**/build/
) or drop the negation if it’s not needed.
🤖 Prompt for AI Agents
In codeSnippets/snippets/tutorial-client-kmm/.gitignore around lines 4-6 the
negation pattern "!src/**/build/" does not match module paths like
"composeApp/src/..." or "shared/src/...", so nested source folders named build
remain ignored; update the negation to a broader pattern such as
"!**/src/**/build/" (or remove the negation if you decide build directories
should stay ignored) so that build directories under any module's src are
correctly unignored.
@@ -0,0 +1,3 @@ | |||
<resources> | |||
<string name="app_name">kmmktor</string> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Capitalize the launcher label.
app_name
is user-facing; the lowercase value looks unpolished in the launcher. Please capitalize it (for example, KMM Ktor
) to match branding.
🤖 Prompt for AI Agents
In
codeSnippets/snippets/tutorial-client-kmm/composeApp/src/androidMain/res/values/strings.xml
around line 2, the launcher label value for the app_name string is lowercase
("kmmktor"); update the user-facing string to a capitalized, branded form (for
example "KMM Ktor" or your preferred capitalization) by replacing the value
while keeping the XML key unchanged so the launcher shows the corrected,
polished app name.
codeSnippets/snippets/tutorial-client-kmm/gradle/libs.versions.toml
Outdated
Show resolved
Hide resolved
codeSnippets/snippets/tutorial-client-kmm/iosApp/Configuration/Config.xcconfig
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm 👍
KTOR-8556